diff --git a/core/embed/extmod/modtrezorui/display_interface.h b/core/embed/extmod/modtrezorui/display_interface.h index 4b166fdc8..5b9c3ca82 100644 --- a/core/embed/extmod/modtrezorui/display_interface.h +++ b/core/embed/extmod/modtrezorui/display_interface.h @@ -43,6 +43,7 @@ int display_backlight(int val); void display_init(void); void display_reinit(void); +void display_sync(void); void display_refresh(void); const char *display_save(const char *prefix); void display_clear_save(void); diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index e40735ce4..944dca9f0 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -293,6 +293,7 @@ fn generate_trezorhal_bindings() { .allowlist_function("display_pixeldata") .allowlist_function("display_pixeldata_dirty") .allowlist_function("display_set_window") + .allowlist_function("display_sync") .allowlist_var("DISPLAY_CMD_ADDRESS") .allowlist_var("DISPLAY_DATA_ADDRESS") .allowlist_type("toif_format_t") diff --git a/core/embed/rust/src/trezorhal/display.rs b/core/embed/rust/src/trezorhal/display.rs index 32083210e..17e9c5128 100644 --- a/core/embed/rust/src/trezorhal/display.rs +++ b/core/embed/rust/src/trezorhal/display.rs @@ -169,3 +169,9 @@ pub fn get_offset() -> (i16, i16) { (x as i16, y as i16) } } + +pub fn sync() { + unsafe { + ffi::display_sync(); + } +} diff --git a/core/embed/rust/src/ui/display/mod.rs b/core/embed/rust/src/ui/display/mod.rs index e85e41aee..3a9ef3ed4 100644 --- a/core/embed/rust/src/ui/display/mod.rs +++ b/core/embed/rust/src/ui/display/mod.rs @@ -826,6 +826,10 @@ pub fn set_window(window: Rect) { ); } +pub fn sync() { + display::sync(); +} + pub fn get_color_table(fg_color: Color, bg_color: Color) -> [Color; 16] { let mut table: [Color; 16] = [Color::from_u16(0); 16]; diff --git a/core/embed/rust/src/ui/layout/obj.rs b/core/embed/rust/src/ui/layout/obj.rs index a51c14a5b..4f6c82462 100644 --- a/core/embed/rust/src/ui/layout/obj.rs +++ b/core/embed/rust/src/ui/layout/obj.rs @@ -18,6 +18,7 @@ use crate::{ ui::{ component::{Child, Component, Event, EventCtx, Never, TimerToken}, constant, + display::sync, geometry::Rect, }, }; @@ -200,6 +201,8 @@ impl LayoutObj { unsafe { Gc::as_mut(&mut inner.root) }.obj_place(constant::screen()); } + sync(); + // SAFETY: `inner.root` is unique because of the `inner.borrow_mut()`. unsafe { Gc::as_mut(&mut inner.root) }.obj_paint() } diff --git a/core/embed/trezorhal/common.c b/core/embed/trezorhal/common.c index 31ba58a67..d8864b033 100644 --- a/core/embed/trezorhal/common.c +++ b/core/embed/trezorhal/common.c @@ -192,6 +192,7 @@ void collect_hw_entropy(void) { void ensure_compatible_settings(void) { #ifdef TREZOR_MODEL_T display_set_big_endian(); + display_orientation(0); set_core_clock(CLOCK_168_MHZ); display_set_slow_pwm(); #endif diff --git a/core/embed/trezorhal/displays/st7789v.c b/core/embed/trezorhal/displays/st7789v.c index 611c411a3..f84321c87 100644 --- a/core/embed/trezorhal/displays/st7789v.c +++ b/core/embed/trezorhal/displays/st7789v.c @@ -151,11 +151,20 @@ int display_orientation(int degrees) { if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) { DISPLAY_ORIENTATION = degrees; + display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1); + for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) { + // 2 bytes per pixel because we're using RGB 5-6-5 format + PIXELDATA(0x0000); + } + + uint16_t shift = 0; char BX = 0, BY = 0; uint32_t id = display_identify(); if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { #define RGB (1 << 3) +#define ML (1 << 4) // vertical refresh order +#define MH (1 << 2) // horizontal refresh order #define MV (1 << 5) #define MX (1 << 6) #define MY (1 << 7) @@ -170,12 +179,14 @@ int display_orientation(int degrees) { BY = (id == DISPLAY_ID_GC9307); break; case 90: - display_command_parameter = MV | MX; - BX = (id == DISPLAY_ID_GC9307); + display_command_parameter = MV | MX | MH | ML; + BX = (id != DISPLAY_ID_GC9307); + shift = 1; break; case 180: - display_command_parameter = MX | MY; - BY = (id != DISPLAY_ID_GC9307); + display_command_parameter = MX | MY | MH | ML; + BY = (id == DISPLAY_ID_GC9307); + shift = 1; break; case 270: display_command_parameter = MV | MY; @@ -187,6 +198,23 @@ int display_orientation(int degrees) { } CMD(0x36); DATA(display_command_parameter); + + if (shift) { + // GATECTRL: Gate Control; NL = 240 gate lines, first scan line is + // gate 80.; gate scan direction 319 -> 0 + CMD(0xE4); + DATA(0x1D); + DATA(0x00); + DATA(0x11); + } else { + // GATECTRL: Gate Control; NL = 240 gate lines, first scan line is + // gate 80.; gate scan direction 319 -> 0 + CMD(0xE4); + DATA(0x1D); + DATA(0x0A); + DATA(0x11); + } + // reset the column and page extents display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); } @@ -634,18 +662,20 @@ void display_reinit(void) { display_backlight(DISPLAY_BACKLIGHT); } -void display_refresh(void) { +void display_sync(void) { uint32_t id = display_identify(); if (id && (id != DISPLAY_ID_GC9307)) { // synchronize with the panel synchronization signal // in order to avoid visual tearing effects - while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { - } while (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } + while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { + } } } +void display_refresh(void) {} + void display_set_slow_pwm(void) { // enable PWM timer TIM_HandleTypeDef TIM1_Handle; diff --git a/core/embed/trezorhal/displays/ug-2828tswig01.c b/core/embed/trezorhal/displays/ug-2828tswig01.c index 835b1ff35..4c3c7991b 100644 --- a/core/embed/trezorhal/displays/ug-2828tswig01.c +++ b/core/embed/trezorhal/displays/ug-2828tswig01.c @@ -347,6 +347,8 @@ void display_init(void) { display_init_seq(); } +void display_sync(void) {} + void display_refresh(void) { for (int y = 0; y < (DISPLAY_RESY / 8); y++) { display_set_page_and_col(y, 0); diff --git a/core/embed/trezorhal/displays/vg-2864ksweg01.c b/core/embed/trezorhal/displays/vg-2864ksweg01.c index 15c74bbdb..15c0b82e6 100644 --- a/core/embed/trezorhal/displays/vg-2864ksweg01.c +++ b/core/embed/trezorhal/displays/vg-2864ksweg01.c @@ -247,6 +247,8 @@ static void rotate_oled_buffer(void) { } } +void display_sync(void) {} + void display_refresh(void) { static const uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00, OLED_SETHIGHCOLUMN | 0x00, diff --git a/core/embed/unix/display-unix.c b/core/embed/unix/display-unix.c index c6669a205..ed6fcb87d 100644 --- a/core/embed/unix/display-unix.c +++ b/core/embed/unix/display-unix.c @@ -234,6 +234,8 @@ void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { PIXELWINDOW.pos.y = y0; } +void display_sync(void) {} + void display_refresh(void) { if (!RENDERER) { display_init();