mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-02 08:13:44 +00:00
rework buttons, add quintuple press for disabling leds
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Common: configure the 'buttons' gpio-keys node as a wakeup source.
|
||||
*
|
||||
* On nRF52840, sys_poweroff() enters System OFF (~1µA). Waking via the user
|
||||
* button requires GPIO SENSE bits to be set before poweroff. Zephyr's gpio-keys
|
||||
* driver adds GPIO_INT_WAKEUP to the interrupt flags when wakeup-source is set,
|
||||
* which causes the nRF52 GPIO driver to call nrf_gpio_cfg_sense_set(). Those
|
||||
* SENSE bits persist through System OFF and trigger a reset on button press.
|
||||
*
|
||||
* Include this in any nRF52 board DTS that defines a 'buttons' gpio-keys node.
|
||||
* Boards without buttons (e.g. ikoka_nano, rak4631) should NOT include this.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&buttons {
|
||||
wakeup-source;
|
||||
};
|
||||
@@ -157,6 +157,21 @@ If you write a fully custom DTS that includes neither, add it yourself:
|
||||
};
|
||||
|
||||
|
||||
**nRF52 boards with a user button: button wakeup from System OFF**
|
||||
|
||||
`sys_poweroff()` on nRF52840 enters System OFF (~1µA). To allow waking via
|
||||
button press (instead of only via USB/charger), GPIO SENSE bits must be set
|
||||
before poweroff. This is done via the `wakeup-source` property on the
|
||||
`gpio-keys` node, which the nRF52 GPIO driver handles automatically.
|
||||
|
||||
Boards that define a `buttons:` gpio-keys node must add at the END of their DTS:
|
||||
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
Boards WITHOUT a `buttons` label (ikoka_nano, rak4631) must NOT include it —
|
||||
referencing an undefined `&buttons` label is a hard build error.
|
||||
|
||||
|
||||
What Goes in board.conf
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -659,6 +659,8 @@
|
||||
* / {
|
||||
* buttons: buttons {
|
||||
* compatible = "gpio-keys";
|
||||
* /* nRF52 only: omit wakeup-source here; use the common include below instead.
|
||||
* * Other platforms: add wakeup-source; directly if the driver supports it. */
|
||||
* user_button: button_0 {
|
||||
* gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
* zephyr,code = <INPUT_KEY_0>;
|
||||
@@ -669,18 +671,29 @@
|
||||
* compatible = "zephyr,input-longpress";
|
||||
* input = <&buttons>;
|
||||
* input-codes = <INPUT_KEY_0>;
|
||||
* short-codes = <INPUT_KEY_A>;
|
||||
* long-codes = <INPUT_KEY_POWER>;
|
||||
* short-codes = <INPUT_KEY_A>; /* short press → multi-tap input */
|
||||
* long-codes = <INPUT_KEY_POWER>; /* long press (≥1s) → deep sleep */
|
||||
* long-delay-ms = <1000>;
|
||||
* };
|
||||
*
|
||||
* /* Multi-tap action mapping (standard ZephCore assignment):
|
||||
* * 1 tap (400ms wait) → KEY_1 = page next
|
||||
* * 2 taps (400ms wait) → KEY_B = flood advert
|
||||
* * 3 taps (400ms wait) → KEY_D = buzzer mute toggle
|
||||
* * 4 taps (400ms wait) → KEY_C = GPS on/off
|
||||
* * 5 taps (immediate) → KEY_E = LED heartbeat toggle */
|
||||
* user_btn_multitap {
|
||||
* compatible = "zephcore,input-multi-tap";
|
||||
* input-codes = <INPUT_KEY_A>;
|
||||
* tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
* tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
* tap-delay-ms = <400>;
|
||||
* };
|
||||
* };
|
||||
*
|
||||
* /* nRF52 boards: add this at the END of the DTS file so the button GPIO
|
||||
* * is configured for System OFF wakeup (press button to boot after shutdown).
|
||||
* * Do NOT add for boards without a 'buttons' label (ikoka_nano, rak4631). */
|
||||
* #include "../../common/nrf52_wakeup.dtsi"
|
||||
*/
|
||||
|
||||
/* --- GPS on UART (nRF52840 typically on &uart0) ---
|
||||
|
||||
@@ -203,3 +203,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* ---- Flash partitions (SoftDevice v6, app@0x26000) ---- */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -95,11 +95,12 @@
|
||||
* 1 tap → KEY_1 = (reserved / next page if display added)
|
||||
* 2 taps → KEY_B = flood advert
|
||||
* 3 taps → KEY_D = buzzer mute toggle
|
||||
* 4 taps → KEY_C = GPS on/off */
|
||||
* 4 taps → KEY_C = GPS on/off
|
||||
* 5 taps → KEY_E = LED heartbeat toggle */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
@@ -277,3 +278,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* ---- Flash partitions (SoftDevice v6, app@0x26000) ---- */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -76,14 +76,15 @@
|
||||
* 1 tap (400ms wait) → KEY_1 = page next (no-op without display)
|
||||
* 2 taps (400ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
* 4 taps (400ms wait) → KEY_C = GPS on/off
|
||||
* 5 taps (immediate) → KEY_E = LED heartbeat toggle */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-device,
|
||||
* not by &buttons, so we must not filter by device. */
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
@@ -279,3 +280,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* Arduino MeshCore compatible partition layout (SoftDevice v7) */
|
||||
#include "../../common/nrf52_partitions_sdv7.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -389,3 +389,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* ---- External QSPI /ext automount ---- */
|
||||
#include "../../common/qspi-ext.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -82,11 +82,12 @@
|
||||
* 1 tap → KEY_1 = page next
|
||||
* 2 taps → KEY_B = flood advert
|
||||
* 3 taps → KEY_D = buzzer mute toggle
|
||||
* 4 taps → KEY_C = GPS on/off */
|
||||
* 4 taps → KEY_C = GPS on/off
|
||||
* 5 taps → KEY_E = LED heartbeat toggle */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
@@ -255,3 +256,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* SoftDevice v6 partition layout (S140 v6 — Adafruit nRF52 bootloader) */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -81,11 +81,12 @@
|
||||
* 1 tap → KEY_1 = page next
|
||||
* 2 taps → KEY_B = flood advert
|
||||
* 3 taps → KEY_D = buzzer mute toggle
|
||||
* 4 taps → KEY_C = GPS on/off */
|
||||
* 4 taps → KEY_C = GPS on/off
|
||||
* 5 taps → KEY_E = LED heartbeat toggle */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
@@ -323,3 +324,4 @@ zephyr_udc0: &usbd {
|
||||
|
||||
/* External QSPI /ext automount */
|
||||
#include "../../common/qspi-ext.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -103,14 +103,15 @@
|
||||
* 1 tap (400ms wait) → KEY_1 = page next on OLED
|
||||
* 2 taps (400ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
* 4 taps (400ms wait) → KEY_C = GPS on/off
|
||||
* 5 taps (immediate) → KEY_E = LED heartbeat toggle */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-device,
|
||||
* not by &buttons, so we must not filter by device. */
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
@@ -340,3 +341,4 @@ zephyr_udc0: &usbd {
|
||||
};
|
||||
};
|
||||
};
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
|
||||
@@ -133,8 +133,8 @@ static int __maybe_unused multi_tap_init(const struct device *dev)
|
||||
"input-codes must have at least 1 entry"); \
|
||||
BUILD_ASSERT(DT_INST_PROP_LEN(inst, tap_codes) >= 1, \
|
||||
"tap-codes must have at least 1 entry"); \
|
||||
BUILD_ASSERT(DT_INST_PROP_LEN(inst, tap_codes) <= 4, \
|
||||
"tap-codes must have at most 4 entries"); \
|
||||
BUILD_ASSERT(DT_INST_PROP_LEN(inst, tap_codes) <= 5, \
|
||||
"tap-codes must have at most 5 entries"); \
|
||||
\
|
||||
INPUT_CALLBACK_DEFINE_NAMED( \
|
||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, input), \
|
||||
|
||||
@@ -76,6 +76,9 @@ LOG_MODULE_REGISTER(ui_task, CONFIG_ZEPHCORE_BOARD_LOG_LEVEL);
|
||||
#define MELODY_GPS_ON "gon:d=16,o=7,b=200:c,p,c,p,c,p,c,p,p,8e"
|
||||
#define MELODY_GPS_OFF "gof:d=16,o=7,b=200:c,p,c,p,c,p,c,p,p,8g5"
|
||||
|
||||
#define MELODY_LED_ON "lon:d=16,o=7,b=200:c,p,c,p,c,p,c,p,c,p,p,8e"
|
||||
#define MELODY_LED_OFF "lof:d=16,o=7,b=200:c,p,c,p,c,p,c,p,c,p,p,8g5"
|
||||
|
||||
/* ========== LED Heartbeat ========== */
|
||||
/* Match Arduino: 4s cycle, 20ms pulse (normal) or 200ms (unread messages).
|
||||
* Uses led0 or led1 alias — whichever exists in the board's DTS.
|
||||
@@ -475,6 +478,9 @@ static void action_leds_toggle(void)
|
||||
s->leds_disabled = new_disabled;
|
||||
ui_set_heartbeat_led(!new_disabled);
|
||||
mesh_set_leds_disabled(new_disabled);
|
||||
#ifdef CONFIG_ZEPHCORE_UI_BUZZER
|
||||
buzzer_play(new_disabled ? MELODY_LED_OFF : MELODY_LED_ON);
|
||||
#endif
|
||||
LOG_INF("LEDs %s (user toggle)", new_disabled ? "disabled" : "enabled");
|
||||
schedule_render();
|
||||
}
|
||||
@@ -698,10 +704,15 @@ static void ui_input_cb(struct input_event *evt, void *user_data)
|
||||
break;
|
||||
|
||||
case INPUT_KEY_C:
|
||||
/* Quadruple tap (immediate): toggle GPS */
|
||||
/* Quadruple tap (400ms delayed): toggle GPS */
|
||||
action_gps_toggle();
|
||||
break;
|
||||
|
||||
case INPUT_KEY_E:
|
||||
/* Quintuple tap (immediate): toggle LED heartbeat */
|
||||
action_leds_toggle();
|
||||
break;
|
||||
|
||||
/* ===== Longpress output ===== */
|
||||
case INPUT_KEY_POWER:
|
||||
case INPUT_KEY_F:
|
||||
|
||||
Reference in New Issue
Block a user