Commit Graph
10 Commits
Author SHA1 Message Date
swaits aca4c3cffd feat(t114): add Heltec Mesh Node T114 board support
Adds nRF52840 + SX1262 + 1.14" 240×135 ST7789 color TFT support. First
color display board in the project; introduces a BoardDisplay trait so
each board renders to its native pixel format and resolution without
aliasing or color-quantization round-trips.

Architecture:
- New BoardDisplay trait (src/display.rs) bundles render_*, present(),
  set_bright/set_dim. Replaces the old DrawTarget<Color=BinaryColor>
  + DisplayBrightness combo as the LoRaBoard::DisplayDriver bound.
- Mono OLED drivers (Sh1106, Ssd1306Async) get adapter impls that
  delegate to the existing display::render module — no behavior change
  for any existing board.
- T114 ST7789 driver (src/driver/st7789.rs) wraps lcd-async (async fork
  of mipidsi) with a 64,800-byte raw byte framebuffer in .bss. Renders
  via lcd_async::raw_framebuf::RawFrameBuf<Rgb565, _>, presents via a
  single async DMA blit (panel.show_raw_data(...).await) — the await
  yields the executor for the ~65 ms SPI transfer so the radio task
  isn't starved during repaints.
- PWM backlight on PWM0 / P0.15 (active-LOW, inverted polarity) for
  smooth dim/bright transitions instead of GPIO toggle.
- Native 240×135 Rgb565 renderer (src/display/render_color.rs) with
  splash + dashboard + sparkline.
- Shared QR-code blit (src/display/qr.rs), generic over PixelColor,
  re-centers the 64×64 bitmap which has cells in cols 0..50 and ~14 px
  of right-side padding — both mono and color splash now show the QR
  with 7 px quiet zones on all four sides (was visibly left-shifted).
- Shared content types (BoardInfo, DashboardCtx) decouple what to draw
  from how each board renders it.
- create_display() now takes the board's full DisplayParts bundle
  (was just the I2C bus) so non-I2C displays can carry SPI + control
  pins through.

Hardware:
- VEXT_ENABLE on P0.21 driven HIGH at boot — powers the SX1262 + TFT
  rail. Without this, lora-phy init succeeds at the SPI level but
  TX_DONE never fires.
- VTFT_CTRL on P0.03, active LOW; backlight on P0.15, active LOW.
- TFT SPI2 (SCK P1.08 / MOSI P1.09) at 8 MHz over EasyDMA. Async
  ExclusiveDevice from embedded-hal-bus (with the 'async' feature).
- lcd-async builder at display_size(135, 240), display_offset(52, 40),
  Deg90 rotation, ColorInversion::Inverted — standard 1.14" ST7789
  die mapping.
- Linker: shared ld/nrf52840-memory.x (S140 SoftDevice preserved at
  0x01000-0x26000 per project policy).
2026-04-30 03:11:36 -06:00
swaits 4d723a85ce fix(boards): BUSY pin pull-down → none on nRF SX1262 boards
SX1262's BUSY pin has an internal 20 kΩ pull-up (datasheet page 53).
Our Input::new(..., Pull::Down) on BUSY creates contention with that
internal pull-up, leaving BUSY at an indeterminate voltage. This can
cause wait_on_busy to mis-read the chip's ready state — sometimes
commands land while the chip is still busy (ignored or corrupted),
which manifests as TX_DONE never firing on DIO1 because the SX1262
never actually completed the SetTx it received during BUSY=high.

Fix per lora-rs/lora-rs#260: Pull::Down → Pull::None on BUSY.
Matches the official lora-rs nRF52840 examples.

