diff options
author | uvok | 2025-07-19 10:56:27 +0200 |
---|---|---|
committer | uvok | 2025-07-19 10:56:27 +0200 |
commit | 96c28ff38fa4339dde6abaad414c0ccd79aca0c4 (patch) | |
tree | 69328104982ddc0e00238ce47e6260690a74e6b3 /src | |
parent | 26a3a757f167b7de920ffe4f3563c40e88e9d3eb (diff) |
gpio: Reorder file, add filter
Diffstat (limited to 'src')
-rw-r--r-- | src/gpio.cpp | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/src/gpio.cpp b/src/gpio.cpp index 84dc545..cf1343f 100644 --- a/src/gpio.cpp +++ b/src/gpio.cpp @@ -16,7 +16,8 @@ #define PRV_KEY 6 #endif -static void gpio_loop(void *); +#define GPIO_STACK 2048 +#define GPIO_QUEUE_LEN 32 typedef struct { @@ -27,21 +28,21 @@ typedef struct _Static_assert(sizeof(uint32_t) >= sizeof(unsigned long), "return type of millis"); -#define GPIO_STACK 2048 -#define GPIO_QUEUE_LEN 32 -static unsigned long pressedTime = 0; -static unsigned long releasedTime = 0; - +//! Keep track of inputs via interrupt typedef struct { // uint32_t last_change; uint32_t last_level; uint32_t pressed; uint32_t released; + // ... already forgot why I wanted this + uint32_t last_handled; } InputInfo_t; +//! Keep track of inputs via interrupt static volatile InputInfo_t inputs[NUM_DIGITAL_PINS]; +//! FreeRTOS handles, storages, etc. static struct { @@ -54,7 +55,9 @@ static struct } gpio_task_stuff; static ARDUINO_ISR_ATTR void gpio_pin_irq(void *); +static void gpio_loop(void *); +//! Create task, initialize pins... void de::uvok::badge::gpio_init(void) { xTaskCreateStatic(gpio_loop, "gpio", GPIO_STACK, NULL, configMAX_PRIORITIES - 1, gpio_task_stuff.task_stack, @@ -73,8 +76,12 @@ void de::uvok::badge::gpio_init(void) #endif } +// "Poll task", for button 0. long de::uvok::badge::gpio_poll(void) { + static unsigned long pressedTime = 0; + static unsigned long releasedTime = 0; + int x = 0; static int lastState = HIGH; int buttonState = digitalRead(BUTTON_PIN); @@ -97,6 +104,7 @@ long de::uvok::badge::gpio_poll(void) return pressDuration; } +//! GPIO task loop, read / handle queue. static void gpio_loop(void *ctx) { Serial.println("Starting GPIO loop"); @@ -109,29 +117,47 @@ static void gpio_loop(void *ctx) const uint8_t pin = received.pin; LOG_F("(%u) Pin %u was %s\n", received.timestamp, pin, pressed ? "pressed" : "released"); LOG_F(" pressed: %u, released: %u\n", inputs[pin].pressed, inputs[pin].released); + + if ( + // ignore weird stuff + inputs[pin].pressed == 0 + // Ignore overflows - badge won't be powered always anyway + || inputs[pin].pressed >= inputs[pin].released + // Ignore "bouncing" or very short presses. + || inputs[pin].released - inputs[pin].pressed < 50) + continue; + + LOG_F(" Handling"); } } } +//! GPIO interrupt handler static ARDUINO_ISR_ATTR IRAM_ATTR void gpio_pin_irq(void *arg) { + /* + ... Ugh. + Pins 4, 5, 6, the selector thingy, is very dirty, or the IRQ is too slow. + Even with that code, I sometimes get multiples pressed events directly after each other, + or multiple released events. + Need to use some filtering, maybe missing some dirty events as a result. + */ const uint8_t pin_no = (uint8_t)(ptrdiff_t)arg; const int pinLevel = digitalRead(pin_no); + const uint32_t now = millis(); - uint32_t now = millis(); + // Only remember pressed events, don't post. if (!pinLevel) { inputs[pin_no].pressed = now; return; } - inputs[pin_no].released = now; - // Elecrow inputs - the selector - are very dirty... - // const bool is_dirty = now - inputs[pin_no].last_change < 50; - // if (is_dirty) - // return; + // Only post released events + inputs[pin_no].released = now; + // do any filtering in the main task loop - pin_notification_t send = {.timestamp = now, .pin = pin_no, .state = (pinLevel == HIGH)}; + const pin_notification_t send = {.timestamp = now, .pin = pin_no, .state = (pinLevel == HIGH)}; BaseType_t wakeup = false; xQueueSendFromISR(gpio_task_stuff.queue_handle, &send, &wakeup); if (wakeup) |