mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 18:08:47 +00:00
add lilygo t-impulse plus
This commit is contained in:
@@ -265,7 +265,7 @@ set(ZEPHCORE_COMMON_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/zephcore_com
|
||||
# Detect platform from board name and add platform-specific common config
|
||||
# For boards with qualifiers like "wio_tracker_l1/nrf52840", check both the full BOARD
|
||||
# string and the BOARD_QUALIFIERS which contains just the qualifier (e.g., "nrf52840")
|
||||
if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "rak3401_1watt" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6" OR BOARD MATCHES "promicro_lr2021" OR BOARD MATCHES "promicro_sx1262" OR BOARD MATCHES "sensecap_solar" OR BOARD MATCHES "xiao_nrf52840" OR BOARD MATCHES "lilygo_techo" OR BOARD MATCHES "heltec_t114" OR BOARD MATCHES "heltec_t096" OR BOARD MATCHES "gat562")
|
||||
if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "rak3401_1watt" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6" OR BOARD MATCHES "promicro_lr2021" OR BOARD MATCHES "promicro_sx1262" OR BOARD MATCHES "sensecap_solar" OR BOARD MATCHES "xiao_nrf52840" OR BOARD MATCHES "lilygo_techo" OR BOARD MATCHES "lilygo_timpulse_plus" OR BOARD MATCHES "heltec_t114" OR BOARD MATCHES "heltec_t096" OR BOARD MATCHES "gat562")
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*nrf52.*")
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
|
||||
@@ -23,6 +23,7 @@ Supported Boards
|
||||
| Ikoka Nano 30dBm | `west build -b ikoka_nano_30dbm zephcore` | UF2 drag-drop |
|
||||
| GAT562 30S Mesh Kit | `west build -b gat562_30s zephcore` | UF2 drag-drop or `west flash` |
|
||||
| LilyGo T-Echo | `west build -b lilygo_techo zephcore` | UF2 drag-drop or `west flash` |
|
||||
| LilyGo T-Impulse Plus | `west build -b lilygo_timpulse_plus zephcore` | UF2 drag-drop or `west flash` |
|
||||
| Heltec T114 | `west build -b heltec_t114 zephcore` | UF2 drag-drop or `west flash` |
|
||||
| Heltec Mesh Node T096 | `west build -b heltec_t096 zephcore` | UF2 drag-drop or `west flash` |
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# LilyGo T-Impulse Plus board configuration
|
||||
# Copyright (c) 2026 ZephCore
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_LILYGO_TIMPULSE_PLUS
|
||||
select SOC_NRF52840_QIAA
|
||||
|
||||
# The RT9080 LDO (P0.14) gates the whole 3V3 peripheral rail — SX1262, the
|
||||
# SSD1315 OLED, the GPS and the QSPI flash all sit behind it. The fixed
|
||||
# regulator that drives it (pwr_enable) must come up before those devices
|
||||
# initialise. QSPI NOR init priority is 41, so pin the regulator ahead of it.
|
||||
if REGULATOR_FIXED
|
||||
config REGULATOR_FIXED_INIT_PRIORITY
|
||||
default 30
|
||||
endif
|
||||
@@ -0,0 +1,92 @@
|
||||
# LilyGo T-Impulse Plus
|
||||
|
||||
A LoRa wristband/tracker built on the **nRF52840 + SX1262**. ZephCore is the
|
||||
first mesh firmware ported to it — there is no upstream Meshtastic or MeshCore
|
||||
variant. The port is derived from LilyGo's official
|
||||
[T-Impulse-Plus repo](https://github.com/Xinyuan-LilyGO/T-Impulse-Plus)
|
||||
(`pin_config.h`, `variant.h`, RadioLib examples and the shipped datasheets).
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# Companion (BLE — default role, recommended for the wristband form factor)
|
||||
west build -b lilygo_timpulse_plus zephcore --pristine
|
||||
|
||||
# Repeater (USB-CDC CLI, no BLE)
|
||||
west build -b lilygo_timpulse_plus zephcore --pristine -- \
|
||||
-DEXTRA_CONF_FILE="boards/common/repeater.conf"
|
||||
|
||||
# Companion + debug logging
|
||||
west build -b lilygo_timpulse_plus zephcore --pristine -- \
|
||||
-DEXTRA_CONF_FILE="boards/common/debug.conf"
|
||||
```
|
||||
|
||||
Flash: drag `build/zephyr/zephyr.uf2` onto the UF2 drive (double-tap the BOOT
|
||||
button to enter the Adafruit bootloader), or `west flash` with a J-Link.
|
||||
Bootloader is Adafruit UF2 / SoftDevice **s140 v6.1.1**, app @ `0x26000`
|
||||
(`SD_FWID 0x00B6`) — the stock bootloader is reused, no re-flash needed.
|
||||
|
||||
## Hardware
|
||||
|
||||
| Function | Part | Bus / notes |
|
||||
|-----------------|--------------------|-----------------------------------------------|
|
||||
| MCU | nRF52840 | BLE5, native USB, 1 MB flash / 256 KB RAM |
|
||||
| LoRa | SX1262 (AcSip S62F)| 22 dBm, embedded 32 MHz TCXO on DIO3 |
|
||||
| Display | SSD1315 128x64 OLED| I2C0 @ 0x3C (SSD1306-compatible, no reset) |
|
||||
| GNSS | u-blox MIA-M10Q | UART0 @ 38400, enable P1.10 |
|
||||
| Ext flash | ZD25WQ32C 32 Mbit | QSPI -> `/ext` LittleFS (contacts/channels) |
|
||||
| IMU | ICM-20948 | 2nd I2C bus @ 0x69 — present, not used |
|
||||
| Charger | SGM41562 | 2nd I2C bus @ 0x03 — present, not used |
|
||||
| Battery | ADC AIN3 (P0.05) | divider enable P0.25 (HIGH to read) |
|
||||
| Input | TTP223 touch | P1.04, active-HIGH |
|
||||
| Haptic | vibration motor | P0.22 (PWM0) — exposed as the buzzer output |
|
||||
| Peripheral rail | RT9080 LDO | enable P0.14 (gates LoRa/OLED/GPS/QSPI) |
|
||||
|
||||
## Pin map (from LilyGo `pin_config.h`)
|
||||
|
||||
| Signal | nRF52840 | Signal | nRF52840 |
|
||||
|-------------------|----------|---------------------|----------|
|
||||
| LoRa SCK | P0.03 | LoRa CS | P1.14 |
|
||||
| LoRa MOSI | P0.28 | LoRa RST | P0.02 |
|
||||
| LoRa MISO | P0.30 | LoRa BUSY | P0.31 |
|
||||
| LoRa DIO1 | P0.29 | RF TX enable (VC1) | P1.13 |
|
||||
| RF RX enable (VC2)| P1.07 | OLED SDA / SCL | P0.20 / P0.15 |
|
||||
| GPS MCU-TX / RX | P1.11 / P1.12 | GPS enable | P1.10 |
|
||||
| QSPI SCK / CS | P0.04 / P0.12 | QSPI IO0/1/2/3 | P0.06 / P1.09 / P0.08 / P0.26 |
|
||||
| Battery ADC / en | P0.05 / P0.25 | RT9080 rail en | P0.14 |
|
||||
| Touch button | P1.04 | Haptic motor | P0.22 |
|
||||
| LED (blue) | P0.17 | BOOT (DFU only) | P0.24 |
|
||||
|
||||
### Notes worth knowing
|
||||
- **RF switch is GPIO, not DIO2.** The S62F uses an external DPDT antenna
|
||||
switch on VC1/VC2. Wired via the patched native sx126x driver's
|
||||
`tx-enable-gpios` (VC1) / `rx-enable-gpios` (VC2). DIO2 (P1.15) is unused.
|
||||
- **GPS RX/TX are swapped relative to the net names.** LilyGo's `GPS_UART_RX`/
|
||||
`GPS_UART_TX` are labelled from the GPS module's side; the MCU receive pin is
|
||||
`GPS_UART_TX` (P1.12) and the MCU transmit pin is `GPS_UART_RX` (P1.11).
|
||||
- **Single-button UI** (like T-Echo): short tap = next page, double tap =
|
||||
previous page, long press (>=1 s) = ENTER. Confirmation needs two ENTERs, so
|
||||
`UI_CONFIRM_WINDOW_MS` is widened to 3 s.
|
||||
- **The ICM-20948 IMU and SGM41562 charger** sit on a second I2C bus
|
||||
(SDA P1.08 / SCL P0.11) that ZephCore does not use — that bus is left
|
||||
disabled. Battery state comes from the ADC, not the charger IC.
|
||||
|
||||
## To verify on real hardware
|
||||
|
||||
These were derived from the vendor sources and build clean, but a physical
|
||||
unit should confirm:
|
||||
|
||||
1. **TCXO voltage** — set to 1.8 V. LilyGo's RadioLib example validated the
|
||||
1.6 V default; drop `dio3-tcxo-voltage` to `SX126X_DIO3_TCXO_1V6` if the
|
||||
radio fails to start.
|
||||
2. **Battery divider ratio** — `vbat-mv-multiplier` assumes 2:1 (7236). Adjust
|
||||
if the reported voltage is off.
|
||||
3. **OLED orientation** — standard 0.96" landscape config; flip
|
||||
`segment-remap`/`com-invdir` in the overlay if the panel is mounted rotated.
|
||||
4. **GPS baud** — 38400 (from the vendor example); adjust `current-speed` if
|
||||
the M10 was left at another rate.
|
||||
|
||||
The QSPI flash needs no verification: the ZD25WQ32C JEDEC id (`ba 60 16`) and
|
||||
deep-power-down timings are datasheet-confirmed, and `/ext` reuses the same
|
||||
`nordic,qspi-nor` + LittleFS automount path as the older MX25R boards — a blank
|
||||
chip auto-formats on first mount, no formatter step required.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2026 ZephCore
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
|
||||
set(OPENOCD_NRF5_SUBFAMILY "nrf52")
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake)
|
||||
@@ -0,0 +1,37 @@
|
||||
# LilyGo T-Impulse Plus (nRF52840 + SX1262 + SSD1315 OLED + u-blox M10 GPS)
|
||||
# Board-specific configuration
|
||||
#
|
||||
# Hardware:
|
||||
# - nRF52840 SoC, SX1262 LoRa (22 dBm, embedded 32 MHz TCXO via DIO3)
|
||||
# - GPIO antenna switch: VC1=TX (P1.13), VC2=RX (P1.07)
|
||||
# - SSD1315 128x64 OLED @ I2C 0x3C (SSD1306-compatible, no reset pin)
|
||||
# - u-blox MIA-M10Q GPS on UART0 @ 38400, power enable P1.10
|
||||
# - ZD25WQ32C 32Mbit (4MB) QSPI flash -> /ext
|
||||
# - Battery ADC on AIN3 (P0.05), divider enable P0.25 (drive HIGH to read)
|
||||
# - Single TTP223 touch button (P1.04, active-HIGH)
|
||||
# - Haptic vibration motor (P0.22) exposed as the buzzer output
|
||||
# - RT9080 LDO enable P0.14 gates the whole 3V3 peripheral rail
|
||||
#
|
||||
# Most features are auto-detected from devicetree:
|
||||
# - PWM + buzzer (buzzer nodelabel / haptic motor)
|
||||
# - SSD1315 OLED (zephyr,display chosen) -> also UI_DISPLAY below
|
||||
# - LoRa RX duty cycle (companion + SX1262)
|
||||
# - battery ADC, GPS, LED, touch button
|
||||
|
||||
# Board identification
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="LilyGo T-Impulse Plus"
|
||||
|
||||
# Device Information Service model name
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="LilyGo T-Impulse Plus"
|
||||
|
||||
# SoftDevice firmware ID — Adafruit bootloader ships s140 v6.1.1 (app @ 0x26000,
|
||||
# same as T-Echo). Matches the LilyGo PlatformIO board JSON (sd_fwid 0x00B6).
|
||||
CONFIG_ZEPHCORE_SD_FWID=0x00B6
|
||||
|
||||
# Compile in the UI display stack; the OLED panel is optional at runtime.
|
||||
CONFIG_ZEPHCORE_UI_DISPLAY=y
|
||||
|
||||
# Single-button board: ENTER is a 1 s long-press, so two ENTERs to confirm
|
||||
# span >2 s. Widen the double-press confirmation window accordingly (matches
|
||||
# the T-Echo single-button mapping).
|
||||
CONFIG_ZEPHCORE_UI_CONFIRM_WINDOW_MS=3000
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* LilyGo T-Impulse Plus — DTS is self-contained.
|
||||
* This overlay is intentionally empty; all nodes live in
|
||||
* lilygo_timpulse_plus.dts. User-level tweaks (e.g. OLED orientation) go here.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2026 ZephCore
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board:
|
||||
name: lilygo_timpulse_plus
|
||||
full_name: LilyGo T-Impulse Plus (nRF52840 + SX1262 + SSD1315 OLED + M10 GPS)
|
||||
vendor: lilygo
|
||||
socs:
|
||||
- name: nrf52840
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* LilyGo T-Impulse Plus pin control definitions
|
||||
* Copyright (c) 2026 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Pin mappings (from LilyGo official pin_config.h, verified 2026-07-04):
|
||||
*
|
||||
* SPI2 (LoRa SX1262): SCK=P0.03, MOSI=P0.28, MISO=P0.30, CS=P1.14
|
||||
* I2C0 (SSD1315 OLED): SDA=P0.20, SCL=P0.15
|
||||
* UART0 (M10 GPS 38400):TX=P1.11 (->GPS RX), RX=P1.12 (<-GPS TX)
|
||||
* PWM0 (haptic motor): P0.22
|
||||
* QSPI (ZD25WQ32C 4MB): SCK=P0.04, CS=P0.12, IO0=P0.06, IO1=P1.09,
|
||||
* IO2=P0.08, IO3=P0.26
|
||||
*
|
||||
* NOTE on the GPS RX/TX: the LilyGo net names GPS_UART_RX/TX are labelled
|
||||
* from the *GPS module's* pin side. The Arduino example calls
|
||||
* Serial2.setPins(GPS_UART_TX, GPS_UART_RX) and Adafruit's
|
||||
* Uart::setPins(pin_rx, pin_tx) takes RX first — so the MCU receive pin is
|
||||
* GPS_UART_TX (P1.12) and the MCU transmit pin is GPS_UART_RX (P1.11).
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
/* UART0 for u-blox MIA-M10Q GPS at 38400 baud */
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 1, 11)>; /* P1.11 -> GPS RX */
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(UART_RX, 1, 12)>; /* P1.12 <- GPS TX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 1, 11)>,
|
||||
<NRF_PSEL(UART_RX, 1, 12)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* I2C0 for SSD1315 OLED (0x3C) */
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 20)>, /* P0.20 */
|
||||
<NRF_PSEL(TWIM_SCL, 0, 15)>; /* P0.15 */
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_sleep: i2c0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 20)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 15)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* SPI2 for LoRa SX1262 (dedicated bus, matches Arduino NRF_SPIM3) */
|
||||
spi2_default: spi2_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 3)>, /* P0.03 */
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 28)>, /* P0.28 */
|
||||
<NRF_PSEL(SPIM_MISO, 0, 30)>; /* P0.30 */
|
||||
};
|
||||
};
|
||||
|
||||
spi2_sleep: spi2_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 3)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 28)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 30)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* PWM0 for the haptic vibration motor on P0.22 */
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 22)>;
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_sleep: pwm0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 22)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* QSPI for ZD25WQ32C 32Mbit (4MB) external flash */
|
||||
qspi_default: qspi_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(QSPI_SCK, 0, 4)>,
|
||||
<NRF_PSEL(QSPI_IO0, 0, 6)>,
|
||||
<NRF_PSEL(QSPI_IO1, 1, 9)>,
|
||||
<NRF_PSEL(QSPI_IO2, 0, 8)>,
|
||||
<NRF_PSEL(QSPI_IO3, 0, 26)>,
|
||||
<NRF_PSEL(QSPI_CSN, 0, 12)>;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_sleep: qspi_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(QSPI_SCK, 0, 4)>,
|
||||
<NRF_PSEL(QSPI_IO0, 0, 6)>,
|
||||
<NRF_PSEL(QSPI_IO1, 1, 9)>,
|
||||
<NRF_PSEL(QSPI_IO2, 0, 8)>,
|
||||
<NRF_PSEL(QSPI_IO3, 0, 26)>;
|
||||
low-power-enable;
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(QSPI_CSN, 0, 12)>;
|
||||
low-power-enable;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* LilyGo T-Impulse Plus — nRF52840 + SX1262 + SSD1315 OLED + u-blox M10 GPS
|
||||
* Copyright (c) 2026 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* A LoRa wristband/tracker. Hardware (from LilyGo's official pin_config.h,
|
||||
* variant.h and the datasheets shipped in the T-Impulse-Plus repo):
|
||||
*
|
||||
* - nRF52840 SoC with BLE 5, native USB, Adafruit UF2 bootloader
|
||||
* (SoftDevice s140 v6.1.1, app @ 0x26000 — same layout as T-Echo)
|
||||
* - SX1262 LoRa (AcSip S62F module): 22 dBm, embedded 32 MHz TCXO on DIO3,
|
||||
* GPIO antenna switch (VC1=TX P1.13, VC2=RX P1.07 — NOT DIO2)
|
||||
* - SSD1315 128x64 mono OLED on I2C0 @ 0x3C (SSD1306-compatible, no reset pin)
|
||||
* - u-blox MIA-M10Q GPS on UART0 @ 38400 baud, power enable P1.10
|
||||
* - ZD25WQ32C 32Mbit (4MB) QSPI flash -> /ext LittleFS
|
||||
* - ICM-20948 IMU (0x69) + SGM41562 charger (0x03) on a second I2C bus —
|
||||
* present but NOT used by ZephCore, so that bus is left disabled
|
||||
* - Battery ADC on AIN3 (P0.05), divider gated by P0.25 (drive HIGH to read)
|
||||
* - TTP223 capacitive touch button (P1.04, active-HIGH)
|
||||
* - Haptic vibration motor (P0.22) exposed as the buzzer/notification output
|
||||
* - Single blue LED (P0.17, active-LOW, per variant.h)
|
||||
*
|
||||
* Power rail:
|
||||
* - RT9080 LDO enable P0.14 (HIGH) powers the whole 3V3 peripheral rail
|
||||
* (SX1262, OLED, GPS, QSPI). Brought up as a boot-on fixed regulator so it
|
||||
* is live before those devices initialise.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
#include "lilygo_timpulse_plus-pinctrl.dtsi"
|
||||
#include <zephyr/dt-bindings/lora/sx126x.h>
|
||||
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
|
||||
/ {
|
||||
model = "LilyGo T-Impulse Plus";
|
||||
compatible = "lilygo,timpulse-plus";
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
zephyr,shell-uart = &cdc_acm_uart;
|
||||
zephyr,display = &oled;
|
||||
};
|
||||
|
||||
aliases {
|
||||
lora0 = &lora;
|
||||
/* Only one LED on this board — use it for both status and LoRa TX. */
|
||||
led0 = &led_blue;
|
||||
lora-tx-led = &led_blue;
|
||||
sw0 = &touch_button;
|
||||
watchdog0 = &wdt0;
|
||||
buzzer = &buzzer;
|
||||
gps-enable = &gps_enable_pin;
|
||||
};
|
||||
|
||||
/* ---- LED ----
|
||||
* Single blue LED on P0.17, active-LOW (variant.h: LED_STATE_ON = 0).
|
||||
* The wristband is primarily an OLED + haptic device; if P0.17 is
|
||||
* unpopulated on a given unit, driving it is simply a no-op. */
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_blue: led_0 {
|
||||
gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
|
||||
label = "Blue LED";
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- Touch button (TTP223, P1.04) ----
|
||||
*
|
||||
* The only user input on the wristband. The TTP223 presents an
|
||||
* active-HIGH momentary output (external pull-down, Arduino uses
|
||||
* INPUT_PULLDOWN), so no internal pull is configured.
|
||||
*
|
||||
* Single-button UI (same scheme as T-Echo / RAK4631):
|
||||
* short press (release < 1s) -> KEY_A -> multi-tap filter:
|
||||
* 1 tap -> KEY_1 = next page
|
||||
* 2 taps -> KEY_LEFT = previous page
|
||||
* long press (>= 1s) -> KEY_ENTER = activate / confirm
|
||||
*
|
||||
* (The recessed BOOT button on P0.24 is left as the DFU/reset button and
|
||||
* is intentionally not wired as a runtime input.)
|
||||
*/
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
touch_button: button_0 {
|
||||
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
label = "Touch Button";
|
||||
};
|
||||
};
|
||||
|
||||
/* short-press -> KEY_A (multi-tap), long-press (>=1s) -> KEY_ENTER */
|
||||
touch_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>;
|
||||
};
|
||||
|
||||
/* ---- Power control ----
|
||||
* RT9080 LDO enable (P0.14). A single fixed regulator gating the entire
|
||||
* 3V3 peripheral rail: SX1262, SSD1315 OLED, GPS and QSPI flash. boot-on
|
||||
* so the regulator framework raises it before those drivers init
|
||||
* (REGULATOR_FIXED_INIT_PRIORITY pinned to 30 in Kconfig, ahead of the
|
||||
* QSPI NOR init at 41). */
|
||||
pwr_enable: pwr-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "pwr-enable";
|
||||
enable-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
|
||||
regulator-boot-on;
|
||||
startup-delay-us = <10000>;
|
||||
};
|
||||
|
||||
/* Battery-measurement enable (P0.25, active-HIGH).
|
||||
* ZephyrBoard::getBattMilliVolts() calls regulator_enable/disable around
|
||||
* the ADC read so the divider only draws current during a measurement. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* ---- GPS power control ----
|
||||
* GPS_EN (P1.10). gnss-nmea-generic has no on-off-gpios property, so
|
||||
* ZephyrGPSManager drives this pin directly via the gps-enable alias to
|
||||
* power the M10 up/down for duty-cycled fixes. */
|
||||
gps_en: gps-enable {
|
||||
compatible = "gpio-leds";
|
||||
gps_enable_pin: gps_enable {
|
||||
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
|
||||
label = "GPS Enable";
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- Haptic motor as buzzer ----
|
||||
* The vibration motor (P0.22) stands in for a piezo buzzer: message and
|
||||
* key-feedback "beeps" become haptic pulses, which is what a wearable
|
||||
* wants. Driven from PWM0. */
|
||||
pwmbuzzer {
|
||||
compatible = "pwm-leds";
|
||||
buzzer: buzzer {
|
||||
pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- Battery ADC ----
|
||||
* AIN3 = P0.05. Divider ratio not published — 7236 assumes a 2:1 divider
|
||||
* (0.6V ref x 1/6 gain x 2.0 x 1000, +0.5% SAADC gain error). VERIFY
|
||||
* against the board and adjust vbat-mv-multiplier if the reported voltage
|
||||
* is off. */
|
||||
zephyr,user {
|
||||
io-channels = <&adc 3>;
|
||||
vbat-mv-multiplier = <7236>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- SoC configuration ---- */
|
||||
|
||||
®0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
®1 {
|
||||
regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Battery voltage on P0.05 (AIN3) */
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
zephyr,gain = "ADC_GAIN_1_6";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
|
||||
zephyr,input-positive = <NRF_SAADC_AIN3>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* ---- PWM0 for the haptic motor ---- */
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&pwm0_default>;
|
||||
pinctrl-1 = <&pwm0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
/* ---- GPS on UART0 (u-blox MIA-M10Q, 38400 baud) ----
|
||||
* The M10 streams standard NMEA at power-on, so we use gnss-nmea-generic
|
||||
* (passive listener) rather than a u-blox UBX driver — no config commands,
|
||||
* no blocking init. GPS power is gated by the gps-enable alias (P1.10);
|
||||
* deferred-init lets ZephyrGPSManager raise power before the driver probes. */
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
status = "okay";
|
||||
current-speed = <38400>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
gnss: gnss {
|
||||
compatible = "gnss-nmea-generic";
|
||||
zephyr,deferred-init;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- I2C0: SSD1315 OLED ----
|
||||
* SSD1315 is SSD1306-compatible; the solomon,ssd1306 driver drives it. No
|
||||
* hardware reset line on this board (SCREEN_RST = -1). Standard 0.96" 128x64
|
||||
* orientation — if the panel is mounted rotated, flip segment-remap/com-invdir. */
|
||||
&i2c0 {
|
||||
compatible = "nordic,nrf-twim";
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-1 = <&i2c0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
oled: ssd1306@3c {
|
||||
compatible = "solomon,ssd1306";
|
||||
reg = <0x3c>;
|
||||
width = <128>;
|
||||
height = <64>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <63>;
|
||||
segment-remap;
|
||||
com-invdir;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- SPI2 for LoRa SX1262 ---- */
|
||||
&spi2 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spi2_default>;
|
||||
pinctrl-1 = <&spi2_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
cs-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; /* P1.14 LORA_CS */
|
||||
|
||||
lora: lora@0 {
|
||||
compatible = "semtech,sx1262";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
/* LoRa control pins */
|
||||
reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; /* P0.02 */
|
||||
busy-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; /* P0.31 */
|
||||
dio1-gpios = <&gpio0 29 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* P0.29 */
|
||||
|
||||
/* GPIO antenna switch (not DIO2). The patched native sx126x driver
|
||||
* drives tx-enable on TX and rx-enable on RX, both low in standby —
|
||||
* matching the RadioLib setRfSwitchPins(rxEn=VC2, txEn=VC1) call in
|
||||
* LilyGo's example. */
|
||||
tx-enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; /* VC1 = P1.13 (TX) */
|
||||
rx-enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; /* VC2 = P1.07 (RX) */
|
||||
|
||||
/* Embedded 32 MHz TCXO on the S62F module, fed via DIO3.
|
||||
* (AcSip S62F datasheet: "Embedded TCXO of 32MHz". Without DIO3
|
||||
* control the module has no clock and stays permanently BUSY.)
|
||||
* 1.8V mirrors the other LilyGo/ZephCore nRF SX1262 boards; the
|
||||
* LilyGo RadioLib example validated the 1.6V default, so drop to
|
||||
* SX126X_DIO3_TCXO_1V6 if the radio fails to start. */
|
||||
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
||||
tcxo-power-startup-delay-ms = <10>;
|
||||
|
||||
/* RX boosted mode for better sensitivity (matches Arduino default). */
|
||||
rx-boosted;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- QSPI Flash — ZD25WQ32C 32Mbit (4MB) ----
|
||||
* Same nordic,qspi-nor driver + LittleFS /ext automount as the MX25R parts on
|
||||
* T-Echo/ThinkNode — no new driver and no formatter: a blank chip auto-formats
|
||||
* on first mount (littlefs mount-fail -> format -> mount). Configured
|
||||
* single-line (fastread/pp) for reliable bring-up; quad can be enabled later.
|
||||
*
|
||||
* All values below are datasheet-confirmed (Zetta ZD25WQ32C, 2022):
|
||||
* - JEDEC RDID (9Fh) = BA 60 16 (MID 0xBA Zetta, type 0x60, capacity 0x16).
|
||||
* The nordic driver hard-fails init (-ENODEV) on an ID mismatch, so this
|
||||
* must be exact for /ext to mount; identity/prefs stay on internal /lfs.
|
||||
* - Deep power-down (B9h) supported: tDP 3us, tRES1 8us — the 10us/35us
|
||||
* waits below are conservative and safe. */
|
||||
&qspi {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&qspi_default>;
|
||||
pinctrl-1 = <&qspi_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
qspi_flash: qspi_flash@0 {
|
||||
compatible = "nordic,qspi-nor";
|
||||
reg = <0>;
|
||||
writeoc = "pp";
|
||||
readoc = "fastread";
|
||||
sck-frequency = <16000000>;
|
||||
jedec-id = [ba 60 16]; /* ZD25WQ32C — Zetta datasheet Table-9 */
|
||||
size = <33554432>; /* size is in BITS: 32Mbit = 4MB */
|
||||
has-dpd;
|
||||
t-enter-dpd = <10000>; /* tDP 3us (conservative) */
|
||||
t-exit-dpd = <35000>; /* tRES1 8us (conservative) */
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- USB CDC for console / repeater CLI / USB companion ---- */
|
||||
zephyr_udc0: &usbd {
|
||||
compatible = "nordic,nrf-usbd";
|
||||
status = "okay";
|
||||
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- Flash partitions (SoftDevice v6, app @ 0x26000) ---- */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
|
||||
/* ---- External QSPI flash partitions ---- */
|
||||
&qspi_flash {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
/* Full 4MB for LittleFS storage */
|
||||
qspi_storage_partition: partition@0 {
|
||||
label = "qspi_storage";
|
||||
reg = <0x00000000 0x00400000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- External QSPI /ext automount ---- */
|
||||
#include "../../common/qspi-ext.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
@@ -0,0 +1,29 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# LilyGo T-Impulse Plus default configuration
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
# Enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# Enable console on USB CDC
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_LINE_CTRL=y
|
||||
|
||||
# Enable flash/NVS storage
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
|
||||
# Pinctrl
|
||||
CONFIG_PINCTRL=y
|
||||
|
||||
# SPI for LoRa SX1262
|
||||
CONFIG_SPI=y
|
||||
|
||||
# ADC for battery
|
||||
CONFIG_ADC=y
|
||||
Reference in New Issue
Block a user