diff --git a/build.sh b/build.sh index 971699c..78ed719 100644 --- a/build.sh +++ b/build.sh @@ -23,6 +23,7 @@ nRF_boards=( promicro_sx1262 heltec_t114 heltec_t096 + heltec_t1 gat562_30s muziworks_r1neo ) diff --git a/docs/supported_boards.md b/docs/supported_boards.md index 3b41f1a..f81a7b2 100644 --- a/docs/supported_boards.md +++ b/docs/supported_boards.md @@ -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. diff --git a/gen_provider_catalog.py b/gen_provider_catalog.py index 9fb7acb..7e3a9d2 100644 --- a/gen_provider_catalog.py +++ b/gen_provider_catalog.py @@ -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, } diff --git a/zephcore/CMakeLists.txt b/zephcore/CMakeLists.txt index 5841a15..90b2aa7 100644 --- a/zephcore/CMakeLists.txt +++ b/zephcore/CMakeLists.txt @@ -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") diff --git a/zephcore/boards/example_board/README.md b/zephcore/boards/example_board/README.md index 941aa29..7dce460 100644 --- a/zephcore/boards/example_board/README.md +++ b/zephcore/boards/example_board/README.md @@ -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. diff --git a/zephcore/boards/nrf52840/heltec_t1/Kconfig.heltec_t1 b/zephcore/boards/nrf52840/heltec_t1/Kconfig.heltec_t1 new file mode 100644 index 0000000..785ef70 --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/Kconfig.heltec_t1 @@ -0,0 +1,6 @@ +# Copyright (c) 2026 ZephCore +# +# SPDX-License-Identifier: MIT + +config BOARD_HELTEC_T1 + select SOC_NRF52840_QIAA diff --git a/zephcore/boards/nrf52840/heltec_t1/README.md b/zephcore/boards/nrf52840/heltec_t1/README.md new file mode 100644 index 0000000..eda0c30 --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/README.md @@ -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. diff --git a/zephcore/boards/nrf52840/heltec_t1/board.cmake b/zephcore/boards/nrf52840/heltec_t1/board.cmake new file mode 100644 index 0000000..3dc94fb --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/board.cmake @@ -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) diff --git a/zephcore/boards/nrf52840/heltec_t1/board.conf b/zephcore/boards/nrf52840/heltec_t1/board.conf new file mode 100644 index 0000000..c89d47d --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/board.conf @@ -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 diff --git a/zephcore/boards/nrf52840/heltec_t1/board.yml b/zephcore/boards/nrf52840/heltec_t1/board.yml new file mode 100644 index 0000000..41ea55c --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/board.yml @@ -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 diff --git a/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840-pinctrl.dtsi b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840-pinctrl.dtsi new file mode 100644 index 0000000..bfa61bb --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840-pinctrl.dtsi @@ -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 = , + , + ; + }; + }; + + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /* ST7735S TFT — write-only, no MISO on the 8-pin FFC */ + spi3_default: spi3_default { + group1 { + psels = , + ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* UC6580 GNSS */ + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* PAM8904 piezo driver tone input */ + pwm0_default: pwm0_default { + group1 { + psels = ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; diff --git a/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.dts b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.dts new file mode 100644 index 0000000..7a281bb --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.dts @@ -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 +#include +#include +#include +#include +#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 = ; + 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 = ; + 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 = ; + short-codes = ; + long-codes = ; + 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 = ; + tap-codes = ; + 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 = ; +}; + +&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 = ; + zephyr,input-positive = ; + 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 = ; + 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" diff --git a/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.yaml b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.yaml new file mode 100644 index 0000000..9d374ce --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840.yaml @@ -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 diff --git a/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840_defconfig b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840_defconfig new file mode 100644 index 0000000..98c300e --- /dev/null +++ b/zephcore/boards/nrf52840/heltec_t1/heltec_t1_nrf52840_defconfig @@ -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