diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 31923543fd..f47f38111e 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -243,6 +243,8 @@ void setup() { } void loop() { + board.pollButton(); + the_mesh.loop(); sensors.loop(); #ifdef DISPLAY_CLASS diff --git a/examples/kiss_modem/main.cpp b/examples/kiss_modem/main.cpp index 7fbcaed127..e97f857f75 100644 --- a/examples/kiss_modem/main.cpp +++ b/examples/kiss_modem/main.cpp @@ -124,6 +124,8 @@ void setup() { } void loop() { + board.pollButton(); + modem->loop(); if (!modem->isActuallyTransmitting()) { diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 297337ab5c..0713ed86b6 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -23,11 +23,6 @@ static char command[160]; unsigned long lastActive = 0; // mark last active time unsigned long nextSleepinSecs = 120; // next sleep in seconds. The first sleep (if enabled) is after 2 minutes from boot -#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_) -static unsigned long userBtnDownAt = 0; -#define USER_BTN_HOLD_OFF_MILLIS 1500 -#endif - void setup() { Serial.begin(115200); delay(1000); @@ -134,20 +129,7 @@ void loop() { command[0] = 0; // reset command buffer } -#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_) - // Hold the user button to power off the SenseCAP Solar repeater. - int btnState = digitalRead(PIN_USER_BTN); - if (btnState == LOW) { - if (userBtnDownAt == 0) { - userBtnDownAt = millis(); - } else if ((unsigned long)(millis() - userBtnDownAt) >= USER_BTN_HOLD_OFF_MILLIS) { - Serial.println("Powering off..."); - board.powerOff(); // does not return - } - } else { - userBtnDownAt = 0; - } -#endif + board.pollButton(); the_mesh.loop(); sensors.loop(); diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index a3798b2175..e19d6b3096 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -109,6 +109,8 @@ void loop() { command[0] = 0; // reset command buffer } + board.pollButton(); + the_mesh.loop(); sensors.loop(); #ifdef DISPLAY_CLASS diff --git a/src/MeshCore.h b/src/MeshCore.h index b4c57faf32..d495ede8a6 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -56,6 +56,10 @@ class MainBoard { // Boards may override to stop a boot-indicator LED sequence or similar. // Default no-op: boards that don't care need not implement anything. virtual void onBootComplete() { /* no op */ } + // Called once per loop() iteration from example main loops. Boards with + // physical buttons may override to poll for user input (e.g., hold-to- + // power-off). Default no-op: boards without buttons need not implement. + virtual void pollButton() { /* no op */ } virtual void sleep(uint32_t secs) { /* no op */ } virtual uint32_t getGpio() { return 0; } virtual void setGpio(uint32_t values) {} diff --git a/variants/sensecap_solar/SenseCapSolarBoard.cpp b/variants/sensecap_solar/SenseCapSolarBoard.cpp index da7964c9e6..7729752701 100644 --- a/variants/sensecap_solar/SenseCapSolarBoard.cpp +++ b/variants/sensecap_solar/SenseCapSolarBoard.cpp @@ -35,10 +35,8 @@ void SenseCapSolarBoard::begin() { analogReference(AR_INTERNAL_3_0); delay(50); -#ifdef PIN_USER_BTN - pinMode(PIN_USER_BTN, INPUT_PULLUP); -#elif defined(PIN_BUTTON1) - pinMode(PIN_BUTTON1, INPUT_PULLUP); +#ifdef PIN_PWR_BTN + pinMode(PIN_PWR_BTN, INPUT_PULLUP); #endif #if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL) diff --git a/variants/sensecap_solar/SenseCapSolarBoard.h b/variants/sensecap_solar/SenseCapSolarBoard.h index 6799a5e921..0772ff43fa 100644 --- a/variants/sensecap_solar/SenseCapSolarBoard.h +++ b/variants/sensecap_solar/SenseCapSolarBoard.h @@ -10,10 +10,33 @@ class SenseCapSolarBoard : public NRF52BoardDCDC { void initiateShutdown(uint8_t reason) override; #endif +private: +#ifdef PIN_PWR_BTN + unsigned long _pwr_btn_down_at = 0; // PWR-button press timestamp (0 = not pressed) + static constexpr unsigned long PWR_BTN_HOLD_OFF_MILLIS = 1500; +#endif + public: SenseCapSolarBoard() : NRF52Board("SENSECAP_SOLAR_OTA") {} void begin(); +#ifdef PIN_PWR_BTN + // Hold the PWR button for >= 1.5s to power off. + void pollButton() override { + int btnState = digitalRead(PIN_PWR_BTN); + if (btnState == LOW) { + if (_pwr_btn_down_at == 0) { + _pwr_btn_down_at = millis(); + } else if ((unsigned long)(millis() - _pwr_btn_down_at) >= PWR_BTN_HOLD_OFF_MILLIS) { + Serial.println("Powering off..."); + powerOff(); // does not return + } + } else { + _pwr_btn_down_at = 0; + } + } +#endif + #if defined(P_LORA_TX_LED) void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on @@ -41,14 +64,10 @@ class SenseCapSolarBoard : public NRF52BoardDCDC { digitalWrite(LED_WHITE, LOW); digitalWrite(LED_BLUE, LOW); -#ifdef PIN_USER_BTN - while (digitalRead(PIN_USER_BTN) == LOW); - // Keep pull-up enabled in system-off so the wake line doesn't float low. - nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_USER_BTN]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); -#elif defined(PIN_BUTTON1) - while (digitalRead(PIN_BUTTON1) == LOW); +#ifdef PIN_PWR_BTN + while (digitalRead(PIN_PWR_BTN) == LOW); // Keep pull-up enabled in system-off so the wake line doesn't float low. - nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_BUTTON1]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); + nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_PWR_BTN]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); #endif #ifdef NRF52_POWER_MANAGEMENT diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini index effef38ccd..fb79d54ca9 100644 --- a/variants/sensecap_solar/platformio.ini +++ b/variants/sensecap_solar/platformio.ini @@ -18,7 +18,6 @@ build_flags = ${nrf52_base.build_flags} -D P_LORA_RESET=2 -D P_LORA_BUSY=3 -D P_LORA_NSS=4 - -D PIN_USER_BTN=PIN_BUTTON1 -D LORA_TX_POWER=22 -D SX126X_RXEN=5 -D SX126X_TXEN=RADIOLIB_NC diff --git a/variants/sensecap_solar/variant.h b/variants/sensecap_solar/variant.h index ef87c7ebd8..0ae39044b9 100644 --- a/variants/sensecap_solar/variant.h +++ b/variants/sensecap_solar/variant.h @@ -30,9 +30,11 @@ #define LED_STATE_ON (1) // State when LED is litted // Buttons -#define PIN_BUTTON1 (13) -#define PIN_BUTTON2 (20) -#define PIN_USER_BTN PIN_BUTTON1 +// Physical buttons are silkscreened PWR / RST / USR (left to right). +// RST is hardwired to the nRF52 reset line and is not exposed as a GPIO, +// so only PWR and USR are defined here. +#define PIN_PWR_BTN (13) // PWR (leftmost): wake source + hold-to-power-off +#define PIN_USER_BTN (20) // USR (rightmost): general-purpose, currently unused #define VBAT_ENABLE (19) // Output LOW to enable reading of the BAT voltage.