From 1d90aeeec73fc5e0e6ebf22803e9442c0d598698 Mon Sep 17 00:00:00 2001 From: David Cruchon Date: Tue, 19 Oct 2021 11:49:04 +0200 Subject: [PATCH] Add the blink utility function from mgos_gpio --- include/mgos_pcf857x.h | 11 +++++++ src/mgos_pcf857x.c | 61 ++++++++++++++++++++++++++++++++++++- src/mgos_pcf857x_internal.h | 10 ++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/include/mgos_pcf857x.h b/include/mgos_pcf857x.h index 0a910ee..3d05070 100644 --- a/include/mgos_pcf857x.h +++ b/include/mgos_pcf857x.h @@ -18,6 +18,7 @@ #include "mgos.h" #include "mgos_gpio.h" #include "mgos_i2c.h" +#include "mgos_timers.h" #ifdef __cplusplus extern "C" { @@ -25,6 +26,8 @@ extern "C" { struct mgos_pcf857x; +struct mgos_pcf857x_gpio_blink_state; + /* * Initialize a PCF857X on the I2C bus `i2c` at address specified in `i2caddr` * parameter (default PCF857X is on address 0x20). The device will be polled for @@ -63,6 +66,14 @@ void mgos_pcf857x_gpio_clear_int(struct mgos_pcf857x *dev, int pin); void mgos_pcf857x_gpio_remove_int_handler(struct mgos_pcf857x *dev, int pin, mgos_gpio_int_handler_f *old_cb, void **old_arg); bool mgos_pcf857x_gpio_set_button_handler(struct mgos_pcf857x *dev, int pin, enum mgos_gpio_pull_type pull_type, enum mgos_gpio_int_mode int_mode, int debounce_ms, mgos_gpio_int_handler_f cb, void *arg); +/* + * A utility function that takes care of blinking an LED. + * The pin must be configured as output first. + * Set to (0, 0) to disable. + */ +bool mgos_pcf857x_gpio_blink(struct mgos_pcf857x *dev, int pin, int on_ms, int off_ms); +void mgos_pcf857x_gpio_blink_cb(void *arg); + #ifdef __cplusplus } #endif diff --git a/src/mgos_pcf857x.c b/src/mgos_pcf857x.c index 8f1973d..2c49439 100644 --- a/src/mgos_pcf857x.c +++ b/src/mgos_pcf857x.c @@ -13,9 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include #include "mgos_pcf857x_internal.h" +#define LD(fmt, ...) LOG(LL_DEBUG, ("[BLINK STATE] " fmt, ##__VA_ARGS__)) + +static struct mgos_pcf857x_gpio_blink_state **blink_states = NULL; + +struct mgos_pcf857x_gpio_blink_state *mgos_pcf857x_get_or_create_blink_state(struct mgos_pcf857x *dev, int pin) { + if (blink_states == NULL) { + blink_states = calloc(dev->num_gpios, sizeof(struct mgos_pcf857x_gpio_blink_state *)); + LD("Init %d pin", dev->num_gpios); + } + + if (blink_states[pin] == NULL) { + blink_states[pin] = calloc(1, sizeof(struct mgos_pcf857x_gpio_blink_state)); + blink_states[pin]->dev = dev; + blink_states[pin]->pin = pin; + blink_states[pin]->blink.timer_id = MGOS_INVALID_TIMER_ID; + } + + return blink_states[pin]; +} + void mgos_pcf857x_print_state(struct mgos_pcf857x *dev) { uint8_t n; char s[17], i[17]; @@ -352,6 +372,45 @@ bool mgos_pcf857x_gpio_set_button_handler(struct mgos_pcf857x *dev, int pin, enu (void)pull_type; } +void mgos_pcf857x_gpio_blink_cb(void *arg) { + struct mgos_pcf857x_gpio_blink_state *bs = (struct mgos_pcf857x_gpio_blink_state *)arg; + + if (bs != NULL) { + bool curr = mgos_pcf857x_gpio_toggle(bs->dev, bs->pin); + if (bs->blink.on_ms != bs->blink.off_ms) { + int timeout = (curr ? bs->blink.on_ms : bs->blink.off_ms); + bs->blink.timer_id = mgos_set_timer(timeout, 0, mgos_pcf857x_gpio_blink_cb, bs); + } + } +} + +bool mgos_pcf857x_gpio_blink(struct mgos_pcf857x *dev, int pin, int on_ms, int off_ms) { + bool res = !(!dev || on_ms < 0 || off_ms < 0 || on_ms >= 65536 || off_ms >= 65536); + if (res) { + struct mgos_pcf857x_gpio_blink_state *bs = mgos_pcf857x_get_or_create_blink_state(dev, pin); + if (bs != NULL) { + + bs->blink.on_ms = on_ms; + bs->blink.off_ms = off_ms; + + if (bs->blink.timer_id != MGOS_INVALID_TIMER_ID) { + mgos_clear_timer(bs->blink.timer_id); + bs->blink.timer_id = MGOS_INVALID_TIMER_ID; + LD("Clear timer for PIN-%d", bs->pin); + } + if (on_ms != 0 && off_ms != 0) { + bs->blink.timer_id = mgos_set_timer( + on_ms, + (on_ms == off_ms ? MGOS_TIMER_REPEAT : 0) | MGOS_TIMER_RUN_NOW, + mgos_pcf857x_gpio_blink_cb, bs); + res = (bs->blink.timer_id != MGOS_INVALID_TIMER_ID); + LD("Set timer for PIN-%d (on=%dms, off=%dms)", bs->pin, bs->blink.on_ms, bs->blink.off_ms); + } + } + } + return res; +} + // Mongoose OS library initialization bool mgos_pcf857x_i2c_init(void) { return true; diff --git a/src/mgos_pcf857x_internal.h b/src/mgos_pcf857x_internal.h index 1fc0992..aa6ea85 100644 --- a/src/mgos_pcf857x_internal.h +++ b/src/mgos_pcf857x_internal.h @@ -46,6 +46,16 @@ struct mgos_pcf857x { struct mgos_pcf857x_cb cb[16]; }; +struct mgos_pcf857x_gpio_blink_state { + int pin; + struct mgos_pcf857x *dev; + struct { + unsigned int on_ms; + unsigned int off_ms; + mgos_timer_id timer_id; + } blink; +}; + /* Mongoose OS initializer */ bool mgos_pcf857x_i2c_init(void);