diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b33b4b8..12ed1ef1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-uart.c cores/esp32/Esp.cpp + cores/esp32/FunctionalInterrupt.cpp cores/esp32/HardwareSerial.cpp cores/esp32/IPAddress.cpp cores/esp32/IPv6Address.cpp diff --git a/cores/esp32/FunctionalInterrupt.cpp b/cores/esp32/FunctionalInterrupt.cpp new file mode 100644 index 00000000..d2e6dfd4 --- /dev/null +++ b/cores/esp32/FunctionalInterrupt.cpp @@ -0,0 +1,44 @@ +/* + * FunctionalInterrupt.cpp + * + * Created on: 8 jul. 2018 + * Author: Herman + */ + +#include "FunctionalInterrupt.h" +#include "Arduino.h" + +typedef void (*voidFuncPtr)(void); +typedef void (*voidFuncPtrArg)(void*); + +extern "C" +{ + extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional); +} + +void IRAM_ATTR interruptFunctional(void* arg) +{ + InterruptArgStructure* localArg = (InterruptArgStructure*)arg; + if (localArg->interruptFunction) + { + localArg->interruptFunction(); + } +} + +void attachInterrupt(uint8_t pin, std::function intRoutine, int mode) +{ + // use the local interrupt routine which takes the ArgStructure as argument + __attachInterruptFunctionalArg (pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true); +} + +extern "C" +{ + void cleanupFunctional(void* arg) + { + delete (InterruptArgStructure*)arg; + } +} + + + + diff --git a/cores/esp32/FunctionalInterrupt.h b/cores/esp32/FunctionalInterrupt.h new file mode 100644 index 00000000..b5e3181f --- /dev/null +++ b/cores/esp32/FunctionalInterrupt.h @@ -0,0 +1,20 @@ +/* + * FunctionalInterrupt.h + * + * Created on: 8 jul. 2018 + * Author: Herman + */ + +#ifndef CORE_CORE_FUNCTIONALINTERRUPT_H_ +#define CORE_CORE_FUNCTIONALINTERRUPT_H_ + +#include + +struct InterruptArgStructure { + std::function interruptFunction; +}; + +void attachInterrupt(uint8_t pin, std::function intRoutine, int mode); + + +#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */ diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c index d3df2961..64cb6653 100644 --- a/cores/esp32/esp32-hal-gpio.c +++ b/cores/esp32/esp32-hal-gpio.c @@ -74,6 +74,7 @@ typedef void (*voidFuncPtrArg)(void*); typedef struct { voidFuncPtr fn; void* arg; + bool functional; } InterruptHandle_t; static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,}; @@ -238,16 +239,26 @@ static void IRAM_ATTR __onPinInterrupt() } } -extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type) +extern void cleanupFunctional(void* arg); + +extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional) { static bool interrupt_initialized = false; - + if(!interrupt_initialized) { interrupt_initialized = true; esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle); } + + // if new attach without detach remove old info + if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) + { + cleanupFunctional(__pinInterruptHandlers[pin].arg); + } __pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc; __pinInterruptHandlers[pin].arg = arg; + __pinInterruptHandlers[pin].functional = functional; + esp_intr_disable(gpio_intr_handle); if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU GPIO.pin[pin].int_ena = 1; @@ -258,15 +269,26 @@ extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * ar esp_intr_enable(gpio_intr_handle); } +extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type) +{ + __attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false); +} + extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) { - __attachInterruptArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type); + __attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false); } extern void __detachInterrupt(uint8_t pin) { esp_intr_disable(gpio_intr_handle); + if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) + { + cleanupFunctional(__pinInterruptHandlers[pin].arg); + } __pinInterruptHandlers[pin].fn = NULL; __pinInterruptHandlers[pin].arg = NULL; + __pinInterruptHandlers[pin].arg = false; + GPIO.pin[pin].int_ena = 0; GPIO.pin[pin].int_type = 0; esp_intr_enable(gpio_intr_handle); diff --git a/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino b/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino new file mode 100644 index 00000000..0e9f9741 --- /dev/null +++ b/libraries/ESP32/examples/GPIO/FunctionalInterrupt/FunctionalInterrupt.ino @@ -0,0 +1,47 @@ +#include +#include + +#define BUTTON1 16 +#define BUTTON2 17 + +class Button +{ +public: + Button(uint8_t reqPin) : PIN(reqPin){ + pinMode(PIN, INPUT_PULLUP); + attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING); + }; + ~Button() { + detachInterrupt(PIN); + } + + void IRAM_ATTR isr() { + numberKeyPresses += 1; + pressed = true; + } + + void checkPressed() { + if (pressed) { + Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses); + pressed = false; + } + } + +private: + const uint8_t PIN; + volatile uint32_t numberKeyPresses; + volatile bool pressed; +}; + +Button button1(BUTTON1); +Button button2(BUTTON2); + + +void setup() { + Serial.begin(115200); +} + +void loop() { + button1.checkPressed(); + button2.checkPressed(); +} diff --git a/libraries/ESP32/examples/GPIOInterrupt/GPIOInterrupt.ino b/libraries/ESP32/examples/GPIO/GPIOInterrupt/GPIOInterrupt.ino similarity index 100% rename from libraries/ESP32/examples/GPIOInterrupt/GPIOInterrupt.ino rename to libraries/ESP32/examples/GPIO/GPIOInterrupt/GPIOInterrupt.ino