mirror of
https://github.com/pelgraine/Meck.git
synced 2026-08-06 08:42:48 +02:00
T-Echo Card: apply hardware findings from Meshtastic PR #10267.
Incorporates hardware-specific learnings from caveman99's Meshtastic T-Echo Card support PR (meshtastic/firmware#10267), cross-referenced against LilyGo's official t_echo_card_config.h pinmap. Battery (critical): - Add BATTERY_MEASUREMENT_CONTROL pin P0.31 — gates the resistive voltage divider feeding AIN0. Without toggling this pin, battery ADC reads are invalid (floating divider input). - TechoCardBoard::getBatteryVoltage() now drives P0.31 HIGH before SAADC read and LOW after to avoid parasitic drain. Display (critical): - Add OLED_DISPLAY_OFFSET = 24 for the SSD1315 72×40 panel. The physical display is mapped at GDDRAM pages 3–7 (rows 24–63); SETDISPLAYOFFSET and SETMULTIPLEX commands are sent after display.begin() in target.cpp to shift the visible window. Power rail (high priority): - RT9080 3V3 LDO now gets a clean HIGH→LOW→HIGH reset cycle with 100ms dwell in board.begin(), preventing brown-out when LoRa TX fires at +22 dBm after a soft reset.
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
// =============================================================================
|
||||
// TechoCardBoard — Implementation for LilyGo T-Echo Card
|
||||
//
|
||||
// Patches applied from Meshtastic PR #10267 (caveman99):
|
||||
// 1. RT9080 power rail reset cycle in begin() — prevents LoRa TX brown-out
|
||||
// 2. Battery measurement control pin (P0.31) — enables voltage divider
|
||||
// 3. WS2812 NeoPixel implementation via Adafruit_NeoPixel
|
||||
// =============================================================================
|
||||
|
||||
#include "TechoCardBoard.h"
|
||||
@@ -11,6 +16,49 @@
|
||||
void TechoCardBoard::begin() {
|
||||
NRF52BoardDCDC::begin();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// RT9080 3V3 rail: clean reset cycle
|
||||
//
|
||||
// From Meshtastic PR #10267 (earlyInitVariant): if the nRF52840 was in a
|
||||
// half-enabled state from a previous soft reset, the RT9080 LDO can be in
|
||||
// an indeterminate state. Toggling EN HIGH→LOW→HIGH with 100ms dwell
|
||||
// forces a clean power-on. Without this, the 3V3 rail can brown-out when
|
||||
// LoRa TX fires at full power (+22 dBm).
|
||||
// -------------------------------------------------------------------------
|
||||
#if PIN_OLED_EN >= 0
|
||||
pinMode(PIN_OLED_EN, OUTPUT);
|
||||
digitalWrite(PIN_OLED_EN, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(PIN_OLED_EN, LOW);
|
||||
delay(100);
|
||||
digitalWrite(PIN_OLED_EN, HIGH);
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Park peripheral enable pins LOW before the rest of setup runs.
|
||||
// Prevents peripherals from sinking current while the 3V3 rail is ramping.
|
||||
// (Adapted from Meshtastic PR #10267 earlyInitVariant)
|
||||
// -------------------------------------------------------------------------
|
||||
#if defined(HAS_GPS) && PIN_GPS_EN >= 0
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
#endif
|
||||
#if defined(HAS_GPS) && PIN_GPS_RF_EN >= 0
|
||||
pinMode(PIN_GPS_RF_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_RF_EN, LOW);
|
||||
#endif
|
||||
#if defined(HAS_BUZZER) && PIN_BUZZER >= 0
|
||||
pinMode(PIN_BUZZER, OUTPUT);
|
||||
digitalWrite(PIN_BUZZER, LOW);
|
||||
#endif
|
||||
|
||||
// Configure battery measurement control pin
|
||||
#if defined(BATTERY_MEASUREMENT_CONTROL)
|
||||
pinMode(BATTERY_MEASUREMENT_CONTROL, OUTPUT);
|
||||
digitalWrite(BATTERY_MEASUREMENT_CONTROL, !BATTERY_MEASUREMENT_ACTIVE);
|
||||
#endif
|
||||
|
||||
// Configure battery ADC pin as analog input
|
||||
pinMode(PIN_VBAT_READ, INPUT);
|
||||
|
||||
@@ -18,29 +66,31 @@ void TechoCardBoard::begin() {
|
||||
pinMode(PIN_BUTTON_A, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON_BOOT, INPUT_PULLUP);
|
||||
|
||||
// Buzzer off
|
||||
#if defined(HAS_BUZZER) && PIN_BUZZER >= 0
|
||||
pinMode(PIN_BUZZER, OUTPUT);
|
||||
digitalWrite(PIN_BUZZER, LOW);
|
||||
#endif
|
||||
|
||||
// RGB LED off at boot
|
||||
// Initialise WS2812 NeoPixels (3 independent LEDs, all off at boot)
|
||||
#if defined(HAS_RGB_LED)
|
||||
ledOff();
|
||||
_pixel_power.begin();
|
||||
_pixel_power.clear();
|
||||
_pixel_power.show();
|
||||
|
||||
_pixel_notify.begin();
|
||||
_pixel_notify.clear();
|
||||
_pixel_notify.show();
|
||||
|
||||
_pixel_pairing.begin();
|
||||
_pixel_pairing.clear();
|
||||
_pixel_pairing.show();
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Battery voltage reading via nRF52840 SAADC
|
||||
//
|
||||
// The T-Echo Card has a voltage divider on AIN0 (P0.02).
|
||||
// nRF52840 SAADC: 12-bit, internal 0.6V reference, configurable gain.
|
||||
// With 1/6 gain: input range 0–3.6V. Multiply by divider ratio (ADC_MULTIPLIER).
|
||||
// The T-Echo Card has a gated voltage divider on AIN0 (P0.02).
|
||||
// BATTERY_MEASUREMENT_CONTROL (P0.31) must be driven HIGH to enable the
|
||||
// divider before reading, and LOW after to avoid parasitic drain.
|
||||
//
|
||||
// NOTE: The T-Echo Lite has a known issue reading 100% / 6.00V constantly.
|
||||
// This is likely caused by incorrect SAADC configuration (wrong gain, wrong
|
||||
// reference, or the pin being pulled high by the charging circuit).
|
||||
// We use explicit SAADC register programming to avoid that issue.
|
||||
// nRF52840 SAADC: 12-bit, internal 0.6V reference, 1/6 gain.
|
||||
// With 1/6 gain: input range 0–3.6V. Multiply by divider ratio (ADC_MULTIPLIER).
|
||||
// -----------------------------------------------------------------------------
|
||||
float TechoCardBoard::getBatteryVoltage() {
|
||||
uint32_t now = millis();
|
||||
@@ -50,6 +100,12 @@ float TechoCardBoard::getBatteryVoltage() {
|
||||
return _cached_battery_mv;
|
||||
}
|
||||
|
||||
// Enable battery voltage divider
|
||||
#if defined(BATTERY_MEASUREMENT_CONTROL)
|
||||
digitalWrite(BATTERY_MEASUREMENT_CONTROL, BATTERY_MEASUREMENT_ACTIVE);
|
||||
delay(5); // Allow divider to settle
|
||||
#endif
|
||||
|
||||
// Configure SAADC for single-shot reading
|
||||
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_12bit;
|
||||
|
||||
@@ -91,6 +147,11 @@ float TechoCardBoard::getBatteryVoltage() {
|
||||
// Disable SAADC to save power
|
||||
NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Disabled;
|
||||
|
||||
// Disable battery voltage divider to save power
|
||||
#if defined(BATTERY_MEASUREMENT_CONTROL)
|
||||
digitalWrite(BATTERY_MEASUREMENT_CONTROL, !BATTERY_MEASUREMENT_ACTIVE);
|
||||
#endif
|
||||
|
||||
// Convert: voltage = (result / 4096) * 3.6V * ADC_MULTIPLIER * 1000 (mV)
|
||||
if (result < 0) result = 0;
|
||||
float voltage_mv = ((float)result / 4096.0f) * 3600.0f * _adc_multiplier;
|
||||
@@ -137,14 +198,24 @@ void TechoCardBoard::enableSpeaker(bool enable) {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RGB LED — WS2812 via NeoPixel protocol
|
||||
// Simple bit-bang implementation for nRF52840 at 64MHz
|
||||
// RGB LEDs — WS2812 via Adafruit_NeoPixel
|
||||
//
|
||||
// Three independent WS2812s on separate data pins (not a chain).
|
||||
// Each is a 1-pixel NeoPixel strand.
|
||||
//
|
||||
// setLED() drives all three to the same colour (legacy interface).
|
||||
// For per-LED control, use setStatusLED() with a role index.
|
||||
// -----------------------------------------------------------------------------
|
||||
void TechoCardBoard::setLED(uint8_t r, uint8_t g, uint8_t b) {
|
||||
#if defined(HAS_RGB_LED)
|
||||
// TODO: Implement WS2812 bit-bang or use Adafruit_NeoPixel library
|
||||
// For initial bringup, just use the Adafruit_NeoPixel library
|
||||
// which is available in the Adafruit nRF52 Arduino core
|
||||
uint32_t color = Adafruit_NeoPixel::Color(r, g, b);
|
||||
_pixel_power.setPixelColor(0, color);
|
||||
_pixel_power.show();
|
||||
_pixel_notify.setPixelColor(0, color);
|
||||
_pixel_notify.show();
|
||||
_pixel_pairing.setPixelColor(0, color);
|
||||
_pixel_pairing.show();
|
||||
#else
|
||||
(void)r; (void)g; (void)b;
|
||||
#endif
|
||||
}
|
||||
@@ -153,6 +224,27 @@ void TechoCardBoard::ledOff() {
|
||||
setLED(0, 0, 0);
|
||||
}
|
||||
|
||||
void TechoCardBoard::setStatusLED(uint8_t led_index, uint32_t color) {
|
||||
#if defined(HAS_RGB_LED)
|
||||
switch (led_index) {
|
||||
case 0: // Power / charge
|
||||
_pixel_power.setPixelColor(0, color);
|
||||
_pixel_power.show();
|
||||
break;
|
||||
case 1: // Notification / mesh activity
|
||||
_pixel_notify.setPixelColor(0, color);
|
||||
_pixel_notify.show();
|
||||
break;
|
||||
case 2: // BLE pairing
|
||||
_pixel_pairing.setPixelColor(0, color);
|
||||
_pixel_pairing.show();
|
||||
break;
|
||||
}
|
||||
#else
|
||||
(void)led_index; (void)color;
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Buzzer — PWM tone generation
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
// TechoCardBoard — Board class for LilyGo T-Echo Card
|
||||
//
|
||||
// Extends NRF52BoardDCDC with:
|
||||
// - Battery ADC (AIN0, P0.02) with solar charging via BQ25896
|
||||
// - Battery ADC (AIN0, P0.02) with gated voltage divider (P0.31)
|
||||
// - Solar charging via BQ25896
|
||||
// - GPS power control (L76K)
|
||||
// - Speaker/mic enable
|
||||
// - RGB LED control
|
||||
// - WS2812 RGB LEDs (3 independent, via Adafruit_NeoPixel)
|
||||
// - Buzzer
|
||||
// - NFC NDEF contact sharing
|
||||
// =============================================================================
|
||||
@@ -16,6 +17,11 @@
|
||||
#include <helpers/NRF52Board.h>
|
||||
#include "variant.h"
|
||||
|
||||
// WS2812 NeoPixel support — 3 independent LEDs on separate GPIOs
|
||||
#if defined(HAS_RGB_LED)
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#endif
|
||||
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
// Power management config for T-Echo Card
|
||||
// AIN0 (P0.02) for battery voltage sensing
|
||||
@@ -33,6 +39,13 @@ private:
|
||||
uint32_t _last_battery_read;
|
||||
float _cached_battery_mv;
|
||||
|
||||
// Three independent WS2812 NeoPixels (1 LED per strand)
|
||||
#if defined(HAS_RGB_LED)
|
||||
Adafruit_NeoPixel _pixel_power = Adafruit_NeoPixel(1, PIN_RGB_LED_1, NEO_GRB + NEO_KHZ800);
|
||||
Adafruit_NeoPixel _pixel_notify = Adafruit_NeoPixel(1, PIN_RGB_LED_2, NEO_GRB + NEO_KHZ800);
|
||||
Adafruit_NeoPixel _pixel_pairing = Adafruit_NeoPixel(1, PIN_RGB_LED_3, NEO_GRB + NEO_KHZ800);
|
||||
#endif
|
||||
|
||||
public:
|
||||
TechoCardBoard()
|
||||
: _adc_multiplier(ADC_MULTIPLIER),
|
||||
@@ -53,10 +66,14 @@ public:
|
||||
// Speaker power control
|
||||
void enableSpeaker(bool enable);
|
||||
|
||||
// RGB LED
|
||||
// RGB LEDs — all three to same colour (legacy interface)
|
||||
void setLED(uint8_t r, uint8_t g, uint8_t b);
|
||||
void ledOff();
|
||||
|
||||
// Per-LED status control (0=power, 1=notify, 2=pairing)
|
||||
// colour is packed 0xRRGGBB — use NEOPIXEL_COLOR_* defines from variant.h
|
||||
void setStatusLED(uint8_t led_index, uint32_t color);
|
||||
|
||||
// Buzzer
|
||||
void buzz(uint16_t freq_hz, uint16_t duration_ms);
|
||||
|
||||
|
||||
@@ -7,14 +7,18 @@
|
||||
// Only needed if creating a custom board variant inside the Adafruit nRF52
|
||||
// Arduino framework package. If using build flag overrides in platformio.ini,
|
||||
// this file is optional.
|
||||
//
|
||||
// Pin mapping cross-referenced against:
|
||||
// - LilyGo official: T-Echo-Card/libraries/private_library/t_echo_card_config.h
|
||||
// - Meshtastic PR #10267 (caveman99 T-Echo-Card support)
|
||||
// =============================================================================
|
||||
|
||||
// On nRF52840, Arduino digital pin numbers map 1:1 to nRF GPIO numbers
|
||||
// (0–47 for port 0 and port 1).
|
||||
|
||||
// LED
|
||||
// LED — WS2812 addressable (no plain GPIO LED on this board)
|
||||
#define LED_BUILTIN PIN_LED1
|
||||
#define PIN_LED1 39 // WS2812 RGB LED data (1, 7)
|
||||
#define PIN_LED1 39 // WS2812 RGB LED data 1 (1, 7)
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// Buttons
|
||||
@@ -39,11 +43,15 @@
|
||||
// Analog
|
||||
#define PIN_A0 2 // (0, 2) — Battery ADC / AIN0
|
||||
|
||||
// QSPI Flash (ZD25WQ32CEIGR 4MB)
|
||||
// nRF52840 QSPI uses fixed pins — framework handles these
|
||||
// #define PIN_QSPI_SCK 19 // Conflict with GPS TX — check if QSPI is on different pins
|
||||
// NOTE: QSPI pin mapping needs verification on actual hardware.
|
||||
// The T-Echo Card may use SPI (not QSPI) for external flash.
|
||||
// QSPI Flash — ZD25WQ32CEIGR 4MB
|
||||
// Confirmed from LilyGo t_echo_card_config.h and Meshtastic PR #10267.
|
||||
// These are on a dedicated SPI bus, separate from LoRa SPI.
|
||||
#define PIN_QSPI_SCK 4 // (0, 4)
|
||||
#define PIN_QSPI_CS 12 // (0, 12)
|
||||
#define PIN_QSPI_IO0 6 // (0, 6) — MOSI / D0
|
||||
#define PIN_QSPI_IO1 8 // (0, 8) — MISO / D1
|
||||
#define PIN_QSPI_IO2 41 // (1, 9) — WP / D2
|
||||
#define PIN_QSPI_IO3 26 // (0, 26) — HOLD / D3
|
||||
|
||||
// NFC (dedicated nRF52840 NFC pins — not GPIO-assignable)
|
||||
// NFC1 = P0.09, NFC2 = P0.10
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
; + MAX98357 Speaker + MP34DT05 PDM Mic + ICM20948 IMU + Solar + NFC
|
||||
;
|
||||
; Platform: nRF52 (Adafruit nRF52 Arduino)
|
||||
;
|
||||
; Patches applied from Meshtastic PR #10267 (caveman99):
|
||||
; - Adafruit_NeoPixel added for WS2812 RGB LED support
|
||||
; =============================================================================
|
||||
|
||||
; --- Base configuration for all T-Echo Card builds ---
|
||||
@@ -57,6 +60,7 @@ build_src_filter = ${nrf52_base.build_src_filter}
|
||||
lib_deps = ${nrf52_base.lib_deps}
|
||||
olikraus/U8g2 @ ^2.35.19
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
adafruit/Adafruit NeoPixel @ ^1.12.3
|
||||
|
||||
; =============================================================================
|
||||
; Build Environments
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
// =============================================================================
|
||||
// MeshCore target implementation for LilyGo T-Echo Card
|
||||
//
|
||||
// nRF52840 + SX1262 (HPB16B3 module) + SSD1315 OLED + L76K GPS
|
||||
// nRF52840 + SX1262 (HPB16B3 / S62F module) + SSD1315 OLED + L76K GPS
|
||||
//
|
||||
// Patches applied from Meshtastic PR #10267 (caveman99):
|
||||
// - RT9080 power rail reset cycle (handled in board.begin())
|
||||
// - SSD1315 OLED display offset for 72×40 panel
|
||||
// - SX1262 TCXO voltage via DIO3
|
||||
// =============================================================================
|
||||
|
||||
#include "target.h"
|
||||
@@ -40,27 +45,27 @@ mesh::DataStore data_store;
|
||||
|
||||
// --- Target initialization ---
|
||||
void target_setup() {
|
||||
// Enable OLED power
|
||||
#if PIN_OLED_EN >= 0
|
||||
pinMode(PIN_OLED_EN, OUTPUT);
|
||||
digitalWrite(PIN_OLED_EN, HIGH);
|
||||
delay(10);
|
||||
#endif
|
||||
// -------------------------------------------------------------------------
|
||||
// Board-level init FIRST — this cycles the RT9080 3V3 rail and parks
|
||||
// peripheral enable pins LOW. Must happen before any other peripheral
|
||||
// access to prevent brown-out on LoRa TX.
|
||||
// -------------------------------------------------------------------------
|
||||
board.begin();
|
||||
|
||||
// Enable GPS power
|
||||
// -------------------------------------------------------------------------
|
||||
// Enable GPS power (was parked LOW in board.begin())
|
||||
// -------------------------------------------------------------------------
|
||||
#if defined(HAS_GPS) && PIN_GPS_EN >= 0
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, HIGH);
|
||||
delay(10);
|
||||
#endif
|
||||
|
||||
// GPS RF/LNA enable
|
||||
#if defined(HAS_GPS) && PIN_GPS_RF_EN >= 0
|
||||
pinMode(PIN_GPS_RF_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_RF_EN, HIGH);
|
||||
#endif
|
||||
|
||||
// Initialize GPS UART
|
||||
// Initialise GPS UART
|
||||
#if defined(HAS_GPS)
|
||||
Serial1.setPins(PIN_GPS_RX, PIN_GPS_TX);
|
||||
Serial1.begin(GPS_BAUDRATE);
|
||||
@@ -76,20 +81,54 @@ void target_setup() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Initialize I2C
|
||||
// Initialise I2C
|
||||
Wire.setPins(I2C_SDA, I2C_SCL);
|
||||
Wire.begin();
|
||||
Wire.setClock(400000);
|
||||
|
||||
// Initialize display
|
||||
// -------------------------------------------------------------------------
|
||||
// Initialise display
|
||||
//
|
||||
// The SSD1315 has a 128×64 GDDRAM but the physical panel is 72×40,
|
||||
// hardwired at columns 28–99, pages 3–7 (rows 24–63).
|
||||
//
|
||||
// After the driver's standard init, we send SETDISPLAYOFFSET = 24 to
|
||||
// shift the COM output mapping so that data written to pages 0–4
|
||||
// appears on the physical display.
|
||||
//
|
||||
// If content is still blank or shifted when hardware arrives, the
|
||||
// alternative is to modify the PAGEADDR writes in the display() method
|
||||
// to target pages 3–7 directly (as Meshtastic does with setYOffset(3)).
|
||||
// -------------------------------------------------------------------------
|
||||
#ifdef DISPLAY_CLASS
|
||||
display.begin(OLED_I2C_ADDR);
|
||||
|
||||
#if defined(OLED_DISPLAY_OFFSET) && OLED_DISPLAY_OFFSET > 0
|
||||
// SSD1306/SSD1315 command 0xD3: Set Display Offset
|
||||
// Shifts COM output by OLED_DISPLAY_OFFSET rows (24 = 3 pages)
|
||||
display.sendCommand(0xD3); // SETDISPLAYOFFSET
|
||||
display.sendCommand(OLED_DISPLAY_OFFSET);
|
||||
|
||||
// SSD1306/SSD1315 command 0xA8: Set Multiplex Ratio
|
||||
// Must match actual panel height (40 - 1 = 39)
|
||||
display.sendCommand(0xA8); // SETMULTIPLEX
|
||||
display.sendCommand(OLED_HEIGHT - 1); // 39
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Board-level init
|
||||
board.begin();
|
||||
|
||||
// Initialize LoRa radio
|
||||
// -------------------------------------------------------------------------
|
||||
// Initialise LoRa radio
|
||||
// -------------------------------------------------------------------------
|
||||
// SX1262 DIO2 as RF switch control (common for HPB16B3 modules)
|
||||
radio_driver.setDio2AsRfSwitch(true);
|
||||
|
||||
// SX1262 TCXO via DIO3
|
||||
// Meshtastic PR #10267 sets this to 1.8V. If the module has a TCXO
|
||||
// powered by DIO3, this must be configured before any frequency setting
|
||||
// or the oscillator won't start, causing frequency drift or init failure.
|
||||
// TODO: Verify on hardware. If the module uses a crystal (not TCXO),
|
||||
// remove this call — it would waste current on DIO3.
|
||||
#if defined(SX126X_DIO3_TCXO_VOLTAGE)
|
||||
radio_driver.setTCXO(SX126X_DIO3_TCXO_VOLTAGE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
// + MP34DT05 PDM Microphone + ICM20948 IMU + BQ25896 Charger + Solar
|
||||
//
|
||||
// Pin notation from LilyGo pinmap: (port, pin) → nRF GPIO = port*32 + pin
|
||||
//
|
||||
// Cross-referenced against:
|
||||
// - LilyGo official: T-Echo-Card/libraries/private_library/t_echo_card_config.h
|
||||
// - Meshtastic PR #10267 (caveman99 T-Echo-Card support)
|
||||
// =============================================================================
|
||||
|
||||
#define LILYGO_TECHO_CARD
|
||||
@@ -30,14 +34,24 @@
|
||||
#define P_LORA_BUSY 14 // (0, 14) — BUSY
|
||||
#define P_LORA_DIO_1 40 // (1, 8) — DIO1 / interrupt
|
||||
|
||||
// RF switch control (HPB16B3 module)
|
||||
#define LORA_DIO2 5 // (0, 5) — DIO2 (TXCO / RF switch)
|
||||
#define LORA_RF_VC1 27 // (0, 27) — RF_VC1
|
||||
#define LORA_RF_VC2 33 // (1, 1) — RF_VC2
|
||||
// RF switch control (HPB16B3 / S62F module)
|
||||
// DIO2 is used internally by the SX1262 for RF switch control.
|
||||
// RF_VC1 / RF_VC2 are external PA/LNA select lines.
|
||||
// Meshtastic PR #10267 maps these as TXEN/RXEN — verify on hardware
|
||||
// whether DIO2-as-RF-switch alone is sufficient, or if VC1/VC2 are also
|
||||
// needed for full TX/RX performance.
|
||||
#define LORA_DIO2 5 // (0, 5) — DIO2 (RF switch / TXCO)
|
||||
#define LORA_RF_VC1 27 // (0, 27) — RF_VC1 (potential TXEN)
|
||||
#define LORA_RF_VC2 33 // (1, 1) — RF_VC2 (potential RXEN)
|
||||
|
||||
// LoRa radio power enable (from schematic: LORA_EN drives RT9080 for LORA_VDD)
|
||||
// NOTE: Confirm actual GPIO — pinmap shows dedicated enable pin
|
||||
// For now use -1 if always powered
|
||||
// SX1262 TCXO voltage via DIO3
|
||||
// Meshtastic PR #10267 sets this to 1.8V. Without it, the TCXO may not
|
||||
// start and the radio will have frequency drift or fail to init.
|
||||
// Confirm on hardware — if the module has a TCXO fed by DIO3, this is needed.
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8f
|
||||
|
||||
// LoRa radio power: RT9080 controls the 3V3 rail for all peripherals
|
||||
// including LoRa. No dedicated LoRa power enable pin.
|
||||
#define PIN_LORA_EN -1
|
||||
|
||||
// Default radio settings (Australia)
|
||||
@@ -47,6 +61,21 @@
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 0.42" OLED Display — SSD1315 (SSD1306-compatible), 72×40, I2C
|
||||
//
|
||||
// The SSD1315 has a 128×64 GDDRAM, but the physical panel is only 72×40.
|
||||
// The visible window is mapped at columns 28–99, pages 3–7 (rows 24–63).
|
||||
// This means:
|
||||
// - Horizontal: auto-centred by driver ((128 - 72) / 2 = 28)
|
||||
// - Vertical: need SETDISPLAYOFFSET = 24 (3 pages × 8 rows) so that
|
||||
// data written to pages 0–4 appears on the physical display.
|
||||
//
|
||||
// If the MeshCore OLEDDisplay driver's display() method sends PAGEADDR
|
||||
// starting at page 0, the SETDISPLAYOFFSET command should handle the
|
||||
// mapping. If content appears shifted or blank, the alternative is to
|
||||
// modify the PAGEADDR commands to write to pages 3–7 directly.
|
||||
//
|
||||
// Ref: Meshtastic PR #10267 uses setYOffset(3) to shift every PAGEADDR
|
||||
// write, plus GEOMETRY_72_40 which sets SETMULTIPLEX to 39.
|
||||
// -----------------------------------------------------------------------------
|
||||
#define HAS_OLED 1
|
||||
#define OLED_I2C_ADDR 0x3C
|
||||
@@ -55,7 +84,12 @@
|
||||
#define OLED_SDA I2C_SDA
|
||||
#define OLED_SCL I2C_SCL
|
||||
|
||||
// OLED power control via RT9080 enable pin
|
||||
// SSD1315 display offset: 3 pages = 24 rows
|
||||
// Applied via SETDISPLAYOFFSET (0xD3) after display.begin() in target.cpp
|
||||
#define OLED_DISPLAY_OFFSET 24
|
||||
|
||||
// OLED / peripheral power control via RT9080 enable pin
|
||||
// This controls the 3V3 rail for OLED, GPS, LoRa, and sensors.
|
||||
#define PIN_OLED_EN 30 // (0, 30) — RT9080_EN
|
||||
|
||||
// No hardware reset pin for OLED on T-Echo Card
|
||||
@@ -80,11 +114,18 @@
|
||||
#define BATTERY_ADC_AIN 0 // nRF SAADC AIN channel number
|
||||
#define BATTERY_CAPACITY_MAH 800
|
||||
|
||||
// Battery voltage divider enable gate
|
||||
// P0.31 controls a FET/switch that enables the resistive divider feeding
|
||||
// AIN0. Must be driven HIGH before ADC read and LOW after to avoid
|
||||
// parasitic drain through the divider.
|
||||
// Source: LilyGo t_echo_card_config.h → BATTERY_MEASUREMENT_CONTROL
|
||||
// Confirmed: Meshtastic PR #10267 → ADC_CTRL (0 + 31), ADC_CTRL_ENABLED HIGH
|
||||
#define BATTERY_MEASUREMENT_CONTROL 31 // (0, 31)
|
||||
#define BATTERY_MEASUREMENT_ACTIVE HIGH
|
||||
|
||||
// Battery voltage divider calibration
|
||||
// The T-Echo Lite has issues reading battery correctly — we'll need to
|
||||
// calibrate this with actual hardware. Starting with a reasonable default.
|
||||
// nRF52840 SAADC: 0.6V internal ref, 1/6 gain → 0–3.6V range
|
||||
// If there's a voltage divider (e.g. 2:1), multiply by 2.
|
||||
// With 2:1 resistive divider, multiply by 2 to get actual cell voltage.
|
||||
// Adjust ADC_MULTIPLIER after measuring real voltage vs ADC reading.
|
||||
#ifndef ADC_MULTIPLIER
|
||||
#define ADC_MULTIPLIER 2.0f
|
||||
@@ -132,13 +173,28 @@
|
||||
#define PIN_BUZZER 38 // (1, 6) — piezo buzzer data / PWM
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// WS2812 RGB LED (3 LEDs in series)
|
||||
// WS2812 RGB LEDs — 3 independent LEDs on separate data lines (NOT a chain)
|
||||
//
|
||||
// Confirmed by Meshtastic PR #10267: each WS2812 is on its own GPIO,
|
||||
// driven as a 1-pixel NeoPixel strand. The bare-die WS2812s are very
|
||||
// bright at full intensity — scale to ~25% (0x40 max per channel).
|
||||
//
|
||||
// Role assignments (matching Meshtastic PR #10267):
|
||||
// DATA_1 (P1.7) → power/charge status (red)
|
||||
// DATA_2 (P1.12) → notification / mesh activity (green)
|
||||
// DATA_3 (P0.28) → BLE pairing status (blue)
|
||||
// -----------------------------------------------------------------------------
|
||||
#define HAS_RGB_LED 1
|
||||
#define PIN_RGB_LED_1 39 // (1, 7) — WS2812 data 1
|
||||
#define PIN_RGB_LED_2 44 // (1, 12) — WS2812 data 2
|
||||
#define PIN_RGB_LED_3 28 // (0, 28) — WS2812 data 3
|
||||
// Typically only one data pin drives the chain; confirm wiring on hardware
|
||||
#define PIN_RGB_LED_1 39 // (1, 7) — WS2812 data 1 (power/charge)
|
||||
#define PIN_RGB_LED_2 44 // (1, 12) — WS2812 data 2 (notification)
|
||||
#define PIN_RGB_LED_3 28 // (0, 28) — WS2812 data 3 (BLE pairing)
|
||||
|
||||
// Default NeoPixel colours at 25% brightness (0x40 max per channel)
|
||||
#define NEOPIXEL_COLOR_POWER 0x400000 // red
|
||||
#define NEOPIXEL_COLOR_NOTIFY 0x004000 // green
|
||||
#define NEOPIXEL_COLOR_PAIRING 0x000040 // blue
|
||||
|
||||
// Legacy aliases (kept for any code referencing these)
|
||||
#define PIN_NEOPIXEL PIN_RGB_LED_1
|
||||
#define NUM_NEOPIXELS 3
|
||||
|
||||
@@ -159,14 +215,22 @@
|
||||
#define HAS_NFC 1
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// External Flash — ZD25WQ32CEIGR (4MB SPI Flash)
|
||||
// Uses QSPI interface on nRF52840
|
||||
// Pin mapping from nRF52840 QSPI peripheral (typically fixed)
|
||||
// External Flash — ZD25WQ32CEIGR (4MB QSPI Flash)
|
||||
//
|
||||
// Pin mapping confirmed from LilyGo t_echo_card_config.h and Meshtastic
|
||||
// PR #10267. These are on a separate SPI bus from LoRa.
|
||||
// The Adafruit nRF52 core supports QSPI via Adafruit_SPIFlash + LittleFS.
|
||||
// -----------------------------------------------------------------------------
|
||||
#define HAS_EXT_FLASH 1
|
||||
#define PIN_QSPI_SCK 4 // (0, 4)
|
||||
#define PIN_QSPI_CS 12 // (0, 12)
|
||||
#define PIN_QSPI_IO0 6 // (0, 6) — MOSI / D0
|
||||
#define PIN_QSPI_IO1 8 // (0, 8) — MISO / D1
|
||||
#define PIN_QSPI_IO2 41 // (1, 9) — WP / D2
|
||||
#define PIN_QSPI_IO3 26 // (0, 26) — HOLD / D3
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// No SD Card on T-Echo Card (unlike T-Echo which has e-paper + no SD either)
|
||||
// No SD Card on T-Echo Card
|
||||
// Settings stored in LittleFS on internal/external flash
|
||||
// -----------------------------------------------------------------------------
|
||||
// #define HAS_SDCARD
|
||||
|
||||
Reference in New Issue
Block a user