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>
53 lines
2.6 KiB
Python
53 lines
2.6 KiB
Python
# Patches the vendored RadioLib so LR11x0::config() tolerates old LR1110
|
|
# transceiver firmware that predates DriveDiosInSleepMode (opcode 0x012A,
|
|
# added in the 0x0308 firmware release). RadioLib >= 7.x sends it
|
|
# unconditionally during begin(); older chip firmware answers CMD_PERR,
|
|
# which turns an otherwise healthy radio.begin() into -706
|
|
# (RADIOLIB_ERR_SPI_CMD_INVALID). Preproduction Elecrow ThinkNode M9 units
|
|
# ship with such firmware (Meshtastic works on them only because it pins an
|
|
# older RadioLib that doesn't send the command).
|
|
#
|
|
# The command is an optional nicety (stops DIO glitches in sleep mode), so
|
|
# skipping it on old firmware is safe.
|
|
#
|
|
# Idempotent. Each PlatformIO env has its own libdeps copy, so this only
|
|
# affects envs that list this script in extra_scripts (the M9 env).
|
|
# NOTE: on a completely fresh checkout the first build may run before
|
|
# RadioLib is downloaded - the script then warns and the patch lands on the
|
|
# next build. Re-run `pio run` once if you see the warning.
|
|
Import("env")
|
|
import os
|
|
|
|
MARKER = "wadamesh-lr1110-oldfw-patch"
|
|
OLD = """ state = this->driveDiosInSleepMode(true);
|
|
RADIOLIB_ASSERT(state);"""
|
|
NEW = """ state = this->driveDiosInSleepMode(true);
|
|
// wadamesh-lr1110-oldfw-patch: LR1110 transceiver FW older than 0x0308
|
|
// doesn't implement DriveDiosInSleepMode (0x012A) and answers CMD_PERR,
|
|
// which would abort init (-706) on an otherwise healthy radio. The command
|
|
// only stops DIO glitches in sleep mode - safe to skip on old firmware.
|
|
if(state == RADIOLIB_ERR_SPI_CMD_INVALID) {
|
|
RADIOLIB_DEBUG_BASIC_PRINTLN("DriveDiosInSleepMode unsupported (old LR11x0 FW), skipping");
|
|
state = RADIOLIB_ERR_NONE;
|
|
}
|
|
RADIOLIB_ASSERT(state);"""
|
|
|
|
path = os.path.join(env.subst("$PROJECT_LIBDEPS_DIR"), env.subst("$PIOENV"),
|
|
"RadioLib", "src", "modules", "LR11x0", "LR11x0.cpp")
|
|
|
|
if not os.path.isfile(path):
|
|
print("[patch_radiolib_lr11x0] WARNING: %s not found (libdeps not fetched yet?)" % path)
|
|
print("[patch_radiolib_lr11x0] WARNING: RadioLib NOT patched - re-run the build once libdeps exist")
|
|
else:
|
|
with open(path) as f:
|
|
src = f.read()
|
|
if MARKER in src:
|
|
print("[patch_radiolib_lr11x0] already patched")
|
|
elif OLD in src:
|
|
with open(path, "w") as f:
|
|
f.write(src.replace(OLD, NEW, 1))
|
|
print("[patch_radiolib_lr11x0] patched LR11x0::config() for old-FW tolerance")
|
|
else:
|
|
print("[patch_radiolib_lr11x0] WARNING: pattern not found - RadioLib version drift?")
|
|
print("[patch_radiolib_lr11x0] WARNING: check LR11x0::config() by hand, NOT patched")
|