4e5796fd51
Apps describe nesting instead of coordinates: /lib/ui.lua borrows CSS block flow, the box model and auto sizing, and owns hit testing, press capture and the pressed repaint. The runtime gains require backed by the SD card, on_touch_down/on_touch_up, text metrics and rounded gradient fills, so the launcher becomes an ordinary Lua app and the firmware keeps only a fallback screen for an unreadable card.
87 lines
2.9 KiB
Lua
87 lines
2.9 KiB
Lua
-- Run: lua test/settings_calibration.lua
|
|
-- Stubs the firmware bindings so the settings app loads on a desktop Lua.
|
|
package.path = "sdcard/lib/?.lua;" .. package.path
|
|
|
|
local saved
|
|
local rotation = 0
|
|
local now = 0
|
|
|
|
gui = {
|
|
color = function() return 0 end,
|
|
width = function() return rotation % 180 == 0 and 320 or 480 end,
|
|
height = function() return rotation % 180 == 0 and 480 or 320 end,
|
|
clear = function() end,
|
|
fillRect = function() end,
|
|
drawText = function() end,
|
|
drawRect = function() end,
|
|
drawLine = function() end,
|
|
fillRoundRect = function() end,
|
|
drawRoundRect = function() end,
|
|
fontHeight = function() return 8 end,
|
|
textWidth = function(text) return #text * 6 end,
|
|
setRotation = function() end,
|
|
}
|
|
sys = {
|
|
millis = function() return now end,
|
|
exit = function() end,
|
|
setCalibration = function(...) saved = {...} return true end,
|
|
getRotation = function() return rotation end,
|
|
setRotation = function(degrees) rotation = degrees return true end,
|
|
}
|
|
input = {getRawTouch = function() return nil end}
|
|
log = {info = function() end}
|
|
|
|
dofile("sdcard/apps/settings/main.lua")
|
|
|
|
-- Menu rows: pad 12, gap 8, title 8 tall, buttons 24 tall.
|
|
local ROTATION_ROW = {x = 100, y = 70}
|
|
local CALIBRATE_ROW = {x = 100, y = 38}
|
|
|
|
local function tap(point)
|
|
on_touch_down(point.x, point.y)
|
|
on_touch_up(point.x, point.y)
|
|
end
|
|
|
|
-- A perfectly linear panel spanning raw 200..3800 over 320x480 must round-trip
|
|
-- to those same extremes from the two inset samples.
|
|
local inset, w, h = 30, 320, 480
|
|
local function raw(pixel, size) return 200 + (3800 - 200) * pixel / size end
|
|
local s1 = {x = raw(inset, w), y = raw(inset, h)}
|
|
local s2 = {x = raw(w - inset, w), y = raw(h - inset, h)}
|
|
|
|
local x0, y0, x1, y1 = computeCalibration(s1, s2, w, h, inset)
|
|
assert(math.abs(x0 - 200) <= 1, "x0 " .. x0)
|
|
assert(math.abs(y0 - 200) <= 1, "y0 " .. y0)
|
|
assert(math.abs(x1 - 3800) <= 1, "x1 " .. x1)
|
|
assert(math.abs(y1 - 3800) <= 1, "y1 " .. y1)
|
|
|
|
-- A flipped panel (raw decreasing with pixel) must yield a descending range.
|
|
local s3 = {x = 3800 - raw(inset, w) + 200, y = s1.y}
|
|
local s4 = {x = 3800 - raw(w - inset, w) + 200, y = s2.y}
|
|
local fx0, _, fx1 = computeCalibration(s3, s4, w, h, inset)
|
|
assert(fx0 > fx1, "flipped axis should descend")
|
|
|
|
-- Rotation cycles through the four quarter turns and wraps back to 0.
|
|
setup()
|
|
for _, expected in ipairs({90, 180, 270, 0}) do
|
|
tap(ROTATION_ROW)
|
|
assert(sys.getRotation() == expected, "rotation " .. sys.getRotation())
|
|
end
|
|
|
|
-- Calibration collects one sample per target and saves on the second release.
|
|
setup()
|
|
tap(CALIBRATE_ROW)
|
|
on_tick() -- release after the menu tap arms sampling
|
|
input.getRawTouch = function() return s1.x, s1.y end
|
|
on_tick()
|
|
input.getRawTouch = function() return nil end
|
|
on_tick()
|
|
input.getRawTouch = function() return s2.x, s2.y end
|
|
on_tick()
|
|
input.getRawTouch = function() return nil end
|
|
on_tick()
|
|
assert(saved, "calibration was not saved")
|
|
assert(math.abs(saved[1] - 200) <= 1, "saved x0 " .. saved[1])
|
|
|
|
print("ok")
|