diff --git a/core/.changelog.d/4492.fixed b/core/.changelog.d/4492.fixed new file mode 100644 index 00000000000..47972e662de --- /dev/null +++ b/core/.changelog.d/4492.fixed @@ -0,0 +1 @@ +[T3T1] Fixed flashing old content when fading diff --git a/core/embed/io/display/st-7789/display_fb.c b/core/embed/io/display/st-7789/display_fb.c index 97b98443ce1..795ec33bdd2 100644 --- a/core/embed/io/display/st-7789/display_fb.c +++ b/core/embed/io/display/st-7789/display_fb.c @@ -135,7 +135,7 @@ void display_fb_clear(void) { static void bg_copy_callback(void) { display_driver_t *drv = &g_display_driver; - drv->update_pending = 1; + drv->update_pending = 2; fb_queue_put(&drv->empty_frames, fb_queue_take(&drv->ready_frames)); } @@ -267,13 +267,6 @@ void display_ensure_refreshed(void) { irq_unlock(irq_key); __WFI(); } while (copy_pending); - - // Wait until the display is fully refreshed - // (TE signal is low when the display is updating) - while (GPIO_PIN_RESET == - HAL_GPIO_ReadPin(DISPLAY_TE_PORT, DISPLAY_TE_PIN)) { - __WFI(); - } } #endif } diff --git a/core/embed/projects/bootloader/.changelog.d/4492.fixed b/core/embed/projects/bootloader/.changelog.d/4492.fixed new file mode 100644 index 00000000000..68632c51175 --- /dev/null +++ b/core/embed/projects/bootloader/.changelog.d/4492.fixed @@ -0,0 +1 @@ +[T3T1] Fix slow fade in/non responsiveness in bootloader UI diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index a6afb178f02..79b5a67f4ee 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -79,6 +79,8 @@ static void _librust_qstrs(void) { MP_QSTR_auto_lock__change_template; MP_QSTR_auto_lock__title; MP_QSTR_auto_lock__turned_on; + MP_QSTR_backlight_fade; + MP_QSTR_backlight_set; MP_QSTR_backup__can_back_up_anytime; MP_QSTR_backup__create_backup_to_prevent_loss; MP_QSTR_backup__info_multi_share_backup; diff --git a/core/embed/rust/src/time.rs b/core/embed/rust/src/time.rs index abdb8bedf06..98a59612514 100644 --- a/core/embed/rust/src/time.rs +++ b/core/embed/rust/src/time.rs @@ -199,7 +199,7 @@ impl Stopwatch { pub fn elapsed(&self) -> Duration { match *self { Self::Stopped(duration) => duration, - Self::Running(time) => Instant::now().checked_duration_since(time).unwrap(), + Self::Running(time) => unwrap!(Instant::now().checked_duration_since(time)), } } diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs index 3cc636cd604..91f41933060 100644 --- a/core/embed/rust/src/ui/api/firmware_micropython.rs +++ b/core/embed/rust/src/ui/api/firmware_micropython.rs @@ -29,6 +29,9 @@ use crate::{ }; use heapless::Vec; +#[cfg(feature = "backlight")] +use crate::ui::display::{fade_backlight_duration, set_backlight}; + /// Dummy implementation so that we can use `Empty` in a return type of /// unimplemented trait function impl ComponentMsgObj for Empty { @@ -1035,6 +1038,24 @@ pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { unsafe { util::try_or_raise(block) } } +pub extern "C" fn upy_backlight_set(_level: Obj) -> Obj { + let block = || { + #[cfg(feature = "backlight")] + set_backlight(_level.try_into()?); + Ok(Obj::const_none()) + }; + unsafe { util::try_or_raise(block) } +} + +pub extern "C" fn upy_backlight_fade(_level: Obj) -> Obj { + let block = || { + #[cfg(feature = "backlight")] + fade_backlight_duration(_level.try_into()?, 150); + Ok(Obj::const_none()) + }; + unsafe { util::try_or_raise(block) } +} + #[no_mangle] pub static mp_module_trezorui_api: Module = obj_module! { /// from trezor import utils @@ -1141,6 +1162,14 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// """Disable animations, debug builds only.""" Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(), + /// def backlight_set(level: int) -> None: + /// """Set backlight to desired level.""" + Qstr::MP_QSTR_backlight_set => obj_fn_1!(upy_backlight_set).as_obj(), + + /// def backlight_fade(level: int) -> None: + /// """Fade backlight to desired level.""" + Qstr::MP_QSTR_backlight_fade => obj_fn_1!(upy_backlight_fade).as_obj(), + /// def confirm_action( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/display/mod.rs b/core/embed/rust/src/ui/display/mod.rs index 4a8d3c95095..a48d0e9bb9b 100644 --- a/core/embed/rust/src/ui/display/mod.rs +++ b/core/embed/rust/src/ui/display/mod.rs @@ -13,6 +13,9 @@ use crate::{strutil::TString, trezorhal::display}; #[cfg(feature = "backlight")] use crate::ui::lerp::Lerp; +#[cfg(feature = "backlight")] +use crate::{time::Stopwatch, ui::util::animation_disabled}; + // Reexports pub use crate::ui::display::toif::Icon; pub use color::Color; @@ -39,11 +42,19 @@ pub fn fade_backlight(target: u8) { #[cfg(feature = "backlight")] pub fn fade_backlight_duration(target: u8, duration_ms: u32) { let target = target as i32; - let duration_ms = duration_ms as i32; let current = backlight() as i32; + let duration = Duration::from_millis(duration_ms); + + if animation_disabled() { + set_backlight(target as u8); + return; + } + + let timer = Stopwatch::new_started(); - for i in 0..duration_ms { - let val = i32::lerp(current, target, i as f32 / duration_ms as f32); + while timer.elapsed() < duration { + let elapsed = timer.elapsed(); + let val = i32::lerp(current, target, elapsed / duration); set_backlight(val as u8); time::sleep(Duration::from_millis(1)); } diff --git a/core/embed/upymod/modtrezorui/modtrezorui-display.h b/core/embed/upymod/modtrezorui/modtrezorui-display.h index d5494a93299..637d49b5d90 100644 --- a/core/embed/upymod/modtrezorui/modtrezorui-display.h +++ b/core/embed/upymod/modtrezorui/modtrezorui-display.h @@ -103,29 +103,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_orientation_obj, 1, 2, mod_trezorui_Display_orientation); -/// def backlight(self, val: int | None = None) -> int: -/// """ -/// Sets backlight intensity to the value specified in val. -/// Call without the val parameter to just perform the read of the value. -/// """ -STATIC mp_obj_t mod_trezorui_Display_backlight(size_t n_args, - const mp_obj_t *args) { - mp_int_t val; - if (n_args > 1) { - val = mp_obj_get_int(args[1]); - if (val < 0 || val > 255) { - mp_raise_ValueError("Value must be between 0 and 255"); - } - val = display_set_backlight(val); - } else { - val = display_get_backlight(); - } - return MP_OBJ_NEW_SMALL_INT(val); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_backlight_obj, - 1, 2, - mod_trezorui_Display_backlight); - /// def save(self, prefix: str) -> None: /// """ /// Saves current display contents to PNG file with given prefix. @@ -162,8 +139,6 @@ STATIC const mp_rom_map_elem_t mod_trezorui_Display_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&mod_trezorui_Display_bar_obj)}, {MP_ROM_QSTR(MP_QSTR_orientation), MP_ROM_PTR(&mod_trezorui_Display_orientation_obj)}, - {MP_ROM_QSTR(MP_QSTR_backlight), - MP_ROM_PTR(&mod_trezorui_Display_backlight_obj)}, {MP_ROM_QSTR(MP_QSTR_save), MP_ROM_PTR(&mod_trezorui_Display_save_obj)}, {MP_ROM_QSTR(MP_QSTR_clear_save), MP_ROM_PTR(&mod_trezorui_Display_clear_save_obj)}, diff --git a/core/mocks/generated/trezorui.pyi b/core/mocks/generated/trezorui.pyi index ed57058ae84..aa4527178c7 100644 --- a/core/mocks/generated/trezorui.pyi +++ b/core/mocks/generated/trezorui.pyi @@ -37,12 +37,6 @@ class Display: value. """ - def backlight(self, val: int | None = None) -> int: - """ - Sets backlight intensity to the value specified in val. - Call without the val parameter to just perform the read of the value. - """ - def save(self, prefix: str) -> None: """ Saves current display contents to PNG file with given prefix. diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index afe82746f30..e2dd7a1db87 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -80,6 +80,16 @@ def disable_animation(disable: bool) -> None: """Disable animations, debug builds only.""" +# rust/src/ui/api/firmware_micropython.rs +def backlight_set(level: int) -> None: + """Set backlight to desired level.""" + + +# rust/src/ui/api/firmware_micropython.rs +def backlight_fade(level: int) -> None: + """Fade backlight to desired level.""" + + # rust/src/ui/api/firmware_micropython.rs def confirm_action( *, diff --git a/core/src/trezor/ui/__init__.py b/core/src/trezor/ui/__init__.py index 2bd3c3e9126..698f0abfa08 100644 --- a/core/src/trezor/ui/__init__.py +++ b/core/src/trezor/ui/__init__.py @@ -8,7 +8,13 @@ from trezor.messages import ButtonAck, ButtonRequest from trezor.wire import context from trezor.wire.protocol_common import Context -from trezorui_api import AttachType, BacklightLevels, LayoutState +from trezorui_api import ( + AttachType, + BacklightLevels, + LayoutState, + backlight_fade, + backlight_set, +) if TYPE_CHECKING: from typing import Any, Callable, Generator, Generic, Iterator, TypeVar @@ -67,12 +73,12 @@ async def _alert(count: int) -> None: long_sleep = loop.sleep(80) for i in range(count * 2): if i % 2 == 0: - display.backlight(BacklightLevels.MAX) + backlight_set(BacklightLevels.MAX) await short_sleep else: - display.backlight(BacklightLevels.DIM) + backlight_set(BacklightLevels.DIM) await long_sleep - display.backlight(BacklightLevels.NORMAL) + backlight_set(BacklightLevels.NORMAL) global _alert_in_progress _alert_in_progress = False @@ -87,24 +93,6 @@ def alert(count: int = 3) -> None: loop.schedule(_alert(count)) -def backlight_fade(val: int, delay: int = 14000, step: int = 15) -> None: - if utils.USE_BACKLIGHT: - if __debug__: - if utils.DISABLE_ANIMATION: - display.backlight(val) - return - current = display.backlight() - if current < 0: - display.backlight(val) - return - elif current > val: - step = -step - for i in range(current, val, step): - display.backlight(i) - utime.sleep_us(delay) - display.backlight(val) - - class Shutdown(Exception): pass @@ -526,9 +514,9 @@ def start(self) -> None: self.layout.request_complete_repaint() painted = self.layout.paint() - backlight_fade(BacklightLevels.NORMAL) if painted: refresh() + backlight_fade(BacklightLevels.NORMAL) def stop(self) -> None: global CURRENT_LAYOUT diff --git a/core/tests/test_trezor.ui.display.py b/core/tests/test_trezor.ui.display.py index 3dac73498db..55c7502a00b 100644 --- a/core/tests/test_trezor.ui.display.py +++ b/core/tests/test_trezor.ui.display.py @@ -2,6 +2,7 @@ from common import * # isort:skip from trezor.ui import display +from trezorui_api import backlight_set class TestDisplay(unittest.TestCase): @@ -17,7 +18,7 @@ def test_orientation(self): def test_backlight(self): for b in range(256): - display.backlight(b) + backlight_set(b) def test_raw(self): pass