Skip to content

Commit cff7e9d

Browse files
committed
Add SAMD21 experimental support
1 parent de1920b commit cff7e9d

File tree

4 files changed

+59
-53
lines changed

4 files changed

+59
-53
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Currently suported architectures:
1515
- SAM (Arduino Due)
1616
- ESP8266
1717
- SAMD21 (Arduino Zero and Zero MKR; experimental support)
18-
- SAMD51 (Adafruit Feather M4, Adafruit Metro M4; experimental support)
18+
19+
- SAMD51 (Adafruit Feather M4, Adafruit Metro M4; work in progress, not functional -need for a SAMD51 board...)
1920

2021
## Device timer usage ##
2122

@@ -25,7 +26,7 @@ Depending on wich architecture this library uses one or another device timer. Ta
2526
- STM32: Timer3 (3rd timer)
2627
- SAM: TC3 (Timer1, channel 0)
2728
- ESP8266: Ticker library (inside ESP8266 core, no extras needed)
28-
- SAMD21: Timer2 (3rd timer); 16 bit mode
29+
- SAMD21: Timer3 (4th timer), CC0; 16 bit mode
2930
- SAMD51: Timer1 (2nd timer); 16 bit mode
3031

3132
## Usage ##

extras/samd51 - 60001507C.pdf

13.3 MB
Binary file not shown.

src/uTimerLib.cpp

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* STM32: Timer3 (3rd timer)
77
* SAM (Due): TC3 (Timer1, channel 0)
88
* ESP8266: OS Timer, one slof of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
9-
* SAMD21: Timer 3 (TCC2. Used because there're 3 a 5 timer versions). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
9+
* SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
1010
* SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
1111
*
1212
* @copyright Naguissa
@@ -300,42 +300,39 @@ void uTimerLib::_attachInterrupt_us(unsigned long int us) {
300300
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
301301

302302
// Disable TC
303-
TCC2->CTRLA.reg &= ~TC_CTRLA_ENABLE;
304-
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
303+
_TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
304+
while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
305305

306306
// Set Timer counter Mode to 16 bits + Set TC as normal Normal Frq + Prescaler: GCLK_TC/16
307-
TCC2->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_NFRQ | TC_CTRLA_PRESCALER_DIV16);
308-
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
307+
_TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_NFRQ + TC_CTRLA_PRESCALER_DIV16);
308+
while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
309+
310+
309311

310312
if (us > 21845) {
311313
__overflows = _overflows = us / 21845.333333333;
312-
__remaining = _remaining = (us - (21845.333333333 * _overflows)) / 0.333333333 + 0.5; // +0.5 is same as round
314+
__remaining = _remaining = ((us - (21845.333333333 * _overflows)) / 0.333333333) + 0.5; // +0.5 is same as round
313315
} else {
314316
__overflows = _overflows = 0;
315-
__remaining = _remaining = (us / 0.333333333 + 0.5); // +0.5 is same as round
317+
__remaining = _remaining = (us / 0.333333333) + 0.5; // +0.5 is same as round
316318
}
317319

318-
319-
// Counter PER not needed
320-
// TCC2->PER.reg = 0xFF;
321-
// while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
322-
323320
if (__overflows == 0) {
324321
_loadRemaining();
325322
_remaining = 0;
326323
} else {
327-
TCC2->CC[0].reg = 0xFFFF;
328-
// Skip: while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
324+
_TC->CC[0].reg = 65535;
325+
_TC->INTENSET.reg = 0; // disable all interrupts
326+
_TC->INTENSET.bit.OVF = 1; // enable overfollow
327+
// Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
329328
}
330329

331-
// Interrupts
332-
TCC2->INTENSET.reg = 0; // disable all interrupts
333-
TCC2->INTENSET.bit.OVF = 0; // disable overfollow
334-
TCC2->INTENSET.bit.MC0 = 1; // enable compare match to CC0
335-
NVIC_EnableIRQ(TCC2_IRQn);
330+
_TC->COUNT.reg = 0; // Reset to 0
331+
332+
NVIC_EnableIRQ(TC3_IRQn);
336333

337334
// Enable TC
338-
TCC2->CTRLA.reg |= TC_CTRLA_ENABLE;
335+
_TC->CTRLA.reg |= TC_CTRLA_ENABLE;
339336
#endif
340337

341338

@@ -534,47 +531,46 @@ void uTimerLib::_attachInterrupt_s(unsigned long int s) {
534531

535532
// SAMD21, Arduino Zero
536533
#ifdef _SAMD21_
534+
/*
535+
GCLK_TC/1024 1024 46.875Hz 21,333333333us 1398101,333333333us; 1398,101333333333ms; 1,398101333333333s
536+
*/
537+
537538
// Enable clock for TC
538539
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC2_TC3)) ;
539540
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
540541

541542
// Disable TC
542-
TCC2->CTRLA.reg &= ~TC_CTRLA_ENABLE;
543-
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
543+
_TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
544+
while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
544545

545546
// Set Timer counter Mode to 16 bits + Set TC as normal Normal Frq + Prescaler: GCLK_TC/1024
546-
TCC2->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_NFRQ + TC_CTRLA_PRESCALER_DIV1024);
547-
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
547+
_TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_NFRQ + TC_CTRLA_PRESCALER_DIV1024);
548+
while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
548549

