diff --git a/docs/development/l2-hardware-checklist.md b/docs/development/l2-hardware-checklist.md index 7b1d23dd..4e26e996 100644 --- a/docs/development/l2-hardware-checklist.md +++ b/docs/development/l2-hardware-checklist.md @@ -66,6 +66,14 @@ Confirmed: green dot inside the ring, waypoints much better, download works, set - [ ] Room server login from the phone app / L1 still works while this exists (only admin logins go to the new session) - [ ] L1 (ui-new): Tools > Admin works as before (login, saved password, typed values, confirm reboot); it now also skips the login for the node you just used +## New: Diagnostics, auto-advert, compass (2026-09-25) +- [ ] Settings > SYSTEM > Diagnostics: tabs Live / System / Font; Live counters (uptime, rx/tx, heap, noise floor, RSSI/SNR, queue, errors) tick every second +- [ ] Live > Reset → confirm popup → "Counters reset", rx/tx and forwarded go back to 0 +- [ ] System shows firmware, build date, board, node name, frequency / SF / BW / CR, TX power; Font shows Polish, Greek and Cyrillic samples without boxes +- [ ] Settings > Trail, live share, alerts > LIVE SHARE > Auto-advert 30 s: another node sees your advert (with position) every ~30 s; Off stops it; survives a reboot +- [ ] L1: Tools › Auto-Advert shows the value set on L2 (same pref), Tools › Diagnostics unchanged +- [ ] Home page 2 > Compass: without a fix "Waiting for a GPS fix" (GPS off: hint to turn it on); standing still "Move to set the heading"; walking: dial turns so your course is under the amber pointer, degrees + cardinal on the right + ## New: Node name, reboot, lock screen, favourites dial (2026-09-25) - [ ] Settings > NODE > Name: popup with the current name, Enter saves; Home and Settings show the new name; another node sees it after your next advert - [ ] Settings > SYSTEM > Reboot / Power off: confirm popup (red button); reboot comes back normally, messages and settings kept diff --git a/docs/development/ui-core.md b/docs/development/ui-core.md index 7d44ef9d..09b45b43 100644 --- a/docs/development/ui-core.md +++ b/docs/development/ui-core.md @@ -110,7 +110,7 @@ call the same ones, so e.g. "marking a channel read" has one implementation. ### 5. Declarative settings schema -`ui-core/SettingsSchema.h` holds three pages -- navigation (trail, live share, arrival alert, units), display & power (brightness, screen off, wake on message, battery shutdown, GPS power saving, time zone) and messages & contacts (DM resends, contact expiry, favourites first). An entry is a one-byte index by default, or a `values` table over a 1/2/4-byte field (seconds, millivolts, an hour offset, `{1, 0}` for a field stored inverted); side effects run through `UiCore` (`applyGpsInterval()`, `host()->applyDisplayPrefs()`). ui-lvgl renders each page; ui-new still uses its own screens. Radio settings are not schema rows (preset list, typed frequency, radio side effects): `ui-core/RadioControl.h` applies them (`applyParams`, `applyTxPower`, `applyApc`, presets = built-ins + user slots) for both ui-new's Settings > Radio and ui-lvgl's Radio screen. Channel management is `ui-core/ChannelControl.h` (`chanctl::`): add Public / Hashtag / Private (passphrase or 32-hex key), rename, delete, notifications / favourite / scope, and `onRemoved()` -- the cleanup of every channel-keyed pref, run by `UiCore::onChannelRemoved` whoever deleted the channel (this device or the app); contacts get the same through `UiCore::cleanupContactPrefs`. Favourites dial slots: `ui-core/Favourites.h` (`pinContact` / `pinChannel` move an entry that is already on another slot; the slot's name is `contactctl::favName`). The schema's display page also carries the lock screen (`auto_lock`) and the 12-hour clock, which ui-lvgl implements (a slide-to-unlock card after the screen turns off). Remote admin is `ui-core/AdminSession.h` (`UiCore::admin`): login with the saved password (forgotten on a wrong password or a silent timeout), CLI round trips with timeouts, the field table (`admin::`), typed values; results come out one at a time through `take()`. `UiCore` offers login answers and CLI replies to it first; only room logins it wasn't waiting for reach the frontend. ui-new's Tools > Admin and ui-lvgl's Admin screen are views over it. The bot's settings are a table too, `ui-core/BotConfig.h` (`botcfg::`: tabs, rows, the NodePrefs flag / text / hour behind each, reply placeholders); ui-new's Tools > Bot and ui-lvgl's Bot screen render it, the bot itself runs in MyMesh. Room servers: `ui-core/RoomSessions.h` (`UiCore::rooms`) keeps who is logged in this session, the one login in flight (with a timeout) and the saved passwords (saved on success, forgotten on failure); `open(contact)` says whether to go straight in, wait for a background login or ask for a password, and outcomes come out through `take()`. Per-contact helpers are `ui-core/ContactControl.h` (`contactctl::`: DM notification / melody overrides, favourite flag, the `@[name] ` reply prefix, splitting a room post into author and text, naming a message's path hops). ui-new's Messages and ui-lvgl's Chats / thread use both. +`ui-core/SettingsSchema.h` holds three pages -- navigation (trail, live share, arrival alert, units), display & power (brightness, screen off, wake on message, battery shutdown, GPS power saving, time zone) and messages & contacts (DM resends, contact expiry, favourites first). An entry is a one-byte index by default, or a `values` table over a 1/2/4-byte field (seconds, millivolts, an hour offset, `{1, 0}` for a field stored inverted); side effects run through `UiCore` (`applyGpsInterval()`, `host()->applyDisplayPrefs()`). ui-lvgl renders each page; ui-new still uses its own screens. Radio settings are not schema rows (preset list, typed frequency, radio side effects): `ui-core/RadioControl.h` applies them (`applyParams`, `applyTxPower`, `applyApc`, presets = built-ins + user slots) for both ui-new's Settings > Radio and ui-lvgl's Radio screen. Channel management is `ui-core/ChannelControl.h` (`chanctl::`): add Public / Hashtag / Private (passphrase or 32-hex key), rename, delete, notifications / favourite / scope, and `onRemoved()` -- the cleanup of every channel-keyed pref, run by `UiCore::onChannelRemoved` whoever deleted the channel (this device or the app); contacts get the same through `UiCore::cleanupContactPrefs`. Favourites dial slots: `ui-core/Favourites.h` (`pinContact` / `pinChannel` move an entry that is already on another slot; the slot's name is `contactctl::favName`). The schema's display page also carries the lock screen (`auto_lock`) and the 12-hour clock, which ui-lvgl implements (a slide-to-unlock card after the screen turns off). Remote admin is `ui-core/AdminSession.h` (`UiCore::admin`): login with the saved password (forgotten on a wrong password or a silent timeout), CLI round trips with timeouts, the field table (`admin::`), typed values; results come out one at a time through `take()`. `UiCore` offers login answers and CLI replies to it first; only room logins it wasn't waiting for reach the frontend. ui-new's Tools > Admin and ui-lvgl's Admin screen are views over it. The bot's settings are a table too, `ui-core/BotConfig.h` (`botcfg::`: tabs, rows, the NodePrefs flag / text / hour behind each, reply placeholders); ui-new's Tools > Bot and ui-lvgl's Bot screen render it, the bot itself runs in MyMesh. Room servers: `ui-core/RoomSessions.h` (`UiCore::rooms`) keeps who is logged in this session, the one login in flight (with a timeout) and the saved passwords (saved on success, forgotten on failure); `open(contact)` says whether to go straight in, wait for a background login or ask for a password, and outcomes come out through `take()`. Per-contact helpers are `ui-core/ContactControl.h` (`contactctl::`: DM notification / melody overrides, favourite flag, the `@[name] ` reply prefix, splitting a room post into author and text, naming a message's path hops). ui-new's Messages and ui-lvgl's Chats / thread use both. Diagnostics rows are `ui-core/Diagnostics.h` (`diag::`: live counters, system card, font card, counter reset), shown by ui-new's Tools > Diagnostics and ui-lvgl's Settings > Diagnostics. Auto-advert is a schema row (`advert_auto_interval_sec`, sent by MyMesh); ui-new keeps its Tools > Auto-Advert screen over the same pref. The compass (ui-lvgl Home > Compass, ui-new Tools > Compass) reads `UiCore::course`. Replaces the per-item code in `SettingsScreen`: diff --git a/examples/companion_radio/ui-core/Diagnostics.h b/examples/companion_radio/ui-core/Diagnostics.h new file mode 100644 index 00000000..37717732 --- /dev/null +++ b/examples/companion_radio/ui-core/Diagnostics.h @@ -0,0 +1,152 @@ +#pragma once +// Device diagnostics shared by ui-new's Tools > Diagnostics and ui-lvgl's +// Settings > Diagnostics: the live counters (uptime, packets by category, +// heap / stack, radio, queue, error flags), the static system card (firmware, +// board, radio parameters) and the font test card. Each frontend lays the rows +// out its own way. +// +// Packet counts come from Dispatcher's per-type counters, grouped into a few +// categories rather than all 16 raw PAYLOAD_TYPE_* values, so they stay +// readable on a 128x64 OLED. + +#include +#include + +namespace diag { + +struct Row { const char* label; char value[20]; }; +static const int MAX_ROWS = 14; +static const int MAX_LINES = 15; +typedef char Line[40]; + +inline void addRow(Row* rows, int& n, const char* label, const char* fmt, ...) { + if (n >= MAX_ROWS) return; + rows[n].label = label; + va_list ap; va_start(ap, fmt); + vsnprintf(rows[n].value, sizeof(rows[n].value), fmt, ap); + va_end(ap); + n++; +} +inline void addLine(Line* lines, int& n, const char* fmt, ...) { + if (n >= MAX_LINES) return; + va_list ap; va_start(ap, fmt); + vsnprintf(lines[n], sizeof(lines[n]), fmt, ap); + va_end(ap); + n++; +} + +inline uint32_t sumByTypes(bool recv, const uint8_t* types, int n) { + uint32_t total = 0; + for (int i = 0; i < n; i++) + total += recv ? the_mesh.getNumRecvByType(types[i]) : the_mesh.getNumSentByType(types[i]); + return total; +} + +// Live counters, label / value. Returns the row count. +inline int liveRows(Row* rows) { + int n = 0; + uint32_t up = millis() / 1000; + unsigned long d = up / 86400, h = (up % 86400) / 3600, m = (up % 3600) / 60, s = up % 60; + if (d > 0) addRow(rows, n, "Uptime", "%lud %02lu:%02lu:%02lu", d, h, m, s); + else addRow(rows, n, "Uptime", "%02lu:%02lu:%02lu", h, m, s); + + static const uint8_t MSG[] = { PAYLOAD_TYPE_TXT_MSG, PAYLOAD_TYPE_GRP_TXT }; + static const uint8_t ADVERT[] = { PAYLOAD_TYPE_ADVERT }; + static const uint8_t ROUTE[] = { PAYLOAD_TYPE_ACK, PAYLOAD_TYPE_PATH, PAYLOAD_TYPE_TRACE }; + static const uint8_t OTHER[] = { PAYLOAD_TYPE_REQ, PAYLOAD_TYPE_RESPONSE, PAYLOAD_TYPE_ANON_REQ, + PAYLOAD_TYPE_GRP_DATA, PAYLOAD_TYPE_MULTIPART, PAYLOAD_TYPE_CONTROL, + PAYLOAD_TYPE_RAW_CUSTOM }; + unsigned long msg_rx = sumByTypes(true, MSG, 2), msg_tx = sumByTypes(false, MSG, 2); + unsigned long adv_rx = sumByTypes(true, ADVERT, 1), adv_tx = sumByTypes(false, ADVERT, 1); + unsigned long rte_rx = sumByTypes(true, ROUTE, 3), rte_tx = sumByTypes(false, ROUTE, 3); + unsigned long oth_rx = sumByTypes(true, OTHER, 7), oth_tx = sumByTypes(false, OTHER, 7); + // "12345/12345" rather than "rx12345 tx12345": 5-digit counts would collide + // with a long label on a 128 px OLED. "Total rx/tx" spells out the order once. + addRow(rows, n, "Total rx/tx", "%lu/%lu", msg_rx + adv_rx + rte_rx + oth_rx, msg_tx + adv_tx + rte_tx + oth_tx); + addRow(rows, n, "Msg", "%lu/%lu", msg_rx, msg_tx); + addRow(rows, n, "Advert", "%lu/%lu", adv_rx, adv_tx); + addRow(rows, n, "Ack/Path", "%lu/%lu", rte_rx, rte_tx); + addRow(rows, n, "Other", "%lu/%lu", oth_rx, oth_tx); + addRow(rows, n, "Forwarded", "%lu", (unsigned long)the_mesh.getNumForwarded()); + + uint32_t heap_free, heap_total; + DeviceDiag::getHeapStats(heap_free, heap_total); + if (heap_total > 0) addRow(rows, n, "Heap free", "%lu/%luKB", (unsigned long)(heap_free / 1024), (unsigned long)(heap_total / 1024)); + else addRow(rows, n, "Heap free", "N/A"); + addRow(rows, n, "Stack free", "%luB", (unsigned long)DeviceDiag::getStackFreeBytes()); + + addRow(rows, n, "Noise floor", "%d dBm", (int)radio_driver.getNoiseFloor()); + addRow(rows, n, "RSSI/SNR", "%d/%.1f", (int)radio_driver.getLastRSSI(), radio_driver.getLastSNR()); + addRow(rows, n, "Pool free", "%d", the_mesh.getPoolFreeCount()); + addRow(rows, n, "Queue", "%d", the_mesh.getOutboundQueueLen()); + + // Radio error flags since boot / reset (F = queue full, C = CAD timeout, + // R = RX-start timeout), "OK" when none have fired. + uint16_t err = the_mesh.getErrFlags(); + if (err == 0) addRow(rows, n, "Errors", "OK"); + else addRow(rows, n, "Errors", "%s%s%s", (err & ERR_EVENT_FULL) ? "F " : "", + (err & ERR_EVENT_CAD_TIMEOUT) ? "C " : "", (err & ERR_EVENT_STARTRX_TIMEOUT) ? "R " : ""); + if (err) { // drop the trailing space so right-alignment sits flush + char* v = rows[n - 1].value; + size_t len = strlen(v); + if (len && v[len - 1] == ' ') v[len - 1] = '\0'; + } +#if FEAT_RX_POWERSAVE + // RX duty-cycle watchdog recoveries since boot / reset (soft re-arm / hard + // chip reset); 0/0 where duty-cycle power-save never arms. + addRow(rows, n, "RXPS wd s/h", "%lu/%lu", (unsigned long)radio_driver.getRxPsWatchdogSoftCount(), + (unsigned long)radio_driver.getRxPsWatchdogHardCount()); +#endif + return n; +} + +// Zeroes the packet / forward counters, error flags and the radio's own counts. +inline void resetCounters() { + the_mesh.resetStats(); + radio_driver.resetStats(); +} + +// Firmware version minus the commit-hash suffix build.sh appends as the last +// dash-segment (v1.16-solo.0-abcdef -> v1.16-solo.0; the last dash, since a +// tag like v1.21-rc1 has one of its own). +inline void shortVersion(char* out, size_t n) { + const char* ver = FIRMWARE_VERSION; + const char* dash = strrchr(ver, '-'); + size_t len = dash ? (size_t)(dash - ver) : strlen(ver); + if (len >= n) len = n - 1; + memcpy(out, ver, len); + out[len] = '\0'; +} + +// Static system card, one full-width line each. Returns the line count. +inline int systemLines(Line* lines) { + int n = 0; + char sv[24]; + shortVersion(sv, sizeof(sv)); + addLine(lines, n, "FW %s", sv); + addLine(lines, n, "Built %s", FIRMWARE_BUILD_DATE); + addLine(lines, n, "Dev %s", board.getManufacturerName()); + addLine(lines, n, "Node %s", the_mesh.getNodeName()); + NodePrefs* p = the_mesh.getNodePrefs(); + if (p) { + addLine(lines, n, "Freq %.3f MHz", p->freq); + addLine(lines, n, "SF%u BW%.0f CR%u", (unsigned)p->sf, p->bw, (unsigned)p->cr); + addLine(lines, n, "TX %d dBm", (int)p->tx_power_dbm); + } + return n; +} + +// One sample per script the UI font covers, to check coverage by eye. "Acc" +// takes one letter from each of the keyboard's accent-popup groups. +inline int fontLines(Line* lines) { + int n = 0; + addLine(lines, n, "Latin ABCabc xyz"); + addLine(lines, n, "Acc áçďéíłñóřśťúýź"); + addLine(lines, n, "Grk ΑΒΓ αβγξω"); + addLine(lines, n, "Cyr АБВ абвжя"); + addLine(lines, n, "Num 0123456789"); + addLine(lines, n, "Sym @#&*()[]{}/\\+="); + return n; +} + +} // namespace diag diff --git a/examples/companion_radio/ui-core/SettingsSchema.h b/examples/companion_radio/ui-core/SettingsSchema.h index fff1137d..8e607a33 100644 --- a/examples/companion_radio/ui-core/SettingsSchema.h +++ b/examples/companion_radio/ui-core/SettingsSchema.h @@ -112,6 +112,9 @@ static const int32_t TZ[] = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, static void optTz(uint8_t v, char* b, int n, const NodePrefs&) { if (TZ[v] == 0) snprintf(b, n, "UTC"); else snprintf(b, n, "UTC%+ld", (long)TZ[v]); } +// The same steps as ui-new's Tools > Auto-Advert. +static const int32_t AUTO_ADVERT[] = { 0, 30, 60, 120, 300, 600, 1800, 3600 }; +static void optAutoAdvert(uint8_t v, char* b, int n, const NodePrefs&) { fmtSecs(b, n, AUTO_ADVERT[v], "Off"); } static const int32_t INVERTED[] = { 1, 0 }; // switch over a field stored as "off" flag static void optResend(uint8_t v, char* b, int n, const NodePrefs&) { if (v == 0) snprintf(b, n, "Off"); else snprintf(b, n, "%u more", (unsigned)v); @@ -151,6 +154,8 @@ static const Setting ALL[] = { NodePrefs::LOC_SHARE_INTERVAL_COUNT, optGap, nullptr), IDX("Heartbeat", "Resend while standing still", SEC_LIVE_SHARE, loc_share_heartbeat_idx, NodePrefs::LOC_SHARE_HEARTBEAT_COUNT, optHeartbeat, nullptr), + MAP("Auto-advert", "Advert with your position", SEC_LIVE_SHARE, advert_auto_interval_sec, AUTO_ADVERT, + optAutoAdvert, nullptr), SW("Arrival alert", "When you reach the target", SEC_LOCATOR, locator_enabled, rearmLocator), IDX("Radius", nullptr, SEC_LOCATOR, locator_radius_idx, diff --git a/examples/companion_radio/ui-lvgl/CompassScreen.h b/examples/companion_radio/ui-lvgl/CompassScreen.h new file mode 100644 index 00000000..27dbdde9 --- /dev/null +++ b/examples/companion_radio/ui-lvgl/CompassScreen.h @@ -0,0 +1,142 @@ +#pragma once +// Home > Compass -- ui-new's Tools > Compass. The course over ground from GPS +// movement (no magnetometer; the Core's CourseEngine, trail or not) on a dial +// that turns so the heading is up under a fixed pointer, with the degrees and +// cardinal beside it. Standing still, the heading is undefined: the dial greys +// out and a hint says to move. +// +// Single-TU fragment: included by ui-lvgl/UITask.cpp after DiagScreen.h. + +namespace compassview { + +static lv_obj_t* s_dial = nullptr; +static lv_obj_t* s_deg = nullptr; +static lv_obj_t* s_degsign = nullptr; +static lv_obj_t* s_card = nullptr; +static lv_obj_t* s_hint = nullptr; +static int s_cog = 0; +static bool s_have = false; +static const int DIAL = 176; + +} // namespace compassview + +static void onOpenCompass(lv_event_t* e) { (void)e; s_ui->showCompass(); } + +// The dial, drawn over its round background: ticks every 10 degrees (longer +// every 30, longest at the cardinals), N / E / S / W and the 30-degree +// numbers, all turned by the heading; the fixed pointer at the top. +static void onCompassDraw(lv_event_t* e) { + using namespace compassview; + lv_obj_t* o = (lv_obj_t*)lv_event_get_target(e); + lv_layer_t* layer = lv_event_get_layer(e); + lv_area_t a; + lv_obj_get_coords(o, &a); + float cx = (a.x1 + a.x2) / 2.0f, cy = (a.y1 + a.y2) / 2.0f; + float r = DIAL / 2.0f - 14; // the ring; the pointer sits outside it + uint32_t ink = s_have ? theme::TEXT : theme::TEXT_MUTED; + static const char* LBL[12] = { "N", "30", "60", "E", "120", "150", "S", "210", "240", "W", "300", "330" }; + + lv_draw_line_dsc_t ld; + lv_draw_line_dsc_init(&ld); + lv_draw_label_dsc_t td; + lv_draw_label_dsc_init(&td); + td.align = LV_TEXT_ALIGN_CENTER; + for (int deg = 0; deg < 360; deg += 10) { + float ang = (deg - s_cog) * (float)M_PI / 180.0f; + float sx = sinf(ang), sy = -cosf(ang); + bool card = deg % 90 == 0, major = deg % 30 == 0; + float len = card ? 12 : major ? 9 : 5; + ld.width = card ? 3 : major ? 2 : 1; + ld.color = lv_color_hex(ink); + ld.p1.x = cx + sx * r; ld.p1.y = cy + sy * r; + ld.p2.x = cx + sx * (r - len); ld.p2.y = cy + sy * (r - len); + lv_draw_line(layer, &ld); + if (!major) continue; + td.text = LBL[deg / 30]; + td.font = card ? THEME_FONT_LARGE : THEME_FONT_SMALL; + td.color = lv_color_hex(deg == 0 && s_have ? theme::FAIL : card ? ink : theme::TEXT_MUTED); + float lr = r - (card ? 26 : 22); + int32_t h = lv_font_get_line_height(td.font); + int32_t px = (int32_t)(cx + sx * lr), py = (int32_t)(cy + sy * lr); + lv_area_t la = { px - 20, py - h / 2, px + 20, py + h / 2 }; + lv_draw_label(layer, &td, &la); + } + + // Fixed pointer: points down at the ring, the heading always under it. + lv_draw_triangle_dsc_t tri; + lv_draw_triangle_dsc_init(&tri); + tri.bg_color = lv_color_hex(theme::ACCENT); + tri.bg_opa = LV_OPA_COVER; + tri.p[0].x = cx - 8; tri.p[0].y = cy - r - 12; + tri.p[1].x = cx + 8; tri.p[1].y = cy - r - 12; + tri.p[2].x = cx; tri.p[2].y = cy - r + 2; + lv_draw_triangle(layer, &tri); +} + +void UITask::showCompass() { + _screen = SCR_COMPASS; + buildCompass(); +} + +void UITask::buildCompass() { + using namespace compassview; + lv_obj_t* body = newScreen("Compass", true); + lv_obj_set_flex_flow(body, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(body, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_remove_flag(body, LV_OBJ_FLAG_SCROLLABLE); + + s_dial = lv_obj_create(body); + styleSurface(s_dial, theme::BG); + lv_obj_remove_flag(s_dial, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_size(s_dial, DIAL, DIAL); + lv_obj_set_style_radius(s_dial, LV_RADIUS_CIRCLE, 0); + lv_obj_add_event_cb(s_dial, onCompassDraw, LV_EVENT_DRAW_MAIN_END, NULL); + + lv_obj_t* col = lv_obj_create(body); + lv_obj_remove_style_all(col); + lv_obj_set_size(col, 110, LV_SIZE_CONTENT); + lv_obj_set_flex_flow(col, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(col, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_style_pad_row(col, 2, 0); + lv_obj_t* num = lv_obj_create(col); // "044" + a raised degree sign (ui_font_40 is digits only) + lv_obj_remove_style_all(num); + lv_obj_set_size(num, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_set_flex_flow(num, LV_FLEX_FLOW_ROW); + s_deg = label(num, "", THEME_FONT_CLOCK, theme::TEXT); + s_degsign = label(num, "", THEME_FONT_LARGE, theme::TEXT); + s_card = label(col, "", THEME_FONT_LARGE, theme::ACCENT); + s_hint = label(col, "", THEME_FONT_SMALL, theme::TEXT_MUTED); + lv_label_set_long_mode(s_hint, LV_LABEL_LONG_WRAP); + lv_obj_set_width(s_hint, LV_PCT(100)); + lv_obj_set_style_text_align(s_hint, LV_TEXT_ALIGN_CENTER, 0); + refreshCompass(); +} + +// From loop(), once a second. +void UITask::refreshCompass() { + using namespace compassview; + if (_screen != SCR_COMPASS || !s_dial) return; + int32_t lat, lon; + int cog = 0; + const char* hint = nullptr; + if (!_core->course.currentLocation(lat, lon)) + hint = _core->gpsAvailable() && !_core->gpsEnabled() ? "GPS is off - turn it on in Settings" : "Waiting for a GPS fix"; + else if (!_core->course.currentCourse(cog)) hint = "Move to set the heading"; + bool have = hint == nullptr; + if (have != s_have || cog != s_cog) { + s_have = have; + if (have) s_cog = cog; + lv_obj_invalidate(s_dial); + } + if (have) { + lv_label_set_text_fmt(s_deg, "%03d", cog); + lv_label_set_text(s_degsign, "\xC2\xB0"); + lv_label_set_text(s_card, geo::bearingCardinal(cog)); + lv_label_set_text(s_hint, "Course over ground"); + } else { + lv_label_set_text(s_deg, ""); + lv_label_set_text(s_degsign, ""); + lv_label_set_text(s_card, "--"); + lv_label_set_text(s_hint, hint); + } +} diff --git a/examples/companion_radio/ui-lvgl/DiagScreen.h b/examples/companion_radio/ui-lvgl/DiagScreen.h new file mode 100644 index 00000000..6d64c81f --- /dev/null +++ b/examples/companion_radio/ui-lvgl/DiagScreen.h @@ -0,0 +1,112 @@ +#pragma once +// Settings > Diagnostics -- ui-new's Tools > Diagnostics. Tabs Live / System / +// Font; the rows come from ui-core/Diagnostics.h. Live refreshes every second +// and its header button resets the counters (after a confirm). +// +// Single-TU fragment: included by ui-lvgl/UITask.cpp after DeviceScreen.h. + +namespace diagview { + +enum : uint8_t { TAB_LIVE, TAB_SYSTEM, TAB_FONT, TAB_COUNT }; +static uint8_t s_tab = TAB_LIVE; // kept across visits +static lv_obj_t* s_list = nullptr; +static lv_obj_t* s_vals[diag::MAX_ROWS]; +static int s_rows = 0; + +} // namespace diagview + +static void onOpenDiag(lv_event_t* e) { (void)e; s_ui->showDiag(); } +static void onDiagTab(lv_event_t* e) { + s_ui->diagTab((int)lv_buttonmatrix_get_selected_button((lv_obj_t*)lv_event_get_target(e))); +} +static void onDiagReset(lv_event_t* e) { (void)e; s_ui->diagResetPopup(); } +static void onDiagResetGo(lv_event_t* e) { (void)e; s_ui->diagReset(); } + +void UITask::showDiag() { + _screen = SCR_DIAG; + buildDiag(); +} + +void UITask::diagTab(int tab) { + if (tab < 0 || tab >= diagview::TAB_COUNT) return; + diagview::s_tab = (uint8_t)tab; + buildDiag(); +} + +void UITask::buildDiag() { + using namespace diagview; + lv_obj_t* body = newScreen("Diagnostics", true); + lv_obj_set_style_pad_row(body, 4, 0); + if (s_tab == TAB_LIVE && _header) headerButton(_header, LV_SYMBOL_REFRESH " Reset", onDiagReset, 4, NULL); + + static const char* TABS[] = { "Live", "System", "Font", "" }; + lv_obj_t* tabs = segmented(body, TABS, s_tab, lv_pct(100), 34); + lv_obj_set_style_bg_color(tabs, lv_color_hex(theme::SURFACE), LV_PART_ITEMS); + lv_obj_add_event_cb(tabs, onDiagTab, LV_EVENT_VALUE_CHANGED, NULL); + + s_list = lv_obj_create(body); + styleSurface(s_list, theme::SURFACE); + lv_obj_set_style_radius(s_list, theme::RADIUS, 0); + lv_obj_set_style_pad_all(s_list, theme::PAD, 0); + lv_obj_set_style_pad_row(s_list, 3, 0); + lv_obj_set_width(s_list, LV_PCT(100)); + lv_obj_set_flex_grow(s_list, 1); + lv_obj_set_flex_flow(s_list, LV_FLEX_FLOW_COLUMN); + lv_obj_set_scrollbar_mode(s_list, LV_SCROLLBAR_MODE_ACTIVE); + s_rows = 0; + + if (s_tab == TAB_LIVE) { + diag::Row rows[diag::MAX_ROWS]; + s_rows = diag::liveRows(rows); + for (int i = 0; i < s_rows; i++) { + lv_obj_t* r = lv_obj_create(s_list); + lv_obj_remove_style_all(r); + lv_obj_remove_flag(r, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_size(r, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_align(label(r, rows[i].label, THEME_FONT_BODY, theme::TEXT_MUTED), LV_ALIGN_LEFT_MID, 0, 0); + s_vals[i] = label(r, rows[i].value, THEME_FONT_BODY, theme::TEXT); + lv_obj_align(s_vals[i], LV_ALIGN_RIGHT_MID, 0, 0); + } + return; + } + diag::Line lines[diag::MAX_LINES]; + int n = s_tab == TAB_SYSTEM ? diag::systemLines(lines) : diag::fontLines(lines); + for (int i = 0; i < n; i++) { + lv_obj_t* l = label(s_list, lines[i], s_tab == TAB_FONT ? THEME_FONT_TITLE : THEME_FONT_BODY, theme::TEXT); + lv_label_set_long_mode(l, LV_LABEL_LONG_WRAP); + lv_obj_set_width(l, LV_PCT(100)); + } +} + +// From loop(), once a second: the Live values in place. +void UITask::refreshDiag() { + using namespace diagview; + if (_screen != SCR_DIAG || s_tab != TAB_LIVE || _nav_overlay) return; + diag::Row rows[diag::MAX_ROWS]; + int n = diag::liveRows(rows); + if (n != s_rows) { buildDiag(); return; } + for (int i = 0; i < n; i++) + if (strcmp(lv_label_get_text(s_vals[i]), rows[i].value) != 0) lv_label_set_text(s_vals[i], rows[i].value); +} + +void UITask::diagResetPopup() { + lv_obj_t* panel = navPopupPanel("Reset counters?", false); + lv_obj_t* t = label(panel, "Zeroes the packet counts, forwarded count and radio errors.", THEME_FONT_SMALL, + theme::TEXT_MUTED); + lv_label_set_long_mode(t, LV_LABEL_LONG_WRAP); + lv_obj_set_width(t, LV_PCT(100)); + lv_obj_t* b = lv_button_create(panel); + lv_obj_set_size(b, LV_PCT(100), 40); + lv_obj_set_style_shadow_width(b, 0, 0); + lv_obj_set_style_radius(b, theme::RADIUS, 0); + lv_obj_set_style_bg_color(b, lv_color_hex(theme::FAIL), 0); + lv_obj_add_event_cb(b, onDiagResetGo, LV_EVENT_CLICKED, NULL); + lv_obj_center(label(b, LV_SYMBOL_REFRESH " Reset", THEME_FONT_BODY, theme::TEXT)); +} + +void UITask::diagReset() { + diag::resetCounters(); + navClosePopup(); + refreshDiag(); + showToast("Counters reset"); +} diff --git a/examples/companion_radio/ui-lvgl/Theme.h b/examples/companion_radio/ui-lvgl/Theme.h index a3d07de9..16847a3a 100644 --- a/examples/companion_radio/ui-lvgl/Theme.h +++ b/examples/companion_radio/ui-lvgl/Theme.h @@ -39,4 +39,5 @@ namespace theme { #define UI_SYMBOL_CLOCK "\xEF\x80\x97" // U+F017, Clock tools #define UI_SYMBOL_STOPWATCH "\xEF\x8B\xB2" // U+F2F2 #define UI_SYMBOL_RADIO "\xEF\x94\x99" // U+F519, broadcast tower + #define UI_SYMBOL_CHART "\xEF\x82\x80" // U+F080, diagnostics } diff --git a/examples/companion_radio/ui-lvgl/UITask.cpp b/examples/companion_radio/ui-lvgl/UITask.cpp index 4078b5f4..7ca51980 100644 --- a/examples/companion_radio/ui-lvgl/UITask.cpp +++ b/examples/companion_radio/ui-lvgl/UITask.cpp @@ -13,6 +13,7 @@ #include "../ui-core/GpsAverager.h" #include "../ui-core/TrackBack.h" #include "../ui-core/RadioControl.h" +#include "../ui-core/Diagnostics.h" #include "../ui-core/ChannelControl.h" #include "../ui-core/BotConfig.h" #include "Theme.h" @@ -189,6 +190,8 @@ void UITask::loop() { refreshStatusBar(); refreshLock(); if (_screen == SCR_HOME) refreshHome(); + refreshDiag(); + refreshCompass(); } if (locked()) lockPoll(); else if (_screen == SCR_HOME) homeSwipePoll(); @@ -492,6 +495,8 @@ void UITask::back() { case SCR_CHANNEL_EDIT: showChats(); break; case SCR_BOT: if (_nav_overlay) navClosePopup(); else showHome(); break; case SCR_FAVS: if (_nav_overlay) navClosePopup(); else showHome(); break; + case SCR_DIAG: if (_nav_overlay) navClosePopup(); else showSettings(); break; + case SCR_COMPASS: showHome(); break; case SCR_ADMIN: if (_nav_overlay) navClosePopup(); else adminLeave(); break; case SCR_SETTINGS: if (_nav_overlay) navClosePopup(); else showHome(); break; case SCR_SETTINGS_NAV: showSettings(); break; @@ -530,6 +535,8 @@ static void onOpenNav(lv_event_t* e) { (void)e; s_ui->openMap(true); } static void onOpenClock(lv_event_t* e); // ClockScreen.h static void onOpenBot(lv_event_t* e); // BotScreen.h static void onOpenFavourites(lv_event_t* e); // DeviceScreen.h +static void onOpenCompass(lv_event_t* e); // CompassScreen.h +static void onOpenDiag(lv_event_t* e); // DiagScreen.h static void onNodeName(lv_event_t* e); static void onPowerRow(lv_event_t* e); @@ -544,6 +551,7 @@ static const App APPS[] = { { LV_SYMBOL_SETTINGS, "Settings", onOpenSettings, false }, // Page 2: tools { UI_SYMBOL_STAR, "Favourites", onOpenFavourites, false }, + { UI_SYMBOL_COMPASS, "Compass", onOpenCompass, false }, { UI_SYMBOL_CLOCK, "Clock", onOpenClock, false }, { LV_SYMBOL_CHARGE, "Bot", onOpenBot, false }, }; @@ -2007,7 +2015,7 @@ void UITask::buildSettings() { if (_core->gpsEnabled()) lv_obj_add_state(sw, LV_STATE_CHECKED); lv_obj_add_event_cb(sw, onGpsSwitch, LV_EVENT_VALUE_CHANGED, NULL); } - listRow(body, UI_SYMBOL_COMPASS " Trail, live share, alerts", "Point spacing, auto-pause, sharing, radius", + listRow(body, UI_SYMBOL_COMPASS " Trail, live share, alerts", "Trail, sharing, auto-advert, radius", onOpenSchemaPage, (void*)(uintptr_t)settings::PG_NAV); sectionTitle(body, "DEVICE"); listRow(body, LV_SYMBOL_EYE_OPEN " Display & power", "Brightness, screen off, battery, GPS, time zone", @@ -2028,6 +2036,7 @@ void UITask::buildSettings() { label(body, "Hold a letter for accents and other variants.", THEME_FONT_SMALL, theme::TEXT_MUTED); sectionTitle(body, "SYSTEM"); + listRow(body, UI_SYMBOL_CHART " Diagnostics", "Packet counts, memory, radio, firmware", onOpenDiag, NULL); listRow(body, LV_SYMBOL_REFRESH " Reboot", NULL, onPowerRow, (void*)(uintptr_t)1); listRow(body, LV_SYMBOL_POWER " Power off", NULL, onPowerRow, (void*)(uintptr_t)0); @@ -2051,3 +2060,5 @@ void UITask::setKeyboardAlphabets(int main_idx, int alt_sel) { #include "ConversationScreen.h" #include "DeviceScreen.h" +#include "DiagScreen.h" +#include "CompassScreen.h" diff --git a/examples/companion_radio/ui-lvgl/UITask.h b/examples/companion_radio/ui-lvgl/UITask.h index 000d5987..ad5c75cf 100644 --- a/examples/companion_radio/ui-lvgl/UITask.h +++ b/examples/companion_radio/ui-lvgl/UITask.h @@ -153,6 +153,11 @@ public: void unlockScreen(); bool locked() const; void showFavourites(); + void showDiag(); + void diagTab(int tab); + void diagResetPopup(); + void diagReset(); + void showCompass(); void favTap(int slot); void favHold(int slot); void favAction(uint8_t act); @@ -167,7 +172,7 @@ public: void openAdminFor(const ContactInfo& ci, bool from_picker) { (void)ci; (void)from_picker; } private: - enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE, SCR_MAP, SCR_WIFI, SCR_SETTINGS_NAV, SCR_CLOCK, SCR_RADIO, SCR_CHANNEL_EDIT, SCR_ADMIN, SCR_BOT, SCR_FAVS }; + enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE, SCR_MAP, SCR_WIFI, SCR_SETTINGS_NAV, SCR_CLOCK, SCR_RADIO, SCR_CHANNEL_EDIT, SCR_ADMIN, SCR_BOT, SCR_FAVS, SCR_DIAG, SCR_COMPASS }; void buildStatusBar(); void refreshStatusBar(); @@ -232,6 +237,10 @@ private: void refreshLock(); void lockPoll(); void buildFavourites(); + void buildDiag(); + void refreshDiag(); + void buildCompass(); + void refreshCompass(); void favPickPopup(int slot); void adminValuePopup(); void adminTextPopup(const char* text, bool digits); diff --git a/examples/companion_radio/ui-lvgl/fonts/generate.sh b/examples/companion_radio/ui-lvgl/fonts/generate.sh index 3e09489e..61625f65 100755 --- a/examples/companion_radio/ui-lvgl/fonts/generate.sh +++ b/examples/companion_radio/ui-lvgl/fonts/generate.sh @@ -29,8 +29,8 @@ TEXT="$TEXT,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122" # plus 61612 = globe (keyboard script key), 61445 = star (favourite), # 62073 = map, 61632 = users (home tiles), 61774 = compass (Navigate), # 61476 = flag (waypoint), 62405 = map marker (mark here), 61463 = clock, -# 62194 = stopwatch, 62745 = broadcast tower (radio) -SYMS="62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650" +# 62194 = stopwatch, 62745 = broadcast tower (radio), 61568 = bar chart (diagnostics) +SYMS="61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650" CONV="npx -y lv_font_conv@1.5.3" gen() { # size weight ranges name diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c index c5055826..14c76117 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 12 px * Bpp: 4 - * Opts: --bpp 4 --size 12 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_12 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c + * Opts: --bpp 4 --size 12 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_12 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE @@ -6686,6 +6686,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x9d, 0x0, 0x3c, 0xce, 0xf4, 0x58, 0x7, 0xff, 0xc1, 0x0, 0x3f, 0xc8, + /* U+F080 "" */ + 0xf7, 0x0, 0x88, 0x80, 0x3, 0xf3, 0xf, 0x0, + 0xa6, 0x40, 0x7, 0x7, 0x0, 0xe7, 0x72, 0xd8, + 0x7, 0x8c, 0x40, 0x1a, 0x80, 0x1e, 0xc6, 0x0, + 0xff, 0xe0, 0x3b, 0xbc, 0x1c, 0x1c, 0x2, 0xf7, + 0xbb, 0x3f, 0x9f, 0x98, 0x24, 0x47, 0xf3, 0x91, + 0xbb, 0xff, 0x40, + /* U+F093 "" */ 0x0, 0xe2, 0x20, 0x7, 0xf1, 0xe6, 0xc, 0x3, 0xe3, 0xd1, 0x16, 0x98, 0x7, 0x1e, 0x88, 0x0, @@ -8046,39 +8054,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 32682, .adv_w = 168, .box_w = 11, .box_h = 7, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 32716, .adv_w = 240, .box_w = 16, .box_h = 10, .ofs_x = -1, .ofs_y = 0}, {.bitmap_index = 32776, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 32796, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 32853, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 32917, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 32987, .adv_w = 240, .box_w = 15, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33061, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33122, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33162, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33206, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33238, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33277, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 33323, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33368, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33421, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33477, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 33540, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33612, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33635, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33710, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 32796, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 32839, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32896, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 32960, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33030, .adv_w = 240, .box_w = 15, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33104, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33165, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33205, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33249, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33281, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33320, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 33366, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33411, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33464, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33520, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 33583, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33655, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33678, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, {.bitmap_index = 33753, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33802, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33851, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33900, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33942, .adv_w = 216, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33979, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 34044, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34108, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33796, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33845, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33894, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33943, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33985, .adv_w = 216, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34022, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34087, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, {.bitmap_index = 34151, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34212, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 34279, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34331, .adv_w = 240, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34413, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 34468, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34497, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 34194, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34255, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 34322, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34374, .adv_w = 240, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34456, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 34511, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34540, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -8106,11 +8115,12 @@ static const uint16_t unicode_list_12[] = { 0xcefb, 0xcefd, 0xceff, 0xcf01, 0xcf03, 0xcf06, 0xcf0b, 0xcf0e, 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, - 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, - 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, - 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, 0xd0d5, - 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, - 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, 0xd78c + 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, + 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, + 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, + 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, + 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, + 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -8166,7 +8176,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 72, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -8314,7 +8324,7 @@ static const uint8_t kern_left_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Map glyph_ids to kern right classes*/ @@ -8456,7 +8466,7 @@ static const uint8_t kern_right_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c index da950b40..1dfa1a22 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 14 px * Bpp: 4 - * Opts: --bpp 4 --size 14 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_14 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c + * Opts: --bpp 4 --size 14 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_14 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE @@ -7620,6 +7620,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xf8, 0x8c, 0xf2, 0x48, 0x7, 0xff, 0xfc, 0x3, 0xf9, 0x40, 0x3f, 0xf8, 0xc, + /* U+F080 "" */ + 0x86, 0x0, 0xfe, 0x58, 0x7, 0xa0, 0xd, 0x30, + 0x1, 0x7b, 0x88, 0x7, 0x9d, 0x40, 0x3f, 0xf8, + 0x47, 0xec, 0x1, 0xe1, 0x20, 0x9, 0xc0, 0x40, + 0x3d, 0x7a, 0x20, 0x1f, 0xfc, 0xd9, 0x90, 0xdc, + 0xac, 0xac, 0xc8, 0x40, 0x23, 0x60, 0x54, 0x16, + 0x23, 0x60, 0x1, 0xe6, 0x7f, 0xd6, 0x60, 0x67, + 0xff, 0x20, + /* U+F093 "" */ 0x0, 0xff, 0xe3, 0x8e, 0xe8, 0x40, 0x3f, 0x87, 0x8, 0x98, 0x20, 0x1f, 0xe, 0x10, 0x0, 0xb0, @@ -9037,39 +9046,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 40136, .adv_w = 196, .box_w = 13, .box_h = 8, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 40181, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 40252, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 40281, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40353, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 40432, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40525, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40623, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40704, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40752, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40808, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40848, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 40901, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 40957, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41020, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41086, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41159, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 41236, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41325, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41357, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41454, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41506, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41561, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41616, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41671, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41720, .adv_w = 252, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41765, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41845, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41929, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41985, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42050, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 42127, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42200, .adv_w = 280, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42315, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 42393, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42429, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 40281, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40331, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40403, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 40482, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40575, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40673, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40754, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40802, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40858, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40898, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40951, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 41007, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41070, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41136, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41209, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 41286, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41375, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41407, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41504, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41556, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41611, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41666, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41721, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41770, .adv_w = 252, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41815, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41895, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41979, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42035, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42100, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 42177, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42250, .adv_w = 280, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42365, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 42443, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42479, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -9097,11 +9107,12 @@ static const uint16_t unicode_list_12[] = { 0xcefb, 0xcefd, 0xceff, 0xcf01, 0xcf03, 0xcf06, 0xcf0b, 0xcf0e, 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, - 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, - 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, - 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, 0xd0d5, - 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, - 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, 0xd78c + 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, + 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, + 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, + 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, + 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, + 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -9157,7 +9168,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 72, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -9305,7 +9316,7 @@ static const uint8_t kern_left_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Map glyph_ids to kern right classes*/ @@ -9447,7 +9458,7 @@ static const uint8_t kern_right_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c index fefabd90..21601745 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 16 px * Bpp: 4 - * Opts: --bpp 4 --size 16 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_16 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c + * Opts: --bpp 4 --size 16 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_16 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE @@ -8712,6 +8712,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xff, 0xd, 0xc0, 0x3f, 0xff, 0xe0, 0x1f, 0xfd, 0x97, 0x0, 0xff, 0xe1, 0x38, + /* U+F080 "" */ + 0xee, 0x0, 0x7f, 0xdf, 0xe0, 0x11, 0x0, 0x77, + 0xf8, 0x3, 0xff, 0xab, 0xfe, 0x0, 0xff, 0xe6, + 0x7f, 0x80, 0x3f, 0xfc, 0x5f, 0xe0, 0xff, 0x7, + 0xf8, 0x3f, 0xc0, 0x1f, 0xfc, 0x7f, 0xff, 0xfe, + 0xf, 0x18, 0x7, 0xff, 0xc, + /* U+F093 "" */ 0x0, 0xfa, 0xec, 0x1, 0xff, 0xc1, 0xb4, 0x45, 0x80, 0x7f, 0xd6, 0x80, 0x4, 0xb0, 0xf, 0xeb, @@ -10155,39 +10162,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 48847, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 48904, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, {.bitmap_index = 48992, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 49021, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49089, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 49183, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49291, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49401, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49492, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49539, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49591, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49646, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 49705, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 49773, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49834, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49904, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 49970, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 50059, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50161, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50194, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 50307, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50352, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50396, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50440, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50486, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50526, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50585, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 50686, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 50782, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50837, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50919, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 51013, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 51095, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 51226, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 51315, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 51354, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 49021, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 49058, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49126, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49220, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49328, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49438, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49529, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49576, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49628, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49683, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 49742, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49810, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49871, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49941, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 50007, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 50096, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50198, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50231, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50344, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50389, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50433, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50477, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50523, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50563, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50622, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50723, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 50819, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50874, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50956, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 51050, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51132, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 51263, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 51352, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51391, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} }; /*--------------------- @@ -10215,11 +10223,12 @@ static const uint16_t unicode_list_12[] = { 0xcefb, 0xcefd, 0xceff, 0xcf01, 0xcf03, 0xcf06, 0xcf0b, 0xcf0e, 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, - 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, - 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, - 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, 0xd0d5, - 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, - 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, 0xd78c + 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, + 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, + 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, + 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, + 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, + 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -10275,7 +10284,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 72, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -10423,7 +10432,7 @@ static const uint8_t kern_left_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Map glyph_ids to kern right classes*/ @@ -10565,7 +10574,7 @@ static const uint8_t kern_right_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c index d40c8091..77a24a30 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 20 px * Bpp: 4 - * Opts: --bpp 4 --size 20 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_20 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c + * Opts: --bpp 4 --size 20 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_20 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE @@ -10954,6 +10954,18 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x80, 0x7f, 0x84, 0x3, 0xff, 0x8c, 0x36, 0x20, 0x1f, 0xfc, 0x41, 0xb0, + /* U+F080 "" */ + 0xef, 0x60, 0xf, 0xfe, 0xe, 0xfb, 0x80, 0x87, + 0x0, 0x7a, 0xec, 0x60, 0x18, 0xc3, 0x80, 0x3f, + 0x85, 0x10, 0xa0, 0x1f, 0xfc, 0x93, 0x20, 0xf, + 0xfe, 0x2b, 0xe6, 0x80, 0x7f, 0xf1, 0x7c, 0x3, + 0xff, 0x81, 0x58, 0x80, 0x1f, 0xfc, 0x55, 0x3c, + 0x0, 0xff, 0xec, 0x88, 0x70, 0x80, 0xf, 0x80, + 0x40, 0xc3, 0x80, 0x3d, 0xde, 0xc1, 0xfe, 0x56, + 0xfe, 0xd, 0xf7, 0x0, 0xff, 0xe5, 0xa4, 0x47, + 0xff, 0x11, 0x80, 0x6, 0xef, 0xff, 0xc4, 0x95, + 0x0, 0xff, 0xe3, 0x8, + /* U+F093 "" */ 0x0, 0xfe, 0x31, 0x0, 0xff, 0xe2, 0xb6, 0x60, 0x40, 0x3f, 0xf8, 0x6d, 0x20, 0x58, 0x20, 0x1f, @@ -12543,39 +12555,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 66503, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 2}, {.bitmap_index = 66581, .adv_w = 400, .box_w = 26, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, {.bitmap_index = 66699, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 66743, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 66853, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 66991, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 67150, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67319, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67467, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 67540, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67633, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 67693, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 67783, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 67876, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 67964, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68075, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 68201, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 68322, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68473, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68521, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 68685, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 68752, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 68820, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 68887, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 68954, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 69014, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 69101, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 69235, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 69382, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69469, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69598, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 69738, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69851, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 70055, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 70175, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 70234, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 66743, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 66819, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 66929, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 67067, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 67226, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67395, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67543, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 67616, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67709, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 67769, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 67859, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 67952, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68040, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68151, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 68277, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 68398, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68549, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68597, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 68761, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 68828, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 68896, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 68963, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 69030, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 69090, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 69177, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 69311, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 69458, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 69545, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 69674, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 69814, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 69927, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70131, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 70251, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70310, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1} }; /*--------------------- @@ -12603,11 +12616,12 @@ static const uint16_t unicode_list_12[] = { 0xcefb, 0xcefd, 0xceff, 0xcf01, 0xcf03, 0xcf06, 0xcf0b, 0xcf0e, 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, - 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, - 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, - 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, 0xd0d5, - 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, - 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, 0xd78c + 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, + 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, + 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, + 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, + 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, + 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -12663,7 +12677,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 72, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -12811,7 +12825,7 @@ static const uint8_t kern_left_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Map glyph_ids to kern right classes*/ @@ -12953,7 +12967,7 @@ static const uint8_t kern_right_class_mapping[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-new/DiagnosticsScreen.h b/examples/companion_radio/ui-new/DiagnosticsScreen.h index 6e113b93..77b3a904 100644 --- a/examples/companion_radio/ui-new/DiagnosticsScreen.h +++ b/examples/companion_radio/ui-new/DiagnosticsScreen.h @@ -1,13 +1,12 @@ #pragma once #include #include -#include #include -#include #include "icons.h" #include "PopupMenu.h" #include "TabBar.h" #include "../MyMesh.h" +#include "../ui-core/Diagnostics.h" extern MyMesh the_mesh; @@ -22,10 +21,8 @@ extern MyMesh the_mesh; // Font — a rendering test card: one sample line per script the UI font // claims to cover (Latin, diacritics, Greek, Cyrillic, digits, // symbols), so the on-device font can be eyeballed for coverage. -// The packet counts are built from Dispatcher's per-type counters — grouped -// into a handful of categories rather than all 16 raw PAYLOAD_TYPE_* values, -// so they stay readable on a 128x64 OLED. Every tab falls back to scrolling on -// screens too small to show its rows at once. +// The rows themselves come from the UI Core (ui-core/Diagnostics.h). Every tab +// falls back to scrolling on screens too small to show its rows at once. class DiagnosticsScreen : public UIScreen { UITask* _task; int _scroll = 0; @@ -35,169 +32,12 @@ class DiagnosticsScreen : public UIScreen { enum Tab : uint8_t { TAB_LIVE, TAB_SYSTEM, TAB_FONT, TAB_COUNT }; static const char* const TAB_LABELS[TAB_COUNT]; - struct Row { const char* label; char value[20]; }; - static const int MAX_ROWS = 14; - Row _rows[MAX_ROWS]; + // Rows / lines built by the Core (ui-core/Diagnostics.h). + diag::Row _rows[diag::MAX_ROWS]; int _row_count = 0; - - // Full-width text lines (System / Font tabs) — long values (device model, - // node name) don't fit the Live tab's narrow right-aligned value column, so - // these tabs draw one ellipsized line each instead of a label/value pair. - static const int MAX_LINES = 15; - char _lines[MAX_LINES][40]; + diag::Line _lines[diag::MAX_LINES]; int _line_count = 0; - void addRow(const char* label, const char* value) { - if (_row_count >= MAX_ROWS) return; - _rows[_row_count].label = label; - strncpy(_rows[_row_count].value, value, sizeof(_rows[_row_count].value) - 1); - _rows[_row_count].value[sizeof(_rows[_row_count].value) - 1] = 0; - _row_count++; - } - // "12345/12345" rather than "rx12345 tx12345" — at 5-digit counts (a busy - // repeater after weeks of uptime) the longer form collides with the value - // column on a 128px OLED when paired with a long label like "Ack/Path". - // The "Total rx/tx" label spells out the rx/tx order once for every row below it. - void addRxTxRow(const char* label, uint32_t rx, uint32_t tx) { - char buf[20]; - snprintf(buf, sizeof(buf), "%lu/%lu", (unsigned long)rx, (unsigned long)tx); - addRow(label, buf); - } - - void addLine(const char* fmt, ...) { - if (_line_count >= MAX_LINES) return; - va_list ap; va_start(ap, fmt); - vsnprintf(_lines[_line_count], sizeof(_lines[_line_count]), fmt, ap); - va_end(ap); - _line_count++; - } - - static uint32_t sumByTypes(bool recv, const uint8_t* types, int n) { - uint32_t total = 0; - for (int i = 0; i < n; i++) - total += recv ? the_mesh.getNumRecvByType(types[i]) : the_mesh.getNumSentByType(types[i]); - return total; - } - - void buildLiveRows() { - _row_count = 0; - - uint32_t up_secs = millis() / 1000; - char buf[20]; - uint32_t d = up_secs / 86400, h = (up_secs % 86400) / 3600, m = (up_secs % 3600) / 60, s = up_secs % 60; - if (d > 0) snprintf(buf, sizeof(buf), "%lud %02lu:%02lu:%02lu", (unsigned long)d, (unsigned long)h, (unsigned long)m, (unsigned long)s); - else snprintf(buf, sizeof(buf), "%02lu:%02lu:%02lu", (unsigned long)h, (unsigned long)m, (unsigned long)s); - addRow("Uptime", buf); - - static const uint8_t MSG_TYPES[] = { PAYLOAD_TYPE_TXT_MSG, PAYLOAD_TYPE_GRP_TXT }; - static const uint8_t ADVERT_TYPES[] = { PAYLOAD_TYPE_ADVERT }; - static const uint8_t ROUTE_TYPES[] = { PAYLOAD_TYPE_ACK, PAYLOAD_TYPE_PATH, PAYLOAD_TYPE_TRACE }; - static const uint8_t OTHER_TYPES[] = { PAYLOAD_TYPE_REQ, PAYLOAD_TYPE_RESPONSE, PAYLOAD_TYPE_ANON_REQ, - PAYLOAD_TYPE_GRP_DATA, PAYLOAD_TYPE_MULTIPART, PAYLOAD_TYPE_CONTROL, - PAYLOAD_TYPE_RAW_CUSTOM }; - - uint32_t msg_rx = sumByTypes(true, MSG_TYPES, 2), msg_tx = sumByTypes(false, MSG_TYPES, 2); - uint32_t adv_rx = sumByTypes(true, ADVERT_TYPES, 1), adv_tx = sumByTypes(false, ADVERT_TYPES, 1); - uint32_t rte_rx = sumByTypes(true, ROUTE_TYPES, 3), rte_tx = sumByTypes(false, ROUTE_TYPES, 3); - uint32_t oth_rx = sumByTypes(true, OTHER_TYPES, 7), oth_tx = sumByTypes(false, OTHER_TYPES, 7); - - addRxTxRow("Total rx/tx", msg_rx + adv_rx + rte_rx + oth_rx, msg_tx + adv_tx + rte_tx + oth_tx); - addRxTxRow("Msg", msg_rx, msg_tx); - addRxTxRow("Advert", adv_rx, adv_tx); - addRxTxRow("Ack/Path", rte_rx, rte_tx); - addRxTxRow("Other", oth_rx, oth_tx); - - snprintf(buf, sizeof(buf), "%lu", (unsigned long)the_mesh.getNumForwarded()); - addRow("Forwarded", buf); - - uint32_t heap_free, heap_total; - DeviceDiag::getHeapStats(heap_free, heap_total); - if (heap_total > 0) snprintf(buf, sizeof(buf), "%lu/%luKB", (unsigned long)(heap_free / 1024), (unsigned long)(heap_total / 1024)); - else strcpy(buf, "N/A"); - addRow("Heap free", buf); - - uint32_t stack_free = DeviceDiag::getStackFreeBytes(); - snprintf(buf, sizeof(buf), "%luB", (unsigned long)stack_free); - addRow("Stack free", buf); - - snprintf(buf, sizeof(buf), "%d dBm", (int)radio_driver.getNoiseFloor()); - addRow("Noise floor", buf); - snprintf(buf, sizeof(buf), "%d/%.1f", (int)radio_driver.getLastRSSI(), radio_driver.getLastSNR()); - addRow("RSSI/SNR", buf); - - snprintf(buf, sizeof(buf), "%d", the_mesh.getPoolFreeCount()); - addRow("Pool free", buf); - snprintf(buf, sizeof(buf), "%d", the_mesh.getOutboundQueueLen()); - addRow("Queue", buf); - - // Radio error flags since boot/reset, decoded to short tokens (F=queue full, - // C=CAD timeout, R=RX-start timeout). "OK" when none have fired. - uint16_t err = the_mesh.getErrFlags(); - if (err == 0) strcpy(buf, "OK"); - else { - buf[0] = '\0'; - if (err & ERR_EVENT_FULL) strcat(buf, "F "); - if (err & ERR_EVENT_CAD_TIMEOUT) strcat(buf, "C "); - if (err & ERR_EVENT_STARTRX_TIMEOUT) strcat(buf, "R "); - int len = strlen(buf); // drop the trailing space so right-alignment sits flush - if (len > 0 && buf[len - 1] == ' ') buf[len - 1] = '\0'; - } - addRow("Errors", buf); - -#if FEAT_RX_POWERSAVE - // RX duty-cycle watchdog recovery counts since boot/reset (soft re-arm / - // hard chip reset). Always 0/0 on radios or profiles that never arm - // duty-cycle power-save (repeaters force it off — see applyPowerSave()). - snprintf(buf, sizeof(buf), "%lu/%lu", (unsigned long)radio_driver.getRxPsWatchdogSoftCount(), - (unsigned long)radio_driver.getRxPsWatchdogHardCount()); - addRow("RXPS wd s/h", buf); -#endif - } - - void buildSystemLines() { - _line_count = 0; - - // Firmware version, minus the commit-hash suffix build.sh appends as the - // LAST dash-segment (v1.16-solo.0-abcdef -> v1.16-solo.0) — same strip the - // boot screen does; the last dash, not the first, since a tag like - // v1.21-rc1 has a dash of its own before the hash. - const char* ver = FIRMWARE_VERSION; - const char* dash = strrchr(ver, '-'); - int plen = dash ? (int)(dash - ver) : (int)strlen(ver); - char sv[24]; - if (plen >= (int)sizeof(sv)) plen = sizeof(sv) - 1; - memcpy(sv, ver, plen); sv[plen] = '\0'; - - addLine("FW %s", sv); - addLine("Built %s", FIRMWARE_BUILD_DATE); - addLine("Dev %s", board.getManufacturerName()); - addLine("Node %s", the_mesh.getNodeName()); - - NodePrefs* p = the_mesh.getNodePrefs(); - if (p) { - addLine("Freq %.3f MHz", p->freq); - addLine("SF%u BW%.0f CR%u", (unsigned)p->sf, p->bw, (unsigned)p->cr); - addLine("TX %d dBm", (int)p->tx_power_dbm); - } - } - - // One sample line per script/keyboard alphabet the UI font claims to cover - // (all inside the U+0020-04FF glyph range the OLED misc-fixed / e-ink Lemon - // fonts carry), so the font's coverage can be checked by eye on real - // hardware. "Acc" samples one variant from each KeyboardWidget.h - // KB_ACCENT_VARIANTS group (the Hold-Enter accent popup that replaced the - // old per-language alt-alphabet pages) so every accented letter actually - // reachable in the UI still gets an eyeball check. - void buildFontLines() { - _line_count = 0; - addLine("Latin ABCabc xyz"); - addLine("Acc áçďéíłñóřśťúýź"); - addLine("Grk ΑΒΓ αβγξω"); // ΑΒΓ αβγξω - addLine("Cyr АБВ абвжя"); // АБВ абвжя - addLine("Num 0123456789"); - addLine("Sym @#&*()[]{}/\\+="); - } - // Shared scrollable renderer for the label/value Live tab. Neither tab has a // row cursor -- UP/DOWN move _scroll directly -- so this passes _scroll as // drawList()'s `sel` too: its internal clamp-toward-sel is then a no-op @@ -210,7 +50,7 @@ class DiagnosticsScreen : public UIScreen { clampScroll(_row_count, visible); drawList(display, _row_count, _scroll, _scroll, [&](int idx, int y, bool, int reserve) { - const Row& r = _rows[idx]; + const diag::Row& r = _rows[idx]; display.setCursor(2, y); display.print(r.label); display.drawTextRightAlign(display.width() - reserve - 2, y, r.value); @@ -245,9 +85,9 @@ public: tabbar::draw(display, TAB_LABELS, TAB_COUNT, _tab); switch (_tab) { - case TAB_SYSTEM: buildSystemLines(); renderLines(display); break; - case TAB_FONT: buildFontLines(); renderLines(display); break; - default: buildLiveRows(); renderRows(display); break; + case TAB_SYSTEM: _line_count = diag::systemLines(_lines); renderLines(display); break; + case TAB_FONT: _line_count = diag::fontLines(_lines); renderLines(display); break; + default: _row_count = diag::liveRows(_rows); renderRows(display); break; } display.setColor(DisplayDriver::LIGHT); @@ -262,8 +102,7 @@ public: if (_reset_menu.active) { auto res = _reset_menu.handleInput(c); if (res == PopupMenu::SELECTED && _reset_menu.selectedIndex() == 0) { - the_mesh.resetStats(); // zeroes Dispatcher per-type counters + Mesh forward count + err flags - radio_driver.resetStats(); // zeroes the radio's own counters, incl. RXPS watchdog soft/hard counts + diag::resetCounters(); _task->showAlert("Counters reset", 800); } return true;