summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoruvok2025-07-19 10:56:27 +0200
committeruvok2025-07-19 10:56:27 +0200
commit96c28ff38fa4339dde6abaad414c0ccd79aca0c4 (patch)
tree69328104982ddc0e00238ce47e6260690a74e6b3 /src
parent26a3a757f167b7de920ffe4f3563c40e88e9d3eb (diff)
gpio: Reorder file, add filter
Diffstat (limited to 'src')
-rw-r--r--src/gpio.cpp52
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)