Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8e4072a
Added RF2 widget
egonl Jan 31, 2026
d7bf58e
Introduced widget.state
egonl Feb 15, 2026
e037e97
Added Model Name widget
egonl Feb 17, 2026
68cd271
Introduced app.lua
egonl Feb 17, 2026
4c5701e
Added backgroundTask
egonl Feb 18, 2026
66a7152
Added pacman tone
egonl Feb 18, 2026
3b6ccf5
Background now updates widget state
egonl Feb 19, 2026
059115e
Improved connected tone
egonl Feb 19, 2026
08d8ec7
Added options
egonl Feb 19, 2026
6bf9cd7
Added model name to RfTool
egonl Feb 19, 2026
7adc671
Renamed tools
egonl Feb 20, 2026
1086f22
Renamed RfTool
egonl Feb 20, 2026
51710a9
Added pub/sub support for state events
egonl Feb 20, 2026
014fa12
Improved documentation
egonl Feb 20, 2026
3034934
RfStatus now uses MSP to show flight stats
egonl Feb 21, 2026
829a88c
Fixed some bugs
egonl Feb 27, 2026
3f5d2db
Better screen transition when exiting RfTool
egonl Feb 28, 2026
675b665
Better support for RTN key
egonl Mar 2, 2026
32af22e
rf2bg: reduced resource usage when not active
egonl Mar 2, 2026
286f6ad
Removed unused options
egonl Mar 2, 2026
e0de1be
Improved showMemoryUsage
egonl Mar 2, 2026
b8fce1c
Restructured app.lua
egonl Mar 2, 2026
6035ca0
Added source display to main menu
egonl Mar 2, 2026
9f22031
Fixed rf2.print when calling with nil
egonl Mar 2, 2026
166b77d
Added scripts
egonl Mar 2, 2026
147ec30
Added 'unknown protocol' state
egonl Mar 2, 2026
7167abf
Bumped version
egonl Mar 2, 2026
2519b3d
Cleaned up RfStats
egonl Mar 4, 2026
e220819
Improved comments
egonl Mar 4, 2026
bb50faf
Cleaned up RfTool
egonl Mar 4, 2026
454fdf3
Updated scripts.lua
egonl Mar 4, 2026
207a2fb
Fixed bug
egonl Mar 4, 2026
1971088
Bumped version
egonl Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/SCRIPTS/FUNCTIONS/rf2bg.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
assert(loadScript("/SCRIPTS/RF2/rf2.lua"))()
rf2.mspQueue = rf2.executeScript("MSP/mspQueue")
rf2.mspQueue.maxRetries = 3
rf2.mspHelper = rf2.executeScript("MSP/mspHelper")
local background = rf2.executeScript("background")
local initialized = false
local backgroundTask = nil

return { run = background }
local function startup()
if not initialized then
assert(loadScript("/SCRIPTS/RF2/rf2.lua"))()
rf2.mspQueue = rf2.executeScript("MSP/mspQueue")
rf2.mspQueue.maxRetries = 3
rf2.mspHelper = rf2.executeScript("MSP/mspHelper")
backgroundTask = rf2.executeScript("background")
initialized = true
else
backgroundTask()
end
end

return { run = startup }
6 changes: 3 additions & 3 deletions src/SCRIPTS/RF2/COMPILE/compile.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
local i = 1
local scripts = assert(loadScript("COMPILE/scripts.lua"))
local scripts = assert(loadScript("/SCRIPTS/RF2/COMPILE/scripts.lua"))
collectgarbage()

local function deleteOrTruncateFile(filepath)
Expand Down Expand Up @@ -33,10 +33,10 @@ local function compile()
assert(loadScript(script, 'cd')) -- The 'd' flags gets removed in by minimize.lua
return 0
end
local file = io.open("COMPILE/scripts_compiled.lua", 'w')
local file = io.open("/SCRIPTS/RF2/COMPILE/scripts_compiled.lua", 'w')
io.write(file, "return true")
io.close(file)
assert(loadScript("COMPILE/scripts_compiled.lua", 'c'))
assert(loadScript("/SCRIPTS/RF2/COMPILE/scripts_compiled.lua", 'c'))
return 1
end

