1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-26 17:46:14 +01:00

Embed ArduinoTimers library

Makes it so much easier for novice users as the ArduinoTimers libraray is not yet available from the IDE Library Manager.
This commit is contained in:
Asbelos 2020-08-23 14:14:04 +01:00
parent d3b486a071
commit 6a986d2b0c
9 changed files with 946 additions and 1 deletions

194
ATMEGA2560/Timer.h Normal file
View File

@ -0,0 +1,194 @@
#ifndef ATMEGA2560Timer_h
#define ATMEGA2560Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer {
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned char clockSelectBits;
int timer_num;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Timer(int timer_num) {
switch (timer_num)
{
case 1:
case 3:
case 4:
case 5:
timer_resolution = 65536;
break;
}
this->timer_num = timer_num;
lastMicroseconds = 0;
}
void initialize() {
switch (timer_num)
{
case 1:
TCCR1B = _BV(WGM13) | _BV(WGM12);
TCCR1A = _BV(WGM11);
break;
case 3:
TCCR3B = _BV(WGM33) | _BV(WGM32);
TCCR3A = _BV(WGM31);
break;
case 4:
TCCR4B = _BV(WGM43) | _BV(WGM42);
TCCR4A = _BV(WGM41);
break;
case 5:
TCCR5B = _BV(WGM53) | _BV(WGM52);
TCCR5A = _BV(WGM51);
break;
}
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = (F_CPU / 1000000) * microseconds;
if (cycles < timer_resolution) {
clockSelectBits = 1 << 0;
pwmPeriod = cycles;
} else
if (cycles < timer_resolution * 8) {
clockSelectBits = 1 << 1;
pwmPeriod = cycles / 8;
} else
if (cycles < timer_resolution * 64) {
clockSelectBits = (1 << 0) | (1 << 1);
pwmPeriod = cycles / 64;
} else
if (cycles < timer_resolution * 256) {
clockSelectBits = 1 << 2;
pwmPeriod = cycles / 256;
} else
if (cycles < timer_resolution * 1024) {
clockSelectBits = (1 << 2) | (1 << 0);
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = (1 << 2) | (1 << 0);
pwmPeriod = timer_resolution - 1;
}
switch (timer_num)
{
case 1:
ICR1 = pwmPeriod;
TCCR1B = _BV(WGM13) | _BV(WGM12) | clockSelectBits;
break;
case 3:
ICR3 = pwmPeriod;
TCCR3B = _BV(WGM33) | _BV(WGM32) | clockSelectBits;
break;
case 4:
ICR4 = pwmPeriod;
TCCR4B = _BV(WGM43) | _BV(WGM42) | clockSelectBits;
break;
case 5:
ICR5 = pwmPeriod;
TCCR5B = _BV(WGM53) | _BV(WGM52) | clockSelectBits;
break;
}
}
void start() {
switch (timer_num)
{
case 1:
TCCR1B = 0;
TCNT1 = 0; // TODO: does this cause an undesired interrupt?
TCCR1B = _BV(WGM13) | _BV(WGM12) | clockSelectBits;
break;
case 3:
TCCR3B = 0;
TCNT3 = 0; // TODO: does this cause an undesired interrupt?
TCCR3B = _BV(WGM33) | _BV(WGM32) | clockSelectBits;
break;
case 4:
TCCR4B = 0;
TCNT4 = 0; // TODO: does this cause an undesired interrupt?
TCCR4B = _BV(WGM43) | _BV(WGM42) | clockSelectBits;
break;
case 5:
TCCR5B = 0;
TCNT5 = 0; // TODO: does this cause an undesired interrupt?
TCCR5B = _BV(WGM53) | _BV(WGM52) | clockSelectBits;
break;
}
}
void stop() {
switch (timer_num)
{
case 1:
TCCR1B = _BV(WGM13) | _BV(WGM12);
break;
case 3:
TCCR3B = _BV(WGM33) | _BV(WGM32);
break;
case 4:
TCCR4B = _BV(WGM43) | _BV(WGM42);
break;
case 5:
TCCR5B = _BV(WGM53) | _BV(WGM52);
break;
}
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr;
switch (timer_num)
{
case 1:
TIMSK1 = _BV(TOIE1);
break;
case 3:
TIMSK3 = _BV(TOIE3);
break;
case 4:
TIMSK4 = _BV(TOIE4);
break;
case 5:
TIMSK5 = _BV(TOIE5);
break;
}
}
void detachInterrupt() {
switch (timer_num)
{
case 1:
TIMSK1 = 0;
break;
case 3:
TIMSK3 = 0;
break;
case 4:
TIMSK4 = 0;
break;
case 5:
TIMSK5 = 0;
break;
}
}
};
extern Timer TimerA;
extern Timer TimerB;
extern Timer TimerC;
extern Timer TimerD;
#endif

