local ui = require("ui") 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 ACCENT = gui.color(0, 120, 255) local screen, message local mode = "menu" local samples, pending, armed = {}, nil, false local buildMenu, startCalibration, cycleRotation -- 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 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, WHITE) gui.drawLine(x - 12, y, x + 12, y, RED) gui.drawLine(x, y - 12, x, y + 12, RED) end local function finishCalibration() 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) buildMenu() end function startCalibration() message = nil mode = "calibrate" samples, pending, armed = {}, nil, false gui.setRotation(0) drawTarget(1) end function cycleRotation() local ok = sys.setRotation((sys.getRotation() + 90) % 360) message = ok and "rotation saved" or "save failed" buildMenu() -- the frame changed size, so lay out again end function buildMenu() local items = { pad = 12, gap = 8, ui.text("settings"), ui.button{label = "calibrate touch", on_press = startCalibration}, ui.button{label = "rotation: " .. sys.getRotation() .. " deg", on_press = cycleRotation}, ui.button{label = "exit", on_press = sys.exit}, } if message then items[#items + 1] = ui.text(message) end items.color, items.bg = BLACK, WHITE items.press_bg, items.press_color = ACCENT, WHITE screen = ui.screen(ui.box(items)) end function setup() buildMenu() end function draw() if mode == "menu" then screen:draw() end end function on_touch_down(x, y) if mode == "menu" then screen:down(x, y) end end function on_touch_up(x, y) if mode == "menu" then screen:up(x, y) 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 finishCalibration() end end end