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 KEYWORD2
|
||||||
attach_ms KEYWORD2
|
attach_ms KEYWORD2
|
||||||
|
attach_us KEYWORD2
|
||||||
once KEYWORD2
|
once KEYWORD2
|
||||||
|
once_ms KEYWORD2
|
||||||
|
once_us KEYWORD2
|
||||||
detach KEYWORD2
|
detach KEYWORD2
|
||||||
|
active KEYWORD2
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Ticker::~Ticker() {
|
||||||
detach();
|
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;
|
esp_timer_create_args_t _timerConfig;
|
||||||
_timerConfig.arg = reinterpret_cast<void*>(arg);
|
_timerConfig.arg = reinterpret_cast<void*>(arg);
|
||||||
_timerConfig.callback = callback;
|
_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);
|
esp_timer_create(&_timerConfig, &_timer);
|
||||||
if (repeat) {
|
if (repeat) {
|
||||||
esp_timer_start_periodic(_timer, milliseconds * 1000ULL);
|
esp_timer_start_periodic(_timer, micros);
|
||||||
} else {
|
} 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_stop(_timer);
|
||||||
esp_timer_delete(_timer);
|
esp_timer_delete(_timer);
|
||||||
_timer = nullptr;
|
_timer = nullptr;
|
||||||
|
_callback_function = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ticker::active() {
|
bool Ticker::active() const {
|
||||||
if (!_timer) return false;
|
if (!_timer) return false;
|
||||||
return esp_timer_is_active(_timer);
|
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" {
|
extern "C" {
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
}
|
}
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class Ticker
|
class Ticker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Ticker();
|
Ticker();
|
||||||
~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>
|
template<typename TArg>
|
||||||
void attach(float seconds, void (*callback)(TArg), TArg arg)
|
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:
|
// C-cast serves two purposes:
|
||||||
// static_cast for smaller integer types,
|
// static_cast for smaller integer types,
|
||||||
// reinterpret_cast + const_cast for pointer types
|
// reinterpret_cast + const_cast for pointer types
|
||||||
uint32_t arg32 = (uint32_t)arg;
|
_attach_us(1000000ULL * seconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||||
_attach_ms(seconds * 1000, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TArg>
|
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");
|
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||||
uint32_t arg32 = (uint32_t)arg;
|
_attach_us(1000ULL * milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||||
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
template<typename TArg>
|
||||||
void once(float seconds, void (*callback)(TArg), TArg arg)
|
void once(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*)");
|
||||||
uint32_t arg32 = (uint32_t)(arg);
|
_attach_us(1000000ULL * seconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||||
_attach_ms(seconds * 1000, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TArg>
|
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");
|
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
|
||||||
uint32_t arg32 = (uint32_t)(arg);
|
_attach_us(1000ULL * milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
|
||||||
_attach_ms(milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
|
}
|
||||||
|
|
||||||
|
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();
|
void detach();
|
||||||
bool active();
|
bool active() const;
|
||||||
|
|
||||||
protected:
|
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;
|
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