From cad0c9bb46c6ab7d6f156661782feb9463c474a6 Mon Sep 17 00:00:00 2001 From: Julius Jurgelenas Date: Sat, 19 Sep 2026 00:31:21 +0300 Subject: [PATCH] Show -- when PWR is 0, retain last position data, merge RSSI 1 / 2 into single row and add RSNR when in non FLRC mdoe addresses > Telem Widget - PWR reads 0 mW when not connected but others show -- > Telem Widget - No last GPS position on disconnect? If not in your design plans that's fine, something for later. > Telem Widget - Fullscreen - Maybe merge RSSI 1 / RSSI 2 onto one line so the RSNR can be added? --- docs/development.md | 1 + screenshots/widget_telemetry_fullscren.png | Bin 29809 -> 29359 bytes src/SCRIPTS/CRSFSimulator/csrfsimulator.lua | 139 ++++++++++++++------ src/WIDGETS/ELRSTelemetry/rf_modes.lua | 12 ++ src/WIDGETS/ELRSTelemetry/telemetry.lua | 8 ++ src/WIDGETS/ELRSTelemetry/ui/display.lua | 4 +- src/WIDGETS/ELRSTelemetry/ui/fullscreen.lua | 85 +++++++----- 7 files changed, 174 insertions(+), 75 deletions(-) diff --git a/docs/development.md b/docs/development.md index 99bb2b4..41b64b2 100644 --- a/docs/development.md +++ b/docs/development.md @@ -143,6 +143,7 @@ The simulator supports multiple test scenarios, configurable via the `config.sce | `model_mismatch` | TX + RX connected with Model ID mismatch flag. Triggers warning dialog. | | `armed` | TX + RX connected with "is Armed" warning flag. `ANT` is pinned to 0. | | `single_antenna` | TX + RX connected on a receiver with one RF path. `2RSS` is pinned to 0, so the telemetry widget reports no diversity. | +| `flrc` | TX + RX connected at F1000. FLRC carries no SNR, so `RSNR` is a permanent 0 and the full-screen SNR row reads "n/a". | | `slow_loading` | Parameter reads delayed by ~2 seconds each. Tests loading UI states. | | `no_module` | No CRSF module found. Triggers "No Module Found" error dialog. | | `critical_error` | TX + RX connected with a critical baud-rate error flag. Triggers the warning screen; the suppress write clears it. | diff --git a/screenshots/widget_telemetry_fullscren.png b/screenshots/widget_telemetry_fullscren.png index b7d58df9b314c5d825d38906c4e035a7fcfbe10b..6db88d0ed73bf99a25520c915b27f7a01a101ff1 100644 GIT binary patch delta 16777 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 A4*&oF delta 16959 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 mockTelemetry returns nil. -- ============================================================================ -local txModuleTelemetry = { TPWR = 50 } - -- TQly/TRSS are the downlink pair: the RX->TX telemetry path, reported by the -- handset's own receiver. They run a few dB behind the uplink in every -- scenario because the receiver transmits at a fraction of the module's power, @@ -1698,6 +1700,7 @@ local scenarioTelemetry = { ["1RSS"] = -87, ["2RSS"] = -93, RQly = 99, + RSNR = 8, ANT = 1, TQly = 100, TRSS = -95, @@ -1717,6 +1720,7 @@ local scenarioTelemetry = { ["1RSS"] = -84, ["2RSS"] = 0, RQly = 97, + RSNR = 8, ANT = 0, TQly = 100, TRSS = -91, @@ -1734,6 +1738,7 @@ local scenarioTelemetry = { ["1RSS"] = -78, ["2RSS"] = -82, RQly = 100, + RSNR = 8, ANT = 0, TQly = 100, TRSS = -83, @@ -1745,6 +1750,26 @@ local scenarioTelemetry = { Alt = 85, GPS = { lat = 54.7050, lon = 25.3100 }, }, + -- TX + RX connected at F1000 (v3 index 13). FLRC carries no SNR, so the + -- receiver reports 0 for as long as the rate runs; pinned in sensorToggle. + flrc = { + TPWR = 250, + RFMD = 13, + ["1RSS"] = -70, + ["2RSS"] = -74, + RQly = 100, + RSNR = 0, + ANT = 0, + TQly = 100, + TRSS = -80, + RxBt = 16.4, + Curr = 18.0, + FM = "ACRO", + Sats = 10, + GSpd = 45.0, + Alt = 30, + GPS = { lat = 54.6872, lon = 25.2797 }, + }, -- A packet rate ExpressLRS publishes no sensitivity figure for (v3 index 18, -- "9K1000", carried in the tables as 0). There is no floor to measure -- against, so everything derived from one has to fall back rather than draw @@ -1755,6 +1780,7 @@ local scenarioTelemetry = { ["1RSS"] = -79, ["2RSS"] = -84, RQly = 98, + RSNR = 8, ANT = 0, TQly = 100, TRSS = -88, @@ -1774,6 +1800,7 @@ local scenarioTelemetry = { ["1RSS"] = -55, ["2RSS"] = -58, RQly = 95, + RSNR = 12, ANT = 1, TQly = 100, TRSS = -61, @@ -1788,11 +1815,17 @@ local scenarioTelemetry = { ["1RSS"] = -55, ["2RSS"] = -58, RQly = 95, + RSNR = 12, ANT = 1, TQly = 100, TRSS = -61, RxBt = 15.8, Curr = 0.5, + FM = "ACRO", + Sats = 12, + GSpd = 25.3, + Alt = 142, + GPS = { lat = 54.6872, lon = 25.2797 }, }, -- Same signal as model_mismatch, and deliberately no sensorToggle entry: the -- mismatch bit is the only thing that may move, so RQly stays at 95 and the @@ -1803,6 +1836,7 @@ local scenarioTelemetry = { ["1RSS"] = -55, ["2RSS"] = -58, RQly = 95, + RSNR = 12, ANT = 1, TQly = 100, TRSS = -61, @@ -1817,6 +1851,7 @@ local scenarioTelemetry = { ["1RSS"] = -85, ["2RSS"] = -88, RQly = 60, + RSNR = 2, ANT = 0, TQly = 62, TRSS = -97, @@ -1828,13 +1863,35 @@ local scenarioTelemetry = { Alt = 210, GPS = { lat = 54.6600, lon = 25.2400 }, }, + no_telemetry = { + -- The sensor list a previous flight left on the model. The RX never + -- answers, so every value is served as 0 the way EdgeTX does; only the + -- key set matters. + TPWR = 50, + RFMD = 7, + ["1RSS"] = -87, + ["2RSS"] = -93, + RQly = 99, + RSNR = 8, + ANT = 1, + TQly = 100, + TRSS = -95, + RxBt = 15.2, + Curr = 12.5, + FM = "ACRO", + Sats = 12, + GSpd = 25.3, + Alt = 142, + GPS = { lat = 54.6872, lon = 25.2797 }, + }, reconnect = { - -- Same as normal; only served when isRxAvailable() is true + -- Same as normal; zeroed until isRxAvailable() turns true TPWR = 50, RFMD = 7, ["1RSS"] = -87, ["2RSS"] = -93, RQly = 99, + RSNR = 8, ANT = 1, TQly = 100, TRSS = -95, @@ -1848,6 +1905,7 @@ local scenarioTelemetry = { ["1RSS"] = -87, ["2RSS"] = -93, RQly = 99, + RSNR = 8, ANT = 1, TQly = 100, TRSS = -95, @@ -1866,6 +1924,7 @@ local scenarioTelemetry = { ["1RSS"] = -87, ["2RSS"] = -93, RQly = 99, + RSNR = 8, ANT = 1, TQly = 100, TRSS = -95, @@ -1887,6 +1946,7 @@ local sensorJitter = { TRSS = 3, RQly = 2, -- +/- 2% TQly = 2, + RSNR = 2, -- +/- 2 dB RxBt = 0.05, -- +/- 0.05V Curr = 2.0, -- +/- 2A GSpd = 3.0, @@ -1914,6 +1974,10 @@ local sensorToggle = { -- Must stay exactly 0: that is what marks the second RF path as absent. ["2RSS"] = { 0 }, }, + flrc = { + -- FLRC reports no SNR: exactly 0, never jittered. + RSNR = { 0 }, + }, mismatch_cycle = { -- ~10 s connected, ~5 s down, repeating. Exactly 95 or 0 so the -- RQly-derived connection state flips cleanly on each phase change. @@ -1935,46 +1999,44 @@ local function updateTelemetryCache() end lastTelemetryUpdate = now - if not isRxAvailable() then - -- TX module still reports RFMD/TPWR via link stats even without RX. - -- Only provide these when a module is present (not no_module). - telemetryCache = {} - if moduleFound then - for k, v in pairs(txModuleTelemetry) do - telemetryCache[k] = v - end - end - return - end local t = scenarioTelemetry[config.scenario] + telemetryCache = {} if not t then - telemetryCache = {} return end - telemetryCache = {} - toggleStep = toggleStep + 1 - local toggles = sensorToggle[config.scenario] - for sensorId, base in pairs(t) do - local seq = toggles and toggles[sensorId] - local jit = sensorJitter[sensorId] - if seq then - telemetryCache[sensorId] = seq[(toggleStep % #seq) + 1] - elseif jit then - local val = base + (math.random() * 2 - 1) * jit - if jit == math.floor(jit) then - val = math.floor(val + 0.5) - end - -- A link quality is a percentage of packets received, so it cannot - -- exceed 100. Jittering a base of 99 was handing the widgets 101, which - -- is not a reading any receiver can produce. - local ceiling = sensorCeiling[sensorId] - if ceiling and val > ceiling then - val = ceiling + if isRxAvailable() then + toggleStep = toggleStep + 1 + local toggles = sensorToggle[config.scenario] + for sensorId, base in pairs(t) do + local seq = toggles and toggles[sensorId] + local jit = sensorJitter[sensorId] + if seq then + telemetryCache[sensorId] = seq[(toggleStep % #seq) + 1] + elseif jit then + local val = base + (math.random() * 2 - 1) * jit + if jit == math.floor(jit) then + val = math.floor(val + 0.5) + end + -- A link quality is a percentage of packets received, so it cannot + -- exceed 100. Jittering a base of 99 was handing the widgets 101, which + -- is not a reading any receiver can produce. + local ceiling = sensorCeiling[sensorId] + if ceiling and val > ceiling then + val = ceiling + end + telemetryCache[sensorId] = val + else + telemetryCache[sensorId] = base end - telemetryCache[sensorId] = val - else - telemetryCache[sensorId] = base + end + end + + -- EdgeTX serves 0 for every sensor while RQly is 0 (luaGetValueAndPush), + -- the module's own TPWR/RFMD included: Lua never sees the link stats frame. + if (telemetryCache.RQly or 0) == 0 then + for sensorId in pairs(t) do + telemetryCache[sensorId] = 0 end end end @@ -1982,7 +2044,8 @@ end --- Return a mock telemetry sensor value for the current scenario. -- Called at ~10 Hz by the widget via crsf.getSensorValue(). Values are -- regenerated only once per second; intermediate calls return cached data. --- Returns nil when disconnected or the sensor is not defined. +-- Returns 0 for every sensor while the link is down, as EdgeTX does, and nil +-- for a sensor the scenario does not define. local function mockGetSensorValue(sensorId) updateTelemetryCache() return telemetryCache[sensorId] diff --git a/src/WIDGETS/ELRSTelemetry/rf_modes.lua b/src/WIDGETS/ELRSTelemetry/rf_modes.lua index 6e8f71f..7080ce2 100644 --- a/src/WIDGETS/ELRSTelemetry/rf_modes.lua +++ b/src/WIDGETS/ELRSTelemetry/rf_modes.lua @@ -195,6 +195,18 @@ function RfModes.floor(rfmd) return dbm end +-- The FLRC rates. The radio reports no SNR for FLRC packets, so RSNR sits at +-- 0 for as long as one of these runs. Keyed by name: both majors spell them +-- the same, and the name is what a reader can check against the RF Mode row. +local NO_SNR = { D250 = true, D500 = true, F500 = true, F1000 = true } + +--- Whether an RFMD sensor value names a rate that carries an SNR reading. +function RfModes.hasSnr(rfmd) + local names = RfModes._names + local name = names and names[rfmd + 1] + return not (name and NO_SNR[name]) +end + -- ============================================================================ -- Return module -- ============================================================================ diff --git a/src/WIDGETS/ELRSTelemetry/telemetry.lua b/src/WIDGETS/ELRSTelemetry/telemetry.lua index cb8a04e..95bf99d 100644 --- a/src/WIDGETS/ELRSTelemetry/telemetry.lua +++ b/src/WIDGETS/ELRSTelemetry/telemetry.lua @@ -188,6 +188,13 @@ function Telemetry.rfModeName() return RfModes.name(rfmd) end +--- Whether the current rate carries an SNR reading at all. FLRC rates do +--- not, so their RSNR is a placeholder 0 rather than a measurement. +function Telemetry.hasSnr() + local rfmd = Telemetry.link.rfmd + return rfmd == nil or RfModes.hasSnr(rfmd) +end + -- ============================================================================ -- Derived state -- ============================================================================ @@ -410,6 +417,7 @@ function Telemetry.update() link.rssi1 = crsf.getSensorValue("1RSS") link.rssi2 = crsf.getSensorValue("2RSS") link.rqly = crsf.getSensorValue("RQly") + link.rsnr = crsf.getSensorValue("RSNR") link.ant = crsf.getSensorValue("ANT") link.tqly = crsf.getSensorValue("TQly") link.trss = crsf.getSensorValue("TRSS") diff --git a/src/WIDGETS/ELRSTelemetry/ui/display.lua b/src/WIDGETS/ELRSTelemetry/ui/display.lua index 932deeb..bc5122e 100644 --- a/src/WIDGETS/ELRSTelemetry/ui/display.lua +++ b/src/WIDGETS/ELRSTelemetry/ui/display.lua @@ -118,10 +118,10 @@ function Display.trssText() return table.concat({ tostring(trss), " dBm" }) end ---- TX power on its own, e.g. "100 mW", or "--" while unknown. +--- TX power on its own, e.g. "100 mW", or "--" while disconnected. function Display.powerText() local tpwr = Telemetry.link.tpwr - if tpwr == nil then + if not Telemetry.isConnected() or tpwr == nil then return "--" end return table.concat({ tostring(tpwr), " mW" }) diff --git a/src/WIDGETS/ELRSTelemetry/ui/fullscreen.lua b/src/WIDGETS/ELRSTelemetry/ui/fullscreen.lua index 67935d3..58fb38f 100644 --- a/src/WIDGETS/ELRSTelemetry/ui/fullscreen.lua +++ b/src/WIDGETS/ELRSTelemetry/ui/fullscreen.lua @@ -30,8 +30,8 @@ local FullScreenUI = {} local LABEL_PCT = (LCD_W < LCD_H) and 42 or 50 --- Wrap a value formatter so a row reads "--" while the link is down. ---- Only the link and power rows take this. The flight controller and GPS rows ---- have their own fallbacks, and latitude/longitude deliberately keep showing +--- The link, power, satellite, speed and altitude rows take this. The flight +--- controller rows have their own fallbacks, and latitude/longitude keep showing --- the last known position after the link drops -- that is what you read when --- you are looking for a model that stopped answering. local function whenConnected(fn) @@ -147,34 +147,37 @@ function FullScreenUI.build() createDisplayRow(fields, "Link Quality", Display.lqValueText) + -- Both antennas on one row in fixed 1 / 2 order, as the module's own screen + -- and the compact tiers print them, so neither number jumps when the + -- receiver switches paths. A single-path receiver gets the bare reading. createDisplayRow( fields, - "RSSI 1", + "RSSI", whenConnected(function() local rssi1 = Telemetry.link.rssi1 if rssi1 == nil then return "--" end + if Telemetry.hasDiversity() then + return table.concat({ tostring(rssi1), " / ", tostring(Telemetry.link.rssi2), " dBm" }) + end return table.concat({ tostring(rssi1), " dBm" }) end) ) createDisplayRow( fields, - "RSSI 2", + "SNR", whenConnected(function() - local rssi2 = Telemetry.link.rssi2 - if rssi2 == nil then + local rsnr = Telemetry.link.rsnr + if rsnr == nil then return "--" end - return table.concat({ tostring(rssi2), " dBm" }) - end), - function() - if not Telemetry.hasDiversity() then - return COLOR_THEME_DISABLED + if not Telemetry.hasSnr() then + return "n/a" -- FLRC: the sensor is a permanent 0, not a reading end - return COLOR_THEME_SECONDARY1 - end + return table.concat({ tostring(rsnr), " dB" }) + end) ) createDisplayRow( @@ -186,7 +189,7 @@ function FullScreenUI.build() end -- EdgeTX's telemetry list prints the raw ANT enum (0/1) and so does the TX -- module's own screen. The "Ant " prefix keeps this row from reading as that - -- same number, and 1/2 matches the RSSI 1 / RSSI 2 rows above. + -- same number, and 1/2 matches the order of the RSSI pair above. if Telemetry.link.ant == 0 then return "Ant 1" end @@ -264,29 +267,41 @@ function FullScreenUI.build() -- GPS section createSectionHeader(fields, "GPS") - createDisplayRow(fields, "Satellites", function() - local sats = Telemetry.link.sats - if sats == nil then - return "--" - end - return tostring(sats) - end) + createDisplayRow( + fields, + "Satellites", + whenConnected(function() + local sats = Telemetry.link.sats + if sats == nil then + return "--" + end + return tostring(sats) + end) + ) - createDisplayRow(fields, "Speed", function() - local gspd = Telemetry.link.gspd - if gspd == nil then - return "--" - end - return string.format("%.1f", gspd) - end) + createDisplayRow( + fields, + "Speed", + whenConnected(function() + local gspd = Telemetry.link.gspd + if gspd == nil then + return "--" + end + return string.format("%.1f", gspd) + end) + ) - createDisplayRow(fields, "Altitude", function() - local alt = Telemetry.link.alt - if alt == nil then - return "--" - end - return tostring(alt) - end) + createDisplayRow( + fields, + "Altitude", + whenConnected(function() + local alt = Telemetry.link.alt + if alt == nil then + return "--" + end + return tostring(alt) + end) + ) createDisplayRow(fields, "Latitude", function() if Telemetry.gps == nil then