mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-10-23 01:41:17 +00:00
rsdeck: prepare dual-mode 2.0 release
This commit is contained in:
1 parent
e2dad27836
commit
f6d6aff288
58 files changed
+984
-447
No files matched your search
@@ -168,7 +168,7 @@ void AudioNotify::playError() {
|
||||
void AudioNotify::playBoot() {
|
||||
if (!_enabled || !_i2sReady) return;
|
||||
|
||||
// === RATDECK BOOT SEQUENCE ===
|
||||
// === RSDECK BOOT SEQUENCE ===
|
||||
// Sci-fi computer startup: sweep -> digital arpeggio -> confirmation
|
||||
// Total ~550ms
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// =============================================================================
|
||||
// Ratdeck — LilyGo T-Deck Plus Pin Definitions
|
||||
// rsDeck — LilyGo T-Deck Plus Pin Definitions
|
||||
// =============================================================================
|
||||
|
||||
// --- Power Control ---
|
||||
|
||||
+15
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// =============================================================================
|
||||
// Ratdeck — Compile-Time Configuration
|
||||
// rsDeck — Compile-Time Configuration
|
||||
// =============================================================================
|
||||
|
||||
#define RATDECK_VERSION_MAJOR 1
|
||||
#define RATDECK_VERSION_MINOR 9
|
||||
#define RATDECK_VERSION_PATCH 3
|
||||
#define RATDECK_VERSION_STRING "1.9.3"
|
||||
#define RSDECK_VERSION_MAJOR 2
|
||||
#define RSDECK_VERSION_MINOR 0
|
||||
#define RSDECK_VERSION_PATCH 0
|
||||
#define RSDECK_VERSION_STRING "2.0.0"
|
||||
|
||||
// --- Feature Flags ---
|
||||
#define HAS_DISPLAY true
|
||||
@@ -19,10 +19,10 @@
|
||||
// TODO(BLE): Revisit as a dedicated Ratspeak BLE Peer transport based on the
|
||||
// rsReticulum GATT/fragmentation/anti-loop design, after T-Deck Plus memory,
|
||||
// flash, power, and interop behavior are tested end to end.
|
||||
#ifndef RATDECK_EXPERIMENTAL_BLE
|
||||
#define RATDECK_EXPERIMENTAL_BLE 0
|
||||
#ifndef RSDECK_EXPERIMENTAL_BLE
|
||||
#define RSDECK_EXPERIMENTAL_BLE 0
|
||||
#endif
|
||||
#define HAS_BLE RATDECK_EXPERIMENTAL_BLE
|
||||
#define HAS_BLE RSDECK_EXPERIMENTAL_BLE
|
||||
#define HAS_SD true
|
||||
#define HAS_AUDIO true
|
||||
#define HAS_GPS true // UBlox MIA-M10Q UART GPS
|
||||
@@ -43,6 +43,8 @@
|
||||
#define PATH_MESSAGES "/messages"
|
||||
|
||||
// --- SD Card Paths ---
|
||||
// Legacy path kept intentionally so existing Standalone users keep their data.
|
||||
// TODO: Migrate to /rsdeck only with an explicit data migration plan.
|
||||
#define SD_PATH_CONFIG_DIR "/ratdeck/config"
|
||||
#define SD_PATH_USER_CONFIG "/ratdeck/config/user.json"
|
||||
#define SD_PATH_MESSAGES "/ratdeck/messages"
|
||||
@@ -56,14 +58,14 @@
|
||||
#define TCP_CONNECT_TIMEOUT_MS 500
|
||||
|
||||
// --- Announce Flood Defense ---
|
||||
#define RATDECK_MAX_ANNOUNCES_PER_SEC 5 // Transport-level rate limit (before Ed25519 verify)
|
||||
#define RSDECK_MAX_ANNOUNCES_PER_SEC 5 // Transport-level rate limit (before Ed25519 verify)
|
||||
|
||||
// --- Limits ---
|
||||
#define RATDECK_MAX_NODES 100 // Endpoint device, not transport node
|
||||
#define RATDECK_MAX_MESSAGES_PER_CONV 100
|
||||
#define RSDECK_MAX_NODES 100 // Endpoint device, not transport node
|
||||
#define RSDECK_MAX_MESSAGES_PER_CONV 100
|
||||
#define FLASH_MSG_CACHE_LIMIT 20
|
||||
#define RATDECK_MAX_OUTQUEUE 20
|
||||
#define RATDECK_LXMF_SINGLE_FRAME_MAX 254 // T-Deck-safe payload cap until resource transfers are fixed
|
||||
#define RSDECK_MAX_OUTQUEUE 20
|
||||
#define RSDECK_LXMF_SINGLE_FRAME_MAX 254 // T-Deck-safe payload cap until resource transfers are fixed
|
||||
#define PATH_PERSIST_INTERVAL_MS 60000
|
||||
|
||||
// --- Power Management ---
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
#include "UserConfig.h"
|
||||
#include "config/BoardConfig.h"
|
||||
|
||||
namespace {
|
||||
bool validLoRaFrequency(uint32_t freq) {
|
||||
return (freq >= 863000000UL && freq <= 870000000UL) ||
|
||||
(freq >= 902000000UL && freq <= 928000000UL) ||
|
||||
(freq >= 920000000UL && freq <= 925000000UL);
|
||||
}
|
||||
}
|
||||
|
||||
void UserConfig::sanitizeSettings() {
|
||||
if (_settings.radioRegion >= REGION_COUNT) _settings.radioRegion = REGION_AMERICAS;
|
||||
if (!validLoRaFrequency(_settings.loraFrequency)) {
|
||||
_settings.loraFrequency = REGION_FREQ[constrain((int)_settings.radioRegion, 0, REGION_COUNT - 1)];
|
||||
}
|
||||
_settings.loraSF = constrain(_settings.loraSF, 5, 12);
|
||||
_settings.loraBW = constrain(_settings.loraBW, 7800UL, 500000UL);
|
||||
_settings.loraCR = constrain(_settings.loraCR, 5, 8);
|
||||
_settings.loraTxPower = constrain(_settings.loraTxPower, -9, 22);
|
||||
_settings.loraPreamble = constrain(_settings.loraPreamble, 6L, 65L);
|
||||
}
|
||||
|
||||
bool UserConfig::parseJson(const String& json) {
|
||||
Serial.printf("[CONFIG] Parsing config (%d bytes)\n", json.length());
|
||||
|
||||
@@ -102,11 +122,13 @@ bool UserConfig::parseJson(const String& json) {
|
||||
if (_settings.announceInterval > 360) _settings.announceInterval = 360;
|
||||
_settings.devMode = doc["dev_mode"] | false;
|
||||
|
||||
sanitizeSettings();
|
||||
Serial.println("[CONFIG] Settings loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
String UserConfig::serializeToJson() const {
|
||||
String UserConfig::serializeToJson() {
|
||||
sanitizeSettings();
|
||||
JsonDocument doc;
|
||||
|
||||
doc["radio_region"] = _settings.radioRegion;
|
||||
|
||||
@@ -111,7 +111,8 @@ public:
|
||||
|
||||
private:
|
||||
bool parseJson(const String& json);
|
||||
String serializeToJson() const;
|
||||
String serializeToJson();
|
||||
void sanitizeSettings();
|
||||
|
||||
UserSettings _settings;
|
||||
};
|
||||
+3
-3
@@ -8,6 +8,6 @@
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
LV_FONT_DECLARE(lv_font_ratdeck_10)
|
||||
LV_FONT_DECLARE(lv_font_ratdeck_12)
|
||||
LV_FONT_DECLARE(lv_font_ratdeck_14)
|
||||
LV_FONT_DECLARE(lv_font_rsdeck_10)
|
||||
LV_FONT_DECLARE(lv_font_rsdeck_12)
|
||||
LV_FONT_DECLARE(lv_font_rsdeck_14)
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* Size: 10 px
|
||||
* Bpp: 4
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 10 --font .pio/libdeps/ratdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_ratdeck_10.c --force-fast-kern-format
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 10 --font .pio/libdeps/rsdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_rsdeck_10.c --force-fast-kern-format
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <lvgl.h>
|
||||
#endif
|
||||
|
||||
#ifndef LV_FONT_RATDECK_10
|
||||
#define LV_FONT_RATDECK_10 1
|
||||
#ifndef LV_FONT_RSDECK_10
|
||||
#define LV_FONT_RSDECK_10 1
|
||||
#endif
|
||||
|
||||
#if LV_FONT_RATDECK_10
|
||||
#if LV_FONT_RSDECK_10
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
@@ -4614,9 +4614,9 @@ static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
const lv_font_t lv_font_ratdeck_10 = {
|
||||
const lv_font_t lv_font_rsdeck_10 = {
|
||||
#else
|
||||
lv_font_t lv_font_ratdeck_10 = {
|
||||
lv_font_t lv_font_rsdeck_10 = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
@@ -4638,5 +4638,5 @@ lv_font_t lv_font_ratdeck_10 = {
|
||||
|
||||
|
||||
|
||||
#endif /*#if LV_FONT_RATDECK_10*/
|
||||
#endif /*#if LV_FONT_RSDECK_10*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* Size: 12 px
|
||||
* Bpp: 4
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 12 --font .pio/libdeps/ratdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_ratdeck_12.c --force-fast-kern-format
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 12 --font .pio/libdeps/rsdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_rsdeck_12.c --force-fast-kern-format
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <lvgl.h>
|
||||
#endif
|
||||
|
||||
#ifndef LV_FONT_RATDECK_12
|
||||
#define LV_FONT_RATDECK_12 1
|
||||
#ifndef LV_FONT_RSDECK_12
|
||||
#define LV_FONT_RSDECK_12 1
|
||||
#endif
|
||||
|
||||
#if LV_FONT_RATDECK_12
|
||||
#if LV_FONT_RSDECK_12
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
@@ -5565,9 +5565,9 @@ static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
const lv_font_t lv_font_ratdeck_12 = {
|
||||
const lv_font_t lv_font_rsdeck_12 = {
|
||||
#else
|
||||
lv_font_t lv_font_ratdeck_12 = {
|
||||
lv_font_t lv_font_rsdeck_12 = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
@@ -5589,5 +5589,5 @@ lv_font_t lv_font_ratdeck_12 = {
|
||||
|
||||
|
||||
|
||||
#endif /*#if LV_FONT_RATDECK_12*/
|
||||
#endif /*#if LV_FONT_RSDECK_12*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* Size: 14 px
|
||||
* Bpp: 4
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 14 --font .pio/libdeps/ratdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_ratdeck_14.c --force-fast-kern-format
|
||||
* Opts: --no-compress --no-prefilter --bpp 4 --size 14 --font .pio/libdeps/rsdeck_915/lvgl/scripts/built_in_font/Montserrat-Medium.ttf -r 0x20-0x7F,0xA0-0xFF,0x100-0x17F,0x400-0x4FF --format lvgl -o src/fonts/lv_font_rsdeck_14.c --force-fast-kern-format
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <lvgl.h>
|
||||
#endif
|
||||
|
||||
#ifndef LV_FONT_RATDECK_14
|
||||
#define LV_FONT_RATDECK_14 1
|
||||
#ifndef LV_FONT_RSDECK_14
|
||||
#define LV_FONT_RSDECK_14 1
|
||||
#endif
|
||||
|
||||
#if LV_FONT_RATDECK_14
|
||||
#if LV_FONT_RSDECK_14
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
@@ -6251,9 +6251,9 @@ static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
const lv_font_t lv_font_ratdeck_14 = {
|
||||
const lv_font_t lv_font_rsdeck_14 = {
|
||||
#else
|
||||
lv_font_t lv_font_ratdeck_14 = {
|
||||
lv_font_t lv_font_rsdeck_14 = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
@@ -6275,5 +6275,5 @@ lv_font_t lv_font_ratdeck_14 = {
|
||||
|
||||
|
||||
|
||||
#endif /*#if LV_FONT_RATDECK_14*/
|
||||
#endif /*#if LV_FONT_RSDECK_14*/
|
||||
|
||||
+19
-8
@@ -1,5 +1,5 @@
|
||||
// =============================================================================
|
||||
// Ratdeck — Main Entry Point
|
||||
// rsDeck — Main Entry Point
|
||||
// LilyGo T-Deck Plus: LovyanGFX Direct UI + microReticulum + LXMF Messaging
|
||||
// =============================================================================
|
||||
|
||||
@@ -411,7 +411,7 @@ void onHotkeyAutoIface() {
|
||||
}
|
||||
void onHotkeyDiag() {
|
||||
Serial.println("=== DIAGNOSTIC DUMP ===");
|
||||
Serial.printf("Device: Ratdeck T-Deck Plus\n");
|
||||
Serial.printf("Device: rsDeck T-Deck Plus\n");
|
||||
Serial.printf("Identity: %s\n", rns.identityHash().c_str());
|
||||
Serial.printf("Transport: %s\n", rns.isTransportActive() ? "ACTIVE" : "OFFLINE");
|
||||
Serial.printf("Paths: %d Links: %d\n", (int)rns.pathCount(), (int)rns.linkCount());
|
||||
@@ -425,6 +425,17 @@ void onHotkeyDiag() {
|
||||
radio.getTxPower());
|
||||
Serial.printf("Regulator: %s\n", LORA_USE_DCDC_REGULATOR ? "DC-DC" : "LDO");
|
||||
Serial.printf("Preamble: %ld symbols\n", radio.getPreambleLength());
|
||||
Serial.printf("Bitrate: %lu bps LDRO: %s frame255: %.0f ms\n",
|
||||
(unsigned long)radio.getBitrate(),
|
||||
radio.lowDataRateEnabled() ? "ON" : "off",
|
||||
radio.getAirtime(MAX_PACKET_SIZE));
|
||||
if (auto* loraIf = rns.loraInterface()) {
|
||||
Serial.printf("LoRaIF: bitrate=%lu bps split_timeout=%lu ms frame=%.0f ms airtime=%.2f%%\n",
|
||||
(unsigned long)loraIf->bitrate(),
|
||||
loraIf->splitRxTimeoutMs(),
|
||||
loraIf->singleFrameAirtimeMs(),
|
||||
loraIf->airtimeUtilization() * 100.0f);
|
||||
}
|
||||
Serial.printf("IQ invert: %s\n", radio.getInvertIQ() ? "ON" : "off");
|
||||
Serial.printf("SyncWord regs: 0x%02X%02X\n",
|
||||
radio.readRegister(REG_SYNC_WORD_MSB_6X),
|
||||
@@ -517,7 +528,7 @@ void onHotkeyRssiMonitor() {
|
||||
void onHotkeyRadioTest() {
|
||||
Serial.println("[TEST] Sending raw test packet...");
|
||||
uint8_t header = 0xA0;
|
||||
const char* testPayload = "RATDECK_TEST_1234567890";
|
||||
const char* testPayload = "RSDECK_TEST_1234567890";
|
||||
radio.beginPacket();
|
||||
radio.write(header);
|
||||
radio.write((const uint8_t*)testPayload, strlen(testPayload));
|
||||
@@ -659,7 +670,7 @@ static bool selectDiagnosticPeer(const char* explicitArg, RNS::Bytes& destHash,
|
||||
}
|
||||
|
||||
static std::string makeDiagnosticLxmfPayload(size_t length) {
|
||||
static constexpr char kPrefix[] = "RATDECK-LXMF-TEST:";
|
||||
static constexpr char kPrefix[] = "RSDECK-LXMF-TEST:";
|
||||
static constexpr char kPattern[] =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
@@ -1055,7 +1066,7 @@ void setup() {
|
||||
delay(100);
|
||||
Serial.println();
|
||||
Serial.println("=================================");
|
||||
Serial.printf(" Ratdeck v%s\n", RATDECK_VERSION_STRING);
|
||||
Serial.printf(" rsDeck v%s\n", RSDECK_VERSION_STRING);
|
||||
Serial.println(" LilyGo T-Deck Plus");
|
||||
Serial.println("=================================");
|
||||
|
||||
@@ -1129,7 +1140,7 @@ void setup() {
|
||||
delay(10);
|
||||
if (sdStore.begin(&sharedSPI, SD_CS)) {
|
||||
sdHadExistingData = sdStore.hasExistingData();
|
||||
sdStore.formatForRatdeck();
|
||||
sdStore.formatForRsDeck();
|
||||
Serial.println("[SD] Card ready");
|
||||
} else {
|
||||
Serial.println("[SD] Not detected");
|
||||
@@ -1715,7 +1726,7 @@ void setup() {
|
||||
if (wipe) {
|
||||
Serial.println("[BOOT] User chose to wipe old data");
|
||||
lvDataCleanScreen.showStatus("Clearing old data...");
|
||||
sdStore.wipeRatdeck();
|
||||
sdStore.wipeRsDeck();
|
||||
if (announceManager) announceManager->clearAll();
|
||||
Serial.println("[BOOT] Old data cleared");
|
||||
lvDataCleanScreen.showStatus("Done! Rebooting...");
|
||||
@@ -1843,7 +1854,7 @@ void setup() {
|
||||
keyboard.backlightOn();
|
||||
}
|
||||
|
||||
Serial.println("[BOOT] Ratdeck ready");
|
||||
Serial.println("[BOOT] rsDeck ready");
|
||||
Serial.printf("[BOOT] Summary: radio=%s flash=%s sd=%s\n",
|
||||
radioOnline ? "ONLINE" : "OFFLINE",
|
||||
flash.isReady() ? "OK" : "FAIL",
|
||||
|
||||
+34
-14
@@ -770,7 +770,13 @@ void SX1262::implicitHeaderMode() {
|
||||
}
|
||||
|
||||
void SX1262::handleLowDataRate() {
|
||||
_ldro = long((1 << _sf) / (getSignalBandwidth() / 1000)) > 16;
|
||||
uint32_t bw = getSignalBandwidth();
|
||||
if (_sf == 0 || bw == 0) {
|
||||
_ldro = false;
|
||||
return;
|
||||
}
|
||||
float symbolTimeMs = 1000.0f * (float)(1UL << _sf) / (float)bw;
|
||||
_ldro = symbolTimeMs > 16.0f;
|
||||
}
|
||||
|
||||
void SX1262::standby() {
|
||||
@@ -785,23 +791,37 @@ void SX1262::sleep() {
|
||||
|
||||
float SX1262::getAirtime(uint16_t written) {
|
||||
if (!_radioOnline) return 0;
|
||||
float symbolRate = (float)getSignalBandwidth() / (float)(1 << _sf);
|
||||
uint32_t bw = getSignalBandwidth();
|
||||
uint8_t crDen = getCodingRate4();
|
||||
if (_sf == 0 || bw == 0 || crDen < 5 || crDen > 8) return 0;
|
||||
|
||||
float symbolRate = (float)bw / (float)(1UL << _sf);
|
||||
float symbolTimeMs = 1000.0 / symbolRate;
|
||||
float loraSymbols;
|
||||
float payloadSymbols;
|
||||
if (_sf >= 7) {
|
||||
loraSymbols = (8.0 * written + PHY_CRC_LORA_BITS - 4.0 * _sf + 8 + PHY_HEADER_LORA_SYMBOLS);
|
||||
loraSymbols /= 4.0 * (_sf - 2 * (_ldro ? 1 : 0));
|
||||
if (loraSymbols < 0) loraSymbols = 0;
|
||||
loraSymbols = ceil(loraSymbols);
|
||||
loraSymbols += _preambleLength + 0.25 + 8;
|
||||
payloadSymbols = (8.0 * written + PHY_CRC_LORA_BITS - 4.0 * _sf + 8 + PHY_HEADER_LORA_SYMBOLS);
|
||||
payloadSymbols /= 4.0 * (_sf - 2 * (_ldro ? 1 : 0));
|
||||
if (payloadSymbols < 0) payloadSymbols = 0;
|
||||
payloadSymbols = ceil(payloadSymbols) * crDen;
|
||||
payloadSymbols += _preambleLength + 0.25 + 8;
|
||||
} else {
|
||||
loraSymbols = (8.0 * written + PHY_CRC_LORA_BITS - 4.0 * _sf + PHY_HEADER_LORA_SYMBOLS);
|
||||
loraSymbols /= 4.0 * _sf;
|
||||
if (loraSymbols < 0) loraSymbols = 0;
|
||||
loraSymbols = ceil(loraSymbols);
|
||||
loraSymbols += _preambleLength + 2.25 + 8;
|
||||
payloadSymbols = (8.0 * written + PHY_CRC_LORA_BITS - 4.0 * _sf + PHY_HEADER_LORA_SYMBOLS);
|
||||
payloadSymbols /= 4.0 * _sf;
|
||||
if (payloadSymbols < 0) payloadSymbols = 0;
|
||||
payloadSymbols = ceil(payloadSymbols) * crDen;
|
||||
payloadSymbols += _preambleLength + 2.25 + 8;
|
||||
}
|
||||
return loraSymbols * symbolTimeMs;
|
||||
return payloadSymbols * symbolTimeMs;
|
||||
}
|
||||
|
||||
uint32_t SX1262::getBitrate() {
|
||||
uint32_t bw = getSignalBandwidth();
|
||||
uint8_t crDen = getCodingRate4();
|
||||
if (_sf == 0 || bw == 0 || crDen < 5 || crDen > 8) return 0;
|
||||
|
||||
float bitrate = (float)_sf * (4.0f / (float)crDen) * (float)bw / (float)(1UL << _sf);
|
||||
if (bitrate < 1.0f) return 1;
|
||||
return (uint32_t)bitrate;
|
||||
}
|
||||
|
||||
void IRAM_ATTR SX1262::onDio0Rise() {
|
||||
|
||||
@@ -65,6 +65,8 @@ public:
|
||||
uint8_t getPacketType();
|
||||
uint16_t getIrqFlags();
|
||||
float getAirtime(uint16_t written);
|
||||
uint32_t getBitrate();
|
||||
bool lowDataRateEnabled() const { return _ldro; }
|
||||
|
||||
// --- FIFO access ---
|
||||
void readBuffer(uint8_t* buffer, size_t size);
|
||||
|
||||
@@ -152,13 +152,14 @@ void AnnounceManager::received_announce(
|
||||
auto& node = _nodes[it->second];
|
||||
if (node.lastSeen != 0 && now >= node.lastSeen &&
|
||||
now - node.lastSeen < ANNOUNCE_MIN_INTERVAL_MS) return;
|
||||
if (!name.empty()) node.name = name;
|
||||
// Saved contacts own their local alias. Incoming announce app_data is
|
||||
// still cached below, but must not reset the user-chosen contact name.
|
||||
if (!name.empty() && !node.saved) node.name = name;
|
||||
if (!idHex.empty()) node.identityHex = idHex;
|
||||
node.lastSeen = now;
|
||||
// hops_to() is expensive (linear routing table scan) — only call for saved contacts
|
||||
if (node.saved) node.hops = RNS::Transport::hops_to(destination_hash);
|
||||
if (_loraIf) { node.rssi = _loraIf->lastRxRssi(); node.snr = _loraIf->lastRxSnr(); }
|
||||
if (node.saved) _contactsDirty = true;
|
||||
// Name cache update — skip expensive toHex() for unnamed re-announces
|
||||
if (!name.empty()) {
|
||||
std::string destHex = destination_hash.toHex();
|
||||
@@ -227,7 +228,14 @@ void AnnounceManager::received_announce(
|
||||
|
||||
DiscoveredNode node;
|
||||
node.hash = destination_hash;
|
||||
node.name = name.empty() ? destHex.substr(0, 12) : name;
|
||||
if (!name.empty()) {
|
||||
node.name = name;
|
||||
} else {
|
||||
auto cached = _nameCache.find(destHex);
|
||||
node.name = (cached != _nameCache.end() && !cached->second.empty())
|
||||
? cached->second
|
||||
: destHex.substr(0, 12);
|
||||
}
|
||||
node.identityHex = idHex;
|
||||
node.lastSeen = millis();
|
||||
// Skip hops_to() for new (unsaved) nodes — resolved when added as contact
|
||||
@@ -296,7 +304,14 @@ void AnnounceManager::addManualContact(const std::string& hexHash, const std::st
|
||||
|
||||
DiscoveredNode node;
|
||||
node.hash = hash;
|
||||
node.name = safeName.empty() ? hexHash.substr(0, 12) : safeName;
|
||||
if (!safeName.empty()) {
|
||||
node.name = safeName;
|
||||
} else {
|
||||
auto cached = _nameCache.find(hexHash);
|
||||
node.name = (cached != _nameCache.end() && !cached->second.empty())
|
||||
? cached->second
|
||||
: hexHash.substr(0, 12);
|
||||
}
|
||||
node.lastSeen = millis();
|
||||
node.saved = true;
|
||||
_hashIndex[key] = (int)_nodes.size();
|
||||
|
||||
@@ -26,7 +26,7 @@ bool LXMFManager::begin(ReticulumManager* rns, MessageStore* store) {
|
||||
}
|
||||
std::vector<LXMFMessage> pending = _store->loadPendingOutgoing();
|
||||
for (auto& msg : pending) {
|
||||
if ((int)_outQueue.size() >= RATDECK_MAX_OUTQUEUE) break;
|
||||
if ((int)_outQueue.size() >= RSDECK_MAX_OUTQUEUE) break;
|
||||
msg.lastRetryMs = 0;
|
||||
_outQueue.push_back(msg);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ bool LXMFManager::sendMessage(const RNS::Bytes& destHash, const std::string& con
|
||||
msg.incoming = false;
|
||||
msg.status = LXMFStatus::QUEUED;
|
||||
|
||||
if ((int)_outQueue.size() >= RATDECK_MAX_OUTQUEUE) {
|
||||
if ((int)_outQueue.size() >= RSDECK_MAX_OUTQUEUE) {
|
||||
Serial.println("[LXMF] Outbound queue full; refusing new message");
|
||||
return false;
|
||||
}
|
||||
@@ -131,11 +131,11 @@ bool LXMFManager::sendMessage(const RNS::Bytes& destHash, const std::string& con
|
||||
Serial.println("[LXMF] Message pack failed");
|
||||
return false;
|
||||
}
|
||||
if (payload.size() > RATDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
if (payload.size() > RSDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
msg.status = LXMFStatus::FAILED;
|
||||
if (_store) _store->saveMessage(msg);
|
||||
Serial.printf("[LXMF] Message too large for T-Deck safe path (%d > %d); resource transfer disabled\n",
|
||||
(int)payload.size(), RATDECK_LXMF_SINGLE_FRAME_MAX);
|
||||
(int)payload.size(), RSDECK_LXMF_SINGLE_FRAME_MAX);
|
||||
return true;
|
||||
}
|
||||
if (preference == DeliveryPreference::Link) {
|
||||
@@ -267,9 +267,9 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) {
|
||||
if (payload.empty()) { Serial.println("[LXMF] packFull returned empty!"); msg.status = LXMFStatus::FAILED; return true; }
|
||||
const std::string msgIdHex = msg.messageId.toHex();
|
||||
const bool requireLink = _linkRequiredIds.count(msgIdHex) > 0;
|
||||
if (payload.size() > RATDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
if (payload.size() > RSDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
Serial.printf("[LXMF] Refusing resource-sized message (%d bytes); T-Deck safe cap is %d\n",
|
||||
(int)payload.size(), RATDECK_LXMF_SINGLE_FRAME_MAX);
|
||||
(int)payload.size(), RSDECK_LXMF_SINGLE_FRAME_MAX);
|
||||
msg.status = LXMFStatus::FAILED;
|
||||
return true;
|
||||
}
|
||||
@@ -338,7 +338,7 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) {
|
||||
// Larger packets require split-frame over LoRa, which is unreliable — any single
|
||||
// frame loss (CRC error, collision, half-duplex timing) kills the entire transfer
|
||||
// with no recovery. Link-based delivery handles retransmission at the protocol level.
|
||||
if (payloadBytes.size() <= RATDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
if (payloadBytes.size() <= RSDECK_LXMF_SINGLE_FRAME_MAX) {
|
||||
// Fits in single LoRa frame — send opportunistic
|
||||
Serial.printf("[LXMF] sending opportunistic: %d bytes to %s\n",
|
||||
(int)payloadBytes.size(), outDest.hash().toHex().substr(0, 12).c_str());
|
||||
@@ -348,7 +348,7 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) {
|
||||
} else {
|
||||
// Too large for single frame — need link + resource transfer
|
||||
Serial.printf("[LXMF] Message needs link delivery (%d bytes > %d single-frame), retry %d\n",
|
||||
(int)payloadBytes.size(), RATDECK_LXMF_SINGLE_FRAME_MAX, msg.retries);
|
||||
(int)payloadBytes.size(), RSDECK_LXMF_SINGLE_FRAME_MAX, msg.retries);
|
||||
if (msg.retries % 3 == 0 && (!_outLink || _outLinkDestHash != msg.destHash
|
||||
|| _outLink.status() != RNS::Type::Link::ACTIVE)) {
|
||||
ensureOutboundLink(outDest, msg.destHash, "resource transfer");
|
||||
@@ -563,7 +563,7 @@ void LXMFManager::handleProofTimeoutHash(const std::string& receiptHash) {
|
||||
_pendingProofs.erase(it);
|
||||
|
||||
p.proofAttempts++;
|
||||
bool retry = p.proofAttempts < 3 && (int)_instance->_outQueue.size() < RATDECK_MAX_OUTQUEUE;
|
||||
bool retry = p.proofAttempts < 3 && (int)_instance->_outQueue.size() < RSDECK_MAX_OUTQUEUE;
|
||||
LXMFStatus nextStatus = retry ? LXMFStatus::QUEUED : LXMFStatus::FAILED;
|
||||
|
||||
if (_instance->_store) {
|
||||
|
||||
@@ -244,7 +244,7 @@ bool ReticulumManager::begin(SX1262* radio, FlashStore* flash, bool loraEnabled)
|
||||
if (packet.context() == RNS::Type::Packet::PATH_RESPONSE) return true;
|
||||
|
||||
// Adaptive rate: tighter during first 60s boot flood, then normal
|
||||
unsigned int maxRate = (now < 60000) ? 3 : RATDECK_MAX_ANNOUNCES_PER_SEC;
|
||||
unsigned int maxRate = (now < 60000) ? 3 : RSDECK_MAX_ANNOUNCES_PER_SEC;
|
||||
if (++count > maxRate) { ReticulumManager::_announceFilterCount++; return false; }
|
||||
|
||||
return true;
|
||||
@@ -349,7 +349,7 @@ void ReticulumManager::loop() {
|
||||
|
||||
// Synchronous persist — one cycle per call to spread I/O across intervals.
|
||||
// Runs on core 1 (main loop) to avoid data races with microReticulum's
|
||||
// single-threaded transport state. Ratdeck is an endpoint, not a transport
|
||||
// single-threaded transport state. rsDeck is an endpoint, not a transport
|
||||
// node, so path tables are intentionally not persisted across boots.
|
||||
void ReticulumManager::persistData() {
|
||||
unsigned long start = millis();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "FlashStore.h"
|
||||
|
||||
bool FlashStore::begin() {
|
||||
// Standalone ratdeck labels this partition "littlefs"; bmorcelli/Launcher
|
||||
// Legacy standalone builds label this partition "littlefs"; bmorcelli/Launcher
|
||||
// labels the equivalent partition "spiffs". Try ours first, fall back.
|
||||
const char* labels[] = { "littlefs", "spiffs" };
|
||||
bool mounted = false;
|
||||
|
||||
@@ -362,8 +362,8 @@ bool MessageStore::saveMessage(LXMFMessage& msg) {
|
||||
if (isPendingStatus(msg.status) && s.pendingCount < UINT16_MAX) s.pendingCount++;
|
||||
if (msg.status == LXMFStatus::FAILED && s.failedCount < UINT16_MAX) s.failedCount++;
|
||||
}
|
||||
int limit = sdOk ? RATDECK_MAX_MESSAGES_PER_CONV
|
||||
: ((_externalStorageEnabled && _sd && _sd->isReady()) ? FLASH_MSG_CACHE_LIMIT : RATDECK_MAX_MESSAGES_PER_CONV);
|
||||
int limit = sdOk ? RSDECK_MAX_MESSAGES_PER_CONV
|
||||
: ((_externalStorageEnabled && _sd && _sd->isReady()) ? FLASH_MSG_CACHE_LIMIT : RSDECK_MAX_MESSAGES_PER_CONV);
|
||||
if (s.totalCount > limit) {
|
||||
rebuildSummary(peerHex);
|
||||
}
|
||||
@@ -965,7 +965,7 @@ void MessageStore::enforceFlashLimit(const std::string& peerHex) {
|
||||
}
|
||||
entry = d.openNextFile();
|
||||
}
|
||||
int limit = (_externalStorageEnabled && _sd && _sd->isReady()) ? FLASH_MSG_CACHE_LIMIT : RATDECK_MAX_MESSAGES_PER_CONV;
|
||||
int limit = (_externalStorageEnabled && _sd && _sd->isReady()) ? FLASH_MSG_CACHE_LIMIT : RSDECK_MAX_MESSAGES_PER_CONV;
|
||||
if ((int)files.size() <= limit) return;
|
||||
std::sort(files.begin(), files.end());
|
||||
int excess = files.size() - limit;
|
||||
@@ -993,9 +993,9 @@ void MessageStore::enforceSDLimit(const std::string& peerHex) {
|
||||
}
|
||||
entry = d.openNextFile();
|
||||
}
|
||||
if ((int)files.size() <= RATDECK_MAX_MESSAGES_PER_CONV) return;
|
||||
if ((int)files.size() <= RSDECK_MAX_MESSAGES_PER_CONV) return;
|
||||
std::sort(files.begin(), files.end());
|
||||
int excess = files.size() - RATDECK_MAX_MESSAGES_PER_CONV;
|
||||
int excess = files.size() - RSDECK_MAX_MESSAGES_PER_CONV;
|
||||
for (int i = 0; i < excess; i++) {
|
||||
_sd->remove(files[i].c_str());
|
||||
}
|
||||
|
||||
@@ -176,9 +176,9 @@ String SDStore::readString(const char* path) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SDStore::wipeRatdeck() {
|
||||
bool SDStore::wipeRsDeck() {
|
||||
if (!_ready) return false;
|
||||
Serial.println("[SD] Wiping /ratdeck/ ...");
|
||||
Serial.println("[SD] Wiping rsDeck legacy /ratdeck/ data ...");
|
||||
wipeDir("/ratdeck/messages");
|
||||
wipeDir("/ratdeck/contacts");
|
||||
wipeDir("/ratdeck/identity");
|
||||
@@ -186,7 +186,7 @@ bool SDStore::wipeRatdeck() {
|
||||
wipeDir("/ratdeck/transport");
|
||||
SD.rmdir("/ratdeck");
|
||||
Serial.println("[SD] Wipe complete, recreating dirs...");
|
||||
return formatForRatdeck();
|
||||
return formatForRsDeck();
|
||||
}
|
||||
|
||||
void SDStore::wipeDir(const char* path) {
|
||||
@@ -221,9 +221,9 @@ bool SDStore::hasExistingData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDStore::formatForRatdeck() {
|
||||
bool SDStore::formatForRsDeck() {
|
||||
if (!_ready) return false;
|
||||
Serial.println("[SD] Creating Ratdeck directory structure...");
|
||||
Serial.println("[SD] Creating rsDeck legacy /ratdeck/ directory structure...");
|
||||
bool ok = true;
|
||||
ok &= ensureDir("/ratdeck");
|
||||
ok &= ensureDir("/ratdeck/config");
|
||||
|
||||
@@ -25,8 +25,8 @@ public:
|
||||
uint64_t totalBytes() const;
|
||||
uint64_t usedBytes() const;
|
||||
|
||||
bool formatForRatdeck();
|
||||
bool wipeRatdeck();
|
||||
bool formatForRsDeck();
|
||||
bool wipeRsDeck();
|
||||
bool hasExistingData();
|
||||
|
||||
private:
|
||||
|
||||
@@ -21,7 +21,7 @@ BLEInterface::~BLEInterface() {
|
||||
|
||||
bool BLEInterface::start() {
|
||||
_framesMutex = xSemaphoreCreateMutex();
|
||||
NimBLEDevice::init("Ratdeck");
|
||||
NimBLEDevice::init("rsDeck");
|
||||
NimBLEDevice::setMTU(512);
|
||||
|
||||
_pServer = NimBLEDevice::createServer();
|
||||
@@ -29,13 +29,13 @@ bool BLEInterface::start() {
|
||||
|
||||
_pService = _pServer->createService(SERVICE_UUID);
|
||||
|
||||
// TX: Ratdeck -> remote (NOTIFY)
|
||||
// TX: rsDeck -> remote (NOTIFY)
|
||||
_pTxChar = _pService->createCharacteristic(
|
||||
TX_CHAR_UUID,
|
||||
NIMBLE_PROPERTY::NOTIFY
|
||||
);
|
||||
|
||||
// RX: remote -> Ratdeck (WRITE)
|
||||
// RX: remote -> rsDeck (WRITE)
|
||||
_pRxChar = _pService->createCharacteristic(
|
||||
RX_CHAR_UUID,
|
||||
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR
|
||||
@@ -47,7 +47,7 @@ bool BLEInterface::start() {
|
||||
|
||||
NimBLEAdvertising* pAdv = NimBLEDevice::getAdvertising();
|
||||
pAdv->addServiceUUID(SERVICE_UUID);
|
||||
pAdv->setName("Ratdeck");
|
||||
pAdv->setName("rsDeck");
|
||||
pAdv->start();
|
||||
|
||||
_active = true;
|
||||
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
static constexpr uint8_t FRAME_ESC = 0x7D;
|
||||
static constexpr uint8_t FRAME_XOR = 0x20;
|
||||
|
||||
// Custom UUIDs for Ratdeck BLE transport
|
||||
// Custom UUIDs for rsDeck BLE transport
|
||||
static constexpr const char* SERVICE_UUID = "e2f0a5b1-c3d4-4e56-8f90-1a2b3c4d5e6f";
|
||||
static constexpr const char* TX_CHAR_UUID = "e2f0a5b2-c3d4-4e56-8f90-1a2b3c4d5e6f";
|
||||
static constexpr const char* RX_CHAR_UUID = "e2f0a5b3-c3d4-4e56-8f90-1a2b3c4d5e6f";
|
||||
|
||||
@@ -11,7 +11,7 @@ bool BLESideband::begin(NimBLEServer* existingServer) {
|
||||
_pServer = existingServer;
|
||||
_ownServer = false;
|
||||
} else {
|
||||
NimBLEDevice::init("Ratdeck");
|
||||
NimBLEDevice::init("rsDeck");
|
||||
_pServer = NimBLEDevice::createServer();
|
||||
_ownServer = true;
|
||||
}
|
||||
@@ -19,13 +19,13 @@ bool BLESideband::begin(NimBLEServer* existingServer) {
|
||||
// Create Nordic UART Service (don't set server callbacks — BLEInterface owns them)
|
||||
_pService = _pServer->createService(NUS_SERVICE_UUID);
|
||||
|
||||
// TX: Ratdeck -> Sideband (NOTIFY)
|
||||
// TX: rsDeck -> Sideband (NOTIFY)
|
||||
_pTxChar = _pService->createCharacteristic(
|
||||
NUS_TX_UUID,
|
||||
NIMBLE_PROPERTY::NOTIFY
|
||||
);
|
||||
|
||||
// RX: Sideband -> Ratdeck (WRITE)
|
||||
// RX: Sideband -> rsDeck (WRITE)
|
||||
_pRxChar = _pService->createCharacteristic(
|
||||
NUS_RX_UUID,
|
||||
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR
|
||||
@@ -39,7 +39,7 @@ bool BLESideband::begin(NimBLEServer* existingServer) {
|
||||
_pServer->start();
|
||||
NimBLEAdvertising* pAdv = NimBLEDevice::getAdvertising();
|
||||
pAdv->addServiceUUID(NUS_SERVICE_UUID);
|
||||
pAdv->setName("Ratdeck");
|
||||
pAdv->setName("rsDeck");
|
||||
pAdv->start();
|
||||
} else {
|
||||
// Add NUS UUID to existing advertising
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "LoRaInterface.h"
|
||||
#include "config/BoardConfig.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
// RNode on-air framing constants (from RNode_Firmware Framing.h / Config.h)
|
||||
// Every LoRa packet has a 1-byte header: upper nibble = random sequence, lower nibble = flags
|
||||
@@ -14,9 +15,9 @@ LoRaInterface::LoRaInterface(SX1262* radio, const char* name)
|
||||
{
|
||||
_IN = true;
|
||||
_OUT = true;
|
||||
_bitrate = 2000;
|
||||
// Reticulum MTU (500 bytes) — split-packet framing allows up to 2x254 = 508 bytes
|
||||
_HW_MTU = RNS::Type::Reticulum::MTU;
|
||||
refreshRadioTiming(true);
|
||||
}
|
||||
|
||||
LoRaInterface::~LoRaInterface() {
|
||||
@@ -30,6 +31,7 @@ bool LoRaInterface::start() {
|
||||
return false;
|
||||
}
|
||||
_online = true;
|
||||
refreshRadioTiming(true);
|
||||
_radio->receive();
|
||||
Serial.println("[LORA_IF] Interface started (split-packet enabled, MTU=500)");
|
||||
return true;
|
||||
@@ -42,6 +44,7 @@ void LoRaInterface::stop() {
|
||||
|
||||
void LoRaInterface::send_outgoing(const RNS::Bytes& data) {
|
||||
if (!_online || !_radio) return;
|
||||
refreshRadioTiming();
|
||||
|
||||
// Reject packets exceeding Reticulum MTU (500 bytes)
|
||||
if (data.size() > RNS::Type::Reticulum::MTU) {
|
||||
@@ -73,6 +76,7 @@ void LoRaInterface::send_outgoing(const RNS::Bytes& data) {
|
||||
}
|
||||
|
||||
void LoRaInterface::transmitNow(const RNS::Bytes& data) {
|
||||
refreshRadioTiming();
|
||||
uint8_t header = (uint8_t)(random(256)) & RNODE_NIBBLE_SEQ;
|
||||
bool needsSplit = (data.size() > RNODE_SINGLE_MTU);
|
||||
|
||||
@@ -129,6 +133,7 @@ void LoRaInterface::transmitNow(const RNS::Bytes& data) {
|
||||
|
||||
void LoRaInterface::loop() {
|
||||
if (!_online || !_radio) return;
|
||||
refreshRadioTiming();
|
||||
|
||||
// Handle async TX completion
|
||||
if (_txPending) {
|
||||
@@ -170,8 +175,10 @@ void LoRaInterface::loop() {
|
||||
}
|
||||
|
||||
// Split RX timeout: discard stale partial packets and drain deferred TX
|
||||
if (_splitRxPending && (millis() - _splitRxTimestamp > SPLIT_RX_TIMEOUT_MS)) {
|
||||
Serial.println("[LORA_IF] RX SPLIT timeout, discarding partial");
|
||||
if (_splitRxPending && (millis() - _splitRxTimestamp > _splitRxTimeoutMs)) {
|
||||
unsigned long age = millis() - _splitRxTimestamp;
|
||||
Serial.printf("[LORA_IF] RX SPLIT timeout after %lums (limit=%lums frame=%.0fms), discarding partial\n",
|
||||
age, _splitRxTimeoutMs, _singleFrameAirtimeMs);
|
||||
_splitRxPending = false;
|
||||
_splitRxBuffer = RNS::Bytes();
|
||||
// Drain any TX that was deferred during split RX hold
|
||||
@@ -226,14 +233,14 @@ void LoRaInterface::loop() {
|
||||
_splitRxBuffer = RNS::Bytes(raw + RNODE_HEADER_L, payloadSize);
|
||||
_splitRxTimestamp = millis();
|
||||
|
||||
Serial.printf("[LORA_IF] RX SPLIT frame 1: %d bytes (seq=0x%02X), RSSI=%d, SNR=%.1f\n",
|
||||
payloadSize, seq, _lastRxRssi, _lastRxSnr);
|
||||
Serial.printf("[LORA_IF] RX SPLIT frame 1: %d bytes (seq=0x%02X), RSSI=%d, SNR=%.1f, timeout=%lums\n",
|
||||
payloadSize, seq, _lastRxRssi, _lastRxSnr, _splitRxTimeoutMs);
|
||||
_radio->receive();
|
||||
return;
|
||||
} else if (seq == _splitRxSeq) {
|
||||
// Second frame matches — reassemble
|
||||
Serial.printf("[LORA_IF] RX SPLIT frame 2: %d bytes (seq=0x%02X), RSSI=%d, SNR=%.1f\n",
|
||||
payloadSize, seq, _lastRxRssi, _lastRxSnr);
|
||||
Serial.printf("[LORA_IF] RX SPLIT frame 2: %d bytes (seq=0x%02X), RSSI=%d, SNR=%.1f, age=%lums\n",
|
||||
payloadSize, seq, _lastRxRssi, _lastRxSnr, millis() - _splitRxTimestamp);
|
||||
|
||||
_splitRxBuffer.append(raw + RNODE_HEADER_L, payloadSize);
|
||||
int totalSize = _splitRxBuffer.size();
|
||||
@@ -293,3 +300,43 @@ float LoRaInterface::airtimeUtilization() const {
|
||||
float windowMs = std::min((float)elapsed, (float)AIRTIME_WINDOW_MS);
|
||||
return _airtimeAccumMs / windowMs;
|
||||
}
|
||||
|
||||
unsigned long LoRaInterface::computeSplitRxTimeoutMs(float frameAirtimeMs) const {
|
||||
if (frameAirtimeMs <= 0) return SPLIT_RX_TIMEOUT_FLOOR_MS;
|
||||
float raw = frameAirtimeMs * SPLIT_RX_TIMEOUT_MULT + SPLIT_RX_TIMEOUT_MARGIN_MS;
|
||||
unsigned long rounded = (unsigned long)(ceil(raw / 500.0f) * 500.0f);
|
||||
return std::min(SPLIT_RX_TIMEOUT_CEIL_MS,
|
||||
std::max(SPLIT_RX_TIMEOUT_FLOOR_MS, rounded));
|
||||
}
|
||||
|
||||
void LoRaInterface::refreshRadioTiming(bool forceLog) {
|
||||
if (!_radio || !_radio->isRadioOnline()) {
|
||||
if (_bitrate == 0) _bitrate = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
if (!forceLog && _lastTimingRefreshMs != 0 && (now - _lastTimingRefreshMs) < 1000) return;
|
||||
_lastTimingRefreshMs = now;
|
||||
|
||||
uint32_t newBitrate = _radio->getBitrate();
|
||||
if (newBitrate == 0) newBitrate = (_bitrate > 0) ? _bitrate : 1;
|
||||
float newFrameAirtime = _radio->getAirtime(MAX_PACKET_SIZE);
|
||||
unsigned long newTimeout = computeSplitRxTimeoutMs(newFrameAirtime);
|
||||
|
||||
bool changed = forceLog || newBitrate != _bitrate ||
|
||||
newTimeout != _splitRxTimeoutMs ||
|
||||
fabsf(newFrameAirtime - _singleFrameAirtimeMs) >= 1.0f;
|
||||
|
||||
_bitrate = newBitrate;
|
||||
_singleFrameAirtimeMs = newFrameAirtime;
|
||||
_splitRxTimeoutMs = newTimeout;
|
||||
|
||||
if (changed) {
|
||||
Serial.printf("[LORA_IF] timing: bitrate=%lu bps frame=%.0fms split_timeout=%lums ldro=%s\n",
|
||||
(unsigned long)_bitrate,
|
||||
_singleFrameAirtimeMs,
|
||||
_splitRxTimeoutMs,
|
||||
_radio->lowDataRateEnabled() ? "on" : "off");
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,17 @@ public:
|
||||
int lastRxRssi() const { return _lastRxRssi; }
|
||||
float lastRxSnr() const { return _lastRxSnr; }
|
||||
bool isOnline() const { return _online; }
|
||||
unsigned long splitRxTimeoutMs() const { return _splitRxTimeoutMs; }
|
||||
float singleFrameAirtimeMs() const { return _singleFrameAirtimeMs; }
|
||||
uint32_t bitrate() const { return _bitrate; }
|
||||
|
||||
protected:
|
||||
virtual void send_outgoing(const RNS::Bytes& data) override;
|
||||
|
||||
private:
|
||||
void transmitNow(const RNS::Bytes& data);
|
||||
void refreshRadioTiming(bool forceLog = false);
|
||||
unsigned long computeSplitRxTimeoutMs(float frameAirtimeMs) const;
|
||||
|
||||
SX1262* _radio;
|
||||
bool _txPending = false;
|
||||
@@ -44,11 +49,17 @@ private:
|
||||
uint8_t _splitTxHeader = 0;
|
||||
|
||||
// Split-packet RX state: reassemble two LoRa frames into one Reticulum packet
|
||||
static constexpr unsigned long SPLIT_RX_TIMEOUT_MS = 5000;
|
||||
static constexpr unsigned long SPLIT_RX_TIMEOUT_FLOOR_MS = 5000;
|
||||
static constexpr unsigned long SPLIT_RX_TIMEOUT_CEIL_MS = 60000;
|
||||
static constexpr unsigned long SPLIT_RX_TIMEOUT_MARGIN_MS = 2000;
|
||||
static constexpr float SPLIT_RX_TIMEOUT_MULT = 1.5f;
|
||||
bool _splitRxPending = false;
|
||||
uint8_t _splitRxSeq = 0;
|
||||
RNS::Bytes _splitRxBuffer;
|
||||
unsigned long _splitRxTimestamp = 0;
|
||||
unsigned long _splitRxTimeoutMs = SPLIT_RX_TIMEOUT_FLOOR_MS;
|
||||
float _singleFrameAirtimeMs = 0;
|
||||
unsigned long _lastTimingRefreshMs = 0;
|
||||
|
||||
int _lastRxRssi = 0;
|
||||
float _lastRxSnr = 0;
|
||||
|
||||
@@ -37,7 +37,7 @@ void WiFiInterface::startAP() {
|
||||
if (_apSSID.isEmpty()) {
|
||||
uint32_t chip = ESP.getEfuseMac() & 0xFFFF;
|
||||
char ssid[32];
|
||||
snprintf(ssid, sizeof(ssid), "ratdeck-%04x", chip);
|
||||
snprintf(ssid, sizeof(ssid), "rsdeck-%04x", chip);
|
||||
_apSSID = ssid;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ void LvStatusBar::create(lv_obj_t* parent) {
|
||||
_lblTime = lv_label_create(_bar);
|
||||
lv_obj_set_size(_lblTime, kTimeW, Theme::STATUS_BAR_H);
|
||||
lv_label_set_long_mode(_lblTime, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_style_text_font(_lblTime, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(_lblTime, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_align(_lblTime, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_label_set_text(_lblTime, "--:--");
|
||||
lv_obj_align(_lblTime, LV_ALIGN_LEFT_MID, 4, 0);
|
||||
@@ -42,14 +42,14 @@ void LvStatusBar::create(lv_obj_t* parent) {
|
||||
lv_obj_set_size(_lblLinks, kLinksW, Theme::STATUS_BAR_H);
|
||||
lv_label_set_long_mode(_lblLinks, LV_LABEL_LONG_CLIP);
|
||||
lv_label_set_recolor(_lblLinks, true);
|
||||
lv_obj_set_style_text_font(_lblLinks, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_lblLinks, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_align(_lblLinks, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_align(_lblLinks, LV_ALIGN_LEFT_MID, kLinksX, 0);
|
||||
|
||||
// Right: battery percentage.
|
||||
_lblBatt = lv_label_create(_bar);
|
||||
lv_obj_set_size(_lblBatt, kBattW, Theme::STATUS_BAR_H);
|
||||
lv_obj_set_style_text_font(_lblBatt, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_lblBatt, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_align(_lblBatt, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
lv_label_set_long_mode(_lblBatt, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_align(_lblBatt, LV_ALIGN_RIGHT_MID, -4, 0);
|
||||
@@ -66,7 +66,7 @@ void LvStatusBar::create(lv_obj_t* parent) {
|
||||
_lblToast = lv_label_create(_toast);
|
||||
lv_obj_set_width(_lblToast, Theme::SCREEN_W - 12);
|
||||
lv_label_set_long_mode(_lblToast, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_style_text_font(_lblToast, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(_lblToast, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(_lblToast, lv_color_hex(Theme::BG), 0);
|
||||
lv_obj_set_style_text_align(_lblToast, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_center(_lblToast);
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ void LvTabBar::create(lv_obj_t* parent) {
|
||||
_labels[i] = lv_label_create(_cells[i]);
|
||||
lv_obj_set_size(_labels[i], Theme::TAB_W - 4, 14);
|
||||
lv_label_set_long_mode(_labels[i], LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_style_text_font(_labels[i], &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_labels[i], &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_align(_labels[i], LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_label_set_text(_labels[i], TAB_NAMES[i]);
|
||||
lv_obj_align(_labels[i], LV_ALIGN_CENTER, 0, 2);
|
||||
@@ -63,7 +63,7 @@ void LvTabBar::create(lv_obj_t* parent) {
|
||||
|
||||
_badgeLabels[i] = lv_label_create(_badges[i]);
|
||||
lv_label_set_long_mode(_badgeLabels[i], LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_style_text_font(_badgeLabels[i], &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_badgeLabels[i], &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_align(_badgeLabels[i], LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_center(_badgeLabels[i]);
|
||||
}
|
||||
|
||||
+14
-14
@@ -120,23 +120,23 @@ void init(lv_disp_t* disp) {
|
||||
// Screen background (LV_USE_THEME_DEFAULT is disabled in lv_conf.h).
|
||||
lv_style_init(&s_screen);
|
||||
lv_style_set_bg_opa(&s_screen, LV_OPA_COVER);
|
||||
lv_style_set_text_font(&s_screen, &lv_font_ratdeck_14);
|
||||
lv_style_set_text_font(&s_screen, &lv_font_rsdeck_14);
|
||||
|
||||
// Labels
|
||||
lv_style_init(&s_label);
|
||||
lv_style_set_text_font(&s_label, &lv_font_ratdeck_14);
|
||||
lv_style_set_text_font(&s_label, &lv_font_rsdeck_14);
|
||||
|
||||
lv_style_init(&s_labelMuted);
|
||||
lv_style_set_text_font(&s_labelMuted, &lv_font_ratdeck_12);
|
||||
lv_style_set_text_font(&s_labelMuted, &lv_font_rsdeck_12);
|
||||
|
||||
lv_style_init(&s_labelAccent);
|
||||
lv_style_set_text_font(&s_labelAccent, &lv_font_ratdeck_14);
|
||||
lv_style_set_text_font(&s_labelAccent, &lv_font_rsdeck_14);
|
||||
|
||||
// Buttons
|
||||
lv_style_init(&s_btn);
|
||||
lv_style_set_bg_opa(&s_btn, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&s_btn, 1);
|
||||
lv_style_set_text_font(&s_btn, &lv_font_ratdeck_12);
|
||||
lv_style_set_text_font(&s_btn, &lv_font_rsdeck_12);
|
||||
lv_style_set_radius(&s_btn, 3);
|
||||
lv_style_set_pad_top(&s_btn, 5);
|
||||
lv_style_set_pad_bottom(&s_btn, 5);
|
||||
@@ -171,7 +171,7 @@ void init(lv_disp_t* disp) {
|
||||
lv_style_init(&s_textarea);
|
||||
lv_style_set_bg_opa(&s_textarea, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&s_textarea, 1);
|
||||
lv_style_set_text_font(&s_textarea, &lv_font_ratdeck_14);
|
||||
lv_style_set_text_font(&s_textarea, &lv_font_rsdeck_14);
|
||||
lv_style_set_radius(&s_textarea, 3);
|
||||
lv_style_set_pad_all(&s_textarea, 6);
|
||||
|
||||
@@ -189,7 +189,7 @@ void init(lv_disp_t* disp) {
|
||||
// List items
|
||||
lv_style_init(&s_listBtn);
|
||||
lv_style_set_bg_opa(&s_listBtn, LV_OPA_COVER);
|
||||
lv_style_set_text_font(&s_listBtn, &lv_font_ratdeck_12);
|
||||
lv_style_set_text_font(&s_listBtn, &lv_font_rsdeck_12);
|
||||
lv_style_set_border_width(&s_listBtn, 1);
|
||||
lv_style_set_border_side(&s_listBtn, LV_BORDER_SIDE_BOTTOM);
|
||||
lv_style_set_pad_top(&s_listBtn, 5);
|
||||
@@ -208,7 +208,7 @@ void init(lv_disp_t* disp) {
|
||||
lv_style_init(&s_dropdown);
|
||||
lv_style_set_bg_opa(&s_dropdown, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&s_dropdown, 1);
|
||||
lv_style_set_text_font(&s_dropdown, &lv_font_ratdeck_12);
|
||||
lv_style_set_text_font(&s_dropdown, &lv_font_rsdeck_12);
|
||||
lv_style_set_radius(&s_dropdown, 3);
|
||||
lv_style_set_pad_all(&s_dropdown, 4);
|
||||
|
||||
@@ -220,7 +220,7 @@ void init(lv_disp_t* disp) {
|
||||
// Section header (for list section dividers like "Contacts (3)")
|
||||
lv_style_init(&s_sectionHeader);
|
||||
lv_style_set_bg_opa(&s_sectionHeader, LV_OPA_TRANSP);
|
||||
lv_style_set_text_font(&s_sectionHeader, &lv_font_ratdeck_10);
|
||||
lv_style_set_text_font(&s_sectionHeader, &lv_font_rsdeck_10);
|
||||
lv_style_set_text_letter_space(&s_sectionHeader, 0);
|
||||
lv_style_set_border_width(&s_sectionHeader, 1);
|
||||
lv_style_set_border_side(&s_sectionHeader, LV_BORDER_SIDE_BOTTOM);
|
||||
@@ -249,7 +249,7 @@ void init(lv_disp_t* disp) {
|
||||
// Roller - no border so selected row highlight extends edge-to-edge
|
||||
lv_style_init(&s_roller);
|
||||
lv_style_set_bg_opa(&s_roller, LV_OPA_COVER);
|
||||
lv_style_set_text_font(&s_roller, &lv_font_ratdeck_14);
|
||||
lv_style_set_text_font(&s_roller, &lv_font_rsdeck_14);
|
||||
lv_style_set_border_width(&s_roller, 0);
|
||||
|
||||
// Persistent shell bars.
|
||||
@@ -262,7 +262,7 @@ void init(lv_disp_t* disp) {
|
||||
|
||||
lv_style_init(&s_statusToast);
|
||||
lv_style_set_bg_opa(&s_statusToast, LV_OPA_COVER);
|
||||
lv_style_set_text_font(&s_statusToast, &lv_font_ratdeck_12);
|
||||
lv_style_set_text_font(&s_statusToast, &lv_font_rsdeck_12);
|
||||
lv_style_set_pad_all(&s_statusToast, 0);
|
||||
lv_style_set_radius(&s_statusToast, 0);
|
||||
|
||||
@@ -277,7 +277,7 @@ void init(lv_disp_t* disp) {
|
||||
lv_style_init(&s_tabCell);
|
||||
lv_style_set_bg_opa(&s_tabCell, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&s_tabCell, 0);
|
||||
lv_style_set_text_font(&s_tabCell, &lv_font_ratdeck_10);
|
||||
lv_style_set_text_font(&s_tabCell, &lv_font_rsdeck_10);
|
||||
lv_style_set_pad_all(&s_tabCell, 0);
|
||||
lv_style_set_radius(&s_tabCell, 0);
|
||||
|
||||
@@ -288,7 +288,7 @@ void init(lv_disp_t* disp) {
|
||||
|
||||
lv_style_init(&s_badge);
|
||||
lv_style_set_bg_opa(&s_badge, LV_OPA_COVER);
|
||||
lv_style_set_text_font(&s_badge, &lv_font_ratdeck_10);
|
||||
lv_style_set_text_font(&s_badge, &lv_font_rsdeck_10);
|
||||
lv_style_set_radius(&s_badge, 3);
|
||||
lv_style_set_pad_all(&s_badge, 0);
|
||||
|
||||
@@ -297,7 +297,7 @@ void init(lv_disp_t* disp) {
|
||||
// Apply screen style to default theme
|
||||
lv_obj_add_style(lv_scr_act(), &s_screen, 0);
|
||||
|
||||
Serial.println("[LVGL] Ratdeck field-console theme initialized");
|
||||
Serial.println("[LVGL] rsDeck field-console theme initialized");
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
// Ratdeck LVGL theme: compact field-console styles for LVGL 8.3.
|
||||
// rsDeck LVGL theme: compact field-console styles for LVGL 8.3.
|
||||
namespace LvTheme {
|
||||
|
||||
void init(lv_disp_t* disp);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#include "Theme.h"
|
||||
|
||||
// Dark column is the original Ratdeck palette, verbatim. Light column is
|
||||
// Dark column is the original rsDeck palette, verbatim. Light column is
|
||||
// derived: same hue family, brand greens/cyan darkened for light-bg contrast.
|
||||
#define THEME_COLORS(X) \
|
||||
X(BG, 0x05080A, 0xF2F6F4) \
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
// =============================================================================
|
||||
// Ratdeck design constants
|
||||
// rsDeck design constants
|
||||
// Field-console palette tuned for the 320x240 LVGL surface.
|
||||
// Colors are runtime-switchable (Dark = original palette, Light = derived);
|
||||
// the value tables live in Theme.cpp. Identifiers keep their original
|
||||
|
||||
@@ -84,13 +84,13 @@ lv_obj_t* createEmptyState(lv_obj_t* parent) {
|
||||
lv_obj_clear_flag(shoulders, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* title = lv_label_create(box);
|
||||
lv_obj_set_style_text_font(title, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_text(title, "No trusted contacts");
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 49);
|
||||
|
||||
lv_obj_t* hint = lv_label_create(box);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(hint, "Saved peers appear here");
|
||||
lv_obj_align(hint, LV_ALIGN_TOP_MID, 0, 70);
|
||||
@@ -194,13 +194,13 @@ void LvContactsScreen::rebuildList() {
|
||||
}, LV_EVENT_FOCUSED, nullptr);
|
||||
|
||||
lv_obj_t* qrLbl = lv_label_create(qrRow);
|
||||
lv_obj_set_style_text_font(qrLbl, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(qrLbl, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(qrLbl, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_text(qrLbl, "Share My QR");
|
||||
lv_obj_align(qrLbl, LV_ALIGN_LEFT_MID, 12, 0);
|
||||
|
||||
lv_obj_t* hintLbl = lv_label_create(qrRow);
|
||||
lv_obj_set_style_text_font(hintLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(hintLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(hintLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(hintLbl, "Enter");
|
||||
lv_obj_align(hintLbl, LV_ALIGN_RIGHT_MID, -12, 0);
|
||||
@@ -247,7 +247,7 @@ void LvContactsScreen::rebuildList() {
|
||||
LxmFaceAvatar::render(avatar.canvas, String(hashHex.c_str()));
|
||||
|
||||
lv_obj_t* nameLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(nameLbl, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(nameLbl, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(nameLbl, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_long_mode(nameLbl, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(nameLbl, Theme::CONTENT_W - kContactTextX - 72);
|
||||
@@ -256,7 +256,7 @@ void LvContactsScreen::rebuildList() {
|
||||
lv_obj_set_pos(nameLbl, kContactTextX, 2);
|
||||
|
||||
lv_obj_t* metaLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(metaLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(metaLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(metaLbl, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_obj_set_style_text_align(metaLbl, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
lv_label_set_long_mode(metaLbl, LV_LABEL_LONG_CLIP);
|
||||
@@ -266,7 +266,7 @@ void LvContactsScreen::rebuildList() {
|
||||
lv_obj_set_pos(metaLbl, Theme::CONTENT_W - 72, 5);
|
||||
|
||||
lv_obj_t* idLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(idLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(idLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(idLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_long_mode(idLbl, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(idLbl, Theme::CONTENT_W - kContactTextX - 8);
|
||||
|
||||
@@ -61,7 +61,7 @@ void LvDataCleanScreen::createUI(lv_obj_t* parent) {
|
||||
_selectedYes = false;
|
||||
_confirmWipe = false;
|
||||
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "STORAGE CHECK", &lv_font_ratdeck_10,
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "STORAGE CHECK", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, 220, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
lv_obj_align(eyebrow, LV_ALIGN_TOP_MID, 0, 10);
|
||||
@@ -72,17 +72,17 @@ void LvDataCleanScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 28);
|
||||
|
||||
lv_obj_t* msg = makeLabel(parent,
|
||||
"Ratdeck found older data on the SD card.",
|
||||
&lv_font_ratdeck_12, Theme::TEXT_PRIMARY, 268, LV_TEXT_ALIGN_CENTER);
|
||||
"rsDeck found older data on the SD card.",
|
||||
&lv_font_rsdeck_12, Theme::TEXT_PRIMARY, 268, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(msg, LV_ALIGN_TOP_MID, 0, 58);
|
||||
|
||||
lv_obj_t* prompt = makeLabel(parent,
|
||||
"Keeping data is safest. Erase only for a clean setup.",
|
||||
&lv_font_ratdeck_12, Theme::TEXT_SECONDARY, 276, LV_TEXT_ALIGN_CENTER);
|
||||
&lv_font_rsdeck_12, Theme::TEXT_SECONDARY, 276, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(prompt, LV_ALIGN_TOP_MID, 0, 82);
|
||||
|
||||
_noBox = makeChoice(parent, 28, 122);
|
||||
_noLabel = makeLabel(_noBox, "KEEP DATA", &lv_font_ratdeck_12,
|
||||
_noLabel = makeLabel(_noBox, "KEEP DATA", &lv_font_rsdeck_12,
|
||||
Theme::TEXT_PRIMARY, 112, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
lv_obj_center(_noLabel);
|
||||
@@ -96,7 +96,7 @@ void LvDataCleanScreen::createUI(lv_obj_t* parent) {
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
_yesBox = makeChoice(parent, 166, 122);
|
||||
_yesLabel = makeLabel(_yesBox, "ERASE", &lv_font_ratdeck_12,
|
||||
_yesLabel = makeLabel(_yesBox, "ERASE", &lv_font_rsdeck_12,
|
||||
Theme::TEXT_PRIMARY, 112, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
lv_obj_center(_yesLabel);
|
||||
@@ -112,26 +112,26 @@ void LvDataCleanScreen::createUI(lv_obj_t* parent) {
|
||||
if (self->_doneCb) self->_doneCb(true);
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
_confirmLabel = makeLabel(parent, "", &lv_font_ratdeck_12,
|
||||
_confirmLabel = makeLabel(parent, "", &lv_font_rsdeck_12,
|
||||
Theme::WARNING_CLR, 280, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(_confirmLabel, LV_ALIGN_TOP_MID, 0, 164);
|
||||
|
||||
_hintLabel = makeLabel(parent, "Left/Right choose Enter continues",
|
||||
&lv_font_ratdeck_12, Theme::ACCENT,
|
||||
&lv_font_rsdeck_12, Theme::ACCENT,
|
||||
286, LV_TEXT_ALIGN_CENTER, LV_LABEL_LONG_DOT);
|
||||
lv_obj_align(_hintLabel, LV_ALIGN_TOP_MID, 0, 188);
|
||||
|
||||
_statusLabel = makeLabel(parent, "", &lv_font_ratdeck_12,
|
||||
_statusLabel = makeLabel(parent, "", &lv_font_rsdeck_12,
|
||||
Theme::PRIMARY, 286, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(_statusLabel, LV_ALIGN_TOP_MID, 0, 140);
|
||||
lv_obj_add_flag(_statusLabel, LV_OBJ_FLAG_HIDDEN);
|
||||
updateSelection();
|
||||
|
||||
lv_obj_t* ver = makeLabel(parent, "", &lv_font_ratdeck_10,
|
||||
lv_obj_t* ver = makeLabel(parent, "", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_MUTED, 120, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
char verBuf[32];
|
||||
snprintf(verBuf, sizeof(verBuf), "v%s", RATDECK_VERSION_STRING);
|
||||
snprintf(verBuf, sizeof(verBuf), "v%s", RSDECK_VERSION_STRING);
|
||||
lv_label_set_text(ver, verBuf);
|
||||
lv_obj_align(ver, LV_ALIGN_BOTTOM_MID, 0, -10);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ lv_obj_t* makeRow(lv_obj_t* parent) {
|
||||
|
||||
void addHelpRow(lv_obj_t* parent, const char* keys, const char* action) {
|
||||
lv_obj_t* row = makeRow(parent);
|
||||
makeLabel(row, keys, &lv_font_ratdeck_10, Theme::ACCENT, 72, LV_TEXT_ALIGN_LEFT);
|
||||
makeLabel(row, action, &lv_font_ratdeck_10, Theme::TEXT_PRIMARY, 178, LV_TEXT_ALIGN_LEFT);
|
||||
makeLabel(row, keys, &lv_font_rsdeck_10, Theme::ACCENT, 72, LV_TEXT_ALIGN_LEFT);
|
||||
makeLabel(row, action, &lv_font_rsdeck_10, Theme::TEXT_PRIMARY, 178, LV_TEXT_ALIGN_LEFT);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -60,8 +60,8 @@ void LvHelpOverlay::create() {
|
||||
|
||||
lv_obj_t* header = makeRow(_overlay);
|
||||
lv_obj_set_height(header, 16);
|
||||
makeLabel(header, "HELP", &lv_font_ratdeck_12, Theme::ACCENT, 70, LV_TEXT_ALIGN_LEFT);
|
||||
makeLabel(header, "Ratspeak.org", &lv_font_ratdeck_10,
|
||||
makeLabel(header, "HELP", &lv_font_rsdeck_12, Theme::ACCENT, 70, LV_TEXT_ALIGN_LEFT);
|
||||
makeLabel(header, "Ratspeak.org", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, 180, LV_TEXT_ALIGN_RIGHT);
|
||||
|
||||
addHelpRow(_overlay, "Trackball", "Move selection");
|
||||
@@ -75,7 +75,7 @@ void LvHelpOverlay::create() {
|
||||
addHelpRow(_overlay, "Ctrl+D/I/T/R", "Diagnostics tools");
|
||||
|
||||
lv_obj_t* footer = makeLabel(_overlay, "Any key or tap closes",
|
||||
&lv_font_ratdeck_10, Theme::TEXT_MUTED,
|
||||
&lv_font_rsdeck_10, Theme::TEXT_MUTED,
|
||||
260, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_set_style_pad_top(footer, 2, 0);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ lv_obj_t* makeLabel(lv_obj_t* parent, lv_coord_t x, lv_coord_t y, lv_coord_t w,
|
||||
}
|
||||
|
||||
lv_obj_t* makeCaption(lv_obj_t* parent, const char* text) {
|
||||
lv_obj_t* lbl = makeLabel(parent, 7, 4, 84, &lv_font_ratdeck_10,
|
||||
lv_obj_t* lbl = makeLabel(parent, 7, 4, 84, &lv_font_rsdeck_10,
|
||||
Theme::TEXT_MUTED, text);
|
||||
lv_obj_set_style_text_letter_space(lbl, 1, 0);
|
||||
return lbl;
|
||||
@@ -71,7 +71,7 @@ lv_obj_t* makeChip(lv_obj_t* parent, lv_coord_t x, const char* title,
|
||||
lv_obj_t* chip = makePanel(parent, x, kChipY, kCellW, kChipH,
|
||||
Theme::BG_ELEVATED, Theme::BORDER);
|
||||
makeCaption(chip, title);
|
||||
*valueLabel = makeLabel(chip, 7, 18, 84, &lv_font_ratdeck_12,
|
||||
*valueLabel = makeLabel(chip, 7, 18, 84, &lv_font_rsdeck_12,
|
||||
Theme::TEXT_SECONDARY, "...");
|
||||
return chip;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ lv_obj_t* makeStat(lv_obj_t* parent, lv_coord_t x, const char* title,
|
||||
lv_obj_t* stat = makePanel(parent, x, kStatY, kCellW, kStatH,
|
||||
Theme::BG_ELEVATED, Theme::BORDER);
|
||||
makeCaption(stat, title);
|
||||
*valueLabel = makeLabel(stat, 7, 17, 84, &lv_font_ratdeck_14,
|
||||
*valueLabel = makeLabel(stat, 7, 17, 84, &lv_font_rsdeck_14,
|
||||
Theme::TEXT_PRIMARY, "0");
|
||||
return stat;
|
||||
}
|
||||
@@ -172,23 +172,23 @@ void LvHomeScreen::createUI(lv_obj_t* parent) {
|
||||
_avatarSeed = "";
|
||||
|
||||
_lblConsoleTitle = makeLabel(_identityPanel, 58, 6, 116,
|
||||
&lv_font_ratdeck_10, Theme::ACCENT,
|
||||
&lv_font_rsdeck_10, Theme::ACCENT,
|
||||
"IDENTITY:");
|
||||
lv_obj_set_style_text_letter_space(_lblConsoleTitle, 1, 0);
|
||||
|
||||
_lblStatus = makeLabel(_identityPanel, 184, 6, 114, &lv_font_ratdeck_10,
|
||||
_lblStatus = makeLabel(_identityPanel, 184, 6, 114, &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, "OFFLINE",
|
||||
LV_TEXT_ALIGN_RIGHT);
|
||||
lv_obj_set_style_text_letter_space(_lblStatus, 1, 0);
|
||||
|
||||
_lblName = makeLabel(_identityPanel, 58, 21, 240, &lv_font_ratdeck_14,
|
||||
_lblName = makeLabel(_identityPanel, 58, 21, 240, &lv_font_rsdeck_14,
|
||||
Theme::TEXT_PRIMARY, "...");
|
||||
lv_label_set_long_mode(_lblName, LV_LABEL_LONG_DOT);
|
||||
|
||||
_lblId = makeLabel(_identityPanel, 58, 41, 136, &lv_font_ratdeck_10,
|
||||
_lblId = makeLabel(_identityPanel, 58, 41, 136, &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, "LXMF ----");
|
||||
_lblIdentity = makeLabel(_identityPanel, 198, 41, 100,
|
||||
&lv_font_ratdeck_10, Theme::TEXT_MUTED,
|
||||
&lv_font_rsdeck_10, Theme::TEXT_MUTED,
|
||||
"ID ----", LV_TEXT_ALIGN_RIGHT);
|
||||
|
||||
_chipLora = makeChip(parent, kPad, "LORA", &_lblLoraState);
|
||||
@@ -226,10 +226,10 @@ void LvHomeScreen::createUI(lv_obj_t* parent) {
|
||||
|
||||
lv_obj_t* footer = makePanel(parent, kPad, kFooterY, 198, kFooterH,
|
||||
Theme::BG_ELEVATED, Theme::BORDER);
|
||||
_lblSummary = makeLabel(footer, 8, 6, 182, &lv_font_ratdeck_12,
|
||||
_lblSummary = makeLabel(footer, 8, 6, 182, &lv_font_rsdeck_12,
|
||||
Theme::TEXT_SECONDARY, "Waiting for transport");
|
||||
lv_label_set_long_mode(_lblSummary, LV_LABEL_LONG_DOT);
|
||||
_lblLastAnnounce = makeLabel(footer, 8, 23, 182, &lv_font_ratdeck_10,
|
||||
_lblLastAnnounce = makeLabel(footer, 8, 23, 182, &lv_font_rsdeck_10,
|
||||
Theme::TEXT_MUTED, "Announced: never");
|
||||
lv_label_set_long_mode(_lblLastAnnounce, LV_LABEL_LONG_CLIP);
|
||||
|
||||
@@ -246,7 +246,7 @@ void LvHomeScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_set_style_pad_all(_btnAnnounce, 0, 0);
|
||||
|
||||
_lblAnnounceAction = lv_label_create(_btnAnnounce);
|
||||
lv_obj_set_style_text_font(_lblAnnounceAction, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(_lblAnnounceAction, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(_lblAnnounceAction, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_text(_lblAnnounceAction, "ANNOUNCE");
|
||||
lv_obj_center(_lblAnnounceAction);
|
||||
@@ -291,7 +291,7 @@ void LvHomeScreen::refreshUI() {
|
||||
String dh = _rns->destinationHashHex();
|
||||
displayName = "Ratspeak.org-" + dh.substring(0, 3);
|
||||
} else {
|
||||
displayName = "Ratdeck";
|
||||
displayName = "rsDeck";
|
||||
}
|
||||
lv_label_set_text(_lblName, displayName.c_str());
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ void LvMapScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_clear_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* lbl = lv_label_create(parent);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(lbl, "Map\n\nComing soon\n\nNode topology view\nwill appear here");
|
||||
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, 0);
|
||||
|
||||
@@ -155,7 +155,7 @@ void LvMessageView::createUI(lv_obj_t* parent) {
|
||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_style_pad_row(parent, 0, 0);
|
||||
|
||||
const lv_font_t* font = &lv_font_ratdeck_12;
|
||||
const lv_font_t* font = &lv_font_rsdeck_12;
|
||||
|
||||
// Header bar (top)
|
||||
_header = lv_obj_create(parent);
|
||||
@@ -170,27 +170,27 @@ void LvMessageView::createUI(lv_obj_t* parent) {
|
||||
lv_obj_clear_flag(_header, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* backLbl = lv_label_create(_header);
|
||||
lv_obj_set_style_text_font(backLbl, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(backLbl, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(backLbl, lv_color_hex(Theme::PRIMARY), 0);
|
||||
lv_label_set_text(backLbl, "<");
|
||||
lv_obj_align(backLbl, LV_ALIGN_LEFT_MID, 6, 0);
|
||||
|
||||
_lblHeader = lv_label_create(_header);
|
||||
lv_obj_set_style_text_font(_lblHeader, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(_lblHeader, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(_lblHeader, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_long_mode(_lblHeader, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(_lblHeader, 188);
|
||||
lv_obj_set_pos(_lblHeader, 22, 3);
|
||||
|
||||
_lblHeaderMeta = lv_label_create(_header);
|
||||
lv_obj_set_style_text_font(_lblHeaderMeta, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_lblHeaderMeta, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_lblHeaderMeta, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_long_mode(_lblHeaderMeta, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(_lblHeaderMeta, Theme::CONTENT_W - 30);
|
||||
lv_obj_set_pos(_lblHeaderMeta, 22, 21);
|
||||
|
||||
_lblHeaderState = lv_label_create(_header);
|
||||
lv_obj_set_style_text_font(_lblHeaderState, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_lblHeaderState, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_lblHeaderState, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(_lblHeaderState, "UNKNOWN");
|
||||
lv_obj_align(_lblHeaderState, LV_ALIGN_TOP_RIGHT, -8, 8);
|
||||
@@ -255,7 +255,7 @@ void LvMessageView::createUI(lv_obj_t* parent) {
|
||||
lv_obj_add_style(_btnSend, LvTheme::styleBtn(), 0);
|
||||
lv_obj_set_style_pad_all(_btnSend, 0, 0);
|
||||
lv_obj_t* sendLbl = lv_label_create(_btnSend);
|
||||
lv_obj_set_style_text_font(sendLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(sendLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(sendLbl, lv_color_hex(Theme::PRIMARY), 0);
|
||||
lv_label_set_text(sendLbl, "SEND");
|
||||
lv_obj_center(sendLbl);
|
||||
@@ -384,7 +384,7 @@ void LvMessageView::refreshUI() {
|
||||
void LvMessageView::appendMessage(const LXMFMessage& msg) {
|
||||
if (!_msgScroll) return;
|
||||
|
||||
const lv_font_t* font = &lv_font_ratdeck_12;
|
||||
const lv_font_t* font = &lv_font_rsdeck_12;
|
||||
int textW = textWidthForBubble(msg.content);
|
||||
if (!msg.incoming && textW < 96) textW = 96;
|
||||
int boxW = textW + 16;
|
||||
@@ -455,7 +455,7 @@ void LvMessageView::appendMessage(const LXMFMessage& msg) {
|
||||
|
||||
if (hasTime) {
|
||||
lv_obj_t* timeLbl = lv_label_create(meta);
|
||||
lv_obj_set_style_text_font(timeLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(timeLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(timeLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(timeLbl, timeBuf);
|
||||
lv_obj_align(timeLbl, LV_ALIGN_LEFT_MID, 0, 0);
|
||||
@@ -463,7 +463,7 @@ void LvMessageView::appendMessage(const LXMFMessage& msg) {
|
||||
|
||||
if (!msg.incoming) {
|
||||
statusLbl = lv_label_create(meta);
|
||||
lv_obj_set_style_text_font(statusLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(statusLbl, &lv_font_rsdeck_10, 0);
|
||||
applyStatusGlyph(statusLbl, msg.status);
|
||||
lv_obj_align(statusLbl, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||
}
|
||||
@@ -519,13 +519,13 @@ void LvMessageView::rebuildMessages() {
|
||||
lv_obj_align(icon, LV_ALIGN_TOP_MID, 0, 13);
|
||||
|
||||
lv_obj_t* title = lv_label_create(empty);
|
||||
lv_obj_set_style_text_font(title, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(Theme::TEXT_PRIMARY), 0);
|
||||
lv_label_set_text(title, "No messages yet");
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 32);
|
||||
|
||||
lv_obj_t* sub = lv_label_create(empty);
|
||||
lv_obj_set_style_text_font(sub, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(sub, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(sub, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_text(sub, "Thread is quiet");
|
||||
lv_obj_align(sub, LV_ALIGN_TOP_MID, 0, 54);
|
||||
@@ -724,7 +724,7 @@ void LvMessageView::showSendModeMenu() {
|
||||
lv_obj_clear_flag(_sendOverlay, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* title = lv_label_create(_sendOverlay);
|
||||
lv_obj_set_style_text_font(title, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_text(title, "Send mode");
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 0);
|
||||
@@ -748,7 +748,7 @@ void LvMessageView::showSendModeMenu() {
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
_sendLabels[i] = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(_sendLabels[i], &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(_sendLabels[i], &lv_font_rsdeck_12, 0);
|
||||
lv_label_set_text(_sendLabels[i], labels[i]);
|
||||
lv_obj_center(_sendLabels[i]);
|
||||
_sendRows[i] = row;
|
||||
|
||||
@@ -121,13 +121,13 @@ void LvMessagesScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_align(emptyIcon, LV_ALIGN_TOP_MID, 0, 15);
|
||||
|
||||
lv_obj_t* emptyTitle = lv_label_create(_lblEmpty);
|
||||
lv_obj_set_style_text_font(emptyTitle, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(emptyTitle, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(emptyTitle, lv_color_hex(Theme::TEXT_PRIMARY), 0);
|
||||
lv_label_set_text(emptyTitle, "No conversations");
|
||||
lv_obj_align(emptyTitle, LV_ALIGN_TOP_MID, 0, 34);
|
||||
|
||||
lv_obj_t* emptySub = lv_label_create(_lblEmpty);
|
||||
lv_obj_set_style_text_font(emptySub, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(emptySub, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(emptySub, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_text(emptySub, "LXMF inbox is clear");
|
||||
lv_obj_align(emptySub, LV_ALIGN_TOP_MID, 0, 56);
|
||||
@@ -241,8 +241,8 @@ void LvMessagesScreen::rebuildList() {
|
||||
for (auto& ci : _sortedConvs) _sortedPeers.push_back(ci.peerHex);
|
||||
|
||||
// Build list items with focus group support
|
||||
const lv_font_t* nameFont = &lv_font_ratdeck_14;
|
||||
const lv_font_t* smallFont = &lv_font_ratdeck_12;
|
||||
const lv_font_t* nameFont = &lv_font_rsdeck_14;
|
||||
const lv_font_t* smallFont = &lv_font_rsdeck_12;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const auto& ci = _sortedConvs[i];
|
||||
@@ -319,7 +319,7 @@ void LvMessagesScreen::rebuildList() {
|
||||
char timeBuf[8];
|
||||
if (formatClock(ci.lastTs, timeBuf, sizeof(timeBuf))) {
|
||||
lv_obj_t* timeLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(timeLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(timeLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(timeLbl, lv_color_hex(ci.hasUnread ? Theme::PRIMARY : Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(timeLbl, timeBuf);
|
||||
lv_obj_align(timeLbl, LV_ALIGN_TOP_RIGHT, -8, 7);
|
||||
@@ -370,7 +370,7 @@ void LvMessagesScreen::rebuildList() {
|
||||
lv_obj_clear_flag(chip, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* chipLbl = lv_label_create(chip);
|
||||
lv_obj_set_style_text_font(chipLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(chipLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(chipLbl, lv_color_hex(chipColor), 0);
|
||||
lv_label_set_text(chipLbl, chipBuf);
|
||||
lv_obj_center(chipLbl);
|
||||
@@ -430,7 +430,7 @@ void LvMessagesScreen::rebuildActionOverlay(const char* title, const char* const
|
||||
lv_obj_clear_flag(_actionOverlay, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* titleLbl = lv_label_create(_actionOverlay);
|
||||
lv_obj_set_style_text_font(titleLbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(titleLbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(titleLbl, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_long_mode(titleLbl, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(titleLbl, 220);
|
||||
@@ -458,7 +458,7 @@ void LvMessagesScreen::rebuildActionOverlay(const char* title, const char* const
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
lv_obj_t* lbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_hex(Theme::TEXT_PRIMARY), 0);
|
||||
lv_label_set_long_mode(lbl, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(lbl, 200);
|
||||
|
||||
@@ -46,7 +46,7 @@ lv_obj_t* makeActionButton(lv_obj_t* parent, const char* text, lv_coord_t y) {
|
||||
lv_obj_set_style_pad_all(btn, 0, 0);
|
||||
|
||||
lv_obj_t* lbl = lv_label_create(btn);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_long_mode(lbl, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(lbl, 150);
|
||||
@@ -66,7 +66,7 @@ void LvNameInputScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_set_style_bg_color(parent, lv_color_hex(Theme::BG), 0);
|
||||
lv_obj_set_style_bg_opa(parent, LV_OPA_COVER, 0);
|
||||
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "FIRST BOOT", &lv_font_ratdeck_10,
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "FIRST BOOT", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, 220, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
lv_obj_align(eyebrow, LV_ALIGN_TOP_MID, 0, 13);
|
||||
@@ -79,7 +79,7 @@ void LvNameInputScreen::createUI(lv_obj_t* parent) {
|
||||
|
||||
lv_obj_t* prompt = makeLabel(parent,
|
||||
"Choose the name other operators see on announces.",
|
||||
&lv_font_ratdeck_12, Theme::TEXT_PRIMARY, 250, LV_TEXT_ALIGN_CENTER);
|
||||
&lv_font_rsdeck_12, Theme::TEXT_PRIMARY, 250, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(prompt, LV_ALIGN_TOP_MID, 0, 70);
|
||||
|
||||
_textarea = lv_textarea_create(parent);
|
||||
@@ -90,13 +90,13 @@ void LvNameInputScreen::createUI(lv_obj_t* parent) {
|
||||
lv_textarea_set_placeholder_text(_textarea, "Optional");
|
||||
lv_obj_add_style(_textarea, LvTheme::styleTextarea(), 0);
|
||||
lv_obj_add_style(_textarea, LvTheme::styleTextareaFocused(), LV_STATE_FOCUSED);
|
||||
lv_obj_set_style_text_font(_textarea, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(_textarea, &lv_font_rsdeck_14, 0);
|
||||
lv_group_add_obj(LvInput::group(), _textarea);
|
||||
lv_group_focus_obj(_textarea);
|
||||
|
||||
lv_obj_t* note = makeLabel(parent,
|
||||
"Leave blank to generate a Ratdeck name from this identity.",
|
||||
&lv_font_ratdeck_12, Theme::TEXT_SECONDARY, 260, LV_TEXT_ALIGN_CENTER);
|
||||
"Leave blank to generate a rsDeck name from this identity.",
|
||||
&lv_font_rsdeck_12, Theme::TEXT_SECONDARY, 260, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(note, LV_ALIGN_TOP_MID, 0, 154);
|
||||
|
||||
_doneButton = makeActionButton(parent, "DONE", 184);
|
||||
@@ -106,11 +106,11 @@ void LvNameInputScreen::createUI(lv_obj_t* parent) {
|
||||
self->submit(false);
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
lv_obj_t* ver = makeLabel(parent, "", &lv_font_ratdeck_10,
|
||||
lv_obj_t* ver = makeLabel(parent, "", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_MUTED, 120, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
char verBuf[32];
|
||||
snprintf(verBuf, sizeof(verBuf), "v%s", RATDECK_VERSION_STRING);
|
||||
snprintf(verBuf, sizeof(verBuf), "v%s", RSDECK_VERSION_STRING);
|
||||
lv_label_set_text(ver, verBuf);
|
||||
lv_obj_align(ver, LV_ALIGN_BOTTOM_MID, 0, -10);
|
||||
}
|
||||
|
||||
@@ -80,13 +80,13 @@ lv_obj_t* createEmptyState(lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
lv_obj_t* title = lv_label_create(box);
|
||||
lv_obj_set_style_text_font(title, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_text(title, "No peers heard");
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 34);
|
||||
|
||||
lv_obj_t* hint = lv_label_create(box);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(hint, "Listening for announces");
|
||||
lv_obj_align(hint, LV_ALIGN_TOP_MID, 0, 55);
|
||||
@@ -122,21 +122,21 @@ void LvNodesScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_add_flag(_overlay, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
_overlayTitle = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(_overlayTitle, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(_overlayTitle, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(_overlayTitle, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_long_mode(_overlayTitle, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(_overlayTitle, 236);
|
||||
lv_obj_set_pos(_overlayTitle, 12, 9);
|
||||
|
||||
_overlayMeta = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(_overlayMeta, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_overlayMeta, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_overlayMeta, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_long_mode(_overlayMeta, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(_overlayMeta, 236);
|
||||
lv_obj_set_pos(_overlayMeta, 12, 29);
|
||||
|
||||
_overlayReach = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(_overlayReach, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_overlayReach, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_overlayReach, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_long_mode(_overlayReach, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(_overlayReach, 236);
|
||||
@@ -166,7 +166,7 @@ void LvNodesScreen::createUI(lv_obj_t* parent) {
|
||||
}, LV_EVENT_CLICKED, this);
|
||||
|
||||
_menuLabels[i] = lv_label_create(btn);
|
||||
lv_obj_set_style_text_font(_menuLabels[i], &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(_menuLabels[i], &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(_menuLabels[i], lv_color_hex(Theme::PRIMARY), 0);
|
||||
lv_label_set_text(_menuLabels[i], menuText[i]);
|
||||
lv_obj_center(_menuLabels[i]);
|
||||
@@ -185,13 +185,13 @@ void LvNodesScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_add_flag(_nicknameBox, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
lv_obj_t* nickTitle = lv_label_create(_nicknameBox);
|
||||
lv_obj_set_style_text_font(nickTitle, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(nickTitle, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(nickTitle, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_label_set_text(nickTitle, "Contact name");
|
||||
lv_obj_set_pos(nickTitle, 0, 0);
|
||||
|
||||
_nicknameLbl = lv_label_create(_nicknameBox);
|
||||
lv_obj_set_style_text_font(_nicknameLbl, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(_nicknameLbl, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(_nicknameLbl, lv_color_hex(Theme::PRIMARY), 0);
|
||||
lv_label_set_long_mode(_nicknameLbl, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(_nicknameLbl, 232);
|
||||
@@ -199,7 +199,7 @@ void LvNodesScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_set_pos(_nicknameLbl, 0, 22);
|
||||
|
||||
_nicknameHint = lv_label_create(_nicknameBox);
|
||||
lv_obj_set_style_text_font(_nicknameHint, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_nicknameHint, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_nicknameHint, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(_nicknameHint, "Enter saves / Esc keeps");
|
||||
lv_obj_set_pos(_nicknameHint, 0, 52);
|
||||
@@ -291,7 +291,7 @@ void LvNodesScreen::rebuildList() {
|
||||
lv_obj_set_style_pad_all(hdr, 0, 0);
|
||||
lv_obj_clear_flag(hdr, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_t* lbl = lv_label_create(hdr);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_text(lbl, text);
|
||||
lv_obj_set_pos(lbl, 8, 5);
|
||||
@@ -327,7 +327,7 @@ void LvNodesScreen::rebuildList() {
|
||||
}, LV_EVENT_FOCUSED, nullptr);
|
||||
|
||||
lv_obj_t* nameLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(nameLbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(nameLbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(nameLbl, lv_color_hex(
|
||||
node.saved ? Theme::ACCENT : Theme::PRIMARY), 0);
|
||||
lv_label_set_long_mode(nameLbl, LV_LABEL_LONG_CLIP);
|
||||
@@ -337,7 +337,7 @@ void LvNodesScreen::rebuildList() {
|
||||
lv_obj_set_pos(nameLbl, 8, 3);
|
||||
|
||||
lv_obj_t* infoLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(infoLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(infoLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(infoLbl, lv_color_hex(Theme::TEXT_SECONDARY), 0);
|
||||
lv_obj_set_style_text_align(infoLbl, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
lv_label_set_long_mode(infoLbl, LV_LABEL_LONG_CLIP);
|
||||
@@ -347,7 +347,7 @@ void LvNodesScreen::rebuildList() {
|
||||
lv_obj_set_pos(infoLbl, Theme::CONTENT_W - 124, 5);
|
||||
|
||||
lv_obj_t* idLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(idLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(idLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(idLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_long_mode(idLbl, LV_LABEL_LONG_CLIP);
|
||||
lv_obj_set_width(idLbl, Theme::CONTENT_W - 16);
|
||||
|
||||
@@ -20,7 +20,7 @@ void LvQrOverlay::create() {
|
||||
lv_obj_clear_flag(_overlay, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* title = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(title, &lv_font_ratdeck_14, 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_rsdeck_14, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(Theme::ACCENT), 0);
|
||||
lv_label_set_text(title, "Scan to add me");
|
||||
|
||||
@@ -31,7 +31,7 @@ void LvQrOverlay::create() {
|
||||
lv_color_hex(0xFFFFFF));
|
||||
|
||||
_lblAddr = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(_lblAddr, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(_lblAddr, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(_lblAddr, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_long_mode(_lblAddr, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_width(_lblAddr, Theme::SCREEN_W - 12);
|
||||
@@ -39,7 +39,7 @@ void LvQrOverlay::create() {
|
||||
lv_label_set_text(_lblAddr, "");
|
||||
|
||||
lv_obj_t* hint = lv_label_create(_overlay);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(hint, "Any key to close");
|
||||
|
||||
|
||||
@@ -203,20 +203,20 @@ bool LvSettingsScreen::categoryNeedsReboot(int catIdx) const {
|
||||
bool LvSettingsScreen::confirmableAction(const SettingItem& item) const {
|
||||
return labelEq(item.label, "Developer Radio Controls")
|
||||
|| labelEq(item.label, "Format SD Card")
|
||||
|| labelEq(item.label, "Erase Ratdeck SD Data")
|
||||
|| labelEq(item.label, "Erase rsDeck SD Data")
|
||||
|| labelEq(item.label, "Erase Device");
|
||||
}
|
||||
|
||||
bool LvSettingsScreen::armedAction(const SettingItem& item) const {
|
||||
return (_confirmingInitSD && labelEq(item.label, "Format SD Card")) ||
|
||||
(_confirmingWipeSD && labelEq(item.label, "Erase Ratdeck SD Data")) ||
|
||||
(_confirmingWipeSD && labelEq(item.label, "Erase rsDeck SD Data")) ||
|
||||
(_confirmingReset && labelEq(item.label, "Erase Device")) ||
|
||||
(_confirmingDevMode && labelEq(item.label, "Developer Radio Controls"));
|
||||
}
|
||||
|
||||
bool LvSettingsScreen::destructiveAction(const SettingItem& item) const {
|
||||
return labelEq(item.label, "Format SD Card")
|
||||
|| labelEq(item.label, "Erase Ratdeck SD Data")
|
||||
|| labelEq(item.label, "Erase rsDeck SD Data")
|
||||
|| labelEq(item.label, "Erase Device");
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ void LvSettingsScreen::runFormatSD() {
|
||||
return;
|
||||
}
|
||||
if (_ui) _ui->lvStatusBar().showToast("Formatting SD card...", 2000);
|
||||
bool ok = _sd->formatForRatdeck();
|
||||
bool ok = _sd->formatForRsDeck();
|
||||
if (_ui) _ui->lvStatusBar().showToast(ok ? "SD card formatted" : "SD format failed", 1500);
|
||||
rebuildItemList();
|
||||
}
|
||||
@@ -267,8 +267,8 @@ void LvSettingsScreen::runWipeSD() {
|
||||
rebuildItemList();
|
||||
return;
|
||||
}
|
||||
if (_ui) _ui->lvStatusBar().showToast("Erasing Ratdeck SD data...", 2000);
|
||||
bool ok = _sd->wipeRatdeck();
|
||||
if (_ui) _ui->lvStatusBar().showToast("Erasing rsDeck SD data...", 2000);
|
||||
bool ok = _sd->wipeRsDeck();
|
||||
if (_ui) _ui->lvStatusBar().showToast(ok ? "SD data erased" : "SD erase failed", 1500);
|
||||
rebuildItemList();
|
||||
}
|
||||
@@ -276,7 +276,7 @@ void LvSettingsScreen::runWipeSD() {
|
||||
void LvSettingsScreen::runFactoryReset() {
|
||||
_confirmingReset = false;
|
||||
if (_ui) _ui->lvStatusBar().showToast("Erasing device...", 3000);
|
||||
if (_sd && _sd->isReady()) _sd->wipeRatdeck();
|
||||
if (_sd && _sd->isReady()) _sd->wipeRsDeck();
|
||||
if (_flash) _flash->format();
|
||||
nvs_flash_erase();
|
||||
delay(1500); // Long enough for key state to clear before reboot
|
||||
@@ -336,7 +336,7 @@ void LvSettingsScreen::firmwareCheckTask(void* arg) {
|
||||
HTTPClient http;
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
http.setTimeout(5000);
|
||||
if (http.begin("https://api.github.com/repos/ratspeak/ratdeck/releases/latest")) {
|
||||
if (http.begin("https://api.github.com/repos/ratspeak/rsDeck/releases/latest")) {
|
||||
http.addHeader("Accept", "application/vnd.github.v3+json");
|
||||
int httpCode = http.GET();
|
||||
if (httpCode == 200) {
|
||||
@@ -355,7 +355,7 @@ void LvSettingsScreen::firmwareCheckTask(void* arg) {
|
||||
delay(10);
|
||||
}
|
||||
if (extractReleaseTag(payload, version, sizeof(version))) {
|
||||
result = strcmp(version, RATDECK_VERSION_STRING) > 0
|
||||
result = strcmp(version, RSDECK_VERSION_STRING) > 0
|
||||
? FirmwareCheckState::AVAILABLE
|
||||
: FirmwareCheckState::CURRENT;
|
||||
}
|
||||
@@ -379,7 +379,7 @@ void LvSettingsScreen::buildItems() {
|
||||
// Identity & Device
|
||||
int devStart = idx;
|
||||
_items.push_back({"Firmware", SettingType::READONLY, nullptr, nullptr,
|
||||
[](int) { return String(RATDECK_VERSION_STRING); }});
|
||||
[](int) { return String(RSDECK_VERSION_STRING); }});
|
||||
idx++;
|
||||
_items.push_back({"LXMF Address", SettingType::READONLY, nullptr, nullptr,
|
||||
[this](int) { return _destinationHash.length() > 0 ? _destinationHash : String("unknown"); }});
|
||||
@@ -1005,7 +1005,7 @@ void LvSettingsScreen::buildItems() {
|
||||
}
|
||||
{
|
||||
SettingItem wipeSD;
|
||||
wipeSD.label = "Erase Ratdeck SD Data";
|
||||
wipeSD.label = "Erase rsDeck SD Data";
|
||||
wipeSD.type = SettingType::ACTION;
|
||||
wipeSD.formatter = [this](int) {
|
||||
if (!_sd || !_sd->isReady()) return String("No Card");
|
||||
@@ -1156,7 +1156,7 @@ void LvSettingsScreen::rebuildCategoryList() {
|
||||
_rowObjs.clear();
|
||||
lv_obj_clean(_scrollContainer);
|
||||
|
||||
const lv_font_t* font = &lv_font_ratdeck_12;
|
||||
const lv_font_t* font = &lv_font_rsdeck_12;
|
||||
|
||||
// Title
|
||||
lv_obj_t* titleRow = lv_obj_create(_scrollContainer);
|
||||
@@ -1177,7 +1177,7 @@ void LvSettingsScreen::rebuildCategoryList() {
|
||||
|
||||
if (_rebootNeeded) {
|
||||
lv_obj_t* pendingLbl = lv_label_create(titleRow);
|
||||
lv_obj_set_style_text_font(pendingLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(pendingLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(pendingLbl, lv_color_hex(Theme::WARNING_CLR), 0);
|
||||
lv_label_set_text(pendingLbl, "REBOOT PENDING");
|
||||
lv_obj_align(pendingLbl, LV_ALIGN_RIGHT_MID, -8, 0);
|
||||
@@ -1222,7 +1222,7 @@ void LvSettingsScreen::rebuildCategoryList() {
|
||||
char countBuf[8];
|
||||
snprintf(countBuf, sizeof(countBuf), "%d", cat.count);
|
||||
lv_obj_t* countLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(countLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(countLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(countLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(countLbl, countBuf);
|
||||
lv_obj_align(countLbl, LV_ALIGN_TOP_RIGHT, -24, 5);
|
||||
@@ -1230,7 +1230,7 @@ void LvSettingsScreen::rebuildCategoryList() {
|
||||
// Summary
|
||||
if (cat.summary) {
|
||||
lv_obj_t* sumLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(sumLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(sumLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(sumLbl, lv_color_hex(pending ? Theme::WARNING_CLR : Theme::TEXT_MUTED), 0);
|
||||
clipLabel(sumLbl, Theme::CONTENT_W - 44);
|
||||
lv_label_set_text(sumLbl, cat.summary().c_str());
|
||||
@@ -1259,7 +1259,7 @@ void LvSettingsScreen::rebuildItemList() {
|
||||
_editValueLbl = nullptr; // Invalidate cached label before destroying widgets
|
||||
lv_obj_clean(_scrollContainer);
|
||||
|
||||
const lv_font_t* font = &lv_font_ratdeck_12;
|
||||
const lv_font_t* font = &lv_font_rsdeck_12;
|
||||
|
||||
// Category header
|
||||
lv_obj_t* headerRow = lv_obj_create(_scrollContainer);
|
||||
@@ -1289,7 +1289,7 @@ void LvSettingsScreen::rebuildItemList() {
|
||||
|
||||
if (_rebootNeeded) {
|
||||
lv_obj_t* pendingLbl = lv_label_create(headerRow);
|
||||
lv_obj_set_style_text_font(pendingLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(pendingLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(pendingLbl, lv_color_hex(Theme::WARNING_CLR), 0);
|
||||
lv_label_set_text(pendingLbl, "REBOOT NEEDED");
|
||||
lv_obj_align(pendingLbl, LV_ALIGN_RIGHT_MID, -8, 0);
|
||||
@@ -1308,7 +1308,7 @@ void LvSettingsScreen::rebuildItemList() {
|
||||
lv_obj_clear_flag(notice, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* noticeLbl = lv_label_create(notice);
|
||||
lv_obj_set_style_text_font(noticeLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(noticeLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(noticeLbl, lv_color_hex(Theme::WARNING_CLR), 0);
|
||||
clipLabel(noticeLbl, Theme::CONTENT_W - 16);
|
||||
lv_label_set_text(noticeLbl, "Saved interface config is pending reboot");
|
||||
@@ -1331,14 +1331,14 @@ void LvSettingsScreen::rebuildItemList() {
|
||||
lv_obj_clear_flag(confirm, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* confirmTitleLbl = lv_label_create(confirm);
|
||||
lv_obj_set_style_text_font(confirmTitleLbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(confirmTitleLbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(confirmTitleLbl, lv_color_hex(confirmColor), 0);
|
||||
clipLabel(confirmTitleLbl, Theme::CONTENT_W - 16);
|
||||
lv_label_set_text(confirmTitleLbl, confirmTitle);
|
||||
lv_obj_align(confirmTitleLbl, LV_ALIGN_TOP_LEFT, 8, 3);
|
||||
|
||||
lv_obj_t* confirmDetailLbl = lv_label_create(confirm);
|
||||
lv_obj_set_style_text_font(confirmDetailLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(confirmDetailLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(confirmDetailLbl, lv_color_hex(Theme::TEXT_PRIMARY), 0);
|
||||
clipLabel(confirmDetailLbl, Theme::CONTENT_W - 16);
|
||||
lv_label_set_text(confirmDetailLbl, confirmDetail);
|
||||
@@ -1515,7 +1515,7 @@ void LvSettingsScreen::rebuildWifiList() {
|
||||
_rowObjs.clear();
|
||||
lv_obj_clean(_scrollContainer);
|
||||
|
||||
const lv_font_t* font = &lv_font_ratdeck_12;
|
||||
const lv_font_t* font = &lv_font_rsdeck_12;
|
||||
|
||||
// Header
|
||||
lv_obj_t* headerRow = lv_obj_create(_scrollContainer);
|
||||
@@ -1591,7 +1591,7 @@ void LvSettingsScreen::rebuildWifiList() {
|
||||
char sigBuf[12];
|
||||
snprintf(sigBuf, sizeof(sigBuf), "%ddBm", net.rssi);
|
||||
lv_obj_t* sigLbl = lv_label_create(row);
|
||||
lv_obj_set_style_text_font(sigLbl, &lv_font_ratdeck_10, 0);
|
||||
lv_obj_set_style_text_font(sigLbl, &lv_font_rsdeck_10, 0);
|
||||
lv_obj_set_style_text_color(sigLbl, lv_color_hex(Theme::TEXT_MUTED), 0);
|
||||
lv_label_set_text(sigLbl, sigBuf);
|
||||
lv_obj_align(sigLbl, LV_ALIGN_RIGHT_MID, -4, 0);
|
||||
@@ -1919,7 +1919,7 @@ bool LvSettingsScreen::handleLongPress() {
|
||||
runFormatSD();
|
||||
return true;
|
||||
}
|
||||
if (_confirmingWipeSD && labelEq(item.label, "Erase Ratdeck SD Data")) {
|
||||
if (_confirmingWipeSD && labelEq(item.label, "Erase rsDeck SD Data")) {
|
||||
runWipeSD();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ lv_obj_t* makeActionButton(lv_obj_t* parent, const char* text, lv_coord_t x,
|
||||
lv_obj_set_style_pad_all(btn, 0, 0);
|
||||
|
||||
lv_obj_t* lbl = lv_label_create(btn);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_ratdeck_12, 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_rsdeck_12, 0);
|
||||
lv_obj_set_style_text_color(lbl,
|
||||
lv_color_hex(primary ? Theme::ACCENT : Theme::TEXT_PRIMARY), 0);
|
||||
lv_label_set_long_mode(lbl, LV_LABEL_LONG_DOT);
|
||||
@@ -78,7 +78,7 @@ void LvTimezoneScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_set_style_bg_opa(parent, LV_OPA_COVER, 0);
|
||||
_selectedIdx = clampTimezoneIndex(_selectedIdx);
|
||||
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "REGION SETUP", &lv_font_ratdeck_10,
|
||||
lv_obj_t* eyebrow = makeLabel(parent, "REGION SETUP", &lv_font_rsdeck_10,
|
||||
Theme::TEXT_SECONDARY, 220, LV_TEXT_ALIGN_CENTER,
|
||||
LV_LABEL_LONG_DOT);
|
||||
lv_obj_align(eyebrow, LV_ALIGN_TOP_MID, 0, 8);
|
||||
@@ -89,7 +89,7 @@ void LvTimezoneScreen::createUI(lv_obj_t* parent) {
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 24);
|
||||
|
||||
lv_obj_t* sub = makeLabel(parent, "Pick the nearest city for time and radio-region hints.",
|
||||
&lv_font_ratdeck_12, Theme::TEXT_PRIMARY,
|
||||
&lv_font_rsdeck_12, Theme::TEXT_PRIMARY,
|
||||
280, LV_TEXT_ALIGN_CENTER);
|
||||
lv_obj_align(sub, LV_ALIGN_TOP_MID, 0, 48);
|
||||
|
||||
@@ -115,12 +115,12 @@ void LvTimezoneScreen::createUI(lv_obj_t* parent) {
|
||||
lv_roller_set_selected(_roller, _selectedIdx, LV_ANIM_OFF);
|
||||
|
||||
lv_obj_add_style(_roller, LvTheme::styleRoller(), LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(_roller, &lv_font_ratdeck_14, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(_roller, &lv_font_rsdeck_14, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_align(_roller, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(_roller, lv_color_hex(Theme::BG_HOVER), LV_PART_SELECTED);
|
||||
lv_obj_set_style_bg_opa(_roller, LV_OPA_COVER, LV_PART_SELECTED);
|
||||
lv_obj_set_style_text_color(_roller, lv_color_hex(Theme::ACCENT), LV_PART_SELECTED);
|
||||
lv_obj_set_style_text_font(_roller, &lv_font_ratdeck_14, LV_PART_SELECTED);
|
||||
lv_obj_set_style_text_font(_roller, &lv_font_rsdeck_14, LV_PART_SELECTED);
|
||||
lv_obj_set_style_text_align(_roller, LV_TEXT_ALIGN_CENTER, LV_PART_SELECTED);
|
||||
|
||||
// Add to focus group for trackball navigation
|
||||
|
||||
Reference in new issue
Block a user