mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 22:38:19 +00:00
heltec v3/v4 oled&button changes
This commit is contained in:
@@ -1,126 +1,134 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V3 — ZephCore overlay
|
||||
*
|
||||
* The upstream Zephyr DTS already defines SX1262, SSD1306 OLED, button,
|
||||
* LED, battery ADC, Vext/ADC control, I2C0, SPI2, BLE, and WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2 pins: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa control: DIO1=14, BUSY=13, RESET=12
|
||||
* Display I2C0: SDA=17, SCL=18 (SSD1306 @ 0x3C)
|
||||
* Battery ADC: GPIO1 (ADC1 ch0), enable GPIO37, divider 100K/390K
|
||||
* Vext: GPIO36 (active-LOW, powers OLED)
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
/* Keep console/shell on UART0 for stable host logging on V3 */
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
};
|
||||
|
||||
/* Add label to upstream buttons node (defined without one) */
|
||||
buttons: buttons {
|
||||
};
|
||||
|
||||
/* Battery ADC — ZephCore reads via zephyr,user { io-channels }
|
||||
* Upstream vbatt node uses voltage-divider compatible which ZephCore
|
||||
* doesn't use. Multiplier: 3300mV full-scale * 5.42x = 17886.
|
||||
* (5.42x is Arduino's empirical divider factor for V3/V4.) */
|
||||
zephyr,user {
|
||||
io-channels = <&adc1 0>;
|
||||
vbat-mv-multiplier = <17886>;
|
||||
};
|
||||
|
||||
/* Battery ADC enable — GPIO37 (gpio1 pin 5) must be driven to read.
|
||||
* Upstream has adc_ctrl power-domain-gpio; ZephCore expects a
|
||||
* regulator-fixed named vbat_enable. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* ---- Button input filter chain ----
|
||||
* Upstream button emits INPUT_KEY_0. Split into:
|
||||
* short press → KEY_A (consumed by multi-tap)
|
||||
* long press (1s) → KEY_POWER (deep sleep) */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_POWER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap decodes short presses:
|
||||
* 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 (immediate) → KEY_C = GPS on/off */
|
||||
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-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Enable native USB serial for console/CLI */
|
||||
&usb_serial {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Add RX boosted mode and DIO1 pull-down to LoRa radio.
|
||||
* Upstream omits rx-boosted and has no pull-down on DIO1. */
|
||||
&lora0 {
|
||||
dio1-gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
rx-boosted;
|
||||
};
|
||||
|
||||
/* Reduce CPU clock from 240 MHz to 160 MHz — saves power, HAL minimum */
|
||||
&cpu0 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
/* I2C sensors — auto-detected at runtime */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions — reclaim unused space from 8MB layout.
|
||||
* Delete lpcore slots, storage, scratch, and coredump partitions.
|
||||
* Repurpose 0x7A0000 - 0x800000 (384KB) for LittleFS.
|
||||
*/
|
||||
/delete-node/ &slot0_lpcore_partition;
|
||||
/delete-node/ &slot1_lpcore_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
/delete-node/ &scratch_partition;
|
||||
/delete-node/ &coredump_partition;
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* LittleFS 384KB for DataStore + file-based BLE settings */
|
||||
lfs_partition: partition@7a0000 {
|
||||
label = "lfs";
|
||||
reg = <0x7A0000 0x60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V3 — ZephCore overlay
|
||||
*
|
||||
* The upstream Zephyr DTS already defines SX1262, SSD1306 OLED, button,
|
||||
* LED, battery ADC, Vext/ADC control, I2C0, SPI2, BLE, and WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2 pins: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa control: DIO1=14, BUSY=13, RESET=12
|
||||
* Display I2C0: SDA=17, SCL=18 (SSD1306 @ 0x3C)
|
||||
* Battery ADC: GPIO1 (ADC1 ch0), enable GPIO37, divider 100K/390K
|
||||
* Vext: GPIO36 (active-LOW, powers OLED) — regulator + vin-supply in overlay
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
/* Keep console/shell on UART0 for stable host logging on V3 */
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
};
|
||||
|
||||
/* Add label to upstream buttons node (defined without one) */
|
||||
buttons: buttons {
|
||||
};
|
||||
|
||||
/* Battery ADC — ZephCore reads via zephyr,user { io-channels }
|
||||
* Upstream vbatt node uses voltage-divider compatible which ZephCore
|
||||
* doesn't use. Multiplier: 3300mV full-scale * 5.42x = 17886.
|
||||
* (5.42x is Arduino's empirical divider factor for V3/V4.) */
|
||||
zephyr,user {
|
||||
io-channels = <&adc1 0>;
|
||||
vbat-mv-multiplier = <17886>;
|
||||
};
|
||||
|
||||
/* Battery ADC enable — GPIO37 (gpio1 pin 5) must be driven to read.
|
||||
* Upstream has adc_ctrl power-domain-gpio; ZephCore expects a
|
||||
* regulator-fixed named vbat_enable. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* Vext — GPIO36, active-LOW enables rail (matches Arduino periph_power / MeshCore
|
||||
* PIN_VEXT_EN). Replaces upstream vext_ctrl power-domain so SSD1306 init works with
|
||||
* CONFIG_PM_DEVICE=n. */
|
||||
vext_enable: vext-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vext";
|
||||
enable-gpios = <&gpio1 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* Button chain — same mapping as RAK4631 / WisMesh Pocket (rak4631/board.overlay). */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_ENTER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
page_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_LEFT>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Enable native USB serial for console/CLI */
|
||||
&usb_serial {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Add RX boosted mode and DIO1 pull-down to LoRa radio.
|
||||
* Upstream omits rx-boosted and has no pull-down on DIO1. */
|
||||
&lora0 {
|
||||
dio1-gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
rx-boosted;
|
||||
};
|
||||
|
||||
/* Reduce CPU clock from 240 MHz to 160 MHz — saves power, HAL minimum */
|
||||
&cpu0 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
/* I2C sensors — auto-detected at runtime */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
|
||||
ssd1306_128x64: display-controller@3c {
|
||||
/delete-property/ power-domains;
|
||||
vin-supply = <&vext_enable>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions — reclaim unused space from 8MB layout.
|
||||
* Delete lpcore slots, storage, scratch, and coredump partitions.
|
||||
* Repurpose 0x7A0000 - 0x800000 (384KB) for LittleFS.
|
||||
*/
|
||||
/delete-node/ &slot0_lpcore_partition;
|
||||
/delete-node/ &slot1_lpcore_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
/delete-node/ &scratch_partition;
|
||||
/delete-node/ &coredump_partition;
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* LittleFS 384KB for DataStore + file-based BLE settings */
|
||||
lfs_partition: partition@7a0000 {
|
||||
label = "lfs";
|
||||
reg = <0x7A0000 0x60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
|
||||
/* After SSD1306 no longer references vext_ctrl, remove upstream power-domain node. */
|
||||
/delete-node/ &vext_ctrl;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Heltec WiFi LoRa 32 V4 — ZephCore overlay
|
||||
*
|
||||
* The DTS already defines: SX1262 (lora0), SSD1306 OLED, button, LED, PWM,
|
||||
* vext_ctrl, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* vext_enable, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
@@ -43,30 +43,20 @@
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5 */
|
||||
};
|
||||
|
||||
/* ---- Button input filter chain ----
|
||||
* Button emits INPUT_KEY_0. Split into:
|
||||
* short press → KEY_A (consumed by multi-tap)
|
||||
* long press (1 s) → KEY_POWER (deep sleep) */
|
||||
/* Button chain — same mapping as RAK4631 / WisMesh Pocket (rak4631/board.overlay). */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_POWER>;
|
||||
long-codes = <INPUT_KEY_ENTER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap decodes short presses:
|
||||
* 1 tap (400 ms wait) → KEY_1 = page next
|
||||
* 2 taps (400 ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400 ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
user_btn_multitap {
|
||||
page_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-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_LEFT>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -85,14 +85,15 @@
|
||||
full-ohms = <(100000 + 390000)>;
|
||||
};
|
||||
|
||||
/* Vext — powers OLED and external peripherals.
|
||||
* V4 DIFFERENCE: active-HIGH (GPIO36 HIGH = power on).
|
||||
* V3 was active-LOW on the same GPIO. */
|
||||
vext_ctrl: vext_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
/* Vext — powers OLED and external peripherals (active-HIGH on GPIO36).
|
||||
* regulator-fixed + SSD1306 vin-supply: powers rail at boot without relying on
|
||||
* power-domains (CONFIG_PM_DEVICE is disabled in prj.conf). */
|
||||
vext_enable: vext-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vext";
|
||||
enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* GPIO36 = gpio1 pin 4 */
|
||||
#power-domain-cells = <0>;
|
||||
label = "Vext Control";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* ADC enable — GPIO37 (gpio1 pin 5) must be driven HIGH to read battery.
|
||||
@@ -186,7 +187,7 @@
|
||||
inversion-on;
|
||||
prechargep = <0x22>;
|
||||
reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; /* RST_OLED = GPIO21 */
|
||||
power-domains = <&vext_ctrl>;
|
||||
vin-supply = <&vext_enable>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Heltec WiFi LoRa 32 V4.3 — ZephCore overlay
|
||||
*
|
||||
* The DTS already defines: SX1262 (lora0), SSD1306 OLED, button, LED, PWM,
|
||||
* vext_ctrl, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* vext_enable, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
@@ -43,30 +43,20 @@
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5 */
|
||||
};
|
||||
|
||||
/* ---- Button input filter chain ----
|
||||
* Button emits INPUT_KEY_0. Split into:
|
||||
* short press → KEY_A (consumed by multi-tap)
|
||||
* long press (1 s) → KEY_POWER (deep sleep) */
|
||||
/* Button chain — same mapping as RAK4631 / WisMesh Pocket (rak4631/board.overlay). */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_POWER>;
|
||||
long-codes = <INPUT_KEY_ENTER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap decodes short presses:
|
||||
* 1 tap (400 ms wait) → KEY_1 = page next
|
||||
* 2 taps (400 ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400 ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
user_btn_multitap {
|
||||
page_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-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_LEFT>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -84,12 +84,15 @@
|
||||
full-ohms = <(100000 + 390000)>;
|
||||
};
|
||||
|
||||
/* Vext — powers OLED and external peripherals (active-HIGH, same as V4.2) */
|
||||
vext_ctrl: vext_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
/* Vext — powers OLED and external peripherals (active-HIGH on GPIO36).
|
||||
* regulator-fixed + SSD1306 vin-supply: powers rail at boot without relying on
|
||||
* power-domains (CONFIG_PM_DEVICE is disabled in prj.conf). */
|
||||
vext_enable: vext-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vext";
|
||||
enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* GPIO36 = gpio1 pin 4 */
|
||||
#power-domain-cells = <0>;
|
||||
label = "Vext Control";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* ADC enable — GPIO37 (gpio1 pin 5) must be driven HIGH to read battery */
|
||||
@@ -182,7 +185,7 @@
|
||||
inversion-on;
|
||||
prechargep = <0x22>;
|
||||
reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; /* RST_OLED = GPIO21 */
|
||||
power-domains = <&vext_ctrl>;
|
||||
vin-supply = <&vext_enable>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
*
|
||||
* Input flow (after longpress + multi-tap filter chain):
|
||||
* KEY_1 → action_page_next() (1 tap, 400ms delayed)
|
||||
* KEY_B → action_flood_advert() (2 taps, 400ms delayed)
|
||||
* KEY_D → action_buzzer_toggle() (3 taps, 400ms delayed)
|
||||
* KEY_LEFT → action_page_prev() (2 taps — RAK4631 / Pocket / Heltec V3–V4.3)
|
||||
* KEY_B → action_flood_advert() (2 taps on extended multitap overlays)
|
||||
* KEY_D → action_buzzer_toggle() (3 taps)
|
||||
* KEY_C → action_gps_toggle() (4 taps, immediate)
|
||||
* KEY_G → GPS switch on/off (hardware toggle, ThinkNode M1)
|
||||
* KEY_POWER → action_deep_sleep() (long press ≥1s)
|
||||
* KEY_RIGHT → action_page_next() (joystick, Wio Tracker)
|
||||
* KEY_LEFT → action_page_prev() (joystick, Wio Tracker)
|
||||
* KEY_ENTER → action_page_enter() (joystick center, Wio Tracker)
|
||||
* KEY_POWER / KEY_F → action_deep_sleep() (long press — boards that emit these)
|
||||
* KEY_ENTER → action_page_enter() (long press — Pocket / Heltec; joystick center Wio)
|
||||
* KEY_RIGHT → action_page_next() (joystick, Wio Tracker)
|
||||
*
|
||||
* Notification flow:
|
||||
* LoRa RX → CompanionMesh → ui_notify(UI_EVENT_CONTACT_MSG)
|
||||
@@ -753,11 +753,9 @@ static void ui_input_cb(struct input_event *evt, void *user_data)
|
||||
|
||||
/* Map input key codes to UI actions.
|
||||
*
|
||||
* KEY_1: 1 tap (from multi-tap, 400ms delayed)
|
||||
* KEY_B: 2 taps (from multi-tap, 400ms delayed)
|
||||
* KEY_D: 3 taps (from multi-tap, 400ms delayed)
|
||||
* KEY_C: 4 taps (from multi-tap, immediate — max count)
|
||||
* KEY_POWER: long press (from longpress filter, ≥1s)
|
||||
* RAK4631 / WisMesh Pocket / Heltec V3–V4.3: 1 tap KEY_1, 2 taps KEY_LEFT;
|
||||
* long press KEY_ENTER (page enter). Other boards: up to 4–5 tap codes
|
||||
* (KEY_B/D/C/E) and KEY_POWER or KEY_F long → deep sleep.
|
||||
* KEY_RIGHT/LEFT/ENTER/UP/DOWN: joystick (Wio Tracker)
|
||||
*
|
||||
* NOTE: KEY_A (raw short-press from longpress filter) is NOT handled
|
||||
|
||||
Reference in New Issue
Block a user