diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index e467e73..90f2f99 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -93,6 +93,7 @@ jobs: libraries: | - name: Arduino_Cellular - name: Blues Wireless Notecard + - name: Arduino_PortentaMachineControl # Nicla Vision - board: type: mbed_nicla diff --git a/README.md b/README.md index 0546307..672ff49 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,27 @@ The procedure: * `Arduino MKR WiFi 1010`: short the pin 7 to GND until the led turns off * `Arduino GIGA R1 WiFi`: short the pin 7 to GND until the led turns off * `Arduino Nano RP2040 Connect`: short the pin 2 to 3.3V until the led turns off +* `Arduino Portenta H7`: short the pin 0 to GND until the led turns off +* `Portenta Machine Control`: plug the device to a 24V power source, short the pin Digital Inputs 0 to 24VOUT until the led (`LED_BUILTIN`) turns off * Other boards: short the pin 2 to GND until the led turns off +### More on the reconfiguration pin +Internally, the pin indicated in the procedure is set as `INPUT_PULLUP` (except for `Arduino Opta` ) and it's attached to an ISR fired on every change of the pin's status. + +In order to be notified when the ISR is fired, it's possible to register a callback function using the function `NetworkConfigurator.addReconfigurePinCallback(callback)`. Please take the example as reference. + +### Change the reconfiguration pin +In order to change the default pin for resetting the board, it's possible to use the function `NetworkConfigurator.setReconfigurePin(your_pin)` specifying the new pin. +The pin must be in the list of digital pins usable for interrupts. Please refer to the Arduino documentation for more details: https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ + +N.B.: For `Portenta Machine Control`, the pin must be one of the Digital Inputs 0-7. + The parameter must be one of the range DIN_READ_CH_PIN_00-DIN_READ_CH_PIN_07. + The defines are available in the Portenta Machine Control library and you must include Arduino_PortentaMachineControl.h for having access to them. + +### Disable the reconfiguration feature +In order to disable the reconfiguration procedure, use this function in the sketch `NetworkConfigurator.setReconfigurePin(DISABLE_PIN)` + + ## Configurator Agents The library provides a set of *Configurator Agents* that added as plug-in to the sketch handle the communication between the Arduino Network Configurator and an external client ([*Arduino IoT App*](https://cloud.arduino.cc/iot-remote-app/) and Arduino IoT Cloud) for configuring the board. diff --git a/examples/NetworkConfiguratorDemo/NetworkConfiguratorDemo.ino b/examples/NetworkConfiguratorDemo/NetworkConfiguratorDemo.ino index 1bb8e6c..57840f1 100644 --- a/examples/NetworkConfiguratorDemo/NetworkConfiguratorDemo.ino +++ b/examples/NetworkConfiguratorDemo/NetworkConfiguratorDemo.ino @@ -21,6 +21,9 @@ * - Arduino MKR WiFi 1010: short the pin 7 to GND until the led turns off * - Arduino GIGA R1 WiFi: short the pin 7 to GND until the led turns off * - Arduino Nano RP2040 Connect: short the pin 2 to 3.3V until the led turns off + * - Portenta H7: short the pin 0 to GND until the led turns off + * - Portenta Machine Control: plug the device to a 24V power source, short the pin Digital Inputs 0 + * to 24VOUT until the led (`LED_BUILTIN`) turns off * - Other boards: short the pin 2 to GND until the led turns off * * In this sketch the BLE and Serial interfaces are always enabled and ready for accepting @@ -76,6 +79,10 @@ void setup() { * The pin must be in the list of digital pins usable for interrupts. * Please refer to the Arduino documentation for more details: * https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ + * N.B.: For Portenta Machine Control, the pin must be one of the Digital Inputs 0-7. + * The parameter must be one of the range DIN_READ_CH_PIN_00-DIN_READ_CH_PIN_07. + * The defines are available in the Portenta Machine Control library and you must include + * Arduino_PortentaMachineControl.h for having access to them. */ //NetworkConfigurator.setReconfigurePin(your_pin); diff --git a/src/ANetworkConfigurator_Config.h b/src/ANetworkConfigurator_Config.h index e1ca4cd..e01374b 100644 --- a/src/ANetworkConfigurator_Config.h +++ b/src/ANetworkConfigurator_Config.h @@ -57,7 +57,9 @@ #if defined(ARDUINO_PORTENTA_H7_M7) #define NETWORK_CONFIGURATOR_COMPATIBLE 1 #define ZERO_TOUCH_ENABLED 1 - #define PIN_RECONFIGURE 2 + #define I2C_ADD_DETECT_MACHINE_CONTROL_1 0x23 + #define I2C_ADD_DETECT_MACHINE_CONTROL_2 0x22 + #define PIN_RECONFIGURE 0 #define LED_RECONFIGURE LED_BUILTIN #define BOARD_HAS_RGB #define GREEN_LED LEDG diff --git a/src/Arduino_NetworkConfigurator.cpp b/src/Arduino_NetworkConfigurator.cpp index f448b1f..680a8ab 100644 --- a/src/Arduino_NetworkConfigurator.cpp +++ b/src/Arduino_NetworkConfigurator.cpp @@ -41,7 +41,7 @@ NetworkConfiguratorClass::NetworkConfiguratorClass(ConnectionHandler &connection _receivedEvent = NetworkConfiguratorEvents::NONE; _optionUpdateTimer.begin(NC_UPDATE_NETWORK_OPTIONS_TIMER_ms); //initialize the timer before calling begin _agentsManager = &AgentsManagerClass::getInstance(); - _resetInput = &ResetInput::getInstance(); + _resetInput = &ResetInputBase::getInstance(); _ledFeedback = &LEDFeedbackClass::getInstance(); } @@ -122,6 +122,9 @@ NetworkConfiguratorStates NetworkConfiguratorClass::update() { * - Arduino MKR WiFi 1010: short the pin 7 to GND until the led turns off * - Arduino GIGA R1 WiFi: short the pin 7 to GND until the led turns off * - Arduino Nano RP2040 Connect: short the pin 2 to 3.3V until the led turns off + * - Portenta H7: short the pin 0 to GND until the led turns off + * - Portenta Machine Control: plug the device to a 24V power source, short the pin Digital Inputs 0 + * to 24VOUT until the led (`LED_BUILTIN`) turns off * - Other boards: short the pin 2 to GND until the led turns off */ @@ -208,7 +211,7 @@ void NetworkConfiguratorClass::setReconfigurePin(int pin) { _resetInput->setPin(pin); } -void NetworkConfiguratorClass::addReconfigurePinCallback(ResetInput::ResetInputCallback callback) { +void NetworkConfiguratorClass::addReconfigurePinCallback(ResetInputBase::ResetInputCallback callback) { _resetInput->setPinChangedCallback(callback); } diff --git a/src/Arduino_NetworkConfigurator.h b/src/Arduino_NetworkConfigurator.h index d68bbdb..b3edc9f 100644 --- a/src/Arduino_NetworkConfigurator.h +++ b/src/Arduino_NetworkConfigurator.h @@ -16,7 +16,7 @@ #include #include #include -#include "utility/ResetInput.h" +#include "utility/ResetInputBase.h" #include "utility/LEDFeedback.h" /** @@ -58,6 +58,9 @@ enum class NetworkConfiguratorStates { ZERO_TOUCH_CONFIG, * - Arduino MKR WiFi 1010: short the pin 7 to GND until the led turns off * - Arduino GIGA R1 WiFi: short the pin 7 to GND until the led turns off * - Arduino Nano RP2040 Connect: short the pin 2 to 3.3V until the led turns off + * - Portenta H7: short the pin 0 to GND until the led turns off + * - Portenta Machine Control: plug the device to a 24V power source, short the pin Digital Inputs 0 + * to 24VOUT until the led (`LED_BUILTIN`) turns off * - Other boards: short the pin 2 to GND until the led turns off * */ @@ -119,6 +122,10 @@ class NetworkConfiguratorClass { * The pin must be in the list of digital pins usable for interrupts. * Please refer to the Arduino documentation for more details: * https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ + * N.B.: For Portenta Machine Control, the pin must be one of the Digital Inputs 0-7. + * The parameter must be one of the range DIN_READ_CH_PIN_00-DIN_READ_CH_PIN_07. + * The defines are available in the Portenta Machine Control library and you must include + * Arduino_PortentaMachineControl.h for having access to them. */ void setReconfigurePin(int pin); @@ -127,7 +134,7 @@ class NetworkConfiguratorClass { * interrupt on the reconfiguration pin is fired. * @param callback Pointer to the callback function. */ - void addReconfigurePinCallback(ResetInput::ResetInputCallback callback); + void addReconfigurePinCallback(ResetInputBase::ResetInputCallback callback); /** * @brief Checks if a specific configuration agent is enabled. @@ -163,7 +170,7 @@ class NetworkConfiguratorClass { static inline models::NetworkSetting _networkSetting; bool _connectionHandlerIstantiated; bool _configInProgress; - ResetInput *_resetInput; + ResetInputBase *_resetInput; LEDFeedbackClass *_ledFeedback; /* Timeout instances */ // Timeout for connection attempt diff --git a/src/utility/ResetInput.cpp b/src/utility/ResetInput.cpp deleted file mode 100644 index 0df5fc0..0000000 --- a/src/utility/ResetInput.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ -#include "ANetworkConfigurator_Config.h" -#if NETWORK_CONFIGURATOR_COMPATIBLE - -#include "ResetInput.h" -#include "utility/LEDFeedback.h" - -ResetInput &ResetInput::getInstance() { - static ResetInput instance; - return instance; -} - -ResetInput::ResetInput() { - _pin = PIN_RECONFIGURE; - _expired = false; - _startPressed = 0; - _fireEvent = false; - _pressedCustomCallback = nullptr; -} - -void ResetInput::begin() { - if(_pin == DISABLE_PIN){ - return; - } -#ifdef ARDUINO_OPTA - pinMode(_pin, INPUT); -#else - pinMode(_pin, INPUT_PULLUP); -#endif - pinMode(LED_RECONFIGURE, OUTPUT); - digitalWrite(LED_RECONFIGURE, LED_OFF); - - attachInterrupt(digitalPinToInterrupt(_pin),_pressedCallback, CHANGE); -} - -bool ResetInput::isEventFired() { - if(_startPressed != 0){ -#if defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_SAMD_MKRWIFI1010) - LEDFeedbackClass::getInstance().stop(); -#endif - if(micros() - _startPressed > RESET_HOLD_TIME){ - digitalWrite(LED_RECONFIGURE, LED_OFF); - _expired = true; - } - } - - return _fireEvent; -} - -void ResetInput::setPinChangedCallback(ResetInputCallback callback) { - _pressedCustomCallback = callback; -} - -void ResetInput::setPin(int pin) { - if(pin < 0){ - _pin = DISABLE_PIN; - }else { - _pin = pin; - } -} - -void ResetInput::_pressedCallback() { -#if defined(ARDUINO_NANO_RP2040_CONNECT) - if(digitalRead(_pin) == HIGH){ -#else - if(digitalRead(_pin) == LOW){ -#endif -#if !defined(ARDUINO_NANO_RP2040_CONNECT) && !defined(ARDUINO_SAMD_MKRWIFI1010) - LEDFeedbackClass::getInstance().stop(); -#endif - _startPressed = micros(); - digitalWrite(LED_RECONFIGURE, LED_ON); - } else { - digitalWrite(LED_RECONFIGURE, LED_OFF); - if(_startPressed != 0 && _expired){ - _fireEvent = true; - }else{ - LEDFeedbackClass::getInstance().restart(); - } - _startPressed = 0; - } - - if (_pressedCustomCallback) { - _pressedCustomCallback(); - } -} - -#endif // NETWORK_CONFIGURATOR_COMPATIBLE diff --git a/src/utility/ResetInput.h b/src/utility/ResetInput.h index a9700ee..c7bab72 100644 --- a/src/utility/ResetInput.h +++ b/src/utility/ResetInput.h @@ -8,68 +8,82 @@ #pragma once -#include "Arduino.h" -#include +#include "ANetworkConfigurator_Config.h" +#include "ResetInputBase.h" +#include "LEDFeedback.h" -#define DISABLE_PIN -1 - -/** - * @class ResetInput - * @brief A singleton class to handle input of the reset functionality with interrupt-based monitoring. - * - * This class provides methods to configure and monitor a reset input pin. It allows - * setting up a custom callback function to be executed when the pin status changes. - */ -class ResetInput{ +class ResetInput : public ResetInputBase { public: - /** - * @typedef ResetInput::ResetInputCallback - * @brief A type definition for the callback function to be executed on pin status change. - */ - typedef std::function ResetInputCallback; - /** - * @brief Get the singleton instance of the ResetInput class. - * @return A reference to the ResetInput instance. - */ - static ResetInput& getInstance(); - /** - * @brief Initialize the reset input by setting up the interrupt pin. - */ - void begin(); - /** - * @brief Check if the reset event has been fired. - * @return True if the event is fired, otherwise false. - */ - bool isEventFired(); - /** - * @brief Set a custom callback function to be called when the pin status changes. - * This function must be called before invoking the `begin` method. - * @param callback The custom callback function to be executed. - */ - void setPinChangedCallback(ResetInputCallback callback); - /** - * @brief Set the pin to be monitored for reset events. - * By default, the pin is set as INPUT_PULLUP. - * Use the value DISABLE_PIN to disable the pin and the reset procedure. - * This function must be called before invoking the `begin` method. - * @param pin The pin number to be monitored. The pin must - * be in the list of digital pins usable for interrupts. - * Please refer to the Arduino documentation for more details: - * https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ - */ - void setPin(int pin); + static ResetInput &getInstance() { + static ResetInput instance; + return instance; + } + + void begin() override { + if(_pin == DISABLE_PIN){ + return; + } + #ifdef ARDUINO_OPTA + pinMode(_pin, INPUT); + #else + pinMode(_pin, INPUT_PULLUP); + #endif + pinMode(LED_RECONFIGURE, OUTPUT); + digitalWrite(LED_RECONFIGURE, LED_OFF); + attachInterrupt(digitalPinToInterrupt(_pin),_pressedCallback, CHANGE); + } + + bool isEventFired() override { + if(_startPressed != 0){ + #if defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_SAMD_MKRWIFI1010) + LEDFeedbackClass::getInstance().stop(); + #endif + if(micros() - _startPressed > RESET_HOLD_TIME){ + digitalWrite(LED_RECONFIGURE, LED_OFF); + _expired = true; + } + } + + return _fireEvent; + } + private: - /** - * @brief Private constructor to enforce the singleton pattern. - */ - ResetInput(); - static inline ResetInputCallback _pressedCustomCallback; - static inline int _pin; + ResetInput() { + _pin = PIN_RECONFIGURE; + _expired = false; + _startPressed = 0; + _fireEvent = false; + } static inline volatile bool _expired; static inline volatile bool _fireEvent; static inline volatile uint32_t _startPressed; /** * @brief Internal callback function to handle pin press events. */ - static void _pressedCallback(); + static void _pressedCallback() { + #if defined(ARDUINO_NANO_RP2040_CONNECT) + if(digitalRead(_pin) == HIGH){ + #else + if(digitalRead(_pin) == LOW){ + #endif + #if !defined(ARDUINO_NANO_RP2040_CONNECT) && !defined(ARDUINO_SAMD_MKRWIFI1010) + LEDFeedbackClass::getInstance().stop(); + #endif + _startPressed = micros(); + digitalWrite(LED_RECONFIGURE, LED_ON); + } else { + digitalWrite(LED_RECONFIGURE, LED_OFF); + if(_startPressed != 0 && _expired){ + _fireEvent = true; + }else{ + LEDFeedbackClass::getInstance().restart(); + } + _startPressed = 0; + } + + if (_pressedCustomCallback) { + _pressedCustomCallback(); + } + } }; + diff --git a/src/utility/ResetInputBase.cpp b/src/utility/ResetInputBase.cpp new file mode 100644 index 0000000..735dfdc --- /dev/null +++ b/src/utility/ResetInputBase.cpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +#include "ANetworkConfigurator_Config.h" +#if NETWORK_CONFIGURATOR_COMPATIBLE + +#include "ResetInputBase.h" +#include "ResetInput.h" + + +#if defined(ARDUINO_PORTENTA_H7_M7) +#include "ResetInput_PortentaMachineControl.h" +#include +bool isPortentaMachineControlAttached() { + Wire.begin(); + Wire.beginTransmission(I2C_ADD_DETECT_MACHINE_CONTROL_1); + if (Wire.endTransmission() != 0) { + return false; + } + + Wire.beginTransmission(I2C_ADD_DETECT_MACHINE_CONTROL_2); + if (Wire.endTransmission() != 0) { + return false; + } + + Wire.end(); + return true; +} + +#endif + +ResetInputBase &ResetInputBase::getInstance() { + static ResetInputBase instance; + return instance; +} + +void ResetInputBase::begin() { + + ResetInputCallback pressedCustomCallback = _pressedCustomCallback; + int pin = _pin; + + #if defined(ARDUINO_PORTENTA_H7_M7) + if(isPortentaMachineControlAttached()) { + _instance = &ResetInput_PortentaMachineControl::getInstance(); + }else{ + _instance = &ResetInput::getInstance(); + } + #else + _instance = &ResetInput::getInstance(); + #endif + if(pin != -2) { + _instance->setPin(pin); + } + + if(pressedCustomCallback) { + _instance->setPinChangedCallback(pressedCustomCallback); + } + + _instance->begin(); +} + +bool ResetInputBase::isEventFired() { + if (_instance == nullptr) { + return false; + } + return _instance->isEventFired(); +} + +void ResetInputBase::setPinChangedCallback(ResetInputCallback callback) { + _pressedCustomCallback = callback; +} + +void ResetInputBase::setPin(int pin) { + if(pin < 0){ + _pin = DISABLE_PIN; + }else { + _pin = pin; + } +} + +ResetInputBase::ResetInputBase() { + _instance = nullptr; + _pressedCustomCallback = nullptr; + _pin = -2; +} + +#endif diff --git a/src/utility/ResetInputBase.h b/src/utility/ResetInputBase.h new file mode 100644 index 0000000..54b9293 --- /dev/null +++ b/src/utility/ResetInputBase.h @@ -0,0 +1,76 @@ +/* + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once +#include "Arduino.h" +#include + +#define DISABLE_PIN -1 + +/** + * @class ResetInputBase + * @brief A singleton class to handle input of the reset functionality with interrupt-based monitoring. + * + * This class provides methods to configure and monitor a reset input pin. It allows + * setting up a custom callback function to be executed when the pin status changes. + */ +class ResetInputBase{ +public: + /** + * @typedef ResetInputBase::ResetInputCallback + * @brief A type definition for the callback function to be executed on pin status change. + */ + typedef std::function ResetInputCallback; + /** + * @brief Get the singleton instance of the ResetInputBase class. + * @return A reference to the ResetInputBase instance. + */ + static ResetInputBase& getInstance(); + /** + * @brief Initialize the reset input by setting up the interrupt pin. + */ + virtual void begin(); + /** + * @brief Check if the reset event has been fired. + * @return True if the event is fired, otherwise false. + */ + virtual bool isEventFired(); + /** + * @brief Set a custom callback function to be called when the pin status changes. + * This function must be called before invoking the `begin` method. + * @param callback The custom callback function to be executed. + */ + void setPinChangedCallback(ResetInputCallback callback); + /** + * @brief Set the pin to be monitored for reset events. + * By default, the pin is set as INPUT_PULLUP. + * Use the value DISABLE_PIN to disable the pin and the reset procedure. + * This function must be called before invoking the `begin` method. + * @param pin The pin number to be monitored. The pin must + * be in the list of digital pins usable for interrupts. + * Please refer to the Arduino documentation for more details: + * https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ + * N.B.: For Portenta Machine Control, the pin must be one of the Digital Inputs 0-7. + * The parameter must be one of the range DIN_READ_CH_PIN_00-DIN_READ_CH_PIN_07. + * The defines are available in the Portenta Machine Control library and you must include + * Arduino_PortentaMachineControl.h for having access to them. + */ + void setPin(int pin); + + +protected: + static inline ResetInputCallback _pressedCustomCallback; + static inline int _pin; + /** + * @brief Private constructor to enforce the singleton pattern. + */ + ResetInputBase(); + +private: + ResetInputBase *_instance; +}; diff --git a/src/utility/ResetInput_PortentaMachineControl.h b/src/utility/ResetInput_PortentaMachineControl.h new file mode 100644 index 0000000..8b36201 --- /dev/null +++ b/src/utility/ResetInput_PortentaMachineControl.h @@ -0,0 +1,104 @@ +/* + Copyright (c) 2025 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "ANetworkConfigurator_Config.h" +#include +#include "ResetInputBase.h" +#include "LEDFeedback.h" + +#define PORTENTA_MACHINE_CONTROL_DI_INTERRUPT PB_4 +#define PIN_RECONFIGURE_MACHINE_CONTROL DIN_READ_CH_PIN_00 + +class ResetInput_PortentaMachineControl : public ResetInputBase { +public: + static ResetInput_PortentaMachineControl &getInstance() { + static ResetInput_PortentaMachineControl instance; + return instance; + } + + void begin() override { + if (_pin == DISABLE_PIN) { + return; + } + + pinMode(LED_RECONFIGURE, OUTPUT); + digitalWrite(LED_RECONFIGURE, LED_OFF); + Wire.begin(); + attachInterrupt(PORTENTA_MACHINE_CONTROL_DI_INTERRUPT, _inputCallback, FALLING); + MachineControl_DigitalInputs.begin(); + } + + bool isEventFired() override { + if(_interruptFlag) { + bool pinChanged = false; + _interruptFlag = false; + int pinStatus = MachineControl_DigitalInputs.read(_pin); + if(pinStatus == -1) { + return false; + } else { + pinChanged = (pinStatus != _pinStatus); + _pinStatus = pinStatus; + } + + if (!pinChanged) { + return false; + } + + if (pinStatus == 1) { + LEDFeedbackClass::getInstance().stop(); + digitalWrite(LED_RECONFIGURE, LED_ON); + _startPressedTs = _interruptEventTs; + + } else { + // Pin released + if(_startPressedTs != 0){ + digitalWrite(LED_RECONFIGURE, LED_OFF); + if(_interruptEventTs - _startPressedTs > RESET_HOLD_TIME) { + return true; + } + LEDFeedbackClass::getInstance().restart(); + _startPressedTs = 0; + } + } + } + + if(_pinStatus == 1) { + // Pin is pressed + if(_startPressedTs != 0 && micros() - _startPressedTs > RESET_HOLD_TIME) { + // Turn off the led after the hold time + digitalWrite(LED_RECONFIGURE, LED_OFF); + } + } + + return false; + } + + +private: + ResetInput_PortentaMachineControl() { + _pin = PIN_RECONFIGURE_MACHINE_CONTROL; + _interruptFlag = false; + _startPressedTs = 0; + _interruptEventTs = 0; + _pinStatus = -1; + } + int _pinStatus; + uint32_t _startPressedTs; + static inline volatile bool _interruptFlag; + static inline volatile uint32_t _interruptEventTs; + static void _inputCallback() { + + _interruptFlag = true; + _interruptEventTs = micros(); + if (_pressedCustomCallback) { + _pressedCustomCallback(); + } + } +};