Files
wadamesh/variants/thinknode_m9/partitions_m9_touch.csv
T
Kaj SchittecatandClaude Fable 5 a38ea1e3bb touch: Elecrow ThinkNode M9 port (ESP32-S3 + LR1110 + I2C QWERTY) — bring-up builds 1-9
New board: ThinkNode_M9_companion_radio_touch env, variants/thinknode_m9/
(board glue, LR1110 target, keyboard driver, partitions, M9_PORT.md pin
reference), boards/thinknode_m9.json, device_caps HAS_THINKNODE_M9 block,
HAS_M9_KEYBOARD input path in the touch UI (d-pad focus nav, tab jump keys,
QWERTY typing).

Based on a contributed bring-up patch by ded (SalishMesh), who also remote-
tested every build on a preproduction unit. Hard-won fixes on top of the
patch, each verified on hardware:

- LR1110 radio init -706: preprod chips run transceiver FW 0x0303, which
  rejects DriveDiosInSleepMode (0x012A, added in FW 0x0308) that RadioLib
  7.x sends unconditionally during begin(). New build-time patch
  scripts/build/patch_radiolib_lr11x0.py tolerates it on old FW;
  radio_init() prints the chip's device/FW/errors either way.
- TCXO: DIO3 at 3.3 V (the patch's active-oscillator/tcxo=0 theory gave
  -707 on hardware).
- Display: rotation 1 (not 3), plus the missing landscape s_ui_rotation
  override so LVGL renders 320x240 instead of portrait-into-landscape.
- Keyboard: the controller is a separate ESP32-S2 I2C slave (0x6C) with
  addressed registers - reads select register 0x01 first (bare reads
  return the HW-version register forever). Boot probe logs the
  controller's HW/FW; backlight duty register wired.
- USB pad release: the keyboard bus lives on GPIO20/21 = the S3's native
  USB D-/D+ pads, owned from reset by the ROM USB-Serial-JTAG (D+ pullup
  on SDA). M9Board::begin() releases them before any bus init.
- GPIO35-37 are octal-PSRAM pins on the S3R8 - never drive them (the
  patch's "SD CS = 36" misread package pin 36 = GPIO48; SD is on the
  shared SPI bus, support returns with PIN_SD_CS=48 later).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 21:49:25 +02:00

1.7 KiB

1# Heltec ThinkNode M9 firmware — custom partition table.
2#
3# 16 MB layout with TWO EQUAL OTA app slots so the firmware can self-update
4# (HTTP OTA via the meshcomod proxy). The app region (app0+app1) is split
5# evenly at 3.875 MB each — the firmware is ~2.55 MB, leaving ~1.3 MB of growth
6# headroom per slot. The tiles + spiffs offsets are UNCHANGED from the previous
7# (single-big-app0) layout, so an OTA — or a one-time USB re-flash to install
8# this table — keeps the map tile cache and all user data (prefs / contacts /
9# channels / chat history) intact.
10# - app0 3.875 MB (ota_0) ┐ equal A/B slots; OTA ping-pongs between them
11# - app1 3.875 MB (ota_1) ┘
12# slippy-tile pack
13# - spiffs 3.375 MB for user data (/new_prefs, /contacts3, /channels2, chat
14# history)
15#
16# Layout (16 MB total):
17# 0x000000–0x009000 bootloader + partition table
18# 0x009000–0x00E000 nvs (20 KB)
19# 0x00E000–0x010000 otadata (8 KB)
20# 0x010000–0x3F0000 app0 (3.875 MB, ota_0)
21# 0x3F0000–0x7D0000 app1 (3.875 MB, ota_1)
22# 0x7D0000–0xC90000 tiles (4.75 MB, LittleFS, type 0x83) [unchanged]
23# 0xC90000–0xFF0000 spiffs (3.375 MB) [unchanged]
24# 0xFF0000–0x1000000 coredump (64 KB)
25# Name, Type, SubType, Offset, Size, Flags
26nvs, data, nvs, 0x9000, 0x5000,
27otadata, data, ota, 0xe000, 0x2000,
28app0, app, ota_0, 0x10000, 0x3E0000,
29app1, app, ota_1, 0x3F0000, 0x3E0000,
30tiles, data, 0x83, 0x7D0000, 0x4C0000,
31spiffs, data, spiffs, 0xC90000, 0x360000,
32coredump, data, coredump, 0xFF0000, 0x10000,