From 353095ae95c0572a14959eb26ad24df6c380a03e Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 28 Jun 2023 10:51:37 +0200 Subject: [PATCH] feat(core): add support for STM32U5A9J-DK board [no changelog] --- core/Makefile | 10 + core/SConscript.bootloader | 2 +- core/SConscript.bootloader_ci | 2 +- core/SConscript.bootloader_emu | 4 +- core/SConscript.firmware | 6 +- core/SConscript.prodtest | 2 +- core/SConscript.reflash | 2 +- core/SConscript.unix | 6 +- core/embed/firmware/memory_DISC2.ld | 123 ++ core/embed/models/model.h | 2 + core/embed/models/model_D002.h | 32 + core/embed/models/model_D002_layout.c | 93 + core/embed/trezorhal/boards/stm32u5a9j-dk.h | 31 + core/embed/trezorhal/stm32u5/displays/dsi.c | 1730 +++++++++++++++++ core/embed/trezorhal/stm32u5/displays/dsi.h | 30 + .../trezorhal/stm32u5/displays/gfxmmu_lut.h | 1006 ++++++++++ core/embed/trezorhal/stm32u5/touch/sitronix.c | 1214 ++++++++++++ core/embed/trezorhal/stm32u5/touch/sitronix.h | 0 .../D002/vendor_dev_DO_NOT_SIGN.json | 20 + .../D002/vendor_dev_DO_NOT_SIGN.toif | Bin 0 -> 3942 bytes .../vendorheader/D002/vendor_unsafe.json | 20 + .../vendorheader/D002/vendor_unsafe.toif | Bin 0 -> 2162 bytes ...endorheader_dev_DO_NOT_SIGN_signed_dev.bin | Bin 0 -> 4608 bytes .../vendorheader_dev_DO_NOT_SIGN_unsigned.bin | Bin 0 -> 4608 bytes .../D002/vendorheader_unsafe_signed_dev.bin | Bin 0 -> 4608 bytes .../D002/vendorheader_unsafe_signed_prod.bin | Bin 0 -> 4608 bytes .../D002/vendorheader_unsafe_unsigned.bin | Bin 0 -> 4608 bytes core/embed/vendorheader/generate.sh | 2 +- core/site_scons/boards/discovery2.py | 97 + core/site_scons/tools.py | 5 + python/src/trezorlib/firmware/models.py | 13 + python/src/trezorlib/models.py | 12 +- 32 files changed, 4452 insertions(+), 12 deletions(-) create mode 100644 core/embed/firmware/memory_DISC2.ld create mode 100644 core/embed/models/model_D002.h create mode 100644 core/embed/models/model_D002_layout.c create mode 100644 core/embed/trezorhal/boards/stm32u5a9j-dk.h create mode 100644 core/embed/trezorhal/stm32u5/displays/dsi.c create mode 100644 core/embed/trezorhal/stm32u5/displays/dsi.h create mode 100644 core/embed/trezorhal/stm32u5/displays/gfxmmu_lut.h create mode 100644 core/embed/trezorhal/stm32u5/touch/sitronix.c create mode 100644 core/embed/trezorhal/stm32u5/touch/sitronix.h create mode 100644 core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.json create mode 100644 core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.toif create mode 100644 core/embed/vendorheader/D002/vendor_unsafe.json create mode 100644 core/embed/vendorheader/D002/vendor_unsafe.toif create mode 100644 core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin create mode 100644 core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_unsigned.bin create mode 100644 core/embed/vendorheader/D002/vendorheader_unsafe_signed_dev.bin create mode 100644 core/embed/vendorheader/D002/vendorheader_unsafe_signed_prod.bin create mode 100644 core/embed/vendorheader/D002/vendorheader_unsafe_unsigned.bin create mode 100644 core/site_scons/boards/discovery2.py diff --git a/core/Makefile b/core/Makefile index 6d450d40e..06b3d0e98 100644 --- a/core/Makefile +++ b/core/Makefile @@ -55,6 +55,16 @@ BOOTLOADER_MAXSIZE = 131072 FIRMWARE_P1_MAXSIZE = 786432 FIRMWARE_P2_MAXSIZE = 917504 FIRMWARE_MAXSIZE = 1703936 +else ifeq ($(TREZOR_MODEL),$(filter $(TREZOR_MODEL),DISC2)) +OPENOCD_TARGET = target/stm32u5x.cfg +BOARDLOADER_START = 0x0C004000 +BOARDLOADER_END = 0x0C010000 +BOOTLOADER_START = 0x0C010000 +FIRMWARE_START = 0x0C050000 +PRODTEST_START = 0x0C050000 +BOARDLOADER_MAXSIZE = 49152 +BOOTLOADER_MAXSIZE = 131072 +FIRMWARE_MAXSIZE = 3735552 else ifeq ($(TREZOR_MODEL), 1) OPENOCD_TARGET = target/stm32f2x.cfg FIRMWARE_START = 0x08010000 diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index a3e468d23..8efabcf27 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -36,7 +36,7 @@ if TREZOR_MODEL in ('R', ): FONT_BOLD='Font_PixelOperator_Bold_8' FONT_MONO='Font_PixelOperator_Regular_8' FONT_BIG=None -elif TREZOR_MODEL in ('T', 'DISC1'): +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): FONT_NORMAL='Font_TTHoves_Regular_21' FONT_DEMIBOLD=None FONT_BOLD='Font_TTHoves_Bold_17' diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index c6356f182..07e59c710 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -6,7 +6,7 @@ import tools TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) -if TREZOR_MODEL in ('1', 'DISC1'): +if TREZOR_MODEL in ('1', 'DISC1', 'DISC2'): # skip bootloader_ci build env = Environment() def build_bootloader_ci(target,source,env): diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index 2ea32755a..a35c95bc9 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -33,7 +33,7 @@ if TREZOR_MODEL in ('1', 'R'): FONT_BOLD='Font_PixelOperator_Bold_8' FONT_MONO='Font_PixelOperator_Regular_8' FONT_BIG=None -elif TREZOR_MODEL in ('T', ): +elif TREZOR_MODEL in ('T', 'DISC2'): FONT_NORMAL='Font_TTHoves_Regular_21' FONT_DEMIBOLD=None FONT_BOLD='Font_TTHoves_Bold_17' @@ -176,6 +176,8 @@ if TREZOR_MODEL in ('T', 'R'): CPU_MODEL = 'STM32F427xx' elif TREZOR_MODEL in ('DISC1', ): CPU_MODEL = 'STM32F429xx' +elif TREZOR_MODEL in ('DISC2', ): + CPU_MODEL = 'STM32U5A9xx' elif TREZOR_MODEL in ('1',): CPU_MODEL = 'STM32F405xx' else: diff --git a/core/SConscript.firmware b/core/SConscript.firmware index fa05d1e8f..9f00b7804 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -41,7 +41,7 @@ if TREZOR_MODEL in ('1', 'R'): FONT_BOLD='Font_PixelOperator_Bold_8' FONT_MONO='Font_PixelOperatorMono_Regular_8' FONT_BIG='Font_Unifont_Regular_16' -elif TREZOR_MODEL in ('T', 'DISC1'): +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): FONT_NORMAL='Font_TTHoves_Regular_21' FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' FONT_BOLD='Font_TTHoves_Bold_17' @@ -391,7 +391,7 @@ SOURCE_FIRMWARE = [ ] -if TREZOR_MODEL in ('T', 'DISC1'): +if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): UI_LAYOUT = 'UI_LAYOUT_TT' ui_layout_feature = 'model_tt' elif TREZOR_MODEL in ('1', 'R'): @@ -806,7 +806,7 @@ if TREZOR_MODEL not in ('1',): ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' ' $SOURCE $TARGET', )) -if TREZOR_MODEL not in ('DISC1', ): +if TREZOR_MODEL not in ('DISC1', 'DISC2'): tools.embed_binary( obj_program, env, diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index 7b6ae6207..dbd384093 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -8,7 +8,7 @@ CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' -if TREZOR_MODEL in ('DISC1', ): +if TREZOR_MODEL in ('DISC1', 'DISC2'): # skip prodtest build env = Environment() def build_prodtest(target,source,env): diff --git a/core/SConscript.reflash b/core/SConscript.reflash index d6b23479c..d0ede89e4 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -6,7 +6,7 @@ import tools TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) -if TREZOR_MODEL in ('DISC1', ): +if TREZOR_MODEL in ('DISC1', 'DISC2'): # skip reflash build env = Environment() def build_reflash(target,source,env): diff --git a/core/SConscript.unix b/core/SConscript.unix index b292dbe1c..2e7cf38cf 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -10,7 +10,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') DMA2D = TREZOR_MODEL in ('T', ) CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) -if TREZOR_MODEL in ('DISC1', ): +if TREZOR_MODEL in ('DISC1', 'DISC2'): # skip unix build env = Environment() def build_unix(target,source,env): @@ -42,7 +42,7 @@ if TREZOR_MODEL in ('1', 'R'): FONT_BOLD='Font_PixelOperator_Bold_8' FONT_MONO='Font_PixelOperatorMono_Regular_8' FONT_BIG='Font_Unifont_Regular_16' -elif TREZOR_MODEL in ('T', ): +elif TREZOR_MODEL in ('T', 'DISC2'): FONT_NORMAL='Font_TTHoves_Regular_21' FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' FONT_BOLD='Font_TTHoves_Bold_17' @@ -501,6 +501,8 @@ if TREZOR_MODEL in ('T', 'R'): CPU_MODEL = 'STM32F427xx' elif TREZOR_MODEL in ('DISC1', ): CPU_MODEL = 'STM32F429xx' +elif TREZOR_MODEL in ('DISC2', ): + CPU_MODEL = 'STM32U5A9xx' elif TREZOR_MODEL in ('1',): CPU_MODEL = 'STM32F405xx' else: diff --git a/core/embed/firmware/memory_DISC2.ld b/core/embed/firmware/memory_DISC2.ld new file mode 100644 index 000000000..d5f81ce6d --- /dev/null +++ b/core/embed/firmware/memory_DISC2.ld @@ -0,0 +1,123 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) + BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K + SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K + SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K + SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2) + 0x100; +_estack = main_stack_base; + +/* used by the startup code to populate variables used by the C code */ +data_lma = LOADADDR(.data); +data_vma = ADDR(.data); +data_size = SIZEOF(.data); + +/* used by the startup code to populate variables used by the C code */ +sensitive_lma = LOADADDR(.sensitive); +sensitive_vma = ADDR(.sensitive); +sensitive_size = SIZEOF(.sensitive); + +/* used by the startup code to wipe memory */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); +g_boot_args = (boot_args_start + 4); +g_boot_flag = boot_args_start; + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .data_ccm : ALIGN(4) { + *(.no_dma_buffers*); + . = ALIGN(4); + } >SRAM1 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */ + } >SRAM2 + + .sensitive : ALIGN(512) { + *(.sensitive*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .fb2 : ALIGN(4) { + *(.fb2*); + __fb_end = .; + . = ALIGN(4); + } >SRAM5 +} diff --git a/core/embed/models/model.h b/core/embed/models/model.h index 0739cdf02..1d1bbb1bc 100644 --- a/core/embed/models/model.h +++ b/core/embed/models/model.h @@ -11,6 +11,8 @@ #include "model_T2B1.h" #elif defined TREZOR_MODEL_DISC1 #include "model_D001.h" +#elif defined TREZOR_MODEL_DISC2 +#include "model_D002.h" #else #error Unknown Trezor model #endif diff --git a/core/embed/models/model_D002.h b/core/embed/models/model_D002.h new file mode 100644 index 000000000..e89165462 --- /dev/null +++ b/core/embed/models/model_D002.h @@ -0,0 +1,32 @@ +#ifndef MODELS_MODEL_DISC2_H_ +#define MODELS_MODEL_DISC2_H_ + +#define MODEL_NAME "T" +#define MODEL_FULL_NAME "Trezor Model T" +#define MODEL_INTERNAL_NAME "D002" +#define MODEL_INTERNAL_NAME_TOKEN D002 +#define MODEL_NAME_QSTR MP_QSTR_T +#define MODEL_INTERNAL_NAME_QSTR MP_QSTR_D001 + +/*** Discovery uses DEV keys in any build variant ***/ +#define MODEL_BOARDLOADER_KEYS \ + (const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d", \ + (const uint8_t *)"\x21\x52\xf8\xd1\x9b\x79\x1d\x24\x45\x32\x42\xe1\x5f\x2e\xab\x6c\xb7\xcf\xfa\x7b\x6a\x5e\xd3\x00\x97\x96\x0e\x06\x98\x81\xdb\x12", \ + (const uint8_t *)"\x22\xfc\x29\x77\x92\xf0\xb6\xff\xc0\xbf\xcf\xdb\x7e\xdb\x0c\x0a\xa1\x4e\x02\x5a\x36\x5e\xc0\xe3\x42\xe8\x6e\x38\x29\xcb\x74\xb6", + +#define MODEL_BOOTLOADER_KEYS \ + (const uint8_t *)"\xd7\x59\x79\x3b\xbc\x13\xa2\x81\x9a\x82\x7c\x76\xad\xb6\xfb\xa8\xa4\x9a\xee\x00\x7f\x49\xf2\xd0\x99\x2d\x99\xb8\x25\xad\x2c\x48", \ + (const uint8_t *)"\x63\x55\x69\x1c\x17\x8a\x8f\xf9\x10\x07\xa7\x47\x8a\xfb\x95\x5e\xf7\x35\x2c\x63\xe7\xb2\x57\x03\x98\x4c\xf7\x8b\x26\xe2\x1a\x56", \ + (const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48", + +#define BOARDLOADER_START 0x0C004000 +#define BOARD_CAPABILITIES_ADDR 0x0C00FF00 +#define BOOTLOADER_START 0x0C010000 +#define FIRMWARE_START 0x0C050000 + +#define IMAGE_CHUNK_SIZE (256 * 1024) +#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB +#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB +#define NORCOW_SECTOR_SIZE (64 * 1024) + +#endif diff --git a/core/embed/models/model_D002_layout.c b/core/embed/models/model_D002_layout.c new file mode 100644 index 000000000..eae23b699 --- /dev/null +++ b/core/embed/models/model_D002_layout.c @@ -0,0 +1,93 @@ +#include "flash.h" +#include "model.h" + +const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = { + { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x18, + .num_sectors = 8, + }, + }, + { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x20, + .num_sectors = 8, + }, + }, +}; + +const flash_area_t BOARDLOADER_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 1, + .num_sectors = 6, + }, +}; + +const flash_area_t BOOTLOADER_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x08, + .num_sectors = 16, + }, +}; + +const flash_area_t FIRMWARE_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x28, + .num_sectors = 456, + }, +}; + +const flash_area_t SECRET_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0, + .num_sectors = 2, + }, +}; + +const flash_area_t BHK_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 1, + .num_sectors = 1, + }, +}; + +const flash_area_t WIPE_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x18, + .num_sectors = 488, + }, +}; + +const flash_area_t ALL_WIPE_AREA = { + .num_subareas = 1, + .secure_area = true, + .subarea[0] = + { + .first_sector = 0x08, + .num_sectors = 504, + }, +}; diff --git a/core/embed/trezorhal/boards/stm32u5a9j-dk.h b/core/embed/trezorhal/boards/stm32u5a9j-dk.h new file mode 100644 index 000000000..8903eec89 --- /dev/null +++ b/core/embed/trezorhal/boards/stm32u5a9j-dk.h @@ -0,0 +1,31 @@ +#ifndef STM32U5A9J_DK_H_ +#define STM32U5A9J_DK_H_ + +#define HSE_16MHZ +#define VDD_1V8 1 + +#define USE_I2C 1 +#define USE_RGB_COLORS 1 +#define USE_TOUCH 1 +//#define USE_SBU 1 +//#define USE_DISP_I8080_8BIT_DW 1 + +#include "displays/dsi.h" + +#define I2C_COUNT 1 +#define I2C_INSTANCE_1 I2C5 +#define I2C_INSTANCE_1_CLK_EN __HAL_RCC_I2C5_CLK_ENABLE +#define I2C_INSTANCE_1_CLK_DIS __HAL_RCC_I2C5_CLK_DISABLE +#define I2C_INSTANCE_1_PIN_AF GPIO_AF2_I2C5 +#define I2C_INSTANCE_1_SDA_PORT GPIOH +#define I2C_INSTANCE_1_SDA_PIN GPIO_PIN_4 +#define I2C_INSTANCE_1_SDA_CLK_EN __HAL_RCC_GPIOH_CLK_ENABLE +#define I2C_INSTANCE_1_SCL_PORT GPIOH +#define I2C_INSTANCE_1_SCL_PIN GPIO_PIN_5 +#define I2C_INSTANCE_1_SCL_CLK_EN __HAL_RCC_GPIOH_CLK_ENABLE +#define I2C_INSTANCE_1_RESET_REG &RCC->APB1RSTR2 +#define I2C_INSTANCE_1_RESET_BIT RCC_APB1RSTR2_I2C5RST + +#define TOUCH_I2C_NUM 0 + +#endif // STM32U5A9J_DK_H_ diff --git a/core/embed/trezorhal/stm32u5/displays/dsi.c b/core/embed/trezorhal/stm32u5/displays/dsi.c new file mode 100644 index 000000000..cf31cf640 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/displays/dsi.c @@ -0,0 +1,1730 @@ +/** + ****************************************************************************** + * @file stm32u5x9j_discovery_lcd.c + * @author MCD Application Team + * @brief This file includes the driver for Liquid Crystal Display (LCD) + module + * mounted on MB1829A board (ARGB8888 color format). + @verbatim + 1. How To use this driver: + -------------------------- + - This driver is used to drive directly in command mode a LCD TFT using the + DSI interface. + The following IPs are implied : DSI Host IP block working + in conjunction to the LTDC controller. + - This driver is linked by construction to LCD. + + 2. Driver description: + ---------------------- + + Initialization steps: + o Initialize the LCD using the BSP_LCD_Init() function. You can select + display orientation with "Orientation" parameter (portrait, landscape, + portrait with 180 degrees rotation or landscape with 180 degrees + rotation). + o Call BSP_LCD_GetXSize() and BSP_LCD_GetYsize() to get respectively + width and height in pixels of LCD in the current orientation. + o Call BSP_LCD_SetBrightness() and BSP_LCD_GetBrightness() to + respectively set and get LCD brightness. + o Call BSP_LCD_SetActiveLayer() to select the current active layer. + o Call BSP_LCD_GetFormat() to get LCD pixel format supported. + + + Display on LCD: + o Call BSP_LCD_DisplayOn() and BSP_LCD_DisplayOff() to respectively + switch on and switch off the LCD display. + o First, check that frame buffer is available using + BSP_LCD_IsFrameBufferAvailable(). o When frame buffer is available, modify it + using following functions: o Call BSP_LCD_WritePixel() and BSP_LCD_ReadPixel() + to respectively write and read a pixel. o Call BSP_LCD_DrawHLine() to draw a + horizontal line. o Call BSP_LCD_DrawVLine() to draw a vertical line. o Call + BSP_LCD_DrawBitmap() to draw a bitmap. o Call BSP_LCD_FillRect() to draw a + rectangle. o Call BSP_LCD_FillRGBRect() to draw a rectangle with RGB buffer. + o Call BSP_LCD_Refresh() to refresh LCD display. + + + De-initialization steps: + o De-initialize the LCD using the BSP_LCD_DeInit() function. + + @endverbatim + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "colors.h" +#include "stdint.h" +#include "string.h" +#include STM32_HAL_H + +/* Common Error codes */ +#define BSP_ERROR_NONE 0 +#define BSP_ERROR_NO_INIT -1 +#define BSP_ERROR_WRONG_PARAM -2 +#define BSP_ERROR_BUSY -3 +#define BSP_ERROR_PERIPH_FAILURE -4 +#define BSP_ERROR_COMPONENT_FAILURE -5 +#define BSP_ERROR_UNKNOWN_FAILURE -6 +#define BSP_ERROR_UNKNOWN_COMPONENT -7 +#define BSP_ERROR_BUS_FAILURE -8 +#define BSP_ERROR_CLOCK_FAILURE -9 +#define BSP_ERROR_MSP_FAILURE -10 +#define BSP_ERROR_FEATURE_NOT_SUPPORTED -11 + +#define BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE (-102) +/* Button user interrupt priority */ +#define BSP_BUTTON_USER_IT_PRIORITY \ + 0x0FUL /* Default is lowest priority level */ + +/* LCD interrupt priorities */ +#define BSP_LCD_GFXMMU_IT_PRIORITY \ + 0x0FUL /* Default is lowest priority level \ + */ +#define BSP_LCD_LTDC_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ +#define BSP_LCD_DSI_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ + +/* HSPI RAM interrupt priority */ +#define BSP_HSPI_RAM_IT_PRIORITY 0x0FUL /* Default is lowest priority level */ +#define LCD_PIXEL_FORMAT_ARGB8888 \ + 0x00000000U /*!< ARGB8888 LTDC pixel format \ + */ +#define LCD_PIXEL_FORMAT_RGB888 0x00000001U /*!< RGB888 LTDC pixel format */ +#define LCD_PIXEL_FORMAT_RGB565 0x00000002U /*!< RGB565 LTDC pixel format */ +#define LCD_PIXEL_FORMAT_ARGB1555 \ + 0x00000003U /*!< ARGB1555 LTDC pixel format \ + */ +#define LCD_PIXEL_FORMAT_ARGB4444 \ + 0x00000004U /*!< ARGB4444 LTDC pixel format \ + */ +#define LCD_PIXEL_FORMAT_L8 0x00000005U /*!< L8 LTDC pixel format */ +#define LCD_PIXEL_FORMAT_AL44 0x00000006U /*!< AL44 LTDC pixel format */ +#define LCD_PIXEL_FORMAT_AL88 0x00000007U /*!< AL88 LTDC pixel format */ +/* LCD instances */ +#define LCD_INSTANCES_NBR 1U + +/* LCD orientations */ +#define LCD_ORIENTATION_PORTRAIT 0U +#define LCD_ORIENTATION_LANDSCAPE 1U +#define LCD_ORIENTATION_PORTRAIT_ROT180 2U +#define LCD_ORIENTATION_LANDSCAPE_ROT180 3U + +#define DSI_POWERON_GPIO_PORT GPIOI +#define DSI_POWERON_GPIO_PIN GPIO_PIN_5 +#define DSI_POWERON_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() + +#define DSI_RESET_GPIO_PORT GPIOD +#define DSI_RESET_GPIO_PIN GPIO_PIN_5 +#define DSI_RESET_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() + +#define VSYNC 1 +#define VBP 12 +#define VFP 50 +#define VACT 481 +#define HSYNC 2 +#define HBP 1 +#define HFP 1 +#define HACT 480 +#define LCD_WIDTH 480 +#define LCD_HEIGHT 480 + +#define PIXEL_PER_LINE 768U +#define BYTE_PER_PIXEL 4U /* ARGB8888 */ + +#include "gfxmmu_lut.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup STM32U5x9J_DISCOVERY + * @{ + */ + +/** @defgroup STM32U5x9J_DISCOVERY_LCD LCD + * @{ + */ + +/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Defines LCD Private Constants + * @{ + */ + +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Variables LCD Private Variables + * @{ + */ + +__attribute__((section(".fb1"))) +ALIGN_32BYTES(uint32_t PhysFrameBuffer0[184320]); +__attribute__((section(".fb2"))) +ALIGN_32BYTES(uint32_t PhysFrameBuffer1[184320]); + +__attribute__((section(".gfxmmu_table"))) +uint32_t gfxmmu_lut[2 * GFXMMU_LUT_SIZE]; +__attribute__((section(".framebuffer_select"))) uint32_t act_frame_buffer = 0; + +#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) +static uint32_t LcdGfxmmu_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; +#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) */ + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +static uint32_t LcdLtdc_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; +#endif /* (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) */ + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +static uint32_t LcdDsi_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; +#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 1) */ + +GFXMMU_HandleTypeDef hlcd_gfxmmu = {0}; +LTDC_HandleTypeDef hlcd_ltdc = {0}; +DSI_HandleTypeDef hlcd_dsi = {0}; +static DSI_VidCfgTypeDef DSIVidCfg = {0}; + +uint16_t window_x0 = 0; +uint16_t window_y0 = 0; +uint16_t window_x1 = 0; +uint16_t window_y1 = 0; +uint16_t cursor_x = 0; +uint16_t cursor_y = 0; + +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_FunctionPrototypes LCD Private + * Function Prototypes + * @{ + */ +static int32_t LCD_Init(void); +static int32_t LCD_DeInit(void); + +static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu); +static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu); +static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc); +static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc); +static void DSI_MspInit(DSI_HandleTypeDef *hdsi); +static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi); +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +static void DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi); +#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 1) */ +/** + * @} + */ + +/** @addtogroup STM32U5x9J_DISCOVERY_LCD_Exported_Functions + * @{ + */ +/** + * @brief Initialize the LCD. + * @param Instance LCD Instance. + * @param Orientation LCD_ORIENTATION_PORTRAIT, LCD_ORIENTATION_LANDSCAPE, + * LCD_ORIENTATION_PORTRAIT_ROT180 or + * LCD_ORIENTATION_LANDSCAPE_ROT180. + * @retval BSP status. + */ +int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation) { + int32_t status = BSP_ERROR_NONE; + + if ((Instance >= LCD_INSTANCES_NBR) || + (Orientation > LCD_ORIENTATION_LANDSCAPE_ROT180)) { + status = BSP_ERROR_WRONG_PARAM; + } else if ((Orientation == LCD_ORIENTATION_LANDSCAPE) || + (Orientation == LCD_ORIENTATION_LANDSCAPE_ROT180)) { + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } else { + if (LCD_Init() != 0) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + + return status; +} + +/** + * @brief De-Initialize the LCD. + * @param Instance LCD Instance. + * @retval BSP status. + */ +int32_t BSP_LCD_DeInit(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + if (LCD_DeInit() != 0) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + + return status; +} + +/** + * @brief Set the display on. + * @param Instance LCD Instance. + * @retval BSP status. + */ +int32_t BSP_LCD_DisplayOn(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Set the display on */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, + DSI_SET_DISPLAY_ON, 0x00) != HAL_OK) { + status = BSP_ERROR_WRONG_PARAM; + } + } + + return status; +} + +/** + * @brief Set the display off. + * @param Instance LCD Instance. + * @retval BSP status. + */ +int32_t BSP_LCD_DisplayOff(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Set the display off */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, + DSI_SET_DISPLAY_OFF, 0x00) != HAL_OK) { + status = BSP_ERROR_WRONG_PARAM; + } + } + + return status; +} + +/** + * @brief Set the display brightness. + * @param Instance LCD Instance. + * @param Brightness [00: Min (black), 100 Max]. + * @retval BSP status. + */ +int32_t BSP_LCD_SetBrightness(uint32_t Instance, uint32_t Brightness) { + int32_t status; + + if ((Instance >= LCD_INSTANCES_NBR) || (Brightness > 100U)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } + + return status; +} + +/** + * @brief Get the display brightness. + * @param Instance LCD Instance. + * @param Brightness [00: Min (black), 100 Max]. + * @retval BSP status. + */ +int32_t BSP_LCD_GetBrightness(uint32_t Instance, uint32_t *Brightness) { + int32_t status; + + if ((Instance >= LCD_INSTANCES_NBR) || (Brightness == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } + + return status; +} + +/** + * @brief Get the LCD X size. + * @param Instance LCD Instance. + * @param Xsize LCD X size. + * @retval BSP status. + */ +int32_t BSP_LCD_GetXSize(uint32_t Instance, uint32_t *Xsize) { + int32_t status = BSP_ERROR_NONE; + + if ((Instance >= LCD_INSTANCES_NBR) || (Xsize == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Get the display Xsize */ + *Xsize = LCD_WIDTH; + } + + return status; +} + +/** + * @brief Get the LCD Y size. + * @param Instance LCD Instance. + * @param Ysize LCD Y size. + * @retval BSP status. + */ +int32_t BSP_LCD_GetYSize(uint32_t Instance, uint32_t *Ysize) { + int32_t status = BSP_ERROR_NONE; + + if ((Instance >= LCD_INSTANCES_NBR) || (Ysize == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Get the display Ysize */ + *Ysize = LCD_HEIGHT; + } + + return status; +} + +/** + * @brief Set the LCD active layer. + * @param Instance LCD Instance. + * @param LayerIndex Active layer index. + * @retval BSP status. + */ +int32_t BSP_LCD_SetActiveLayer(uint32_t Instance, uint32_t LayerIndex) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Nothing to do */ + UNUSED(LayerIndex); + } + + return status; +} + +/** + * @brief Get pixel format supported by LCD. + * @param Instance LCD Instance. + * @param Format Pointer on pixel format. + * @retval BSP status. + */ +int32_t BSP_LCD_GetFormat(uint32_t Instance, uint32_t *Format) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Get pixel format supported by LCD */ + *Format = LCD_PIXEL_FORMAT_ARGB8888; + } + + return status; +} + +void MX_GFXMMU_Reinit(GFXMMU_HandleTypeDef *hgfxmmu) { + /* Initialize GFXMMU */ + hgfxmmu->Instance = GFXMMU; + hgfxmmu->Init.BlocksPerLine = GFXMMU_192BLOCKS; + hgfxmmu->Init.DefaultValue = 0xFFFFFFFFU; + hgfxmmu->Init.Buffers.Buf0Address = (uint32_t)PhysFrameBuffer0; + hgfxmmu->Init.Buffers.Buf1Address = (uint32_t)PhysFrameBuffer1; + hgfxmmu->Init.Buffers.Buf2Address = 0; + hgfxmmu->Init.Buffers.Buf3Address = 0; +#if defined(GFXMMU_CR_CE) + hgfxmmu->Init.CachePrefetch.Activation = DISABLE; + hgfxmmu->Init.CachePrefetch.CacheLock = GFXMMU_CACHE_LOCK_DISABLE; + hgfxmmu->Init.CachePrefetch.CacheLockBuffer = + GFXMMU_CACHE_LOCK_BUFFER0; /* NU */ + hgfxmmu->Init.CachePrefetch.CacheForce = GFXMMU_CACHE_FORCE_ENABLE; /* NU */ + hgfxmmu->Init.CachePrefetch.OutterBufferability = + GFXMMU_OUTTER_BUFFERABILITY_DISABLE; + hgfxmmu->Init.CachePrefetch.OutterCachability = + GFXMMU_OUTTER_CACHABILITY_DISABLE; + hgfxmmu->Init.CachePrefetch.Prefetch = GFXMMU_PREFETCH_DISABLE; +#endif /* GFXMMU_CR_CE */ +#if defined(GFXMMU_CR_ACE) + hgfxmmu->Init.AddressCache.Activation = DISABLE; + hgfxmmu->Init.AddressCache.AddressCacheLockBuffer = + GFXMMU_ADDRESSCACHE_LOCK_BUFFER0; +#endif /* GFXMMU_CR_ACE */ + hgfxmmu->Init.Interrupts.Activation = DISABLE; + hgfxmmu->Init.Interrupts.UsedInterrupts = GFXMMU_AHB_MASTER_ERROR_IT; /* NU */ +} + +/** + * @brief MX GFXMMU initialization. + * @param hgfxmmu GFXMMU handle. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_GFXMMU_Init(GFXMMU_HandleTypeDef *hgfxmmu) { + MX_GFXMMU_Reinit(hgfxmmu); + return HAL_GFXMMU_Init(hgfxmmu); +} + +/** + * @brief MX LTDC clock configuration. + * @param hltdc LTDC handle. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_LTDC_ClockConfig(LTDC_HandleTypeDef *hltdc) { + RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* Start and configurre PLL3 */ + /* HSE = 16MHZ */ + /* 16/(M=4) = 4MHz input (min) */ + /* 4*(N=125) = 500MHz VCO (almost max) */ + /* 500/(P=8) = 62.5 for DSI ie exactly the lane byte clock*/ + /* 500/(R=24) = 20.83 for LTDC exact match with DSI bandwidth */ + PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + PLL3InitPeriph.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; + PLL3InitPeriph.PLL3.PLL3M = 4; + PLL3InitPeriph.PLL3.PLL3N = 125; + PLL3InitPeriph.PLL3.PLL3P = 8; + PLL3InitPeriph.PLL3.PLL3Q = 8; + PLL3InitPeriph.PLL3.PLL3R = 24; + PLL3InitPeriph.PLL3.PLL3FRACN = 0; + PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; + PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; + PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + return HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); +} + +void MX_LTDC_Reinit(LTDC_HandleTypeDef *hltdc) { + /* LTDC initialization */ + hltdc->Instance = LTDC; + hltdc->Init.HSPolarity = LTDC_HSPOLARITY_AL; + hltdc->Init.VSPolarity = LTDC_VSPOLARITY_AL; + hltdc->Init.DEPolarity = LTDC_DEPOLARITY_AL; + hltdc->Init.PCPolarity = LTDC_PCPOLARITY_IPC; + hltdc->Init.HorizontalSync = HSYNC - 1; + hltdc->Init.AccumulatedHBP = HSYNC + HBP - 1; + hltdc->Init.AccumulatedActiveW = HACT + HBP + HSYNC - 1; + hltdc->Init.TotalWidth = HACT + HBP + HFP + HSYNC - 1; + hltdc->Init.Backcolor.Red = 0; /* Not used default value */ + hltdc->Init.Backcolor.Green = 0; /* Not used default value */ + hltdc->Init.Backcolor.Blue = 0; /* Not used default value */ + hltdc->Init.Backcolor.Reserved = 0xFF; + + HAL_LTDCEx_StructInitFromVideoConfig(&hlcd_ltdc, &DSIVidCfg); +} + +/** + * @brief MX LTDC initialization. + * @param hltdc LTDC handle. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_LTDC_Init(LTDC_HandleTypeDef *hltdc) { + MX_LTDC_Reinit(hltdc); + + return HAL_LTDC_Init(hltdc); +} + +// HAL_StatusTypeDef MX_LTDC_ReConfigLayer(LTDC_HandleTypeDef *hltdc, uint32_t +// LayerIndex) +//{ +// LTDC_LayerCfgTypeDef LayerCfg = {0}; +// +///* LTDC layer configuration */ +// LayerCfg.WindowX0 = 0; +// LayerCfg.WindowX1 = LCD_WIDTH; +// LayerCfg.WindowY0 = 1; +// LayerCfg.WindowY1 = (uint32_t)LCD_HEIGHT + 1UL; +// LayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888; +// LayerCfg.Alpha = 0xFF; /* NU default value */ +// LayerCfg.Alpha0 = 0; /* NU default value */ +// LayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; /* Not Used: default +// value */ LayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; /* Not +// Used: default value */ LayerCfg.FBStartAdress = +// GFXMMU_VIRTUAL_BUFFER0_BASE; LayerCfg.ImageWidth = PIXEL_PER_LINE; /* +// Number of pixels per line in virtual frame buffer */ LayerCfg.ImageHeight = +// LCD_HEIGHT; LayerCfg.Backcolor.Red = 0; /* Not Used: default value */ +// LayerCfg.Backcolor.Green = 0; /* Not Used: default value */ +// LayerCfg.Backcolor.Blue = 0; /* Not Used: default value */ +// LayerCfg.Bac +// return HAL_LTDC_ConfigLayer(hltdc, &LayerCfg, LayerIndex);kcolor.Reserved = +// 0xFF; +//} + +/** + * @brief MX LTDC layer configuration. + * @param hltdc LTDC handle. + * @param LayerIndex LTDC layer index. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, + uint32_t LayerIndex, + uint32_t fb_addr) { + LTDC_LayerCfgTypeDef LayerCfg = {0}; + + /* LTDC layer configuration */ + LayerCfg.WindowX0 = 0; + LayerCfg.WindowX1 = LCD_WIDTH; + LayerCfg.WindowY0 = 1; + LayerCfg.WindowY1 = (uint32_t)LCD_HEIGHT + 1UL; + LayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888; + LayerCfg.Alpha = 0xFF; /* NU default value */ + LayerCfg.Alpha0 = 0; /* NU default value */ + LayerCfg.BlendingFactor1 = + LTDC_BLENDING_FACTOR1_PAxCA; /* Not Used: default value */ + LayerCfg.BlendingFactor2 = + LTDC_BLENDING_FACTOR2_PAxCA; /* Not Used: default value */ + LayerCfg.FBStartAdress = fb_addr; + LayerCfg.ImageWidth = + PIXEL_PER_LINE; /* Number of pixels per line in virtual frame buffer */ + LayerCfg.ImageHeight = LCD_HEIGHT; + LayerCfg.Backcolor.Red = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Green = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Blue = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Reserved = 0xFF; + return HAL_LTDC_ConfigLayer(hltdc, &LayerCfg, LayerIndex); +} + +/** + * @brief MX DSI initialization. + * @param hdsi DSI handle. + * @retval HAL status. + */ +HAL_StatusTypeDef MX_DSI_Reinit(DSI_HandleTypeDef *hdsi) { + /* DSI initialization */ + hdsi->Instance = DSI; + hdsi->Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; + /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */ + /* We want TX escape clock at around 20MHz and under 20MHz so clock division + * is set to 4 */ + hdsi->Init.TXEscapeCkdiv = 4; + hdsi->Init.NumberOfLanes = DSI_TWO_DATA_LANES; + hdsi->Init.PHYFrequencyRange = DSI_DPHY_FRANGE_450MHZ_510MHZ; + hdsi->Init.PHYLowPowerOffset = 0; + + /* Configure the DSI for Video mode */ + DSIVidCfg.VirtualChannelID = 0; + DSIVidCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; + DSIVidCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; + DSIVidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; + DSIVidCfg.ColorCoding = DSI_RGB888; + DSIVidCfg.Mode = DSI_VID_MODE_BURST; + DSIVidCfg.PacketSize = LCD_WIDTH; + DSIVidCfg.NullPacketSize = 0xFFFU; + DSIVidCfg.HorizontalSyncActive = HSYNC * 3; + DSIVidCfg.HorizontalBackPorch = HBP * 3; + DSIVidCfg.HorizontalLine = (HACT + HSYNC + HBP + HFP) * 3; + DSIVidCfg.VerticalSyncActive = VSYNC; + DSIVidCfg.VerticalBackPorch = VBP; + DSIVidCfg.VerticalFrontPorch = VFP; + DSIVidCfg.VerticalActive = VACT; + DSIVidCfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE; + DSIVidCfg.LPLargestPacketSize = 64; + /* Specify for each region of the video frame, if the transmission of command + * in LP mode is allowed in this region */ + /* while streaming is active in video mode */ + DSIVidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; + DSIVidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; + DSIVidCfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; + DSIVidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; + DSIVidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; + DSIVidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; + DSIVidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_ENABLE; + DSIVidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE; + + return HAL_OK; +} + +/** + * @brief MX DSI initialization. + * @param hdsi DSI handle. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_DSI_Init(DSI_HandleTypeDef *hdsi) { + DSI_PLLInitTypeDef PLLInit = {0}; + + /* DSI initialization */ + hdsi->Instance = DSI; + hdsi->Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; + /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */ + /* We want TX escape clock at around 20MHz and under 20MHz so clock division + * is set to 4 */ + hdsi->Init.TXEscapeCkdiv = 4; + hdsi->Init.NumberOfLanes = DSI_TWO_DATA_LANES; + hdsi->Init.PHYFrequencyRange = DSI_DPHY_FRANGE_450MHZ_510MHZ; + hdsi->Init.PHYLowPowerOffset = 0; + + PLLInit.PLLNDIV = 125; + PLLInit.PLLIDF = 4; + PLLInit.PLLODF = 2; + PLLInit.PLLVCORange = DSI_DPHY_VCO_FRANGE_800MHZ_1GHZ; + PLLInit.PLLChargePump = DSI_PLL_CHARGE_PUMP_2000HZ_4400HZ; + PLLInit.PLLTuning = DSI_PLL_LOOP_FILTER_2000HZ_4400HZ; + + if (HAL_DSI_Init(hdsi, &PLLInit) != HAL_OK) { + return HAL_ERROR; + } + + if (HAL_DSI_SetGenericVCID(&hlcd_dsi, 0) != HAL_OK) { + return HAL_ERROR; + } + + /* Configure the DSI for Video mode */ + DSIVidCfg.VirtualChannelID = 0; + DSIVidCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; + DSIVidCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; + DSIVidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; + DSIVidCfg.ColorCoding = DSI_RGB888; + DSIVidCfg.Mode = DSI_VID_MODE_BURST; + DSIVidCfg.PacketSize = LCD_WIDTH; + DSIVidCfg.NullPacketSize = 0xFFFU; + DSIVidCfg.HorizontalSyncActive = HSYNC * 3; + DSIVidCfg.HorizontalBackPorch = HBP * 3; + DSIVidCfg.HorizontalLine = (HACT + HSYNC + HBP + HFP) * 3; + DSIVidCfg.VerticalSyncActive = VSYNC; + DSIVidCfg.VerticalBackPorch = VBP; + DSIVidCfg.VerticalFrontPorch = VFP; + DSIVidCfg.VerticalActive = VACT; + DSIVidCfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE; + DSIVidCfg.LPLargestPacketSize = 64; + /* Specify for each region of the video frame, if the transmission of command + * in LP mode is allowed in this region */ + /* while streaming is active in video mode */ + DSIVidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; + DSIVidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; + DSIVidCfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; + DSIVidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; + DSIVidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; + DSIVidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; + DSIVidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_ENABLE; + DSIVidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE; + + /* Drive the display */ + if (HAL_DSI_ConfigVideoMode(&hlcd_dsi, &DSIVidCfg) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief MX DMA2D initialization. + * @param hdma2d DMA2D handle. + * @param Mode DMA2D transfer mode. + * @param OffLine DMA2D output offset. + * @retval HAL status. + */ +__weak HAL_StatusTypeDef MX_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d, + uint32_t Mode, uint32_t OffLine) { + /* Register to memory mode with ARGB8888 as color Mode */ + hdma2d->Instance = DMA2D; + hdma2d->Init.Mode = Mode; + hdma2d->Init.ColorMode = DMA2D_OUTPUT_ARGB8888; + hdma2d->Init.OutputOffset = OffLine; + hdma2d->Init.AlphaInverted = DMA2D_REGULAR_ALPHA; + hdma2d->Init.RedBlueSwap = DMA2D_RB_REGULAR; + hdma2d->Init.BytesSwap = DMA2D_BYTES_REGULAR; + hdma2d->Init.LineOffsetMode = DMA2D_LOM_PIXELS; + + /* DMA2D Initialization */ + return HAL_DMA2D_Init(hdma2d); +} + +#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) +/** + * @brief Register Default LCD GFXMMU Msp Callbacks + * @retval BSP status + */ +int32_t BSP_LCD_GFXMMU_RegisterDefaultMspCallbacks(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_GFXMMU_RESET_HANDLE_STATE(&hlcd_gfxmmu); + + /* Register default MspInit/MspDeInit Callback */ + if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, HAL_GFXMMU_MSPINIT_CB_ID, + GFXMMU_MspInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, + HAL_GFXMMU_MSPDEINIT_CB_ID, + GFXMMU_MspDeInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdGfxmmu_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} + +/** + * @brief Register LCD GFXMMU Msp Callback + * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions + * @retval BSP status + */ +int32_t BSP_LCD_GFXMMU_RegisterMspCallbacks(uint32_t Instance, + BSP_LCD_GFXMMU_Cb_t *Callback) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_GFXMMU_RESET_HANDLE_STATE(&hlcd_gfxmmu); + + /* Register MspInit/MspDeInit Callbacks */ + if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, HAL_GFXMMU_MSPINIT_CB_ID, + Callback->pMspGfxmmuInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_GFXMMU_RegisterCallback( + &hlcd_gfxmmu, HAL_GFXMMU_MSPDEINIT_CB_ID, + Callback->pMspGfxmmuDeInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdGfxmmu_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} +#endif /* USE_HAL_GFXMMU_REGISTER_CALLBACKS */ + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +/** + * @brief Register Default LCD LTDC Msp Callbacks + * @retval BSP status + */ +int32_t BSP_LCD_LTDC_RegisterDefaultMspCallbacks(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_LTDC_RESET_HANDLE_STATE(&hlcd_ltdc); + + /* Register default MspInit/MspDeInit Callback */ + if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPINIT_CB_ID, + LTDC_MspInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPDEINIT_CB_ID, + LTDC_MspDeInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdLtdc_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} + +/** + * @brief Register LCD LTDC Msp Callback + * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions + * @retval BSP status + */ +int32_t BSP_LCD_LTDC_RegisterMspCallbacks(uint32_t Instance, + BSP_LCD_LTDC_Cb_t *Callback) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_LTDC_RESET_HANDLE_STATE(&hlcd_ltdc); + + /* Register MspInit/MspDeInit Callbacks */ + if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPINIT_CB_ID, + Callback->pMspLtdcInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPDEINIT_CB_ID, + Callback->pMspLtdcDeInitCb) != + HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdLtdc_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +/** + * @brief Register Default LCD DSI Msp Callbacks + * @retval BSP status + */ +int32_t BSP_LCD_DSI_RegisterDefaultMspCallbacks(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_DSI_RESET_HANDLE_STATE(&hlcd_dsi); + + /* Register default MspInit/MspDeInit Callback */ + if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPINIT_CB_ID, + DSI_MspInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPDEINIT_CB_ID, + DSI_MspDeInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdDsi_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} + +/** + * @brief Register LCD DSI Msp Callback + * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions + * @retval BSP status + */ +int32_t BSP_LCD_DSI_RegisterMspCallbacks(uint32_t Instance, + BSP_LCD_DSI_Cb_t *Callback) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_DSI_RESET_HANDLE_STATE(&hlcd_dsi); + + /* Register MspInit/MspDeInit Callbacks */ + if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPINIT_CB_ID, + Callback->pMspDsiInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPDEINIT_CB_ID, + Callback->pMspDsiDeInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdDsi_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +/** + * @brief Register Default LCD DMA2D Msp Callbacks + * @retval BSP status + */ +int32_t BSP_LCD_DMA2D_RegisterDefaultMspCallbacks(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_DMA2D_RESET_HANDLE_STATE(&hlcd_dma2d); + + /* Register default MspInit/MspDeInit Callback */ + if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, HAL_DMA2D_MSPINIT_CB_ID, + DMA2D_MspInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, + HAL_DMA2D_MSPDEINIT_CB_ID, + DMA2D_MspDeInit) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdDma2d_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} + +/** + * @brief Register LCD DMA2D Msp Callback + * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions + * @retval BSP status + */ +int32_t BSP_LCD_DMA2D_RegisterMspCallbacks(uint32_t Instance, + BSP_LCD_DMA2D_Cb_t *Callback) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= LCD_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + __HAL_DMA2D_RESET_HANDLE_STATE(&hlcd_dma2d); + + /* Register MspInit/MspDeInit Callbacks */ + if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, HAL_DMA2D_MSPINIT_CB_ID, + Callback->pMspDma2dInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else if (HAL_DMA2D_RegisterCallback( + &hlcd_dma2d, HAL_DMA2D_MSPDEINIT_CB_ID, + Callback->pMspDma2dDeInitCb) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + LcdDma2d_IsMspCbValid[Instance] = 1U; + } + } + + /* BSP status */ + return status; +} +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Functions LCD Private Functions + * @{ + */ + +/** + * @brief Initialize LCD. + * @retval BSP status. + */ +static int32_t LCD_Init(void) { + int32_t status = BSP_ERROR_NONE; + uint32_t ErrorNumber = 0; + DSI_PHY_TimerTypeDef PhyTimers = {0}; + DSI_HOST_TimeoutTypeDef HostTimeouts = {0}; + + /***************/ + /* GFXMMU init */ + /***************/ +#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) + GFXMMU_MspInit(&hlcd_gfxmmu); +#else + /* Register the GFXMMU MSP Callbacks */ + if (LcdGfxmmu_IsMspCbValid[0] == 0U) { + if (BSP_LCD_GFXMMU_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } +#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ + + if (status == BSP_ERROR_NONE) { + /* GFXMMU peripheral initialization */ + if (MX_GFXMMU_Init(&hlcd_gfxmmu) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } + /* Initialize LUT */ + else if (HAL_GFXMMU_ConfigLut(&hlcd_gfxmmu, 0, LCD_WIDTH, + (uint32_t)&gfxmmu_lut) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + /* Disable non visible lines : from line 480 to 1023 */ + if (HAL_OK != HAL_GFXMMU_DisableLutLines(&hlcd_gfxmmu, LCD_WIDTH, 544)) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + } + + /************/ + /* DSI init */ + /************/ + if (status == BSP_ERROR_NONE) { +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 0) + DSI_MspInit(&hlcd_dsi); +#else + /* Register the DSI MSP Callbacks */ + if (LcdDsi_IsMspCbValid[0] == 0U) { + if (BSP_LCD_DSI_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } +#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 0) */ + + if (status == BSP_ERROR_NONE) { + /* DSI peripheral initialization */ + if (MX_DSI_Init(&hlcd_dsi) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + } + + /*********************/ + /* LCD configuration */ + /*********************/ + if (status == BSP_ERROR_NONE) { + PhyTimers.ClockLaneHS2LPTime = 11; + PhyTimers.ClockLaneLP2HSTime = 40; + PhyTimers.DataLaneHS2LPTime = 12; + PhyTimers.DataLaneLP2HSTime = 23; + PhyTimers.DataLaneMaxReadTime = 0; + PhyTimers.StopWaitTime = 7; + + if (HAL_DSI_ConfigPhyTimer(&hlcd_dsi, &PhyTimers) != HAL_OK) { + return 6; + } + + HostTimeouts.TimeoutCkdiv = 1; + HostTimeouts.HighSpeedTransmissionTimeout = 0; + HostTimeouts.LowPowerReceptionTimeout = 0; + HostTimeouts.HighSpeedReadTimeout = 0; + HostTimeouts.LowPowerReadTimeout = 0; + HostTimeouts.HighSpeedWriteTimeout = 0; + HostTimeouts.HighSpeedWritePrespMode = 0; + HostTimeouts.LowPowerWriteTimeout = 0; + HostTimeouts.BTATimeout = 0; + + if (HAL_DSI_ConfigHostTimeouts(&hlcd_dsi, &HostTimeouts) != HAL_OK) { + return 7; + } + + if (HAL_DSI_ConfigFlowControl(&hlcd_dsi, DSI_FLOW_CONTROL_BTA) != HAL_OK) { + return 7; + } + + /* Enable the DSI host */ + __HAL_DSI_ENABLE(&hlcd_dsi); + + /*************/ + /* LTDC init */ + /*************/ + if (status == BSP_ERROR_NONE) { + if (MX_LTDC_ClockConfig(&hlcd_ltdc) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) + LTDC_MspInit(&hlcd_ltdc); +#else + /* Register the LTDC MSP Callbacks */ + if (LcdLtdc_IsMspCbValid[0] == 0U) { + if (BSP_LCD_LTDC_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } +#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ + + if (status == BSP_ERROR_NONE) { + /* LTDC peripheral initialization */ + if (MX_LTDC_Init(&hlcd_ltdc) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } else { + if (MX_LTDC_ConfigLayer(&hlcd_ltdc, LTDC_LAYER_1, + GFXMMU_VIRTUAL_BUFFER0_BASE_S) != HAL_OK) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + } + } + } + + /* Start DSI */ + if (HAL_DSI_Start(&(hlcd_dsi)) != HAL_OK) { + return 8; + } + + /* CMD Mode */ + uint8_t InitParam1[3] = {0xFF, 0x83, 0x79}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB9, + InitParam1) != HAL_OK) { + ErrorNumber++; + } + + /* SETPOWER */ + uint8_t InitParam2[16] = {0x44, 0x1C, 0x1C, 0x37, 0x57, 0x90, 0xD0, 0xE2, + 0x58, 0x80, 0x38, 0x38, 0xF8, 0x33, 0x34, 0x42}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 16, 0xB1, + InitParam2) != HAL_OK) { + ErrorNumber++; + } + + /* SETDISP */ + uint8_t InitParam3[9] = {0x80, 0x14, 0x0C, 0x30, 0x20, + 0x50, 0x11, 0x42, 0x1D}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 9, 0xB2, + InitParam3) != HAL_OK) { + ErrorNumber++; + } + + /* Set display cycle timing */ + uint8_t InitParam4[10] = {0x01, 0xAA, 0x01, 0xAF, 0x01, + 0xAF, 0x10, 0xEA, 0x1C, 0xEA}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 10, 0xB4, + InitParam4) != HAL_OK) { + ErrorNumber++; + } + + /* SETVCOM */ + uint8_t InitParam5[4] = {00, 00, 00, 0xC0}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, 0xC7, + InitParam5) != HAL_OK) { + ErrorNumber++; + } + + /* Set Panel Related Registers */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xCC, + 0x02) != HAL_OK) { + ErrorNumber++; + } + + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xD2, + 0x77) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam6[37] = {0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x32, + 0x10, 0x01, 0x00, 0x01, 0x03, 0x72, 0x03, 0x72, + 0x00, 0x08, 0x00, 0x08, 0x33, 0x33, 0x05, 0x05, + 0x37, 0x05, 0x05, 0x37, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x01, 0x00, 0x0E}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 37, 0xD3, + InitParam6) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam7[34] = { + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, + 0x23, 0x22, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 34, 0xD5, + InitParam7) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam8[32] = {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, + 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, + 0x20, 0x21, 0x22, 0x23, 0x18, 0x18, 0x18, 0x18}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 35, 0xD6, + InitParam8) != HAL_OK) { + ErrorNumber++; + } + + /* SET GAMMA */ + uint8_t InitParam9[42] = { + 0x00, 0x16, 0x1B, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0D, 0x0F, + 0x18, 0x0E, 0x11, 0x12, 0x11, 0x14, 0x07, 0x12, 0x13, 0x18, 0x00, + 0x17, 0x1C, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0C, 0x0F, 0x18, + 0x0E, 0x11, 0x14, 0x11, 0x12, 0x07, 0x12, 0x14, 0x18}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xE0, + InitParam9) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam10[3] = {0x2C, 0x2C, 00}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB6, + InitParam10) != HAL_OK) { + ErrorNumber++; + } + + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, + 0x00) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam11[] = { + 0x01, 0x00, 0x07, 0x0F, 0x16, 0x1F, 0x27, 0x30, 0x38, 0x40, 0x47, + 0x4E, 0x56, 0x5D, 0x65, 0x6D, 0x74, 0x7D, 0x84, 0x8A, 0x90, 0x99, + 0xA1, 0xA9, 0xB0, 0xB6, 0xBD, 0xC4, 0xCD, 0xD4, 0xDD, 0xE5, 0xEC, + 0xF3, 0x36, 0x07, 0x1C, 0xC0, 0x1B, 0x01, 0xF1, 0x34, 0x00}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam11) != HAL_OK) { + ErrorNumber++; + } + + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, + 0x01) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam12[] = { + 0x00, 0x08, 0x0F, 0x16, 0x1F, 0x28, 0x31, 0x39, 0x41, 0x48, 0x51, + 0x59, 0x60, 0x68, 0x70, 0x78, 0x7F, 0x87, 0x8D, 0x94, 0x9C, 0xA3, + 0xAB, 0xB3, 0xB9, 0xC1, 0xC8, 0xD0, 0xD8, 0xE0, 0xE8, 0xEE, 0xF5, + 0x3B, 0x1A, 0xB6, 0xA0, 0x07, 0x45, 0xC5, 0x37, 0x00}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam12) != HAL_OK) { + ErrorNumber++; + } + + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, + 0x02) != HAL_OK) { + ErrorNumber++; + } + + uint8_t InitParam13[42] = { + 0x00, 0x09, 0x0F, 0x18, 0x21, 0x2A, 0x34, 0x3C, 0x45, 0x4C, 0x56, + 0x5E, 0x66, 0x6E, 0x76, 0x7E, 0x87, 0x8E, 0x95, 0x9D, 0xA6, 0xAF, + 0xB7, 0xBD, 0xC5, 0xCE, 0xD5, 0xDF, 0xE7, 0xEE, 0xF4, 0xFA, 0xFF, + 0x0C, 0x31, 0x83, 0x3C, 0x5B, 0x56, 0x1E, 0x5A, 0xFF}; + if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam13) != HAL_OK) { + ErrorNumber++; + } + + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, + 0x00) != HAL_OK) { + ErrorNumber++; + } + + /* Exit Sleep Mode*/ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x11, + 0x00) != HAL_OK) { + ErrorNumber++; + } + + HAL_Delay(120); + + /* Display On */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x29, + 0x00) != HAL_OK) { + ErrorNumber++; + } + + HAL_Delay(120); + + if (ErrorNumber != 0U) { + status = BSP_ERROR_PERIPH_FAILURE; + } + } + + return status; +} + +/** + * @brief De-Initialize LCD. + * @retval BSP status. + */ +static int32_t LCD_DeInit(void) { + int32_t status = BSP_ERROR_NONE; + uint32_t ErrorNumber = 0; + + /* Disable DSI wrapper */ + __HAL_DSI_WRAPPER_DISABLE(&hlcd_dsi); + + /* Set display off */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, + DSI_SET_DISPLAY_OFF, 0x00) != HAL_OK) { + ErrorNumber++; + } + + /* Wait before entering in sleep mode */ + HAL_Delay(2000); + + /* Put LCD in sleep mode */ + if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, + DSI_ENTER_SLEEP_MODE, 0x0) != HAL_OK) { + ErrorNumber++; + } + + HAL_Delay(120); + + /* De-initialize DSI */ + if (HAL_DSI_DeInit(&hlcd_dsi) != HAL_OK) { + ErrorNumber++; + } +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 0) + DSI_MspDeInit(&hlcd_dsi); +#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 0) */ + + /* De-initialize LTDC */ + if (HAL_LTDC_DeInit(&hlcd_ltdc) != HAL_OK) { + ErrorNumber++; + } +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) + LTDC_MspDeInit(&hlcd_ltdc); +#endif /* (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) */ + + /* De-initialize GFXMMU */ + if (HAL_GFXMMU_DeInit(&hlcd_gfxmmu) != HAL_OK) { + ErrorNumber++; + } +#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) + GFXMMU_MspDeInit(&hlcd_gfxmmu); +#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ + + if (ErrorNumber != 0U) { + status = BSP_ERROR_PERIPH_FAILURE; + } + + return status; +} + +/** + * @brief Initialize GFXMMU MSP. + * @param hgfxmmu GFXMMU handle + * @retval None + */ +static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(hgfxmmu); + + /* GFXMMU clock enable */ + __HAL_RCC_GFXMMU_CLK_ENABLE(); + + /* Enable GFXMMU interrupt */ + HAL_NVIC_SetPriority(GFXMMU_IRQn, BSP_LCD_GFXMMU_IT_PRIORITY, 0); + HAL_NVIC_EnableIRQ(GFXMMU_IRQn); +} + +/** + * @brief De-Initialize GFXMMU MSP. + * @param hgfxmmu GFXMMU handle + * @retval None + */ +static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(hgfxmmu); + + /* Disable GFXMMU interrupt */ + HAL_NVIC_DisableIRQ(GFXMMU_IRQn); + + /* GFXMMU clock disable */ + __HAL_RCC_GFXMMU_CLK_DISABLE(); +} + +/** + * @brief Initialize LTDC MSP. + * @param hltdc LTDC handle + * @retval None + */ +static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* Enable LCD clock */ + __HAL_RCC_LTDC_CLK_ENABLE(); + + /* Enable LTDC interrupt */ + HAL_NVIC_SetPriority(LTDC_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); + HAL_NVIC_EnableIRQ(LTDC_IRQn); + + HAL_NVIC_SetPriority(LTDC_ER_IRQn, BSP_LCD_LTDC_IT_PRIORITY, 0); + HAL_NVIC_EnableIRQ(LTDC_ER_IRQn); +} + +/** + * @brief De-Initialize LTDC MSP. + * @param hltdc LTDC handle + * @retval None + */ +static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* Disable LTDC interrupts */ + HAL_NVIC_DisableIRQ(LTDC_ER_IRQn); + HAL_NVIC_DisableIRQ(LTDC_IRQn); + + /* LTDC clock disable */ + __HAL_RCC_LTDC_CLK_DISABLE(); +} + +/** + * @brief Initialize DSI MSP. + * @param hdsi DSI handle + * @retval None + */ +static void DSI_MspInit(DSI_HandleTypeDef *hdsi) { + RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; + RCC_PeriphCLKInitTypeDef DSIPHYInitPeriph = {0}; + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + UNUSED(hdsi); + + /* Enable GPIOI & GPIOD clocks */ + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOI_CLK_ENABLE(); + + /* Configure DSI Reset pin */ + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* Configure LCD Backlight Pin */ + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + + /* Enable DSI clock */ + __HAL_RCC_DSI_CLK_ENABLE(); + + /** ################ Set DSI clock to D-PHY source clock ################## + * **/ + + /* Start and configurre PLL3 */ + /* HSE = 16MHZ */ + /* 16/(M=4) = 4MHz input (min) */ + /* 4*(N=125) = 500MHz VCO (almost max) */ + /* 500/(P=8) = 62.5 for DSI ie exactly the lane byte clock*/ + + PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; + PLL3InitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; + PLL3InitPeriph.PLL3.PLL3M = 4; + PLL3InitPeriph.PLL3.PLL3N = 125; + PLL3InitPeriph.PLL3.PLL3P = 8; + PLL3InitPeriph.PLL3.PLL3Q = 8; + PLL3InitPeriph.PLL3.PLL3R = 24; + PLL3InitPeriph.PLL3.PLL3FRACN = 0; + PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; + PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; + PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + (void)HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); + + __HAL_RCC_DSI_CLK_ENABLE(); + + /* Switch to D-PHY source clock */ + /* Enable the DSI host */ + hlcd_dsi.Instance = DSI; + + __HAL_DSI_ENABLE(&hlcd_dsi); + + /* Enable the DSI PLL */ + __HAL_DSI_PLL_ENABLE(&hlcd_dsi); + + HAL_Delay(1); + + /* Enable the clock lane and the digital section of the D-PHY */ + hlcd_dsi.Instance->PCTLR |= (DSI_PCTLR_CKE | DSI_PCTLR_DEN); + + /* Set the TX escape clock division factor */ + hlcd_dsi.Instance->CCR = 4; + + HAL_Delay(1); + + /* Config DSI Clock to DSI PHY */ + DSIPHYInitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; + DSIPHYInitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_DSIPHY; + + (void)HAL_RCCEx_PeriphCLKConfig(&DSIPHYInitPeriph); + + /* Reset */ + HAL_Delay(11); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET); + HAL_Delay(150); + + /* Reset the TX escape clock division factor */ + hlcd_dsi.Instance->CCR &= ~DSI_CCR_TXECKDIV; + + /* Disable the DSI PLL */ + __HAL_DSI_PLL_DISABLE(&hlcd_dsi); + + /* Disable the DSI host */ + __HAL_DSI_DISABLE(&hlcd_dsi); + + /** ######################################################################### + * **/ + + /* Enable DSI NVIC interrupt */ + /* Default is lowest priority level */ + HAL_NVIC_SetPriority(DSI_IRQn, 0x0FUL, 0); + HAL_NVIC_EnableIRQ(DSI_IRQn); +} + +/** + * @brief De-Initialize DSI MSP. + * @param hdsi DSI handle + * @retval None + */ +static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi) { + RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; + + UNUSED(hdsi); + + /* Switch to PLL3 before Disable */ + PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; + PLL3InitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; + PLL3InitPeriph.PLL3.PLL3M = 4; + PLL3InitPeriph.PLL3.PLL3N = 125; + PLL3InitPeriph.PLL3.PLL3P = 8; + PLL3InitPeriph.PLL3.PLL3Q = 8; + PLL3InitPeriph.PLL3.PLL3R = 24; + PLL3InitPeriph.PLL3.PLL3FRACN = 0; + PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; + PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; + PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + (void)HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); + + /* DSI clock disable */ + __HAL_RCC_DSI_CLK_DISABLE(); + + /** @brief Toggle Sw reset of DSI IP */ + __HAL_RCC_DSI_FORCE_RESET(); + __HAL_RCC_DSI_RELEASE_RESET(); + + /* Disable DSI interrupts */ + HAL_NVIC_DisableIRQ(DSI_IRQn); +} + +void display_pixeldata(uint16_t c) { + uint32_t address = 0; + + if (act_frame_buffer == 0) { + address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + } else { + address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + } + + /* Get the rectangle start address */ + address = + (address + (4 * ((cursor_y + 120) * PIXEL_PER_LINE + (cursor_x + 120)))); + + *(__IO uint32_t *)(address) = rgb565_to_rgb888(c) | 0xFF000000; + + cursor_x++; + if (cursor_x > window_x1) { + cursor_x = window_x0; + cursor_y++; + } + if (cursor_y > window_y1) { + cursor_y = window_y0; + } +} + +// this is just for compatibility with DMA2D using algorithms +uint8_t *const DISPLAY_DATA_ADDRESS = 0; + +void display_reset_state() {} + +void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + window_x0 = x0; + window_y0 = y0; + window_x1 = x1; + window_y1 = y1; + cursor_x = x0; + cursor_y = y0; +} + +uint8_t *display_get_wr_addr(void) { + uint32_t address = 0; + + if (act_frame_buffer == 0) { + address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + } else { + address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + } + + /* Get the rectangle start address */ + address = + (address + (4 * ((cursor_y + 120) * PIXEL_PER_LINE + (cursor_x + 120)))); + + return (uint8_t *)address; +} + +uint32_t *display_get_fb_addr(void) { + uint32_t address = 0; + + if (act_frame_buffer == 0) { + address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + } else { + address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + } + + return (uint32_t *)address; +} + +void display_efficient_clear(void) { + if (act_frame_buffer == 0) { + memset(PhysFrameBuffer1, 0x00, sizeof(PhysFrameBuffer1)); + } else { + memset(PhysFrameBuffer0, 0x00, sizeof(PhysFrameBuffer0)); + } +} + +uint16_t display_get_window_width(void) { return window_x1 - window_x0 + 1; } + +uint16_t display_get_window_height(void) { return window_y1 - window_y0 + 1; } + +void display_shift_window(uint16_t pixels) { + uint16_t w = display_get_window_width(); + uint16_t h = display_get_window_height(); + + uint16_t line_rem = w - (cursor_x - window_x0); + + if (pixels < line_rem) { + cursor_x += pixels; + return; + } + + // start of next line + pixels = pixels - line_rem; + cursor_x = window_x0; + cursor_y++; + + // add the rest of pixels + cursor_y = window_y0 + (((cursor_y - window_y0) + (pixels / w)) % h); + cursor_x += pixels % w; +} + +uint16_t display_get_window_offset(void) { + return PIXEL_PER_LINE - display_get_window_width(); +} + +int display_orientation(int degrees) { return degrees; } + +int display_get_orientation(void) { return 0; } +int display_backlight(int val) { return val; } + +void display_init(void) { + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Initializes the common periph clock + */ + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; + PeriphClkInit.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; + PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; + PeriphClkInit.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + PeriphClkInit.PLL3.PLL3M = 4; + PeriphClkInit.PLL3.PLL3N = 125; + PeriphClkInit.PLL3.PLL3P = 8; + PeriphClkInit.PLL3.PLL3Q = 2; + PeriphClkInit.PLL3.PLL3R = 24; + PeriphClkInit.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0; + PeriphClkInit.PLL3.PLL3FRACN = 0; + PeriphClkInit.PLL3.PLL3ClockOut = RCC_PLL3_DIVP | RCC_PLL3_DIVR; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + + memset(PhysFrameBuffer0, 0x00, sizeof(PhysFrameBuffer0)); + memset(PhysFrameBuffer1, 0x00, sizeof(PhysFrameBuffer1)); + memcpy(gfxmmu_lut, gfxmmu_lut_config_argb8888, + sizeof(gfxmmu_lut_config_argb8888)); + + BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT); + + BSP_LCD_SetBrightness(0, 100); + BSP_LCD_SetActiveLayer(0, 0); + BSP_LCD_DisplayOn(0); +} +void display_reinit(void) { + memcpy(gfxmmu_lut, gfxmmu_lut_config_argb8888, + sizeof(gfxmmu_lut_config_argb8888)); + + /* Switch to D-PHY source clock */ + /* Enable the DSI host */ + hlcd_dsi.Instance = DSI; + MX_GFXMMU_Reinit(&hlcd_gfxmmu); + MX_DSI_Reinit(&hlcd_dsi); + MX_LTDC_Reinit(&hlcd_ltdc); + + if (act_frame_buffer == 0) { + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + } else { + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); + } +} +void display_sync(void) {} + +void display_refresh(void) { + if (act_frame_buffer == 0) { + act_frame_buffer = 1; + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); + memcpy(PhysFrameBuffer0, PhysFrameBuffer1, sizeof(PhysFrameBuffer1)); + } else { + act_frame_buffer = 0; + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + memcpy(PhysFrameBuffer1, PhysFrameBuffer0, sizeof(PhysFrameBuffer1)); + } +} + +const char *display_save(const char *prefix) { return NULL; } + +void display_clear_save(void) {} + +void display_pixeldata_dirty(void) {} diff --git a/core/embed/trezorhal/stm32u5/displays/dsi.h b/core/embed/trezorhal/stm32u5/displays/dsi.h new file mode 100644 index 000000000..a717e4bb7 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/displays/dsi.h @@ -0,0 +1,30 @@ +#ifndef DSI_H_ +#define DSI_H_ + +#include STM32_HAL_H + +#define MAX_DISPLAY_RESX 240 +#define MAX_DISPLAY_RESY 240 +#define DISPLAY_RESX 240 +#define DISPLAY_RESY 240 +#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_ARGB8888 +#define DISPLAY_FRAMEBUFFER_WIDTH 768 +#define DISPLAY_FRAMEBUFFER_HEIGHT 480 +#define DISPLAY_FRAMEBUFFER_OFFSET_X 120 +#define DISPLAY_FRAMEBUFFER_OFFSET_Y 120 +#define TREZOR_FONT_BPP 4 + +#define DISPLAY_EFFICIENT_CLEAR 1 + +extern uint8_t* const DISPLAY_DATA_ADDRESS; + +uint32_t rgb565_to_rgb888(uint16_t color); + +static inline void display_pixel(uint8_t* fb, int16_t x, int16_t y, + uint16_t color) { + uint32_t p = 4 * ((y + 120) * DISPLAY_FRAMEBUFFER_WIDTH + (x + 120)); + uint32_t c = rgb565_to_rgb888(color); + *((uint32_t*)(fb + p)) = c; +} + +#endif diff --git a/core/embed/trezorhal/stm32u5/displays/gfxmmu_lut.h b/core/embed/trezorhal/stm32u5/displays/gfxmmu_lut.h new file mode 100644 index 000000000..7360378e8 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/displays/gfxmmu_lut.h @@ -0,0 +1,1006 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : gfxmmu_lut.h + * Description : header file for GFX MMU Configuration Table + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __gfxmmu_lut_H +#define __gfxmmu_lut_H +#ifdef __cplusplus +extern "C" { +#endif +// GFX MMU Configuration Table + +#define GFXMMU_FB_SIZE 733936 +#define GFXMMU_LUT_FIRST 0 +#define GFXMMU_LUT_LAST 479 +#define GFXMMU_LUT_SIZE 480 + +uint32_t gfxmmu_lut_config_argb8888[2 * GFXMMU_LUT_SIZE] = { + 0x00413601, // GFXMMU_LUT0L + 0x003FFCA0, // GFXMMU_LUT0H + 0x00433401, // GFXMMU_LUT1L + 0x003FFD80, // GFXMMU_LUT1H + 0x00453201, // GFXMMU_LUT2L + 0x003FFEA0, // GFXMMU_LUT2H + 0x00463101, // GFXMMU_LUT3L + 0x003FFFF0, // GFXMMU_LUT3H + 0x00482F01, // GFXMMU_LUT4L + 0x00000170, // GFXMMU_LUT4H + 0x00492E01, // GFXMMU_LUT5L + 0x00000320, // GFXMMU_LUT5H + 0x004A2D01, // GFXMMU_LUT6L + 0x000004F0, // GFXMMU_LUT6H + 0x004B2C01, // GFXMMU_LUT7L + 0x000006E0, // GFXMMU_LUT7H + 0x004C2B01, // GFXMMU_LUT8L + 0x000008F0, // GFXMMU_LUT8H + 0x004D2A01, // GFXMMU_LUT9L + 0x00000B20, // GFXMMU_LUT9H + 0x004D2A01, // GFXMMU_LUT10L + 0x00000D60, // GFXMMU_LUT10H + 0x004E2901, // GFXMMU_LUT11L + 0x00000FB0, // GFXMMU_LUT11H + 0x004F2801, // GFXMMU_LUT12L + 0x00001220, // GFXMMU_LUT12H + 0x00502701, // GFXMMU_LUT13L + 0x000014B0, // GFXMMU_LUT13H + 0x00502701, // GFXMMU_LUT14L + 0x00001750, // GFXMMU_LUT14H + 0x00512601, // GFXMMU_LUT15L + 0x00001A00, // GFXMMU_LUT15H + 0x00522501, // GFXMMU_LUT16L + 0x00001CD0, // GFXMMU_LUT16H + 0x00522501, // GFXMMU_LUT17L + 0x00001FB0, // GFXMMU_LUT17H + 0x00532401, // GFXMMU_LUT18L + 0x000022A0, // GFXMMU_LUT18H + 0x00532401, // GFXMMU_LUT19L + 0x000025A0, // GFXMMU_LUT19H + 0x00542301, // GFXMMU_LUT20L + 0x000028B0, // GFXMMU_LUT20H + 0x00552201, // GFXMMU_LUT21L + 0x00002BE0, // GFXMMU_LUT21H + 0x00552201, // GFXMMU_LUT22L + 0x00002F20, // GFXMMU_LUT22H + 0x00562101, // GFXMMU_LUT23L + 0x00003270, // GFXMMU_LUT23H + 0x00562101, // GFXMMU_LUT24L + 0x000035D0, // GFXMMU_LUT24H + 0x00572001, // GFXMMU_LUT25L + 0x00003940, // GFXMMU_LUT25H + 0x00572001, // GFXMMU_LUT26L + 0x00003CC0, // GFXMMU_LUT26H + 0x00581F01, // GFXMMU_LUT27L + 0x00004050, // GFXMMU_LUT27H + 0x00581F01, // GFXMMU_LUT28L + 0x000043F0, // GFXMMU_LUT28H + 0x00591E01, // GFXMMU_LUT29L + 0x000047A0, // GFXMMU_LUT29H + 0x00591E01, // GFXMMU_LUT30L + 0x00004B60, // GFXMMU_LUT30H + 0x00591E01, // GFXMMU_LUT31L + 0x00004F20, // GFXMMU_LUT31H + 0x005A1D01, // GFXMMU_LUT32L + 0x000052F0, // GFXMMU_LUT32H + 0x005A1D01, // GFXMMU_LUT33L + 0x000056D0, // GFXMMU_LUT33H + 0x005B1C01, // GFXMMU_LUT34L + 0x00005AC0, // GFXMMU_LUT34H + 0x005B1C01, // GFXMMU_LUT35L + 0x00005EC0, // GFXMMU_LUT35H + 0x005C1B01, // GFXMMU_LUT36L + 0x000062D0, // GFXMMU_LUT36H + 0x005C1B01, // GFXMMU_LUT37L + 0x000066F0, // GFXMMU_LUT37H + 0x005C1B01, // GFXMMU_LUT38L + 0x00006B10, // GFXMMU_LUT38H + 0x005D1A01, // GFXMMU_LUT39L + 0x00006F40, // GFXMMU_LUT39H + 0x005D1A01, // GFXMMU_LUT40L + 0x00007380, // GFXMMU_LUT40H + 0x005D1A01, // GFXMMU_LUT41L + 0x000077C0, // GFXMMU_LUT41H + 0x005E1901, // GFXMMU_LUT42L + 0x00007C10, // GFXMMU_LUT42H + 0x005E1901, // GFXMMU_LUT43L + 0x00008070, // GFXMMU_LUT43H + 0x005E1901, // GFXMMU_LUT44L + 0x000084D0, // GFXMMU_LUT44H + 0x005F1801, // GFXMMU_LUT45L + 0x00008940, // GFXMMU_LUT45H + 0x005F1801, // GFXMMU_LUT46L + 0x00008DC0, // GFXMMU_LUT46H + 0x00601801, // GFXMMU_LUT47L + 0x00009240, // GFXMMU_LUT47H + 0x00601701, // GFXMMU_LUT48L + 0x000096E0, // GFXMMU_LUT48H + 0x00601701, // GFXMMU_LUT49L + 0x00009B80, // GFXMMU_LUT49H + 0x00601701, // GFXMMU_LUT50L + 0x0000A020, // GFXMMU_LUT50H + 0x00611601, // GFXMMU_LUT51L + 0x0000A4D0, // GFXMMU_LUT51H + 0x00611601, // GFXMMU_LUT52L + 0x0000A990, // GFXMMU_LUT52H + 0x00611601, // GFXMMU_LUT53L + 0x0000AE50, // GFXMMU_LUT53H + 0x00621501, // GFXMMU_LUT54L + 0x0000B320, // GFXMMU_LUT54H + 0x00621501, // GFXMMU_LUT55L + 0x0000B800, // GFXMMU_LUT55H + 0x00621501, // GFXMMU_LUT56L + 0x0000BCE0, // GFXMMU_LUT56H + 0x00631401, // GFXMMU_LUT57L + 0x0000C1D0, // GFXMMU_LUT57H + 0x00631401, // GFXMMU_LUT58L + 0x0000C6D0, // GFXMMU_LUT58H + 0x00631401, // GFXMMU_LUT59L + 0x0000CBD0, // GFXMMU_LUT59H + 0x00631401, // GFXMMU_LUT60L + 0x0000D0D0, // GFXMMU_LUT60H + 0x00641301, // GFXMMU_LUT61L + 0x0000D5E0, // GFXMMU_LUT61H + 0x00641301, // GFXMMU_LUT62L + 0x0000DB00, // GFXMMU_LUT62H + 0x00641301, // GFXMMU_LUT63L + 0x0000E020, // GFXMMU_LUT63H + 0x00651201, // GFXMMU_LUT64L + 0x0000E550, // GFXMMU_LUT64H + 0x00651201, // GFXMMU_LUT65L + 0x0000EA90, // GFXMMU_LUT65H + 0x00651201, // GFXMMU_LUT66L + 0x0000EFD0, // GFXMMU_LUT66H + 0x00651201, // GFXMMU_LUT67L + 0x0000F510, // GFXMMU_LUT67H + 0x00661101, // GFXMMU_LUT68L + 0x0000FA60, // GFXMMU_LUT68H + 0x00661101, // GFXMMU_LUT69L + 0x0000FFC0, // GFXMMU_LUT69H + 0x00661101, // GFXMMU_LUT70L + 0x00010520, // GFXMMU_LUT70H + 0x00661101, // GFXMMU_LUT71L + 0x00010A80, // GFXMMU_LUT71H + 0x00671001, // GFXMMU_LUT72L + 0x00010FF0, // GFXMMU_LUT72H + 0x00671001, // GFXMMU_LUT73L + 0x00011570, // GFXMMU_LUT73H + 0x00671001, // GFXMMU_LUT74L + 0x00011AF0, // GFXMMU_LUT74H + 0x00671001, // GFXMMU_LUT75L + 0x00012070, // GFXMMU_LUT75H + 0x00680F01, // GFXMMU_LUT76L + 0x00012600, // GFXMMU_LUT76H + 0x00680F01, // GFXMMU_LUT77L + 0x00012BA0, // GFXMMU_LUT77H + 0x00680F01, // GFXMMU_LUT78L + 0x00013140, // GFXMMU_LUT78H + 0x00680F01, // GFXMMU_LUT79L + 0x000136E0, // GFXMMU_LUT79H + 0x00680F01, // GFXMMU_LUT80L + 0x00013C80, // GFXMMU_LUT80H + 0x00690E01, // GFXMMU_LUT81L + 0x00014230, // GFXMMU_LUT81H + 0x00690E01, // GFXMMU_LUT82L + 0x000147F0, // GFXMMU_LUT82H + 0x00690E01, // GFXMMU_LUT83L + 0x00014DB0, // GFXMMU_LUT83H + 0x00690E01, // GFXMMU_LUT84L + 0x00015370, // GFXMMU_LUT84H + 0x006A0D01, // GFXMMU_LUT85L + 0x00015940, // GFXMMU_LUT85H + 0x006A0D01, // GFXMMU_LUT86L + 0x00015F20, // GFXMMU_LUT86H + 0x006A0D01, // GFXMMU_LUT87L + 0x00016500, // GFXMMU_LUT87H + 0x006A0D01, // GFXMMU_LUT88L + 0x00016AE0, // GFXMMU_LUT88H + 0x006A0D01, // GFXMMU_LUT89L + 0x000170C0, // GFXMMU_LUT89H + 0x006B0C01, // GFXMMU_LUT90L + 0x000176B0, // GFXMMU_LUT90H + 0x006B0C01, // GFXMMU_LUT91L + 0x00017CB0, // GFXMMU_LUT91H + 0x006B0C01, // GFXMMU_LUT92L + 0x000182B0, // GFXMMU_LUT92H + 0x006B0C01, // GFXMMU_LUT93L + 0x000188B0, // GFXMMU_LUT93H + 0x006B0C01, // GFXMMU_LUT94L + 0x00018EB0, // GFXMMU_LUT94H + 0x006C0C01, // GFXMMU_LUT95L + 0x000194B0, // GFXMMU_LUT95H + 0x006C0B01, // GFXMMU_LUT96L + 0x00019AD0, // GFXMMU_LUT96H + 0x006C0B01, // GFXMMU_LUT97L + 0x0001A0F0, // GFXMMU_LUT97H + 0x006C0B01, // GFXMMU_LUT98L + 0x0001A710, // GFXMMU_LUT98H + 0x006C0B01, // GFXMMU_LUT99L + 0x0001AD30, // GFXMMU_LUT99H + 0x006C0B01, // GFXMMU_LUT100L + 0x0001B350, // GFXMMU_LUT100H + 0x006D0A01, // GFXMMU_LUT101L + 0x0001B980, // GFXMMU_LUT101H + 0x006D0A01, // GFXMMU_LUT102L + 0x0001BFC0, // GFXMMU_LUT102H + 0x006D0A01, // GFXMMU_LUT103L + 0x0001C600, // GFXMMU_LUT103H + 0x006D0A01, // GFXMMU_LUT104L + 0x0001CC40, // GFXMMU_LUT104H + 0x006D0A01, // GFXMMU_LUT105L + 0x0001D280, // GFXMMU_LUT105H + 0x006D0A01, // GFXMMU_LUT106L + 0x0001D8C0, // GFXMMU_LUT106H + 0x006E0901, // GFXMMU_LUT107L + 0x0001DF10, // GFXMMU_LUT107H + 0x006E0901, // GFXMMU_LUT108L + 0x0001E570, // GFXMMU_LUT108H + 0x006E0901, // GFXMMU_LUT109L + 0x0001EBD0, // GFXMMU_LUT109H + 0x006E0901, // GFXMMU_LUT110L + 0x0001F230, // GFXMMU_LUT110H + 0x006E0901, // GFXMMU_LUT111L + 0x0001F890, // GFXMMU_LUT111H + 0x006E0901, // GFXMMU_LUT112L + 0x0001FEF0, // GFXMMU_LUT112H + 0x006F0801, // GFXMMU_LUT113L + 0x00020560, // GFXMMU_LUT113H + 0x006F0801, // GFXMMU_LUT114L + 0x00020BE0, // GFXMMU_LUT114H + 0x006F0801, // GFXMMU_LUT115L + 0x00021260, // GFXMMU_LUT115H + 0x006F0801, // GFXMMU_LUT116L + 0x000218E0, // GFXMMU_LUT116H + 0x006F0801, // GFXMMU_LUT117L + 0x00021F60, // GFXMMU_LUT117H + 0x006F0801, // GFXMMU_LUT118L + 0x000225E0, // GFXMMU_LUT118H + 0x006F0801, // GFXMMU_LUT119L + 0x00022C60, // GFXMMU_LUT119H + 0x00700701, // GFXMMU_LUT120L + 0x000232F0, // GFXMMU_LUT120H + 0x00700701, // GFXMMU_LUT121L + 0x00023990, // GFXMMU_LUT121H + 0x00700701, // GFXMMU_LUT122L + 0x00024030, // GFXMMU_LUT122H + 0x00700701, // GFXMMU_LUT123L + 0x000246D0, // GFXMMU_LUT123H + 0x00700701, // GFXMMU_LUT124L + 0x00024D70, // GFXMMU_LUT124H + 0x00700701, // GFXMMU_LUT125L + 0x00025410, // GFXMMU_LUT125H + 0x00700701, // GFXMMU_LUT126L + 0x00025AB0, // GFXMMU_LUT126H + 0x00710601, // GFXMMU_LUT127L + 0x00026160, // GFXMMU_LUT127H + 0x00710601, // GFXMMU_LUT128L + 0x00026820, // GFXMMU_LUT128H + 0x00710601, // GFXMMU_LUT129L + 0x00026EE0, // GFXMMU_LUT129H + 0x00710601, // GFXMMU_LUT130L + 0x000275A0, // GFXMMU_LUT130H + 0x00710601, // GFXMMU_LUT131L + 0x00027C60, // GFXMMU_LUT131H + 0x00710601, // GFXMMU_LUT132L + 0x00028320, // GFXMMU_LUT132H + 0x00710601, // GFXMMU_LUT133L + 0x000289E0, // GFXMMU_LUT133H + 0x00710601, // GFXMMU_LUT134L + 0x000290A0, // GFXMMU_LUT134H + 0x00720501, // GFXMMU_LUT135L + 0x00029770, // GFXMMU_LUT135H + 0x00720501, // GFXMMU_LUT136L + 0x00029E50, // GFXMMU_LUT136H + 0x00720501, // GFXMMU_LUT137L + 0x0002A530, // GFXMMU_LUT137H + 0x00720501, // GFXMMU_LUT138L + 0x0002AC10, // GFXMMU_LUT138H + 0x00720501, // GFXMMU_LUT139L + 0x0002B2F0, // GFXMMU_LUT139H + 0x00720501, // GFXMMU_LUT140L + 0x0002B9D0, // GFXMMU_LUT140H + 0x00720501, // GFXMMU_LUT141L + 0x0002C0B0, // GFXMMU_LUT141H + 0x00720501, // GFXMMU_LUT142L + 0x0002C790, // GFXMMU_LUT142H + 0x00720501, // GFXMMU_LUT143L + 0x0002CE70, // GFXMMU_LUT143H + 0x00730401, // GFXMMU_LUT144L + 0x0002D560, // GFXMMU_LUT144H + 0x00730401, // GFXMMU_LUT145L + 0x0002DC60, // GFXMMU_LUT145H + 0x00730401, // GFXMMU_LUT146L + 0x0002E360, // GFXMMU_LUT146H + 0x00730401, // GFXMMU_LUT147L + 0x0002EA60, // GFXMMU_LUT147H + 0x00730401, // GFXMMU_LUT148L + 0x0002F160, // GFXMMU_LUT148H + 0x00730401, // GFXMMU_LUT149L + 0x0002F860, // GFXMMU_LUT149H + 0x00730401, // GFXMMU_LUT150L + 0x0002FF60, // GFXMMU_LUT150H + 0x00730401, // GFXMMU_LUT151L + 0x00030660, // GFXMMU_LUT151H + 0x00730401, // GFXMMU_LUT152L + 0x00030D60, // GFXMMU_LUT152H + 0x00740301, // GFXMMU_LUT153L + 0x00031470, // GFXMMU_LUT153H + 0x00740301, // GFXMMU_LUT154L + 0x00031B90, // GFXMMU_LUT154H + 0x00740301, // GFXMMU_LUT155L + 0x000322B0, // GFXMMU_LUT155H + 0x00740301, // GFXMMU_LUT156L + 0x000329D0, // GFXMMU_LUT156H + 0x00740301, // GFXMMU_LUT157L + 0x000330F0, // GFXMMU_LUT157H + 0x00740301, // GFXMMU_LUT158L + 0x00033810, // GFXMMU_LUT158H + 0x00740301, // GFXMMU_LUT159L + 0x00033F30, // GFXMMU_LUT159H + 0x00740301, // GFXMMU_LUT160L + 0x00034650, // GFXMMU_LUT160H + 0x00740301, // GFXMMU_LUT161L + 0x00034D70, // GFXMMU_LUT161H + 0x00740301, // GFXMMU_LUT162L + 0x00035490, // GFXMMU_LUT162H + 0x00740301, // GFXMMU_LUT163L + 0x00035BB0, // GFXMMU_LUT163H + 0x00740301, // GFXMMU_LUT164L + 0x000362D0, // GFXMMU_LUT164H + 0x00750201, // GFXMMU_LUT165L + 0x00036A00, // GFXMMU_LUT165H + 0x00750201, // GFXMMU_LUT166L + 0x00037140, // GFXMMU_LUT166H + 0x00750201, // GFXMMU_LUT167L + 0x00037880, // GFXMMU_LUT167H + 0x00750201, // GFXMMU_LUT168L + 0x00037FC0, // GFXMMU_LUT168H + 0x00750201, // GFXMMU_LUT169L + 0x00038700, // GFXMMU_LUT169H + 0x00750201, // GFXMMU_LUT170L + 0x00038E40, // GFXMMU_LUT170H + 0x00750201, // GFXMMU_LUT171L + 0x00039580, // GFXMMU_LUT171H + 0x00750201, // GFXMMU_LUT172L + 0x00039CC0, // GFXMMU_LUT172H + 0x00750201, // GFXMMU_LUT173L + 0x0003A400, // GFXMMU_LUT173H + 0x00750201, // GFXMMU_LUT174L + 0x0003AB40, // GFXMMU_LUT174H + 0x00750201, // GFXMMU_LUT175L + 0x0003B280, // GFXMMU_LUT175H + 0x00750201, // GFXMMU_LUT176L + 0x0003B9C0, // GFXMMU_LUT176H + 0x00750201, // GFXMMU_LUT177L + 0x0003C100, // GFXMMU_LUT177H + 0x00760101, // GFXMMU_LUT178L + 0x0003C850, // GFXMMU_LUT178H + 0x00760101, // GFXMMU_LUT179L + 0x0003CFB0, // GFXMMU_LUT179H + 0x00760101, // GFXMMU_LUT180L + 0x0003D710, // GFXMMU_LUT180H + 0x00760101, // GFXMMU_LUT181L + 0x0003DE70, // GFXMMU_LUT181H + 0x00760101, // GFXMMU_LUT182L + 0x0003E5D0, // GFXMMU_LUT182H + 0x00760101, // GFXMMU_LUT183L + 0x0003ED30, // GFXMMU_LUT183H + 0x00760101, // GFXMMU_LUT184L + 0x0003F490, // GFXMMU_LUT184H + 0x00760101, // GFXMMU_LUT185L + 0x0003FBF0, // GFXMMU_LUT185H + 0x00760101, // GFXMMU_LUT186L + 0x00040350, // GFXMMU_LUT186H + 0x00760101, // GFXMMU_LUT187L + 0x00040AB0, // GFXMMU_LUT187H + 0x00760101, // GFXMMU_LUT188L + 0x00041210, // GFXMMU_LUT188H + 0x00760101, // GFXMMU_LUT189L + 0x00041970, // GFXMMU_LUT189H + 0x00760101, // GFXMMU_LUT190L + 0x000420D0, // GFXMMU_LUT190H + 0x00760101, // GFXMMU_LUT191L + 0x00042830, // GFXMMU_LUT191H + 0x00760101, // GFXMMU_LUT192L + 0x00042F90, // GFXMMU_LUT192H + 0x00760101, // GFXMMU_LUT193L + 0x000436F0, // GFXMMU_LUT193H + 0x00760101, // GFXMMU_LUT194L + 0x00043E50, // GFXMMU_LUT194H + 0x00760101, // GFXMMU_LUT195L + 0x000445B0, // GFXMMU_LUT195H + 0x00770001, // GFXMMU_LUT196L + 0x00044D20, // GFXMMU_LUT196H + 0x00770001, // GFXMMU_LUT197L + 0x000454A0, // GFXMMU_LUT197H + 0x00770001, // GFXMMU_LUT198L + 0x00045C20, // GFXMMU_LUT198H + 0x00770001, // GFXMMU_LUT199L + 0x000463A0, // GFXMMU_LUT199H + 0x00770001, // GFXMMU_LUT200L + 0x00046B20, // GFXMMU_LUT200H + 0x00770001, // GFXMMU_LUT201L + 0x000472A0, // GFXMMU_LUT201H + 0x00770001, // GFXMMU_LUT202L + 0x00047A20, // GFXMMU_LUT202H + 0x00770001, // GFXMMU_LUT203L + 0x000481A0, // GFXMMU_LUT203H + 0x00770001, // GFXMMU_LUT204L + 0x00048920, // GFXMMU_LUT204H + 0x00770001, // GFXMMU_LUT205L + 0x000490A0, // GFXMMU_LUT205H + 0x00770001, // GFXMMU_LUT206L + 0x00049820, // GFXMMU_LUT206H + 0x00770001, // GFXMMU_LUT207L + 0x00049FA0, // GFXMMU_LUT207H + 0x00770001, // GFXMMU_LUT208L + 0x0004A720, // GFXMMU_LUT208H + 0x00770001, // GFXMMU_LUT209L + 0x0004AEA0, // GFXMMU_LUT209H + 0x00770001, // GFXMMU_LUT210L + 0x0004B620, // GFXMMU_LUT210H + 0x00770001, // GFXMMU_LUT211L + 0x0004BDA0, // GFXMMU_LUT211H + 0x00770001, // GFXMMU_LUT212L + 0x0004C520, // GFXMMU_LUT212H + 0x00770001, // GFXMMU_LUT213L + 0x0004CCA0, // GFXMMU_LUT213H + 0x00770001, // GFXMMU_LUT214L + 0x0004D420, // GFXMMU_LUT214H + 0x00770001, // GFXMMU_LUT215L + 0x0004DBA0, // GFXMMU_LUT215H + 0x00770001, // GFXMMU_LUT216L + 0x0004E320, // GFXMMU_LUT216H + 0x00770001, // GFXMMU_LUT217L + 0x0004EAA0, // GFXMMU_LUT217H + 0x00770001, // GFXMMU_LUT218L + 0x0004F220, // GFXMMU_LUT218H + 0x00770001, // GFXMMU_LUT219L + 0x0004F9A0, // GFXMMU_LUT219H + 0x00770001, // GFXMMU_LUT220L + 0x00050120, // GFXMMU_LUT220H + 0x00770001, // GFXMMU_LUT221L + 0x000508A0, // GFXMMU_LUT221H + 0x00770001, // GFXMMU_LUT222L + 0x00051020, // GFXMMU_LUT222H + 0x00770001, // GFXMMU_LUT223L + 0x000517A0, // GFXMMU_LUT223H + 0x00770001, // GFXMMU_LUT224L + 0x00051F20, // GFXMMU_LUT224H + 0x00770001, // GFXMMU_LUT225L + 0x000526A0, // GFXMMU_LUT225H + 0x00770001, // GFXMMU_LUT226L + 0x00052E20, // GFXMMU_LUT226H + 0x00770001, // GFXMMU_LUT227L + 0x000535A0, // GFXMMU_LUT227H + 0x00770001, // GFXMMU_LUT228L + 0x00053D20, // GFXMMU_LUT228H + 0x00770001, // GFXMMU_LUT229L + 0x000544A0, // GFXMMU_LUT229H + 0x00770001, // GFXMMU_LUT230L + 0x00054C20, // GFXMMU_LUT230H + 0x00770001, // GFXMMU_LUT231L + 0x000553A0, // GFXMMU_LUT231H + 0x00770001, // GFXMMU_LUT232L + 0x00055B20, // GFXMMU_LUT232H + 0x00770001, // GFXMMU_LUT233L + 0x000562A0, // GFXMMU_LUT233H + 0x00770001, // GFXMMU_LUT234L + 0x00056A20, // GFXMMU_LUT234H + 0x00770001, // GFXMMU_LUT235L + 0x000571A0, // GFXMMU_LUT235H + 0x00770001, // GFXMMU_LUT236L + 0x00057920, // GFXMMU_LUT236H + 0x00770001, // GFXMMU_LUT237L + 0x000580A0, // GFXMMU_LUT237H + 0x00770001, // GFXMMU_LUT238L + 0x00058820, // GFXMMU_LUT238H + 0x00770001, // GFXMMU_LUT239L + 0x00058FA0, // GFXMMU_LUT239H + 0x00780001, // GFXMMU_LUT240L + 0x00059720, // GFXMMU_LUT240H + 0x00770001, // GFXMMU_LUT241L + 0x00059EB0, // GFXMMU_LUT241H + 0x00770001, // GFXMMU_LUT242L + 0x0005A630, // GFXMMU_LUT242H + 0x00770001, // GFXMMU_LUT243L + 0x0005ADB0, // GFXMMU_LUT243H + 0x00770001, // GFXMMU_LUT244L + 0x0005B530, // GFXMMU_LUT244H + 0x00770001, // GFXMMU_LUT245L + 0x0005BCB0, // GFXMMU_LUT245H + 0x00770001, // GFXMMU_LUT246L + 0x0005C430, // GFXMMU_LUT246H + 0x00770001, // GFXMMU_LUT247L + 0x0005CBB0, // GFXMMU_LUT247H + 0x00770001, // GFXMMU_LUT248L + 0x0005D330, // GFXMMU_LUT248H + 0x00770001, // GFXMMU_LUT249L + 0x0005DAB0, // GFXMMU_LUT249H + 0x00770001, // GFXMMU_LUT250L + 0x0005E230, // GFXMMU_LUT250H + 0x00770001, // GFXMMU_LUT251L + 0x0005E9B0, // GFXMMU_LUT251H + 0x00770001, // GFXMMU_LUT252L + 0x0005F130, // GFXMMU_LUT252H + 0x00770001, // GFXMMU_LUT253L + 0x0005F8B0, // GFXMMU_LUT253H + 0x00770001, // GFXMMU_LUT254L + 0x00060030, // GFXMMU_LUT254H + 0x00770001, // GFXMMU_LUT255L + 0x000607B0, // GFXMMU_LUT255H + 0x00770001, // GFXMMU_LUT256L + 0x00060F30, // GFXMMU_LUT256H + 0x00770001, // GFXMMU_LUT257L + 0x000616B0, // GFXMMU_LUT257H + 0x00770001, // GFXMMU_LUT258L + 0x00061E30, // GFXMMU_LUT258H + 0x00770001, // GFXMMU_LUT259L + 0x000625B0, // GFXMMU_LUT259H + 0x00770001, // GFXMMU_LUT260L + 0x00062D30, // GFXMMU_LUT260H + 0x00770001, // GFXMMU_LUT261L + 0x000634B0, // GFXMMU_LUT261H + 0x00770001, // GFXMMU_LUT262L + 0x00063C30, // GFXMMU_LUT262H + 0x00770001, // GFXMMU_LUT263L + 0x000643B0, // GFXMMU_LUT263H + 0x00770001, // GFXMMU_LUT264L + 0x00064B30, // GFXMMU_LUT264H + 0x00770001, // GFXMMU_LUT265L + 0x000652B0, // GFXMMU_LUT265H + 0x00770001, // GFXMMU_LUT266L + 0x00065A30, // GFXMMU_LUT266H + 0x00770001, // GFXMMU_LUT267L + 0x000661B0, // GFXMMU_LUT267H + 0x00770001, // GFXMMU_LUT268L + 0x00066930, // GFXMMU_LUT268H + 0x00770001, // GFXMMU_LUT269L + 0x000670B0, // GFXMMU_LUT269H + 0x00770001, // GFXMMU_LUT270L + 0x00067830, // GFXMMU_LUT270H + 0x00770001, // GFXMMU_LUT271L + 0x00067FB0, // GFXMMU_LUT271H + 0x00770001, // GFXMMU_LUT272L + 0x00068730, // GFXMMU_LUT272H + 0x00770001, // GFXMMU_LUT273L + 0x00068EB0, // GFXMMU_LUT273H + 0x00770001, // GFXMMU_LUT274L + 0x00069630, // GFXMMU_LUT274H + 0x00770001, // GFXMMU_LUT275L + 0x00069DB0, // GFXMMU_LUT275H + 0x00770001, // GFXMMU_LUT276L + 0x0006A530, // GFXMMU_LUT276H + 0x00770001, // GFXMMU_LUT277L + 0x0006ACB0, // GFXMMU_LUT277H + 0x00770001, // GFXMMU_LUT278L + 0x0006B430, // GFXMMU_LUT278H + 0x00770001, // GFXMMU_LUT279L + 0x0006BBB0, // GFXMMU_LUT279H + 0x00770001, // GFXMMU_LUT280L + 0x0006C330, // GFXMMU_LUT280H + 0x00770001, // GFXMMU_LUT281L + 0x0006CAB0, // GFXMMU_LUT281H + 0x00770001, // GFXMMU_LUT282L + 0x0006D230, // GFXMMU_LUT282H + 0x00770001, // GFXMMU_LUT283L + 0x0006D9B0, // GFXMMU_LUT283H + 0x00770001, // GFXMMU_LUT284L + 0x0006E130, // GFXMMU_LUT284H + 0x00760101, // GFXMMU_LUT285L + 0x0006E8A0, // GFXMMU_LUT285H + 0x00760101, // GFXMMU_LUT286L + 0x0006F000, // GFXMMU_LUT286H + 0x00760101, // GFXMMU_LUT287L + 0x0006F760, // GFXMMU_LUT287H + 0x00760101, // GFXMMU_LUT288L + 0x0006FEC0, // GFXMMU_LUT288H + 0x00760101, // GFXMMU_LUT289L + 0x00070620, // GFXMMU_LUT289H + 0x00760101, // GFXMMU_LUT290L + 0x00070D80, // GFXMMU_LUT290H + 0x00760101, // GFXMMU_LUT291L + 0x000714E0, // GFXMMU_LUT291H + 0x00760101, // GFXMMU_LUT292L + 0x00071C40, // GFXMMU_LUT292H + 0x00760101, // GFXMMU_LUT293L + 0x000723A0, // GFXMMU_LUT293H + 0x00760101, // GFXMMU_LUT294L + 0x00072B00, // GFXMMU_LUT294H + 0x00760101, // GFXMMU_LUT295L + 0x00073260, // GFXMMU_LUT295H + 0x00760101, // GFXMMU_LUT296L + 0x000739C0, // GFXMMU_LUT296H + 0x00760101, // GFXMMU_LUT297L + 0x00074120, // GFXMMU_LUT297H + 0x00760101, // GFXMMU_LUT298L + 0x00074880, // GFXMMU_LUT298H + 0x00760101, // GFXMMU_LUT299L + 0x00074FE0, // GFXMMU_LUT299H + 0x00760101, // GFXMMU_LUT300L + 0x00075740, // GFXMMU_LUT300H + 0x00760101, // GFXMMU_LUT301L + 0x00075EA0, // GFXMMU_LUT301H + 0x00760101, // GFXMMU_LUT302L + 0x00076600, // GFXMMU_LUT302H + 0x00750201, // GFXMMU_LUT303L + 0x00076D50, // GFXMMU_LUT303H + 0x00750201, // GFXMMU_LUT304L + 0x00077490, // GFXMMU_LUT304H + 0x00750201, // GFXMMU_LUT305L + 0x00077BD0, // GFXMMU_LUT305H + 0x00750201, // GFXMMU_LUT306L + 0x00078310, // GFXMMU_LUT306H + 0x00750201, // GFXMMU_LUT307L + 0x00078A50, // GFXMMU_LUT307H + 0x00750201, // GFXMMU_LUT308L + 0x00079190, // GFXMMU_LUT308H + 0x00750201, // GFXMMU_LUT309L + 0x000798D0, // GFXMMU_LUT309H + 0x00750201, // GFXMMU_LUT310L + 0x0007A010, // GFXMMU_LUT310H + 0x00750201, // GFXMMU_LUT311L + 0x0007A750, // GFXMMU_LUT311H + 0x00750201, // GFXMMU_LUT312L + 0x0007AE90, // GFXMMU_LUT312H + 0x00750201, // GFXMMU_LUT313L + 0x0007B5D0, // GFXMMU_LUT313H + 0x00750201, // GFXMMU_LUT314L + 0x0007BD10, // GFXMMU_LUT314H + 0x00750201, // GFXMMU_LUT315L + 0x0007C450, // GFXMMU_LUT315H + 0x00740301, // GFXMMU_LUT316L + 0x0007CB80, // GFXMMU_LUT316H + 0x00740301, // GFXMMU_LUT317L + 0x0007D2A0, // GFXMMU_LUT317H + 0x00740301, // GFXMMU_LUT318L + 0x0007D9C0, // GFXMMU_LUT318H + 0x00740301, // GFXMMU_LUT319L + 0x0007E0E0, // GFXMMU_LUT319H + 0x00740301, // GFXMMU_LUT320L + 0x0007E800, // GFXMMU_LUT320H + 0x00740301, // GFXMMU_LUT321L + 0x0007EF20, // GFXMMU_LUT321H + 0x00740301, // GFXMMU_LUT322L + 0x0007F640, // GFXMMU_LUT322H + 0x00740301, // GFXMMU_LUT323L + 0x0007FD60, // GFXMMU_LUT323H + 0x00740301, // GFXMMU_LUT324L + 0x00080480, // GFXMMU_LUT324H + 0x00740301, // GFXMMU_LUT325L + 0x00080BA0, // GFXMMU_LUT325H + 0x00740301, // GFXMMU_LUT326L + 0x000812C0, // GFXMMU_LUT326H + 0x00740301, // GFXMMU_LUT327L + 0x000819E0, // GFXMMU_LUT327H + 0x00730401, // GFXMMU_LUT328L + 0x000820F0, // GFXMMU_LUT328H + 0x00730401, // GFXMMU_LUT329L + 0x000827F0, // GFXMMU_LUT329H + 0x00730401, // GFXMMU_LUT330L + 0x00082EF0, // GFXMMU_LUT330H + 0x00730401, // GFXMMU_LUT331L + 0x000835F0, // GFXMMU_LUT331H + 0x00730401, // GFXMMU_LUT332L + 0x00083CF0, // GFXMMU_LUT332H + 0x00730401, // GFXMMU_LUT333L + 0x000843F0, // GFXMMU_LUT333H + 0x00730401, // GFXMMU_LUT334L + 0x00084AF0, // GFXMMU_LUT334H + 0x00730401, // GFXMMU_LUT335L + 0x000851F0, // GFXMMU_LUT335H + 0x00730401, // GFXMMU_LUT336L + 0x000858F0, // GFXMMU_LUT336H + 0x00730401, // GFXMMU_LUT337L + 0x00085FF0, // GFXMMU_LUT337H + 0x00720501, // GFXMMU_LUT338L + 0x000866E0, // GFXMMU_LUT338H + 0x00720501, // GFXMMU_LUT339L + 0x00086DC0, // GFXMMU_LUT339H + 0x00720501, // GFXMMU_LUT340L + 0x000874A0, // GFXMMU_LUT340H + 0x00720501, // GFXMMU_LUT341L + 0x00087B80, // GFXMMU_LUT341H + 0x00720501, // GFXMMU_LUT342L + 0x00088260, // GFXMMU_LUT342H + 0x00720501, // GFXMMU_LUT343L + 0x00088940, // GFXMMU_LUT343H + 0x00720501, // GFXMMU_LUT344L + 0x00089020, // GFXMMU_LUT344H + 0x00720501, // GFXMMU_LUT345L + 0x00089700, // GFXMMU_LUT345H + 0x00710601, // GFXMMU_LUT346L + 0x00089DD0, // GFXMMU_LUT346H + 0x00710601, // GFXMMU_LUT347L + 0x0008A490, // GFXMMU_LUT347H + 0x00710601, // GFXMMU_LUT348L + 0x0008AB50, // GFXMMU_LUT348H + 0x00710601, // GFXMMU_LUT349L + 0x0008B210, // GFXMMU_LUT349H + 0x00710601, // GFXMMU_LUT350L + 0x0008B8D0, // GFXMMU_LUT350H + 0x00710601, // GFXMMU_LUT351L + 0x0008BF90, // GFXMMU_LUT351H + 0x00710601, // GFXMMU_LUT352L + 0x0008C650, // GFXMMU_LUT352H + 0x00710601, // GFXMMU_LUT353L + 0x0008CD10, // GFXMMU_LUT353H + 0x00700701, // GFXMMU_LUT354L + 0x0008D3C0, // GFXMMU_LUT354H + 0x00700701, // GFXMMU_LUT355L + 0x0008DA60, // GFXMMU_LUT355H + 0x00700701, // GFXMMU_LUT356L + 0x0008E100, // GFXMMU_LUT356H + 0x00700701, // GFXMMU_LUT357L + 0x0008E7A0, // GFXMMU_LUT357H + 0x00700701, // GFXMMU_LUT358L + 0x0008EE40, // GFXMMU_LUT358H + 0x00700701, // GFXMMU_LUT359L + 0x0008F4E0, // GFXMMU_LUT359H + 0x00700701, // GFXMMU_LUT360L + 0x0008FB80, // GFXMMU_LUT360H + 0x006F0801, // GFXMMU_LUT361L + 0x00090210, // GFXMMU_LUT361H + 0x006F0801, // GFXMMU_LUT362L + 0x00090890, // GFXMMU_LUT362H + 0x006F0801, // GFXMMU_LUT363L + 0x00090F10, // GFXMMU_LUT363H + 0x006F0801, // GFXMMU_LUT364L + 0x00091590, // GFXMMU_LUT364H + 0x006F0801, // GFXMMU_LUT365L + 0x00091C10, // GFXMMU_LUT365H + 0x006F0801, // GFXMMU_LUT366L + 0x00092290, // GFXMMU_LUT366H + 0x006F0801, // GFXMMU_LUT367L + 0x00092910, // GFXMMU_LUT367H + 0x006E0901, // GFXMMU_LUT368L + 0x00092F80, // GFXMMU_LUT368H + 0x006E0901, // GFXMMU_LUT369L + 0x000935E0, // GFXMMU_LUT369H + 0x006E0901, // GFXMMU_LUT370L + 0x00093C40, // GFXMMU_LUT370H + 0x006E0901, // GFXMMU_LUT371L + 0x000942A0, // GFXMMU_LUT371H + 0x006E0901, // GFXMMU_LUT372L + 0x00094900, // GFXMMU_LUT372H + 0x006E0901, // GFXMMU_LUT373L + 0x00094F60, // GFXMMU_LUT373H + 0x006D0A01, // GFXMMU_LUT374L + 0x000955B0, // GFXMMU_LUT374H + 0x006D0A01, // GFXMMU_LUT375L + 0x00095BF0, // GFXMMU_LUT375H + 0x006D0A01, // GFXMMU_LUT376L + 0x00096230, // GFXMMU_LUT376H + 0x006D0A01, // GFXMMU_LUT377L + 0x00096870, // GFXMMU_LUT377H + 0x006D0A01, // GFXMMU_LUT378L + 0x00096EB0, // GFXMMU_LUT378H + 0x006C0B01, // GFXMMU_LUT379L + 0x000974E0, // GFXMMU_LUT379H + 0x006C0B01, // GFXMMU_LUT380L + 0x00097B00, // GFXMMU_LUT380H + 0x006C0B01, // GFXMMU_LUT381L + 0x00098120, // GFXMMU_LUT381H + 0x006C0B01, // GFXMMU_LUT382L + 0x00098740, // GFXMMU_LUT382H + 0x006C0B01, // GFXMMU_LUT383L + 0x00098D60, // GFXMMU_LUT383H + 0x006C0B01, // GFXMMU_LUT384L + 0x00099380, // GFXMMU_LUT384H + 0x006B0C01, // GFXMMU_LUT385L + 0x00099990, // GFXMMU_LUT385H + 0x006B0C01, // GFXMMU_LUT386L + 0x00099F90, // GFXMMU_LUT386H + 0x006B0C01, // GFXMMU_LUT387L + 0x0009A590, // GFXMMU_LUT387H + 0x006B0C01, // GFXMMU_LUT388L + 0x0009AB90, // GFXMMU_LUT388H + 0x006B0C01, // GFXMMU_LUT389L + 0x0009B190, // GFXMMU_LUT389H + 0x006A0D01, // GFXMMU_LUT390L + 0x0009B780, // GFXMMU_LUT390H + 0x006A0D01, // GFXMMU_LUT391L + 0x0009BD60, // GFXMMU_LUT391H + 0x006A0D01, // GFXMMU_LUT392L + 0x0009C340, // GFXMMU_LUT392H + 0x006A0D01, // GFXMMU_LUT393L + 0x0009C920, // GFXMMU_LUT393H + 0x006A0D01, // GFXMMU_LUT394L + 0x0009CF00, // GFXMMU_LUT394H + 0x00690E01, // GFXMMU_LUT395L + 0x0009D4D0, // GFXMMU_LUT395H + 0x00690E01, // GFXMMU_LUT396L + 0x0009DA90, // GFXMMU_LUT396H + 0x00690E01, // GFXMMU_LUT397L + 0x0009E050, // GFXMMU_LUT397H + 0x00690E01, // GFXMMU_LUT398L + 0x0009E610, // GFXMMU_LUT398H + 0x00690E01, // GFXMMU_LUT399L + 0x0009EBD0, // GFXMMU_LUT399H + 0x00690E01, // GFXMMU_LUT400L + 0x0009F190, // GFXMMU_LUT400H + 0x00690E01, // GFXMMU_LUT401L + 0x0009F750, // GFXMMU_LUT401H + 0x00680F01, // GFXMMU_LUT402L + 0x0009FD00, // GFXMMU_LUT402H + 0x00680F01, // GFXMMU_LUT403L + 0x000A02A0, // GFXMMU_LUT403H + 0x00680F01, // GFXMMU_LUT404L + 0x000A0840, // GFXMMU_LUT404H + 0x00680F01, // GFXMMU_LUT405L + 0x000A0DE0, // GFXMMU_LUT405H + 0x00671001, // GFXMMU_LUT406L + 0x000A1370, // GFXMMU_LUT406H + 0x00671001, // GFXMMU_LUT407L + 0x000A18F0, // GFXMMU_LUT407H + 0x00671001, // GFXMMU_LUT408L + 0x000A1E70, // GFXMMU_LUT408H + 0x00671001, // GFXMMU_LUT409L + 0x000A23F0, // GFXMMU_LUT409H + 0x00661101, // GFXMMU_LUT410L + 0x000A2960, // GFXMMU_LUT410H + 0x00661101, // GFXMMU_LUT411L + 0x000A2EC0, // GFXMMU_LUT411H + 0x00661101, // GFXMMU_LUT412L + 0x000A3420, // GFXMMU_LUT412H + 0x00661101, // GFXMMU_LUT413L + 0x000A3980, // GFXMMU_LUT413H + 0x00651201, // GFXMMU_LUT414L + 0x000A3ED0, // GFXMMU_LUT414H + 0x00651201, // GFXMMU_LUT415L + 0x000A4410, // GFXMMU_LUT415H + 0x00651201, // GFXMMU_LUT416L + 0x000A4950, // GFXMMU_LUT416H + 0x00641301, // GFXMMU_LUT417L + 0x000A4E80, // GFXMMU_LUT417H + 0x00641301, // GFXMMU_LUT418L + 0x000A53A0, // GFXMMU_LUT418H + 0x00641301, // GFXMMU_LUT419L + 0x000A58C0, // GFXMMU_LUT419H + 0x00641301, // GFXMMU_LUT420L + 0x000A5DE0, // GFXMMU_LUT420H + 0x00631401, // GFXMMU_LUT421L + 0x000A62F0, // GFXMMU_LUT421H + 0x00631401, // GFXMMU_LUT422L + 0x000A67F0, // GFXMMU_LUT422H + 0x00631401, // GFXMMU_LUT423L + 0x000A6CF0, // GFXMMU_LUT423H + 0x00621501, // GFXMMU_LUT424L + 0x000A71E0, // GFXMMU_LUT424H + 0x00621501, // GFXMMU_LUT425L + 0x000A76C0, // GFXMMU_LUT425H + 0x00621501, // GFXMMU_LUT426L + 0x000A7BA0, // GFXMMU_LUT426H + 0x00621501, // GFXMMU_LUT427L + 0x000A8080, // GFXMMU_LUT427H + 0x00611601, // GFXMMU_LUT428L + 0x000A8550, // GFXMMU_LUT428H + 0x00611601, // GFXMMU_LUT429L + 0x000A8A10, // GFXMMU_LUT429H + 0x00611601, // GFXMMU_LUT430L + 0x000A8ED0, // GFXMMU_LUT430H + 0x00601701, // GFXMMU_LUT431L + 0x000A9380, // GFXMMU_LUT431H + 0x00601701, // GFXMMU_LUT432L + 0x000A9820, // GFXMMU_LUT432H + 0x00601701, // GFXMMU_LUT433L + 0x000A9CC0, // GFXMMU_LUT433H + 0x005F1801, // GFXMMU_LUT434L + 0x000AA150, // GFXMMU_LUT434H + 0x005F1801, // GFXMMU_LUT435L + 0x000AA5D0, // GFXMMU_LUT435H + 0x005F1801, // GFXMMU_LUT436L + 0x000AAA50, // GFXMMU_LUT436H + 0x005E1901, // GFXMMU_LUT437L + 0x000AAEC0, // GFXMMU_LUT437H + 0x005E1901, // GFXMMU_LUT438L + 0x000AB320, // GFXMMU_LUT438H + 0x005D1A01, // GFXMMU_LUT439L + 0x000AB770, // GFXMMU_LUT439H + 0x005D1A01, // GFXMMU_LUT440L + 0x000ABBB0, // GFXMMU_LUT440H + 0x005D1A01, // GFXMMU_LUT441L + 0x000ABFF0, // GFXMMU_LUT441H + 0x005C1B01, // GFXMMU_LUT442L + 0x000AC420, // GFXMMU_LUT442H + 0x005C1B01, // GFXMMU_LUT443L + 0x000AC840, // GFXMMU_LUT443H + 0x005B1C01, // GFXMMU_LUT444L + 0x000ACC50, // GFXMMU_LUT444H + 0x005B1C01, // GFXMMU_LUT445L + 0x000AD050, // GFXMMU_LUT445H + 0x005B1C01, // GFXMMU_LUT446L + 0x000AD450, // GFXMMU_LUT446H + 0x005A1D01, // GFXMMU_LUT447L + 0x000AD840, // GFXMMU_LUT447H + 0x005A1D01, // GFXMMU_LUT448L + 0x000ADC20, // GFXMMU_LUT448H + 0x00591E01, // GFXMMU_LUT449L + 0x000ADFF0, // GFXMMU_LUT449H + 0x00591E01, // GFXMMU_LUT450L + 0x000AE3B0, // GFXMMU_LUT450H + 0x00581F01, // GFXMMU_LUT451L + 0x000AE760, // GFXMMU_LUT451H + 0x00581F01, // GFXMMU_LUT452L + 0x000AEB00, // GFXMMU_LUT452H + 0x00572001, // GFXMMU_LUT453L + 0x000AEE90, // GFXMMU_LUT453H + 0x00572001, // GFXMMU_LUT454L + 0x000AF210, // GFXMMU_LUT454H + 0x00562101, // GFXMMU_LUT455L + 0x000AF580, // GFXMMU_LUT455H + 0x00562101, // GFXMMU_LUT456L + 0x000AF8E0, // GFXMMU_LUT456H + 0x00552201, // GFXMMU_LUT457L + 0x000AFC30, // GFXMMU_LUT457H + 0x00552201, // GFXMMU_LUT458L + 0x000AFF70, // GFXMMU_LUT458H + 0x00542301, // GFXMMU_LUT459L + 0x000B02A0, // GFXMMU_LUT459H + 0x00542301, // GFXMMU_LUT460L + 0x000B05C0, // GFXMMU_LUT460H + 0x00532401, // GFXMMU_LUT461L + 0x000B08D0, // GFXMMU_LUT461H + 0x00522501, // GFXMMU_LUT462L + 0x000B0BC0, // GFXMMU_LUT462H + 0x00522501, // GFXMMU_LUT463L + 0x000B0EA0, // GFXMMU_LUT463H + 0x00512601, // GFXMMU_LUT464L + 0x000B1170, // GFXMMU_LUT464H + 0x00502701, // GFXMMU_LUT465L + 0x000B1420, // GFXMMU_LUT465H + 0x00502701, // GFXMMU_LUT466L + 0x000B16C0, // GFXMMU_LUT466H + 0x004F2801, // GFXMMU_LUT467L + 0x000B1950, // GFXMMU_LUT467H + 0x004E2901, // GFXMMU_LUT468L + 0x000B1BC0, // GFXMMU_LUT468H + 0x004D2A01, // GFXMMU_LUT469L + 0x000B1E10, // GFXMMU_LUT469H + 0x004D2A01, // GFXMMU_LUT470L + 0x000B2050, // GFXMMU_LUT470H + 0x004C2B01, // GFXMMU_LUT471L + 0x000B2280, // GFXMMU_LUT471H + 0x004B2C01, // GFXMMU_LUT472L + 0x000B2490, // GFXMMU_LUT472H + 0x004A2D01, // GFXMMU_LUT473L + 0x000B2680, // GFXMMU_LUT473H + 0x00492E01, // GFXMMU_LUT474L + 0x000B2850, // GFXMMU_LUT474H + 0x00482F01, // GFXMMU_LUT475L + 0x000B2A00, // GFXMMU_LUT475H + 0x00463101, // GFXMMU_LUT476L + 0x000B2B80, // GFXMMU_LUT476H + 0x00453201, // GFXMMU_LUT477L + 0x000B2CD0, // GFXMMU_LUT477H + 0x00433401, // GFXMMU_LUT478L + 0x000B2DF0, // GFXMMU_LUT478H + 0x00413601, // GFXMMU_LUT479L + 0x000B2ED0 // GFXMMU_LUT479H +}; + +#ifdef __cplusplus +} +#endif +#endif /*__ gfxmmu_lut_H */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/core/embed/trezorhal/stm32u5/touch/sitronix.c b/core/embed/trezorhal/stm32u5/touch/sitronix.c new file mode 100644 index 000000000..3177d6dad --- /dev/null +++ b/core/embed/trezorhal/stm32u5/touch/sitronix.c @@ -0,0 +1,1214 @@ +#include STM32_HAL_H +#include TREZOR_BOARD + +#include "i2c.h" + +/** @addtogroup STM32U5x9J_DISCOVERY + * @{ + */ + +/** @addtogroup STM32U5x9J_DISCOVERY_BUS + * @{ + */ +/** @defgroup STM32U5x9J_DISCOVERY_BUS_Exported_Types BUS Exported Types + * @{ + */ +/* Common Error codes */ +#define BSP_ERROR_NONE 0 +#define BSP_ERROR_NO_INIT -1 +#define BSP_ERROR_WRONG_PARAM -2 +#define BSP_ERROR_BUSY -3 +#define BSP_ERROR_PERIPH_FAILURE -4 +#define BSP_ERROR_COMPONENT_FAILURE -5 +#define BSP_ERROR_UNKNOWN_FAILURE -6 +#define BSP_ERROR_UNKNOWN_COMPONENT -7 +#define BSP_ERROR_BUS_FAILURE -8 +#define BSP_ERROR_CLOCK_FAILURE -9 +#define BSP_ERROR_MSP_FAILURE -10 +#define BSP_ERROR_FEATURE_NOT_SUPPORTED -11 + +/* BSP OSPI error codes */ +#define BSP_ERROR_OSPI_SUSPENDED -20 +#define BSP_ERROR_OSPI_MMP_UNLOCK_FAILURE -21 +#define BSP_ERROR_OSPI_MMP_LOCK_FAILURE -22 + +/* BSP HSPI error codes */ +#define BSP_ERROR_HSPI_MMP_UNLOCK_FAILURE -31 +#define BSP_ERROR_HSPI_MMP_LOCK_FAILURE -32 + +/* BSP BUS error codes */ +#define BSP_ERROR_BUS_TRANSACTION_FAILURE -100 +#define BSP_ERROR_BUS_ARBITRATION_LOSS -101 +#define BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE -102 +#define BSP_ERROR_BUS_PROTOCOL_FAILURE -103 + +#define BSP_ERROR_BUS_MODE_FAULT -104 +#define BSP_ERROR_BUS_FRAME_ERROR -105 +#define BSP_ERROR_BUS_CRC_ERROR -106 +#define BSP_ERROR_BUS_DMA_FAILURE -107 + +/* TS I2C address */ +#define TS_I2C_ADDRESS 0xE0U + +/******************************************************************************* + * Function Name : sitronix_read_reg + * Description : Generic Reading function. It must be full-filled with either + * I2C or SPI reading functions + * Input : Register Address, length of buffer + * Output : pdata Read + *******************************************************************************/ +int32_t sitronix_read_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { + return i2c_mem_read(TOUCH_I2C_NUM, TS_I2C_ADDRESS, reg, length, pdata, length, + 1000); +} + +/******************************************************************************* + * Function Name : sitronix_write_reg + * Description : Generic Writing function. It must be full-filled with either + * I2C or SPI writing function + * Input : Register Address, pdata to be written, length of buffer + * Output : None + *******************************************************************************/ +int32_t sitronix_write_reg(uint8_t reg, uint8_t *pdata, uint16_t length) { + return i2c_mem_write(TOUCH_I2C_NUM, TS_I2C_ADDRESS, reg, length, pdata, + length, 1000); +} + +/******************************************************************************* + * Function Name : sitronix_read_data + * Description : Generic Reading function. It must be full-filled with either + * I2C or SPI reading functions + * Input : Register Address, length of buffer + * Output : pdata Read + *******************************************************************************/ +int32_t sitronix_read_data(uint8_t *pdata, uint16_t length) { + return i2c_receive(TOUCH_I2C_NUM, TS_I2C_ADDRESS, pdata, length, 1000); +} + +/* Includes ------------------------------------------------------------------*/ +/* Macros --------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#define SITRONIX_MAX_X_LENGTH 480U +#define SITRONIX_MAX_Y_LENGTH 480U + +/** @defgroup SITRONIX_Exported_Constants SITRONIX Exported Constants + * @{ + */ +#define SITRONIX_OK (0) +#define SITRONIX_ERROR (-1) + +/* Max detectable simultaneous touches */ +#define SITRONIX_MAX_DETECTABLE_TOUCH 10U + +/* Touch FT6XX6 IDs */ +#define SITRONIX_ID 0x02U + +/* Values Pn_XH and Pn_YH related */ +#define SITRONIX_TOUCH_EVT_FLAG_PRESS_DOWN 0x20U +#define SITRONIX_TOUCH_EVT_FLAG_LIFT_UP 0x60U +#define SITRONIX_TOUCH_EVT_FLAG_CONTACT 0x80U +#define SITRONIX_TOUCH_EVT_FLAG_NO_EVENT 0x00U +#define SITRONIX_TOUCH_POS_MSB_MASK 0x07U +#define SITRONIX_TOUCH_POS_LSB_MASK 0x70U + +/* Point 1 registers */ +#define SITRONIX_P1_XH_REG 0x09U +#define SITRONIX_P1_XL_REG 0x0AU +#define SITRONIX_P1_YH_REG 0x0BU +#define SITRONIX_P1_YL_REG 0x0CU + +/** + * @} + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup SITRONIX_Exported_Types SITRONIX Exported Types + * @{ + */ +typedef struct { + uint32_t Radian; + uint32_t OffsetLeftRight; + uint32_t OffsetUpDown; + uint32_t DistanceLeftRight; + uint32_t DistanceUpDown; + uint32_t DistanceZoom; +} SITRONIX_Gesture_Init_t; + +typedef struct { + uint32_t TouchDetected; + uint32_t TouchX; + uint32_t TouchY; +} SITRONIX_State_t; + +typedef struct { + uint32_t TouchDetected; + uint32_t TouchX[SITRONIX_MAX_DETECTABLE_TOUCH]; + uint32_t TouchY[SITRONIX_MAX_DETECTABLE_TOUCH]; + uint32_t TouchWeight[SITRONIX_MAX_DETECTABLE_TOUCH]; + uint32_t TouchEvent[SITRONIX_MAX_DETECTABLE_TOUCH]; + uint32_t TouchArea[SITRONIX_MAX_DETECTABLE_TOUCH]; +} SITRONIX_MultiTouch_State_t; + +typedef struct { + uint8_t IsInitialized; +} SITRONIX_Object_t; + +typedef struct { + uint8_t MultiTouch; + uint8_t Gesture; + uint8_t MaxTouch; + uint32_t MaxXl; + uint32_t MaxYl; +} SITRONIX_Capabilities_t; + +typedef struct { + int32_t (*Init)(SITRONIX_Object_t *); + int32_t (*DeInit)(SITRONIX_Object_t *); + int32_t (*GestureConfig)(SITRONIX_Object_t *, SITRONIX_Gesture_Init_t *); + int32_t (*ReadID)(SITRONIX_Object_t *, uint32_t *); + int32_t (*GetState)(SITRONIX_Object_t *, SITRONIX_State_t *); + int32_t (*GetMultiTouchState)(SITRONIX_Object_t *, + SITRONIX_MultiTouch_State_t *); + int32_t (*GetGesture)(SITRONIX_Object_t *, uint8_t *); + int32_t (*GetCapabilities)(SITRONIX_Object_t *, SITRONIX_Capabilities_t *); + int32_t (*EnableIT)(SITRONIX_Object_t *); + int32_t (*DisableIT)(SITRONIX_Object_t *); + int32_t (*ClearIT)(SITRONIX_Object_t *); + int32_t (*ITStatus)(SITRONIX_Object_t *); +} SITRONIX_TS_Drv_t; + +int32_t SITRONIX_Init(SITRONIX_Object_t *pObj); +int32_t SITRONIX_DeInit(SITRONIX_Object_t *pObj); +int32_t SITRONIX_GestureConfig(SITRONIX_Object_t *pObj, + SITRONIX_Gesture_Init_t *GestureInit); +int32_t SITRONIX_ReadID(SITRONIX_Object_t *pObj, uint32_t *Id); +int32_t SITRONIX_GetState(SITRONIX_Object_t *pObj, SITRONIX_State_t *State); +int32_t SITRONIX_GetMultiTouchState(SITRONIX_Object_t *pObj, + SITRONIX_MultiTouch_State_t *State); +int32_t SITRONIX_GetGesture(SITRONIX_Object_t *pObj, uint8_t *GestureId); +int32_t SITRONIX_EnableIT(SITRONIX_Object_t *pObj); +int32_t SITRONIX_DisableIT(SITRONIX_Object_t *pObj); +int32_t SITRONIX_ITStatus(SITRONIX_Object_t *pObj); +int32_t SITRONIX_ClearIT(SITRONIX_Object_t *pObj); +int32_t SITRONIX_GetCapabilities(SITRONIX_Object_t *pObj, + SITRONIX_Capabilities_t *Capabilities); + +/* Touch screen driver structure initialization */ +SITRONIX_TS_Drv_t SITRONIX_TS_Driver = { + SITRONIX_Init, SITRONIX_DeInit, SITRONIX_GestureConfig, + SITRONIX_ReadID, SITRONIX_GetState, SITRONIX_GetMultiTouchState, + SITRONIX_GetGesture, SITRONIX_GetCapabilities, SITRONIX_EnableIT, + SITRONIX_DisableIT, SITRONIX_ClearIT, SITRONIX_ITStatus}; +/** + * @} + */ + +/** @defgroup SITRONIX_Private_Function_Prototypes SITRONIX Private Function + * Prototypes + * @{ + */ +#if (SITRONIX_AUTO_CALIBRATION_ENABLED == 1) +static int32_t SITRONIX_TS_Calibration(SITRONIX_Object_t *pObj); +static int32_t SITRONIX_Delay(SITRONIX_Object_t *pObj, uint32_t Delay); +#endif /* SITRONIX_AUTO_CALIBRATION_ENABLED == 1 */ +static int32_t SITRONIX_DetectTouch(SITRONIX_Object_t *pObj); +// static int32_t ReadRegWrap(void *handle, uint8_t Reg, uint8_t *Data, +// uint16_t Length); +// static int32_t WriteRegWrap(void *handle, uint8_t Reg, uint8_t *Data, +// uint16_t Length); +// static int32_t ReadDataWrap(void *handle, uint8_t *pData, uint16_t Length); + +/** + * @} + */ + +/** @defgroup SITRONIX_Exported_Functions SITRONIX Exported Functions + * @{ + */ + +/** + * @brief Get SITRONIX sensor capabilities + * @param pObj Component object pointer + * @param Capabilities pointer to SITRONIX sensor capabilities + * @retval Component status + */ +int32_t SITRONIX_GetCapabilities(SITRONIX_Object_t *pObj, + SITRONIX_Capabilities_t *Capabilities) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Store component's capabilities */ + Capabilities->MultiTouch = 1; + Capabilities->Gesture = + 0; /* Gesture feature is currently not activated on FW chipset */ + Capabilities->MaxTouch = SITRONIX_MAX_DETECTABLE_TOUCH; + Capabilities->MaxXl = SITRONIX_MAX_X_LENGTH; + Capabilities->MaxYl = SITRONIX_MAX_Y_LENGTH; + + return SITRONIX_OK; +} + +/** + * @brief Initialize the SITRONIX communication bus + * from MCU to SITRONIX : ie I2C channel initialization (if required). + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_Init(SITRONIX_Object_t *pObj) { + int32_t ret = SITRONIX_OK; + uint8_t data[28U]; + + if (pObj->IsInitialized == 0U) { + if (sitronix_read_data(data, (uint16_t)sizeof(data)) != SITRONIX_OK) { + ret = SITRONIX_ERROR; + } + + pObj->IsInitialized = 1; + } + + if (ret != SITRONIX_OK) { + ret = SITRONIX_ERROR; + } + + return ret; +} + +/** + * @brief De-Initialize the SITRONIX communication bus + * from MCU to SITRONIX : ie I2C channel initialization (if required). + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_DeInit(SITRONIX_Object_t *pObj) { + if (pObj->IsInitialized == 1U) { + pObj->IsInitialized = 0; + } + + return SITRONIX_OK; +} + +/** + * @brief Configure the SITRONIX gesture + * from MCU to SITRONIX : ie I2C channel initialization (if required). + * @param pObj Component object pointer + * @param GestureInit Gesture init structure + * @retval Component status + */ +int32_t SITRONIX_GestureConfig(SITRONIX_Object_t *pObj, + SITRONIX_Gesture_Init_t *GestureInit) { + return SITRONIX_ERROR; +} + +/** + * @brief Read the SITRONIX device ID, pre initialize I2C in case of need to be + * able to read the SITRONIX device ID, and verify this is a SITRONIX. + * @param pObj Component object pointer + * @param Id Pointer to component's ID + * @retval Component status + */ +int32_t SITRONIX_ReadID(SITRONIX_Object_t *pObj, uint32_t *Id) { + int32_t ret = SITRONIX_OK; + uint8_t data[28]; + uint8_t trial = 0; + + for (trial = 0; trial < 10; trial++) { + if (sitronix_read_data(data, 28) != SITRONIX_OK) { + ret = SITRONIX_ERROR; + } else { + if ((uint32_t)data[0] == SITRONIX_ID) { + *Id = (uint32_t)data[0]; + return ret; + } + } + } + return ret; +} + +uint8_t sitronix_touching = 0; + +/** + * @brief Get the touch screen X and Y positions values + * @param pObj Component object pointer + * @param State Single Touch structure pointer + * @retval Component status. + */ +int32_t SITRONIX_GetState(SITRONIX_Object_t *pObj, SITRONIX_State_t *State) { + int32_t ret = SITRONIX_OK; + uint8_t data[64]; + + State->TouchDetected = (uint32_t)SITRONIX_DetectTouch(pObj); + if (sitronix_read_data(data, (uint16_t)sizeof(data)) != SITRONIX_OK) { + ret = SITRONIX_ERROR; + } else { + if ((uint32_t)data[2] & 0x80) { + sitronix_touching = 1; + } else { + sitronix_touching = 0; + } + + State->TouchX = (((uint32_t)data[2] & SITRONIX_TOUCH_POS_LSB_MASK) << 4); + + /* Send back first ready X position to caller */ + State->TouchX = ((((uint32_t)data[2] & SITRONIX_TOUCH_POS_LSB_MASK) << 4) | + ((uint32_t)data[3])); + /* Send back first ready Y position to caller */ + State->TouchY = (((uint32_t)data[2] & SITRONIX_TOUCH_POS_MSB_MASK) << 8) | + ((uint32_t)data[4]); + } + + return ret; +} + +/** + * @brief Get the touch screen Xn and Yn positions values in multi-touch mode + * @param pObj Component object pointer + * @param State Multi Touch structure pointer + * @retval Component status. + */ +int32_t SITRONIX_GetMultiTouchState(SITRONIX_Object_t *pObj, + SITRONIX_MultiTouch_State_t *State) { + int32_t ret = SITRONIX_OK; + uint8_t data[28]; + + State->TouchDetected = (uint32_t)SITRONIX_DetectTouch(pObj); + + if (sitronix_read_reg(SITRONIX_P1_XH_REG, data, (uint16_t)sizeof(data)) != + SITRONIX_OK) { + ret = SITRONIX_ERROR; + } else { + /* To be implemented */ + } + + return ret; +} + +/** + * @brief Get Gesture ID + * @param pObj Component object pointer + * @param GestureId gesture ID + * @retval Component status + */ +int32_t SITRONIX_GetGesture(SITRONIX_Object_t *pObj, uint8_t *GestureId) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Always return SITRONIX_OK as feature not supported by SITRONIX */ + return SITRONIX_ERROR; +} + +/** + * @brief Configure the SITRONIX device to generate IT on given INT pin + * connected to MCU as EXTI. + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_EnableIT(SITRONIX_Object_t *pObj) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Always return SITRONIX_OK as feature not supported by SITRONIX */ + return SITRONIX_ERROR; +} + +/** + * @brief Configure the SITRONIX device to stop generating IT on the given INT + * pin connected to MCU as EXTI. + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_DisableIT(SITRONIX_Object_t *pObj) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Always return SITRONIX_OK as feature not supported by SITRONIX */ + return SITRONIX_ERROR; +} + +/** + * @brief Get IT status from SITRONIX interrupt status registers + * Should be called Following an EXTI coming to the MCU to know the + * detailed reason of the interrupt. + * @note : This feature is not supported by SITRONIX. + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_ITStatus(SITRONIX_Object_t *pObj) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Always return SITRONIX_OK as feature not supported by SITRONIX */ + return SITRONIX_ERROR; +} + +/** + * @brief Clear IT status in SITRONIX interrupt status clear registers + * Should be called Following an EXTI coming to the MCU. + * @note : This feature is not supported by SITRONIX. + * @param pObj Component object pointer + * @retval Component status + */ +int32_t SITRONIX_ClearIT(SITRONIX_Object_t *pObj) { + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + /* Always return SITRONIX_OK as feature not supported by SITRONIX */ + return SITRONIX_ERROR; +} + +/** + * @} + */ + +/** @defgroup SITRONIX_Private_Functions SITRONIX Private Functions + * @{ + */ + +/** + * @brief Return if there is touches detected or not. + * Try to detect new touches and forget the old ones (reset internal + * global variables). + * @param pObj Component object pointer + * @retval Number of active touches detected (can be between 0 and10) or + * SITRONIX_ERROR in case of error + */ +__attribute__((optimize("-O0"))) int32_t SITRONIX_DetectTouch( + SITRONIX_Object_t *pObj) { + int32_t ret; + uint8_t nb_touch = 0; + static uint8_t first_event = 0; + uint8_t data[28]; + + if (sitronix_read_data((uint8_t *)&data, 28) != SITRONIX_OK) { + ret = SITRONIX_ERROR; + } else { + if (first_event == 0) { + if ((data[0] == 0x09)) { + nb_touch = 1; + first_event = 1; + } else { + nb_touch = 0; + } + } else { + if (data[8] == 0x60) { + nb_touch = 0; + } else { + nb_touch = 1; + } + } + ret = (int32_t)nb_touch; + } + + return ret; +} +// +///** +// * @brief Wrap IO bus read function to component register red function +// * @param handle Component object handle +// * @param Reg The target register address to read +// * @param pData The target register value to be read +// * @param Length buffer size to be read +// * @retval Component status. +// */ +// static int32_t ReadRegWrap(void *handle, uint8_t Reg, uint8_t *pData, +// uint16_t Length) { +// return i2c_mem_read(TOUCH_I2C_NUM, TS_I2C_ADDRESS, Reg, Length, pData, +// Length, 1000); +//} +// +///** +// * @brief Wrap IO bus write function to component register write function +// * @param handle Component object handle +// * @param Reg The target register address to write +// * @param pData The target register value to be written +// * @param Length buffer size to be written +// * @retval Component status. +// */ +// static int32_t WriteRegWrap(void *handle, uint8_t Reg, uint8_t *pData, +// uint16_t Length) { +// return i2c_mem_write(TOUCH_I2C_NUM, TS_I2C_ADDRESS, Reg, Length, pData, +// Length, 1000); +//} +// +///** +// * @brief Wrap IO bus read function to component register red function +// * @param handle Component object handle +// * @param pData The target register value to be read +// * @param Length buffer size to be read +// * @retval Component status. +// */ +// static int32_t ReadDataWrap(void *handle, uint8_t *pData, uint16_t Length) { +// return i2c_receive(TOUCH_I2C_NUM, TS_I2C_ADDRESS, pData, Length, 1000); +//} + +/** + ****************************************************************************** + * @file stm32u5x9j_discovery_ts.c + * @author MCD Application Team + * @brief This file provides a set of functions needed to manage the Touch + * Screen on STM32U5x9J-DISCOVERY board. + @verbatim + 1. How To use this driver: + -------------------------- + - This driver is used to drive the touch screen module of the + STM32U5x9J-DISCOVERY board on the LCD mounted on MB1829A daughter board. The + touch screen driver IC is a SITRONIX. + + 2. Driver description: + --------------------- + + Initialization steps: + o Initialize the TS using the BSP_TS_Init() function. You can select + display orientation with "Orientation" parameter of TS_Init_t structure + (portrait, landscape, portrait with 180 degrees rotation or landscape + with 180 degrees rotation). The LCD size properties (width and height) + are also parameters of TS_Init_t and depend on the orientation + selected. + + + Touch screen use + o Call BSP_TS_EnableIT() (BSP_TS_DisableIT()) to enable (disable) touch + screen interrupt. BSP_TS_Callback() is called when TS interrupt occurs. + o Call BSP_TS_GetState() to get the current touch status (detection and + coordinates). + o Call BSP_TS_Set_Orientation() to change the current orientation. + Call BSP_TS_Get_Orientation() to get the current orientation. + o Call BSP_TS_GetCapabilities() to get the SITRONIX capabilities. + o SITRONIX doesn't support multi touch and gesture features. + BSP_TS_Get_MultiTouchState(), BSP_TS_GestureConfig() and + BSP_TS_GetGestureId() functions will return + BSP_ERROR_FEATURE_NOT_SUPPORTED. + + + De-initialization steps: + o De-initialize the touch screen using the BSP_TS_DeInit() function. + + @endverbatim + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* TS instances */ +#define TS_INSTANCES_NBR 1U +#define TS_TOUCH_NBR 10U + +/* TS orientations */ +#define TS_ORIENTATION_PORTRAIT 0U +#define TS_ORIENTATION_LANDSCAPE 1U +#define TS_ORIENTATION_PORTRAIT_ROT180 2U +#define TS_ORIENTATION_LANDSCAPE_ROT180 3U + +/** @defgroup STM32U5x9J_DISCOVERY_TS_Exported_Types TS Exported Types + * @{ + */ +typedef struct { + uint32_t Width; /* Screen width */ + uint32_t Height; /* Screen height */ + uint32_t Orientation; /* Touch screen orientation */ + uint32_t Accuracy; /* Expressed in pixel and means the x or y difference vs + old position to consider the new values valid */ +} TS_Init_t; + +typedef struct { + uint8_t MultiTouch; + uint8_t Gesture; + uint8_t MaxTouch; + uint32_t MaxXl; + uint32_t MaxYl; +} TS_Capabilities_t; + +typedef struct { + uint32_t TouchDetected; + uint32_t TouchX; + uint32_t TouchY; +} TS_State_t; + +typedef struct { + uint32_t TouchDetected; + uint32_t TouchX[2]; + uint32_t TouchY[2]; + uint32_t TouchWeight[2]; + uint32_t TouchEvent[2]; + uint32_t TouchArea[2]; +} TS_MultiTouch_State_t; + +typedef struct { + uint32_t Radian; + uint32_t OffsetLeftRight; + uint32_t OffsetUpDown; + uint32_t DistanceLeftRight; + uint32_t DistanceUpDown; + uint32_t DistanceZoom; +} TS_Gesture_Config_t; + +typedef struct { + uint32_t Width; + uint32_t Height; + uint32_t Orientation; + uint32_t Accuracy; + uint32_t MaxX; + uint32_t MaxY; + uint32_t PreviousX[TS_TOUCH_NBR]; + uint32_t PreviousY[TS_TOUCH_NBR]; +} TS_Ctx_t; + +typedef struct { + int32_t (*Init)(void *); + int32_t (*DeInit)(void *); + int32_t (*GestureConfig)(void *, void *); + int32_t (*ReadID)(void *, uint32_t *); + int32_t (*GetState)(void *, void *); + int32_t (*GetMultiTouchState)(void *, void *); + int32_t (*GetGesture)(void *, void *); + int32_t (*GetCapabilities)(void *, void *); + int32_t (*EnableIT)(void *); + int32_t (*DisableIT)(void *); + int32_t (*ClearIT)(void *); + int32_t (*ITStatus)(void *); +} TS_Drv_t; + +/* DSI TS INT pin */ +#define TS_INT_PIN GPIO_PIN_8 +#define TS_INT_GPIO_PORT GPIOE +#define TS_INT_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE() +#define TS_INT_GPIO_CLK_DISABLE() __HAL_RCC_GPIOE_CLK_DISABLE() +#define TS_INT_EXTI_IRQn EXTI8_IRQn + +/* Includes ------------------------------------------------------------------*/ +//#include "stm32u5x9j_discovery_ts.h" +//#include "stm32u5x9j_discovery.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup STM32U5x9J_DISCOVERY + * @{ + */ + +/** @defgroup STM32U5x9J_DISCOVERY_TS TS + * @{ + */ + +/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_Defines TS Private Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_TypesDefinitions TS Private + * TypesDefinitions + * @{ + */ +typedef void (*BSP_EXTI_LineCallback)(void); +/** + * @} + */ + +/** @addtogroup STM32U5x9J_DISCOVERY_TS_Exported_Variables TS Exported Variables + * @{ + */ +void *Ts_CompObj[TS_INSTANCES_NBR] = {0}; +TS_Drv_t *Ts_Drv[TS_INSTANCES_NBR] = {0}; +TS_Ctx_t Ts_Ctx[TS_INSTANCES_NBR] = {0}; +EXTI_HandleTypeDef hts_exti[TS_INSTANCES_NBR]; +IRQn_Type Ts_IRQn[TS_INSTANCES_NBR] = {EXTI15_IRQn}; + +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_FunctionPrototypes TS Private + * Function Prototypes + * @{ + */ +static int32_t SITRONIX_Probe(uint32_t Instance); + +/** + * @} + */ + +/** @addtogroup STM32U5x9J_DISCOVERY_TS_Exported_Functions + * @{ + */ +/** + * @brief Initialize the TS. + * @param Instance TS Instance. + * @param TS_Init Pointer to TS initialization structure. + * @retval BSP status. + */ +int32_t BSP_TS_Init(uint32_t Instance, TS_Init_t *TS_Init) { + int32_t status = BSP_ERROR_NONE; + + if ((TS_Init == NULL) || (Instance >= TS_INSTANCES_NBR)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Probe the TS driver */ + if (SITRONIX_Probe(Instance) != BSP_ERROR_NONE) { + status = BSP_ERROR_COMPONENT_FAILURE; + } else { + TS_Capabilities_t Capabilities; + uint32_t i; + /* Store parameters on TS context */ + Ts_Ctx[Instance].Width = TS_Init->Width; + Ts_Ctx[Instance].Height = TS_Init->Height; + Ts_Ctx[Instance].Orientation = TS_Init->Orientation; + Ts_Ctx[Instance].Accuracy = TS_Init->Accuracy; + /* Get capabilities to retrieve maximum values of X and Y */ + if (Ts_Drv[Instance]->GetCapabilities(Ts_CompObj[Instance], + &Capabilities) < 0) { + status = BSP_ERROR_COMPONENT_FAILURE; + } else { + /* Store maximum X and Y on context */ + Ts_Ctx[Instance].MaxX = Capabilities.MaxXl; + Ts_Ctx[Instance].MaxY = Capabilities.MaxYl; + /* Initialize previous position in order to always detect first touch */ + for (i = 0; i < TS_TOUCH_NBR; i++) { + Ts_Ctx[Instance].PreviousX[i] = + TS_Init->Width + TS_Init->Accuracy + 1U; + Ts_Ctx[Instance].PreviousY[i] = + TS_Init->Height + TS_Init->Accuracy + 1U; + } + } + } + } + + return status; +} + +/** + * @brief De-Initialize the TS. + * @param Instance TS Instance. + * @retval BSP status. + */ +int32_t BSP_TS_DeInit(uint32_t Instance) { + int32_t status = BSP_ERROR_NONE; + + if (Instance >= TS_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* De-Init the TS driver */ + if (Ts_Drv[Instance]->DeInit(Ts_CompObj[Instance]) < 0) { + status = BSP_ERROR_COMPONENT_FAILURE; + } + } + + return status; +} + +/** + * @brief Enable the TS interrupt. + * @param Instance TS Instance. + * @retval BSP status. + */ +int32_t BSP_TS_EnableIT(uint32_t Instance) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(Instance); + + GPIO_InitTypeDef gpio_init_structure; + + __HAL_RCC_GPIOE_CLK_ENABLE(); + + /* Configure Interrupt mode for TS detection pin */ + gpio_init_structure.Pin = TS_INT_PIN; + gpio_init_structure.Pull = GPIO_PULLUP; + gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; + gpio_init_structure.Mode = GPIO_MODE_IT_FALLING; + HAL_GPIO_Init(TS_INT_GPIO_PORT, &gpio_init_structure); + + /* Enable and set Touch screen EXTI Interrupt to the lowest priority */ + HAL_NVIC_SetPriority((IRQn_Type)(TS_INT_EXTI_IRQn), 0x0F, 0x00); + HAL_NVIC_EnableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn)); + + return BSP_ERROR_NONE; +} + +/** + * @brief Disable the TS interrupt. + * @param Instance TS Instance. + * @retval BSP status. + */ +int32_t BSP_TS_DisableIT(uint32_t Instance) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(Instance); + + /* To be Implemented */ + return BSP_ERROR_NONE; +} + +/** + * @brief Set the TS orientation. + * @param Instance TS Instance. + * @param Orientation TS orientation. + * @retval BSP status. + */ +int32_t BSP_TS_Set_Orientation(uint32_t Instance, uint32_t Orientation) { + int32_t status = BSP_ERROR_NONE; + uint32_t temp; + uint32_t i; + + if ((Instance >= TS_INSTANCES_NBR) || + (Orientation > TS_ORIENTATION_LANDSCAPE_ROT180)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Update TS context if orientation is changed from/to portrait to/from + * landscape */ + if ((((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE) || + (Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)) && + ((Orientation == TS_ORIENTATION_PORTRAIT) || + (Orientation == TS_ORIENTATION_PORTRAIT_ROT180))) || + (((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_PORTRAIT) || + (Ts_Ctx[Instance].Orientation == TS_ORIENTATION_PORTRAIT_ROT180)) && + ((Orientation == TS_ORIENTATION_LANDSCAPE) || + (Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)))) { + /* Invert width and height */ + temp = Ts_Ctx[Instance].Width; + Ts_Ctx[Instance].Width = Ts_Ctx[Instance].Height; + Ts_Ctx[Instance].Height = temp; + /* Invert MaxX and MaxY */ + temp = Ts_Ctx[Instance].MaxX; + Ts_Ctx[Instance].MaxX = Ts_Ctx[Instance].MaxY; + Ts_Ctx[Instance].MaxY = temp; + } + /* Store orientation on TS context */ + Ts_Ctx[Instance].Orientation = Orientation; + /* Reset previous position */ + for (i = 0; i < TS_TOUCH_NBR; i++) { + Ts_Ctx[Instance].PreviousX[i] = + Ts_Ctx[Instance].Width + Ts_Ctx[Instance].Accuracy + 1U; + Ts_Ctx[Instance].PreviousY[i] = + Ts_Ctx[Instance].Height + Ts_Ctx[Instance].Accuracy + 1U; + } + } + + return status; +} + +/** + * @brief Get the TS orientation. + * @param Instance TS Instance. + * @param Orientation Pointer to TS orientation. + * @retval BSP status. + */ +int32_t BSP_TS_Get_Orientation(uint32_t Instance, uint32_t *Orientation) { + int32_t status = BSP_ERROR_NONE; + + if ((Instance >= TS_INSTANCES_NBR) || (Orientation == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Get orientation from TS context */ + *Orientation = Ts_Ctx[Instance].Orientation; + } + + return status; +} + +/** + * @brief Get position of a single touch. + * @param Instance TS Instance. + * @param TS_State Pointer to single touch structure. + * @retval BSP status. + */ +int32_t BSP_TS_GetState(uint32_t Instance, TS_State_t *TS_State) { + int32_t status = BSP_ERROR_NONE; + uint32_t x_oriented; + uint32_t y_oriented; + uint32_t x_diff; + uint32_t y_diff; + + if (Instance >= TS_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + SITRONIX_State_t state; + + /* Get each touch coordinates */ + if (Ts_Drv[Instance]->GetState(Ts_CompObj[Instance], &state) < 0) { + status = BSP_ERROR_COMPONENT_FAILURE; + } /* Check and update the number of touches active detected */ + else if (state.TouchDetected != 0U) { + x_oriented = /*Ts_Ctx[Instance].MaxX -*/ state.TouchX; + y_oriented = /*Ts_Ctx[Instance].MaxY -*/ state.TouchY; + + /* Apply boundary */ + TS_State->TouchX = + (x_oriented * Ts_Ctx[Instance].Width) / (Ts_Ctx[Instance].MaxX); + TS_State->TouchY = + (y_oriented * Ts_Ctx[Instance].Height) / (Ts_Ctx[Instance].MaxY); + /* Store Current TS state */ + TS_State->TouchDetected = state.TouchDetected; + + /* Check accuracy */ + x_diff = (TS_State->TouchX > Ts_Ctx[Instance].PreviousX[0]) + ? (TS_State->TouchX - Ts_Ctx[Instance].PreviousX[0]) + : (Ts_Ctx[Instance].PreviousX[0] - TS_State->TouchX); + + y_diff = (TS_State->TouchY > Ts_Ctx[Instance].PreviousY[0]) + ? (TS_State->TouchY - Ts_Ctx[Instance].PreviousY[0]) + : (Ts_Ctx[Instance].PreviousY[0] - TS_State->TouchY); + + if ((x_diff > Ts_Ctx[Instance].Accuracy) || + (y_diff > Ts_Ctx[Instance].Accuracy)) { + /* New touch detected */ + Ts_Ctx[Instance].PreviousX[0] = TS_State->TouchX; + Ts_Ctx[Instance].PreviousY[0] = TS_State->TouchY; + } else { + TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0]; + TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0]; + } + } else { + TS_State->TouchDetected = 0U; + TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0]; + TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0]; + } + } + + return status; +} + +/** + * @brief Get positions of multiple touch. + * @param Instance TS Instance. + * @param TS_State Pointer to multiple touch structure. + * @retval BSP status. + */ +int32_t BSP_TS_Get_MultiTouchState(const uint32_t Instance, + TS_MultiTouch_State_t *TS_State) { + int32_t status; + + UNUSED(TS_State); + + if (Instance >= TS_INSTANCES_NBR) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Feature not supported in this release */ + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } + + return status; +} + +/** + * @brief Configure gesture on TS. + * @param Instance TS Instance. + * @param GestureConfig Pointer to gesture configuration structure. + * @retval BSP status. + */ +int32_t BSP_TS_GestureConfig(const uint32_t Instance, + TS_Gesture_Config_t *GestureConfig) { + int32_t status; + + if ((Instance >= TS_INSTANCES_NBR) || (GestureConfig == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Feature not supported */ + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } + + return status; +} + +/** + * @brief Get gesture. + * @param Instance TS Instance. + * @param GestureId Pointer to gesture. + * @retval BSP status. + */ +int32_t BSP_TS_GetGestureId(const uint32_t Instance, uint32_t *GestureId) { + int32_t status; + + if ((Instance >= TS_INSTANCES_NBR) || (GestureId == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Feature not supported */ + status = BSP_ERROR_FEATURE_NOT_SUPPORTED; + } + + return status; +} + +/** + * @brief Get the TS capabilities. + * @param Instance TS Instance. + * @param Capabilities Pointer to TS capabilities structure. + * @retval BSP status. + */ +int32_t BSP_TS_GetCapabilities(uint32_t Instance, + TS_Capabilities_t *Capabilities) { + int32_t status = BSP_ERROR_NONE; + + if ((Instance >= TS_INSTANCES_NBR) || (Capabilities == NULL)) { + status = BSP_ERROR_WRONG_PARAM; + } else { + /* Get the TS driver capabilities */ + if (Ts_Drv[Instance]->GetCapabilities(Ts_CompObj[Instance], Capabilities) < + 0) { + status = BSP_ERROR_COMPONENT_FAILURE; + } else { + /* Update maximum X and Y according orientation */ + if ((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE) || + (Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)) { + uint32_t tmp; + tmp = Capabilities->MaxXl; + Capabilities->MaxXl = Capabilities->MaxYl; + Capabilities->MaxYl = tmp; + } + } + } + + return status; +} + +/** + * @brief TS Callback. + * @param Instance TS Instance. + * @retval None. + */ +__weak void BSP_TS_Callback(uint32_t Instance) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(Instance); + + /* This function should be implemented by the user application. + It is called into this driver when an event on TS touch detection */ +} + +/** + * @brief BSP TS interrupt handler. + * @param Instance TS Instance. + * @retval None. + */ +void BSP_TS_IRQHandler(uint32_t Instance) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(Instance); + + /* To be implemented */ +} +/** + * @} + */ + +/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_Functions TS Private Functions + * @{ + */ +/** + * @brief Probe the SITRONIX TS driver. + * @param Instance TS Instance. + * @retval BSP status. + */ +static int32_t SITRONIX_Probe(uint32_t Instance) { + int32_t status; + static SITRONIX_Object_t SITRONIXObj; + + Ts_CompObj[Instance] = &SITRONIXObj; + Ts_Drv[Instance] = (TS_Drv_t *)&SITRONIX_TS_Driver; + if (Ts_Drv[Instance]->Init(Ts_CompObj[Instance]) < 0) { + status = BSP_ERROR_COMPONENT_FAILURE; + } else { + status = BSP_ERROR_NONE; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#include +#include "touch.h" + +void touch_init(void) { + TS_Init_t TsInit; + + /* Initialize the TouchScreen */ + TsInit.Width = 480; + TsInit.Height = 480; + TsInit.Orientation = 0; + TsInit.Accuracy = 10; + + BSP_TS_Init(0, &TsInit); +} +void touch_power_on(void) {} +void touch_power_off(void) {} +void touch_sensitivity(uint8_t value) {} + +uint32_t touch_is_detected(void) { return sitronix_touching != 0; } + +uint32_t touch_read(void) { + TS_State_t state = {0}; + static uint32_t xy = 0; + static TS_State_t state_last = {0}; + // static uint16_t first = 1; + static uint16_t touching = 0; + + BSP_TS_GetState(0, &state); + + state.TouchDetected = touch_is_detected(); + state.TouchY = state.TouchY > 120 ? state.TouchY - 120 : 0; + state.TouchX = state.TouchX > 120 ? state.TouchX - 120 : 0; + + if (!touch_is_detected()) { + // if (state.TouchDetected == 0) { + if (touching) { + // touch end + memcpy(&state_last, &state, sizeof(state)); + touching = 0; + return TOUCH_END | xy; + } + return 0; + } + + if (state.TouchDetected == 0) { + return 0; + } + + // if (first != 0) { + // memcpy(&state_last, &state, sizeof(state)); + // first = 0; + // return 0; + // } + + if ((state.TouchDetected == 0 && state_last.TouchDetected == 0) || + memcmp(&state, &state_last, sizeof(state)) == 0) { + // no change detected + return 0; + } + + xy = touch_pack_xy(state.TouchX, state.TouchY); + + if (state.TouchDetected && !state_last.TouchDetected) { + // touch start + memcpy(&state_last, &state, sizeof(state)); + touching = 1; + return TOUCH_START | xy; + } else if (!state.TouchDetected && state_last.TouchDetected) { + // touch end + memcpy(&state_last, &state, sizeof(state)); + touching = 0; + return TOUCH_END | xy; + } else { + // touch move + memcpy(&state_last, &state, sizeof(state)); + return TOUCH_MOVE | xy; + } + + return 0; +} diff --git a/core/embed/trezorhal/stm32u5/touch/sitronix.h b/core/embed/trezorhal/stm32u5/touch/sitronix.h new file mode 100644 index 000000000..e69de29bb diff --git a/core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.json b/core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.json new file mode 100644 index 000000000..82c5dc44e --- /dev/null +++ b/core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.json @@ -0,0 +1,20 @@ +{ + "header_len": 4608, + "text": "DEV ONLY, DO NOT USE!", + "hw_model": "D002", + "expiry": 0, + "version": [0, 0], + "sig_m": 2, + "trust": { + "allow_run_with_secret": false, + "show_vendor_string": false, + "require_user_click": false, + "red_background": false, + "delay": 0 + }, + "pubkeys": [ + "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351", + "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869", + "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef" + ] +} diff --git a/core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.toif b/core/embed/vendorheader/D002/vendor_dev_DO_NOT_SIGN.toif new file mode 100644 index 0000000000000000000000000000000000000000..3b187a7006fb93342ae4e8459e995f53f2c5423f GIT binary patch literal 3942 zcmZu!>2K6k6fM(2+o7p+heEgMMwt$!8q8e@zIqQcZ;f6<{W|D~kRaXIYF(}_A_AlGs;-)31N|`}ppdGns*5j&*n)Hz z@N;ra^16tK2!30SZ%h7iepvbl(qKQJnJ}umIzwfg1=S?x9;nE)F>r4JXg9hNSLvne6P&Nf#PPxTsu~L;F#*v z%U}6m^fz)z9;emf0RzqRqIXq74~ks|b>~wMzhy&KuLkMnlH&?WVf5xjZ-FX`1_AL9 zW^gkkXH(4jXQ6?oAsm0)$lGC~{>doKG&_Y?@Ih$JlcJ~w0s zgf$bW&@(piMgl$y$O=)}+B~!rs(y}PF$ADQ6!;m<8iiFqx-L^S1xDQU2^4gx3$FP+ zdhV4u4RW*1S|JA^)V?9bsRYoqGob4ynKX0Ua*&yO;LxzQP0XRc-#Q7auy3Ee zhTS0GwFD9m@bEqv3{62-9CW0#sh^5FpQ%|qwHD0dvX?Z}%{;ebyEf9RzK3H5!li*p zhj$XnWUkE!zr@tAm5YoZ0h_?jrvT7DwmKZ@A!Fuk>>Ixc1h4}En~{wM@Tmc=9NsC0 zuvrujFlgSfm$hXl0j@-^T_+}ZvJ&K89?#r7F>33DFAKt#%+sg#F`2o6nJ;1{gl}-M zD}i}k12MRGRRiPI(`t5N1h6skA$$)CyiFc;sF)(I<%VSNX8=!SR!w~E8}SJbL#YeL zB-e4NWQgjFvh|lw^>ng+lNnRB4_}C3QhC<|jK|20023Q#GJqtGTW|J>k!N%#wXw`V zhEKFLcC1h=rlEE_Q&}L6ecXQ~jC$1yjPT|W?Gx{58CU6o%tII)kFHFpYOcv-YEX;c z_!=I2n&x(>JJ^$}x!RYnPbGuw;ub(UWJFAGv1Y9_ZXUxZ2NKT5v@JMtm3PWNpsK+I z!V{QOfZYJ7NElsY6^L&lj|K2l%;dqvGvjF;;sgKsHgmRWCW*ZS%sN3STa2tpJ0$GV z2jKl&BotzUH07xmwRt8U!}bP{DF`IsW1@k1>@EVWf-KL$U@WwvP(RK!0Vame1B0Xh z%gdFZR6ox^00CxtTAztAQR>unIPTS*TQv|LFRnJ?R#l=^m)6voc zwS5o-wDPL(7SBPZ(m?qTAXUE`>|{LzS3ZMwFrR=SKkdP*d37CLeIrw?^XvzQ%Qq$! zXf0qJd%4Qp7eSlZ9sS%+5a)7s!kW%zxJ=G2rhs>aFJa9OM{MIPNf|^n8?1>D^-6Se zQf+}7%x#?&Ab`P_h{>}wLD&T*hOH~=-XWdEw4ESdMBCz>R)Cdo)Z&=}mnw{JcFHg4e>V_OGS$`YV}ps{6RUO(wOo**uV~ z<*W`6;=THXSZxee!()GhO1QUR-kErbQ87jha~m`hMtT(}#X12lgjl0NywoH7=LAz@ zWds0kR-HHMk3(uDOE(;hG>9_=^Z%ZI{{l>gd+Q}{RNvCS3*%UT(4?O}lu65ln-+&~ zDR&Km)Iqkg3o7i9500k~!{P#hQq6h}mW35|M~Sal`;@~Z0&~1h^AL|4bo&HIL%(K; zVeV!|_vg<>S$QJ_B~ZqZi?2f&j3BiWo3mm9G{nGE;dn)v**u>=X&{eN>h8bCh6F6U zvVO5wvVp+`@^3A0@2qGRv(L1yYw?)6q!`x+fW{_e0(c;vY5D#Q5KCaq1_8V6=FOEp zZpsI&I*Q8+cKV?6mzvDAVgBmp7|p8|GU|uRW-xBzZ+<*wic|ia+IAOvH2MBn-hem= z&z>% literal 0 HcmV?d00001 diff --git a/core/embed/vendorheader/D002/vendor_unsafe.json b/core/embed/vendorheader/D002/vendor_unsafe.json new file mode 100644 index 000000000..500fcb84e --- /dev/null +++ b/core/embed/vendorheader/D002/vendor_unsafe.json @@ -0,0 +1,20 @@ +{ + "header_len": 4608, + "text": "UNSAFE, DO NOT USE!", + "hw_model": "D002", + "expiry": 0, + "version": [0, 1], + "sig_m": 2, + "trust": { + "allow_run_with_secret": false, + "show_vendor_string": true, + "require_user_click": true, + "red_background": true, + "delay": 1 + }, + "pubkeys": [ + "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351", + "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869", + "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef" + ] +} diff --git a/core/embed/vendorheader/D002/vendor_unsafe.toif b/core/embed/vendorheader/D002/vendor_unsafe.toif new file mode 100644 index 0000000000000000000000000000000000000000..8c25f0ddd9f77e9e0259da329d46af4621bbb0db GIT binary patch literal 2162 zcmV-&2#xntPf1320C)gq2mk=>k}G&3OAv(-2m}Ig1p+Yw5fOnvL|{fBA`plb2*e0P zL`1}j2uuV5frvmLMj#Lo5fKQ)7(_%w1OkCTj6keFAn5Mu$4z$k+uhJbU|tE6k15$x zr_Nue5+re~V;$>Q$2!(amFa?>vvZbWW%`vlTeQG?(oyq&%26YE#Rp%E`-Y@pCe=G1 z$Wyra608|JzKD1*p6e{316yuoC8l(c-DCRF56&O&LxMV;pFctHy#1$}N z!JDUb)W5ABxSm;`Ja8NRzp3)ExakLux$nso+t!g{J&EMTK5u~ixli*`)bNV*^`&q@}VNnI%`-Gk!2L{d@ej``8LV3=0tfD+Er5t7MwVfj+C z$T##>%JeX3O_JfdKS!mQU&RHrk%X(649(AgV)|Y2IkattrMn9C-XO%%tx2*{ z_u?pPXQxXFd?xB8~T2QQO`GEBhU@)~I)(6Q$7nh^WqQyk zqP$lgcufL`i<)#p=UoEk^@4fPm~c#E=_#EPhG}GYxU?-gLiRcoh9{LO!aG+TPrL@{ zB3Ck!0~#K!fjU*H;c><@%n{x+cvERm%*z!wLgQV~CNiPQO^-Sil()^ishFgIY~NOk zkP@~?5xF3cWzYIQ7{;4oUUl+xCUr;OgcSc7zH2BeKAiR#c@#QNGHj?lXg3*qNgQ!l0KQ)(N zynek6g+i{y4aD0;G@B~L{Hfg_+w;%6piLx;q3}<8!sdu#F@U1ZTUY+o{zDVKV1D(k zC6;cVgvmRS{?+=Vj^xpkhA*`aIEY#Y5&?L1e`hj?-X-V`9d+-+W0H;}w!0wi5=7S= zieQS^4US}5g0BRU#AztHX*A)dJreGd9MU=5b62~nOyBCx zl^cp~pLCI%EUDeDt6cAEsy0iIaO&!feujso+h$E9r`sL+EjmZKzKO70C5TC$VI*Hw zd$I!t2~W9*Bs^Cw`d&{~V(B($f`nORx_GI4=&E%jt24R1BMn%(RUWRd=&H)Ggiitg z+afb0-I6j$TzCyqLh=G>ZP^Z%?h}i~Su|U`V_3r2g|;Xl>1Jj4p4=B#RbJ(HEJ?#x z&q^%emNw~uBjKt>$c{{M3iUtgb(My&b8b+K<6$G=M>JjR4uVxd+v+ofJ)?>wms5*3 z$t?l90yktQ=WMP`anvB>8*&Mj-4g!&1H1au&^Nyp*sZNXzoImf-kD6&zt^n4Pes`2 znk0wes*wzv*CkVAvwttTg6!i53)@A13onGuizj>u#?Lp4O!($oO_pi+EA zw5H8kaqIWq*IN4jiSRunkiEWsRUXBx|1_qo?EicjlbN=QB}CyNNpr|Gk4Y4>GTLru zzbB1JY2(FFl}LCK6tuX(M-AoXM?Jwe(}1bzVTwK(};KzWI-IOJ4-ZT8Z=RUcXn{T%~LE>E#zR6UR{hu#4 z8;X9cXA}g*Fo&QO& zL37$`GsX$G*<9lp$ufO^A7?U2<4D`0BdOCoaPyyko|vQmqNXB#!~=Sb(Aui~=34t? zEf8SUlTWd_>PrBLadd^X@n;%r?8leQOvOnon4efpIw(VZBi&!sMH7Dg=BoKZeZ@0; z35Qo1e#^7cesQ_&D++8sd74vS@tet;Ef;ae>@P=KR|}dT+o}Wh7o)vn+i72`0`)IL z3$nd~_O&ipPksg3tW51e`&wl>;qhjjs{&8b{b*myBqyvE+myRvKn;@cTq#x*@gjB9 o18>j-2~y{*%BKRP{i1f5)l?(d6-#&wNP4Ve9qU-fI@U+k|Kc$>ZU6uP literal 0 HcmV?d00001 diff --git a/core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin b/core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin new file mode 100644 index 0000000000000000000000000000000000000000..0689bb2efc9641221d3cc06f5e28160644513926 GIT binary patch literal 4608 zcmeHJ|4-Cq9KY^Fu9HZF1Lf-hdWZ*;FNeed0&#GhaGZP>@&Nf3Cx&;%mjgL*+S+18 zYyFbhvNc<|*0h?VnO|b2tEM>?YHO9NH79FH3s&M=kkJ8B69`@!KGQ8n8yAIWSOJKh^~_Q%K@3vX$z*sl59!)X&%lmA$M ze4FPuF2?aqxSh7Qk7F5Ee{YI9QVm3h6jtkK}Cu4+y*Se=GyXT71Jt}Icds(0GU zeJY=-N2^lJpE+gnB~>nm4bv`BdxO-O>aZ}himmPCh9t)IT8P$awSGLIty-c+gO3g6 zhUH;lVSKg{&lcmwe6aWsqQEhvxNyqaTOSndRG2#9w!y4e?S*#6LAHPvuo9fx_bT*B zu%jCStQ%pKKqUoF{r*Q`TUe0 zPERenN8!CO;fHcSBR}rB z{2G)^fpC~akXhgc05-5xW@#JzMkb-4sq)J=VON1#Z*VA#0@h2i%+V9@<9Ee4V2Zep za#;-fL4ZAYYGS!N$s*#~y(>S0FQ>{Do877g5MC$DGgOY zDnLUzWD~d5?n*U%vmcJNmem5xoM?wOf~*LD^9P2x*jnM|!tf0sqnC>TikKLn4df=@ zivlfLSs<6xuYqK98lCLt5fIP`(*u(!+y~<9E_f!;2|6-aKkA1eKuP$<$6+e_AWYfW z;{zJLDZmXhv-XC0no?{Hh7i~~PZBg16yU^b_ft zkW)9t@p%KaNK4%)6grDsxk)&w{o69)p)Sug`CiU@r1a+h$jOs<3$ZZlx? z3u}+`<_M2zux(%}%_6X!K^6L_b@*7mSt zj~wCO=}tfN#?k(%;i*q1J+sw+z8KP9a&vTM;`Yzx-=Ew1+wHmJ3qLH_G{sAP?U;H# Ga@pTZE8W@v literal 0 HcmV?d00001 diff --git a/core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_unsigned.bin b/core/embed/vendorheader/D002/vendorheader_dev_DO_NOT_SIGN_unsigned.bin new file mode 100644 index 0000000000000000000000000000000000000000..c46a005e79514449b7129bcba64fd88a9c368b2e GIT binary patch literal 4608 zcmeHJ-A~(97_McES{I~1f$>>jD`SNWC=4m(OA4hx>G&43!1%HS+*&M97#(IaCUQaI zopVNwS)#izPR*j3OhV>%VZ?To&ggQ}ov zRHIUDtz0(+vzlUHb((!@f26ult<#}ZZ5yaJWHGMSKr}X+?aM_?^FB2id~B#U#OQQ7 zK1;&0op?1L>^y`ha84^OoVtO&$3;6Ard_!GFtLaH(4jQQGoS@*0w0`v3;H5BI06C6 zo)z{COe?rRn>`DSVm}H_8sU~_K;$T~a1*@dpm^gL3@!)Wf&DRDi_Qr%C%>j-4cy!|(D4POt zFqt5;zzqQGV6Dv3N%&n%g0;Kp`}bfEf*OBRG>ih)OSa6>3-Hq?Q=BkW+()@AhC?90 z9(=8-+?{L@ai5tikLSy|vQ*q6F0`-sIXH){6{5KS!*3Pj)pWz}Oy-oPn;{LLAs^Dn zZFRVFO+TK8V{2oz0PEKVpj{v<0^t0C87{U>_@yv>11RutF+dd)1N4L3cNhNmgV-f1`h+wRMPrh)>Tc&l6nT&Cj@aGSGPx^w*g_Dd{2H&_O8&jjSujj245 zK*$PlfHGT0#&@Qwo#(VT1)xG0Xp7?c;5GSTa%54U#ZezY@qj$wO5CgESUEEgH_NOC zoC6&t5FkSs=!6>*&znI(FV7g02ryTkXuoLOTlzvcP?>W#3yYH!*e^SFq|dLdWF9`i zI{Qz^3nnCQD7-V323fld`Q`$XW=Y(gWKKT<3PyT`JO1mN7vPl)k2&jE4FWutK>9Qn z9}9XTWODpRhfmx7U0|8es0F!UA8>4SB zH7w;)6GVVTu)wPT(Eh7;1ms1=%r~=c7V;qgD-dWlvCsfsHNaQrpB9c#i!fY($5J-J zy=5f<-RVK6TDZ_aEyTUso?U<4*F1z+F36kAJ1ob^w{QRpZ^RsscW`-k8uPjz%zP!ZH381Y#DRc(7EC}z5rJ>t7#2>E$(_;5Z3c`XVI2wn65%lo z_Tx-tu?UQD{Jk(~Whrom>r2Wbp3^G!G60?hIXNy}x-fO@lgU&dJHP!oBF;lf*d@>4 fU?D@h|9Qe*I0NAfgfkG%KsW>841_cAf6l<))ML8S literal 0 HcmV?d00001 diff --git a/core/embed/vendorheader/D002/vendorheader_unsafe_signed_dev.bin b/core/embed/vendorheader/D002/vendorheader_unsafe_signed_dev.bin new file mode 100644 index 0000000000000000000000000000000000000000..8db53a9fe3ed8fa16844fe4d8ad5292cfa05caa3 GIT binary patch literal 4608 zcmeI!*HaVd765PvxDfKlICDv=Mano5GCPFpM7!q3%DDHpQ`hiB9xpS2oUbIYPu{$I!<+a8) zfOa=+46mE0f{c-%n@C%bosEf{EfRhm$ARPU=H=j6BSCQT=4XVYwycXPm_!I-sbnmM|@Lk6A zpo!~kzRZW`KiU-cyA+EkVksWdUmd!1#?7;q6P{ItWV?GEWNAB9w?q$HvEq8I6e2r# zT<#wdirm0sS7f_w>i0z`;usk2$&NZpI{ivWu6XkHrkIIBXI*Tow{_$XgW6lVn2|wS zeABBN*M9gGR6i&7o8^;w zPXowBF;-c-*hTl&{Nk|D<}#W3XSWJ;gQSj{OSUWPmwAW{8$F_o@kj1@sXLUtxe*~1 zCJijL;XU?zLS<|IA7Hs$Q^*Roc*8XB8t%;(w-I}TU0syw#SLFtaQVt?57R zCJBB!@ZP?ZQO79_N7q2^BNq{uR8s-JlJgCLSA7c1{Ya9ecQv70kj5f{N}`5-Rs1Rt^6MnlTSLqbxQ#wkyCsX46<~4OgeN zmabtYMi5@79I=DO?B4p)7*zqkoLem0b9mn$T_PIY{55HR+0l~Xw;#_}=PQJ*m}e53 zYFhsKwc`*C&JCiM7X2doxB@N{)7LDgB!G(lRyW(ze?+i(xD@MEUpW#c{iUzuxIfpt zMMpxGw3$1q?DBrQ|D%`VRGZ)0U%ADXJ^w^pM;<0Fhb*qhghvo#XIXw>ErwA@IY-CL z$?j1YW^FA0bc-KJl~hqiF^jyTt;tGVn-COPSX+zCilC&1B5|SBYC5K1p^l~_g~wWu z-L(yVN}R!q`KSD<)15P{e#@DS=#5f~fTB3H!oLxTi53uCeX(5LKyRWE;p-7mCwUXo z<*TFZ6*Z_*NJGis5P+2QywGclXaI93A#x}u$iid!{8JzSq6TV zlr)m|%d$KQO5!>zQx>mdN1nrW!afMkXy9xxmLJ}WX&Eh`2f@(4dl3(H#2(l6(MocP z?)uN#r)P-Nnh7_6GQ0*3^ndHjcfTFB9SROJolO$s-_U-yz9>V3pr6y!WE(;`SfQ;6 zBYB=lt5679*70=O7C3g32p7j*&TIuXnQCH6HTH)71ks4ptuGKkP12@F!Vobv@%7DQ z{mV~WX?VI|vQc@5U^~M^BmY9jkCJH+gEi3j9HE&0_a-vBjhW(p>26`a6Y6;E_!_Xu z6~9xilpR=*)N_S&Ja$k-{5+INP_GgCBgK(NgcBDQ=L1cdQCbp`4%>L=K_V*FHiFhg zj3>^exu#7D54Ts1Lv2c}a8^ozKXX%b zv5S7o^$Q=eAw^LarFL)|Y45(Q>6?&r%ZrLDiCH3tDVD+-=n8@kR6CjSH%sK+$|NKw zn;{QVoF+ldoNr~ ziudNoj|B23lx#e!;?$`Ls|!4*876V3)syo#OT<@QM=7vZ<4MNM1or6Vagpr;|~hXkyfPj>J%bBPxA z<+wkB)yrJD3Z3DuG)w&bHrWs%GW}S|e+KrWY4K`9cK)3@UBh`au&Kv3^Qb^w>vQ8| zj8qz)f&q-@L*!LzS)TWbk+_205STqo>*1E?c>yaUW?b+kZC(q8;hn{L@T*oqz zmDCk;j#O-Da?O^{S^w3pCw&$jaMhdw2ZWBwwOEB|moXC{{)kE5H;V0m#qixjN#fsE z4dby5YY={a{m48Um#zGsd^HJd*Q&ay6Y6vxh(YH1F7bly!N9nb0(R7|oqkJC{9g0B z0}_8~iej;5cgav=o3GKJs;Wuc%BBXFP6nHxMLkI-j=}-I5O*<+?M-&1bzx z=`98n9TkS>jM*xD6f?&Om__|}{hN-l|99`4{7wW;1Wp7_1Wp7_1WpA0&jq-4M~QhM z$Dd$cYIrZYChQYbdppl9I+AMQUF%)>vbU+EPoKYLr?=byS-X zq0}C+wf5G&mSWJxQhTa)c|GU7cizA7e(?R}e((L|p7S~PoO`V;?QPkF*#7<40USh@ z;gu_D|H*%b`P7uaP#Cl^=;S+)QT}#A;&$m|WMQlRHVk{&JFL=TWWAM8P*GR3Bxdo) zXtA12bhY=H_uoX9n16GO8PDP{;mWCokeG6RQQyPXk97J>zzteh(K3VcNlS2_`4yHnEx zM$Y$mG9F+0WJT_CA`5}BR5!_QcAZ*drkTs}&nttoTs;mlH65y2qJ}J(u{{=Y5$#+~ z4-W}NE()X9rMs-^_JydT7#Qx^jw(|!?Rs#IXwvqkh>=`JZA`1DWyFzQ&0THG@PIYG z>GkcKN8Sb5x|8E?%J6N<3un$01EN7<>Nl#~pu(5`(GXt99=K2hm{MY>UKIJ&{8^p5 z9^{G$v$Rd*ifd~gIdr7CRI2Xz-2&}EiR0$t?TWf(E@J&gxA4^16IY#-9qQiPuz(VS zt{}1DIr?H;X>0x;V3|x)@Cuf^VVrvt_vWk1u&v&%Hp+B@yerP&#&QWf`#~5H?3BZ- zj{2ob1xX-Ab?s(EI*0r!V-EYpvjQzHDy+%1522%it_$0}yA+m8N5{R&E4rud7%#7_ z(~=llt}tKK(zv3mkE*b_AdnVjHfBNtsr26#&4HsYL8cSt8x1WjR*3t9H0NyF#rr~i z!-AylaF>0{$}WxXwmsjkcq2%2G+pCY*-q_es-Gm5eAeckf#%Dt`*YO6OfuaxrhmVm z$p8Job6YLFmR%B#u7*5BE+W*FQvknE^7Mf>yb4TxNaCdT)gc^^h9ZJeg1T;II1f$H z*apP6W)&z~f030*MzmSj5?(cn(rBeU-z#y=a`>l_e7*hmT@TP(npJ*;R}H*7GYS_? z_lPmtrSP|wyYosuUSw0=XeEN|`)Qrm6J2*IhmHbgOasp=icE~|^07`>bS6vP*#ek4-H-accZ zYXpW_8_he{;zLp>)sVN~yTu7CQma&3Bd(*MpQw_-O z+6FH*R`2C}KCkk0#|*R2d}bqRqr}XwC|0HLFGNCu83b2HmdWk!NiZOMJ0@x+ZDKmT zwKP2<2b2owC@CBQkerqqa&r+4VC=+43}y$Kxh-GH2NE#uxVoR641Q<{6BIKqzq^i- zMAFYL%c7tpjtf$yaauN%Icx{)qu`7>&I)7x@q>tl!2)_f0s2=D;<1*<)7oBoady#t z-&xzVbfFp(!Fo`-NB@EDuN`@=_d>Tr6he(>6GeD8G~cf;O3@+c7jzZr`Vcl|NNfCX zu6yDt6oQtvKbN|t5VJ{yi(;>4v;v!quVG5m_Xhs}(TTLJuMqxgq)nmtL1Ie6-*=L9 zuRe38;~V*t49eR1+op`v^Deg^6;FevnEeee5a6`GHjz>97|E_`_Y3S{wv+tbWn@IUlp0${rzoiNQ>bvgww&43YZi5YN~Cn&Ic%%R@5j zwt|XM2CXA5j5t^tZ`!T=kPW* zC}hM9BhuqL4*6PbGO83pJADRcOAZAP8j|sEI7w|7B^pM3j;tfJo^f$V^K&q&fnqkh z(w8Zb>R%A@Bu}|`x~#-;!-sOsG(B)-y0#oAH%GbEMKlZI-O*hM%_Niu`UZ#SdS*2-o ztFSi!G~5*zeajHo5zrTjAfBvgp_5~dhJ)b&jb_n_(o%!wLUqzij@eN2IJFsRG_jlu zelSOQ!k0HLZ{=PYt4fPsUEn%5WfXf(HL)*EF`B2NUn9+IkKusG!tDK~=Spwn#(k)I z-D{8iwmUO!f51xF)B&eAHsNig+Nmt{*VI*3w0K5NO`5#noD4j;>*`~;a3yro->X^i z5gfD7Zjot%1Ad8bY+TOKb{RCIae5_Citt;sqNXj^lHp_=&|M#OBnIo^kskP)u|yC3 zdeRrp>|w0jfX;AMm?ZpmkD`wdntm$pI|DmvTD(!8l^0N}tv`wC*t}IuwY1Th^E?qzstPf|u(DPx`<* zcxpd6E{JzSV`8PfpzsBgsY1EpVeLR>LG1JFm#o6qviLTR$VUT{lw*edp}Wd?=g|yg z1#QKYEd?8rRK4YO!FRRuS+7|;TsgbI4xy!VGe&OOY19aaKW0$&4Px41(L4`O;`k4h zLwIcc8idzZHzL={X)CWgPelydxvFaHfI628nxb(05PR9^HidC20qm&WJomOS;Yamv zc1Zl0NvheJ{-M2x*4&n7ehC0MbnNZ)0jx+BoqF2fs>e^-bi8CMyd@ht!VxgQ$z!=l z?I8n-jtj%GN3G>PiJ0Q}Od|ig{*6aj|GRfif2RVc0;d9}0;d9}0;dB1=K>r@*<{ob zhhcf&Z5p0SbKKUND_buKY_4`;54sU9zh3v?N3`{&K(f{&LUxoO{l_b~a89e3E?se*6Fd z3eWW1IoN;lA7Pf98XOLXHHI911#-$?ugPC8oro@IHQt2d&iX}ET92%@lJYC+3KwLp ze`gh+w~wv%JNEXA%mVjsfl>2mJT_93YzmDl50VMkZ+*{XPTje}h$vj7aCz-=H&t{; z*MRmnY>ls(X@X2qpc^PVkiD&$vK4bO+?^AY0XTcJYnDwZdcC4>Y4xMP6x011f% zBU86)AeECT(n4)QrlzKCWFad-KthTU=o;vxgoK1p+b=(=KPpD|jOa$7h1I1_WW+Xm za=^^(ws6LSGaqb=`do`7Avn6H!WYL*y-~}|MdH)S&@2z{z06C_RV^_?*4+3WYj9Ni zao2nMq(XN!)@7wG+qzvzx(pVMf4rs5RYAx^|6WiZd7wiA3Ho? zM`(I^{pxqW{A|OCu~%h;HqE(X$BF^5AX%L&Rh}@Zv;XKy&1DaqDg>}KINGPBf4TX% z&dUgTPMTZVCVkGMHLoaqq`6eF?&+<3{b2cn=HktYy2ay^`n7H;_UJ5s)~D50!0khrn2^g-j&IIHq%biFFY*d+>$nhA z^$l8*;>*=$t6CbDG>y>}_NToPeA%o*rp;%uX-jr9^`caY(h?J$2= zvTs;|+8yb>Yg5^!`_-Z6>p4Fpb%tSR{vzA8{aE$Gq>_*NLQ}9O;ME|3I=Drqr|#r$ zcay}v?)hwf7ot0cb-ZNh49mFf&q^ zp>A#u5?!$kR;fSD%Pc~+Sv!zkG|Mm;r9EFO@y%euqiE6I{<|J~n2k$Sfut7=B3n~x zr!99Var&i**EZX;8vedTmLjnlB$c<51~13EZd49^51z6NKB+D}&e|5`9rBo5o{pRI zN=xSu2P=lCRgc`lV7G65Zip^NT*xU>>fXN>fGL)WY5tP5yXbV2?!TKLT6QRc&J)eCdqB+?y#qGN}wHC8hVii~zuT}6DGBME#imxkD&h76>G$DOCpy(y9 zV>|uyE_p`}XcREfig+X-B`r7X>O2O(*&;>_W(Qk&E}nS;Bw@Yqbw4_peAAO6sb`*j za~Z9GV*a$Kf`(BAPAQfq=-Ja|a2@dX5>q;OTkOsE@1%82<}d?lu)lhc5A>uT)%G%r zvkUJAOgp5dOV(IO)PvH!`}Yig>B#fA9ljZ+7H&SBBrURb>Fw&gA`^;v#?(@(598y8 zwGxMOy^@w;P>hn(3G#+o+&TpzgS(K?3T!gJh%M3C8T=i@q%bxRpgl(mbsvCVYy&bEIqo&>SE{SD8MkhH(nQ88~gDIVwV7W6rz4_Sv- zflY3NtuocDp!}rn%hW^GULobvU@g1AEX+FMU51ya)h zT9q^%J56>YkBd>fo<_5ZLm)2I&ssk|!LE||qm<5Yxa1i7ZsoI3#rMuc(e{^|K(}6D zs#UiwOoldS7j?-f_B61@l_!=X z(%7JukuZ!*CwA2E|^4K;_ zw_A(90if%pJ|9qq#EpPH$%hDMO-ddf2sG>s59l__jF*<0G#BVlr*f=@n#btPD6{d! zT*x0Yw1=X3W2&}ZmGRmP;_}?_6Ku2i6WU3AY3i}U9sRm#Ry!PLWEOVkS0fK*qY(aG z)yrNd+?VaCF{eFV>be0Wy|Ia4uh>rK>Aa*b^J3*Pa%$34O=px5ph}@YxpwPJ3q0@>v9WP6N8f$WiXrHmNGl|4FbbPCJW7UB@IWtP^mkc!m$1^n-<$q~zoy)qpAZ_on$P^;vm$YW0n0F~Fv7yNrW;ZQV}| zr5VtmL2X&1D$p|E6CR@6ICR1v z-XUE3!DUXa8x|L@B=$#5)L@DU6Z(Wc&zXrXgR{W z${_--eg!HLU>KEa>$;KGou?&>>s;10cSfJc1+i%Y-(;URda|*uC4epMt0!JJCVs2_ z)e%KFHbJ*qG2VCb)|=Vzc~SyE4ITKozJsXKW!R4zJdDJs>n>*;q&8H-M+EK+2nyTG z(|d{lg$D%@*(^Ko2Wd;Zs73UD*S|T7_rH7R=yxP=Byc2fByc2fByc3~|1R(^k$ZKG literal 0 HcmV?d00001 diff --git a/core/embed/vendorheader/generate.sh b/core/embed/vendorheader/generate.sh index 7dc1a264f..975586d53 100755 --- a/core/embed/vendorheader/generate.sh +++ b/core/embed/vendorheader/generate.sh @@ -16,7 +16,7 @@ for arg in "$@"; do fi done -MODELS=(T2T1 T2B1 D001) +MODELS=(T2T1 T2B1 D001 D002) for MODEL in ${MODELS[@]}; do cd $MODEL diff --git a/core/site_scons/boards/discovery2.py b/core/site_scons/boards/discovery2.py new file mode 100644 index 000000000..7ee701a43 --- /dev/null +++ b/core/site_scons/boards/discovery2.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from . import get_hw_model_as_number +from .stm32u5_common import stm32u5_common_files + + +def configure( + env: dict, + features_wanted: list[str], + defines: list[str | tuple[str, str]], + sources: list[str], + paths: list[str], +) -> list[str]: + features_available: list[str] = [] + board = "stm32u5a9j-dk.h" + display = "dsi.c" + hw_model = get_hw_model_as_number("D002") + hw_revision = 0 + + mcu = "STM32U5A9xx" + linker_script = "stm32u5a" + + stm32u5_common_files(env, defines, sources, paths) + + env.get("ENV")[ + "CPU_ASFLAGS" + ] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 " + env.get("ENV")[ + "CPU_CCFLAGS" + ] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mtune=cortex-m33 -mcmse " + env.get("ENV")["RUST_TARGET"] = "thumbv8m.main-none-eabihf" + + defines += [mcu] + defines += [ + f'TREZOR_BOARD=\\"boards/{board}\\"', + ] + defines += [ + f"HW_MODEL={hw_model}", + ] + defines += [ + f"HW_REVISION={hw_revision}", + ] + sources += [ + "embed/models/model_D002_layout.c", + ] + sources += [ + f"embed/trezorhal/stm32u5/displays/{display}", + ] + + if "input" in features_wanted: + sources += [ + "embed/trezorhal/stm32u5/i2c.c", + ] + sources += [ + "embed/lib/touch.c", + ] + sources += [ + "embed/trezorhal/stm32u5/touch/sitronix.c", + ] + features_available.append("touch") + + # if "sd_card" in features_wanted: + # sources += ['embed/trezorhal/sdcard.c', ] + # sources += ['embed/extmod/modtrezorio/ff.c', ] + # sources += ['embed/extmod/modtrezorio/ffunicode.c', ] + # features_available.append("sd_card") + + if "sbu" in features_wanted: + sources += [ + "embed/trezorhal/stm32u5/sbu.c", + ] + features_available.append("sbu") + + if "usb" in features_wanted: + sources += [ + "embed/trezorhal/stm32u5/usb.c", + "embed/trezorhal/stm32u5/usbd_conf.c", + "embed/trezorhal/stm32u5/usbd_core.c", + "embed/trezorhal/stm32u5/usbd_ctlreq.c", + "embed/trezorhal/stm32u5/usbd_ioreq.c", + "vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_ll_usb.c", + ] + features_available.append("usb") + + defines += ["USE_DMA2D", "FRAMEBUFFER", "FRAMEBUFFER32BIT"] + sources += [ + "embed/trezorhal/stm32u5/dma2d.c", + ] + features_available.append("dma2d") + features_available.append("framebuffer") + features_available.append("framebuffer32bit") + + env.get("ENV")["TREZOR_BOARD"] = board + env.get("ENV")["MCU_TYPE"] = mcu + env.get("ENV")["LINKER_SCRIPT"] = linker_script + + return features_available diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py index 0cc34f0f2..d84bcc8d6 100644 --- a/core/site_scons/tools.py +++ b/core/site_scons/tools.py @@ -6,6 +6,7 @@ from pathlib import Path from boards import ( discovery, + discovery2, trezor_1, trezor_r_v3, trezor_r_v4, @@ -59,6 +60,8 @@ def configure_board( raise Exception("Unknown model_r_version") elif model in ("DISC1",): return discovery.configure(env, features_wanted, defines, sources, paths) + elif model in ("DISC2",): + return discovery2.configure(env, features_wanted, defines, sources, paths) raise Exception("Unknown model") @@ -71,6 +74,8 @@ def get_model_identifier(model: str) -> str: return "T2B1" elif model == "DISC1": return "D001" + elif model == "DISC2": + return "D002" else: raise Exception("Unknown model") diff --git a/python/src/trezorlib/firmware/models.py b/python/src/trezorlib/firmware/models.py index d70eb996d..5fc203f46 100644 --- a/python/src/trezorlib/firmware/models.py +++ b/python/src/trezorlib/firmware/models.py @@ -32,12 +32,14 @@ class Model(Enum): T2T1 = b"T2T1" T2B1 = b"T2B1" D001 = b"D001" + D002 = b"D002" # legacy aliases ONE = b"T1B1" T = b"T2T1" R = b"T2B1" DISC1 = b"D001" + DISC2 = b"D002" @classmethod def from_hw_model(cls, hw_model: t.Union["Self", bytes]) -> "Model": @@ -232,11 +234,18 @@ T2T1_HASH_PARAMS = FirmwareHashParameters( padding_byte=None, ) +D002_HASH_PARAMS = FirmwareHashParameters( + hash_function=hashlib.blake2s, + chunk_size=1024 * 256, + padding_byte=None, +) + MODEL_MAP = { Model.T1B1: LEGACY_V3, Model.T2T1: T2T1, Model.T2B1: T2B1, Model.D001: TREZOR_CORE_DEV, + Model.D002: TREZOR_CORE_DEV, } MODEL_MAP_DEV = { @@ -244,6 +253,7 @@ MODEL_MAP_DEV = { Model.T2T1: TREZOR_CORE_DEV, Model.T2B1: TREZOR_CORE_DEV, Model.D001: TREZOR_CORE_DEV, + Model.D002: TREZOR_CORE_DEV, } MODEL_HASH_PARAMS_MAP = { @@ -251,6 +261,7 @@ MODEL_HASH_PARAMS_MAP = { Model.T2T1: T2T1_HASH_PARAMS, Model.T2B1: T2T1_HASH_PARAMS, Model.D001: T2T1_HASH_PARAMS, + Model.D002: D002_HASH_PARAMS, } # aliases @@ -269,3 +280,5 @@ DISC1 = TREZOR_CORE_DEV DISC1_DEV = TREZOR_CORE_DEV D001 = TREZOR_CORE_DEV D001_DEV = TREZOR_CORE_DEV +D002 = TREZOR_CORE_DEV +D002_DEV = TREZOR_CORE_DEV diff --git a/python/src/trezorlib/models.py b/python/src/trezorlib/models.py index af83214a2..f80b504f9 100644 --- a/python/src/trezorlib/models.py +++ b/python/src/trezorlib/models.py @@ -72,6 +72,15 @@ DISC1 = TrezorModel( default_mapping=mapping.DEFAULT_MAPPING, ) +DISC2 = TrezorModel( + name="DISC2", + internal_name="D002", + minimum_version=(2, 1, 0), + vendors=VENDORS, + usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)), + default_mapping=mapping.DEFAULT_MAPPING, +) + # ==== model based names ==== TREZOR_ONE = T1B1 @@ -79,8 +88,9 @@ TREZOR_T = T2T1 TREZOR_R = T2B1 TREZOR_SAFE3 = T2B1 TREZOR_DISC1 = DISC1 +TREZOR_DISC2 = DISC2 -TREZORS = {T1B1, T2T1, T2B1, DISC1} +TREZORS = {T1B1, T2T1, T2B1, DISC1, DISC2} def by_name(name: Optional[str]) -> Optional[TrezorModel]: