-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
Copy pathsam.cpp
102 lines (79 loc) · 2.93 KB
/
sam.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// 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)