Expand Down
6 changes: 6 additions & 0 deletions src/SCRIPTS/RF2/COMPILE/scripts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ local scripts = {
"/SCRIPTS/RF2/LCD/shared.lua",
"/SCRIPTS/RF2/LCD/waitMessage.lua",
"/SCRIPTS/RF2/F/canUseLvgl.lua",
"/SCRIPTS/RF2/F/formatSeconds.lua",
"/SCRIPTS/RF2/F/getBit.lua",
"/SCRIPTS/RF2/F/getProtocol.lua",
"/SCRIPTS/RF2/F/hasSensor.lua",
"/SCRIPTS/RF2/F/incMax.lua",
"/SCRIPTS/RF2/F/pilotConfigReset.lua",
Expand Down Expand Up @@ -104,5 +106,9 @@ local scripts = {
"/SCRIPTS/RF2/ui_lvgl_framework.lua",
"/SCRIPTS/RF2/ui_lvgl_runner.lua",
"/SCRIPTS/TOOLS/rf2.lua",
"/WIDGETS/RfStats/app.lua",
"/WIDGETS/RfStats/main.lua",
"/WIDGETS/RfTool/app.lua",
"/WIDGETS/RfTool/main.lua",
}
return scripts[...]
19 changes: 19 additions & 0 deletions src/SCRIPTS/RF2/F/formatSeconds.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- Usage: local formattedSeconds = rf2.executeScript("F/formatSeconds")(seconds)
local function formatSeconds(seconds)
local days = math.floor(seconds / 86400)
seconds = seconds % 86400
local hours = math.floor(seconds / 3600)
seconds = seconds % 3600
local minutes = math.floor(seconds / 60)
seconds = seconds % 60
local s = string.format("%02d:%02d:%02d", hours, minutes, seconds)
if days > 0 then
-- e.g. 12d04:30:58
return string.format("%dd%s", days, s)
else
-- only 04:30:58
return s
end
end

return formatSeconds
12 changes: 12 additions & 0 deletions src/SCRIPTS/RF2/F/getProtocol.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Usage: local protocol = rf2.executeScript("F/getProtocol")()
local function getProtocol()
if sportTelemetryPush() ~= nil then
return "sp"
elseif crossfireTelemetryPush() ~= nil then
return "crsf"
elseif ghostTelemetryPush() ~= nil then
return "ghst"
end
end

return getProtocol
7 changes: 6 additions & 1 deletion src/SCRIPTS/RF2/LVGL/mainMenu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ local function show(menu)
{
type = "page",
title = menu.title,
subtitle = menu.subtitle,
subtitle = function()
if rf2.widget and rf2.widget.options then
return menu.subtitle .. " - " .. rf2.widget.options:getText()
end
return menu.subtitle
end,
icon = rf2.baseDir .. "rf2.png",
back = function()
if menu.back then
Expand Down
7 changes: 6 additions & 1 deletion src/SCRIPTS/RF2/LVGL/page.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,12 @@ local function show(page)
{
type = "page",
title = "Rotorflight " .. rf2.luaVersion,
subtitle = page.title,
subtitle = function()
if rf2.widget and rf2.widget.options then
return page.title .. " - " .. rf2.widget.options:getText()
end
return page.title
end,
icon = rf2.baseDir .. "rf2.png",
back = function()
if page.back then
Expand Down
5 changes: 3 additions & 2 deletions src/SCRIPTS/RF2/LVGL/waitMessage.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
local t = {}

t.setWaitMessage = function(title, message)
t.setWaitMessage = function(title, message, back)
--rf2.print("Setting wait message: "..message)
if message ~= t.message or (message == t.message and not t.shown) then
t.message = message
t.title = title
t.back = back
t.shown = false
end
end
Expand All @@ -29,7 +30,7 @@ t.updateWaitMessage = function()
title = "Rotorflight " .. rf2.luaVersion,
subtitle = t.title or "",
icon = rf2.baseDir .. "rf2.png",
--back = function() ui.show() end,
back = t.back,
children = {
{
type = "label", x = 70, y = 16, color = BLACK, font = DBLSIZE, text = t.message or ""
Expand Down
2 changes: 1 addition & 1 deletion src/SCRIPTS/RF2/MSP/common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ end

local function mspPollReply()
local startTime = rf2.clock()
while (rf2.clock() - startTime < 0.05) do
while (rf2.clock() - startTime < 0.01) do
local mspData = mspPoll()
if mspData ~= nil and mspReceivedReply(mspData) then
mspLastReq = 0
Expand Down
19 changes: 1 addition & 18 deletions src/SCRIPTS/RF2/PAGES/model.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,7 @@ local function buildForm(page)

if flighStats.statsEnabled.value and flighStats.statsEnabled.value == 1 then
fields[#fields + 1] = { t = "Total flights", x = x, y = incY(lineSpacing), sp = x + sp, data = flighStats.stats_total_flights, readOnly = true }

local function formatSeconds(seconds)
local days = math.floor(seconds / 86400)
seconds = seconds % 86400
local hours = math.floor(seconds / 3600)
seconds = seconds % 3600
local minutes = math.floor(seconds / 60)
seconds = seconds % 60
local s = string.format("%02d:%02d:%02d", hours, minutes, seconds)
if days > 0 then
-- e.g. 12d04:30:58
return string.format("%dd%s", days, s)
else
-- only 04:30:58
return s
end
end
local totalTime = formatSeconds(flighStats.stats_total_time_s.value)
local totalTime = rf2.executeScript("F/formatSeconds")(flighStats.stats_total_time_s.value)
fields[#fields + 1] = { t = "Total time", x = x, y = incY(lineSpacing), sp = x + sp, data = { value = totalTime }, readOnly = true }

fields[#fields + 1] = { t = "Total distance", x = x, y = incY(lineSpacing), sp = x + sp, data = flighStats.stats_total_dist_m, readOnly = true }
Expand Down
32 changes: 25 additions & 7 deletions src/SCRIPTS/RF2/background.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ end

local hasSensor = rf2.executeScript("F/hasSensor")

local function run()
if rf2.runningInSimulator then
modelIsConnected = true
elseif isInitialized and customTelemetryTask and not hasSensor("*Cnt") then
local function setState(widget, state)
if widget == nil then return end
widget:setState(state)
end

--local lastHelloTime = nil
local function run(widget)
-- if lastHelloTime == nil or rf2.clock() - lastHelloTime > 1 then
-- rf2.print("Background says hello!")
-- lastHelloTime = rf2.clock()
-- end

if isInitialized and customTelemetryTask and not hasSensor("*Cnt") then
isInitialized = false -- user probably deleted all sensors on TX
elseif getRSSI() > 0 then
lastTimeRssi = rf2.clock()
Expand All @@ -27,10 +36,11 @@ local function run()
if lastTimeRssi and rf2.clock() - lastTimeRssi < 5 then
-- Do not re-initialise if the RSSI is 0 for less than 5 seconds.
-- This is also a work-around for https://github.com/ExpressLRS/ExpressLRS/issues/3207 (AUX channel bug in ELRS TX < 3.5.5)
-- setState(widget, "telemetry lost") -- also needs telemetry recoverede/connected
return
end
rf2.executeScript("F/pilotConfigReset")()
if modelIsConnected then
rf2.executeScript("F/pilotConfigReset")()
if initTask then
initTask.reset()
initTask = nil
Expand All @@ -51,6 +61,11 @@ local function run()
local initTaskResult = initTask.run(modelIsConnected)
if not initTaskResult.isInitialized then
--rf2.print("Not initialized yet")
if getRSSI() == 0 then
setState(widget, "disconnected")
else
setState(widget, "initializing")
end
return
end
if initTaskResult.crsfCustomTelemetryEnabled then
Expand All @@ -62,6 +77,7 @@ local function run()
end
initTask = nil
isInitialized = true
setState(widget, "connected")
end

if getRSSI() == 0 and not rf2.runningInSimulator then
Expand All @@ -78,8 +94,10 @@ local function run()
end
end

local function runProtected()
local status, err = pcall(run)
-- widget is optional and will be provided by the RfTool widget.
-- If the background script runs as a special function, widget will be nil.
local function runProtected(widget)
local status, err = pcall(run, widget)
--[NIR
if not status then rf2.print(err) end
--]]
Expand Down
5 changes: 4 additions & 1 deletion src/SCRIPTS/RF2/background_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ local function initializeQueue()
if autoSetName then
setModelName(rf2.modelName)
end
playTone(1600, 300, 0, PLAY_BACKGROUND)
playTone(523, 200, 0, PLAY_NOW) -- C5
playTone(659, 200, 0) -- E5
playTone(784, 200, 0) -- G5
playTone(1047, 200, 0) -- C6
--rf2.print("RTC set")
rf2.mspQueue.maxRetries = 3
initializationDone = true
Expand Down
14 changes: 2 additions & 12 deletions src/SCRIPTS/RF2/protocols.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
local function getProtocol()
if sportTelemetryPush() ~= nil then
return "sp"
elseif crossfireTelemetryPush() ~= nil then
return "crsf"
elseif ghostTelemetryPush() ~= nil then
return "ghst"
end
end

local protocol = assert(getProtocol(), "Unsupported protocol!")

local protocol = rf2.executeScript("F/getProtocol")()
assert(protocol, "Unsupported protocol!")
return protocol
8 changes: 5 additions & 3 deletions src/SCRIPTS/RF2/rf2.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
rf2 = {
luaVersion = "2.3.0-20260211",
luaVersion = "2.3.0-20260305",
baseDir = "/SCRIPTS/RF2/",
runningInSimulator = string.sub(select(2, getVersion()), -4) == "simu",

Expand All @@ -17,7 +17,9 @@ rf2 = {
script = script .. ".lua"
end
collectgarbage()
return loadScript(script)
local result = loadScript(script)
--rf2.showMemoryUsage(script .. " loaded")
return result
end,

executeScript = function(scriptName, ...)
Expand Down Expand Up @@ -59,7 +61,7 @@ rf2 = {

--[NIR
print = function(format, ...)
local str = string.format("RF2: " .. format, ...)
local str = string.format("RF2: " .. tostring(format), ...)
if rf2.runningInSimulator then
print(str)
else
Expand Down
6 changes: 2 additions & 4 deletions src/SCRIPTS/RF2/tool.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ if scriptsCompiled then
assert(loadScript("rf2.lua"))()
--rf2.showMemoryUsage("rf2 loaded")
rf2.radio = rf2.executeScript("radios")
--rf2.showMemoryUsage("radios loaded")
rf2.mspQueue = rf2.executeScript("MSP/mspQueue")
--rf2.showMemoryUsage("MSP queue loaded")
rf2.mspQueue.maxRetries = 3
rf2.mspHelper = rf2.executeScript("MSP/mspHelper")
--rf2.showMemoryUsage("MSP helper loaded")

local canUseLvgl = rf2.executeScript("F/canUseLvgl")()
if canUseLvgl then
Expand All @@ -27,7 +24,8 @@ if scriptsCompiled then
else
run = rf2.executeScript("ui_lcd")
end
--rf2.showMemoryUsage("ui loaded")

rf2.isTool = true
else
run = assert(loadScript("COMPILE/compile.lua"))()
collectgarbage()
Expand Down
2 changes: 1 addition & 1 deletion src/SCRIPTS/RF2/ui_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local apiVersion
local lastRunTS

local function init()
if getRSSI() == 0 and not rf2.runningInSimulator then
if getRSSI() == 0 then
returnTable.t = "Waiting for connection"
return false
end
Expand Down
13 changes: 11 additions & 2 deletions src/SCRIPTS/RF2/ui_lvgl_framework.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ local PageFiles = nil
local Page = nil
local CurrentPageIndex = -1

ui.exit = function()
ui.state = ui.status.exit
end

ui.refresh = function()
ui.previousState = nil
end

ui.setWaitMessage = function(message)
local title = Page and Page.title or ""
waitMessage.setWaitMessage(title, message)
waitMessage.setWaitMessage(title, message, ui.exit)
end

ui.clearWaitMessage = function()
Expand All @@ -49,7 +53,7 @@ ui.showMainMenu = function()
title = "Rotorflight " .. rf2.luaVersion,
subtitle = "Main Menu",
items = {},
back = function() ui.state = ui.status.exit end
back = ui.exit
}

local onMenuItemClick = function(index)
Expand Down Expand Up @@ -191,4 +195,9 @@ ui.onPageReady = function(page)
ui.showPage()
end

ui.restart = function()
ui.state = ui.status.init
ui.clearWaitMessage()
end

return ui
Loading