Ticker updated to match extensions in ESP8266 API (#2849)
* Update Ticker API to compatibility with ESP8266, prepares for co-op loop Scheduler * Fixing Build server complaints * Fix omitted casts in template member function * Changes after review * Expose µs resolution of OS API in Ticker class * Return Ticker to libraries only for modularity. * Unify Ticker examples. * Default for LED_BUILTIN * In Ticker, the *scheduled functions become available in another development branch. * Astyle from ESP8266 * Fixed Arduino keywords.txt * 64bit integers instead of 32bits, timer functions on ESP32 accept 64bit integers. * Move code from header into compiliation unit. Reformat. * Test case same as ESP8266 * Implementing inline in header saves 204+ bytes program size. * Examples * Fix a compiler warning due to c-style casting. * Revert formatting changes * More format reversions * Revert * Revert * Revert --------- Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
This commit is contained in:
parent
ead76fd395
commit
f764af0d1c
6 changed files with 178 additions and 82 deletions
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* This example demonstrates used of Ticker with arguments.
|
||||
* You can call the same callback function with different argument on different times.
|
||||
* Based on the argument the callback can perform different tasks.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Ticker.h>
|
||||
|
||||
// Arguments for the function must remain valid (not run out of scope) otherwise the function would read garbage data.
|
||||
int LED_PIN_1 = 4;
|
||||
#ifdef LED_BUILTIN
|
||||
int LED_PIN_2 = LED_BUILTIN;
|
||||
#else
|
||||
int LED_PIN_2 = 8;
|
||||
#endif
|
||||
|
||||
Ticker tickerSetHigh;
|
||||
Ticker tickerSetLow;
|
||||
|
||||
// Argument to callback must always be passed a reference
|
||||
void swapState(int *pin) {
|
||||
static int led_1_state = 1;
|
||||
static int led_2_state = 1;
|
||||
if(*pin == LED_PIN_1){
|
||||
Serial.printf("[%lu ms] set pin %d to state: %d\n", millis(), *pin, led_1_state);
|
||||
digitalWrite(*pin, led_1_state);
|
||||
led_1_state = led_1_state ? 0 : 1; // reverse for next pass
|
||||
}else if(*pin == LED_PIN_2){
|
||||
Serial.printf("[%lu ms] set pin %d to state: %d\n", millis(), *pin, led_2_state);
|
||||
digitalWrite(*pin, led_2_state);
|
||||
led_2_state = led_2_state ? 0 : 1; // reverse for next pass
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_PIN_1, OUTPUT);
|
||||
pinMode(LED_PIN_2, OUTPUT);
|
||||
//digitalWrite(1, LOW);
|
||||
|
||||
// Blink LED every 500 ms on LED_PIN_1
|
||||
tickerSetLow.attach_ms(500, swapState, &LED_PIN_1);
|
||||
|
||||
// Blink LED every 1000 ms on LED_PIN_2
|
||||
tickerSetHigh.attach_ms(1000, swapState, &LED_PIN_2);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
49
libraries/Ticker/examples/TickerBasic/TickerBasic.ino
Normal file
49
libraries/Ticker/examples/TickerBasic/TickerBasic.ino
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Basic Ticker usage
|
||||
|
||||
Ticker is an object that will call a given function with a certain period.
|
||||
Each Ticker calls one function. You can have as many Tickers as you like,
|
||||
memory being the only limitation.
|
||||
|
||||
A function may be attached to a ticker and detached from the ticker.
|
||||
There are two variants of the attach function: attach and attach_ms.
|
||||
The first one takes period in seconds, the second one in milliseconds.
|
||||
|
||||
The built-in LED will be blinking.
|
||||
*/
|
||||
|
||||
#include <Ticker.h>
|
||||
|
||||
#ifndef LED_BUILTIN
|
||||
#define LED_BUILTIN 13
|
||||
#endif
|
||||
|
||||
Ticker flipper;
|
||||
|
||||
int count = 0;
|
||||
|
||||
void flip() {
|
||||
int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
|
||||
digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state
|
||||
|
||||
++count;
|
||||
// when the counter reaches a certain value, start blinking like crazy
|
||||
if (count == 20) {
|
||||
flipper.attach(0.1, flip);
|
||||
}
|
||||
// when the counter reaches yet another value, stop blinking
|
||||
else if (count == 120) {
|
||||
flipper.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
// flip the pin every 0.3s
|
||||
flipper.attach(0.3, flip);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Passing paramters to Ticker callbacks
|
||||
|
||||
Apart from void(void) functions, the Ticker library supports
|
||||
functions taking one argument. This argument's size has to be less or
|
||||
equal to 4 bytes (so char, short, int, float, void*, char* types will do).
|
||||
|
||||
This sample runs two tickers that both call one callback function,
|
||||
but with different arguments.
|
||||
|
||||
The built-in LED will be pulsing.
|
||||
*/
|
||||
|
||||
#include <Ticker.h>
|
||||
|
||||
#ifndef LED_BUILTIN
|
||||
#define LED_BUILTIN 13
|
||||
#endif
|
||||
|
||||
Ticker tickerSetLow;
|
||||
Ticker tickerSetHigh;
|
||||
Ticker tickerSetChar;
|
||||
|
||||
void setPinLow() {
|
||||
digitalWrite(LED_BUILTIN, 0);
|
||||
}
|
||||
|
||||
void setPinHigh() {
|
||||
digitalWrite(LED_BUILTIN, 1);
|
||||
}
|
||||
|
||||
void setPin(int state) {
|
||||
digitalWrite(LED_BUILTIN, state);
|
||||
}
|
||||
|
||||
void setPinChar(char state) {
|
||||
digitalWrite(LED_BUILTIN, state);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// every 25 ms, call setPinLow()
|
||||
tickerSetLow.attach_ms(25, setPinLow);
|
||||
|
||||
// every 26 ms, call setPinHigh()
|
||||
tickerSetHigh.attach_ms(26, setPinHigh);
|
||||
|
||||
// every 54 ms, call setPinChar(1)
|
||||
tickerSetChar.attach_ms(26, setPinChar, (char)1);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
|
@ -10,5 +10,9 @@ Ticker KEYWORD1
|
|||
|
||||
attach KEYWORD2
|
||||
attach_ms KEYWORD2
|
||||
attach_us KEYWORD2
|
||||
once KEYWORD2
|
||||
once_ms KEYWORD2
|
||||
once_us KEYWORD2
|
||||
detach KEYWORD2
|
||||
active KEYWORD2
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Ticker::~Ticker() {
|
|||
detach();
|
||||
}
|
||||
|
||||
void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg) {
|
||||
void Ticker::_attach_us(uint64_t micros, bool repeat, callback_with_arg_t callback, void* arg) {
|
||||
esp_timer_create_args_t _timerConfig;
|
||||
_timerConfig.arg = reinterpret_cast<void*>(arg);
|
||||
_timerConfig.callback = callback;
|
||||
|
|
@ -43,9 +43,9 @@ void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t
|
|||
}
|
||||
esp_timer_create(&_timerConfig, &_timer);
|
||||
if (repeat) {
|
||||
esp_timer_start_periodic(_timer, milliseconds * 1000ULL);
|
||||
esp_timer_start_periodic(_timer, micros);
|
||||
} else {
|
||||
esp_timer_start_once(_timer, milliseconds * 1000ULL);
|
||||
esp_timer_start_once(_timer, micros);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,10 +54,19 @@ void Ticker::detach() {
|
|||
esp_timer_stop(_timer);
|
||||
esp_timer_delete(_timer);
|
||||
_timer = nullptr;
|
||||
_callback_function = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ticker::active() {
|
||||
bool Ticker::active() const {
|
||||
if (!_timer) return false;
|
||||
return esp_timer_is_active(_timer);
|
||||
}
|
||||
|
||||
void Ticker::_static_callback(void* arg)
|
||||
{
|
||||
Ticker* _this = reinterpret_cast<Ticker*>(arg);
|
||||
if (_this && _this->_callback_function)
|
||||
_this->_callback_function();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,79 +28,110 @@
|
|||
extern "C" {
|
||||
#include "esp_timer.h"
|
||||
}
|
||||
#include <functional>
|
||||
|
||||
class Ticker
|
||||
{
|
||||
public:
|
||||
Ticker();
|
||||
~Ticker();
|
||||
typedef void (*callback_t)(void);
|
||||
typedef void (*callback_with_arg_t)(void*);
|
||||
|
||||
void attach(float seconds, callback_t callback)
|
||||
typedef void (*callback_with_arg_t)(void*);
|
||||
typedef std::function<void(void)> callback_function_t;
|
||||
|
||||
void attach(float seconds, callback_function_t callback)
|
||||
{
|
||||
_attach_ms(seconds * 1000, true, reinterpret_cast<callback_with_arg_t>(callback), 0);
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(1000000ULL * seconds, true, _static_callback, this);
|
||||
}
|
||||
|
||||
void attach_ms(uint32_t milliseconds, callback_t callback)
|
||||
void attach_ms(uint64_t milliseconds, callback_function_t callback)
|
||||
{
|
||||
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), 0);
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(1000ULL * milliseconds, true, _static_callback, this);
|
||||
}
|
||||
|
||||
void attach_us(uint64_t micros, callback_function_t callback)
|
||||
{
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(micros, true, _static_callback, this);
|
||||
}
|
||||
|
||||
template<typename TArg>
|
||||
void attach(float seconds, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes");
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
// C-cast serves two purposes:
|
||||
// static_cast for smaller integer types,
|
||||
// reinterpret_cast + const_cast for pointer types
|
||||
uint32_t arg32 = (uint32_t)arg;
|
||||
_attach_ms(seconds * 1000, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
||||
_attach_us(1000000ULL * seconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
template<typename TArg>
|
||||
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
|
||||
void attach_ms(uint64_t milliseconds, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes");
|
||||
uint32_t arg32 = (uint32_t)arg;
|
||||
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
_attach_us(1000ULL * milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
void once(float seconds, callback_t callback)
|
||||
template<typename TArg>
|
||||
void attach_us(uint64_t micros, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
_attach_ms(seconds * 1000, false, reinterpret_cast<callback_with_arg_t>(callback), 0);
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
_attach_us(micros, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
void once_ms(uint32_t milliseconds, callback_t callback)
|
||||
void once(float seconds, callback_function_t callback)
|
||||
{
|
||||
_attach_ms(milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), 0);
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(1000000ULL * seconds, false, _static_callback, this);
|
||||
}
|
||||
|
||||
void once_ms(uint64_t milliseconds, callback_function_t callback)
|
||||
{
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(1000ULL * milliseconds, false, _static_callback, this);
|
||||
}
|
||||
|
||||
void once_us(uint64_t micros, callback_function_t callback)
|
||||
{
|
||||
_callback_function = std::move(callback);
|
||||
_attach_us(micros, false, _static_callback, this);
|
||||
}
|
||||
|
||||
template<typename TArg>
|
||||
void once(float seconds, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes");
|
||||
uint32_t arg32 = (uint32_t)(arg);
|
||||
_attach_ms(seconds * 1000, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
_attach_us(1000000ULL * seconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
template<typename TArg>
|
||||
void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
|
||||
void once_ms(uint64_t milliseconds, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes");
|
||||
uint32_t arg32 = (uint32_t)(arg);
|
||||
_attach_ms(milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
_attach_us(1000ULL * milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
template<typename TArg>
|
||||
void once_us(uint64_t micros, void (*callback)(TArg), TArg arg)
|
||||
{
|
||||
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||
_attach_us(micros, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||
}
|
||||
|
||||
void detach();
|
||||
bool active();
|
||||
bool active() const;
|
||||
|
||||
protected:
|
||||
void _attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg);
|
||||
static void _static_callback(void* arg);
|
||||
|
||||
callback_function_t _callback_function = nullptr;
|
||||
|
||||
protected:
|
||||
esp_timer_handle_t _timer;
|
||||
|
||||
private:
|
||||
void _attach_us(uint64_t micros, bool repeat, callback_with_arg_t callback, void* arg);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue