Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ RGB LED control tool for EdgeTX 2.11+ radios.
## Notes

- Requires EdgeTX 2.11 or newer.
- Animates decorative gimbal / "bling" LEDs only (20 LEDs on TX16S Mk3, GX15 and TX15). Custom function switch RGB colours stay under Radio/Model settings.
- The keeper polls `/SCRIPTS/TOOLS/RGB.dat` and runs the selected mode, so no other mode scripts are needed.
38 changes: 36 additions & 2 deletions SCRIPTS/RGBLED/rgbk.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,42 @@
-- on-screen preview matches exactly what the keeper runs on the radio.

local CFG = "/SCRIPTS/TOOLS/RGB.dat"
local N = LED_STRIP_LENGTH or 0
local HALF = math.floor(N / 2)

-- Decorative ("bling") LEDs only. Firmware maps Lua index 0 to the first
-- gimbal/bling LED. Function-switch LEDs stay under model on/off colours /
-- setCFSLedColor() and must not be painted here.
local function decorativeLength()
if type(BLING_LED_STRIP_LENGTH) == "number" and BLING_LED_STRIP_LENGTH > 0 then
return BLING_LED_STRIP_LENGTH
end
local n = LED_STRIP_LENGTH or 0
if type(CFS_LED_STRIP_LENGTH) == "number" and CFS_LED_STRIP_LENGTH > 0 and n >= CFS_LED_STRIP_LENGTH then
return n - CFS_LED_STRIP_LENGTH
end
-- Pre-constant firmware: TX16S Mk3 / GX15 / TX15 report 20 bling + 6 CFS.
if n == 26 then return 20 end
return n
end

local N = decorativeLength()
local HALF = math.max(1, math.floor(N / 2))

-- Bound every write to the decorative range so leftover CFS indices are never
-- touched, even if a pattern hardcodes a 10+10 gimbal layout.
local _setRGB = setRGBLedColor
local _applyRGB = applyRGBLedColors

local function setRGBLedColor(id, r, g, b)
if type(_setRGB) ~= "function" then return false end
if type(id) ~= "number" or id < 0 or id >= N then return false end
return _setRGB(id, r, g, b)
end

local function applyRGBLedColors()
if type(_applyRGB) == "function" then
_applyRGB()
end
end

local curSel = nil
local runFn = nil
Expand Down
34 changes: 25 additions & 9 deletions SCRIPTS/TOOLS/RGB.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
local LED_DIR = "/SCRIPTS/RGBLED"
local CFG_FILE = "/SCRIPTS/TOOLS/RGB.dat"
-- Native "RGB Led" special function: loads <name>.lua from /SCRIPTS/RGBLED/
local FUNC_RGB_LED = 25
-- Prefer the firmware constant so a future enum shift does not break setup.
local RGB_LED_FUNC = (type(FUNC_RGB_LED) == "number") and FUNC_RGB_LED or 25
-- Fixed Special Function slot for the keeper script (SF64 = index 63)
local SF_SLOT = 63
local KEEPER_NAME = "rgbk"
Expand All @@ -12,6 +13,7 @@ local CUSTOM_PREFIX = "custom:"

local exitRequested = false
local noLvgl = false
local noLeds = type(setRGBLedColor) ~= "function" or type(applyRGBLedColors) ~= "function"
local selected = nil
local subtitle = ""
local buttons = {}
Expand Down Expand Up @@ -156,7 +158,7 @@ end
local function keeperInstalled()
if type(model.getCustomFunction) ~= "function" then return false end
local cur = model.getCustomFunction(SF_SLOT)
return cur ~= nil and cur.func == FUNC_RGB_LED and cur.name == KEEPER_NAME and cur.active == 1
return cur ~= nil and cur.func == RGB_LED_FUNC and cur.name == KEEPER_NAME and cur.active == 1
end

-- Install the keeper Special Function once. After it exists (and is enabled)
Expand All @@ -169,7 +171,7 @@ local function ensureKeeper()
return
end
local cur = model.getCustomFunction(SF_SLOT)
local ours = cur ~= nil and cur.func == FUNC_RGB_LED and cur.name == KEEPER_NAME
local ours = cur ~= nil and cur.func == RGB_LED_FUNC and cur.name == KEEPER_NAME
if cur ~= nil and type(cur.func) == "number" and cur.func ~= 0 and not ours then
lvgl.message({ title = "SF64 in use",
message = "Special Function SF64 is already assigned to a different function. Free it to let the RGB LED tool use it." })
Expand All @@ -182,7 +184,7 @@ local function ensureKeeper()
end
model.setCustomFunction(SF_SLOT, {
switch = onSwitch,
func = FUNC_RGB_LED,
func = RGB_LED_FUNC,
name = KEEPER_NAME,
active = 1,
})
Expand Down Expand Up @@ -228,8 +230,10 @@ end
local function selectMode(name)
selected = name
saveSelection(name)
preview(name)
ensureKeeper()
if not noLeds then
preview(name)
ensureKeeper()
end
for key, _ in pairs(buttons) do
setChecked(key, key == name)
end
Expand All @@ -254,9 +258,15 @@ local function buildUi()
local MARGIN = 8
local GAP = 6
local LABEL_H = 28

local y = MARGIN

if noLeds then
pg:label({ x = MARGIN, y = y, w = W - 2 * MARGIN,
text = "This radio has no RGB LED strip (setRGBLedColor missing).",
color = COLOR_THEME_WARNING })
y = y + LABEL_H + GAP
end

local offBtn = pg:button({ x = MARGIN, y = y, w = W - 2 * MARGIN, h = EH,
text = "Off",
color = function() return COLOR_THEME_PRIMARY3 end,
Expand All @@ -272,8 +282,9 @@ local function buildUi()
text = "Setup Background Script on Model",
color = function() return rgbValue({ r = 30, g = 120, b = 255 }, true) end,
textColor = function() return rgbValue({ r = 30, g = 120, b = 255 }, false) end,
active = function() return not keeperInstalled() end,
active = function() return not noLeds and not keeperInstalled() end,
press = function()
if noLeds then return end
ensureKeeper()
if keeperInstalled() then
lvgl.message({ title = "Background Script Installed",
Expand Down Expand Up @@ -341,6 +352,11 @@ local function init()
if ok and info and type(info) == "table" then
subtitle = info.name or ""
end
if type(BLING_LED_STRIP_LENGTH) == "number" and BLING_LED_STRIP_LENGTH > 0 then
subtitle = (subtitle ~= "" and (subtitle .. " · ") or "") .. tostring(BLING_LED_STRIP_LENGTH) .. " LEDs"
elseif type(LED_STRIP_LENGTH) == "number" and LED_STRIP_LENGTH > 0 then
subtitle = (subtitle ~= "" and (subtitle .. " · ") or "") .. tostring(LED_STRIP_LENGTH) .. " LEDs"
end
if lvgl == nil then
noLvgl = true
return
Expand All @@ -365,7 +381,7 @@ local function run(event, touchState)
end
return 0
end
if selected then
if not noLeds and selected then
preview(selected)
end
if exitRequested then
Expand Down