What changed, and why it matters
This commit adds a new touchscreen diagnostic tool under Tools > Device Tests and fixes a simulator crash on some computers. It also moves the definition of the PRESSED constant from the input module to a new buttons module across several files. There is no obvious security vulnerability in the changes; it reads mainly as a feature addition and minor code cleanup.
No security action required. Treat as a normal feature/maintenance commit. If reviewing further, verify that the PRESSED move to buttons.py does not break any downstream consumers outside the changed files.
Security signals we found
No memory-unsafe operations or cryptographic changes observed
New test code reads touch coordinates and draws on screen only; no data crosses trust boundaries
Import refactor is a code-organization change with no behavioral change evident from diff
Simulator throttling is a host-side workaround, not a device security control
Evidence from the diff
The patch introduces test_touch() in src/krux/pages/device_tests.py, which paints a 10x10 rectangle at the touch release point while the user holds a touchscreen, exiting on physical button press. It also refactors imports so that PRESSED is imported from ..buttons rather than ..input in multiple page modules. A simulator mock for lcd.py adds a throttling sleep after every 10 fill_rectangle calls to avoid crashes on certain host machines. A typo fix in touch.py and a new unit test are included.
Changed components
src/krux/pages/device_tests.pysrc/krux/pages/__init__.pysrc/krux/pages/datum_tool.pysrc/krux/pages/keypads.pysrc/krux/pages/mnemonic_editor.pysrc/krux/pages/qr_capture.pysrc/krux/pages/stack_1248.pysrc/krux/pages/tiny_seed.pysimulator/kruxsim/mocks/lcd.pysrc/krux/touch.pytests/pages/test_device_tests.pyInspect captured patch +69 / −12
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77e4b8f..b639fe2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,9 @@ Reduced firmware size by 25% and lowered RAM usage through code cleanup and opti
### Discontinued Support for Maix Bit Device
The Maix Bit device has long been discouraged due to its poor-quality camera. Starting with this release, we are discontinuing support and it will no longer be included in future builds. The support and parameters for building its firmware from source, however, will be kept.
+### Other Bug Fixes and Improvements
+- Touchscreen test added in Tools for detection check
+
# Changelog 25.09.0 - September 2025
### Extended Encryption Options
diff --git a/docs/img/maixpy_amigo/device-tests-options-300.en.png b/docs/img/maixpy_amigo/device-tests-options-300.en.png
index 6f412b6..448569c 100644
Binary files a/docs/img/maixpy_amigo/device-tests-options-300.en.png and b/docs/img/maixpy_amigo/device-tests-options-300.en.png differ
diff --git a/simulator/kruxsim/mocks/lcd.py b/simulator/kruxsim/mocks/lcd.py
index c0086bf..571b564 100644
--- a/simulator/kruxsim/mocks/lcd.py
+++ b/simulator/kruxsim/mocks/lcd.py
@@ -28,6 +28,7 @@ from numpy import zeros_like
from kruxsim import events
from kruxsim.mocks.board import BOARD_CONFIG
from krux.krux_settings import Settings
+import time
COLOR_BLACK = (0, 0, 0)
COLOR_WHITE = (255, 255, 255)
@@ -46,6 +47,8 @@ screen = None
portrait = True
landscape = False
+count_call_fill_rectangle = 0
+
def rgb565torgb888(color):
"""convert from gggbbbbbrrrrrggg to tuple"""
@@ -412,6 +415,12 @@ def fill_rectangle(x, y, w, h, color, radius=0):
radius = min(radius, min(w, h) // 2)
pg.event.post(pg.event.Event(events.LCD_FILL_RECTANGLE_EVENT, {"f": run}))
+ global count_call_fill_rectangle
+ count_call_fill_rectangle += 1
+ if count_call_fill_rectangle > 9:
+ time.sleep(0.01)
+ count_call_fill_rectangle = 0
+
def draw_circle(x, y, radious, quadrant, color):
def run():
diff --git a/src/krux/pages/__init__.py b/src/krux/pages/__init__.py
index 93fc32a..8dd070b 100644
--- a/src/krux/pages/__init__.py
+++ b/src/krux/pages/__init__.py
@@ -38,9 +38,9 @@ from ..input import (
SWIPE_LEFT,
SWIPE_RIGHT,
ONE_MINUTE,
- PRESSED,
KEY_REPEAT_DELAY_MS,
)
+from ..buttons import PRESSED
from ..display import (
DEFAULT_PADDING,
MINIMAL_PADDING,
diff --git a/src/krux/pages/datum_tool.py b/src/krux/pages/datum_tool.py
index 902b1e6..d350eab 100644
--- a/src/krux/pages/datum_tool.py
+++ b/src/krux/pages/datum_tool.py
@@ -50,8 +50,8 @@ from ..input import (
SWIPE_RIGHT,
SWIPE_DOWN,
KEY_REPEAT_DELAY_MS,
- PRESSED,
)
+from ..buttons import PRESSED
DATUM_DESCRIPTOR = "DESC"
DATUM_PSBT = "PSBT"
diff --git a/src/krux/pages/device_tests.py b/src/krux/pages/device_tests.py
index 4f6586b..373dd78 100644
--- a/src/krux/pages/device_tests.py
+++ b/src/krux/pages/device_tests.py
@@ -24,20 +24,24 @@ from . import Page, Menu, MENU_CONTINUE
from ..display import DEFAULT_PADDING, FONT_HEIGHT, FONT_WIDTH
from ..krux_settings import t
from ..wdt import wdt
+from ..kboard import kboard
class DeviceTests(Page):
"""On-Device test-suite"""
def __init__(self, ctx):
+ menu_items = [
+ (t("Print Test QR"), self.print_test),
+ (t("Test Suite"), self.test_suite),
+ ]
+ if kboard.has_touchscreen:
+ menu_items += [(t("Touchscreen"), self.test_touch)]
super().__init__(
ctx,
Menu(
ctx,
- [
- (t("Print Test QR"), self.print_test),
- (t("Test Suite"), self.test_suite),
- ],
+ menu_items,
),
)
self.results = []
@@ -153,6 +157,32 @@ class DeviceTests(Page):
return MENU_CONTINUE
return self.run_one_test(self.results[idx][0])
+ def test_touch(self):
+ """Check touch detection across the entire screen"""
+ from ..buttons import PRESSED
+ from ..themes import theme
+
+ self.ctx.display.clear()
+ self.ctx.display.draw_centered_text(t("Touchscreen"))
+ while True:
+ wdt.feed()
+ if self.ctx.input.touch_value() == PRESSED:
+ x, y = self.ctx.input.touch.release_point
+ self.ctx.display.fill_rectangle(x, y, 10, 10, theme.fg_color)
+ elif (
+ self.ctx.input.enter_value() == PRESSED
+ or self.ctx.input.page_value() == PRESSED
+ or self.ctx.input.page_prev_value() == PRESSED
+ ):
+ break
+
+ # Prevent release capture when exiting
+ self.ctx.input.wait_for_release()
+ # Prevent the next touch from being mistakenly detected as a swipe
+ self.ctx.input.touch.gesture = None
+
+ return MENU_CONTINUE
+
def run_one_test(self, test):
"""run a single test w/ interactive=True, display success/fail and results"""
diff --git a/src/krux/pages/keypads.py b/src/krux/pages/keypads.py
index fd73252..86f2604 100644
--- a/src/krux/pages/keypads.py
+++ b/src/krux/pages/keypads.py
@@ -33,9 +33,9 @@ from ..input import (
SWIPE_LEFT,
FAST_FORWARD,
FAST_BACKWARD,
- PRESSED,
KEY_REPEAT_DELAY_MS,
)
+from ..buttons import PRESSED
from ..display import DEFAULT_PADDING, MINIMAL_PADDING, FONT_HEIGHT, FONT_WIDTH
FIXED_KEYS = 3 # 'More' key only appears when there are multiple keysets.
diff --git a/src/krux/pages/mnemonic_editor.py b/src/krux/pages/mnemonic_editor.py
index 3c772f2..c3327a8 100644
--- a/src/krux/pages/mnemonic_editor.py
+++ b/src/krux/pages/mnemonic_editor.py
@@ -33,9 +33,9 @@ from ..input import (
BUTTON_PAGE_PREV,
FAST_FORWARD,
FAST_BACKWARD,
- PRESSED,
KEY_REPEAT_DELAY_MS,
)
+from ..buttons import PRESSED
from ..key import Key
from ..kboard import kboard
import time
diff --git a/src/krux/pages/qr_capture.py b/src/krux/pages/qr_capture.py
index e57853f..b3f1431 100644
--- a/src/krux/pages/qr_capture.py
+++ b/src/krux/pages/qr_capture.py
@@ -23,7 +23,7 @@ import board
import time
from . import Page
from ..display import FONT_HEIGHT, MINIMAL_PADDING, BOTTOM_LINE
-from ..input import PRESSED
+from ..buttons import PRESSED
from ..themes import theme
from ..qr import QRPartParser, FORMAT_UR
from ..wdt import wdt
diff --git a/src/krux/pages/stack_1248.py b/src/krux/pages/stack_1248.py
index e5a2b75..ebeab1b 100644
--- a/src/krux/pages/stack_1248.py
+++ b/src/krux/pages/stack_1248.py
@@ -32,9 +32,9 @@ from ..input import (
BUTTON_TOUCH,
FAST_FORWARD,
FAST_BACKWARD,
- PRESSED,
KEY_REPEAT_DELAY_MS,
)
+from ..buttons import PRESSED
from ..kboard import kboard
import time
diff --git a/src/krux/pages/tiny_seed.py b/src/krux/pages/tiny_seed.py
index 2d0f598..df13807 100644
--- a/src/krux/pages/tiny_seed.py
+++ b/src/krux/pages/tiny_seed.py
@@ -43,9 +43,9 @@ from ..input import (
BUTTON_TOUCH,
FAST_FORWARD,
FAST_BACKWARD,
- PRESSED,
KEY_REPEAT_DELAY_MS,
)
+from ..buttons import PRESSED
from ..bip39 import entropy_checksum
from ..kboard import kboard
diff --git a/src/krux/touch.py b/src/krux/touch.py
index f222a65..ee1435a 100644
--- a/src/krux/touch.py
+++ b/src/krux/touch.py
@@ -291,5 +291,5 @@ class Touch:
return 1
def current_index(self):
- """Returns current intex of last touched point"""
+ """Returns current index of last touched point"""
return self.index
diff --git a/tests/pages/test_device_tests.py b/tests/pages/test_device_tests.py
index 7fdbe20..0fc530d 100644
--- a/tests/pages/test_device_tests.py
+++ b/tests/pages/test_device_tests.py
@@ -662,3 +662,18 @@ def test_run_one_test_without_touch_gestures(m5stickv, mocker):
assert page.results == [(page.touch_gestures, True)]
assert ctx.input.wait_for_button.call_count == len(BTN_SEQUENCE)
+
+
+def test_test_touch(mocker, amigo):
+ from krux.pages.device_tests import DeviceTests
+ from krux.buttons import PRESSED
+
+ ctx = create_ctx(mocker, [])
+ ctx.input.touch.release_point = (1, 1)
+ ctx.input.touch_value = mocker.MagicMock(side_effect=[PRESSED, None])
+ ctx.input.page_value = mocker.MagicMock(side_effect=[PRESSED, None])
+ DeviceTests(ctx).test_touch()
+
+ ctx.display.fill_rectangle.assert_called()
+ ctx.input.wait_for_release.assert_called()
+ assert ctx.input.touch.gesture == None
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.