#include "badge/gpio.h" #include "badge/config.h" #include #define BUTTON_PIN 0 #if UVOK_EPAP_BOARD == BOARD_ESP32_CROWPANEL // Elecrow #define EXIT_KEY 1 #define HOME_KEY 2 #define NEXT_KEY 4 #define OK_KEY 5 #define PRV_KEY 6 #endif static unsigned long pressedTime = 0; static unsigned long releasedTime = 0; static void gpio_loop(void *); typedef uint32_t pin_notification_t; #define GPIO_STACK 2048 #define GPIO_QUEUE_LEN 4 static StaticTask_t gpio_task; static StackType_t gpio_stack[GPIO_STACK / sizeof(StackType_t)]; static StaticQueue_t gpio_queue_storage; static uint8_t gpio_queue_content[GPIO_QUEUE_LEN * sizeof(pin_notification_t)]; static QueueHandle_t gpio_q; static ARDUINO_ISR_ATTR void gpio_pin_irq(void *); void de::uvok::badge::gpio_init(void) { xTaskCreateStatic(gpio_loop, "gpio", GPIO_STACK, NULL, configMAX_PRIORITIES - 1, gpio_stack, &gpio_task); gpio_q = xQueueCreateStatic(4, sizeof(pin_notification_t), &(gpio_queue_content[0]), &gpio_queue_storage); #if UVOK_EPAP_BOARD == BOARD_ESP32_CROWPANEL uint8_t inPins[] = {EXIT_KEY, HOME_KEY, NEXT_KEY, OK_KEY, PRV_KEY}; for (uint8_t p : inPins) { pinMode(p, GPIO_MODE_INPUT); // simply use pin number as arg attachInterruptArg(p, gpio_pin_irq, (void *)(ptrdiff_t)p, CHANGE); } #endif } long de::uvok::badge::gpio_poll(void) { int x = 0; static int lastState = HIGH; int buttonState = digitalRead(BUTTON_PIN); long pressDuration = 0; if (lastState == HIGH && buttonState == LOW) { Serial.println("``\\__"); pressedTime = millis(); lastState = LOW; } else if (lastState == LOW && buttonState == HIGH) { lastState = HIGH; Serial.println("__/``"); releasedTime = millis(); pressDuration = releasedTime - pressedTime; }; return pressDuration; } static void gpio_loop(void *ctx) { Serial.println("Starting GPIO loop"); while (1) { pin_notification_t received; if (xQueueReceive(gpio_q, &received, portMAX_DELAY) == pdTRUE) { const int level = (received & 0x100) ? HIGH : LOW; const bool pressed = !level; const int pin = received & 0xff; Serial.printf("Pin %d was %s\n", pin, pressed ? "pressed" : "released"); } } } static ARDUINO_ISR_ATTR void gpio_pin_irq(void *arg) { uint8_t pin_no = (uint8_t)(ptrdiff_t)arg; int pinLevel = digitalRead(pin_no); pin_notification_t send = (pinLevel << 8) | (pin_no); BaseType_t wakeup = false; xQueueSendFromISR(gpio_q, &send, &wakeup); if (wakeup) { portYIELD_FROM_ISR(); } }