LilyGo T-Display P4 (ESP32-P4 + factory ESP-AT C6) reaches POC: LoRa mesh, Wi-Fi companion (TCP:5000), GPS, SD, battery gauge, chat persistence, and now: - Web VNC/REMOTE/terminal via a first-byte router on the single ESP-AT listener (HTTP verbs -> WS server, '<' frames -> phone companion; both live at once). C6Server gains a _begun gate so never-listening instances stay inert. - VNC freeze fixed: bounded one-CIPSEND-chunk drains under the WS client mutex (a whole-band blocking write starved the main loop), fast-drop of stalled mirror clients, SEND-OK wait 8s->4s. - Wi-Fi robustness: CWJAP? miss-streak tolerance, CIPSERVER liveness verify + re-arm (a re-association silently killed the listener until reboot). - Time sync: HTTP-Date fallback when SNTP is blocked; ClockFloorRTC gains a MAX_PLAUSIBLE_EPOCH guard (all boards) after a garbage-future hardware RTC read (2043) latched the ratchet. - Brightness: RM69A10 DCS 0x51 driven live (CC slider + persisted pref). - Sound: ES8311 + NS4150B notification chimes (P4Audio, esp-bsp-derived register sequence on Wire1), full HAS_UI_SOUND surface + CC Screen/Sound sliders; ccVolumeReleaseCb's hardcoded tanBeep -> uiSoundPreview. - tdisplay_p4/: IDF project (build.sh, c6_at AT-over-SDIO driver, sdkconfigs, fetch-deps.sh vendoring, .gitignore for local payloads). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
80 lines
3.0 KiB
C++
80 lines
3.0 KiB
C++
#include <Arduino.h>
|
|
#include <Wire.h> // BQ27220 fuel gauge (getBattMilliVolts)
|
|
#include "target.h"
|
|
#include <helpers/ArduinoHelpers.h> // RadioNoiseListener / StdRNG
|
|
|
|
TDisplayP4Board board;
|
|
Xl9535 xl9535; // board-global expander (declared extern in Xl9535.h)
|
|
|
|
// SX1262 on the P4 SPI (SCLK=2/MOSI=3/MISO=4, CS=24, BUSY=6). RESET + DIO1 are on the XL9535
|
|
// (P_LORA_RESET/DIO_1 == -1 = RADIOLIB_NC): reset is pulsed via the expander in radio_init(); with
|
|
// DIO1 == NC RadioLib polls for RX/TX-done instead of taking a hardware IRQ.
|
|
// TODO(device): if polling RX is unreliable, route DIO1 through the XL9535 INT (GPIO5).
|
|
static SPIClass spi(FSPI);
|
|
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
|
|
WRAPPER_CLASS radio_driver(radio, board);
|
|
|
|
DISPLAY_CLASS display; // RM69A10 MIPI-DSI
|
|
|
|
ESP32RTCClock fallback_clock;
|
|
ClockFloorRTC rtc_clock(fallback_clock);
|
|
|
|
#if ENV_INCLUDE_GPS
|
|
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
|
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
|
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
|
#else
|
|
EnvironmentSensorManager sensors;
|
|
#endif
|
|
|
|
void TDisplayP4Board::begin() {
|
|
ESP32Board::begin();
|
|
}
|
|
|
|
// BQ27220 fuel gauge (I2C_1 @0x55, same shared Wire bus as the XL9535/RTC/touch — TwoWire's
|
|
// internal lock makes each transaction atomic across tasks). Standard command reads: 16-bit
|
|
// little-endian at Voltage()=0x08 (mV). Reads are rate-limited and sanity-windowed; on any I2C
|
|
// hiccup the last good value is kept so the battery UI never flickers to nonsense.
|
|
static uint16_t bq27220ReadU16(uint8_t cmd) {
|
|
Wire.beginTransmission(0x55);
|
|
Wire.write(cmd);
|
|
if (Wire.endTransmission(false) != 0) return 0;
|
|
if (Wire.requestFrom(0x55, 2) != 2) return 0;
|
|
uint16_t lo = Wire.read(), hi = Wire.read();
|
|
return (uint16_t)(lo | (hi << 8));
|
|
}
|
|
|
|
uint16_t TDisplayP4Board::getBattMilliVolts() {
|
|
static uint32_t last_ms = 0;
|
|
static uint16_t last_mv = 3800; // pre-first-read placeholder
|
|
static bool logged = false;
|
|
const uint32_t now = millis();
|
|
if (last_ms == 0 || now - last_ms >= 5000) {
|
|
last_ms = now;
|
|
const uint16_t mv = bq27220ReadU16(0x08); // Voltage(), mV
|
|
if (mv >= 2500 && mv <= 4600) {
|
|
last_mv = mv;
|
|
if (!logged) { printf("[BATT] BQ27220 alive: %u mV\n", mv); logged = true; }
|
|
} else if (!logged) {
|
|
printf("[BATT] BQ27220 read invalid (%u) — placeholder in use\n", mv);
|
|
logged = true;
|
|
}
|
|
}
|
|
return last_mv;
|
|
}
|
|
|
|
bool radio_init() {
|
|
fallback_clock.begin();
|
|
rtc_clock.begin(Wire); // PCF8563 RTC is on I2C_1 (shared Wire, SDA=7/SCL=8)
|
|
|
|
// SX1262 RESET is on the XL9535 — pulse it before RadioLib init.
|
|
xl9535.sx1262Reset();
|
|
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI, P_LORA_NSS);
|
|
return radio.std_init(&spi);
|
|
}
|
|
|
|
mesh::LocalIdentity radio_new_identity() {
|
|
RadioNoiseListener rng(radio);
|
|
return mesh::LocalIdentity(&rng); // fresh random identity from SX1262 RSSI noise
|
|
}
|