diff --git a/examples/uTimerLib_setInterval_us_example_led/uTimerLib_setInterval_us_example_led.ino b/examples/uTimerLib_setInterval_us_example_led/uTimerLib_setInterval_us_example_led.ino index 7a20811..11ba820 100644 --- a/examples/uTimerLib_setInterval_us_example_led/uTimerLib_setInterval_us_example_led.ino +++ b/examples/uTimerLib_setInterval_us_example_led/uTimerLib_setInterval_us_example_led.ino @@ -9,6 +9,12 @@ #include "Arduino.h" #include "uTimerLib.h" +#ifndef LED_BUILTIN + // change to fit your needs + #define LED_BUILTIN 13 +#endif + + bool status = 0; diff --git a/library.properties b/library.properties index 61b6afb..09608f9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=uTimerLib -version=0.1.0 +version=0.2.0 author=Naguissa maintainer=Naguissa sentence=Tiny and cross-device compatible timer library diff --git a/src/uTimerLib.cpp b/src/uTimerLib.cpp index e93ecc8..e14198e 100644 --- a/src/uTimerLib.cpp +++ b/src/uTimerLib.cpp @@ -2,7 +2,8 @@ * Tiny and cross-device compatible timer library. * * Timers used by microcontroller - * Atmel AVR: Timer2 + * Atmel AVR: Timer2 (3rd timer) + * STM32: Timer3 (3rd timer) * * @copyright Naguissa * @author Naguissa @@ -10,16 +11,18 @@ * @version 0.1.0 * @created 2018-01-27 */ -#include #include "uTimerLib.h" - /** * Constructor * * Nothing to do here */ -uTimerLib::uTimerLib() {} +uTimerLib::uTimerLib() { +#ifdef _VARIANT_ARDUINO_STM32_ + clearTimer(); +#endif +} /** * Attaches a callback function to be executed each us microseconds @@ -27,7 +30,7 @@ uTimerLib::uTimerLib() {} * @param void*() cb Callback function to be called * @param unsigned long int us Interval in microseconds */ -void uTimerLib::setInterval_us(void * cb(), unsigned long int us) { +void uTimerLib::setInterval_us(void (* cb)(), unsigned long int us) { clearTimer(); _cb = cb; _type = UTIMERLIB_TYPE_INTERVAL; @@ -41,7 +44,7 @@ void uTimerLib::setInterval_us(void * cb(), unsigned long int us) { * @param void*() cb Callback function to be called * @param unsigned long int us Timeout in microseconds */ -int uTimerLib::setTimeout_us(void * cb(), unsigned long int us) { +int uTimerLib::setTimeout_us(void (* cb)(), unsigned long int us) { clearTimer(); _cb = cb; _type = UTIMERLIB_TYPE_TIMEOUT; @@ -55,7 +58,7 @@ int uTimerLib::setTimeout_us(void * cb(), unsigned long int us) { * @param void*() cb Callback function to be called * @param unsigned long int s Interval in seconds */ -void uTimerLib::setInterval_s(void * cb(), unsigned long int s) { +void uTimerLib::setInterval_s(void (* cb)(), unsigned long int s) { clearTimer(); _cb = cb; _type = UTIMERLIB_TYPE_INTERVAL; @@ -69,7 +72,7 @@ void uTimerLib::setInterval_s(void * cb(), unsigned long int s) { * @param void*() cb Callback function to be called * @param unsigned long int s Timeout in seconds */ -int uTimerLib::setTimeout_s(void * cb(), unsigned long int s) { +int uTimerLib::setTimeout_s(void (* cb)(), unsigned long int s) { clearTimer(); _cb = cb; _type = UTIMERLIB_TYPE_TIMEOUT; @@ -163,6 +166,23 @@ void uTimerLib::_attachInterrupt_us(unsigned long int us) { sei(); #endif + + // STM32, all variants + #ifdef _VARIANT_ARDUINO_STM32_ + Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE); + Timer3.setPeriod(us); // in microseconds + Timer3.setCompare(TIMER_CH1, 1); + __overflows = _overflows = 1; + __remaining = _remaining = 0; + if (_toInit) { + _toInit = false; + Timer3.attachInterrupt(TIMER_CH1, uTimerLib_interruptHandle); + } + Timer3.refresh(); + Timer3.resume(); + #endif + + } @@ -174,7 +194,7 @@ void uTimerLib::_attachInterrupt_us(unsigned long int us) { * @param unsigned long int s Desired timing in seconds */ void uTimerLib::_attachInterrupt_s(unsigned long int s) { - // Using longest mode from _ms function + // Arduino AVR #ifdef ARDUINO_ARCH_AVR unsigned char CSMask = 0; // For this notes, we asume 16MHz CPU. We recalculate 's' if not: @@ -185,6 +205,7 @@ void uTimerLib::_attachInterrupt_s(unsigned long int s) { cli(); /* + Using longest mode from _ms function CS22 CS21 CS20 Freq Divisor Base Delay Overflow delay 1 1 1 15.625KHz 1024 64us 16384us */ @@ -203,7 +224,6 @@ void uTimerLib::_attachInterrupt_s(unsigned long int s) { _remaining = 256 - round(((s * 1000000) % 16384) / 64); } - __overflows = _overflows; __remaining = _remaining; @@ -222,6 +242,23 @@ void uTimerLib::_attachInterrupt_s(unsigned long int s) { sei(); #endif + + + // STM32, all variants + #ifdef _VARIANT_ARDUINO_STM32_ + Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE); + Timer3.setPeriod((unsigned long int) 1000000); // 1s, in microseconds + Timer3.setCompare(TIMER_CH1, 1); + __overflows = _overflows = s; + __remaining = _remaining = 0; + if (_toInit) { + _toInit = false; + Timer3.attachInterrupt(TIMER_CH1, uTimerLib_interruptHandle); + } + Timer3.refresh(); + Timer3.resume(); + #endif + } @@ -235,6 +272,8 @@ void uTimerLib::_loadRemaining() { #ifdef ARDUINO_ARCH_AVR TCNT2 = _remaining; #endif + + // STM32: Not needed } /** @@ -243,13 +282,20 @@ void uTimerLib::_loadRemaining() { * Note: This is device-dependant */ void uTimerLib::clearTimer() { + _type = UTIMERLIB_TYPE_OFF; + #ifdef ARDUINO_ARCH_AVR TIMSK2 &= ~(1 << TOIE2); // Disable overflow interruption when 0 SREG = (SREG & 0b01111111); // Disable interrupts without modifiying other interrupts #endif - _type = UTIMERLIB_TYPE_OFF; + + #ifdef _VARIANT_ARDUINO_STM32_ + Timer3.pause(); + #endif } +// Preinstantiate Object +uTimerLib TimerLib = uTimerLib(); /** @@ -258,37 +304,33 @@ void uTimerLib::clearTimer() { * As timers doesn't give us enougth flexibility for large timings, * this function implements oferflow control to offer user desired timings. */ -void uTimerLib::_interruptHandler() { - extern uTimerLib TimerLib; - - if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen +void uTimerLib_interruptHandle() { + if (TimerLib._type == UTIMERLIB_TYPE_OFF) { // Should not happen return; } - if (_overflows > 0) { - _overflows--; + if (TimerLib._overflows > 0) { + TimerLib._overflows--; } - if (_overflows == 0 && _remaining > 0) { + if (TimerLib._overflows == 0 && TimerLib._remaining > 0) { // Load remaining count to counter - _loadRemaining(); + TimerLib._loadRemaining(); // And clear remaining count - _remaining = 0; - } else if (_overflows == 0 && _remaining == 0) { - if (_type == UTIMERLIB_TYPE_TIMEOUT) { - clearTimer(); - } else if (_type == UTIMERLIB_TYPE_INTERVAL) { - if (__overflows == 0) { - _loadRemaining(); + TimerLib._remaining = 0; + } else if (TimerLib._overflows == 0 && TimerLib._remaining == 0) { + if (TimerLib._type == UTIMERLIB_TYPE_TIMEOUT) { + TimerLib.clearTimer(); + } else if (TimerLib._type == UTIMERLIB_TYPE_INTERVAL) { + if (TimerLib.__overflows == 0) { + TimerLib._loadRemaining(); } else { - _overflows = __overflows; - _remaining = __remaining; + TimerLib._overflows = TimerLib.__overflows; + TimerLib._remaining = TimerLib.__remaining; } } - _cb(); + TimerLib._cb(); } } -// Preinstantiate Object -uTimerLib TimerLib = uTimerLib(); @@ -301,7 +343,7 @@ uTimerLib TimerLib = uTimerLib(); #ifdef ARDUINO_ARCH_AVR // Arduino AVR ISR(TIMER2_OVF_vect) { - TimerLib._interruptHandler(); + uTimerLib_interruptHandle(); } #endif diff --git a/src/uTimerLib.h b/src/uTimerLib.h index c0a3ed7..a977ef4 100644 --- a/src/uTimerLib.h +++ b/src/uTimerLib.h @@ -20,19 +20,24 @@ #define UTIMERLIB_TYPE_TIMEOUT 1 #define UTIMERLIB_TYPE_INTERVAL 2 + #ifdef _VARIANT_ARDUINO_STM32_ + #include "HardwareTimer.h" + extern HardwareTimer Timer3; + #endif class uTimerLib { public: uTimerLib(); - void setInterval_us(void * (), unsigned long int); - void setInterval_s(void * (), unsigned long int); - int setTimeout_us(void * (), unsigned long int); - int setTimeout_s(void * (), unsigned long int); + void setInterval_us(void (*) (), unsigned long int); + void setInterval_s(void (*) (), unsigned long int); + int setTimeout_us(void (*) (), unsigned long int); + int setTimeout_s(void (*) (), unsigned long int); void clearTimer(); - void _interruptHandler(); - - private: + /** + * Because several compatibility issues -specially STM32- we need to put + * these as public, but it should be private. Maybe in future upgrades... + */ unsigned long int _overflows = 0; unsigned char _remaining = 0; unsigned long int __overflows = 0; @@ -42,6 +47,10 @@ void _loadRemaining(); + private: + #ifdef _VARIANT_ARDUINO_STM32_ + bool _toInit = true; + #endif void _attachInterrupt_us(unsigned long int); void _attachInterrupt_s(unsigned long int); @@ -49,6 +58,9 @@ }; extern uTimerLib TimerLib; + #ifdef _VARIANT_ARDUINO_STM32_ + void uTimerLib_interruptHandle(); + #endif #endif