diff --git a/docs/solo/developer/build-flags.md b/docs/solo/developer/build-flags.md index 22ca99e4..5bc2b788 100644 --- a/docs/solo/developer/build-flags.md +++ b/docs/solo/developer/build-flags.md @@ -24,7 +24,7 @@ per-user. Listed here so the rest of this page can assume them. | Flag | Meaning | | --- | --- | | `FIRMWARE_SOLO_BUILD=1` | Marks the build as Solo (full on-device UI) rather than a companion-only firmware. | -| `DUAL_SERIAL=1` | The companion app can attach over BLE *or* USB serial, whichever it finds; BLE wins if both are live. Every solo build sets this — Solo standardises on one build per board rather than splitting BLE-only / USB-only variants. | +| `DUAL_SERIAL=1` | The companion app attaches over BLE and USB serial at once (upstream's `MultiSerialInterface`; the same as `ENABLE_USB_INTERFACE` next to `BLE_PIN_CODE`). Every solo build sets this — Solo standardises on one build per board rather than splitting BLE-only / USB-only variants. | | `MAX_CONTACTS=` | Size of the contact table. Default is 32 if unset; solo builds set 350. | | `MAX_GROUP_CHANNELS=` | Size of the channel list. Required for channel support to compile in at all — not optional the way the rest of this page is. | | `OFFLINE_QUEUE_SIZE=` | How many messages queue for later delivery while the phone app is disconnected. Default 16; solo builds set 256. | diff --git a/docs/solo/developer/ui-framework.md b/docs/solo/developer/ui-framework.md index d4a4b26b..3523d733 100644 --- a/docs/solo/developer/ui-framework.md +++ b/docs/solo/developer/ui-framework.md @@ -95,6 +95,13 @@ pixel sizes** — derive everything from these: | `width()` / `height()` | panel size in px | | `isEink()` | true only on landscape e-ink; branch on this, not on pixel counts | +Colours are upstream's `UIColor` roles (`DisplayDriver.h`), each display +driver's `.cpp` filling them with its own values. ui-new draws in two: +`UIColor::window_bkg` (the background: black on an OLED, white on e-ink) and +`UIColor::primary_txt` (the ink). A highlight is a `primary_txt` bar with +`window_bkg` text on it. A new driver defines all nine roles in its `.cpp` +(see `SH1106Display.cpp`), and `setColor()` takes the value as it is. + Drawing helpers (all clip/measure for you): - `drawScreenHeader(d, title, page=-1, pages=0, menu_hint=false, menu_open=false)` @@ -353,15 +360,21 @@ slow e-ink refresh: Device settings live in one `NodePrefs` struct (`NodePrefs.h`), saved via `the_mesh.savePrefs()` and loaded by `DataStore.cpp`. Rules when adding a field: -- `/prefs` holds the struct as it is in memory, behind a header with a format - version and a CRC. **Add a new field at the end of the struct**; nothing - else is needed: an older file is shorter, so the field keeps its default - (set in `MyMesh`'s constructor). -- Moving, resizing or removing a field shifts the ones after it: bump - `NodePrefs::PREFS_VERSION`, and every device starts again from the - defaults. +- `/prefs.json` holds one JSON key per field, written by upstream's + `ConfigSerializer`. The keys upstream MeshCore has (`radio`, `gps`, + `repeat`, `comp`, `custom`, `wifi`) keep upstream's names; everything + Solo adds sits under `solo`, grouped by topic (`display`, `sound`, `bot` …). +- **A new field** goes anywhere in `NodePrefsFields` and gets a key in the + matching `…Solo(Section&)` function of `NodePrefs`: `s.def("key", field)` + for a number or a string, `s.hex("key", field)` for a byte array or a + bit mask. A key is at most 15 characters. A file without the key leaves the + default (set in `MyMesh`'s constructor), and a key no field has any more is + skipped, so fields can be moved, resized and removed freely. +- `test/test_companion_prefs_json` checks that every field comes back byte + for byte: run `pio test -e native` after adding one; a field without a key + fails it. - Give a field with a range a line in `sanitize()` (`DataStore.cpp`), so a - damaged byte reads as the default. Saves are atomic (temp-file + rename), + damaged value reads as the default. Saves are atomic (temp-file + rename), so a crash mid-save can't corrupt settings. **The `_dirty` convention:** a multi-field editor screen mutates `_node_prefs` diff --git a/docs/solo/getting-started.md b/docs/solo/getting-started.md index 6d6ae4e9..f2edf502 100644 --- a/docs/solo/getting-started.md +++ b/docs/solo/getting-started.md @@ -91,9 +91,9 @@ connected over USB. ## Connecting the phone app -Every build serves the MeshCore app over **Bluetooth and USB**, one at a time: -while Bluetooth is connected, USB is ignored. To use USB, disconnect Bluetooth -first or turn it off on the device. +Every build serves the MeshCore app over **Bluetooth and USB** at the same +time: the app works on either link, with no need to disconnect the other. +Turning Bluetooth off on the device leaves USB on. The Bluetooth pairing PIN is shown on the Bluetooth home page until the phone is paired. Switching Bluetooth off keeps it off after a restart or diff --git a/docs/solo/settings.md b/docs/solo/settings.md index 193cf44f..d04d6abb 100644 --- a/docs/solo/settings.md +++ b/docs/solo/settings.md @@ -117,6 +117,8 @@ so its documentation applies: | `get tx`, `set tx 14` | TX power in dBm | | `get af` / `set af`, `get dutycycle` / `set dutycycle` | Airtime factor, or the same as a duty cycle in % | | `rxdelay`, `int.thresh`, `cad`, `radio.rxgain`, `path.hash.mode`, `multi.acks` | The advanced radio options, with `get` / `set` | +| `txdelay`, `direct.txdelay` | How long a repeated packet waits, as a share of its airtime (0–2; 0.5 and 0.2 by default), with `get` / `set` | +| `agc.reset.interval` | Seconds between radio gain resets (in steps of 4, `0` off), with `get` / `set` | | `get name`, `set name …` | The device name | | `get pin`, `set pin 123456` | The Bluetooth PIN, `0` for a random one; used from the next start | | `get tz.offset`, `set tz.offset 2` | Time zone, in hours from UTC |