208
ATMEGA328/Timer.h Normal file
View File

@ -0,0 +1,208 @@
#ifndef ATMEGA328Timer_h
#define ATMEGA328Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer {
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned char clockSelectBits;
int timer_num;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Timer(int timer_num) {
switch (timer_num)
{
//case 0:
case 2:
timer_resolution = 256;
break;
case 1:
timer_resolution = 65536;
break;
}
this->timer_num = timer_num;
lastMicroseconds = 0;
}
void initialize() {
switch (timer_num)
{
// case 0:
// TCCR0B = _BV(WGM02);
// TCCR0A = _BV(WGM00) | _BV(WGM01);
// break;
case 1:
TCCR1B = _BV(WGM13) | _BV(WGM12);
TCCR1A = _BV(WGM11);
break;
case 2:
TCCR2B = _BV(WGM22);
TCCR2A = _BV(WGM20) | _BV(WGM21);
break;
}
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = (F_CPU / 1000000) * microseconds;
switch(timer_num) {
case 2:
if (cycles < timer_resolution) {
clockSelectBits = 1 << 0;
pwmPeriod = cycles;
} else
if (cycles < timer_resolution * 8) {
clockSelectBits = 1 << 1;
pwmPeriod = cycles / 8;
} else
if (cycles < timer_resolution * 32) {
clockSelectBits = 1 << 0 | 1 << 1;
pwmPeriod = cycles / 32;
} else
if (cycles < timer_resolution * 64) {
clockSelectBits = 1 << 2;
pwmPeriod = cycles / 64;
} else
if (cycles < timer_resolution * 128) {
clockSelectBits = 1 << 2 | 1 << 0;
pwmPeriod = cycles / 128;
} else
if (cycles < timer_resolution * 256) {
clockSelectBits = 1 << 2 | 1 << 1;
pwmPeriod = cycles / 256;
} else
if (cycles < timer_resolution * 1024) {
clockSelectBits = 1 << 2 | 1 << 1 | 1 << 0;
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = 1 << 2 | 1 << 1 | 1 << 0;
pwmPeriod = timer_resolution - 1;
}
break;
//case 0:
case 1:
if (cycles < timer_resolution) {
clockSelectBits = 1 << 0;
pwmPeriod = cycles;
} else
if (cycles < timer_resolution * 8) {
clockSelectBits = 1 << 1;
pwmPeriod = cycles / 8;
} else
if (cycles < timer_resolution * 64) {
clockSelectBits = (1 << 0) | (1 << 1);
pwmPeriod = cycles / 64;
} else
if (cycles < timer_resolution * 256) {
clockSelectBits = 1 << 2;
pwmPeriod = cycles / 256;
} else
if (cycles < timer_resolution * 1024) {
clockSelectBits = (1 << 2) | (1 << 0);
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = (1 << 2) | (1 << 0);
pwmPeriod = timer_resolution - 1;
}
break;
}
switch (timer_num)
{
// case 0:
// OCR0A = pwmPeriod;
// TCCR0B = _BV(WGM02) | clockSelectBits;
// break;
case 1:
ICR1 = pwmPeriod;
TCCR1B = _BV(WGM13) | _BV(WGM12) | clockSelectBits;
break;
case 2:
OCR2A = pwmPeriod;
TCCR2B = _BV(WGM22) | clockSelectBits;
break;
}
}
void start() {
switch (timer_num)
{
// case 0:
// TCCR0B = 0;
// TCNT0 = 0; // TODO: does this cause an undesired interrupt?
// TCCR0B = _BV(WGM02) | clockSelectBits;
// break;
case 1:
TCCR1B = 0;
TCNT1 = 0; // TODO: does this cause an undesired interrupt?
TCCR1B = _BV(WGM13) | _BV(WGM12) | clockSelectBits;
break;
case 2:
TCCR2B = 0;
TCNT2 = 0; // TODO: does this cause an undesired interrupt?
TCCR2B = _BV(WGM22) | clockSelectBits;
break;
}
}
void stop() {
switch (timer_num)
{
// case 0:
// TCCR0B = _BV(WGM02);
// break;
case 1:
TCCR1B = _BV(WGM13) | _BV(WGM12);
break;
case 2:
TCCR2B = _BV(WGM22);
break;
}
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr;
switch (timer_num)
{
// case 0:
// TIMSK0 = _BV(TOIE0);
// break;
case 1:
TIMSK1 = _BV(TOIE1);
break;
case 2:
TIMSK2 = _BV(TOIE2);
break;
}
}
void detachInterrupt() {
switch (timer_num)
{
// case 0:
// TIMSK0 = 0;
// break;
case 1:
TIMSK1 = 0;
break;
case 2:
TIMSK2 = 0;
break;
}
}
};
extern Timer TimerA;
extern Timer TimerB;
#endif

