Last active
September 10, 2020 07:30
-
-
Save ciniml/6b3fed2370b1308440a9aee09d4e3cd7 to your computer and use it in GitHub Desktop.
Wio Terminal TC interrupt sample (separated)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "SAMD51_TC.h" | |
bool isLEDOn = false; | |
char time = 0; | |
void setup() | |
{ | |
//SerialUSB.begin(115200); | |
//while(!SerialUSB); | |
pinMode(LED_BUILTIN, OUTPUT); | |
TimerTC3.initialize(1000000); | |
TimerTC3.attachInterrupt(timerIsr); | |
} | |
void loop() | |
{ | |
/* | |
time ++; | |
if(time == 10)TimerTc3.detachInterrupt(); | |
else if(time == 20) | |
{ | |
TimerTc3.attachInterrupt(timerIsr); | |
time = 0; | |
} | |
delay(1000); | |
*/ | |
} | |
void timerIsr() | |
{ | |
digitalWrite(LED_BUILTIN, isLEDOn); | |
isLEDOn = !isLEDOn; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "SAMD51_TC.h" | |
SAMD51TC TimerTC0(0); | |
SAMD51TC TimerTC1(1); | |
SAMD51TC TimerTC2(2); | |
SAMD51TC TimerTC3(3); | |
SAMD51TC TimerTC4(4); | |
SAMD51TC TimerTC5(5); | |
SAMD51TC TimerTC6(6); | |
SAMD51TC TimerTC7(7); | |
class SAMD51TCInterruptHelper | |
{ | |
public: | |
static void callProcessIsr(SAMD51TC& tc) | |
{ | |
tc.processIsr(); | |
} | |
}; | |
void TC0_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC0); } | |
void TC1_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC1); } | |
void TC2_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC2); } | |
void TC3_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC3); } | |
void TC4_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC4); } | |
void TC5_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC5); } | |
void TC6_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC6); } | |
void TC7_Handler() { SAMD51TCInterruptHelper::callProcessIsr(TimerTC7); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SAMD51_TC_H__ | |
#define SAMD51_TC_H__ | |
#include <samd.h> | |
#include <cstdint> | |
#include <array> | |
#define GENERIC_CLOCK_GENERATOR_1M 5u | |
class SAMD51TCInterruptHelper; | |
class SAMD51TC | |
{ | |
public: | |
/** | |
* @brief Create a new instance of SAM51TC for the TCx peripheral where x == tcUnit. | |
* @param [in] tcUnit index of TC peripheral. | |
*/ | |
SAMD51TC(std::uint_least8_t tcUnit) : tcUnit(tcUnit), regs(nullptr), isrCallback(nullptr), microseconds(0) | |
{ | |
switch(tcUnit) | |
{ | |
case 0: {this->regs = &TC0->COUNT16; this->irqn = TC0_IRQn; break;} | |
case 1: {this->regs = &TC1->COUNT16; this->irqn = TC1_IRQn; break;} | |
case 2: {this->regs = &TC2->COUNT16; this->irqn = TC2_IRQn; break;} | |
case 3: {this->regs = &TC3->COUNT16; this->irqn = TC3_IRQn; break;} | |
case 4: {this->regs = &TC4->COUNT16; this->irqn = TC4_IRQn; break;} | |
case 5: {this->regs = &TC5->COUNT16; this->irqn = TC5_IRQn; break;} | |
case 6: {this->regs = &TC6->COUNT16; this->irqn = TC6_IRQn; break;} | |
case 7: {this->regs = &TC7->COUNT16; this->irqn = TC7_IRQn; break;} | |
} | |
} | |
void initialize(std::uint32_t microseconds = 1000000) | |
{ | |
this->configureClock(); | |
this->regs->CTRLA.bit.SWRST = 1; | |
while(this->regs->SYNCBUSY.bit.SWRST); | |
this->setPeriod(microseconds); | |
} | |
void setPeriod(std::uint32_t microseconds) | |
{ | |
this->microseconds = microseconds; | |
} | |
void start() | |
{ | |
this->regs->CTRLA.bit.ENABLE = 0; | |
while(this->regs->SYNCBUSY.bit.ENABLE); | |
this->regs->COUNT.reg = 0; | |
while(this->regs->SYNCBUSY.bit.COUNT); | |
const std::array<uint_fast8_t, 8> prescaler_shifts = { 0, 1, 2, 3, 4, 6, 8, 10 }; | |
for( std::uint_fast8_t index = 0; index < prescaler_shifts.size(); index++ ) { | |
const auto compare_value = this->microseconds >> prescaler_shifts[index]; | |
if( compare_value <= 65535 ) { | |
this->regs->CTRLA.bit.PRESCALER = index; | |
this->regs->CC[0].reg = compare_value; | |
break; | |
} | |
} | |
while(this->regs->SYNCBUSY.bit.CC0); | |
this->regs->WAVE.bit.WAVEGEN = TC_WAVE_WAVEGEN_MFRQ_Val; | |
this->regs->INTENSET.bit.MC0 = 1; | |
NVIC_EnableIRQ(this->irqn); | |
this->regs->CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val; | |
this->regs->CTRLA.bit.ENABLE = 1; | |
while(this->regs->SYNCBUSY.bit.ENABLE); | |
this->regs->CTRLBSET.bit.CMD = TC_CTRLBCLR_CMD_RETRIGGER_Val; | |
while(this->regs->SYNCBUSY.bit.CTRLB); | |
} | |
void stop() | |
{ | |
this->regs->CTRLA.bit.ENABLE = 0; | |
while(this->regs->SYNCBUSY.bit.ENABLE); | |
this->regs->INTENCLR.bit.MC0 = 1; | |
NVIC_DisableIRQ(this->irqn); | |
NVIC_ClearPendingIRQ(this->irqn); | |
} | |
void restart() | |
{ | |
this->regs->CTRLBSET.bit.CMD = TC_CTRLBCLR_CMD_RETRIGGER_Val; | |
while(this->regs->SYNCBUSY.bit.CTRLB); | |
} | |
void attachInterrupt(void (*isrCallback)()) | |
{ | |
this->isrCallback = isrCallback; | |
this->start(); | |
} | |
void detachInterrupt() | |
{ | |
this->stop(); | |
this->isrCallback = nullptr; | |
} | |
private: | |
std::uint_least8_t tcUnit; | |
TcCount16* regs; | |
IRQn_Type irqn; | |
std::uint32_t microseconds; | |
void (*isrCallback)(); | |
void configureClock() | |
{ | |
switch(this->tcUnit) { | |
case 0: {MCLK->APBAMASK.bit.TC0_ = 1; GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 1: {MCLK->APBAMASK.bit.TC1_ = 1; GCLK->PCHCTRL[TC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 2: {MCLK->APBBMASK.bit.TC2_ = 1; GCLK->PCHCTRL[TC2_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 3: {MCLK->APBBMASK.bit.TC3_ = 1; GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 4: {MCLK->APBCMASK.bit.TC4_ = 1; GCLK->PCHCTRL[TC4_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 5: {MCLK->APBCMASK.bit.TC5_ = 1; GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 6: {MCLK->APBDMASK.bit.TC6_ = 1; GCLK->PCHCTRL[TC6_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
case 7: {MCLK->APBDMASK.bit.TC7_ = 1; GCLK->PCHCTRL[TC7_GCLK_ID].reg = GCLK_PCHCTRL_GEN(GENERIC_CLOCK_GENERATOR_1M) | GCLK_PCHCTRL_CHEN; break;} | |
} | |
} | |
void processIsr() | |
{ | |
if( this->regs->INTFLAG.bit.MC0 ) { | |
this->regs->INTFLAG.bit.MC0 = 1; | |
if( this->isrCallback != nullptr ) { | |
this->isrCallback(); | |
} | |
} | |
} | |
friend class SAMD51TCInterruptHelper; | |
}; | |
extern SAMD51TC TimerTC0; | |
extern SAMD51TC TimerTC1; | |
extern SAMD51TC TimerTC2; | |
extern SAMD51TC TimerTC3; | |
extern SAMD51TC TimerTC4; | |
extern SAMD51TC TimerTC5; | |
extern SAMD51TC TimerTC6; | |
extern SAMD51TC TimerTC7; | |
#endif // SAMD51_TC_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment