mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 19:38:20 +00:00
fix build and update readmes
This commit is contained in:
@@ -46,6 +46,8 @@ Other benefits:
|
||||
| **Heltec V3** | ESP32-S3 | SX1262 | OLED (SSD1306), 8MB flash |
|
||||
| **Heltec V4.2** | ESP32-S3 | SX1262 + GC1109 PA | OLED (SSD1306), 16MB flash, 2MB PSRAM |
|
||||
| **Heltec V4.3** | ESP32-S3 | SX1262 + KCT8103L PA | OLED (SSD1306), 16MB flash, 2MB PSRAM |
|
||||
| **Heltec Wireless Tracker** | ESP32-S3 | SX1262 | ST7735R 160×80 TFT, UC6580 GPS |
|
||||
| **LilyGo T-Beam v1.2** | ESP32 (PICO-D4) | SX1262 | AXP2101 PMU, GNSS, USB-UART CLI |
|
||||
|
||||
### Other
|
||||
|
||||
@@ -204,7 +206,9 @@ Key Kconfig options (set in board configs or via `-D` flags):
|
||||
| `CONFIG_ZEPHCORE_MAX_CONTACTS` | 350 | Contact storage slots (companion) |
|
||||
| `CONFIG_ZEPHCORE_MAX_CHANNELS` | 40 | Channel slots (companion) |
|
||||
| `CONFIG_ZEPHCORE_BLE_PASSKEY` | 123456 | BLE pairing PIN |
|
||||
| `CONFIG_ZEPHCORE_GPS_POLL_INTERVAL_SEC` | 300 | GPS fix interval (seconds) |
|
||||
| `CONFIG_ZEPHCORE_GPS_POLL_INTERVAL_SEC` | 300 | Companion GPS duty interval between fixes (seconds); 0 = always-on |
|
||||
| `CONFIG_ZEPHCORE_GPS_FIRST_FIX_TIMEOUT_SEC` | 300 | Cold-start window for the very first fix (longer to allow almanac download) |
|
||||
| `CONFIG_ZEPHCORE_REPEATER_GPS_INTERVAL_SEC` | 172800 | Repeater/room-server GPS duty interval boot default (48 h); 0 = always-on |
|
||||
| `CONFIG_ZEPHCORE_WIFI_OTA` | n | WiFi AP + HTTP OTA updates (ESP32 repeaters, requires `--sysbuild`) |
|
||||
| `CONFIG_ZEPHCORE_REPEATER_UPLINK` | n | Repeater WiFi+MQTT uplink (ESP32) |
|
||||
| `CONFIG_ZEPHCORE_PACKET_LOGGING` | n | Arduino-compatible mesh packet logging |
|
||||
|
||||
@@ -429,8 +429,9 @@ Power: `powersaving on/off`
|
||||
- Nordic UART Service (NUS) with AUTHEN permissions on CCC + RX (forces pairing)
|
||||
- Passkey-based MITM pairing (SC + MITM + Bonding), runtime configurable PIN via `app_passkey` callback
|
||||
- DisplayOnly IO capability — phone enters passkey displayed on device / known to user
|
||||
- Advertising with public identity address (no RPA) — required for Android Flutter BLE app compatibility
|
||||
- `CONFIG_BT_PRIVACY` disabled: Android's Flutter BLE plugin fails to `connectGatt()` to RPA-advertised devices from app context; iOS and Android system BT settings handle RPA fine but the MeshCore app doesn't. Arduino MeshCore also uses public addresses.
|
||||
- Advertising always uses `BT_LE_ADV_OPT_USE_IDENTITY` — exposes the stable identity address even when privacy is enabled, preserving Android connect-from-app
|
||||
- `CONFIG_BT_PRIVACY` **disabled** on nRF52840 / MG24: identity address is advertised directly; both iOS and Android work without RPA. Android's Flutter BLE plugin fails `connectGatt()` to RPA-advertised devices from app context.
|
||||
- `CONFIG_BT_PRIVACY` **enabled** on ESP32-S3 (`boards/common/esp32_common.conf`): the Espressif controller's privacy-OFF Secure-Connections path produces a MIC failure against iOS (HCI disconnect `0x3d` at encryption start). Privacy ON keeps the controller on its working SC path. `USE_IDENTITY` advertising preserves Android compatibility. Do **not** remove `USE_IDENTITY` while ESP32 privacy is on.
|
||||
- Pairing triggered reactively: phone hits ATT error 0x05 on secured attribute → initiates SMP pairing (Apple Accessory Design Guidelines §55 compliant — no proactive Security Request)
|
||||
- TX congestion control: queue (12 frames) + overflow buffer + retry + timeout watchdog
|
||||
- Fast/slow advertising switching with post-disconnect flap prevention
|
||||
@@ -442,21 +443,50 @@ Power: `powersaving on/off`
|
||||
|
||||
- **Internal**: LittleFS on flash (`/lfs`), 256-byte cache for reduced flash I/O
|
||||
- **External**: Optional LittleFS on QSPI (`/ext`) with auto-migration
|
||||
- **BLE bonds**: File-based settings on LittleFS (`/lfs/settings/`) — all platforms (no NVS)
|
||||
- **BLE bonds**: NVS (`storage_partition`, 0xD0000 on nRF52) via Zephyr settings backend (≥1.16.2)
|
||||
- **Prefs**: 292-byte binary format, Arduino-compatible, field-by-field I/O (see §13)
|
||||
- **Contacts**: 152-byte records, stored on external flash if available
|
||||
- **Channels**: 68-byte records (4 pad + 32 name + 32 secret)
|
||||
- **Blobs**: Fixed-size records with LRU eviction by timestamp
|
||||
|
||||
**First-boot migration (3-way FS self-heal)**
|
||||
|
||||
A marker file `/lfs/_zc_init` is written after the first clean ZephCore boot. On every subsequent boot it is present and the logic below is skipped. On first boot (marker absent), `main_companion.cpp` picks one of three paths before `bt_enable()` runs:
|
||||
|
||||
1. **No prefs, or Arduino MeshCore prefs** → full LFS + NVS format. Arduino's `new_prefs` omits `node_lat`/`node_lon`, shifting `freq`/`sf`/`bw` by 16 bytes; `prefsLookLikeArduino()` detects this by range-checking those fields. Covers fresh installs and Arduino → ZephCore migrations.
|
||||
2. **Valid ZephCore prefs + `/lfs/settings` present** → NVS-only erase (`formatNVSOnly()`). ZephCore ≤1.16.1 stored BLE bonds in `/lfs/settings` (file backend); ≤1.16.1 used 0xD0000 as app code, so bytes there may pass NVS sector validation and hang `settings_load()`. Identity/prefs/contacts are preserved; re-pairing is required.
|
||||
3. **Valid ZephCore prefs + no `/lfs/settings`** → skip format entirely. NVS was already initialised by ZephCore ≥1.16.2; bonds survive the upgrade.
|
||||
|
||||
`loadPrefs()` also range-checks `freq`/`sf`/`bw` after deserialisation and reverts to compile-time defaults on out-of-range values, so a misread Arduino prefs file never corrupts the radio config.
|
||||
|
||||
### 7.3 GPS (`adapters/gps/`)
|
||||
|
||||
- State machine: OFF → ACQUIRING → STANDBY (with warm standby on supported hardware)
|
||||
- 3 consecutive good fixes (≥4 satellites) required before reporting
|
||||
- Multi-constellation: GPS+GLONASS+Galileo+BeiDou with fallback
|
||||
- T1000-E: Complex 6-GPIO power sequencing with VRTC preservation
|
||||
- Repeater mode: 48-hour wake interval for time sync only
|
||||
- GPS time blocks phone time sync for 2 hours after last fix
|
||||
|
||||
**Duty cycle vs always-on**
|
||||
|
||||
`gps_wake_interval_ms` (initialised from `prefs.gps_interval`) controls the mode:
|
||||
|
||||
- **Duty cycling** (`gps_wake_interval_ms > 0`): after acquiring 3 good fixes the GPS powers down; the state machine wakes it again after the configured standby interval. The fix callback fires and then the GPS sleeps.
|
||||
- **Always-on** (`gps_wake_interval_ms == 0`): the GPS never powers down. `consecutive_good_fixes` is reset after each promotion so the 3-fix gate cycles continuously, streaming fresh positions. Flash writes and fix callbacks are rate-limited to once per `gps_acquire_timeout_ms` to avoid hammering storage.
|
||||
|
||||
`gps_set_poll_interval_sec(0)` switches to always-on live; persisted via `prefs.gps_interval` (set by `set gps duty 0`).
|
||||
|
||||
**Timeout split**
|
||||
|
||||
Two separate timeouts apply to acquisition:
|
||||
|
||||
- `CONFIG_ZEPHCORE_GPS_FIRST_FIX_TIMEOUT_SEC` (default 300s): the cold-start window used for the very first acquisition after `gps_enable()`. Longer to allow almanac download.
|
||||
- `CONFIG_ZEPHCORE_GPS_FIX_TIMEOUT_SEC` (default 120s): the normal per-wake timeout for all subsequent acquisitions (warm start).
|
||||
|
||||
**Repeater mode**
|
||||
|
||||
Repeaters and room servers default to `CONFIG_ZEPHCORE_REPEATER_GPS_INTERVAL_SEC` (48 h) for GPS duty — GPS wakes only for a periodic time-sync fix (5-minute acquire window). The interval is now unified with companion via `prefs.gps_interval` and is configurable at runtime via `set gps duty <sec>`; persists across reboots.
|
||||
|
||||
### 7.4 USB (`adapters/usb/`)
|
||||
|
||||
- **CompanionUSB**: V3-framed CDC (little-endian 16-bit length prefix + payload)
|
||||
@@ -569,6 +599,8 @@ prj.conf (base: console; production defaults — LOG=n, ASSERT=n)
|
||||
| XIAO ESP32-C6 | ESP32-C6 | SX1262 | - | - | - | - | - | 300 |
|
||||
| LilyGo TLoRa C6 | ESP32-C6 | SX1262 | - | - | - | - | - | 300 |
|
||||
| Station G2 | ESP32-S3 | SX1262+PA | UART1 | OLED 128x64 | - | 1 button | - | 350 |
|
||||
| Heltec Wireless Tracker | ESP32-S3 | SX1262 | UC6580 | TFT 160x80 | - | - | - | 350 |
|
||||
| LilyGo T-Beam v1.2 | ESP32 | SX1262 | gnss-nmea | - | - | - | - | 300 |
|
||||
| XIAO MG24 | EFR32MG24 | SX1262 | - | - | - | - | - | 350 |
|
||||
|
||||
---
|
||||
@@ -667,7 +699,7 @@ Over USB CDC: V3 framing: `[2B LE length] [1B opcode] [payload...]`
|
||||
| `/lfs/adv_blobs` or `/ext/adv_blobs` | Advert cache | Fixed-size blob records |
|
||||
| `/lfs/repeater/acl` | Client ACL | 136B × N records |
|
||||
| `/lfs/repeater/regions2` | Region map | Header + 164B × N entries |
|
||||
| `/lfs/settings/` | BLE bonds + Zephyr settings | File-based settings (all platforms) |
|
||||
| `storage_partition` (NVS, 0xD0000 nRF52) | BLE bonds + Zephyr settings | NVS settings backend (≥1.16.2; old `/lfs/settings` file detected by self-heal) |
|
||||
|
||||
### Preferences Binary Layout (292 bytes)
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ void ZephyrDataStore::begin()
|
||||
checkAdvBlobFile();
|
||||
}
|
||||
|
||||
bool ZephyrDataStore::exists(const char *path)
|
||||
bool ZephyrDataStore::exists(const char *path) const
|
||||
{
|
||||
struct fs_dirent ent;
|
||||
return fs_stat(path, &ent) == 0;
|
||||
@@ -145,7 +145,7 @@ bool ZephyrDataStore::removeFile(const char *path)
|
||||
return fs_unlink(path) == 0;
|
||||
}
|
||||
|
||||
bool ZephyrDataStore::openRead(const char *path, uint8_t *buf, size_t buf_sz, size_t &out_len)
|
||||
bool ZephyrDataStore::openRead(const char *path, uint8_t *buf, size_t buf_sz, size_t &out_len) const
|
||||
{
|
||||
struct fs_file_t file;
|
||||
fs_file_t_init(&file);
|
||||
|
||||
@@ -90,9 +90,9 @@ private:
|
||||
|
||||
void checkAdvBlobFile();
|
||||
void migrateToExternalFS();
|
||||
bool openRead(const char *path, uint8_t *buf, size_t buf_sz, size_t &out_len);
|
||||
bool openRead(const char *path, uint8_t *buf, size_t buf_sz, size_t &out_len) const;
|
||||
bool atomicReplaceFile(const char *path, const uint8_t *buf, size_t len);
|
||||
bool exists(const char *path);
|
||||
bool exists(const char *path) const;
|
||||
bool removeFile(const char *path);
|
||||
bool copyFile(const char *src, const char *dst);
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ SWD flash: `west flash` (requires J-Link, pyocd, or nrfjprog connected).
|
||||
| Heltec V4.2 (GC1109 PA) | `west build -b heltec_wifi_lora32_v4/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Heltec V4.3 (KCT8103L PA) | `west build -b heltec_wifi_lora32_v43/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Heltec Wireless Tracker | `west build -b heltec_wireless_tracker/esp32s3/procpu zephcore` | `west flash` |
|
||||
| LilyGo T-Beam v1.2 | `west build -b ttgo_tbeam/esp32/procpu zephcore` | `west flash` |
|
||||
|
||||
**Heltec V3 console:** ZephCore routes console/shell to `uart0` on V3. Use the UART serial port for boot logs and CLI.
|
||||
|
||||
@@ -51,6 +52,13 @@ unclear, check GPIO2's default pull: the V4.2 GC1109 PA has an internal pull-dow
|
||||
(GPIO2 reads LOW at boot), while the V4.3 KCT8103L PA has an internal pull-up
|
||||
(GPIO2 reads HIGH). Only difference in firmware: TX control pin GPIO46→GPIO5.
|
||||
|
||||
**LilyGo T-Beam v1.2:** Classic ESP32 (PICO-D4) board — several caveats apply:
|
||||
- Upstream Zephyr DTS models the SX1276 variant; `board.overlay` overrides the radio node to SX1262 on the same SPI3 wiring.
|
||||
- PICO-D4 rev 1.0 bootloops when the bootloader tries to enable QIO flash mode. `board.conf` forces DIO (`CONFIG_ESPTOOLPY_FLASHMODE_DIO=y`). Any new classic ESP32 board with PICO-D4 needs this.
|
||||
- Classic ESP32 DRAM is much smaller than ESP32-S3. `board.conf` shrinks contacts/channels/queue (`MAX_CONTACTS=160`, `MAX_CHANNELS=8`, `OFFLINE_QUEUE_SIZE=128`) to fit.
|
||||
- AXP2101 PMU manages LoRa and GPS power rails via Zephyr regulator + fuel-gauge drivers (auto-enabled from the upstream DTS PMU nodes). Add `CONFIG_FUEL_GAUGE=y` to boards that expose battery state-of-charge over I2C.
|
||||
- Console/CLI are on `uart0` (onboard USB-UART). No native USB on classic ESP32.
|
||||
|
||||
ESP32 flash uses esptool over USB via `west flash`. Hold BOOT button if the device
|
||||
doesn't enter download mode automatically.
|
||||
|
||||
@@ -67,6 +75,26 @@ west build -b <board>/esp32s3/procpu zephcore --pristine --sysbuild -- \
|
||||
west flash --esp-device COMX
|
||||
```
|
||||
|
||||
### SX127x Boards (loramac-node backend)
|
||||
|
||||
ZephCore supports SX1272/SX1276/SX1278 via the loramac-node backend — a separate radio path from the native SX126x driver used by all other boards. The TTGO LoRa32 is the reference implementation:
|
||||
|
||||
| Board | Build string | Flash |
|
||||
|----------------|------------------------------------------------|--------------|
|
||||
| TTGO LoRa32 | `west build -b ttgo_lora32/esp32/procpu zephcore` | `west flash` |
|
||||
|
||||
SX127x boards require these `board.conf` overrides (the `zephcore_common.conf` default enables the native SX126x path):
|
||||
|
||||
```kconfig
|
||||
CONFIG_LORA_MODULE_BACKEND_NATIVE=n
|
||||
CONFIG_LORA_MODULE_BACKEND_LORAMAC_NODE=y
|
||||
CONFIG_ZEPHCORE_RADIO_SX127X=y
|
||||
CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE=n # lora_recv_duty_cycle not implemented for SX127x
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=17 # PA_BOOST max without external PA
|
||||
```
|
||||
|
||||
Classic ESP32 + PICO-D4 also need the DIO flash mode fix (see T-Beam note above).
|
||||
|
||||
**One-time setup required (all ESP32 boards):**
|
||||
|
||||
```
|
||||
@@ -248,6 +276,9 @@ should ONLY contain settings that can't be inferred from hardware:
|
||||
CONFIG_HEAP_MEM_POOL_SIZE Override for large displays (>128x64)
|
||||
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP Shrink RTT on RAM-tight boards
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB ESP32 boards with 16MB flash
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y Classic ESP32 PICO-D4 boards (bootloops otherwise)
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=n Companion to the DIO override above
|
||||
CONFIG_FUEL_GAUGE=y Boards with AXP2101 or other I2C fuel gauge
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM Boards with external PA
|
||||
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM Boards with external PA
|
||||
CONFIG_ZEPHCORE_APC Adaptive Power Control — OFF by default.
|
||||
@@ -331,16 +362,16 @@ Quick Reference: Wio-SX1262 XIAO Pin Mapping
|
||||
|
||||
All XIAO boards use the same D-pin assignment for Wio-SX1262:
|
||||
|
||||
Signal | XIAO Pin | nRF52840 | nRF54L15 | MG24 | ESP32-C3
|
||||
-------|----------|-----------|-----------|-----------|--------
|
||||
DIO1 | D1 | P0.03 | P1.05 | PC01 | GPIO3
|
||||
RESET | D2 | P0.28 | P1.06 | PC02 | GPIO4
|
||||
BUSY | D3 | P0.05 | P1.07 | PC03 | GPIO5
|
||||
NSS | D4 | P0.04 | P1.10 | PC04 | GPIO6
|
||||
RXEN | D5 | P0.29 | P1.11 | PC05 | GPIO7
|
||||
SCK | D8 | P1.13 | P2.01 | PA03 | GPIO8
|
||||
MISO | D9 | P1.14 | P2.04 | PA04 | GPIO9
|
||||
MOSI | D10 | P1.15 | P2.02 | PA05 | GPIO10
|
||||
Signal | XIAO Pin | nRF52840 | nRF54L15 | MG24 | ESP32-C3 | ESP32-C6 | ESP32-S3
|
||||
-------|----------|-----------|-----------|-----------|-----------|-----------|----------
|
||||
DIO1 | D1 | P0.03 | P1.05 | PC01 | GPIO3 | GPIO1 | GPIO39
|
||||
RESET | D2 | P0.28 | P1.06 | PC02 | GPIO4 | GPIO2 | GPIO42
|
||||
BUSY | D3 | P0.05 | P1.07 | PC03 | GPIO5 | GPIO21 | GPIO40
|
||||
NSS | D4 | P0.04 | P1.10 | PC04 | GPIO6 | GPIO22 | GPIO41
|
||||
RXEN | D5 | P0.29 | P1.11 | PC05 | GPIO7 | GPIO23 | GPIO38
|
||||
SCK | D8 | P1.13 | P2.01 | PA03 | GPIO8 | GPIO19 | GPIO7
|
||||
MISO | D9 | P1.14 | P2.04 | PA04 | GPIO9 | GPIO20 | GPIO8
|
||||
MOSI | D10 | P1.15 | P2.02 | PA05 | GPIO10 | GPIO18 | GPIO9
|
||||
|
||||
Note: nRF52840 D-pin mapping varies by board (XIAO nRF52840 shown).
|
||||
RAK4631 has SX1262 integrated — different pinout entirely.
|
||||
|
||||
Reference in New Issue
Block a user