131
ATMEGA4809/Timer.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef ATMEGA328Timer_h
#define ATMEGA328Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
// We only define behavior for timer 0 (TCA0), because TCB0 is very limited in functionality.
class Timer : public VirtualTimer {
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned char clockSelectBits;
int timer_num;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Timer(int timer_num) {
switch (timer_num)
{
case 0:
timer_resolution = 65536;
break;
}
this->timer_num = timer_num;
lastMicroseconds = 0;
}
void initialize() {
switch (timer_num)
{
case 0:
break;
}
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = (F_CPU / 1000000) * microseconds;
switch(timer_num) {
case 0:
if (cycles < timer_resolution) {
clockSelectBits = 0x0;
pwmPeriod = cycles;
} else
if (cycles < timer_resolution * 2) {
clockSelectBits = 0x1;
pwmPeriod = cycles / 8;
} else
if (cycles < timer_resolution * 4) {
clockSelectBits = 0x2;
pwmPeriod = cycles / 32;
} else
if (cycles < timer_resolution * 8) {
clockSelectBits = 0x3;
pwmPeriod = cycles / 64;
} else
if (cycles < timer_resolution * 64) {
clockSelectBits = 0x5;
pwmPeriod = cycles / 128;
} else
if (cycles < timer_resolution * 256) {
clockSelectBits = 0x6;
pwmPeriod = cycles / 256;
} else
if (cycles < timer_resolution * 1024) {
clockSelectBits = 0x7;
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = 0x7;
pwmPeriod = timer_resolution - 1;
}
break;
}
switch (timer_num)
{
case 0:
TCA0.SINGLE.PER = pwmPeriod;
TCA0.SINGLE.CTRLA = clockSelectBits << 1;
break;
}
}
void start() {
switch (timer_num)
{
case 0:
bitSet(TCA0.SINGLE.CTRLA, 0);
break;
}
}
void stop() {
switch (timer_num)
{
case 0:
bitClear(TCA0.SINGLE.CTRLA, 0);
break;
}
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr;
switch (timer_num)
{
case 0:
TCA0.SINGLE.INTCTRL = 0x1;
break;
}
}
void detachInterrupt() {
switch (timer_num)
{
case 0:
TCA0.SINGLE.INTCTRL = 0x0;
break;
}
}
};
extern Timer TimerA;
#endif

129
ATSAMC21G/Timer.h Normal file
View File