Applied to both Wio Tracker L1 (reported broken by @swaits today) and
RAK4631 (currently works for us, but was affected by the same class
of bug per the upstream issue — this makes it deterministically
correct rather than 'happens to work').
2026-04-24 01:34:32 -06:00
swaits f9582c0b94 style: cargo fmt 2026-04-16 13:25:19 -06:00
swaits 41b5775268 refactor: unify SimpleLed via embedded-hal, remove Option<L> from BoardParts
- Added embedded-hal 1.0 as direct dep (already transitive via embedded-hal-async)
- SimpleLed<P: OutputPin> now generic over any HAL — single definition in driver/
- Removed duplicate SimpleLed from board/esp32s3.rs and board/wio_tracker_l1.rs
- Changed BoardParts.led from Option<L> to L — boards with no LED use ()
- Display task calls led.set_rgb() unconditionally (no-op for () boards)
- RAK board: led: () instead of led: None
2026-04-07 12:40:55 -06:00
swaits f9117d71c8 fix: Wio Tracker LED on P1.01, move SimpleLed to board layer
Per the Wio Tracker L1 schematic, it has a green LED on P1.01.
Moved SimpleLed from driver/ to board layer (esp32s3.rs and
wio_tracker_l1.rs) since the impl needs HAL-specific Output types.
Removed driver/simple_led.rs — each board layer defines its own.
RAK WisBlock remains LedDriver=() (no user LED on the core module).
2026-04-07 12:20:20 -06:00
swaits 5ac4b73739 feat: RGB LED support — blinks green on RX, red on TX
- Added RgbLed trait with impl on () for boards without LED
- Added WS2812 driver (driver/ws2812.rs) using ESP32-S3 RMT peripheral
  - 80MHz clock, 12.5ns resolution, 24-bit GRB encoding
  - Zero extra crate dependencies
- Heltec V3/V3-UART/V4: WS2812B on GPIO38 via RMT channel 0
- RAK WisBlock/Wio Tracker: type LedDriver = (), led = None (no-op)
- Display task: green blink on RX packet, red blink on TX packet
- LED auto-off on timer tick (~1s), off when display is off/reset
- LoRaBoard trait gains type LedDriver: RgbLed associated type
- BoardParts gains led: Option<L> field
2026-04-07 11:18:30 -06:00
swaits ecc451affe refactor: LoRaBoard trait with full associated types + BoardParts
- LoRaBoard trait now has associated types: RadioParts, CommParts, DisplayParts, DisplayDriver
- into_parts() is on the trait (enforced by compiler, not implicit convention)
- BoardParts<R, C, D> struct replaces tuple return from into_parts()
- mac_address() stays on trait, MAC also in BoardParts for convenience
- Removed mac field from DisplayParts (display task calls Board::mac_address())
- DisplayDriver associated type requires DrawTarget<Color = BinaryColor>
2026-04-07 09:50:50 -06:00
swaits 7a54c4dff3 refactor: board-owned display init, zero cfg in application code
- Each board now exports DisplayDriver type and create_display() async fn
- ESP32-S3 boards share SSD1306 create_display in board/esp32s3.rs
- RAK WisBlock has its own SSD1306 create_display (different I2C type)
- Wio Tracker has SH1106 create_display (different display IC)
- Removed all cfg_if from display.rs — calls board::create_display()
- Removed display init retry logic (single attempt, return None on failure)
- ZERO board-specific #[cfg(feature)] outside board/, host/mod.rs, and hal/
2026-04-07 09:46:25 -06:00
swaits fb334118fd refactor: extract hal/ and driver/ modules
- Created hal/esp32s3.rs with MCU primitives (SPI, I2C, USB, UART, timer, MAC)
- Created hal/nrf52840.rs with shared nRF boilerplate (interrupts, bus wrapping, VBUS, MAC)
- Moved SH1106 OLED driver from display/ to driver/ (clear separation from app code)
- Board esp32s3.rs now delegates MCU init to hal, keeps only peripheral wiring (RadioParts)
- nRF board files use hal for shared StaticCell patterns, mac_address, interrupt bindings
- Board files still own pin assignments and peripheral construction
2026-04-07 09:38:56 -06:00
swaits 38684482e8 WIP: functional checkpoint! 2026-04-06 21:15:35 -06:00