Files
slate32/sdcard/apps/settings/main.lua
T
evan ad396d3f01 feat: Lua app firmware for the E32R40T display module
Boots to a launcher that lists /apps/<name>/main.lua on the SD card and runs
the selected app in a vendored Lua 5.4 with gui, input, fs, sys and log
bindings. Settings persist as a Lua table in /settings.lua, covering touch
calibration and screen rotation, with a settings app to edit both. Rotation is
applied after mapping raw touch into the panel's rotation-0 frame, so turning
the UI never invalidates a calibration.
2026-07-31 21:28:11 -04:00

106 lines
2.8 KiB
Lua

TICK_MS = 50
local INSET = 30
local BLACK, WHITE, RED = gui.color(0, 0, 0), gui.color(255, 255, 255), gui.color(255, 0, 0)
local ROWS = {"calibrate touch", "rotation", "exit"}
local mode = "menu"
local samples = {}
local pending = nil
local armed = false
local message = nil
local function rowY(index)
return 40 * index
end
local function drawMenu()
gui.clear(WHITE)
gui.drawText("settings", 10, 10, BLACK)
for i, label in ipairs(ROWS) do
if label == "rotation" then
label = "rotation: " .. sys.getRotation() .. " deg"
end
gui.drawRect(10, rowY(i), gui.width() - 20, 28, BLACK)
gui.drawText(label, 18, rowY(i) + 6, BLACK)
end
if message then gui.drawText(message, 10, rowY(#ROWS + 1) + 10, BLACK) end
end
local function target(n)
-- Calibration always runs in the rotation-0 frame, so use panel geometry.
if n == 1 then return INSET, INSET end
return 320 - INSET, 480 - INSET
end
local function drawTarget(n)
local x, y = target(n)
gui.clear(WHITE)
gui.drawText("tap the cross", 10, 10, BLACK)
gui.drawLine(x - 12, y, x + 12, y, RED)
gui.drawLine(x, y - 12, x, y + 12, RED)
end
-- Two inset targets give a raw-per-pixel slope; extrapolate it to the screen edges.
-- Exposed as a global so test/settings_calibration.lua can exercise it.
function computeCalibration(s1, s2, w, h, inset)
local sx = (s2.x - s1.x) / (w - 2 * inset)
local sy = (s2.y - s1.y) / (h - 2 * inset)
return math.floor(s1.x - sx * inset), math.floor(s1.y - sy * inset),
math.floor(s2.x + sx * inset), math.floor(s2.y + sy * inset)
end
local function finish()
local ok = sys.setCalibration(computeCalibration(samples[1], samples[2], 320, 480, INSET))
message = ok and "calibration saved" or "save failed"
mode = "menu"
gui.setRotation(sys.getRotation() / 90)
drawMenu()
end
function setup()
drawMenu()
end
function on_touch(x, y)
if mode ~= "menu" then return end
local index = math.floor(y / 40)
if y < rowY(1) or index > #ROWS then return end
if ROWS[index] == "calibrate touch" then
message = nil
mode = "calibrate"
samples = {}
pending = nil
armed = false -- the menu tap is still down; wait for release
gui.setRotation(0)
drawTarget(1)
elseif ROWS[index] == "rotation" then
local ok = sys.setRotation((sys.getRotation() + 90) % 360)
message = ok and "rotation saved" or "save failed"
drawMenu()
elseif ROWS[index] == "exit" then
sys.exit()
end
end
function on_tick()
if mode ~= "calibrate" then return end
local rx, ry = input.getRawTouch()
if not armed then
if not rx then armed = true end
return
end
if rx then
pending = {x = rx, y = ry}
elseif pending then
samples[#samples + 1] = pending
pending = nil
if #samples == 1 then
drawTarget(2)
else
finish()
end
end
end