@ -0,0 +1,129 @@
#ifndef ATSAMC21Timer_h
#define ATSAMC21Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer
{
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Tcc* timer;
Timer(Tcc* timer) {
this->timer = timer;
if(timer == TCC0 || timer == TCC1) {
timer_resolution = 16777216;
} else {
timer_resolution = 65536;
}
lastMicroseconds = 0;
}
void initialize() {
if(timer == TCC0 || timer == TCC1) {
MCLK->APBCMASK.bit.TCC0_ = 1;
MCLK->APBCMASK.bit.TCC1_ = 1;
GCLK->GENCTRL[4].reg = ( GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE );
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 4) & 1); // Wait for synchronization
GCLK->PCHCTRL[28].reg = ( GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(4) ); // 28 = TCC0_TCC1
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 4) & 1); // Wait for synchronization
}
else if (timer == TCC2) {
MCLK->APBCMASK.bit.TCC2_ = 1;
GCLK->GENCTRL[5].reg = ( GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE );
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 5) & 1); // Wait for synchronization
GCLK->PCHCTRL[29].reg = ( GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(5) ); // 29 = TCC2
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 5) & 1); // Wait for synchronization
}
timer->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform
while (timer->SYNCBUSY.bit.WAVE); // Wait for synchronization
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = F_CPU / 1000000 * microseconds; // cycles corresponds to how many clock ticks per microsecond times number of microseconds we want
timer->CTRLA.bit.PRESCALER = 0;
if(cycles < timer_resolution) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);
pwmPeriod = cycles;
} else
if(cycles < timer_resolution * 2) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV2_Val);
pwmPeriod = cycles / 2;
} else
if(cycles < timer_resolution * 4) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV4_Val);
pwmPeriod = cycles / 4;
} else
if(cycles < timer_resolution * 8) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV8_Val);
pwmPeriod = cycles / 8;
} else
if(cycles < timer_resolution * 16) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV16_Val);
pwmPeriod = cycles / 16;
} else
if(cycles < timer_resolution * 64) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV64_Val);
pwmPeriod = cycles / 64;
} else
if(cycles < timer_resolution * 1024) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1024_Val);
pwmPeriod = cycles / 1024;
}
timer->PER.reg = pwmPeriod;
while (timer->SYNCBUSY.bit.PER);
}
void start() {
timer->CTRLA.bit.ENABLE = 1; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void stop() {
timer->CTRLA.bit.ENABLE = 0; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr; // Store the interrupt callback function
timer->INTENSET.reg = TCC_INTENSET_OVF; // Set the interrupt to occur on overflow
if(timer == TCC0) {
NVIC_EnableIRQ((IRQn_Type) TCC0_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC1) {
NVIC_EnableIRQ((IRQn_Type) TCC1_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC2) {
NVIC_EnableIRQ((IRQn_Type) TCC2_IRQn); // Enable the interrupt (clock is still off)
}
}
void detachInterrupt() {
if(timer == TCC0) {
NVIC_DisableIRQ((IRQn_Type) TCC0_IRQn); // Disable the interrupt
}
else if(timer == TCC1) {
NVIC_DisableIRQ((IRQn_Type) TCC1_IRQn); // Disable the interrupt
}
else if(timer == TCC2) {
NVIC_DisableIRQ((IRQn_Type) TCC2_IRQn); // Disable the interrupt
}
}
};
extern Timer TimerA;
extern Timer TimerB;
extern Timer TimerC;
#endif // ATSAMC21Timer_h

144
ATSAMD21G/Timer.h Normal file
View File

@ -0,0 +1,144 @@
#ifndef ATSAMD21GTimer_h
#define ATSAMD21GTimer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer
{
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Tcc* timer;
Timer(Tcc* timer) {
this->timer = timer;
if(timer == TCC0 || timer == TCC1) {
timer_resolution = 16777216;
} else {
timer_resolution = 65536;
}
lastMicroseconds = 0;
}
void initialize() {
if(timer == TCC0 || timer == TCC1) {
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1
GCLK_GENDIV_ID(4); // Apply to GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_GENEN | // Enable GCLK
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable generic clock
4 << GCLK_CLKCTRL_GEN_Pos | // Apply to GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK to TCC0/1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
}
else if (timer == TCC2) {
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1
GCLK_GENDIV_ID(5); // Apply to GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_GENEN | // Enable GCLK
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(5); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable generic clock
5 << GCLK_CLKCTRL_GEN_Pos | // Apply to GCLK4
GCLK_CLKCTRL_ID_TCC2_TC3; // Feed GCLK to TCC0/1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
}
timer->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform
while (timer->SYNCBUSY.bit.WAVE); // Wait for synchronization
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = F_CPU / 1000000 * microseconds; // cycles corresponds to how many clock ticks per microsecond times number of microseconds we want
if(cycles < timer_resolution) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);
pwmPeriod = cycles;
} else
if(cycles < timer_resolution * 2) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV2_Val);
pwmPeriod = cycles / 2;
} else
if(cycles < timer_resolution * 4) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV4_Val);
pwmPeriod = cycles / 4;
} else
if(cycles < timer_resolution * 8) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV8_Val);
pwmPeriod = cycles / 8;
} else
if(cycles < timer_resolution * 16) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV16_Val);
pwmPeriod = cycles / 16;
} else
if(cycles < timer_resolution * 64) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV64_Val);
pwmPeriod = cycles / 64;
} else
if(cycles < timer_resolution * 1024) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1024_Val);
pwmPeriod = cycles / 1024;
}
timer->PER.reg = pwmPeriod;
while (timer->SYNCBUSY.bit.PER);
}
void start() {
timer->CTRLA.bit.ENABLE = 1; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void stop() {
timer->CTRLA.bit.ENABLE = 0; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr; // Store the interrupt callback function
timer->INTENSET.reg = TCC_INTENSET_OVF; // Set the interrupt to occur on overflow
if(timer == TCC0) {
NVIC_EnableIRQ((IRQn_Type) TCC0_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC1) {
NVIC_EnableIRQ((IRQn_Type) TCC1_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC2) {
NVIC_EnableIRQ((IRQn_Type) TCC2_IRQn); // Enable the interrupt (clock is still off)
}
}
void detachInterrupt() {
if(timer == TCC0) {
NVIC_DisableIRQ((IRQn_Type) TCC0_IRQn); // Disable the interrupt
}
else if(timer == TCC1) {
NVIC_DisableIRQ((IRQn_Type) TCC1_IRQn); // Disable the interrupt
}
else if(timer == TCC2) {
NVIC_DisableIRQ((IRQn_Type) TCC2_IRQn); // Disable the interrupt
}
}
};
extern Timer TimerA;
extern Timer TimerB;
extern Timer TimerC;
#endif

24
ArduinoTimers.h Normal file
View File

@ -0,0 +1,24 @@
// This file is copied from https://github.com/davidcutting42/ArduinoTimers
// All Credit and copyright David Cutting
// The files included below come from the same source.
// This library had been included with the DCC code to avoid issues with
// library management for inexperienced users. "It just works (TM)"
#ifndef ArduinoTimers_h
#define ArduinoTimers_h
#if defined(SAMC21)
#include "ATSAMC21G/Timer.h"
#elif defined(ARDUINO_SAMD_ZERO)
#include "ATSAMD21G/Timer.h"
#elif defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#include "ATMEGA2560/Timer.h"
#elif defined(ARDUINO_AVR_UNO)
#include "ATMEGA328/Timer.h"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "ATMEGA4809/Timer.h"
#else
#error "Cannot compile - ArduinoTimers library does not support your board, or you are missing compatible build flags."
#endif
#endif

View File

@ -21,7 +21,7 @@
#include "DCCWaveform.h" #include "DCCWaveform.h"
#include "DIAG.h" #include "DIAG.h"
#include "MotorDriver.h" #include "MotorDriver.h"
#include <ArduinoTimers.h> // use IDE menu Tools..Manage Libraries to locate and install TimerOne #include "ArduinoTimers.h"
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);

94
Timer.cpp Normal file
View File

@ -0,0 +1,94 @@
// This file is copied from https://github.com/davidcutting42/ArduinoTimers
// All Credit to David Cutting
#include <Arduino.h>
#if defined(ARDUINO_SAMD_ZERO)
#if defined(SAMC21)
#include "ATSAMC21G/Timer.h"
#else
#include "ATSAMD21G/Timer.h"
#endif
Timer TimerA(TCC0);
Timer TimerB(TCC1);
Timer TimerC(TCC2);
void TCC0_Handler() {
if(TCC0->INTFLAG.bit.OVF) {
TCC0->INTFLAG.bit.OVF = 1;
TimerA.isrCallback();
}
}
void TCC1_Handler() {
if(TCC1->INTFLAG.bit.OVF) {
TCC1->INTFLAG.bit.OVF = 1;
TimerB.isrCallback();
}
}
void TCC2_Handler() {
if(TCC2->INTFLAG.bit.OVF) {
TCC2->INTFLAG.bit.OVF = 1;
TimerC.isrCallback();
}
}
#elif defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#include "ATMEGA2560/Timer.h"
Timer TimerA(1);
Timer TimerB(3);
Timer TimerC(4);
Timer TimerD(5);
ISR(TIMER1_OVF_vect)
{
TimerA.isrCallback();
}
ISR(TIMER3_OVF_vect)
{
TimerB.isrCallback();
}
ISR(TIMER4_OVF_vect)
{
TimerC.isrCallback();
}
ISR(TIMER5_OVF_vect)
{
TimerD.isrCallback();
}
#elif defined(ARDUINO_AVR_UNO) // Todo: add other 328 boards for compatibility
#include "ATMEGA328/Timer.h"
Timer TimerA(1);
Timer TimerB(2);
ISR(TIMER1_OVF_vect)
{
TimerA.isrCallback();
}
ISR(TIMER2_OVF_vect)
{
TimerB.isrCallback();
}
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "ATMEGA4809/Timer.h"
Timer TimerA(0);
ISR(TCA0_OVF_vect) {
TimerA.isrCallback();
}
#endif

21
VirtualTimer.h Normal file
View File

@ -0,0 +1,21 @@
// This file is copied from https://github.com/davidcutting42/ArduinoTimers
// All Credit to David Cutting
#ifndef VirtualTimer_h
#define VirtualTimer_h
class VirtualTimer
{
public:
virtual void initialize() = 0;
virtual void setPeriod(unsigned long microseconds) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual void attachInterrupt(void (*isr)()) = 0;
virtual void detachInterrupt() = 0;
private:
};
#endif