102 lines
2.8 KiB
C++
102 lines
2.8 KiB
C++
|
// Support routines for SAM processor boards
|
||
|
|
||
|
#include "IRremote.h"
|
||
|
#include "IRremoteInt.h"
|
||
|
|
||
|
#if defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
|
||
|
|
||
|
// "Idiot check"
|
||
|
#ifdef USE_DEFAULT_ENABLE_IR_IN
|
||
|
#error Must undef USE_DEFAULT_ENABLE_IR_IN
|
||
|
#endif
|
||
|
|
||
|
//+=============================================================================
|
||
|
// ATSAMD Timer setup & IRQ functions
|
||
|
//
|
||
|
|
||
|
// following based on setup from GitHub jdneo/timerInterrupt.ino
|
||
|
|
||
|
static void setTimerFrequency(int frequencyHz)
|
||
|
{
|
||
|
int compareValue = (SYSCLOCK / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
|
||
|
//Serial.println(compareValue);
|
||
|
TcCount16* TC = (TcCount16*) TC3;
|
||
|
// Make sure the count is in a proportional position to where it was
|
||
|
// to prevent any jitter or disconnect when changing the compare value.
|
||
|
TC->COUNT.reg = map(TC->COUNT.reg, 0, TC->CC[0].reg, 0, compareValue);
|
||
|
TC->CC[0].reg = compareValue;
|
||
|
//Serial.print("COUNT.reg ");
|
||
|
//Serial.println(TC->COUNT.reg);
|
||
|
//Serial.print("CC[0].reg ");
|
||
|
//Serial.println(TC->CC[0].reg);
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1);
|
||
|
}
|
||
|
|
||
|
static void startTimer()
|
||
|
{
|
||
|
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3);
|
||
|
while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
|
||
|
TcCount16* TC = (TcCount16*) TC3;
|
||
|
|
||
|
TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
|
||
|
// Use the 16-bit timer
|
||
|
TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
|
||
|
// Use match mode so that the timer counter resets when the count matches the compare register
|
||
|
TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
|
||
|
// Set prescaler to 1024
|
||
|
//TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
|
||
|
TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV64;
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
|
||
|
setTimerFrequency(1000000 / USECPERTICK);
|
||
|
|
||
|
// Enable the compare interrupt
|
||
|
TC->INTENSET.reg = 0;
|
||
|
TC->INTENSET.bit.MC0 = 1;
|
||
|
|
||
|
NVIC_EnableIRQ(TC3_IRQn);
|
||
|
|
||
|
TC->CTRLA.reg |= TC_CTRLA_ENABLE;
|
||
|
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
|
||
|
}
|
||
|
|
||
|
//+=============================================================================
|
||
|
// initialization
|
||
|
//
|
||
|
|
||
|
void IRrecv::enableIRIn()
|
||
|
{
|
||
|
// Interrupt Service Routine - Fires every 50uS
|
||
|
//Serial.println("Starting timer");
|
||
|
startTimer();
|
||
|
//Serial.println("Started timer");
|
||
|
|
||
|
// Initialize state machine variables
|
||
|
irparams.rcvstate = STATE_IDLE;
|
||
|
irparams.rawlen = 0;
|
||
|
|
||
|
// Set pin modes
|
||
|
pinMode(irparams.recvpin, INPUT);
|
||
|
}
|
||
|
|
||
|
void irs(); // Defined in IRRemote as ISR(TIMER_INTR_NAME)
|
||
|
|
||
|
void TC3_Handler(void)
|
||
|
{
|
||
|
TcCount16* TC = (TcCount16*) TC3;
|
||
|
// If this interrupt is due to the compare register matching the timer count
|
||
|
// we toggle the LED.
|
||
|
if (TC->INTFLAG.bit.MC0 == 1) {
|
||
|
TC->INTFLAG.bit.MC0 = 1;
|
||
|
irs();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
|