// 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)