Skip to content

Commit

Permalink
Adding support to use the TC Block as a hardware counter
Browse files Browse the repository at this point in the history
  • Loading branch information
pklaus committed Jun 8, 2013
1 parent 10ce588 commit b6034b5
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 9 deletions.
96 changes: 87 additions & 9 deletions DueTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
#include "DueTimer.h"

const DueTimer::Timer DueTimer::Timers[9] = {
{TC0,0,TC0_IRQn},
{TC0,1,TC1_IRQn},
{TC0,2,TC2_IRQn},
{TC1,0,TC3_IRQn},
{TC1,1,TC4_IRQn},
{TC1,2,TC5_IRQn},
{TC2,0,TC6_IRQn},
{TC2,1,TC7_IRQn},
{TC2,2,TC8_IRQn},
{TC0, 0, TC0_IRQn, 22},
{TC0, 1, TC1_IRQn, 59}, // A5
{TC0, 2, TC2_IRQn, 31},
{TC1, 0, TC3_IRQn, 57}, // A3
{TC1, 1, TC4_IRQn, 56}, // A2
{TC1, 2, TC5_IRQn, 67},
{TC2, 0, TC6_IRQn, NULL}, // n/a
{TC2, 1, TC7_IRQn, NULL}, // LED "RX"
{TC2, 2, TC8_IRQn, 30},
};

void (*DueTimer::callbacks[9])() = {};
Expand Down Expand Up @@ -147,6 +147,84 @@ uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){
return clockConfig[bestClock].flag;
}

bool DueTimer::setUpCounter() {
/*
Set up a TC channel as hardware counter
driven by its external clock input.
*/

Timer t = Timers[timer];

if (t.tclk == NULL) return false;

// Set up the external clock input
pinMode(t.tclk, INPUT);

// Tell the Power Management Controller to disable
// the write protection of the (Timer/Counter) registers:
pmc_set_writeprotect(false);

// Enable clock for the timer
pmc_enable_periph_clk((uint32_t)t.irq);

uint32_t xc_tclk, tcclk_xc;
// Set up external clock input for the channel
switch (t.channel) {
case 0:
xc_tclk = TC_BMR_TC0XC0S_TCLK0;
tcclk_xc = TC_CMR_TCCLKS_XC0;
break;
case 1:
xc_tclk = TC_BMR_TC1XC1S_TCLK1;
tcclk_xc = TC_CMR_TCCLKS_XC1;
break;
case 2:
xc_tclk = TC_BMR_TC2XC2S_TCLK2;
tcclk_xc = TC_CMR_TCCLKS_XC2;
break;
default:
return false;
}

t.tc->TC_BMR |= xc_tclk;
TC_Configure(t.tc, t.channel, tcclk_xc | TC_CMR_BURST_NONE);

return true;
}

DueTimer DueTimer::startCounter() {
/*
Start the counter (resets the counter value to zero)
*/

Timer t = Timers[timer];

TC_Start(t.tc, t.channel);

return *this;
}

DueTimer DueTimer::stopCounter() {
/*
Stop the counter
*/

Timer t = Timers[timer];

TC_Stop(t.tc, t.channel);

return *this;
}

uint32_t DueTimer::counterValue(){
/*
Get the current counter value
*/

Timer t = Timers[timer];

return TC_ReadCV(t.tc, t.channel);
}

DueTimer DueTimer::setFrequency(double frequency){
/*
Expand Down
5 changes: 5 additions & 0 deletions DueTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class DueTimer
Tc *tc;
uint32_t channel;
IRQn_Type irq;
int tclk;
};

static DueTimer getAvailable();
Expand All @@ -51,6 +52,10 @@ class DueTimer
DueTimer detachInterrupt();
DueTimer start(long microseconds = -1);
DueTimer stop();
bool setUpCounter();
DueTimer startCounter();
DueTimer stopCounter();
uint32_t counterValue();
DueTimer setFrequency(double frequency);
DueTimer setPeriod(long microseconds);

Expand Down

2 comments on commit b6034b5

@ivanseidel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't change the Main DueTimer class. Instead, creating a TimerCounter class that extends DueTimer is the best solution, to avoid a class with thousands of methods. But, it's good to add the pin and Channel to the Timers configuration array.

What I suggest:

  • Implementing a new class called TimerCounter that extends DueTimer
  • Implement methods: getValue, setValue.
  • Override start method to run setUpCounter protected method and do others modifications to work properly

@pklaus
Copy link
Owner Author

@pklaus pklaus commented on b6034b5 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comment! Let's move this discussion to the pull request I created as I rebased my branch counter-implementation on your current master branch (and thus making this commit disappear).

Please sign in to comment.