18#if (defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)) & ! defined(ARDUINO_SAM_DUE)
21#error "This library only supports SAMD21G18A based boards (e.g. Zero/M0...)"
28void Sam::setTimerFrequency(
frequency_t frequencyHz) {
29 int compareValue = (F_CPU / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
30 TcCount16* TC = (TcCount16*) TC3;
33 TC->COUNT.reg = map(TC->COUNT.reg, 0, TC->CC[0].reg, 0, compareValue);
34 TC->CC[0].reg = compareValue;
35 while (TC->STATUS.bit.SYNCBUSY == 1);
38void Sam::timerEnableIntr() {
39 REG_GCLK_CLKCTRL =
static_cast<uint16_t
>(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3);
40 while (GCLK->STATUS.bit.SYNCBUSY == 1);
42 TcCount16* TC = (TcCount16*) TC3;
44 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
45 while (TC->STATUS.bit.SYNCBUSY == 1);
48 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
49 while (TC->STATUS.bit.SYNCBUSY == 1);
52 TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
53 while (TC->STATUS.bit.SYNCBUSY == 1);
57 TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV64;
58 while (TC->STATUS.bit.SYNCBUSY == 1);
64 TC->INTENSET.bit.MC0 = 1;
66 NVIC_EnableIRQ(TC3_IRQn);
68 TC->CTRLA.reg |= TC_CTRLA_ENABLE;
69 while (TC->STATUS.bit.SYNCBUSY == 1);
72void Sam::timerDisableIntr() {
73 TcCount16* TC = (TcCount16*) TC3;
74 NVIC_DisableIRQ(TC3_IRQn);
75 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
76 while (TC->STATUS.bit.SYNCBUSY == 1);
84 TcCount16* TC = (TcCount16*) TC3;
87 if (TC->INTFLAG.bit.MC0 == 1) {
88 TC->INTFLAG.bit.MC0 = 1;
89 interruptServiceRoutine();
95 maxValue = F_CPU / 2 / frequency;
96 onLength = maxValue * dutyCycle / 100;
102 REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |
104 while (GCLK->STATUS.bit.SYNCBUSY);
106 REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |
108 GCLK_GENCTRL_SRC_DFLL48M |
110 while (GCLK->STATUS.bit.SYNCBUSY);
112 PORT->Group[g_APinDescription[pwmPin].ulPort].PINCFG[g_APinDescription[pwmPin].ulPin].bit.PMUXEN = 1;
115 PORT->Group[g_APinDescription[1].ulPort].PMUX[g_APinDescription[1].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;
119 PORT->Group[g_APinDescription[1].ulPort].PMUX[g_APinDescription[1].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;
123 PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg |= PORT_PMUX_PMUXE_F;
127 PORT->Group[g_APinDescription[4].ulPort].PMUX[g_APinDescription[4].ulPin >> 1].reg |= PORT_PMUX_PMUXO_F;
131 PORT->Group[g_APinDescription[4].ulPort].PMUX[g_APinDescription[4].ulPin >> 1].reg |= PORT_PMUX_PMUXE_F;
135 PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg |= PORT_PMUX_PMUXO_F;
139 PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg |= PORT_PMUX_PMUXE_F;
143 PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg |= PORT_PMUX_PMUXO_F;
147 PORT->Group[g_APinDescription[8].ulPort].PMUX[g_APinDescription[8].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;
151 PORT->Group[g_APinDescription[8].ulPort].PMUX[g_APinDescription[8].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;
155 PORT->Group[g_APinDescription[10].ulPort].PMUX[g_APinDescription[10].ulPin >> 1].reg |= PORT_PMUX_PMUXE_F;
159 PORT->Group[g_APinDescription[11].ulPort].PMUX[g_APinDescription[11].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;
163 PORT->Group[g_APinDescription[10].ulPort].PMUX[g_APinDescription[10].ulPin >> 1].reg |= PORT_PMUX_PMUXO_F;
167 PORT->Group[g_APinDescription[11].ulPort].PMUX[g_APinDescription[11].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;
171 PORT->Group[g_APinDescription[A3].ulPort].PMUX[g_APinDescription[A3].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;
175 PORT->Group[g_APinDescription[A3].ulPort].PMUX[g_APinDescription[A3].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;
183 TCCx = timerTCC0 ? TCC0
189 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |
190 GCLK_CLKCTRL_GEN_GCLK4 |
191 GCLK_CLKCTRL_ID_TCC0_TCC1;
192 while (GCLK->STATUS.bit.SYNCBUSY);
195 REG_TCC0_WAVE |= TCC_WAVE_WAVEGEN_DSBOTH;
196 while (TCC0->SYNCBUSY.bit.WAVE);
198 REG_TCC0_WAVE |= TCC_WAVE_POL(0xF) | TCC_WAVE_WAVEGEN_DSBOTH;
199 while (TCC0->SYNCBUSY.bit.WAVE);
202 REG_TCC0_PER = maxValue;
203 while (TCC0->SYNCBUSY.bit.PER);
205 REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |
207 while (TCC0->SYNCBUSY.bit.ENABLE);
212 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |
213 GCLK_CLKCTRL_GEN_GCLK4 |
214 GCLK_CLKCTRL_ID_TCC0_TCC1;
215 while (GCLK->STATUS.bit.SYNCBUSY);
218 REG_TCC1_WAVE |= TCC_WAVE_WAVEGEN_DSBOTH;
219 while (TCC1->SYNCBUSY.bit.WAVE);
221 REG_TCC1_WAVE |= TCC_WAVE_POL(0xF) | TCC_WAVE_WAVEGEN_DSBOTH;
222 while (TCC1->SYNCBUSY.bit.WAVE);
225 REG_TCC1_PER = maxValue;
226 while (TCC1->SYNCBUSY.bit.PER);
228 REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |
230 while (TCC1->SYNCBUSY.bit.ENABLE);
235 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |
236 GCLK_CLKCTRL_GEN_GCLK4 |
237 GCLK_CLKCTRL_ID_TCC2_TC3;
238 while (GCLK->STATUS.bit.SYNCBUSY);
241 REG_TCC2_WAVE |= TCC_WAVE_WAVEGEN_DSBOTH;
242 while (TCC0->SYNCBUSY.bit.WAVE);
244 REG_TCC2_WAVE |= TCC_WAVE_POL(0xF) | TCC_WAVE_WAVEGEN_DSBOTH;
245 while (TCC2->SYNCBUSY.bit.WAVE);
248 REG_TCC2_PER = maxValue;
249 while (TCC2->SYNCBUSY.bit.PER);
251 REG_TCC2_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |
253 while (TCC2->SYNCBUSY.bit.ENABLE);
258void Sam::setValue(uint16_t value) {
261 REG_TCC1_CC1 = value;
262 while (TCC1->SYNCBUSY.bit.CC1);
265 REG_TCC1_CC0 = value;
266 while (TCC1->SYNCBUSY.bit.CC0);
269 REG_TCC0_CC0 = value;
270 while (TCC0->SYNCBUSY.bit.CC0);
273 REG_TCC1_CC1 = value;
274 while (TCC1->SYNCBUSY.bit.CC1);
277 REG_TCC1_CC0 = value;
278 while (TCC1->SYNCBUSY.bit.CC0);
281 REG_TCC0_CC1 = value;
282 while (TCC0->SYNCBUSY.bit.CC1);
285 REG_TCC0_CC2 = value;
286 while (TCC0->SYNCBUSY.bit.CC2);
289 REG_TCC0_CC3 = value;
290 while (TCC0->SYNCBUSY.bit.CC3);
293 REG_TCC1_CC0 = value;
294 while (TCC1->SYNCBUSY.bit.CC0);
297 REG_TCC1_CC1 = value;
298 while (TCC1->SYNCBUSY.bit.CC1);
301 REG_TCC0_CC2 = value;
302 while (TCC0->SYNCBUSY.bit.CC2);
305 REG_TCC2_CC0 = value;
306 while (TCC2->SYNCBUSY.bit.CC0);
309 REG_TCC0_CC3 = value;
310 while (TCC0->SYNCBUSY.bit.CC3);
313 REG_TCC2_CC1 = value;
314 while (TCC2->SYNCBUSY.bit.CC1);
317 REG_TCC0_CC0 = value;
318 while (TCC0->SYNCBUSY.bit.CC0);
321 REG_TCC0_CC1 = value;
322 while (TCC0->SYNCBUSY.bit.CC1);
345void Sam::timerConfigNormal() {
346 TCCx->CTRLA.bit.ENABLE = 0;
347 while (TCCx->SYNCBUSY.bit.ENABLE);
int8_t dutycycle_t
Type for duty cycle in percent.
uint32_t frequency_t
Type for modulation frequency in Hz.
uint8_t pin_t
Type for GPIO pin, compatible with Arduino libs.
static const unsigned long microsPerTick