mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-16 11:22:39 +00:00
heltec t1
This commit is contained in:
@@ -23,6 +23,7 @@ nRF_boards=(
|
||||
promicro_sx1262
|
||||
heltec_t114
|
||||
heltec_t096
|
||||
heltec_t1
|
||||
gat562_30s
|
||||
muziworks_r1neo
|
||||
)
|
||||
|
||||
@@ -22,6 +22,7 @@ promicro_sx1262
|
||||
promicro_lr2021
|
||||
heltec_t114
|
||||
heltec_t096
|
||||
heltec_t1
|
||||
gat562_30s
|
||||
muziworks_r1neo
|
||||
lilygo_timpulse_plus
|
||||
@@ -35,6 +36,8 @@ lilygo_timpulse_plus
|
||||
>
|
||||
> **Heltec Mesh Node T096** (`heltec_t096`): nRF52840 with SX1262 + KCT8103L PA/FEM, UC6580 GNSS, and ST7735S 160x80 TFT companion display. The external SPI flash footprint is documented in the board notes but left disabled until the device parameters are confirmed.
|
||||
>
|
||||
> **Heltec Mesh Node T1** (`heltec_t1`): nRF52840 + SX1262 handheld tracker card with UC6580 L1+L5 GNSS, ST7735S 160x80 TFT, PAM8904-driven piezo buzzer, two buttons and a 1850 mAh battery. No PA/FEM — the SX1262 drives a uPG2179 antenna switch from DIO2. The onboard ICM-42607-P/MMC5983MA IMU bus is left powered down (no ZephCore consumer). Untested on hardware; the GNSS UART direction and the display offsets are the two things to check first, both flagged in the board README.
|
||||
>
|
||||
> **LilyGo T-Impulse Plus** (`lilygo_timpulse_plus`): nRF52840 wristband/tracker with SX1262 (GPIO antenna switch, not DIO2), SSD1315 64x32 OLED, u-blox MIA-M10Q GPS, 4 MB QSPI flash (`/ext`), touch button, haptic motor. Builds and ships in releases, but several parameters are inferred from vendor sources and not bench-verified (TCXO voltage, battery divider ratio, OLED offsets) — see the board README. Early hardware testing also showed occasional spontaneous reboots, untriaged.
|
||||
>
|
||||
> **ProMicro LR2021** (`promicro_lr2021`): nRF52840 SuperMini + Semtech LR2021, the first ZephCore board bring-up for that radio. Source-only — **not in `build.sh`, the release workflow, or the Mesh America catalog**, so no release carries a binary for it. The bring-up module was destroyed by an accidental 5V feed (LR2021 VBAT max ~3.7V); build it yourself if you want to continue testing on a fresh module.
|
||||
|
||||
@@ -84,6 +84,7 @@ MAKER_BY_DEVICE = {
|
||||
"ProMicro nrf52 (faketec)": "promicro",
|
||||
"Heltec T114": "heltec",
|
||||
"Heltec Mesh Node T096": "heltec",
|
||||
"Heltec Mesh Node T1": "heltec",
|
||||
"Heltec v3": "heltec",
|
||||
"Heltec v4": "heltec",
|
||||
"Heltec v4.3": "heltec",
|
||||
@@ -171,6 +172,7 @@ BOARDS = [
|
||||
dict(stem="heltec_t114", kind="nrf", device="Heltec T114"),
|
||||
dict(stem="heltec_t114", kind="nrf", device="Heltec T114",
|
||||
variant="noscreen", subtitle="No screen"),
|
||||
dict(stem="heltec_t1", kind="nrf", device="Heltec Mesh Node T1"),
|
||||
dict(stem="gat562_30s", kind="nrf", device="GAT-IoT GAT562 30s"),
|
||||
dict(stem="muziworks_r1neo", kind="nrf", device="muzi works R1 Neo"),
|
||||
|
||||
@@ -264,7 +266,7 @@ SOFTDEVICE = {
|
||||
"rak4631": 6, "rak3401_1watt": 6, "thinknode_m1": 6, "thinknode_m3": 6,
|
||||
"thinknode_m6": 6, "rak_wismesh_tag": 6, "lilygo_techo": 6,
|
||||
"lilygo_timpulse_plus": 6, "promicro_sx1262": 6, "heltec_t114": 6,
|
||||
"heltec_t096": 6, "gat562_30s": 6, "muziworks_r1neo": 6,
|
||||
"heltec_t096": 6, "heltec_t1": 6, "gat562_30s": 6, "muziworks_r1neo": 6,
|
||||
"wio_tracker_l1": 7, "t1000_e": 7, "ikoka_nano_30dbm": 7,
|
||||
"sensecap_solar": 7, "xiao_nrf52840": 7, "meshtracker_x1": 7,
|
||||
}
|
||||
|
||||
@@ -319,7 +319,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 "meshtracker_x1" 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" OR BOARD MATCHES "muziworks_r1neo")
|
||||
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 "meshtracker_x1" 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 "heltec_t1" OR BOARD MATCHES "gat562" OR BOARD MATCHES "muziworks_r1neo")
|
||||
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")
|
||||
|
||||
@@ -27,6 +27,7 @@ Supported Boards
|
||||
| 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` |
|
||||
| Heltec Mesh Node T1 | `west build -b heltec_t1 zephcore` | UF2 drag-drop or `west flash` |
|
||||
| muzi works R1 Neo | `west build -b muziworks_r1neo zephcore` | UF2 drag-drop or `west flash` |
|
||||
|
||||
**Heltec T114 screenless:** append `boards/nrf52840/heltec_t114/no_display.conf` to `EXTRA_CONF_FILE` for units without the TFT module.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2026 ZephCore
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_HELTEC_T1
|
||||
select SOC_NRF52840_QIAA
|
||||
@@ -0,0 +1,229 @@
|
||||
# Heltec Mesh Node T1
|
||||
|
||||
Custom ZephCore board target for the Heltec Mesh Node T1.
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
west build -b heltec_t1 zephcore --pristine
|
||||
```
|
||||
|
||||
Repeater/observer roles build the same way with the usual `EXTRA_CONF_FILE`
|
||||
overlays; the T1 is a handheld tracker, so companion is the expected role.
|
||||
|
||||
## Hardware
|
||||
|
||||
- MCU: nRF52840 (1 MB flash, 256 kB RAM), Adafruit UF2 bootloader, SoftDevice
|
||||
s140 v6.1.1 layout (app @ `0x26000`, bootloader @ `0xF4000`)
|
||||
- Radio: SX1262, 32 MHz TCXO on DIO3 @ 1.8 V, no PA/FEM
|
||||
- RF path: separate RFO (TX) and RFI_P/RFI_N (RX) matched networks into a
|
||||
uPG2179 SPDT switch driven by SX1262 DIO2. Datasheet table 3.3: 21 ±1 dBm at
|
||||
the antenna in 863–870 and 902–928 MHz.
|
||||
- GNSS: UC6580 (L1+L5, GPS/BDS/GLONASS/Galileo/QZSS/NavIC/SBAS), ATR2652 LNA
|
||||
and HDDL1L5RSS-B8 diplexer, 26 MHz TCXO, 32.768 kHz RTC crystal
|
||||
- Display: ST7735S 0.96" TFT, 80×160 native / 160×80 landscape
|
||||
- Buzzer: piezo element driven differentially by a PAM8904 charge-pump driver
|
||||
- IMU: ICM-42607-P (accel + gyro) and MMC5983MA (magnetometer) — present but
|
||||
unused, see "Not enabled"
|
||||
- Battery: 1850 mAh Li-ion, CN3165 charger (red LED is hardware-only)
|
||||
- No external SPI/QSPI flash — storage is internal `/lfs` only
|
||||
- IP65, 85 × 55 × 9.5 mm, 53 g
|
||||
|
||||
## Confirmed pinout
|
||||
|
||||
Source: official Heltec `Mesh_Node_T1_V1.0` schematic — the pin table on the
|
||||
sheet, cross-checked against the U10/U11/U14/U18 symbols. Component behaviour
|
||||
comes from the parts' own datasheets (ST7735S panel spec
|
||||
`N096-1608TBBIG09-C08`, Diodes PAM8904, Semtech SX1262).
|
||||
|
||||
| Function | nRF52840 pin | Schematic net | ZephCore mapping |
|
||||
| --- | --- | --- | --- |
|
||||
| LoRa SCK | P1.13 | LOAR_SCK | `spi2` SCK |
|
||||
| LoRa MOSI | P1.14 | LOAR_MOSI | `spi2` MOSI |
|
||||
| LoRa MISO | P0.03 | LOAR_MISO | `spi2` MISO |
|
||||
| LoRa NSS / CS | P1.11 | LOAR_NSS | `cs-gpios` |
|
||||
| LoRa reset | P0.02 | LOAR_NRSET | `reset-gpios` |
|
||||
| LoRa busy | P0.29 | LORA_BUSY | `busy-gpios` |
|
||||
| LoRa DIO1 | P0.31 | DIO1 | `dio1-gpios` |
|
||||
| Antenna switch | SX1262 DIO2 | ANT_SW_CTRL | `dio2-tx-enable` |
|
||||
| GNSS UART TX from MCU | P0.07 | GNSS_RX | `uart0` TX |
|
||||
| GNSS UART RX into MCU | P0.08 | GNSS_TX | `uart0` RX |
|
||||
| GNSS reset | P0.26 | GNSS_RST | `gps-reset` alias, active-low |
|
||||
| GNSS rail enable | P0.04 | VGNSS_Ctrl | regulator `gps_power`, active-low |
|
||||
| GNSS PPS | P1.09 | PPS | documented, not consumed |
|
||||
| Display SCK | P1.00 | SCLK | `spi3` SCK |
|
||||
| Display MOSI | P0.24 | SDIN | `spi3` MOSI |
|
||||
| Display CS | P0.12 | CS | `spi3` `cs-gpios` |
|
||||
| Display DC | P0.22 | RS | MIPI-DBI `dc-gpios` |
|
||||
| Display reset | P0.20 | RES | MIPI-DBI `reset-gpios` |
|
||||
| Display backlight | P0.15 | LED_K | regulator `disp_pwr_enable`, active-low |
|
||||
| Display panel rail | P0.13 | VScreen_Ctrl | regulator `tft_pwr_enable`, active-low |
|
||||
| Buzzer tone | P0.09 | DIN | `pwm0` channel 0, `buzzer` alias |
|
||||
| Buzzer 2× select | P1.02 | EN1 | unclaimed (10K pull-up) |
|
||||
| Buzzer 3× select | P1.05 | EN2 | unclaimed (10K pull-up) |
|
||||
| White LED | P0.16 | LED | `led0`, `lora-tx-led`, active-low |
|
||||
| User button | P1.10 | Button | `sw0`, active-low |
|
||||
| Function button | P0.14 | User | `KEY_LEFT`, active-low |
|
||||
| Battery ADC | P0.05 / AIN3 | BAT_ADC | ADC channel 3 |
|
||||
| Battery ADC enable | P0.11 | ADC_Ctrl | regulator `vbat_enable`, active-high |
|
||||
| Sensor rail enable | P1.06 | VSensor_Ctrl | regulator `sensor_power`, active-low, held off |
|
||||
| Sensor I2C SDA | P1.03 | Sensor_SDA | not enabled |
|
||||
| Sensor I2C SCL | P0.10 | Sensor_SCL | not enabled |
|
||||
| IMU INT1 / INT2 | P1.01 / P1.07 | INT1 / INT2 | not consumed |
|
||||
|
||||
The power button (S1) is not visible to firmware. It feeds the EC190708 latch
|
||||
that gates the 3V3 LDO enable and, through Q7/Q4, pulls `nRF_RST` low. Per the
|
||||
datasheet: 3 s hold = on/off, short press = reboot, double-click = DFU.
|
||||
|
||||
## Two Heltec document errors, corrected here
|
||||
|
||||
**The white LED is on P0.16, not P0.09.** Datasheet §2.2 says "White Function
|
||||
LED, connected to P0.09". P0.09 is the PAM8904 `DIN` (buzzer). The schematic
|
||||
puts the LED on P0.16, and Heltec's own nRF52 Arduino variant
|
||||
(`HT-mesh-node-t1`) agrees.
|
||||
|
||||
**The GNSS UART aliases in the schematic's pin table are inverted.** The table
|
||||
prints `nRF_RX` beside P0.07 and `nRF_TX` beside P0.08. The `GNSS_RX`/`GNSS_TX`
|
||||
halves of the same rows are correct, and they are the ones to trust:
|
||||
|
||||
- `GNSS_RX` lands on UC6580 pin 18, whose symbol pin name is `RX` — an input.
|
||||
Nothing else drives that node, so P0.07 can only be the nRF's **transmit**
|
||||
line. Two inputs tied together with no driver is not a circuit.
|
||||
- `GNSS_TX` lands on UC6580 pin 19 (`TX`, an output), which must feed an MCU
|
||||
input, so P0.08 is the nRF's **receive** line.
|
||||
|
||||
Heltec's own Arduino core (`HelTecAutomation/Heltec_nRF52`,
|
||||
`variants/HT-mesh-node-t1/variant.h`) sets `PIN_SERIAL1_TX = P0.07` and
|
||||
`PIN_SERIAL1_RX = P0.08` — the same way round — and it is what their shipped
|
||||
`GPS_To_Serial` test firmware for this board is built against. Meshtastic's
|
||||
variant is a copy of it and agrees.
|
||||
|
||||
Arduino MeshCore's `variants/heltec_t1/variant.h` has these two swapped
|
||||
(`PIN_SERIAL1_RX = P0.07`), still on both `main` and `dev`. Their T1 GPS
|
||||
cannot be receiving.
|
||||
|
||||
If a first hardware run shows no NMEA, swapping the two `psels` in
|
||||
`heltec_t1_nrf52840-pinctrl.dtsi` is the one-line test.
|
||||
|
||||
## Display
|
||||
|
||||
- Controller: ST7735S, driven by Zephyr's `sitronix,st7735r` driver.
|
||||
- Panel: Unvision `N096-1608TBBIG09-C08`, 0.96", 80(H)RGB × 160(V), dot pitch
|
||||
0.135 mm, active area 10.8 × 21.7 mm, normally black, 4-line SPI, one white
|
||||
LED backlight, −20…+70 °C.
|
||||
- Bus: SPI3 through MIPI-DBI, **write-only** — the 8-pin FFC has no data-out
|
||||
line.
|
||||
- UI path: `zephcore,mono-tft` wraps the colour TFT as a 1bpp display for
|
||||
ZephCore's CFB UI. At 160×80 with the 6×8 font that is 26 columns × 10 rows,
|
||||
identical to the T096 and the Heltec Wireless Tracker.
|
||||
- Orientation: landscape, rotated 180° from the T096 mounting of the same panel
|
||||
class — `madctl = 0x68` (MX | MV | BGR) against `0xa8` (MY | MV | BGR) there.
|
||||
Offsets are `x-offset = 0`, `y-offset = 24`, matching the "red tab 160×80"
|
||||
column-start of 24 / row-start of 0 transposed by MV.
|
||||
|
||||
**To check on first boot:** mirroring an 80-column window that sits at GRAM
|
||||
offset 24 inside the ST7735S's 132 columns should geometrically land it at
|
||||
28, yet both mainstream Arduino ST7735 drivers keep the same offsets across
|
||||
rotations 1 and 3. If the image is shifted with a black band on one edge, the
|
||||
mirrored alternative is `x-offset = 2`, `y-offset = 28`,
|
||||
`caset = [00 02 00 a1]`, `raset = [00 1c 00 6b]`.
|
||||
- Power: the panel rail (`VScreen_Ctrl`) is boot-enabled so the ST7735 init
|
||||
sequence reaches a powered panel. The backlight FET's source is `VDD_3V3`,
|
||||
**not** the panel rail, so it has to be switched off in its own right —
|
||||
`disp_pwr_enable` does that and follows ZephCore display on/off.
|
||||
|
||||
## Buzzer
|
||||
|
||||
The piezo is driven by a PAM8904 charge pump, not a bare transistor. From the
|
||||
MCU's side it is still one tone input: PWM0 channel 0 on P0.09.
|
||||
|
||||
Its charge-pump multiplier is selected by EN1 (P1.02) and EN2 (P1.05), which
|
||||
both carry 10K pull-ups to VDD_3V3. Per the PAM8904 datasheet that is 3× mode —
|
||||
7.2–9 V out, the loudest setting — with no firmware involvement, and the part
|
||||
sits under 1 µA whenever `DIN` is low, auto-sleeping 42 ms after the tone
|
||||
stops. So both pins are deliberately left unclaimed. Driving them is only
|
||||
worth doing if a quieter mode is ever wanted:
|
||||
|
||||
| DIN | EN1 | EN2 | Mode |
|
||||
| --- | --- | --- | --- |
|
||||
| 0 | × | × | shutdown |
|
||||
| 1 | 0 | 0 | shutdown |
|
||||
| 1 | 0 | 1 | 1× (2.8–3 V) |
|
||||
| 1 | 1 | 0 | 2× (5.2–6 V) |
|
||||
| 1 | 1 | 1 | 3× (7.2–9 V) |
|
||||
|
||||
## Buttons
|
||||
|
||||
Two buttons, so unlike the single-button Heltec boards the T1 can page
|
||||
backwards.
|
||||
|
||||
| Button | Pin | Gesture | Action |
|
||||
| --- | --- | --- | --- |
|
||||
| User (S3) | P1.10 | 1 tap | page next |
|
||||
| | | 2 taps | LED heartbeat toggle |
|
||||
| | | 3 taps | notification mode |
|
||||
| | | 4 taps | GPS on/off |
|
||||
| | | 5 taps | flood advert |
|
||||
| | | hold 1 s | page enter |
|
||||
| Function (S2) | P0.14 | press | page previous |
|
||||
|
||||
The datasheet calls P1.10 "Button1 / USER key" and P0.14 "Button2 / Function
|
||||
key"; the schematic silkscreen labels are the other way round (S2 = "User1" on
|
||||
P0.14, S3 = "User2" on P1.10). Pins are what matter.
|
||||
|
||||
## NFC pins used as GPIO
|
||||
|
||||
P0.09 (buzzer `DIN`) and P0.10 (`Sensor_SCL`) are the nRF52840's NFC antenna
|
||||
pins, so `UICR.NFCPINS` has to select GPIO. The DTS sets `nfct-pins-as-gpios`
|
||||
on `&uicr`.
|
||||
|
||||
Stock boards already have this programmed by the factory Adafruit UF2
|
||||
bootloader, so a normal UF2 install needs nothing extra. A board that has been
|
||||
fully erased over SWD does, and that property is what puts it back.
|
||||
|
||||
## Not enabled
|
||||
|
||||
- **Sensor I2C bus.** The ICM-42607-P and MMC5983MA sit on `Sensor_SDA`
|
||||
(P1.03) / `Sensor_SCL` (P0.10) behind the `VSensor_Ctrl` rail, which also
|
||||
powers the bus's 4.7K pull-ups. ZephCore has no consumer for either part —
|
||||
there is no IMU support, and the MMC5983MA has no Zephyr driver at all — and
|
||||
the board is sealed with no external sensor connector, so the bus stays down
|
||||
and the `sensor_power` regulator node exists purely to hold P1.06 inactive.
|
||||
The datasheet's 11 µA sleep figure assumes that rail is off.
|
||||
|
||||
To bring it up: enable `&i2c0` with a pinctrl pair for those two pins and add
|
||||
`regulator-boot-on` to `sensor_power`.
|
||||
- **U6**, an 8-pin pressure-sensor footprint on the same bus, is marked NC on
|
||||
the schematic, and so is `R25`, its SDO/address strap — the address would
|
||||
float even if a part were fitted.
|
||||
- **External flash.** There is none on this board, so `&qspi` is disabled and
|
||||
`/ext` is unavailable. Contacts and channels live in internal `/lfs`.
|
||||
|
||||
## Heltec license page overlap
|
||||
|
||||
Heltec's own Arduino variant reserves `0xF3000`–`0xF4000` (the last flash page
|
||||
before the bootloader) for a hardware-version byte and a license blob
|
||||
(`HARD_VERSION_ADDR` / `HT_LICENSE_ADDR`). That page falls inside ZephCore's
|
||||
`/lfs` partition, so running ZephCore will eventually erase it, the same way it
|
||||
does on the other nRF52 boards that overlap an Adafruit-era filesystem region.
|
||||
It only matters if you intend to go back to Heltec's own F&T / SnapEmu
|
||||
firmware, which is what reads that blob; MeshCore and Meshtastic do not.
|
||||
|
||||
## Hardware smoke test plan
|
||||
|
||||
1. Flash UF2 by double-clicking the power button and drag-dropping.
|
||||
2. Confirm USB CDC/logging appears.
|
||||
3. Confirm the white LED goes out after boot (it is lit from power-up until
|
||||
firmware drives P0.16 high).
|
||||
4. Confirm BLE advertises and the MeshCore app pairs.
|
||||
5. Confirm the display lights and shows the companion UI. **Check the image
|
||||
fills the panel edge to edge** — see the offsets note above.
|
||||
6. Confirm the backlight and panel both go dark on display timeout.
|
||||
7. Confirm both buttons: page next / page previous.
|
||||
8. Confirm SX1262 init with no reset, busy or DIO1 errors, then RX.
|
||||
9. Test TX at low power first, then step up — the antenna switch is chip-driven
|
||||
via DIO2, so a wrong `dio2-tx-enable` shows up as very poor range rather
|
||||
than an error.
|
||||
10. Confirm the buzzer sounds.
|
||||
11. Confirm GNSS last: `get gps` should show sentences arriving. **If nothing
|
||||
arrives, swap the UART psels** — see the GNSS UART note above.
|
||||
@@ -0,0 +1,14 @@
|
||||
# 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 @@
|
||||
# Heltec Mesh Node T1 - nRF52840 + SX1262 + UC6580 GNSS
|
||||
# Board-specific configuration
|
||||
#
|
||||
# Hardware (Heltec Mesh_Node_T1_V1.0 schematic + datasheet Rev 1.0.0):
|
||||
# - nRF52840 SoC, SX1262 LoRa, no FEM (uPG2179 SPDT switch driven by DIO2)
|
||||
# - UC6580 GNSS on UART0 at 115200 baud (L1+L5, ATR2652 LNA front end)
|
||||
# - ST7735S 0.96" 160x80 TFT (SPI3, MIPI-DBI, mono-tft wrapper)
|
||||
# - PAM8904 piezo buzzer driver, tone input on PWM0/P0.09
|
||||
# - Battery ADC on AIN3 (P0.05), 390K/100K divider, enable P0.11
|
||||
# - LED: P0.16 (active-LOW)
|
||||
# - Buttons: P1.10 (user, active-LOW) and P0.14 (function, active-LOW)
|
||||
# - ICM-42607-P + MMC5983MA on a gated I2C bus; no ZephCore consumer, so the
|
||||
# bus and its rail are left off
|
||||
# - No external flash: storage is internal /lfs only
|
||||
#
|
||||
# Not set here because devicetree already decides them:
|
||||
# - CONFIG_PWM / CONFIG_ZEPHCORE_UI_BUZZER come from the "buzzer" nodelabel
|
||||
# - CONFIG_ZEPHCORE_UI_DISPLAY comes from chosen { zephyr,display }
|
||||
# - CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM stays at the 22 dBm default: there is
|
||||
# no PA to overdrive, and datasheet table 3.3 rates the board at 21 +/- 1 dBm
|
||||
# in both the 863-870 and 902-928 MHz bands.
|
||||
|
||||
# Board identification. "Heltec Mesh Node T1" is the exact device name the
|
||||
# MeshCore flasher catalogue uses, so the Mesh America configurator folds this
|
||||
# into the existing device tile instead of creating a ZephCore-only one.
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="Heltec Mesh Node T1"
|
||||
|
||||
# Device Information Service model name
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="Heltec Mesh Node T1"
|
||||
|
||||
# SoftDevice firmware ID (s140 v6.1.1)
|
||||
CONFIG_ZEPHCORE_SD_FWID=0x00B6
|
||||
|
||||
# ========== RAM budget ==========
|
||||
# CFB mono-tft framebuffer = 160x80/8 = 1600 bytes, allocated from k_malloc.
|
||||
# Default heap (2048) is sized tightly for SSD1306 128x64 (1024 bytes).
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=4096
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2026 ZephCore
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board:
|
||||
name: heltec_t1
|
||||
full_name: Heltec Mesh Node T1
|
||||
vendor: heltec
|
||||
socs:
|
||||
- name: nrf52840
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Heltec Mesh Node T1 pin control definitions
|
||||
* Copyright (c) 2026 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Sources:
|
||||
* - Heltec "Mesh_Node_T1_V1.0" schematic (resource.heltec.cn), pin table and
|
||||
* the U10/U11/U14/U18 symbols
|
||||
* - Heltec "Mesh Node T1 Wireless Position Tag" datasheet Rev 1.0.0
|
||||
*
|
||||
* Schematic nets:
|
||||
* - SPI2 (SX1262 LoRa): SCK=P1.13 (LOAR_SCK), MOSI=P1.14 (LOAR_MOSI),
|
||||
* MISO=P0.03 (LOAR_MISO)
|
||||
* - SPI3 (ST7735S display): SCK=P1.00 (SCLK), MOSI=P0.24 (SDIN); the FFC has
|
||||
* no data-out line, so the bus is write-only
|
||||
* - UART0 (UC6580 GNSS): TX=P0.07 -> UC6580 pin 18 (RX),
|
||||
* RX=P0.08 <- UC6580 pin 19 (TX)
|
||||
* - PWM0 (PAM8904 buzzer): OUT0=P0.09 (DIN)
|
||||
*
|
||||
* The schematic's pin table prints "nRF_RX" beside P0.07 and "nRF_TX" beside
|
||||
* P0.08. Those two aliases are inverted: P0.07 is wired to the UC6580's RX
|
||||
* input, which no other part drives, so it can only be the nRF's transmit
|
||||
* line. The GNSS_RX/GNSS_TX halves of the same table are correct, and match
|
||||
* Heltec's own nRF52 Arduino variant (HT-mesh-node-t1) which sets
|
||||
* PIN_SERIAL1_TX = P0.07 and PIN_SERIAL1_RX = P0.08.
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
/* SX1262 LoRa radio */
|
||||
spi2_default: spi2_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 3)>;
|
||||
};
|
||||
};
|
||||
|
||||
spi2_sleep: spi2_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 3)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* ST7735S TFT — write-only, no MISO on the 8-pin FFC */
|
||||
spi3_default: spi3_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 0)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 24)>;
|
||||
};
|
||||
};
|
||||
|
||||
spi3_sleep: spi3_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 0)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 24)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* UC6580 GNSS */
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 7)>;
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(UART_RX, 0, 8)>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 7)>,
|
||||
<NRF_PSEL(UART_RX, 0, 8)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* PAM8904 piezo driver tone input */
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 9)>;
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_sleep: pwm0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 9)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
* Heltec Mesh Node T1 - nRF52840 + SX1262 + UC6580 GNSS
|
||||
* Copyright (c) 2026 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Every net named below is taken from the official Heltec
|
||||
* "Mesh_Node_T1_V1.0" schematic (resource.heltec.cn), cross-checked against
|
||||
* the "Mesh Node T1 Wireless Position Tag" datasheet Rev 1.0.0 and the
|
||||
* component datasheets for the parts the nets land on (ST7735S panel spec
|
||||
* N096-1608TBBIG09-C08, Diodes PAM8904, Semtech SX1262). Where the two
|
||||
* Heltec documents disagree the schematic wins; the two places where that
|
||||
* happens are called out at the nodes concerned.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.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>
|
||||
#include "heltec_t1_nrf52840-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Heltec Mesh Node T1";
|
||||
compatible = "heltec,t1";
|
||||
|
||||
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 = &mono_tft;
|
||||
zephcore,gps-power = &gps_power;
|
||||
};
|
||||
|
||||
aliases {
|
||||
led0 = &led_white;
|
||||
lora-tx-led = &led_white;
|
||||
sw0 = &user_button;
|
||||
lora0 = &lora;
|
||||
watchdog0 = &wdt0;
|
||||
gps-reset = &gps_reset_pin;
|
||||
display0 = &tft;
|
||||
buzzer = &buzzer;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
/*
|
||||
* Schematic net LED: P0.16 -> R56 1K -> gate of Q10 (AO3401A,
|
||||
* P-channel, source on VDD_3V3), drain -> R30 330R -> LED2
|
||||
* (white) -> GND. Pulling the gate low turns the FET on, so
|
||||
* the LED is active-LOW.
|
||||
*
|
||||
* The datasheet's "2.2 LED" table instead says the white LED is
|
||||
* on P0.09. That is wrong - P0.09 is the PAM8904 DIN (buzzer);
|
||||
* the schematic, and every vendor firmware, put the LED on
|
||||
* P0.16.
|
||||
*
|
||||
* Caveat for anyone chasing a boot-time glow: unlike the
|
||||
* backlight FET, Q10's gate has no pull-up to its source, only
|
||||
* R57 10M to ground. While P0.16 is still an input the gate
|
||||
* sits near 0 V and the LED is lit. gpio-leds drives it
|
||||
* inactive at init, which closes the window but does not remove
|
||||
* it.
|
||||
*/
|
||||
led_white: led_0 {
|
||||
gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
|
||||
label = "White LED";
|
||||
};
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
/*
|
||||
* Schematic S3 (silkscreen "User2"), net Button: P1.10 to GND,
|
||||
* R8 10K pull-up to VDD_nRF, C8 0.1uF debounce. The datasheet
|
||||
* calls this one "Button1 / USER key".
|
||||
*/
|
||||
user_button: button_0 {
|
||||
gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
label = "User Button";
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic S2 (silkscreen "User1"), net User: P0.14 to GND,
|
||||
* R20 10K pull-up to VDD_3V3, C15 0.1uF debounce. The
|
||||
* datasheet calls this one "Button2 / Function key".
|
||||
*
|
||||
* Wired straight to KEY_LEFT: with two buttons the T1 can do
|
||||
* page-previous, which the single-button Heltec boards cannot.
|
||||
*/
|
||||
page_prev_button: button_1 {
|
||||
gpios = <&gpio0 14 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
zephyr,code = <INPUT_KEY_LEFT>;
|
||||
label = "Function Button";
|
||||
};
|
||||
};
|
||||
|
||||
/* Input filter: user button long-press detection (1000ms) */
|
||||
user_btn_longpress: 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>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Input filter: user button multi-tap detection. Stock ladder - the
|
||||
* T1 has a real buzzer, so the 3-tap notification-mode slot is live
|
||||
* here (unlike T096, where it was compiled out and had to be dropped).
|
||||
*
|
||||
* 1 tap (400ms wait) → KEY_1 = page next
|
||||
* 2 taps (400ms wait) → KEY_B = LED heartbeat toggle
|
||||
* 3 taps (400ms wait) → KEY_D = notification mode
|
||||
* 4 taps (400ms wait) → KEY_C = GPS on/off
|
||||
* 5 taps (immediate) → KEY_E = flood advert
|
||||
*/
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle - KEY_A comes from the longpress
|
||||
* pseudo-device, not from &buttons. */
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net DIN: P0.09 -> R24 0R -> PAM8904 (U3) pin 3.
|
||||
*
|
||||
* U3 is a charge-pump piezo driver, not a plain transistor: it drives
|
||||
* the element differentially from VO1/VO2 through R14/R18 100R. From
|
||||
* the MCU's side it is still just a tone input - PAM8904 datasheet
|
||||
* p.5 has the part idle at under 1uA whenever DIN is low, and
|
||||
* auto-sleep 42ms after DIN stops toggling, so no enable sequencing is
|
||||
* needed.
|
||||
*
|
||||
* P0.09 is NFC1. See the &uicr node at the bottom of this file.
|
||||
*
|
||||
* The charge-pump multiplier pins EN1 (P1.02) and EN2 (P1.05) are
|
||||
* deliberately left unconfigured: both carry 10K pull-ups to VDD_3V3,
|
||||
* which selects 3x mode (7.2-9V out, the loudest setting) with no
|
||||
* firmware involvement. Driving them would only ever make the buzzer
|
||||
* quieter, so they are documented in the README as a future volume
|
||||
* control rather than claimed here.
|
||||
*/
|
||||
pwmbuzzer {
|
||||
compatible = "pwm-leds";
|
||||
buzzer: buzzer {
|
||||
pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net VGNSS_Ctrl: P0.04 -> R32 1K -> gate of Q5 (AO3401A,
|
||||
* P-channel, source on VDD_3V3, R54 10K gate pull-up), drain feeds
|
||||
* VDD_GNSS. Active-LOW, and off at reset while the pin is an input.
|
||||
*/
|
||||
gps_power: gps-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "gps-power";
|
||||
enable-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
||||
regulator-boot-on;
|
||||
/* Documents the module's requirement, but do not rely on it:
|
||||
* regulator-boot-on sends regulator_common_init() down the
|
||||
* refcount-only branch, so regulator_delay() never runs and this
|
||||
* value is inert. Harmless here because gnss-nmea-generic never
|
||||
* probes the receiver — it attaches a UART and parses whatever
|
||||
* arrives, so an unpowered module means no sentences yet, not a
|
||||
* failed init. ZephyrGPSManager owns the rail at runtime via
|
||||
* chosen { zephcore,gps-power }. */
|
||||
startup-delay-us = <10000>;
|
||||
};
|
||||
|
||||
/* Schematic net GNSS_RST: P0.26 -> UC6580 pin 17 (RESETN), active-LOW,
|
||||
* R37 10K pull-up to VDD_GNSS and C90 0.1uF. */
|
||||
gps_rst: gps-reset {
|
||||
compatible = "gpio-leds";
|
||||
gps_reset_pin: gps_reset {
|
||||
gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
|
||||
label = "GNSS Reset";
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net VSensor_Ctrl: P1.06 -> R31 1K -> gate of Q11 (AO3401A,
|
||||
* P-channel, source on VDD_3V3, R23 10K gate pull-up) -> VDD_Sensor.
|
||||
* Active-LOW.
|
||||
*
|
||||
* VDD_Sensor powers the ICM-42607-P, the MMC5983MA, the unpopulated U6
|
||||
* pressure-sensor footprint, and the 4.7K pull-ups on the Sensor_SDA /
|
||||
* Sensor_SCL bus. ZephCore consumes none of those, so this node exists
|
||||
* only to hold the rail off: with no consumer and no regulator-boot-on,
|
||||
* regulator-fixed init drives P1.06 inactive and the rail stays down.
|
||||
* That is what the datasheet's 11uA sleep figure assumes.
|
||||
*/
|
||||
sensor_power: sensor-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "sensor-power";
|
||||
enable-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net ADC_Ctrl: P0.11 -> R7 1K -> base of Q2 (S9013 NPN,
|
||||
* R12 10K base pulldown); Q2's collector pulls the gate of Q1
|
||||
* (AO3401A, source on VBAT, R5 10K gate pull-up) low, switching VBAT
|
||||
* into the R11 390K / R16 100K divider. Active-HIGH.
|
||||
*/
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net VScreen_Ctrl: P0.13 -> R26 1K -> gate of Q6 (AO3401A,
|
||||
* P-channel, source on VDD_3V3, R52 10K gate pull-up) -> VDD_Screen,
|
||||
* which is FFC pin 7 (VDD). Active-LOW.
|
||||
*
|
||||
* Meshtastic's variant.h comments this net as "Active HIGH". That
|
||||
* comment is wrong - Q6 is a P-channel FET with its gate pulled to its
|
||||
* own source - and Heltec's nRF52 Arduino variant agrees with the
|
||||
* schematic (TFT_VDD_ENABLE = 0).
|
||||
*/
|
||||
tft_pwr_enable: tft-pwr-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "tft-pwr-enable";
|
||||
enable-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||
regulator-boot-on;
|
||||
/* Documents the panel's requirement, but do not rely on it:
|
||||
* regulator-boot-on sends regulator_common_init() down the
|
||||
* refcount-only branch, so regulator_delay() never runs and this
|
||||
* value is inert. The real settle time comes from the ST7735R
|
||||
* driver's own mipi_dbi_reset() + exit-sleep delay, at
|
||||
* DISPLAY_INIT_PRIORITY 85 against this rail's 75. */
|
||||
startup-delay-us = <10000>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Schematic net LED_K: P0.15 -> R28 1K -> gate of Q9 (AO3401A,
|
||||
* P-channel, source on VDD_3V3, R27 10K gate pull-up), drain ->
|
||||
* R55 22R -> FFC pin 1 (LEDA). Active-LOW, off at reset.
|
||||
*
|
||||
* The net name is a misnomer inherited from other Heltec boards: the
|
||||
* N096-1608TBBIG09-C08 only brings the backlight *anode* out to the
|
||||
* FFC (panel spec section 3), so Q9 switches the high side.
|
||||
*
|
||||
* Note the FET source is VDD_3V3, not VDD_Screen - the backlight does
|
||||
* not follow the panel rail and has to be switched off in its own
|
||||
* right.
|
||||
*/
|
||||
disp_pwr_enable: disp-pwr-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp-pwr-enable";
|
||||
enable-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Monochrome wrapper around the ST7735S-compatible TFT.
|
||||
* Reports PIXEL_FORMAT_MONO01 to CFB and converts rows to RGB565.
|
||||
*/
|
||||
mono_tft: mono-tft {
|
||||
compatible = "zephcore,mono-tft";
|
||||
tft-dev = <&tft>;
|
||||
width = <160>;
|
||||
height = <80>;
|
||||
};
|
||||
|
||||
/*
|
||||
* MIPI-DBI SPI bus for the 0.96" TFT.
|
||||
*
|
||||
* Panel is an Unvision N096-1608TBBIG09-C08: 80(H)RGB x 160(V),
|
||||
* 10.8 x 21.7 mm active area, normally black, 4-line SPI, ST7735S
|
||||
* driver IC, single white LED backlight (panel spec sections 1.2
|
||||
* and 3).
|
||||
*
|
||||
* Schematic nets, all on the 8-pin FFC U18:
|
||||
* - CS -> P0.12, FFC pin 8
|
||||
* - RS -> P0.22, FFC pin 4, data/command
|
||||
* - SDIN -> P0.24, FFC pin 5 (SDA)
|
||||
* - SCLK -> P1.00, FFC pin 6 (SCL)
|
||||
* - RES -> P0.20, FFC pin 3, active-LOW reset
|
||||
*
|
||||
* The FFC carries no data-out line, hence write-only.
|
||||
*/
|
||||
mipi_dbi {
|
||||
compatible = "zephyr,mipi-dbi-spi";
|
||||
spi-dev = <&spi3>;
|
||||
dc-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
|
||||
write-only;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
tft: st7735s@0 {
|
||||
compatible = "sitronix,st7735r";
|
||||
mipi-max-frequency = <20000000>;
|
||||
mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";
|
||||
reg = <0>;
|
||||
width = <160>;
|
||||
height = <80>;
|
||||
/* No inversion-on: the mono_tft wrapper writes 0xFFFF for a lit
|
||||
* pixel and 0x0000 for background, so INV_ON paints a light
|
||||
* background with dark text. The UI is drawn light-on-dark. */
|
||||
|
||||
/*
|
||||
* Landscape, rotated 180 degrees from the T096 mounting
|
||||
* of the same panel class. MADCTL 0x68 = MX | MV | BGR,
|
||||
* against 0xa8 = MY | MV | BGR there. The offsets are
|
||||
* the pair that belongs to this glass bonding (the
|
||||
* "red tab 160x80" column start of 24, row start of 0,
|
||||
* transposed by MV).
|
||||
*
|
||||
* If the first hardware run shows the image shifted with
|
||||
* a black band on one edge, the alternative offsets for
|
||||
* the mirrored orientation are x-offset 2 / y-offset 28,
|
||||
* caset [00 02 00 a1], raset [00 1c 00 6b].
|
||||
*/
|
||||
x-offset = <0>;
|
||||
y-offset = <24>;
|
||||
madctl = <0x68>;
|
||||
colmod = <0x05>;
|
||||
invctr = <7>;
|
||||
vmctr1 = <0x0e>;
|
||||
pwctr1 = [a2 02 84];
|
||||
pwctr2 = [c1];
|
||||
pwctr3 = [0a 00];
|
||||
pwctr4 = [8a 2a];
|
||||
pwctr5 = [8a ee];
|
||||
frmctr1 = [01 26 2e];
|
||||
frmctr2 = [01 26 2e];
|
||||
frmctr3 = [01 26 2e 01 26 2e];
|
||||
gamctrp1 = [0f 1a 0f 18 2f 28 20 22 1f 1b 23 37 00 07 02 10];
|
||||
gamctrn1 = [0f 1b 0f 17 33 2c 29 2e 30 2e 30 3b 00 07 03 10];
|
||||
caset = [00 00 00 9f];
|
||||
raset = [00 18 00 67];
|
||||
};
|
||||
};
|
||||
|
||||
zephyr,user {
|
||||
io-channels = <&adc 3>;
|
||||
/*
|
||||
* Schematic: BAT_ADC on P0.05/AIN3, divider R11=390K high side
|
||||
* and R16=100K low side -> 4.9:1. With ADC_GAIN_1_6 and the
|
||||
* internal 0.6V reference, full-scale is 3600 mV, so the
|
||||
* nominal multiplier is 3600 * 4.9 = 17640; the value below
|
||||
* carries the same +0.5% nRF SAADC gain-error correction used
|
||||
* on the other ZephCore nRF52 boards.
|
||||
*/
|
||||
vbat-mv-multiplier = <17728>;
|
||||
};
|
||||
};
|
||||
|
||||
®0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
®1 {
|
||||
regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* P0.09 (PAM8904 DIN) and P0.10 (Sensor_SCL) are the nRF52840's NFC antenna
|
||||
* pins. UICR.NFCPINS has to select GPIO or neither pin can be driven.
|
||||
*
|
||||
* Stock boards already have this programmed by the factory Adafruit UF2
|
||||
* bootloader, so a UF2 install needs nothing extra; a board that has been
|
||||
* fully erased over SWD does, and this property is what puts it back.
|
||||
*/
|
||||
&uicr {
|
||||
nfct-pins-as-gpios;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&pwm0_default>;
|
||||
pinctrl-1 = <&pwm0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
/*
|
||||
* The Sensor_SDA (P1.03) / Sensor_SCL (P0.10) bus is left disabled on
|
||||
* purpose - see the sensor_power node above. To bring it up, enable
|
||||
* &i2c0 with a pinctrl pair for those two pins and give sensor_power a
|
||||
* regulator-boot-on; without the rail the 4.7K pull-ups are unpowered and
|
||||
* the bus cannot work.
|
||||
*/
|
||||
|
||||
/* UC6580 GNSS - 115200 baud, plain NMEA stream, no command handshake. */
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
status = "okay";
|
||||
current-speed = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
gnss: gnss {
|
||||
compatible = "gnss-nmea-generic";
|
||||
};
|
||||
};
|
||||
|
||||
/* SPI3 - ST7735S 0.96" 160x80 TFT display */
|
||||
&spi3 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spi3_default>;
|
||||
pinctrl-1 = <&spi3_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
cs-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; /* Schematic net CS */
|
||||
};
|
||||
|
||||
/* SPI2 - SX1262 LoRa radio */
|
||||
&spi2 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; /* Schematic net LOAR_NSS */
|
||||
pinctrl-0 = <&spi2_default>;
|
||||
pinctrl-1 = <&spi2_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
lora: lora@0 {
|
||||
compatible = "semtech,sx1262";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; /* LOAR_NRSET */
|
||||
busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; /* LORA_BUSY */
|
||||
dio1-gpios = <&gpio0 31 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* DIO1 */
|
||||
|
||||
/*
|
||||
* There is no FEM on this board. The SX1262's RFO (pin 23) and
|
||||
* RFI_P/RFI_N (pins 21/22) run as separate matched paths into a
|
||||
* uPG2179 SPDT switch (U13), whose Vcont1 is driven straight
|
||||
* from schematic net ANT_SW_CTRL = SX1262 DIO2 (pin 12) and
|
||||
* whose Vcont2 is the complement produced by Q8 (2SC3356). So
|
||||
* the chip switches its own antenna path and no MCU GPIO is
|
||||
* involved: dio2-tx-enable, and no antenna-enable-gpios or
|
||||
* lna-bypass-gpios.
|
||||
*/
|
||||
dio2-tx-enable;
|
||||
|
||||
/*
|
||||
* X3 is a 32 MHz TCXO whose supply comes from DIO3 through
|
||||
* FB2 (10R@100MHz). 1.8V per Heltec's own Arduino variant
|
||||
* (SX126X_DIO3_TCXO_VOLTAGE 1.8).
|
||||
*/
|
||||
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
||||
tcxo-power-startup-delay-ms = <5>;
|
||||
rx-boosted;
|
||||
};
|
||||
};
|
||||
|
||||
/* No external SPI/QSPI flash on this board - storage is internal only. */
|
||||
&qspi {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
zephyr_udc0: &usbd {
|
||||
compatible = "nordic,nrf-usbd";
|
||||
status = "okay";
|
||||
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
};
|
||||
};
|
||||
|
||||
/* SoftDevice s140 v6.1.1 flash layout (app@0x26000, bootloader@0xF4000) */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
#include "../../common/nrf52_wakeup.dtsi"
|
||||
@@ -0,0 +1,20 @@
|
||||
identifier: heltec_t1/nrf52840
|
||||
name: Heltec Mesh Node T1
|
||||
type: mcu
|
||||
arch: arm
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
ram: 256
|
||||
flash: 1024
|
||||
supported:
|
||||
- adc
|
||||
- ble
|
||||
- gpio
|
||||
- pwm
|
||||
- spi
|
||||
- usb_device
|
||||
- lora
|
||||
- gnss
|
||||
vendor: heltec
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2026 ZephCore
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable hardware stack protection
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
# Enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# Enable UART driver
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
# Enable console
|
||||
CONFIG_CONSOLE=y
|
||||
|
||||
# Build UF2 by default
|
||||
CONFIG_BUILD_OUTPUT_UF2=y
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
Reference in New Issue
Block a user