diff --git a/.arduino-ci.yaml b/.arduino-ci.yaml new file mode 100644 index 0000000..480cdc2 --- /dev/null +++ b/.arduino-ci.yaml @@ -0,0 +1,11 @@ +compile: + platforms: + - uno + - due + - zero + - leonardo + - m4 + - esp32 + #- esp8266 + - mega2560 + - nano_every diff --git a/.github/workflows/arduino-lint.yaml b/.github/workflows/arduino-lint.yaml new file mode 100644 index 0000000..4e4c0d5 --- /dev/null +++ b/.github/workflows/arduino-lint.yaml @@ -0,0 +1,16 @@ +--- +name: arduino-lint + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # https://github.com/actions/checkout + - uses: arduino/arduino-lint-action@v1 + # https://github.com/arduino/arduino-lint-action + with: + library-manager: update + compliance: strict diff --git a/.github/workflows/arduino_ci.yaml b/.github/workflows/arduino_ci.yaml new file mode 100644 index 0000000..17d0263 --- /dev/null +++ b/.github/workflows/arduino_ci.yaml @@ -0,0 +1,13 @@ +--- +name: arduino_ci + +on: [push, pull_request] + +jobs: + arduino_ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # https://github.com/actions/checkout + - uses: Arduino-CI/action@stable-1.x + # https://github.com/marketplace/actions/arduino_ci diff --git a/contributors.txt b/contributors.txt index b795745..c6d9617 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,3 +1,4 @@ Naguissa - https://github.com/Naguissa svlPanelMaker - https://github.com/svlPanelMaker - SAMD21 timing issue fix Raf (Raffaele Rialdi) - https://github.com/raffaeler - ESP32 hardware timer (better precission than ticker library) +Daniel Mohr - https://github.com/daniel-mohr - SAMD21 timing issue fix diff --git a/library.properties b/library.properties index ad6a3a0..15f747c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=uTimerLib -version=1.7.1 +version=1.7.2 author=Naguissa maintainer=Naguissa sentence=Tiny and cross-device compatible timer library diff --git a/src/hardware/uTimerLib.SAMD21.cpp b/src/hardware/uTimerLib.SAMD21.cpp index cbfa7a0..6f26f53 100644 --- a/src/hardware/uTimerLib.SAMD21.cpp +++ b/src/hardware/uTimerLib.SAMD21.cpp @@ -52,7 +52,7 @@ Prescaler: Prescalers: GCLK_TC, GCLK_TC/2, GCLK_TC/4, GCLK_TC/8, GCLK_TC/16, GCLK_TC/64, GCLK_TC/256, GCLK_TC/1024 - Base frequency: 84MHz + Base frequency: 48MHz We will use TCC2, as there're some models with only 3 timers (regular models have 5 TCs) @@ -60,18 +60,33 @@ Name Prescaler Freq Base Delay Overflow delay - GCLK_TC 1 48MHz 0,020833333us 1365,333333333us; 1,365333333333ms - GCLK_TC/2 2 24MHz 0,041666667us 2730,666666667us; 2,730666666667ms - GCLK_TC/4 4 12MHz 0,083333333us 5461,333333333us; 5,461333333333ms - GCLK_TC/8 8 6MHz 0,166666667us 10922,666666667us; 10,922666666667ms - GCLK_TC/16 16 3MHz 0,333333333us 21845,333333333us; 21,845333333333ms - GCLK_TC/64 64 750KHz 1,333333333us 87381,333311488us; 87,381333311488ms - GCLK_TC/256 256 187,5KHz 5,333333333us 349525,333311488us; 349,525333311488ms - GCLK_TC/1024 1024 46.875Hz 21,333333333us 1398101,333333333us; 1398,101333333333ms; 1,398101333333333s + GCLK_TC 1 48MHz ~0,020833333us 1365,3125us; 1,3653125ms + GCLK_TC/2 2 24MHz ~0,041666667us 2730,625us; 2,730625ms + GCLK_TC/4 4 12MHz ~0,083333333us 5461,25us; 5,46125ms + GCLK_TC/8 8 6MHz ~0,166666667us 10922,5us; 10,9225ms + GCLK_TC/16 16 3MHz ~0,333333333us 21845us; 21,845ms + GCLK_TC/64 64 750KHz ~1,333333333us 87380us; 87,380ms + GCLK_TC/256 256 187,5KHz ~5,333333333us 349520us; 349,52ms + GCLK_TC/1024 1024 46.875kHz ~21,333333333us 1398080us; 1398,08ms; 1,39808s + + In general: + freq = 48 MHz / prescaler + base_delay = 1 / freq + overflow_delay = UINT16_MAX * base_delay Will be using: GCLK_TC/16 for us GCLK_TC/1024 for s + + GCLK_TC/16: + freq = 48 MHz / prescaler = 48 MHz / 16 = 3 MHz + base_delay = 1 / freq = 1 / 3e6 s = 1/3 us ~= 0.333333333 us + overflow_delay = UINT16_MAX * base_delay = 65535 / 3 us = 21845 us + + GCLK_TC/1024: + freq = 48 MHz / prescaler = 48 MHz / 1024 = 46.875 kHz = 46875 Hz + base_delay = 1 / freq = 1 / 46875 s = ~= 21.333333333us + overflow_delay = UINT16_MAX * base_delay = 65535 / 46875 s = 1.39808 s */ // Enable clock for TC @@ -82,23 +97,23 @@ _TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; while (_TC->STATUS.bit.SYNCBUSY == 1); // sync - // Set Timer counter Mode to 16 bits + Set TC as normal Normal Frq + Prescaler: GCLK_TC/16 - _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_NFRQ + TC_CTRLA_PRESCALER_DIV16); + // Set Timer counter Mode to 16 bits + Set TC as normal Match Frq + Prescaler: GCLK_TC/16 + _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_MFRQ + TC_CTRLA_PRESCALER_DIV16); while (_TC->STATUS.bit.SYNCBUSY == 1); // sync if (us > 21845) { - __overflows = _overflows = us / 21845.333333333; - __remaining = _remaining = ((us - (21845.333333333 * _overflows)) / 0.333333333) + 0.5; // +0.5 is same as round + __overflows = _overflows = us / 21845.0; + __remaining = _remaining = (us - (21845 * _overflows)) * 3 - 1; } else { __overflows = _overflows = 0; - __remaining = _remaining = (us / 0.333333333) + 0.5; // +0.5 is same as round + __remaining = _remaining = us * 3 - 1; } if (__overflows == 0) { _loadRemaining(); _remaining = 0; } else { - _TC->CC[0].reg = 65535; + _TC->CC[0].reg = UINT16_MAX; _TC->INTENSET.reg = 0; // disable all interrupts _TC->INTENSET.bit.OVF = 1; // enable overfollow // Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync @@ -126,7 +141,7 @@ } /* - GCLK_TC/1024 1024 46.875Hz 21,333333333us 1398101,333333333us; 1398,101333333333ms; 1,398101333333333s + GCLK_TC/1024 1024 46.875kHz ~21,333333333us 1398080us; 1398,08ms; 1,39808s */ // Enable clock for TC @@ -137,23 +152,23 @@ _TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; while (_TC->STATUS.bit.SYNCBUSY == 1); // sync - // Set Timer counter Mode to 16 bits + Set TC as normal Normal Frq + Prescaler: GCLK_TC/1024 - _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_NFRQ + TC_CTRLA_PRESCALER_DIV1024); + // Set Timer counter Mode to 16 bits + Set TC as normal Match Frq + Prescaler: GCLK_TC/1024 + _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_MFRQ + TC_CTRLA_PRESCALER_DIV1024); while (_TC->STATUS.bit.SYNCBUSY == 1); // sync if (s > 1) { - __overflows = _overflows = s / 1.398101333333333; - __remaining = _remaining = ((s - (1.398101333333333 * _overflows)) / 0.000021333333333) + 0.5; // +0.5 is same as round + __overflows = _overflows = s / 1.39808; + __remaining = _remaining = ((s * 100000) % 139808) * 480 / 1024 - 1; // for integer s this is always an integer } else { __overflows = _overflows = 0; - __remaining = _remaining = (s / 0.000021333333333) + 0.5; // +0.5 is same as round + __remaining = _remaining = s * 46875 - 1; } if (__overflows == 0) { _loadRemaining(); _remaining = 0; } else { - _TC->CC[0].reg = 65535; + _TC->CC[0].reg = UINT16_MAX; _TC->INTENSET.reg = 0; // disable all interrupts _TC->INTENSET.bit.OVF = 1; // enable overfollow // Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync @@ -174,7 +189,6 @@ * Note: This is device-dependant */ void uTimerLib::_loadRemaining() { - _TC->COUNT.reg = 0; // Reset to 0 _TC->CC[0].reg = _remaining; _TC->INTENSET.reg = 0; // disable all interrupts _TC->INTENSET.bit.MC0 = 1; // enable compare match to CC0 @@ -217,28 +231,22 @@ if (_type == UTIMERLIB_TYPE_TIMEOUT) { clearTimer(); } else if (_type == UTIMERLIB_TYPE_INTERVAL) { - if (__overflows == 0) { - _remaining = __remaining; - _loadRemaining(); - _remaining = 0; - } else { + if (__overflows != 0) { _overflows = __overflows; _remaining = __remaining; - _TC->COUNT.reg = 0; // Reset to 0 _TC->INTENSET.reg = 0; // disable all interrupts _TC->INTENSET.bit.OVF = 0; // enable overfollow _TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0 - _TC->CC[0].reg = 65535; + _TC->CC[0].reg = UINT16_MAX; } } _cb(); } else if (_overflows > 0) { // Reload for SAMD21 - _TC->COUNT.reg = 0; // Reset to 0 _TC->INTENSET.reg = 0; // disable all interrupts _TC->INTENSET.bit.OVF = 0; // enable overfollow _TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0 - _TC->CC[0].reg = 65535; + _TC->CC[0].reg = UINT16_MAX; } }