549550
if (s > 1) {
550551
__overflows = _overflows = s / 1.398101333333333;
551-
__remaining = _remaining = (s - (1.398101333333333 * _overflows)) / 0.000021333333333 + 0.5; // +0.5 is same as round
552+
__remaining = _remaining = ((s - (1.398101333333333 * _overflows)) / 0.000021333333333) + 0.5; // +0.5 is same as round
552553
} else {
553554
__overflows = _overflows = 0;
554-
__remaining = _remaining = (s / 0.000021333333333 + 0.5); // +0.5 is same as round
555+
__remaining = _remaining = (s / 0.000021333333333) + 0.5; // +0.5 is same as round
555556
}
556557

557-
// Counter PER not needed
558-
// TCC2->PER.reg = 0xFF;
559-
// while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
560-
561558
if (__overflows == 0) {
562559
_loadRemaining();
563560
_remaining = 0;
564561
} else {
565-
TCC2->CC[0].reg = 0xFFFF;
566-
// Skip: while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
562+
_TC->CC[0].reg = 65535;
563+
_TC->INTENSET.reg = 0; // disable all interrupts
564+
_TC->INTENSET.bit.OVF = 1; // enable overfollow
565+
// Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
567566
}
568567

568+
_TC->COUNT.reg = 0; // Reset to 0
569569

570-
// Interrupts
571-
TCC2->INTENSET.reg = 0; // disable all interrupts
572-
TCC2->INTENSET.bit.OVF = 0; // disable overfollow
573-
TCC2->INTENSET.bit.MC0 = 1; // enable compare match to CC0
574-
NVIC_EnableIRQ(TCC2_IRQn);
570+
NVIC_EnableIRQ(TC3_IRQn);
575571

576572
// Enable TC
577-
TCC2->CTRLA.reg |= TC_CTRLA_ENABLE;
573+
_TC->CTRLA.reg |= TC_CTRLA_ENABLE;
578574
#endif
579575

580576

@@ -639,8 +635,10 @@ void uTimerLib::_loadRemaining() {
639635

640636
// SAMD21, Arduino Zero
641637
#ifdef _SAMD21_
642-
TCC2->CC[0].reg = _remaining;
643-
while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
638+
_TC->CC[0].reg = _remaining;
639+
_TC->INTENSET.reg = 0; // disable all interrupts
640+
_TC->INTENSET.bit.MC0 = 1; // enable compare match to CC0
641+
while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
644642
#endif
645643

646644
#ifdef __SAMD51__
@@ -679,8 +677,8 @@ void uTimerLib::clearTimer() {
679677
// SAMD21, Arduino Zero
680678
#ifdef _SAMD21_
681679
// Disable TC
682-
TCC2->INTENSET.reg = 0; // disable all interrupts
683-
TCC2->CTRLA.reg &= ~TC_CTRLA_ENABLE;
680+
_TC->INTENSET.reg = 0; // disable all interrupts
681+
_TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
684682
#endif
685683

686684
// SAMD51
@@ -732,7 +730,10 @@ void uTimerLib::_interrupt() {
732730

733731
// SAMD21, Arduino Zero
734732
#ifdef _SAMD21_
735-
TCC2->CC[0].reg = 0xFFFF;
733+
_TC->INTENSET.reg = 0; // disable all interrupts
734+
_TC->INTENSET.bit.OVF = 0; // enable overfollow
735+
_TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0
736+
_TC->CC[0].reg = 65535;
736737
#endif
737738

738739

@@ -756,7 +757,10 @@ void uTimerLib::_interrupt() {
756757
#ifdef _SAMD21_
757758
// Reload for SAMD21
758759
else if (_overflows > 0) {
759-
TCC2->CC[0].reg = 0xFFFF;
760+
_TC->INTENSET.reg = 0; // disable all interrupts
761+
_TC->INTENSET.bit.OVF = 0; // enable overfollow
762+
_TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0
763+
_TC->CC[0].reg = 65535;
760764
}
761765
#endif
762766

@@ -816,14 +820,15 @@ uTimerLib TimerLib = uTimerLib();
816820

817821

818822
#ifdef _SAMD21_
819-
void TCC2_Handler() {
823+
void TC3_Handler() {
820824
// Overflow - Nothing, we will use compare to max value instead to unify behaviour
821-
if (TCC2->INTFLAG.bit.OVF == 1) {
822-
TCC2->INTFLAG.bit.OVF = 1; // Clear flag
825+
if (TimerLib._TC->INTFLAG.bit.OVF == 1) {
826+
TimerLib._TC->INTFLAG.bit.OVF = 1; // Clear flag
827+
TimerLib._interrupt();
823828
}
824829
// Compare
825-
if (TCC2->INTFLAG.bit.MC0 == 1) {
826-
TCC2->INTFLAG.bit.MC0 = 1; // Clear flag
830+
if (TimerLib._TC->INTFLAG.bit.MC0 == 1) {
831+
TimerLib._TC->INTFLAG.bit.MC0 = 1; // Clear flag
827832
TimerLib._interrupt();
828833
}
829834
}

src/uTimerLib.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* STM32: Timer3 (3rd timer)
77
* SAM (Due): TC3 (Timer1, channel 0)
88
* ESP8266: OS Timer, one slof of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
9-
* SAMD21: Timer 3 (TCC2. Used because there're 3 a 5 timer versions). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
9+
* SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
1010
* SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
1111
*
1212
* @copyright Naguissa
@@ -54,6 +54,7 @@
5454

5555
#ifdef _SAMD21_
5656
#pragma message "SAMD21 support is still experimental"
57+
TcCount16* _TC = (TcCount16*) TC3;
5758
#endif
5859

5960
#ifdef __SAMD51__
@@ -87,7 +88,6 @@
8788
#ifdef ARDUINO_ARCH_ESP8266
8889
Ticker _ticker;
8990
#endif
90-
9191
};
9292

9393
extern uTimerLib TimerLib;

0 commit comments

Comments
 (0)