mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
docs(solo): bring the docs up to date with the L1 refresh
- Home pages as they are now (Status, quick panels, Map page), the Status screen's tabs instead of Diagnostics / GPS / Sensors, lock clock Big / Compact and the hint on a key press, battery curve on L1 and L2, "+ Send" and a failed send, trail pin, vector map behind -D MAP_VECTOR. - Developer guide: drawScreenHeader, soft frames, InfoKit, TabBar, a status bar without blinking, toast and millis() rules; ui-core status; build flags (GPS_SKYVIEW, MAP_VECTOR, HIST_ARCHIVE added, ui-tiny-only ones out). - New simulator screenshots: the clock page and the Status page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ per-user. Listed here so the rest of this page can assume them.
|
||||
| `TRAIL_CAPACITY=<n>` | Points the GPS trail holds (16 B each). Default 512 for the nRF52's RAM; the L2 sets 32768 in PSRAM. At most 65535 (the save format's count). |
|
||||
| `TRAIL_SIMPLIFY=0` | Keeps every trail sample instead of storing straight stretches as their two ends. For boards with the memory for it (the L2). |
|
||||
| `TRAIL_FIXED_MIN_DELTA_M=<m>` | A fixed distance between trail points instead of the Point spacing setting, which is then hidden (the L2: 5 m, against GPS jitter). |
|
||||
| `UI_SENSORS_PAGE=1` | Enables the on-device sensors dashboard page. |
|
||||
| `UI_SENSORS_PAGE=1` | Only the default Home page order in the solo UI: sensor readings are on the Status screen's Power tab whenever the board has sensors. |
|
||||
| `BLE_PIN_CODE=<n>` | See below — not a plain fixed value in practice. |
|
||||
| `DISPLAY_CLASS=<Class>` | Selects the display driver (e.g. `SSD1306Display`, `GxEPDDisplay`, `ST7789Display` — see `src/helpers/ui/` for the full set). Fixed by whatever panel the board actually has; only relevant if you're wiring on a *different* display than stock, in which case the matching driver's `.cpp` also needs adding to `build_src_filter`. |
|
||||
|
||||
@@ -56,7 +56,6 @@ existing `solo/<board>/platformio.ini` for what's already claimed).
|
||||
| `UI_HAS_JOYSTICK=1` + `UI_HAS_JOYSTICK_UPDOWN=1` (optional) + `JOYSTICK_UP` / `JOYSTICK_DOWN` / `JOYSTICK_LEFT` / `JOYSTICK_RIGHT` + `PIN_USER_BTN` + `PIN_BACK_BTN` | A wired joystick (four direction contacts + a press contact for Enter). Replaces single-button navigation entirely once enabled. See [External Keyboard & Joystick](../hardware.md#external-keyboard-and-joystick). |
|
||||
| `PIN_GPIO1` .. `PIN_GPIO4` | Up to four general-purpose pins, each independently switchable between Off / Input / Output (GPIO1/GPIO2 also get an Analog step, if wired to an ADC-capable pin) from Tools › GPIO, and via the `!gpio1`..`!gpio4` bot commands. Not restricted to any particular board — works anywhere the pins are actually free. See [Tools › GPIO](../tools.md#gpio). |
|
||||
| `PIN_HALL_SENSOR` + `HALL_ACTIVE_HIGH=1` (optional) | A Hall-effect or reed sensor for a magnetic flip cover: closing locks and blanks the screen instantly, opening unlocks and wakes it, no combo either way. `HALL_ACTIVE_HIGH` is only for a module wired to pull the pin high (rather than low) when the magnet is near. See [Screen lock › Magnetic cover](../lock.md#magnetic-cover). |
|
||||
| `PIN_GPS_SWITCH` | A physical on/off switch for GPS power, read alongside the software GPS toggle — the Tools screen shows `gps off(hw)` / `gps off(sw)` when the two disagree, instead of silently trusting one over the other. |
|
||||
|
||||
---
|
||||
|
||||
@@ -75,9 +74,7 @@ existing `solo/<board>/platformio.ini` for what's already claimed).
|
||||
| --- | --- |
|
||||
| `ENV_INCLUDE_GPS=1` | Compiles in GPS support (NMEA parsing, location provider) at all. |
|
||||
| `GPS_BAUD_RATE=<n>` | Baud rate for the GPS module's serial link (`Serial1`). Match your module's default. |
|
||||
|
||||
`PIN_GPS_SWITCH` (above) is independent of both — it's a hardware kill switch
|
||||
layered on top of GPS support, not a requirement for it.
|
||||
| `GPS_SKYVIEW` | Keeps every satellite in view (constellation, elevation, azimuth, signal) for the Status screen's Sky tab and the L2's GPS app (~1.5 KB RAM). Set on the Wio Tracker L1 and L2. |
|
||||
|
||||
---
|
||||
|
||||
@@ -90,7 +87,6 @@ layered on top of GPS support, not a requirement for it.
|
||||
| `ENABLE_SCREENSHOT` | Lets the site's [USB tools](https://solo.marekzegarek.com/#pc-tools) (or `tools/screenshot.py`) capture the screen over USB. A colour screen (the L2) renders a fresh frame and sends it as RGB565. |
|
||||
| `KEEP_DISPLAY_ON_USB` | Refreshes the auto-off deadline continuously while externally (USB) powered, so the auto-off timer only starts counting once power is actually removed. Off by default because OLED panels burn in quickly with a permanently-lit screen — only worth enabling for an LCD/e-ink target, or a display you don't mind replacing. |
|
||||
| `AUTO_OFF_MILLIS=<ms>` | How long the display stays on before auto-off. Default 15000 (15s); `0` disables auto-off entirely. |
|
||||
| `UI_RECENT_LIST_SIZE=<n>` | How many entries the recent-activity lists show before scrolling. Default 4. |
|
||||
|
||||
---
|
||||
|
||||
@@ -116,4 +112,6 @@ values above that are set from the phone app or the CLI.
|
||||
| Flag | Meaning |
|
||||
| --- | --- |
|
||||
| `ADVERT_NAME='"name"'` | Sets the default node name baked into a fresh device, instead of the hex of the first 4 bytes of its public key. Note the doubled quoting — it's a C string literal passed through a build flag. |
|
||||
| `MAP_VECTOR` | Wio Tracker L2: turns on the unfinished vector map (regions from `tools/maps/osm_vector.py`). Without it the vector map stays off whatever was saved. |
|
||||
| `HIST_ARCHIVE` | Wio Tracker L2: message history also kept on the SD card (`ui-lvgl/HistoryStore.h`). Set in its solo build. |
|
||||
| `MESHCORE_VERSION='"x.y"'` | Overrides the upstream MeshCore base-version string shown in diagnostics, for boards whose port hasn't been rebased onto the latest yet. Cosmetic only — doesn't change protocol behaviour. |
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -63,7 +63,9 @@ public:
|
||||
Only screens needing a *parameter* at entry add a typed call after it (e.g.
|
||||
`gotoRingtoneEditor` → `selectSlot(slot)`, `gotoMapScreen` → `showMapView()`).
|
||||
4. Reach it from somewhere — usually a row in `ToolsScreen.h` (add an `Action`
|
||||
enum value, a row in the right section table, and a `dispatch()` case).
|
||||
enum value, a row in the right section table, and a `run()` case). The
|
||||
Tools home page lists the last two tools used; give the new one a state
|
||||
in `HomeScreen::toolState()` (`UITask.cpp`) if it has one worth showing.
|
||||
|
||||
That's the whole contract. Steps 1, 3 and 4 are compiler-checked (a mismatch
|
||||
won't link); only a forgotten step 2 can slip through — every screen pointer is
|
||||
@@ -95,14 +97,19 @@ pixel sizes** — derive everything from these:
|
||||
|
||||
Drawing helpers (all clip/measure for you):
|
||||
|
||||
- `drawCenteredHeader(title, menu_hint=false, menu_open=false)` — plain centered
|
||||
title + separator.
|
||||
- `drawInvertedHeader(label, menu_hint=false, menu_open=false)` — filled title
|
||||
bar (used by detail views).
|
||||
- Both take an optional `menu_hint`: pass `true` on a screen with a Hold-Enter
|
||||
context menu to reserve a `≡` glyph (`menuHintWidth()`/`drawContextMenuHint()`)
|
||||
in the header, so the menu is discoverable without already knowing the
|
||||
shortcut; `menu_open` highlights it while the menu is actually up.
|
||||
- `drawScreenHeader(d, title, page=-1, pages=0, menu_hint=false, menu_open=false)`
|
||||
(`ui-new/icons.h`) — every screen's title bar: the title (title case, no
|
||||
icon) centred over the separator, page dots at the right for a screen with
|
||||
views (`page` of `pages`, e.g. Trail's Summary / Map / List), and the `≡`
|
||||
hint when the screen has a Hold-Enter menu, so the menu is discoverable
|
||||
without knowing the shortcut; `menu_open` highlights it while the menu is
|
||||
up. A title too long to centre goes left and ends in an ellipsis.
|
||||
- `drawInvertedHeader(label, menu_hint=false, menu_open=false)` — a filled
|
||||
title bar, kept for the node detail and Navigate views.
|
||||
- `drawSoftRect` / `fillSoftRect` — a box with its corner pixels left out;
|
||||
every frame and fill in the UI uses them (selections, pills, buttons).
|
||||
`drawPanel(x, y, w, h)` is a box floating over the view (alert, popup,
|
||||
hint): it clears a 1 px moat, fills dark and draws the soft border.
|
||||
- `drawSelectionRow(x, y, w, h, sel)` — the highlight bar behind a list row.
|
||||
- `drawTextEllipsized(x, y, max_w, str, selected=false)` — truncates with `…`;
|
||||
**use this for any user string** (names, labels) so long/UTF-8 text can't
|
||||
@@ -160,6 +167,8 @@ calculator (`scrollIndicatorReserve`) are exposed for hand-laid lists.
|
||||
| `DigitEditor` | `DigitEditor.h` | scroll-edit one number, digit by digit |
|
||||
| `FullscreenMsgView` | `FullscreenMsgView.h` | scrollable full-message reader + word wrap |
|
||||
| `NavView` | `NavView.h` | bearing/distance/ETA "navigate to a point" view |
|
||||
| `TabBar` | `TabBar.h` | a row of tabs: the current one a soft pill, whole tabs only, ◂ ▸ where more are off screen |
|
||||
| `info::` rows and blocks | `InfoKit.h` | settings rows, data screens (below) |
|
||||
|
||||
All follow the same shape: a `begin(...)` to open, an `active` flag, a
|
||||
`handleInput(c)` returning a small `Result` enum, and a `render()`/`draw()`.
|
||||
@@ -211,6 +220,24 @@ to pick, Enter to insert via the shared `insertGlyph()` helper, Cancel to
|
||||
dismiss. Holding a letter with no variants, or any T9/alt-alphabet/symbols
|
||||
cell, is a no-op.
|
||||
|
||||
**InfoKit** (`ui-new/InfoKit.h`, namespace `info`) is the shared look of
|
||||
settings and data screens. Rows (drawn after `drawRowSelection()`, in its
|
||||
ink): `valueRow(d, y, label, value, sel, reserve, x0)` — label left, value
|
||||
flush right with its unit after a space ("50 m"), cut and marquee-scrolled
|
||||
when selected; `switchRow` — a yes/no setting as an on/off switch
|
||||
(`toggle()`); `listRow` — picks between the two for a formatter that returns
|
||||
exactly "ON" / "OFF". `rowWrapped` gives a long value its own line instead of
|
||||
an ellipsis nobody can scroll. Blocks for data screens: `section` (a centred
|
||||
"··· Font ···" divider), `meter`, `battery`, `chip`, `big` (a 2× number with
|
||||
its unit), `History<N>` + `spark` (a sparkline), `rule` / `vrule`. `Flow`
|
||||
places blocks top-down, skips the ones scrolled off and tells whether more
|
||||
are below, which gives the scroll indicator for free (see `StatusScreen.h`).
|
||||
|
||||
Other drawing helpers in `icons.h`: `drawButton` (a push button, soft pill,
|
||||
filled while selected), `drawDisclosure` (▸ / ▾ on an accordion section),
|
||||
`drawPageDots`, `drawLoadingDots` (the waiting animation), `drawSignalBars`
|
||||
(SNR as four bars).
|
||||
|
||||
`FullscreenMsgView::wrapLines()` is a standalone pixel-accurate word-wrapper
|
||||
(O(n), variable-width-font aware) reusable by any multi-line layout; it writes
|
||||
into the shared `s_wrap_trans` / `s_wrap_lines` scratch (single-threaded render,
|
||||
@@ -260,21 +287,19 @@ MINI_ICON(ICON_FOO, 5,
|
||||
```
|
||||
|
||||
Draw with `miniIconDraw(display, x, topY, ICON_FOO)` (auto-scaled & centered),
|
||||
`miniIconDrawTop` (exact placement), or the boxed/slot variants
|
||||
(`drawBoxedIcon` = lit when active, `drawSlotIcon` = plain). Bigger page glyphs
|
||||
use `BIG_ICON` / `bigIconDraw`. The home status bar composes these right-to-left
|
||||
with a `blinkOn()` cadence for "leave it on and forget" broadcasts (auto-advert,
|
||||
Live Share, trail, repeater) — follow that pattern when adding an indicator:
|
||||
always shown on e-ink, blinking on OLED.
|
||||
`miniIconDrawTop` (exact placement), `miniIconDrawCentered`, or `drawSlotIcon`
|
||||
(centred in a status-bar slot). Use icons sparingly: headers and the Tools
|
||||
list have none, the Home page row is the main place for them.
|
||||
|
||||
Icons are drawn from a fixed priority-ordered table (`HomeScreen::renderBatteryIndicator()`,
|
||||
`UITask.cpp`); once the row runs out of horizontal space the loop just stops,
|
||||
so the lowest-priority icons silently drop first rather than the whole bar
|
||||
crushing the node name. A blinking icon still reserves its width on the
|
||||
off-phase of its blink, so the row's layout can't visibly shift width as icons
|
||||
blink in and out.
|
||||
The home status bar (`HomeScreen::renderBatteryIndicator()`, `UITask.cpp`)
|
||||
draws plain glyphs right to left from a fixed, priority-ordered table, with
|
||||
no boxes and no blinking: each icon tells a state by its shape (Bluetooth only
|
||||
while a phone is connected, the GPS reticle broken until a fix, a pin while
|
||||
the trail records). Once the row runs out of room the loop stops, so the
|
||||
lowest-priority icons drop first instead of the bar crushing the time. Add an
|
||||
indicator as one more row in that table, at its priority.
|
||||
|
||||
Screens with a Hold-Enter context menu (Nodes, Bot, Admin, Diagnostics, …) pass
|
||||
Screens with a Hold-Enter context menu (Nodes, Messages, Bot, Admin, …) pass
|
||||
`menu_hint=true` to their header call (see §2) so a `≡` glyph advertises the
|
||||
menu; `KEY_CONTEXT_MENU` (Hold-Enter) opens it.
|
||||
|
||||
@@ -363,7 +388,13 @@ with `resolvePersonPos()` (live `[LOC]` share, else last-advertised fix).
|
||||
`chanctl::onRemoved()` (ui-core/ChannelControl.h). New per-contact or
|
||||
per-channel state should clear there too.
|
||||
- **Toasts:** `_task->showAlert("msg", duration_ms)` overlays a transient banner
|
||||
over any screen; no redraw plumbing needed.
|
||||
over any screen (not over the keyboard); no redraw plumbing needed. Use one
|
||||
only for what the screen doesn't already show: a failure ("Send failed",
|
||||
"Contacts full") or an outcome somewhere else. No echo of an action whose
|
||||
result is in view ("Sent", "Deleted", "Counters reset").
|
||||
- **Time:** `millis()` wraps after ~49.7 days. Compare deadlines as
|
||||
`(int32_t)(millis() - deadline) >= 0`, never `millis() >= deadline`, and use
|
||||
0 as "now / none" (`UITask::refreshDue()`, `alertShowing()`).
|
||||
- **Strings:** always `strncpy`+NUL or `snprintf`; treat every name/label as
|
||||
untrusted-length and render through `drawTextEllipsized`.
|
||||
|
||||
@@ -374,7 +405,8 @@ with `resolvePersonPos()` (live `[LOC]` share, else last-advertised fix).
|
||||
```cpp
|
||||
// ui-new/MyToolScreen.h — included by UITask.cpp near the other screens
|
||||
#pragma once
|
||||
#include "icons.h" // drawList + mini-icons
|
||||
#include "icons.h" // drawList, drawScreenHeader, mini-icons
|
||||
#include "InfoKit.h" // valueRow / switchRow
|
||||
#include "../NodePrefs.h"
|
||||
|
||||
class MyToolScreen : public UIScreen {
|
||||
@@ -389,13 +421,15 @@ public:
|
||||
|
||||
int render(DisplayDriver& d) override {
|
||||
d.setTextSize(1);
|
||||
d.drawCenteredHeader("MY TOOL");
|
||||
drawScreenHeader(d, "My tool");
|
||||
int next = 500;
|
||||
drawList(d, ROWS, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
|
||||
drawRowSelection(d, y, sel, reserve);
|
||||
d.setCursor(4, y);
|
||||
d.print(i == 0 ? "Alpha" : i == 1 ? "Bravo" : "Charlie");
|
||||
static const char* const L[ROWS] = { "Alpha", "Bravo", "Charlie" };
|
||||
const int m = info::valueRow(d, y, L[i], "50 m", sel, reserve); // value flush right
|
||||
if (m > 0 && m < next) next = m; // a marquee moving
|
||||
});
|
||||
return 500;
|
||||
return next;
|
||||
}
|
||||
|
||||
bool handleInput(char c) override {
|
||||
|
||||
Reference in New Issue
Block a user