From 10f30116631882105f7dfdb1849ec94914a4b972 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 24 Feb 2025 09:35:39 +0100 Subject: [PATCH] feat(core/prodtest): add touch-draw command to prodtest [no changelog] --- core/embed/projects/prodtest/README.md | 9 ++++ .../projects/prodtest/cmd/prodtest_touch.c | 41 +++++++++++++++++++ core/embed/rust/rust_ui_prodtest.h | 2 + core/embed/rust/src/ui/api/prodtest_c.rs | 20 +++++++++ core/embed/rust/src/ui/layout/simplified.rs | 5 +-- .../rust/src/ui/layout_bolt/prodtest/mod.rs | 36 ++++++++++++++++ .../rust/src/ui/layout_caesar/prodtest/mod.rs | 12 ++++++ core/embed/rust/src/ui/ui_prodtest.rs | 8 ++++ 8 files changed, 130 insertions(+), 3 deletions(-) diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md index 9f8bccdd22..4425fea608 100644 --- a/core/embed/projects/prodtest/README.md +++ b/core/embed/projects/prodtest/README.md @@ -220,6 +220,15 @@ haptic-test 3000 OK ``` +### touch-draw +Starts a drawing canvas, where user can draw with finger on pen. Canvas is exited by sending CTRL+C command. +``` +touch-draw +# Starting drawing canvas... +# Press CTRL+C for exit. +ERROR abort +``` + ### touch-test Tests the functionality of the display's touch screen. It draws a filled rectangle in one of the four display quadrants and waits for user interaction. diff --git a/core/embed/projects/prodtest/cmd/prodtest_touch.c b/core/embed/projects/prodtest/cmd/prodtest_touch.c index 75646277b6..413754a1ff 100644 --- a/core/embed/projects/prodtest/cmd/prodtest_touch.c +++ b/core/embed/projects/prodtest/cmd/prodtest_touch.c @@ -336,6 +336,40 @@ static void prodtest_touch_test_sensitivity(cli_t* cli) { screen_prodtest_welcome(); } +static void prodtest_touch_draw(cli_t* cli) { +#define MAX_EVENTS 256 + + if (cli_arg_count(cli) > 0) { + cli_error_arg_count(cli); + return; + } + + cli_trace(cli, "Starting drawing canvas..."); + cli_trace(cli, "Press CTRL+C for exit."); + + uint32_t events[MAX_EVENTS] = {0}; + uint32_t idx = 0; + + screen_prodtest_draw(events, 0); + display_set_backlight(150); + + for (;;) { + uint32_t evt = touch_get_event(); + + if (evt != 0) { + events[idx] = evt; + idx = (idx + 1) % MAX_EVENTS; + + screen_prodtest_draw(events, MAX_EVENTS); + } + if (cli_aborted(cli)) { + break; + } + } + + screen_prodtest_welcome(); +} + // clang-format off PRODTEST_CLI_CMD( @@ -380,4 +414,11 @@ PRODTEST_CLI_CMD( .args = "" ) +PRODTEST_CLI_CMD( + .name = "touch-draw", + .func = prodtest_touch_draw, + .info = "Simple drawing canvas", + .args = "" + ) + #endif // USE_TOUCH diff --git a/core/embed/rust/rust_ui_prodtest.h b/core/embed/rust/rust_ui_prodtest.h index b25a7166bc..72e960a824 100644 --- a/core/embed/rust/rust_ui_prodtest.h +++ b/core/embed/rust/rust_ui_prodtest.h @@ -12,3 +12,5 @@ void screen_prodtest_show_text(const char* text, uint8_t text_len); void screen_prodtest_touch(int16_t x0, int16_t y0, int16_t w, int16_t h); void screen_prodtest_border(void); + +void screen_prodtest_draw(uint32_t* events, uint32_t events_len); diff --git a/core/embed/rust/src/ui/api/prodtest_c.rs b/core/embed/rust/src/ui/api/prodtest_c.rs index 57f1497f2b..2faf792389 100644 --- a/core/embed/rust/src/ui/api/prodtest_c.rs +++ b/core/embed/rust/src/ui/api/prodtest_c.rs @@ -3,7 +3,11 @@ use crate::ui::{ui_prodtest::ProdtestUI, util::from_c_array, ModelUI}; #[cfg(feature = "touch")] use crate::ui::geometry::{Offset, Point, Rect}; #[cfg(feature = "touch")] +use crate::ui::{event::TouchEvent, layout::simplified::touch_unpack}; +#[cfg(feature = "touch")] use cty::int16_t; +#[cfg(feature = "touch")] +use heapless::Vec; #[no_mangle] extern "C" fn screen_prodtest_welcome() { @@ -47,3 +51,19 @@ extern "C" fn screen_prodtest_touch(x0: int16_t, y0: int16_t, w: int16_t, h: int let area = Rect::from_top_left_and_size(Point::new(x0, y0), Offset::new(w, h)); ModelUI::screen_prodtest_touch(area); } + +#[no_mangle] +#[cfg(feature = "touch")] +extern "C" fn screen_prodtest_draw(events: *const cty::uint32_t, events_len: u32) { + let events = unsafe { core::slice::from_raw_parts(events, events_len as usize) }; + + let mut v: Vec = Vec::new(); + + for e in events.iter() { + if let Some(event) = touch_unpack(*e) { + unwrap!(v.push(event)); + } + } + + ModelUI::screen_prodtest_draw(v); +} diff --git a/core/embed/rust/src/ui/layout/simplified.rs b/core/embed/rust/src/ui/layout/simplified.rs index 3ed54b99c7..e42a59de33 100644 --- a/core/embed/rust/src/ui/layout/simplified.rs +++ b/core/embed/rust/src/ui/layout/simplified.rs @@ -52,8 +52,7 @@ fn button_eval() -> Option { } #[cfg(feature = "touch")] -fn touch_eval() -> Option { - let event = io_touch_get_event(); +pub fn touch_unpack(event: u32) -> Option { if event == 0 { return None; } @@ -85,7 +84,7 @@ pub fn run(frame: &mut impl Component) -> u32 { #[cfg(all(feature = "button", not(feature = "touch")))] let event = button_eval(); #[cfg(feature = "touch")] - let event = touch_eval(); + let event = touch_unpack(io_touch_get_event()); if let Some(e) = event { let mut ctx = EventCtx::new(); #[cfg(all(feature = "button", not(feature = "touch")))] diff --git a/core/embed/rust/src/ui/layout_bolt/prodtest/mod.rs b/core/embed/rust/src/ui/layout_bolt/prodtest/mod.rs index b23880b671..5e9ce304ce 100644 --- a/core/embed/rust/src/ui/layout_bolt/prodtest/mod.rs +++ b/core/embed/rust/src/ui/layout_bolt/prodtest/mod.rs @@ -3,12 +3,17 @@ use crate::ui::{ constant::screen, display, display::Color, + event::{ + TouchEvent, + TouchEvent::{TouchEnd, TouchMove, TouchStart}, + }, geometry::{Alignment, Offset, Rect}, layout_bolt::{fonts, theme, UIBolt}, shape, shape::render_on_display, ui_prodtest::ProdtestUI, }; +use heapless::Vec; impl ProdtestUI for UIBolt { fn screen_prodtest_welcome() { @@ -133,4 +138,35 @@ impl ProdtestUI for UIBolt { display::refresh(); display::set_backlight(theme::backlight::get_backlight_normal()); } + + fn screen_prodtest_draw(events: Vec) { + display::sync(); + + render_on_display(None, Some(Color::black()), |target| { + for ev in events.iter() { + match ev { + TouchStart(p) => { + shape::Bar::new(Rect::from_center_and_size(*p, Offset::new(3, 3))) + .with_fg(Color::rgb(0, 255, 0)) + .with_bg(Color::rgb(0, 255, 0)) + .render(target); + } + TouchMove(p) => { + shape::Bar::new(Rect::from_center_and_size(*p, Offset::new(1, 1))) + .with_fg(Color::white()) + .with_bg(Color::white()) + .render(target); + } + TouchEnd(p) => { + shape::Bar::new(Rect::from_center_and_size(*p, Offset::new(3, 3))) + .with_fg(Color::rgb(255, 0, 0)) + .with_bg(Color::rgb(255, 0, 0)) + .render(target); + } + } + } + }); + + display::refresh(); + } } diff --git a/core/embed/rust/src/ui/layout_caesar/prodtest/mod.rs b/core/embed/rust/src/ui/layout_caesar/prodtest/mod.rs index 430103ccb0..ef2831f954 100644 --- a/core/embed/rust/src/ui/layout_caesar/prodtest/mod.rs +++ b/core/embed/rust/src/ui/layout_caesar/prodtest/mod.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "touch")] +use crate::ui::event::TouchEvent; use crate::ui::{ component::{base::Component, Qr}, constant::screen, @@ -9,6 +11,8 @@ use crate::ui::{ shape::render_on_display, ui_prodtest::ProdtestUI, }; +#[cfg(feature = "touch")] +use heapless::Vec; impl ProdtestUI for UICaesar { fn screen_prodtest_welcome() { @@ -109,7 +113,15 @@ impl ProdtestUI for UICaesar { display::refresh(); } + // currently has to be here due to clippy limitations + #[cfg(feature = "touch")] fn screen_prodtest_touch(_area: Rect) { unimplemented!(); } + + // currently has to be here due to clippy limitations + #[cfg(feature = "touch")] + fn screen_prodtest_draw(events: Vec) { + unimplemented!() + } } diff --git a/core/embed/rust/src/ui/ui_prodtest.rs b/core/embed/rust/src/ui/ui_prodtest.rs index fea55f7a4c..73a5cf8c97 100644 --- a/core/embed/rust/src/ui/ui_prodtest.rs +++ b/core/embed/rust/src/ui/ui_prodtest.rs @@ -1,4 +1,8 @@ +#[cfg(feature = "touch")] +use crate::ui::event::TouchEvent; use crate::ui::geometry::Rect; +#[cfg(feature = "touch")] +use heapless::Vec; pub trait ProdtestUI { fn screen_prodtest_welcome(); @@ -11,5 +15,9 @@ pub trait ProdtestUI { fn screen_prodtest_bars(colors: &str); + #[cfg(feature = "touch")] fn screen_prodtest_touch(area: Rect); + + #[cfg(feature = "touch")] + fn screen_prodtest_draw(events: Vec); }