firmware/src/ButtonThread.h

200 lines
6.0 KiB
C
Raw Normal View History

#include "PowerFSM.h"
#include "RadioLibInterface.h"
2022-05-07 10:31:21 +00:00
#include "buzz.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "graphics/Screen.h"
#include "power.h"
#include <OneButton.h>
namespace concurrency
{
2023-01-19 03:13:31 +00:00
/**
* Watch a GPIO and if we get an IRQ, wake the main thread.
* Use to add wake on button press
*/
void wakeOnIrq(int irq, int mode)
{
attachInterrupt(
irq,
[] {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
},
FALLING);
}
2023-01-19 03:13:31 +00:00
class ButtonThread : public concurrency::OSThread
{
// Prepare for button presses
#ifdef BUTTON_PIN
2023-01-19 03:13:31 +00:00
OneButton userButton;
#endif
#ifdef BUTTON_PIN_ALT
2023-01-19 03:13:31 +00:00
OneButton userButtonAlt;
#endif
#ifdef BUTTON_PIN_TOUCH
2023-01-19 03:13:31 +00:00
OneButton userButtonTouch;
#endif
2023-01-19 03:13:31 +00:00
static bool shutdown_on_long_stop;
2023-01-19 03:13:31 +00:00
public:
static uint32_t longPressTime;
2023-01-19 03:13:31 +00:00
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
ButtonThread() : OSThread("Button")
{
#ifdef BUTTON_PIN
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
#ifdef INPUT_PULLUP_SENSE
2023-01-19 03:13:31 +00:00
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
2023-01-19 03:13:31 +00:00
#endif
userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300);
userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
#endif
#ifdef BUTTON_PIN_ALT
2023-01-19 03:13:31 +00:00
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
#ifdef INPUT_PULLUP_SENSE
2023-01-19 03:13:31 +00:00
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
#endif
2023-01-19 03:13:31 +00:00
userButtonAlt.attachClick(userButtonPressed);
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
#ifdef BUTTON_PIN_TOUCH
2023-01-19 03:13:31 +00:00
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
userButtonTouch.attachClick(touchPressed);
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
#endif
2023-01-19 03:13:31 +00:00
}
2023-01-19 03:13:31 +00:00
protected:
/// If the button is pressed we suppress CPU sleep until release
int32_t runOnce() override
{
canSleep = true; // Assume we should not keep the board awake
#ifdef BUTTON_PIN
2023-01-19 03:13:31 +00:00
userButton.tick();
canSleep &= userButton.isIdle();
#endif
#ifdef BUTTON_PIN_ALT
2023-01-19 03:13:31 +00:00
userButtonAlt.tick();
canSleep &= userButtonAlt.isIdle();
#endif
#ifdef BUTTON_PIN_TOUCH
2023-01-19 03:13:31 +00:00
userButtonTouch.tick();
canSleep &= userButtonTouch.isIdle();
#endif
2023-01-19 03:13:31 +00:00
// if (!canSleep) LOG_DEBUG("Supressing sleep!\n");
// else LOG_DEBUG("sleep ok\n");
2023-01-19 03:13:31 +00:00
return 5;
}
2023-01-19 03:13:31 +00:00
private:
static void touchPressed()
{
screen->forceDisplay();
LOG_DEBUG("touch press!\n");
}
2022-05-07 10:31:21 +00:00
2023-01-19 03:13:31 +00:00
static void userButtonPressed()
{
// LOG_DEBUG("press!\n");
#ifdef BUTTON_PIN
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) {
2023-01-19 03:13:31 +00:00
powerFSM.trigger(EVENT_PRESS);
}
2023-01-19 03:13:31 +00:00
#endif
}
static void userButtonPressedLong()
{
// LOG_DEBUG("Long press!\n");
2023-04-13 16:19:33 +00:00
// If user button is held down for 5 seconds, shutdown the device.
if ((millis() - longPressTime > 5000) && (longPressTime > 0)) {
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
2023-01-19 03:13:31 +00:00
// Do actual shutdown when button released, otherwise the button release
// may wake the board immediatedly.
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
screen->startShutdownScreen();
LOG_INFO("Shutdown from long press");
playBeep();
2022-07-28 07:37:16 +00:00
#ifdef PIN_LED1
2023-01-19 03:13:31 +00:00
ledOff(PIN_LED1);
2022-07-28 07:37:16 +00:00
#endif
#ifdef PIN_LED2
2023-01-19 03:13:31 +00:00
ledOff(PIN_LED2);
2022-07-28 07:37:16 +00:00
#endif
#ifdef PIN_LED3
2023-01-19 03:13:31 +00:00
ledOff(PIN_LED3);
#endif
2023-01-19 03:13:31 +00:00
shutdown_on_long_stop = true;
}
2023-01-19 03:13:31 +00:00
#endif
} else {
// LOG_DEBUG("Long press %u\n", (millis() - longPressTime));
}
2023-01-19 03:13:31 +00:00
}
2023-01-19 03:13:31 +00:00
static void userButtonDoublePressed()
{
#if defined(USE_EINK) && defined(PIN_EINK_EN)
2023-01-19 03:13:31 +00:00
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
#endif
2023-01-19 03:13:31 +00:00
screen->print("Sent ad-hoc ping\n");
service.refreshMyNodeInfo();
service.sendNetworkPing(NODENUM_BROADCAST, true);
}
2023-01-19 03:13:31 +00:00
static void userButtonMultiPressed()
{
#if defined(GPS_POWER_TOGGLE)
2023-01-19 03:13:31 +00:00
if (config.position.gps_enabled) {
LOG_DEBUG("Flag set to false for gps power\n");
} else {
LOG_DEBUG("Flag set to true to restore power\n");
}
2023-01-19 03:13:31 +00:00
config.position.gps_enabled = !(config.position.gps_enabled);
doGPSpowersave(config.position.gps_enabled);
#endif
}
2023-01-19 03:13:31 +00:00
static void userButtonPressedLongStart()
{
if (millis() > 30 * 1000) {
LOG_DEBUG("Long press start!\n");
longPressTime = millis();
}
2023-01-19 03:13:31 +00:00
}
2023-01-19 03:13:31 +00:00
static void userButtonPressedLongStop()
{
if (millis() > 30 * 1000) {
LOG_DEBUG("Long press stop!\n");
longPressTime = 0;
if (shutdown_on_long_stop) {
playShutdownMelody();
delay(3000);
power->shutdown();
}
}
2023-01-19 03:13:31 +00:00
}
};
2022-05-07 10:31:21 +00:00
} // namespace concurrency