Nice library - thank you for sharing it.
One idea: it would be nice if startTimer() picked the clock source with the least error, given the desired frequency (credit for this idea goes to RCArduino - see comments in RCArduino: Arduino Due DDS - Part 1 - Sinewaves and Fixed Point Maths).
I hacked together some code to demonstrate it. Caveat: I'm an arduino newb.
/*
* pick clock that provides the least error for specified frequency.
*/
uint8_t pickClock(uint32_t frequency, uint32_t& retRC)
{
/*
Timer Definition
TIMER_CLOCK1 MCK/2
TIMER_CLOCK2 MCK/8
TIMER_CLOCK3 MCK/32
TIMER_CLOCK4 MCK/128
*/
struct {
uint8_t flag;
uint8_t divisor;
} clockConfig[] = {
{ TC_CMR_TCCLKS_TIMER_CLOCK1, 2 },
{ TC_CMR_TCCLKS_TIMER_CLOCK2, 8 },
{ TC_CMR_TCCLKS_TIMER_CLOCK3, 32 },
{ TC_CMR_TCCLKS_TIMER_CLOCK4, 128 }
};
int clkId = 3;
int bestClock = 3;
float bestError = 1.0;
do {
float ticks = (float) VARIANT_MCK / (float) frequency / (float) clockConfig[clkId].divisor;
float error = abs(ticks - round(ticks));
if (abs(error) < bestError) {
bestClock = clkId;
bestError = error;
}
} while (clkId-- > 0);
float ticks = (float) VARIANT_MCK / (float) frequency / (float) clockConfig[bestClock].divisor;
retRC = (uint32_t) round(ticks);
return clockConfig[bestClock].flag;
}
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency, volatile void (*function)())
{
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
uint32_t rc = 0;
uint8_t clock = pickClock(frequency, rc);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock);
... remainder of startTimer() unchanged ...
}