mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-11 07:02:41 +00:00
feat(core): refactor display drivers
[no changelog]
This commit is contained in:
parent
a47ae5da1a
commit
f085c50931
@ -233,18 +233,20 @@ build_embed: build_boardloader build_bootloader build_firmware # build boardload
|
||||
|
||||
build_boardloader: ## build boardloader
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" $(BOARDLOADER_BUILD_DIR)/boardloader.bin
|
||||
CMAKELISTS="$(CMAKELISTS)" NEW_RENDERING="$(NEW_RENDERING)" $(BOARDLOADER_BUILD_DIR)/boardloader.bin
|
||||
|
||||
build_bootloader: ## build bootloader
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" $(BOOTLOADER_BUILD_DIR)/bootloader.bin
|
||||
CMAKELISTS="$(CMAKELISTS)" BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \
|
||||
NEW_RENDERING="$(NEW_RENDERING)" $(BOOTLOADER_BUILD_DIR)/bootloader.bin
|
||||
|
||||
build_bootloader_ci: ## build CI device testing bootloader
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" $(BOOTLOADER_CI_BUILD_DIR)/bootloader.bin
|
||||
|
||||
build_bootloader_emu: ## build the unix bootloader emulator
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BOOTLOADER_EMU_BUILD_DIR)/bootloader.elf
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" NEW_RENDERING="$(NEW_RENDERING)" $(BOOTLOADER_EMU_BUILD_DIR)/bootloader.elf
|
||||
|
||||
build_prodtest: ## build production test firmware
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
@ -252,7 +254,7 @@ build_prodtest: ## build production test firmware
|
||||
|
||||
build_reflash: ## build reflash firmware + reflash image
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" $(REFLASH_BUILD_DIR)/reflash.bin
|
||||
CMAKELISTS="$(CMAKELISTS)" NEW_RENDERING="$(NEW_RENDERING)" $(REFLASH_BUILD_DIR)/reflash.bin
|
||||
dd if=build/boardloader/boardloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=0
|
||||
dd if=build/bootloader/bootloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=49152
|
||||
|
||||
@ -261,24 +263,26 @@ build_firmware: templates build_cross ## build firmware with frozen modules
|
||||
TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \
|
||||
PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \
|
||||
BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \
|
||||
DISABLE_OPTIGA="$(DISABLE_OPTIGA)" \
|
||||
DISABLE_OPTIGA="$(DISABLE_OPTIGA)" NEW_RENDERING="$(NEW_RENDERING)"\
|
||||
$(FIRMWARE_BUILD_DIR)/firmware.bin
|
||||
|
||||
build_unix: templates ## build unix port
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" $(UNIX_BUILD_DIR)/trezor-emu-core $(UNIX_PORT_OPTS) \
|
||||
TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \
|
||||
PYOPT="0" BITCOIN_ONLY="$(BITCOIN_ONLY)" TREZOR_EMULATOR_ASAN="$(ADDRESS_SANITIZER)"
|
||||
PYOPT="0" BITCOIN_ONLY="$(BITCOIN_ONLY)" TREZOR_EMULATOR_ASAN="$(ADDRESS_SANITIZER)" \
|
||||
NEW_RENDERING="$(NEW_RENDERING)"
|
||||
|
||||
build_unix_frozen: templates build_cross ## build unix port with frozen modules
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" $(UNIX_BUILD_DIR)/trezor-emu-core $(UNIX_PORT_OPTS) \
|
||||
TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \
|
||||
PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" TREZOR_EMULATOR_ASAN="$(ADDRESS_SANITIZER)" \
|
||||
TREZOR_MEMPERF="$(TREZOR_MEMPERF)" TREZOR_EMULATOR_FROZEN=1
|
||||
TREZOR_MEMPERF="$(TREZOR_MEMPERF)" TREZOR_EMULATOR_FROZEN=1 NEW_RENDERING="$(NEW_RENDERING)"
|
||||
|
||||
build_unix_debug: templates ## build unix port
|
||||
$(SCONS) --max-drift=1 CFLAGS="$(CFLAGS)" $(UNIX_BUILD_DIR)/trezor-emu-core $(UNIX_PORT_OPTS) \
|
||||
TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \
|
||||
BITCOIN_ONLY="$(BITCOIN_ONLY)" TREZOR_EMULATOR_ASAN=1 TREZOR_EMULATOR_DEBUGGABLE=1
|
||||
BITCOIN_ONLY="$(BITCOIN_ONLY)" TREZOR_EMULATOR_ASAN=1 TREZOR_EMULATOR_DEBUGGABLE=1 \
|
||||
NEW_RENDERING="$(NEW_RENDERING)"
|
||||
|
||||
build_cross: ## build mpy-cross port
|
||||
$(MAKE) -C vendor/micropython/mpy-cross $(CROSS_PORT_OPTS)
|
||||
|
@ -5,6 +5,7 @@ import tools
|
||||
|
||||
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
# skip boardloader build
|
||||
@ -20,6 +21,9 @@ if TREZOR_MODEL in ('1', ):
|
||||
|
||||
FEATURES_WANTED = ["sd_card"]
|
||||
|
||||
if NEW_RENDERING:
|
||||
FEATURES_WANTED.append("new_rendering")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
CPPDEFINES_MOD = ["BOARDLOADER"]
|
||||
@ -60,13 +64,27 @@ CPPPATH_MOD += [
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/gl_color.c',
|
||||
'embed/lib/gl_bitblt_rgb565.c',
|
||||
'embed/lib/gl_bitblt_rgba8888.c',
|
||||
'embed/lib/gl_bitblt_mono8.c',
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/mini_printf.c',
|
||||
'embed/lib/terminal.c',
|
||||
]
|
||||
if NEW_RENDERING:
|
||||
CPPDEFINES_MOD += ['NEW_RENDERING']
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/gl_draw.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/display_draw.c',
|
||||
]
|
||||
|
||||
|
||||
|
||||
env = Environment(ENV=os.environ,
|
||||
CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')),
|
||||
|
@ -7,6 +7,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1'
|
||||
PRODUCTION = 0 if BOOTLOADER_QA else ARGUMENTS.get('PRODUCTION', '0') == '1'
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
# skip bootloader build
|
||||
@ -22,6 +23,9 @@ if TREZOR_MODEL in ('1', ):
|
||||
|
||||
FEATURES_WANTED = ["input", "rgb_led", "consumption_mask", "usb", "optiga", "dma2d"]
|
||||
|
||||
if NEW_RENDERING:
|
||||
FEATURES_WANTED.append("new_rendering")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
CPPDEFINES_MOD = []
|
||||
@ -90,9 +94,12 @@ SOURCE_MOD += [
|
||||
'embed/lib/buffers.c',
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/gl_color.c',
|
||||
'embed/lib/gl_bitblt_mono8.c',
|
||||
'embed/lib/gl_bitblt_rgb565.c',
|
||||
'embed/lib/gl_bitblt_rgba8888.c',
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/mini_printf.c',
|
||||
'embed/lib/terminal.c',
|
||||
@ -102,6 +109,17 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
CPPDEFINES_MOD += ['NEW_RENDERING']
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/gl_draw.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/display_draw.c',
|
||||
]
|
||||
|
||||
|
||||
SOURCE_NANOPB = [
|
||||
'vendor/nanopb/pb_common.c',
|
||||
'vendor/nanopb/pb_decode.c',
|
||||
@ -228,6 +246,12 @@ def cargo_build():
|
||||
features.append("bootloader")
|
||||
features.extend(FEATURES_AVAILABLE)
|
||||
|
||||
if NEW_RENDERING:
|
||||
features.append('new_rendering')
|
||||
|
||||
if TREZOR_MODEL in ('T',):
|
||||
features.append('ui_antialiasing')
|
||||
|
||||
cargo_opts = [
|
||||
f'--target={env.get("ENV")["RUST_TARGET"]}',
|
||||
f'--target-dir=../../build/bootloader/rust',
|
||||
|
@ -5,6 +5,7 @@ import tools
|
||||
|
||||
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
|
||||
if TREZOR_MODEL in ('1', 'DISC1', 'DISC2'):
|
||||
# skip bootloader_ci build
|
||||
@ -82,8 +83,8 @@ CPPPATH_MOD += [
|
||||
SOURCE_MOD += [
|
||||
'embed/extmod/modtrezorcrypto/rand.c',
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_draw.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/image.c',
|
||||
|
@ -6,6 +6,7 @@ import boards
|
||||
|
||||
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
DMA2D = False
|
||||
|
||||
if TREZOR_MODEL in ('1', 'DISC1'):
|
||||
@ -22,6 +23,9 @@ if TREZOR_MODEL in ('1', 'DISC1'):
|
||||
|
||||
FEATURES_WANTED = ["input", "rgb_led", "dma2d"]
|
||||
|
||||
if NEW_RENDERING:
|
||||
FEATURES_WANTED.append("new_rendering")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
CPPDEFINES_MOD = []
|
||||
@ -87,10 +91,13 @@ SOURCE_MOD += [
|
||||
'embed/lib/buffers.c',
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/dma2d_emul.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/gl_color.c',
|
||||
'embed/lib/gl_bitblt_mono8.c',
|
||||
'embed/lib/gl_bitblt_rgb565.c',
|
||||
'embed/lib/gl_bitblt_rgba8888.c',
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/terminal.c',
|
||||
'embed/lib/touch.c',
|
||||
@ -101,6 +108,22 @@ SOURCE_MOD += [
|
||||
'vendor/trezor-storage/flash_area.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
CPPDEFINES_MOD += ['NEW_RENDERING']
|
||||
if TREZOR_MODEL in ('T',):
|
||||
CPPDEFINES_MOD += ['DISPLAY_RGB565']
|
||||
elif TREZOR_MODEL in ('R', '1',):
|
||||
CPPDEFINES_MOD += ['XFRAMEBUFFER', 'DISPLAY_MONO']
|
||||
elif TREZOR_MODEL in ('T3T1',):
|
||||
CPPDEFINES_MOD += ['XFRAMEBUFFER', 'DISPLAY_RGB565']
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/gl_draw.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/display_draw.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T1B1_layout.c',
|
||||
@ -135,7 +158,6 @@ SOURCE_BOOTLOADER = [
|
||||
|
||||
SOURCE_TREZORHAL = [
|
||||
'embed/trezorhal/unix/boot_args.c',
|
||||
'embed/trezorhal/unix/display-unix.c',
|
||||
'embed/trezorhal/unix/fault_handlers.c',
|
||||
'embed/trezorhal/unix/flash.c',
|
||||
'embed/trezorhal/unix/flash_otp.c',
|
||||
@ -147,6 +169,17 @@ SOURCE_TREZORHAL = [
|
||||
'embed/trezorhal/unix/secret.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
SOURCE_TREZORHAL += [
|
||||
'embed/trezorhal/unix/display_driver.c',
|
||||
'embed/trezorhal/unix/dma2d_bitblt.c',
|
||||
'embed/trezorhal/xdisplay_legacy.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_TREZORHAL += [
|
||||
'embed/trezorhal/unix/display-unix.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('R', 'T3T1'):
|
||||
SOURCE_TREZORHAL += [
|
||||
'embed/trezorhal/unix/optiga_hal.c',
|
||||
@ -260,17 +293,18 @@ cmake_gen = env.Command(
|
||||
#
|
||||
|
||||
RUST_TARGET = 'x86_64-unknown-linux-gnu'
|
||||
RUST_PROFILE = 'release'
|
||||
RUST_LIB = 'trezor_lib'
|
||||
RUST_LIBDIR = f'build/bootloader_emu/rust/{RUST_TARGET}/{RUST_PROFILE}'
|
||||
|
||||
if ARGUMENTS.get('TREZOR_EMULATOR_DEBUGGABLE', '0') == '1':
|
||||
RUST_PROFILE = 'dev'
|
||||
RUST_LIBDIR = f'build/bootloader_emu/rust/{RUST_TARGET}/debug'
|
||||
else:
|
||||
RUST_PROFILE = 'release'
|
||||
RUST_LIBDIR = f'build/bootloader_emu/rust/{RUST_TARGET}/release'
|
||||
|
||||
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'
|
||||
|
||||
def cargo_build():
|
||||
# Determine the profile build flags.
|
||||
if RUST_PROFILE == 'release':
|
||||
profile = '--release'
|
||||
else:
|
||||
profile = ''
|
||||
if TREZOR_MODEL in ("1",):
|
||||
features = ["model_t1"]
|
||||
elif TREZOR_MODEL in ("R",):
|
||||
@ -280,6 +314,19 @@ def cargo_build():
|
||||
else:
|
||||
features = ["model_tt"]
|
||||
|
||||
if NEW_RENDERING:
|
||||
features.append('new_rendering')
|
||||
if TREZOR_MODEL in ('T',):
|
||||
features.append('display_rgb565')
|
||||
features.append('ui_antialiasing')
|
||||
elif TREZOR_MODEL in ('R', '1',):
|
||||
features.append('display_mono')
|
||||
features.append('xframebuffer')
|
||||
elif TREZOR_MODEL in ('T3T1',):
|
||||
features.append('display_rgb565')
|
||||
features.append('xframebuffer')
|
||||
features.append('ui_antialiasing')
|
||||
|
||||
if TREZOR_MODEL in ('T', 'T3T1'):
|
||||
features.append('touch')
|
||||
features.append('backlight')
|
||||
@ -299,7 +346,7 @@ def cargo_build():
|
||||
'-Z build-std-features=panic_immediate_abort',
|
||||
]
|
||||
|
||||
return f'cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts)
|
||||
return f'cd embed/rust; cargo build --profile {RUST_PROFILE} ' + ' '.join(cargo_opts)
|
||||
|
||||
rust = env.Command(
|
||||
target=RUST_LIBPATH,
|
||||
|
@ -13,6 +13,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
PYOPT = ARGUMENTS.get('PYOPT', '1')
|
||||
DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1'
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
|
||||
|
||||
FEATURE_FLAGS = {
|
||||
@ -25,6 +26,8 @@ FEATURE_FLAGS = {
|
||||
FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"]
|
||||
if DISABLE_OPTIGA and PYOPT == '0':
|
||||
FEATURES_WANTED.remove("optiga")
|
||||
if NEW_RENDERING:
|
||||
FEATURES_WANTED.append("new_rendering")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
@ -203,9 +206,12 @@ SOURCE_MOD += [
|
||||
'embed/lib/buffers.c',
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/gl_color.c',
|
||||
'embed/lib/gl_bitblt_rgb565.c',
|
||||
'embed/lib/gl_bitblt_rgba8888.c',
|
||||
'embed/lib/gl_bitblt_mono8.c',
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/mini_printf.c',
|
||||
'embed/lib/terminal.c',
|
||||
@ -216,6 +222,17 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
CPPDEFINES_MOD += ['NEW_RENDERING']
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/gl_draw.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/display_draw.c',
|
||||
]
|
||||
|
||||
|
||||
CPPDEFINES_MOD += [
|
||||
'TREZOR_UI2',
|
||||
'TRANSLATIONS',
|
||||
@ -744,8 +761,17 @@ def cargo_build():
|
||||
features.append('universal_fw')
|
||||
features.append('ui')
|
||||
features.append('translations')
|
||||
|
||||
if NEW_RENDERING:
|
||||
features.append('new_rendering')
|
||||
|
||||
if PYOPT == '0':
|
||||
features.append('debug')
|
||||
features.append('ui_debug')
|
||||
if TREZOR_MODEL in ('T', 'T3T1', 'DISC1', 'DISC2'):
|
||||
features.append('ui_antialiasing')
|
||||
features.append('ui_blurring')
|
||||
features.append('ui_jpeg_decoder')
|
||||
|
||||
features.extend(FEATURES_AVAILABLE)
|
||||
|
||||
|
@ -81,8 +81,8 @@ CPPPATH_MOD += [
|
||||
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_draw.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/image.c',
|
||||
|
@ -55,8 +55,8 @@ CPPPATH_MOD += [
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_draw.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/image.c',
|
||||
|
@ -10,6 +10,7 @@ TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
DMA2D = TREZOR_MODEL in ('T', 'T3T1')
|
||||
OPTIGA = TREZOR_MODEL in ('R', 'T3T1')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
NEW_RENDERING = ARGUMENTS.get('NEW_RENDERING', '1') == '1'
|
||||
|
||||
if TREZOR_MODEL in ('DISC1', 'DISC2'):
|
||||
# skip unix build
|
||||
@ -205,9 +206,12 @@ SOURCE_MOD += [
|
||||
'embed/lib/buffers.c',
|
||||
'embed/lib/colors.c',
|
||||
'embed/lib/display_utils.c',
|
||||
'embed/lib/display.c',
|
||||
'embed/lib/fonts/font_bitmap.c',
|
||||
'embed/lib/fonts/fonts.c',
|
||||
'embed/lib/gl_color.c',
|
||||
'embed/lib/gl_bitblt_rgb565.c',
|
||||
'embed/lib/gl_bitblt_rgba8888.c',
|
||||
'embed/lib/gl_bitblt_mono8.c',
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/terminal.c',
|
||||
'embed/lib/translations.c',
|
||||
@ -217,6 +221,16 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/gl_draw.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/lib/display_draw.c',
|
||||
]
|
||||
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T1B1_layout.c',
|
||||
@ -250,6 +264,17 @@ if FROZEN:
|
||||
if RASPI:
|
||||
CPPDEFINES_MOD += ['TREZOR_EMULATOR_RASPI']
|
||||
|
||||
if NEW_RENDERING:
|
||||
CPPDEFINES_MOD += ['NEW_RENDERING']
|
||||
if TREZOR_MODEL in ('T',):
|
||||
CPPDEFINES_MOD += ['DISPLAY_RGB565']
|
||||
elif TREZOR_MODEL in ('R', '1',):
|
||||
CPPDEFINES_MOD += ['XFRAMEBUFFER', 'DISPLAY_MONO']
|
||||
elif TREZOR_MODEL in ('T3T1',):
|
||||
CPPDEFINES_MOD += ['XFRAMEBUFFER', 'DISPLAY_RGB565']
|
||||
|
||||
|
||||
|
||||
# modtrezorutils
|
||||
SOURCE_MOD += [
|
||||
'embed/extmod/modtrezorutils/modtrezorutils.c',
|
||||
@ -394,7 +419,6 @@ SOURCE_MICROPYTHON = [
|
||||
SOURCE_UNIX = [
|
||||
'embed/trezorhal/unix/boot_args.c',
|
||||
'embed/trezorhal/unix/common.c',
|
||||
'embed/trezorhal/unix/display-unix.c',
|
||||
'embed/trezorhal/unix/flash.c',
|
||||
'embed/trezorhal/unix/flash_otp.c',
|
||||
'embed/trezorhal/unix/random_delays.c',
|
||||
@ -410,6 +434,19 @@ SOURCE_UNIX = [
|
||||
'vendor/micropython/ports/unix/input.c',
|
||||
'vendor/micropython/ports/unix/unix_mphal.c',
|
||||
]
|
||||
|
||||
if NEW_RENDERING:
|
||||
SOURCE_MOD += [
|
||||
'embed/trezorhal/unix/display_driver.c',
|
||||
'embed/trezorhal/unix/dma2d_bitblt.c',
|
||||
'embed/trezorhal/xdisplay_legacy.c',
|
||||
]
|
||||
else:
|
||||
SOURCE_MOD += [
|
||||
'embed/trezorhal/unix/display-unix.c',
|
||||
]
|
||||
|
||||
|
||||
if TREZOR_MODEL in ('T', 'R', 'T3T1'):
|
||||
SOURCE_UNIX += [
|
||||
'embed/trezorhal/unix/sbu.c',
|
||||
@ -424,6 +461,7 @@ if DMA2D:
|
||||
CPPDEFINES_MOD += [
|
||||
'USE_DMA2D',
|
||||
]
|
||||
|
||||
SOURCE_UNIX += [
|
||||
'embed/lib/dma2d_emul.c',
|
||||
]
|
||||
@ -839,9 +877,24 @@ def cargo_build():
|
||||
if TREZOR_MODEL in ('T', 'T3T1'):
|
||||
features.append('touch')
|
||||
features.append('sd_card')
|
||||
features.append('ui_antialiasing')
|
||||
features.append('ui_blurring')
|
||||
features.append('ui_jpeg_decoder')
|
||||
if TREZOR_MODEL in ('R', '1'):
|
||||
features.append('button')
|
||||
|
||||
|
||||
if NEW_RENDERING:
|
||||
features.append('new_rendering')
|
||||
if TREZOR_MODEL in ('T',):
|
||||
features.append('display_rgb565')
|
||||
elif TREZOR_MODEL in ('R', '1',):
|
||||
features.append('display_mono')
|
||||
features.append('xframebuffer')
|
||||
elif TREZOR_MODEL in ('T3T1',):
|
||||
features.append('display_rgb565')
|
||||
features.append('xframebuffer')
|
||||
|
||||
env.get('ENV')['TREZOR_MODEL'] = TREZOR_MODEL
|
||||
|
||||
return f'cd embed/rust; cargo build --profile {RUST_PROFILE} --target-dir=../../build/unix/rust --no-default-features --features "{" ".join(features)}" --target {TARGET}'
|
||||
|
@ -21,9 +21,11 @@
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include "board_capabilities.h"
|
||||
#include "buffers.h"
|
||||
#include "common.h"
|
||||
#include "compiler_traits.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "fault_handlers.h"
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
|
@ -78,6 +78,8 @@ SECTIONS {
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
*(.no_dma_buffers*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
|
@ -78,6 +78,8 @@ SECTIONS {
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
*(.no_dma_buffers*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "bootui.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "display_utils.h"
|
||||
#include "icon_done.h"
|
||||
#include "icon_fail.h"
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "flash.h"
|
||||
#include "flash_otp.h"
|
||||
#include "image.h"
|
||||
|
@ -73,4 +73,10 @@ SECTIONS {
|
||||
*(.boot_args*);
|
||||
. = ALIGN(8);
|
||||
} >BOOT_ARGS
|
||||
|
||||
.data_ccm : ALIGN(4) {
|
||||
*(.no_dma_buffers*);
|
||||
. = ALIGN(4);
|
||||
} >CCMRAM
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "fonts/fonts.h"
|
||||
|
||||
/// class Display:
|
||||
/// """
|
||||
@ -128,11 +130,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_backlight_obj,
|
||||
/// Saves current display contents to PNG file with given prefix.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorui_Display_save(mp_obj_t self, mp_obj_t prefix) {
|
||||
#ifdef TREZOR_EMULATOR
|
||||
mp_buffer_info_t pfx = {0};
|
||||
mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ);
|
||||
if (pfx.len > 0) {
|
||||
display_save(pfx.buf);
|
||||
}
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_save_obj,
|
||||
@ -143,7 +147,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_save_obj,
|
||||
/// Clears buffers in display saving.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorui_Display_clear_save(mp_obj_t self) {
|
||||
#ifdef TREZOR_EMULATOR
|
||||
display_clear_save();
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui_Display_clear_save_obj,
|
||||
|
@ -89,6 +89,8 @@ SECTIONS {
|
||||
.data_ccm : ALIGN(4) {
|
||||
*(.no_dma_buffers*);
|
||||
. = ALIGN(4);
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.heap : ALIGN(4) {
|
||||
|
@ -87,6 +87,11 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
} >SRAM
|
||||
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM
|
||||
|
||||
.heap : ALIGN(4) {
|
||||
. = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */
|
||||
. = ABSOLUTE(sram_end); /* this explicitly sets the end of the heap */
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "buffers.h"
|
||||
#include "common.h"
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
#include "memzero.h"
|
||||
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
|
||||
static struct { int x, y; } DISPLAY_OFFSET;
|
||||
|
||||
@ -61,8 +61,8 @@ void display_clear(void) {
|
||||
// set MADCTL first so that we can set the window correctly next
|
||||
display_orientation(0);
|
||||
// address the complete frame memory
|
||||
display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1);
|
||||
for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) {
|
||||
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
for (uint32_t i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
|
||||
// 2 bytes per pixel because we're using RGB 5-6-5 format
|
||||
PIXELDATA(0x0000);
|
||||
}
|
@ -17,8 +17,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DISPLAY_H__
|
||||
#define __DISPLAY_H__
|
||||
#ifndef __DISPLAY_DRAW_H__
|
||||
#define __DISPLAY_DRAW_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
@ -27,7 +27,6 @@
|
||||
#include "buffers.h"
|
||||
#include "colors.h"
|
||||
#include TREZOR_BOARD
|
||||
#include "display_interface.h"
|
||||
#include "fonts/fonts.h"
|
||||
|
||||
// provided by common
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "colors.h"
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
|
||||
#ifndef NEW_RENDERING
|
||||
|
||||
typedef enum {
|
||||
DMA2D_LAYER_FG = 1,
|
||||
@ -142,3 +144,5 @@ void dma2d_start_blend(uint8_t* overlay_addr, uint8_t* bg_addr,
|
||||
void dma2d_wait_for_transfer(void) {
|
||||
// done in place when emulating, so no need for wait here
|
||||
}
|
||||
|
||||
#endif
|
||||
|
120
core/embed/lib/gl_bitblt.h
Normal file
120
core/embed/lib/gl_bitblt.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GL_BITBLT_H
|
||||
#define GL_BITBLT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gl_color.h"
|
||||
|
||||
// These module provides provides low-level bit block transfer (bitblt)
|
||||
// operations on different bitmap/framebuffer types.
|
||||
//
|
||||
// `fill` - fills a rectangle with a solid color (with an optional
|
||||
// alpha, allowing color blending).
|
||||
//
|
||||
// `copy` - copies a bitmap or part of it to the destination bitmap.
|
||||
//
|
||||
// `blend` - blends a bitmap with a 1- or 4-bit alpha channel to the
|
||||
// destination using background and foreground colors.
|
||||
//
|
||||
// These operations might be accelerated using DMA2D (ChromART accelerator)
|
||||
// on the STM32 platform.
|
||||
|
||||
// Represents a set of parameters for a bit block transfer operation.
|
||||
typedef struct {
|
||||
// Pointer to the destination bitmap's first row
|
||||
void* dst_row;
|
||||
// Number of bytes per line in the destination bitmap
|
||||
uint16_t dst_stride;
|
||||
// X-coordinate of the top-left corner inside the destination
|
||||
uint16_t dst_x;
|
||||
// Y-coordinate of the top-left corner inside the destination
|
||||
uint16_t dst_y;
|
||||
// Height of the filled/copied/blended area
|
||||
uint16_t height;
|
||||
// Width of the filled/copied/blended area
|
||||
uint16_t width;
|
||||
|
||||
// Pointer to the source bitmap's first row
|
||||
// (unused for fill operations)
|
||||
void* src_row;
|
||||
// Number of bytes per line in the source bitmap
|
||||
// (unused for fill operations)
|
||||
uint16_t src_stride;
|
||||
// X-coordinate of the origin in the source bitmap
|
||||
// (unused for fill operations)
|
||||
uint16_t src_x;
|
||||
// Y-coordinate of the origin in the source bitmap
|
||||
// (unused for fill operations)
|
||||
uint16_t src_y;
|
||||
|
||||
// Foreground color used when copying/blending/filling
|
||||
gl_color_t src_fg;
|
||||
// Background color used when copying mono bitmaps
|
||||
gl_color_t src_bg;
|
||||
// Alpha value for fill operation (255 => normal fill, 0 => noop)
|
||||
uint8_t src_alpha;
|
||||
|
||||
} gl_bitblt_t;
|
||||
|
||||
// Functions for RGB565 bitmap/framebuffer
|
||||
|
||||
// Fills a rectangle with a solid color
|
||||
void gl_rgb565_fill(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 1-bit alpha channel)
|
||||
void gl_rgb565_copy_mono1p(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 4-bit alpha channel)
|
||||
void gl_rgb565_copy_mono4(const gl_bitblt_t* bb);
|
||||
// Copies an RGB565 bitmap
|
||||
void gl_rgb565_copy_rgb565(const gl_bitblt_t* bb);
|
||||
// Blends a mono bitmap (with 4-bit alpha channel)
|
||||
// with the destination bitmap
|
||||
void gl_rgb565_blend_mono4(const gl_bitblt_t* bb);
|
||||
|
||||
// Functions for RGBA8888 bitmap/framebuffer
|
||||
void gl_rgba8888_fill(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 1-bit alpha channel)
|
||||
void gl_rgba8888_copy_mono1p(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 4-bit alpha channel)
|
||||
void gl_rgba8888_copy_mono4(const gl_bitblt_t* bb);
|
||||
// Copies an RGB565 bitmap
|
||||
void gl_rgba8888_copy_rgb565(const gl_bitblt_t* bb);
|
||||
// Copies an RGBA8888 bitmap
|
||||
void gl_rgba8888_copy_rgba8888(const gl_bitblt_t* bb);
|
||||
// Blends a mono bitmap (with 4-bit alpha channel)
|
||||
// with the destination bitmap
|
||||
void gl_rgba8888_blend_mono4(const gl_bitblt_t* bb);
|
||||
|
||||
// Functions for Mono8 bitmap/framebuffer
|
||||
void gl_mono8_fill(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 1-bit alpha channel)
|
||||
void gl_mono8_copy_mono1p(const gl_bitblt_t* bb);
|
||||
// Copies a mono bitmap (with 4-bit alpha channel)
|
||||
void gl_mono8_copy_mono4(const gl_bitblt_t* bb);
|
||||
// Blends a mono bitmap (with 1-bit alpha channel)
|
||||
// with the destination bitmap
|
||||
void gl_mono8_blend_mono1p(const gl_bitblt_t* bb);
|
||||
// Blends a mono bitmap (with 4-bit alpha channel)
|
||||
// with the destination bitmap
|
||||
void gl_mono8_blend_mono4(const gl_bitblt_t* bb);
|
||||
|
||||
#endif // GL_BITBLT_H
|
110
core/embed/lib/gl_bitblt_mono8.c
Normal file
110
core/embed/lib/gl_bitblt_mono8.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gl_bitblt.h"
|
||||
|
||||
void gl_mono8_fill(const gl_bitblt_t* bb) {
|
||||
uint8_t* dst_ptr = (uint8_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint8_t fg = gl_color_lum(bb->src_fg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = fg;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_mono8_copy_mono1p(const gl_bitblt_t* bb) {
|
||||
uint8_t* dst_ptr = (uint8_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src = (uint8_t*)bb->src_row;
|
||||
uint16_t src_ofs = bb->src_stride * bb->src_y + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint8_t fg = gl_color_lum(bb->src_fg);
|
||||
uint8_t bg = gl_color_lum(bb->src_bg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t mask = 1 << (7 - ((src_ofs + x) & 7));
|
||||
uint8_t data = src[(src_ofs + x) / 8];
|
||||
dst_ptr[x] = (data & mask) ? fg : bg;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ofs += bb->src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void gl_mono8_copy_mono4(const gl_bitblt_t* bb) {
|
||||
uint8_t* dst_ptr = (uint8_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint8_t fg = gl_color_lum(bb->src_fg);
|
||||
uint8_t bg = gl_color_lum(bb->src_bg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t src_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t src_lum = (x + bb->src_x) & 1 ? src_data >> 4 : src_data & 0xF;
|
||||
dst_ptr[x] = (fg * src_lum + bg * (15 - src_lum)) / 15;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_mono8_blend_mono1p(const gl_bitblt_t* bb) {
|
||||
uint8_t* dst_ptr = (uint8_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src = (uint8_t*)bb->src_row;
|
||||
uint16_t src_ofs = bb->src_stride * bb->src_y + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint8_t fg = gl_color_lum(bb->src_fg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t mask = 1 << (7 - ((src_ofs + x) & 7));
|
||||
uint8_t data = src[(src_ofs + x) / 8];
|
||||
dst_ptr[x] = (data & mask) ? fg : dst_ptr[x];
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ofs += bb->src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void gl_mono8_blend_mono4(const gl_bitblt_t* bb) {
|
||||
uint8_t* dst_ptr = (uint8_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint8_t fg = gl_color_lum(bb->src_fg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t src_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t src_alpha = (x + bb->src_x) & 1 ? src_data >> 4 : src_data & 0x0F;
|
||||
dst_ptr[x] = (fg * src_alpha + dst_ptr[x] * (15 - src_alpha)) / 15;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
144
core/embed/lib/gl_bitblt_rgb565.c
Normal file
144
core/embed/lib/gl_bitblt_rgb565.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gl_bitblt.h"
|
||||
|
||||
#if USE_DMA2D
|
||||
#include "dma2d_bitblt.h"
|
||||
#endif
|
||||
|
||||
void gl_rgb565_fill(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row)) {
|
||||
dma2d_rgb565_fill(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
if (bb->src_alpha == 255) {
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = bb->src_fg;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
} else {
|
||||
uint8_t alpha = bb->src_alpha;
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color16_blend_a8(bb->src_fg, dst_ptr[x], alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgb565_copy_mono1p(const gl_bitblt_t* bb) {
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src = (uint8_t*)bb->src_row;
|
||||
uint16_t src_ofs = bb->src_stride * bb->src_y + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint16_t fg = gl_color_to_color16(bb->src_fg);
|
||||
uint16_t bg = gl_color_to_color16(bb->src_bg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t mask = 1 << (7 - ((src_ofs + x) & 7));
|
||||
uint8_t data = src[(src_ofs + x) / 8];
|
||||
dst_ptr[x] = (data & mask) ? fg : bg;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ofs += bb->src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgb565_copy_mono4(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgb565_copy_mono4(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const gl_color16_t* gradient =
|
||||
gl_color16_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t fg_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t fg_lum = (x + bb->src_x) & 1 ? fg_data >> 4 : fg_data & 0xF;
|
||||
dst_ptr[x] = gradient[fg_lum];
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgb565_copy_rgb565(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgb565_copy_rgb565(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t* src_ptr = (uint16_t*)bb->src_row + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = src_ptr[x];
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgb565_blend_mono4(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgb565_blend_mono4(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t fg_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t fg_alpha = (x + bb->src_x) & 1 ? fg_data >> 4 : fg_data & 0x0F;
|
||||
dst_ptr[x] = gl_color16_blend_a4(
|
||||
bb->src_fg, gl_color16_to_color(dst_ptr[x]), fg_alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
||||
}
|
166
core/embed/lib/gl_bitblt_rgba8888.c
Normal file
166
core/embed/lib/gl_bitblt_rgba8888.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gl_bitblt.h"
|
||||
|
||||
#if USE_DMA2D
|
||||
#include "dma2d_bitblt.h"
|
||||
#endif
|
||||
|
||||
void gl_rgba8888_fill(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row)) {
|
||||
dma2d_rgba8888_fill(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
if (bb->src_alpha == 255) {
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color_to_color32(bb->src_fg);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
} else {
|
||||
uint8_t alpha = bb->src_alpha;
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color32_blend_a8(
|
||||
bb->src_fg, gl_color32_to_color(dst_ptr[x]), alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgba8888_copy_mono1p(const gl_bitblt_t* bb) {
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src = (uint8_t*)bb->src_row;
|
||||
uint16_t src_ofs = bb->src_stride * bb->src_y + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
uint32_t fg = gl_color_to_color32(bb->src_fg);
|
||||
uint32_t bg = gl_color_to_color32(bb->src_bg);
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t mask = 1 << (7 - ((src_ofs + x) & 7));
|
||||
uint8_t data = src[(src_ofs + x) / 8];
|
||||
dst_ptr[x] = (data & mask) ? fg : bg;
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ofs += bb->src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgba8888_copy_mono4(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgba8888_copy_mono4(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const gl_color32_t* gradient =
|
||||
gl_color32_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t fg_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t fg_lum = (x + bb->src_x) & 1 ? fg_data >> 4 : fg_data & 0xF;
|
||||
dst_ptr[x] = gradient[fg_lum];
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgba8888_copy_rgb565(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgba8888_copy_rgb565(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t* src_ptr = (uint16_t*)bb->src_row + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color16_to_color32(src_ptr[x]);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgba8888_copy_rgba8888(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgba8888_copy_rgba8888(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint32_t* src_ptr = (uint32_t*)bb->src_row + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = src_ptr[x];
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_rgba8888_blend_mono4(const gl_bitblt_t* bb) {
|
||||
#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR)
|
||||
if (dma2d_accessible(bb->dst_row) && dma2d_accessible(bb->src_row)) {
|
||||
dma2d_rgba8888_blend_mono4(bb);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t fg_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t fg_alpha = (x + bb->src_x) & 1 ? fg_data >> 4 : fg_data & 0x0F;
|
||||
dst_ptr[x] = gl_color32_blend_a4(
|
||||
bb->src_fg, gl_color32_to_color(dst_ptr[x]), fg_alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
||||
}
|
49
core/embed/lib/gl_color.c
Normal file
49
core/embed/lib/gl_color.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gl_color.h"
|
||||
#include "colors.h"
|
||||
|
||||
const gl_color16_t* gl_color16_gradient_a4(gl_color_t fg_color,
|
||||
gl_color_t bg_color) {
|
||||
static gl_color16_t cache[16] = {0};
|
||||
|
||||
if (gl_color_to_color16(bg_color) != cache[0] ||
|
||||
gl_color_to_color16(fg_color) != cache[15]) {
|
||||
for (int alpha = 0; alpha < 16; alpha++) {
|
||||
cache[alpha] = gl_color16_blend_a4(fg_color, bg_color, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
return (const gl_color16_t*)&cache[0];
|
||||
}
|
||||
|
||||
const gl_color32_t* gl_color32_gradient_a4(gl_color_t fg_color,
|
||||
gl_color_t bg_color) {
|
||||
static gl_color32_t cache[16] = {0};
|
||||
|
||||
if (bg_color != gl_color32_to_color(cache[0]) ||
|
||||
fg_color != gl_color32_to_color(cache[15])) {
|
||||
for (int alpha = 0; alpha < 16; alpha++) {
|
||||
cache[alpha] = gl_color32_blend_a4(fg_color, bg_color, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
return (const gl_color32_t*)&cache[0];
|
||||
}
|
308
core/embed/lib/gl_color.h
Normal file
308
core/embed/lib/gl_color.h
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GL_COLOR_H
|
||||
#define GL_COLOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GL_COLOR_16BIT
|
||||
// #define GL_COLOR_32BIT
|
||||
|
||||
// Color in RGB565 format
|
||||
//
|
||||
// |15 8 | 7 0|
|
||||
// |---------------------------------|
|
||||
// |r r r r r g g g | g g g b b b b b|
|
||||
// |---------------------------------|
|
||||
|
||||
typedef uint16_t gl_color16_t;
|
||||
|
||||
// Color in RGBA8888 format
|
||||
//
|
||||
// |31 24 |23 16 |15 8 | 7 0 |
|
||||
// |----------------------------------------------------------------------|
|
||||
// |a a a a a a a a | r r r r r r r r | g g g g g g g g | b b b b b b b b |
|
||||
// |----------------------------------------------------------------------|
|
||||
//
|
||||
|
||||
typedef uint32_t gl_color32_t;
|
||||
|
||||
#ifdef GL_COLOR_16BIT
|
||||
#define gl_color_t gl_color16_t
|
||||
#define gl_color_to_color16(c) (c)
|
||||
#define gl_color16_to_color(c) (c)
|
||||
#define gl_color_to_color32(c) (gl_color16_to_color32(c))
|
||||
#define gl_color32_to_color(c) (gl_color32_to_color16(c))
|
||||
#define gl_color_lum(c) (gl_color16_lum(c))
|
||||
#elif GL_COLOR_32BIT
|
||||
#define gl_color_t gl_color32_t
|
||||
#define gl_color_to_color16(c) (gl_color32_to_color16(c))
|
||||
#define gl_color16_to_color(c) (gl_color16_to_color32(c))
|
||||
#define gl_color_to_color32(c) (c)
|
||||
#define gl_color32_to_color(c) (c)
|
||||
#else
|
||||
#error "GL_COLOR_16BIT/32BIT not specified"
|
||||
#endif
|
||||
|
||||
// Constructs a 16-bit color from the given red (r),
|
||||
// green (g), and blue (b) values in the range 0..255
|
||||
static inline gl_color16_t gl_color16_rgb(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return ((r & 0xF8U) << 8) | ((g & 0xFCU) << 3) | ((b & 0xF8U) >> 3);
|
||||
}
|
||||
|
||||
// Constructs a 32-bit color from the given red (r),
|
||||
// green (g), and blue (b) values in the range 0..255.
|
||||
// Alpha is set to 255.
|
||||
static inline gl_color32_t gl_color32_rgb(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return (0xFFU << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
|
||||
// Converts a 16-bit color to a 32-bit color; alpha is set to 255
|
||||
static inline gl_color32_t gl_color16_to_color32(gl_color16_t color) {
|
||||
uint32_t r = (color & 0xF800) >> 8;
|
||||
uint32_t g = (color & 0x07E0) >> 3;
|
||||
uint32_t b = (color & 0x001F) << 3;
|
||||
|
||||
r |= (r >> 5);
|
||||
g |= (g >> 6);
|
||||
b |= (b >> 5);
|
||||
|
||||
return (0xFFU << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// Converts 32-bit color to 16-bit color, alpha is ignored
|
||||
static inline gl_color16_t gl_color32_to_color16(gl_color32_t color) {
|
||||
uint16_t r = (color & 0x00F80000) >> 8;
|
||||
uint16_t g = (color & 0x0000FC00) >> 5;
|
||||
uint16_t b = (color & 0x000000F8) >> 3;
|
||||
|
||||
return r | g | b;
|
||||
}
|
||||
|
||||
// Converts 16-bit color into luminance (ranging from 0 to 255)
|
||||
static inline uint8_t gl_color16_lum(gl_color16_t color) {
|
||||
uint32_t r = (color & 0xF800) >> 8;
|
||||
uint32_t g = (color & 0x07E0) >> 3;
|
||||
uint32_t b = (color & 0x001F) << 3;
|
||||
|
||||
r |= (r >> 5);
|
||||
g |= (g >> 6);
|
||||
b |= (b >> 5);
|
||||
|
||||
return (r + g + b) / 3;
|
||||
}
|
||||
|
||||
#ifdef GL_COLOR_16BIT
|
||||
// Blends foreground and background colors with 4-bit alpha
|
||||
//
|
||||
// Returns a color in 16-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 15, the function returns the foreground color
|
||||
static inline gl_color16_t gl_color16_blend_a4(gl_color16_t fg, gl_color16_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0xF800) >> 11;
|
||||
uint16_t bg_r = (bg & 0xF800) >> 11;
|
||||
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_g = (fg & 0x07E0) >> 5;
|
||||
uint16_t bg_g = (bg & 0x07E0) >> 5;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_b = (fg & 0x001F) >> 0;
|
||||
uint16_t bg_b = (bg & 0x001F) >> 0;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15;
|
||||
|
||||
return (r << 11) | (g << 5) | b;
|
||||
}
|
||||
|
||||
// Blends foreground and background colors with 4-bit alpha
|
||||
//
|
||||
// Returns a color in 16-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 15, the function returns the foreground color
|
||||
static inline gl_color16_t gl_color16_blend_a8(gl_color16_t fg, gl_color16_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0xF800) >> 11;
|
||||
uint16_t bg_r = (bg & 0xF800) >> 11;
|
||||
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_g = (fg & 0x07E0) >> 5;
|
||||
uint16_t bg_g = (bg & 0x07E0) >> 5;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_b = (fg & 0x001F) >> 0;
|
||||
uint16_t bg_b = (bg & 0x001F) >> 0;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255;
|
||||
|
||||
return (r << 11) | (g << 5) | b;
|
||||
}
|
||||
|
||||
// Blends foreground and background colors with 4-bit alpha
|
||||
//
|
||||
// Returns a color in 32-bit format
|
||||
//
|
||||
// If alpha is 0, the function returns the background color
|
||||
// If alpha is 15, the function returns the foreground color
|
||||
static inline gl_color32_t gl_color32_blend_a4(gl_color16_t fg, gl_color16_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0xF800) >> 8;
|
||||
fg_r |= fg_r >> 5;
|
||||
uint16_t bg_r = (bg & 0xF800) >> 8;
|
||||
bg_r |= bg_r >> 5;
|
||||
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_g = (fg & 0x07E0) >> 3;
|
||||
fg_g |= fg_g >> 6;
|
||||
uint16_t bg_g = (bg & 0x07E0) >> 3;
|
||||
bg_g |= bg_g >> 6;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_b = (fg & 0x001F) << 3;
|
||||
fg_b |= fg_b >> 5;
|
||||
uint16_t bg_b = (bg & 0x001F) << 3;
|
||||
bg_b |= bg_b >> 5;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15;
|
||||
|
||||
return (0xFFU << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
|
||||
// Blends foreground and background colors with 8-bit alpha
|
||||
//
|
||||
// Returns a color in 32-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 255, the function returns the foreground color
|
||||
static inline gl_color32_t gl_color32_blend_a8(gl_color16_t fg, gl_color16_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0xF800) >> 8;
|
||||
fg_r |= fg_r >> 5;
|
||||
uint16_t bg_r = (bg & 0xF800) >> 8;
|
||||
bg_r |= bg_r >> 5;
|
||||
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_g = (fg & 0x07E0) >> 3;
|
||||
fg_g |= fg_g >> 6;
|
||||
uint16_t bg_g = (bg & 0x07E0) >> 3;
|
||||
bg_g |= bg_g >> 6;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_b = (fg & 0x001F) << 3;
|
||||
fg_b |= fg_b >> 5;
|
||||
uint16_t bg_b = (bg & 0x001F) << 3;
|
||||
bg_b |= bg_b >> 5;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255;
|
||||
|
||||
return (0xFFU << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
|
||||
#elif GL_COLOR_32BIT
|
||||
|
||||
// Blends foreground and background colors with 4-bit alpha
|
||||
//
|
||||
// Returns a color in 16-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 15, the function returns the foreground color
|
||||
static inline gl_color16_t gl_color16_blend_a4(gl_color32_t fg, gl_color32_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0x00FF0000) >> 16;
|
||||
uint16_t bg_r = (bg & 0x00FF0000) >> 16;
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_g = (fg & 0x0000FF00) >> 8;
|
||||
uint16_t bg_g = (bg & 0x0000FF00) >> 8;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_b = (fg & 0x000000FF) >> 0;
|
||||
uint16_t bg_b = (bg & 0x000000FF) >> 0;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15;
|
||||
|
||||
return gl_color16_rgb(r, g, b)
|
||||
}
|
||||
|
||||
// Blends foreground and background colors with 8-bit alpha
|
||||
//
|
||||
// Returns a color in 16-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 255, the function returns the foreground color
|
||||
static inline gl_color16_t gl_color16_blend_a8(gl_color32_t fg, gl_color32_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0x00FF0000) >> 16;
|
||||
uint16_t bg_r = (bg & 0x00FF0000) >> 16;
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_g = (fg & 0x0000FF00) >> 8;
|
||||
uint16_t bg_g = (bg & 0x0000FF00) >> 8;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (255 - alpha))) / 255;
|
||||
|
||||
uint16_t fg_b = (fg & 0x000000FF) >> 0;
|
||||
uint16_t bg_b = (bg & 0x000000FF) >> 0;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (255 - alpha))) / 255;
|
||||
|
||||
return gl_color16_rgb(r, g, b)
|
||||
}
|
||||
|
||||
// Blends foreground and background colors with 4-bit alpha
|
||||
//
|
||||
// Returns a color in 32-bit format
|
||||
//
|
||||
// If `alpha` is 0, the function returns the background color
|
||||
// If `alpha` is 15, the function returns the foreground color
|
||||
static inline gl_color32_t gl_color32_blend_a4(gl_color32_t fg, gl_color32_t bg,
|
||||
uint8_t alpha) {
|
||||
uint16_t fg_r = (fg & 0x00FF0000) >> 16;
|
||||
uint16_t bg_r = (bg & 0x00FF0000) >> 16;
|
||||
uint16_t r = (fg_r * alpha + (bg_r * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_g = (fg & 0x0000FF00) >> 8;
|
||||
uint16_t bg_g = (bg & 0x0000FF00) >> 8;
|
||||
uint16_t g = (fg_g * alpha + (bg_g * (15 - alpha))) / 15;
|
||||
|
||||
uint16_t fg_b = (fg & 0x000000FF) >> 0;
|
||||
uint16_t bg_b = (bg & 0x000000FF) >> 0;
|
||||
uint16_t b = (fg_b * alpha + (bg_b * (15 - alpha))) / 15;
|
||||
|
||||
return gl_color32_rgb(r, g, b);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "GL_COLOR_16BIT/32BIT not specified"
|
||||
#endif
|
||||
|
||||
// Returns a gradient as an array of 16 consecutive 16-bit colors
|
||||
//
|
||||
// Each element in the array represents a color, with `retval[0]` being
|
||||
// the background (`bg`) color and `retval[15]` the foreground (`fg`) color
|
||||
const gl_color16_t* gl_color16_gradient_a4(gl_color_t fg, gl_color_t bg);
|
||||
|
||||
// Returns a gradient as an array of 16 consecutive 32-bit colors
|
||||
//
|
||||
// Each element in the array represents a color, with `retval[0]` being
|
||||
// the background (`bg`) color and `retval[15]` the foreground (`fg`) color
|
||||
const gl_color32_t* gl_color32_gradient_a4(gl_color_t fg, gl_color_t bg);
|
||||
|
||||
#endif // TREZORHAL_GL_COLOR_H
|
270
core/embed/lib/gl_draw.c
Normal file
270
core/embed/lib/gl_draw.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <display.h>
|
||||
|
||||
#include "display_draw.h"
|
||||
#include "fonts/fonts.h"
|
||||
#include "gl_draw.h"
|
||||
|
||||
typedef struct {
|
||||
int16_t dst_x;
|
||||
int16_t dst_y;
|
||||
int16_t src_x;
|
||||
int16_t src_y;
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
} gl_clip_t;
|
||||
|
||||
static inline gl_clip_t gl_clip(gl_rect_t dst, const gl_bitmap_t* bitmap) {
|
||||
int16_t dst_x = dst.x0;
|
||||
int16_t dst_y = dst.y0;
|
||||
|
||||
int16_t src_x = 0;
|
||||
int16_t src_y = 0;
|
||||
|
||||
if (bitmap != NULL) {
|
||||
src_x += bitmap->offset.x;
|
||||
src_y += bitmap->offset.y;
|
||||
|
||||
// Normalize negative x-offset of bitmap
|
||||
if (src_x < 0) {
|
||||
dst_x -= src_x;
|
||||
src_x = 0;
|
||||
}
|
||||
|
||||
// Normalize negative y-offset of src bitmap
|
||||
if (src_y < 0) {
|
||||
dst_y -= src_y;
|
||||
src_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize negative top-left of destination rectangle
|
||||
if (dst_x < 0) {
|
||||
src_x -= dst_x;
|
||||
dst_x = 0;
|
||||
}
|
||||
|
||||
if (dst_y < 0) {
|
||||
src_y -= dst_y;
|
||||
dst_y = 0;
|
||||
}
|
||||
|
||||
// Calculate dimension of effective rectangle
|
||||
int16_t width = MIN(DISPLAY_RESX, dst.x1) - dst_x;
|
||||
int16_t height = MIN(DISPLAY_RESY, dst.y1) - dst_y;
|
||||
|
||||
if (bitmap != NULL) {
|
||||
width = MIN(width, bitmap->size.x - src_x);
|
||||
height = MIN(height, bitmap->size.y - src_y);
|
||||
}
|
||||
|
||||
gl_clip_t clip = {
|
||||
.dst_x = dst_x,
|
||||
.dst_y = dst_y,
|
||||
.src_x = src_x,
|
||||
.src_y = src_y,
|
||||
.width = width,
|
||||
.height = height,
|
||||
};
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
void gl_clear(void) {
|
||||
gl_bitblt_t bb = {
|
||||
// Destination bitmap
|
||||
.height = DISPLAY_RESX,
|
||||
.width = DISPLAY_RESY,
|
||||
.dst_row = NULL,
|
||||
.dst_x = 0,
|
||||
.dst_y = 0,
|
||||
.dst_stride = 0,
|
||||
|
||||
// Source bitmap
|
||||
.src_fg = 0,
|
||||
.src_alpha = 255,
|
||||
};
|
||||
|
||||
display_fill(&bb);
|
||||
}
|
||||
|
||||
void gl_draw_bar(gl_rect_t rect, gl_color_t color) {
|
||||
gl_clip_t clip = gl_clip(rect, NULL);
|
||||
|
||||
if (clip.width <= 0 || clip.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_bitblt_t bb = {
|
||||
// Destination bitmap
|
||||
.height = clip.height,
|
||||
.width = clip.width,
|
||||
.dst_row = NULL,
|
||||
.dst_x = clip.dst_x,
|
||||
.dst_y = clip.dst_y,
|
||||
.dst_stride = 0,
|
||||
|
||||
// Source bitmap
|
||||
.src_fg = color,
|
||||
.src_alpha = 255,
|
||||
};
|
||||
|
||||
display_fill(&bb);
|
||||
}
|
||||
|
||||
void gl_draw_bitmap(gl_rect_t rect, const gl_bitmap_t* bitmap) {
|
||||
gl_clip_t clip = gl_clip(rect, bitmap);
|
||||
|
||||
if (clip.width <= 0 || clip.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_bitblt_t bb = {
|
||||
// Destination bitmap
|
||||
.height = clip.height,
|
||||
.width = clip.width,
|
||||
.dst_row = NULL,
|
||||
.dst_x = clip.dst_x,
|
||||
.dst_y = clip.dst_y,
|
||||
.dst_stride = 0,
|
||||
|
||||
// Source bitmap
|
||||
.src_row = (uint8_t*)bitmap->ptr + bitmap->stride * clip.src_y,
|
||||
.src_x = clip.src_x,
|
||||
.src_y = clip.src_y,
|
||||
.src_stride = bitmap->stride,
|
||||
.src_fg = bitmap->fg_color,
|
||||
.src_bg = bitmap->bg_color,
|
||||
.src_alpha = 255,
|
||||
};
|
||||
|
||||
#if TREZOR_FONT_BPP == 1
|
||||
if (bitmap->format == GL_FORMAT_MONO1P) {
|
||||
display_copy_mono1p(&bb);
|
||||
}
|
||||
#endif
|
||||
#if TREZOR_FONT_BPP == 4
|
||||
if (bitmap->format == GL_FORMAT_MONO4) {
|
||||
display_copy_mono4(&bb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TREZOR_FONT_BPP == 1
|
||||
#define GLYPH_FORMAT GL_FORMAT_MONO1P
|
||||
#define GLYPH_STRIDE(w) (((w) + 7) / 8)
|
||||
#elif TREZOR_FONT_BPP == 2
|
||||
#error Unsupported TREZOR_FONT_BPP value
|
||||
#define GLYPH_FORMAT GL_FORMAT_MONO2
|
||||
#define GLYPH_STRIDE(w) (((w) + 3) / 4)
|
||||
#elif TREZOR_FONT_BPP == 4
|
||||
#define GLYPH_FORMAT GL_FORMAT_MONO4
|
||||
#define GLYPH_STRIDE(w) (((w) + 1) / 2)
|
||||
#elif TREZOR_FONT_BPP == 8
|
||||
#error Unsupported TREZOR_FONT_BPP value
|
||||
#define GLYPH_FORMAT GL_FORMAT_MONO8
|
||||
#define GLYPH_STRIDE(w) (w)
|
||||
#else
|
||||
#error Unsupported TREZOR_FONT_BPP value
|
||||
#endif
|
||||
|
||||
#define GLYPH_WIDTH(g) ((g)[0])
|
||||
#define GLYPH_HEIGHT(g) ((g)[1])
|
||||
#define GLYPH_ADVANCE(g) ((g)[2])
|
||||
#define GLYPH_BEARING_X(g) ((g)[3])
|
||||
#define GLYPH_BEARING_Y(g) ((g)[4])
|
||||
#define GLYPH_DATA(g) ((void*)&(g)[5])
|
||||
|
||||
void gl_draw_text(gl_offset_t pos, const char* text, size_t maxlen,
|
||||
const gl_text_attr_t* attr) {
|
||||
if (text == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_bitmap_t bitmap = {
|
||||
.format = GLYPH_FORMAT,
|
||||
.fg_color = attr->fg_color,
|
||||
.bg_color = attr->bg_color,
|
||||
};
|
||||
|
||||
int max_height = font_max_height(attr->font);
|
||||
int baseline = font_baseline(attr->font);
|
||||
|
||||
for (int i = 0; i < maxlen; i++) {
|
||||
uint8_t ch = (uint8_t)text[i];
|
||||
|
||||
if (ch == 0 || pos.x >= DISPLAY_RESX) {
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t* glyph = font_get_glyph(attr->font, ch);
|
||||
|
||||
if (glyph == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bitmap.ptr = GLYPH_DATA(glyph);
|
||||
bitmap.stride = GLYPH_STRIDE(GLYPH_WIDTH(glyph));
|
||||
bitmap.size.x = GLYPH_WIDTH(glyph);
|
||||
bitmap.size.y = GLYPH_HEIGHT(glyph);
|
||||
|
||||
bitmap.offset.x = -GLYPH_BEARING_X(glyph);
|
||||
bitmap.offset.y = -(max_height - baseline - GLYPH_BEARING_Y(glyph));
|
||||
|
||||
gl_draw_bitmap(gl_rect(pos.x, pos.y, DISPLAY_RESX, DISPLAY_RESY), &bitmap);
|
||||
|
||||
pos.x += GLYPH_ADVANCE(glyph);
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// emulation of legacy functions
|
||||
|
||||
void display_clear(void) { gl_clear(); }
|
||||
|
||||
void display_bar(int x, int y, int w, int h, uint16_t c) {
|
||||
gl_draw_bar(gl_rect_wh(x, y, w, h), c);
|
||||
}
|
||||
|
||||
void display_text(int x, int y, const char* text, int textlen, int font,
|
||||
uint16_t fg_color, uint16_t bg_color) {
|
||||
gl_text_attr_t attr = {
|
||||
.font = font,
|
||||
.fg_color = fg_color,
|
||||
.bg_color = bg_color,
|
||||
};
|
||||
|
||||
size_t maxlen = textlen < 0 ? UINT32_MAX : textlen;
|
||||
gl_draw_text(gl_offset(x, y), text, maxlen, &attr);
|
||||
}
|
||||
|
||||
void display_text_center(int x, int y, const char* text, int textlen, int font,
|
||||
uint16_t fg_color, uint16_t bg_color) {
|
||||
gl_text_attr_t attr = {
|
||||
.font = font,
|
||||
.fg_color = fg_color,
|
||||
.bg_color = bg_color,
|
||||
};
|
||||
|
||||
size_t maxlen = textlen < 0 ? UINT32_MAX : textlen;
|
||||
int w = font_text_width(font, text, textlen);
|
||||
gl_draw_text(gl_offset(x - w / 2, y), text, maxlen, &attr);
|
||||
}
|
149
core/embed/lib/gl_draw.h
Normal file
149
core/embed/lib/gl_draw.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GL_DRAW_H
|
||||
#define GL_DRAW_H
|
||||
|
||||
#include "gl_color.h"
|
||||
|
||||
// 2D rectangle coordinates
|
||||
//
|
||||
// `x0`, `y0` - top-left coordinates
|
||||
// `x1`, `y1` - bottom-right coordinates point (not included)
|
||||
typedef struct {
|
||||
int16_t x0;
|
||||
int16_t y0;
|
||||
int16_t x1;
|
||||
int16_t y1;
|
||||
} gl_rect_t;
|
||||
|
||||
// Builds a rectangle (`gl_rect_t`) from top-left coordinates and dimensions
|
||||
static inline gl_rect_t gl_rect_wh(int16_t x, int16_t y, int16_t w, int16_t h) {
|
||||
gl_rect_t rect = {
|
||||
.x0 = x,
|
||||
.y0 = y,
|
||||
.x1 = x + w,
|
||||
.y1 = y + h,
|
||||
};
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Builds a rectangle (`gl_rect_t`) from top-left and bottom-right coordinates
|
||||
static inline gl_rect_t gl_rect(int16_t x0, int16_t y0, int16_t x1,
|
||||
int16_t y1) {
|
||||
gl_rect_t rect = {
|
||||
.x0 = x0,
|
||||
.y0 = y0,
|
||||
.x1 = x1,
|
||||
.y1 = y1,
|
||||
};
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
// 2D offset/ coordinates
|
||||
typedef struct {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} gl_offset_t;
|
||||
|
||||
// Builds a `gl_offset_t` structure
|
||||
static inline gl_offset_t gl_offset(int16_t x, int16_t y) {
|
||||
gl_offset_t offset = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
};
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
// 2D size in pixels
|
||||
typedef struct {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} gl_size_t;
|
||||
|
||||
// Builds a `gl_size_t` structure
|
||||
static inline gl_size_t gl_size(int16_t x, int16_t y) {
|
||||
gl_size_t size = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
};
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// Format of pixels in a bitmap
|
||||
typedef enum {
|
||||
GL_FORMAT_UNKNOWN, //
|
||||
GL_FORMAT_MONO1P, // 1-bpp per pixel (packed)
|
||||
GL_FORMAT_MONO4, // 4-bpp per pixel
|
||||
GL_FORMAT_RGB565, // 16-bpp per pixel
|
||||
GL_FORMAT_RGBA8888, // 32-bpp
|
||||
} gl_format_t;
|
||||
|
||||
// 2D bitmap reference
|
||||
typedef struct {
|
||||
// pointer to top-left pixel
|
||||
void* ptr;
|
||||
// stride in bytes
|
||||
size_t stride;
|
||||
// size in pixels
|
||||
gl_size_t size;
|
||||
// format of pixels, GL_FORMAT_xxx
|
||||
uint8_t format;
|
||||
// offset used when bitmap is drawed using gl_draw_bitmap()
|
||||
gl_offset_t offset;
|
||||
// foreground color (used with MONOx formats)
|
||||
gl_color_t fg_color;
|
||||
// background color (used with MONOx formats)
|
||||
gl_color_t bg_color;
|
||||
} gl_bitmap_t;
|
||||
|
||||
// Text attributes (font and color)
|
||||
typedef struct {
|
||||
// Font identifier
|
||||
int font;
|
||||
// Foreground color
|
||||
gl_color_t fg_color;
|
||||
// Background color
|
||||
gl_color_t bg_color;
|
||||
} gl_text_attr_t;
|
||||
|
||||
// Fills a rectangle with a specified color.
|
||||
void gl_draw_bar(gl_rect_t rect, gl_color_t color);
|
||||
|
||||
// Draws a bitmap into the specified rectangle.
|
||||
//
|
||||
// The destination rectangle may not be fully filled if the source bitmap
|
||||
// is smaller then destination rectangle or if the bitmap is translated by
|
||||
// an offset partially or completely outside the destination rectangle.
|
||||
void gl_draw_bitmap(gl_rect_t rect, const gl_bitmap_t* bitmap);
|
||||
|
||||
// Draws a text to the specified position.
|
||||
//
|
||||
// `offset` - the most left point on the font baseline
|
||||
// `text` - utf-8 text
|
||||
// `maxlen` - maximum number of characters displayed (use SIZE_MAX when not
|
||||
// specified) `attr` - font & text color
|
||||
void gl_draw_text(gl_offset_t offset, const char* text, size_t maxlen,
|
||||
const gl_text_attr_t* attr);
|
||||
|
||||
#endif // GL_DRAW_H
|
@ -24,7 +24,8 @@
|
||||
#include "display.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#ifndef TREZOR_PRINT_DISABLE
|
||||
#include "fonts/fonts.h"
|
||||
#include "gl_draw.h"
|
||||
|
||||
#define TERMINAL_COLS (DISPLAY_RESX / 6)
|
||||
#define TERMINAL_ROWS (DISPLAY_RESY / 8)
|
||||
@ -39,6 +40,62 @@ void term_set_color(uint16_t fgcolor, uint16_t bgcolor) {
|
||||
terminal_bgcolor = bgcolor;
|
||||
}
|
||||
|
||||
#ifdef NEW_RENDERING
|
||||
|
||||
// Font_Bitmap contains 96 (0x20 - 0x7F) 5x7 glyphs
|
||||
// Each glyph consists of 5 bytes (each byte represents one column)
|
||||
//
|
||||
// This function converts the glyph into the format compatible
|
||||
// with `display_copy_mono1p()` functions.
|
||||
static uint64_t term_glyph_bits(char ch) {
|
||||
union {
|
||||
uint64_t u64;
|
||||
uint8_t bytes[8];
|
||||
} result = {0};
|
||||
|
||||
if (ch > ' ' && ch < 128) {
|
||||
const uint8_t *b = &Font_Bitmap[(ch - ' ') * 5];
|
||||
|
||||
for (int y = 0; y < 7; y++) {
|
||||
uint8_t mask = 1 << y;
|
||||
result.bytes[y] |= ((b[0] & mask) ? 128 : 0) + ((b[1] & mask) ? 64 : 0) +
|
||||
((b[2] & mask) ? 32 : 0) + ((b[3] & mask) ? 16 : 0) +
|
||||
((b[4] & mask) ? 8 : 0);
|
||||
}
|
||||
}
|
||||
return result.u64;
|
||||
}
|
||||
|
||||
// Redraws specified rows to the display
|
||||
static void term_redraw_rows(int start_row, int row_count) {
|
||||
uint64_t glyph_bits = 0;
|
||||
gl_bitblt_t bb = {
|
||||
.height = 8,
|
||||
.width = 6,
|
||||
.dst_row = NULL,
|
||||
.dst_x = 0,
|
||||
.dst_y = 0,
|
||||
.dst_stride = 0,
|
||||
|
||||
.src_row = &glyph_bits,
|
||||
.src_x = 0,
|
||||
.src_y = 0,
|
||||
.src_stride = 8,
|
||||
.src_fg = terminal_fgcolor,
|
||||
.src_bg = terminal_bgcolor,
|
||||
};
|
||||
|
||||
for (int y = start_row; y < start_row + row_count; y++) {
|
||||
bb.dst_y = y * 8;
|
||||
for (int x = 0; x < TERMINAL_COLS; x++) {
|
||||
glyph_bits = term_glyph_bits(terminal_fb[y][x]);
|
||||
bb.dst_x = x * 6;
|
||||
display_copy_mono1p(&bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NEW_RENDERING
|
||||
|
||||
// display text using bitmap font
|
||||
void term_print(const char *text, int textlen) {
|
||||
static uint8_t row = 0, col = 0;
|
||||
@ -77,6 +134,10 @@ void term_print(const char *text, int textlen) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NEW_RENDERING
|
||||
term_redraw_rows(0, TERMINAL_ROWS);
|
||||
display_refresh();
|
||||
#else // NEW RENDERING
|
||||
// render buffer to display
|
||||
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
|
||||
@ -105,6 +166,7 @@ void term_print(const char *text, int textlen) {
|
||||
}
|
||||
display_pixeldata_dirty();
|
||||
display_refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TREZOR_EMULATOR
|
||||
@ -127,5 +189,3 @@ void term_printf(const char *fmt, ...) {
|
||||
va_end(va);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TREZOR_PRINT_DISABLE
|
||||
|
@ -22,11 +22,9 @@
|
||||
|
||||
#include "colors.h"
|
||||
|
||||
#ifndef TREZOR_PRINT_DISABLE
|
||||
void term_set_color(uint16_t fgcolor, uint16_t bgcolor);
|
||||
void term_print(const char *text, int textlen);
|
||||
void term_printf(const char *fmt, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
#endif
|
||||
|
||||
#endif // LIB_TERMINAL_H
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "button.h"
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "display_utils.h"
|
||||
#include "fault_handlers.h"
|
||||
#include "flash.h"
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
#include "model.h"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "sbu.h"
|
||||
#include "sdcard.h"
|
||||
#include "secbool.h"
|
||||
#include "terminal.h"
|
||||
#include "touch.h"
|
||||
|
||||
#ifdef USE_HASH_PROCESSOR
|
||||
@ -56,8 +58,7 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source,
|
||||
ensure(sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1),
|
||||
"sdcard_read_blocks");
|
||||
|
||||
for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / FLASH_BLOCK_SIZE)
|
||||
; j++) {
|
||||
for (uint32_t j = 0; j < (SDCARD_BLOCK_SIZE / FLASH_BLOCK_SIZE); j++) {
|
||||
ensure(flash_area_write_block(
|
||||
area, i * SDCARD_BLOCK_SIZE + j * FLASH_BLOCK_SIZE,
|
||||
&buf[j * FLASH_BLOCK_WORDS]),
|
||||
|
@ -1,12 +1,15 @@
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#include "buffers.h"
|
||||
#include "button.h"
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_interface.h"
|
||||
#include "display_draw.h"
|
||||
#include "dma2d.h"
|
||||
#include "dma2d_bitblt.h"
|
||||
#include "flash.h"
|
||||
#include "fonts/fonts.h"
|
||||
#include "gl_bitblt.h"
|
||||
#include "haptic.h"
|
||||
#include "model.h"
|
||||
#include "rgb_led.h"
|
||||
|
@ -3,18 +3,16 @@
|
||||
|
||||
#define HSE_8MHZ
|
||||
|
||||
#define MAX_DISPLAY_RESX 240
|
||||
#define MAX_DISPLAY_RESY 320
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 320
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
|
||||
#define DISPLAY_LEGACY_HEADER "displays/ltdc.h"
|
||||
|
||||
#define USE_I2C 1
|
||||
#define USE_TOUCH 1
|
||||
#define USE_SDRAM 1
|
||||
#define USE_RGB_COLORS 1
|
||||
|
||||
#include "displays/ltdc.h"
|
||||
|
||||
#define I2C_COUNT 1
|
||||
#define I2C_INSTANCE_0 I2C3
|
||||
#define I2C_INSTANCE_0_CLK_EN __HAL_RCC_I2C3_CLK_ENABLE
|
||||
|
@ -11,7 +11,11 @@
|
||||
//#define USE_DISP_I8080_8BIT_DW 1
|
||||
#define USE_HASH_PROCESSOR 1
|
||||
|
||||
#include "displays/dsi.h"
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_ARGB8888
|
||||
#define DISPLAY_LEGACY_HEADER "displays/dsi.h"
|
||||
|
||||
#define I2C_COUNT 1
|
||||
#define I2C_INSTANCE_0 I2C5
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
#define USE_BUTTON 1
|
||||
|
||||
#include "displays/vg-2864ksweg01.h"
|
||||
#define DISPLAY_RESX 128
|
||||
#define DISPLAY_RESY 64
|
||||
|
||||
#define BTN_LEFT_PIN GPIO_PIN_5
|
||||
#define BTN_LEFT_PORT GPIOC
|
||||
|
@ -8,7 +8,9 @@
|
||||
#define USE_I2C 1
|
||||
#define USE_CONSUMPTION_MASK 1
|
||||
|
||||
#include "displays/vg-2864ksweg01.h"
|
||||
#define DISPLAY_RESX 128
|
||||
#define DISPLAY_RESY 64
|
||||
#define DISPLAY_LEGACY_HEADER "displays/vg-2864ksweg01.h"
|
||||
|
||||
#define BTN_LEFT_PIN GPIO_PIN_10
|
||||
#define BTN_LEFT_PORT GPIOC
|
||||
|
@ -6,7 +6,9 @@
|
||||
#define USE_BUTTON 1
|
||||
#define USE_SBU 1
|
||||
|
||||
#include "displays/ug-2828tswig01.h"
|
||||
#define DISPLAY_RESX 128
|
||||
#define DISPLAY_RESY 128
|
||||
#define DISPLAY_LEGACY_HEADER "displays/ug-2828tswig01.h"
|
||||
|
||||
#define BTN_LEFT_PIN GPIO_PIN_0
|
||||
#define BTN_LEFT_PORT GPIOA
|
||||
|
@ -6,7 +6,9 @@
|
||||
#define USE_BUTTON 1
|
||||
#define USE_SBU 1
|
||||
|
||||
#include "displays/vg-2864ksweg01.h"
|
||||
#define DISPLAY_RESX 128
|
||||
#define DISPLAY_RESY 64
|
||||
#define DISPLAY_LEGACY_HEADER "displays/vg-2864ksweg01.h"
|
||||
|
||||
#define BTN_LEFT_PIN GPIO_PIN_5
|
||||
#define BTN_LEFT_PORT GPIOC
|
||||
|
@ -6,7 +6,9 @@
|
||||
#define USE_BUTTON 1
|
||||
#define USE_SBU 1
|
||||
|
||||
#include "displays/vg-2864ksweg01.h"
|
||||
#define DISPLAY_RESX 128
|
||||
#define DISPLAY_RESY 64
|
||||
#define DISPLAY_LEGACY_HEADER "displays/vg-2864ksweg01.h"
|
||||
|
||||
#define BTN_LEFT_PIN GPIO_PIN_10
|
||||
#define BTN_LEFT_PORT GPIOC
|
||||
|
@ -3,9 +3,6 @@
|
||||
|
||||
#define HSE_8MHZ
|
||||
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
|
||||
#define USE_SD_CARD 1
|
||||
#define USE_I2C 1
|
||||
#define USE_TOUCH 1
|
||||
@ -14,12 +11,14 @@
|
||||
#define USE_BACKLIGHT 1
|
||||
#define USE_DISP_I8080_8BIT_DW 1
|
||||
|
||||
#include "displays/panels/lx154a2422.h"
|
||||
#include "displays/st7789v.h"
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
|
||||
#define DISPLAY_LEGACY_HEADER "displays/st7789v.h"
|
||||
|
||||
#define DISPLAY_IDENTIFY 1
|
||||
#define DISPLAY_TE_PORT GPIOD
|
||||
#define DISPLAY_TE_PIN GPIO_PIN_12
|
||||
#define TRANSFORM_TOUCH_COORDS lx154a2422_transform_touch_coords
|
||||
|
||||
#define BACKLIGHT_PWM_FREQ 10000
|
||||
#define BACKLIGHT_PWM_TIM TIM1
|
||||
|
@ -1,9 +1,6 @@
|
||||
#ifndef _TREZOR_T3T1_H
|
||||
#define _TREZOR_T3T1_H
|
||||
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
|
||||
#define VDD_1V8 1
|
||||
|
||||
#define USE_SD_CARD 1
|
||||
@ -16,8 +13,11 @@
|
||||
#define USE_BACKLIGHT 1
|
||||
#define USE_HASH_PROCESSOR 1
|
||||
|
||||
#include "displays/panels/lx154a2422.h"
|
||||
#include "displays/st7789v.h"
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
#define DISPLAY_LEGACY_HEADER "displays/st7789v.h"
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
|
||||
|
||||
#define DISPLAY_IDENTIFY 1
|
||||
#define DISPLAY_TE_PORT GPIOD
|
||||
#define DISPLAY_TE_PIN GPIO_PIN_12
|
||||
@ -26,10 +26,6 @@
|
||||
#define DISPLAY_TE_INTERRUPT_GPIOSEL EXTI_GPIOD
|
||||
#define DISPLAY_TE_INTERRUPT_EXTI_LINE EXTI_LINE_12
|
||||
|
||||
#define DISPLAY_PANEL_INIT_SEQ lx154a2422_init_seq
|
||||
#define DISPLAY_PANEL_ROTATE lx154a2422_rotate
|
||||
#define TRANSFORM_TOUCH_COORDS lx154a2422_transform_touch_coords
|
||||
|
||||
#define BACKLIGHT_PWM_FREQ 12500
|
||||
#define BACKLIGHT_PWM_TIM TIM17
|
||||
#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
|
||||
|
@ -1,9 +1,6 @@
|
||||
#ifndef _TREZOR_T3T1_H
|
||||
#define _TREZOR_T3T1_H
|
||||
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
|
||||
#define VDD_1V8 1
|
||||
#define HSE_16MHZ 1
|
||||
|
||||
@ -17,8 +14,11 @@
|
||||
#define USE_BACKLIGHT 1
|
||||
#define USE_HASH_PROCESSOR 1
|
||||
|
||||
#include "displays/panels/lx154a2422.h"
|
||||
#include "displays/st7789v.h"
|
||||
#define DISPLAY_RESX 240
|
||||
#define DISPLAY_RESY 240
|
||||
#define DISPLAY_LEGACY_HEADER "displays/st7789v.h"
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
|
||||
|
||||
#define DISPLAY_IDENTIFY 1
|
||||
#define DISPLAY_TE_PORT GPIOD
|
||||
#define DISPLAY_TE_PIN GPIO_PIN_12
|
||||
@ -27,10 +27,6 @@
|
||||
#define DISPLAY_TE_INTERRUPT_GPIOSEL EXTI_GPIOD
|
||||
#define DISPLAY_TE_INTERRUPT_EXTI_LINE EXTI_LINE_12
|
||||
|
||||
#define DISPLAY_PANEL_INIT_SEQ lx154a2422_init_seq
|
||||
#define DISPLAY_PANEL_ROTATE lx154a2422_rotate
|
||||
#define TRANSFORM_TOUCH_COORDS lx154a2422_transform_touch_coords
|
||||
|
||||
#define BACKLIGHT_PWM_FREQ 12500
|
||||
#define BACKLIGHT_PWM_TIM TIM8
|
||||
#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM8_CLK_ENABLE
|
||||
|
@ -17,13 +17,22 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DISPLAY_INTERFACE_H
|
||||
#define _DISPLAY_INTERFACE_H
|
||||
#ifndef TREZORHAL_DISPLAY_H
|
||||
#define TREZORHAL_DISPLAY_H
|
||||
|
||||
#if NEW_RENDERING
|
||||
#include <xdisplay.h>
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#ifdef DISPLAY_LEGACY_HEADER
|
||||
#include DISPLAY_LEGACY_HEADER
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_FRAMEBUFFER_OFFSET_Y
|
||||
#define DISPLAY_FRAMEBUFFER_OFFSET_Y 0
|
||||
#endif
|
||||
@ -68,4 +77,5 @@ uint8_t *display_get_wr_addr(void);
|
||||
void display_shift_window(uint16_t pixels);
|
||||
uint16_t display_get_window_offset(void);
|
||||
|
||||
#endif //_DISPLAY_INTERFACE_H
|
||||
#endif // NEW_RENDERING
|
||||
#endif // TREZORHAL_DISPLAY_H
|
46
core/embed/trezorhal/dma2d_bitblt.h
Normal file
46
core/embed/trezorhal/dma2d_bitblt.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_DMA2D_BITBLT_H
|
||||
#define TREZORHAL_DMA2D_BITBLT_H
|
||||
|
||||
#include "gl_bitblt.h"
|
||||
|
||||
// Returns `true` if the specified address is accessible by DMA2D
|
||||
// and can be used by any of the following functions
|
||||
bool dma2d_accessible(const void* ptr);
|
||||
|
||||
// Waits until any pending DMA2D operation is finished
|
||||
void dma2d_wait(void);
|
||||
|
||||
// Following functions are hardware (DMA2D) accelerated versions
|
||||
// of `gl_rgb565_xxx()` and `gl_rgba8888_xxx()` function from `gl_bitblt.h`
|
||||
|
||||
void dma2d_rgb565_fill(const gl_bitblt_t* bb);
|
||||
void dma2d_rgb565_copy_mono4(const gl_bitblt_t* bb);
|
||||
void dma2d_rgb565_copy_rgb565(const gl_bitblt_t* bb);
|
||||
void dma2d_rgb565_blend_mono4(const gl_bitblt_t* bb);
|
||||
|
||||
void dma2d_rgba8888_fill(const gl_bitblt_t* bb);
|
||||
void dma2d_rgba8888_copy_mono4(const gl_bitblt_t* bb);
|
||||
void dma2d_rgba8888_copy_rgb565(const gl_bitblt_t* bb);
|
||||
void dma2d_rgba8888_copy_rgba8888(const gl_bitblt_t* bb);
|
||||
void dma2d_rgba8888_blend_mono4(const gl_bitblt_t* bb);
|
||||
|
||||
#endif // TREZORHAL_DMA2D_BITBLT_H
|
@ -220,7 +220,11 @@ void collect_hw_entropy(void) {
|
||||
void ensure_compatible_settings(void) {
|
||||
display_finish_actions();
|
||||
#ifdef TREZOR_MODEL_T
|
||||
#ifdef NEW_RENDERING
|
||||
display_set_compatible_settings();
|
||||
#else
|
||||
display_set_big_endian();
|
||||
#endif
|
||||
display_orientation(0);
|
||||
set_core_clock(CLOCK_168_MHZ);
|
||||
backlight_pwm_set_slow();
|
||||
|
222
core/embed/trezorhal/stm32f4/display/st-7789/display_driver.c
Normal file
222
core/embed/trezorhal/stm32f4/display/st-7789/display_driver.c
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <xdisplay.h>
|
||||
|
||||
#include "display_fb.h"
|
||||
#include "display_io.h"
|
||||
#include "display_panel.h"
|
||||
|
||||
#include "backlight_pwm.h"
|
||||
#include "supervise.h"
|
||||
|
||||
#ifndef BOARDLOADER
|
||||
#include "bg_copy.h"
|
||||
#endif
|
||||
|
||||
#if (DISPLAY_RESX != 240) || (DISPLAY_RESY != 240)
|
||||
#error "Incompatible display resolution"
|
||||
#endif
|
||||
|
||||
// Display driver context.
|
||||
typedef struct {
|
||||
// Current display orientation (0, 90, 180, 270)
|
||||
int orientation_angle;
|
||||
} display_driver_t;
|
||||
|
||||
// Display driver instance
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
void display_init(void) {
|
||||
display_driver_t* drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
|
||||
display_io_init_gpio();
|
||||
display_io_init_fmc();
|
||||
display_panel_init();
|
||||
display_panel_set_little_endian();
|
||||
backlight_pwm_init();
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
display_io_init_te_interrupt();
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
display_driver_t* drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
|
||||
// Reinitialize FMC to set correct timing
|
||||
// We have to do this in reinit because boardloader is fixed.
|
||||
display_io_init_fmc();
|
||||
|
||||
// Important for model T as this is not set in boardloader
|
||||
display_panel_set_little_endian();
|
||||
display_panel_init_gamma();
|
||||
backlight_pwm_reinit();
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
display_io_init_te_interrupt();
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
#ifdef XFRAMEBUFFER
|
||||
#ifndef BOARDLOADER
|
||||
bg_copy_wait();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
#ifdef XFRAMEBUFFER
|
||||
#ifndef BOARDLOADER
|
||||
// wait for DMA transfer to finish before changing backlight
|
||||
// so that we know that panel has current data
|
||||
if (backlight_pwm_get() != level && !is_mode_handler()) {
|
||||
bg_copy_wait();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return backlight_pwm_set(level);
|
||||
}
|
||||
|
||||
int display_get_backlight(void) { return backlight_pwm_get(); }
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t* drv = &g_display_driver;
|
||||
|
||||
if (angle != drv->orientation_angle) {
|
||||
if (angle == 0 || angle == 90 || angle == 180 || angle == 270) {
|
||||
drv->orientation_angle = angle;
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
memset(physical_frame_buffer_0, 0, sizeof(physical_frame_buffer_0));
|
||||
memset(physical_frame_buffer_1, 0, sizeof(physical_frame_buffer_1));
|
||||
#endif
|
||||
|
||||
display_panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
for (uint32_t i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
|
||||
// 2 bytes per pixel because we're using RGB 5-6-5 format
|
||||
ISSUE_PIXEL_DATA(0x0000);
|
||||
}
|
||||
|
||||
display_panel_rotate(angle);
|
||||
}
|
||||
}
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t* drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
#ifndef XFRAMEBUFFER
|
||||
void display_refresh(void) {
|
||||
// if the framebuffer is not used the implementation is empty
|
||||
}
|
||||
#endif
|
||||
|
||||
void display_wait_for_sync(void) {
|
||||
#ifdef DISPLAY_TE_PIN
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id && (id != DISPLAY_ID_GC9307)) {
|
||||
// synchronize with the panel synchronization signal
|
||||
// in order to avoid visual tearing effects
|
||||
while (GPIO_PIN_SET == HAL_GPIO_ReadPin(DISPLAY_TE_PORT, DISPLAY_TE_PIN))
|
||||
;
|
||||
while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(DISPLAY_TE_PORT, DISPLAY_TE_PIN))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_set_compatible_settings(void) { display_panel_set_big_endian(); }
|
||||
|
||||
static inline void set_window(const gl_bitblt_t* bb) {
|
||||
display_panel_set_window(bb->dst_x, bb->dst_y, bb->dst_x + bb->width - 1,
|
||||
bb->dst_y + bb->height + 1);
|
||||
}
|
||||
|
||||
void display_fill(const gl_bitblt_t* bb) {
|
||||
set_window(bb);
|
||||
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
ISSUE_PIXEL_DATA(bb->src_fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display_copy_rgb565(const gl_bitblt_t* bb) {
|
||||
set_window(bb);
|
||||
|
||||
uint16_t* src_ptr = (uint16_t*)bb->src_row + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
ISSUE_PIXEL_DATA(src_ptr[x]);
|
||||
}
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t* bb) {
|
||||
set_window(bb);
|
||||
|
||||
uint8_t* src = (uint8_t*)bb->src_row;
|
||||
uint16_t src_ofs = bb->src_stride * bb->src_y + bb->src_x;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t mask = 1 << (7 - ((src_ofs + x) & 7));
|
||||
uint8_t data = src[(src_ofs + x) / 8];
|
||||
ISSUE_PIXEL_DATA((data & mask) ? bb->src_fg : bb->src_bg);
|
||||
}
|
||||
src_ofs += bb->src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void display_copy_mono4(const gl_bitblt_t* bb) {
|
||||
set_window(bb);
|
||||
|
||||
const gl_color16_t* gradient = gl_color16_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
|
||||
uint8_t* src_row = (uint8_t*)bb->src_row;
|
||||
uint16_t height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
uint8_t fg_data = src_row[(x + bb->src_x) / 2];
|
||||
uint8_t fg_lum = (x + bb->src_x) & 1 ? fg_data >> 4 : fg_data & 0xF;
|
||||
ISSUE_PIXEL_DATA(gradient[fg_lum]);
|
||||
}
|
||||
src_row += bb->src_stride / sizeof(*src_row);
|
||||
}
|
||||
}
|
172
core/embed/trezorhal/stm32f4/display/st-7789/display_fb.c
Normal file
172
core/embed/trezorhal/stm32f4/display/st-7789/display_fb.c
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "display_fb.h"
|
||||
#include "display_io.h"
|
||||
#include "display_panel.h"
|
||||
#include "xdisplay.h"
|
||||
|
||||
#include "irq.h"
|
||||
#include "supervise.h"
|
||||
|
||||
#ifndef BOARDLOADER
|
||||
#include "bg_copy.h"
|
||||
#endif
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
|
||||
#ifndef STM32U5
|
||||
#error Framebuffer only supported on STM32U5 for now
|
||||
#endif
|
||||
|
||||
// Physical frame buffers in internal SRAM memory
|
||||
__attribute__((section(".fb1")))
|
||||
ALIGN_32BYTES(uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]);
|
||||
|
||||
__attribute__((section(".fb2")))
|
||||
ALIGN_32BYTES(uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]);
|
||||
|
||||
// The current frame buffer selector at fixed memory address
|
||||
// It's shared between bootloaders and the firmware
|
||||
__attribute__((section(".framebuffer_select"))) uint32_t current_frame_buffer =
|
||||
0;
|
||||
|
||||
#ifndef BOARDLOADER
|
||||
static bool pending_fb_switch = false;
|
||||
#endif
|
||||
|
||||
#ifndef BOARDLOADER
|
||||
void DISPLAY_TE_INTERRUPT_HANDLER(void) {
|
||||
HAL_NVIC_DisableIRQ(DISPLAY_TE_INTERRUPT_NUM);
|
||||
|
||||
if (current_frame_buffer == 1) {
|
||||
bg_copy_start_const_out_8((uint8_t *)physical_frame_buffer_1,
|
||||
(uint8_t *)DISPLAY_DATA_ADDRESS,
|
||||
DISPLAY_RESX * DISPLAY_RESY * 2);
|
||||
|
||||
} else {
|
||||
bg_copy_start_const_out_8((uint8_t *)physical_frame_buffer_0,
|
||||
(uint8_t *)DISPLAY_DATA_ADDRESS,
|
||||
DISPLAY_RESX * DISPLAY_RESY * 2);
|
||||
}
|
||||
|
||||
pending_fb_switch = false;
|
||||
__HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN);
|
||||
}
|
||||
|
||||
static void wait_for_fb_switch(void) {
|
||||
while (pending_fb_switch) {
|
||||
__WFI();
|
||||
}
|
||||
bg_copy_wait();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void copy_fb_to_display(uint16_t *fb) {
|
||||
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
|
||||
// 2 bytes per pixel because we're using RGB 5-6-5 format
|
||||
ISSUE_PIXEL_DATA(fb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void switch_fb_manually(void) {
|
||||
// sync with the panel refresh
|
||||
while (GPIO_PIN_SET == HAL_GPIO_ReadPin(DISPLAY_TE_PORT, DISPLAY_TE_PIN)) {
|
||||
}
|
||||
while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(DISPLAY_TE_PORT, DISPLAY_TE_PIN)) {
|
||||
}
|
||||
|
||||
if (current_frame_buffer == 0) {
|
||||
current_frame_buffer = 1;
|
||||
copy_fb_to_display((uint16_t *)physical_frame_buffer_1);
|
||||
memcpy(physical_frame_buffer_0, physical_frame_buffer_1,
|
||||
sizeof(physical_frame_buffer_0));
|
||||
|
||||
} else {
|
||||
current_frame_buffer = 0;
|
||||
copy_fb_to_display((uint16_t *)physical_frame_buffer_0);
|
||||
memcpy(physical_frame_buffer_1, physical_frame_buffer_0,
|
||||
sizeof(physical_frame_buffer_1));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOARDLOADER
|
||||
static void switch_fb_in_backround(void) {
|
||||
if (current_frame_buffer == 0) {
|
||||
current_frame_buffer = 1;
|
||||
|
||||
memcpy(physical_frame_buffer_0, physical_frame_buffer_1,
|
||||
sizeof(physical_frame_buffer_0));
|
||||
|
||||
pending_fb_switch = true;
|
||||
__HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN);
|
||||
svc_enableIRQ(DISPLAY_TE_INTERRUPT_NUM);
|
||||
} else {
|
||||
current_frame_buffer = 0;
|
||||
memcpy(physical_frame_buffer_1, physical_frame_buffer_0,
|
||||
sizeof(physical_frame_buffer_1));
|
||||
|
||||
pending_fb_switch = true;
|
||||
__HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN);
|
||||
svc_enableIRQ(DISPLAY_TE_INTERRUPT_NUM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
void *addr;
|
||||
|
||||
if (current_frame_buffer == 0) {
|
||||
addr = (void *)physical_frame_buffer_1;
|
||||
} else {
|
||||
addr = (void *)physical_frame_buffer_0;
|
||||
}
|
||||
|
||||
display_fb_info_t fb = {
|
||||
.ptr = addr,
|
||||
.stride = DISPLAY_RESX * sizeof(uint16_t),
|
||||
};
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
void display_refresh(void) {
|
||||
#ifndef BOARDLOADER
|
||||
wait_for_fb_switch();
|
||||
display_panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
|
||||
if (is_mode_handler()) {
|
||||
switch_fb_manually();
|
||||
} else {
|
||||
switch_fb_in_backround();
|
||||
}
|
||||
#else
|
||||
display_panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
switch_fb_manually();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // XFRAMEBUFFER
|
46
core/embed/trezorhal/stm32f4/display/st-7789/display_fb.h
Normal file
46
core/embed/trezorhal/stm32f4/display/st-7789/display_fb.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZOR_HAL_DISPLAY_INTERNAL_H
|
||||
#define TREZOR_HAL_DISPLAY_INTERNAL_H
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
|
||||
// Size of the physical frame buffer in bytes
|
||||
#define PHYSICAL_FRAME_BUFFER_SIZE (DISPLAY_RESX * DISPLAY_RESY * 2)
|
||||
|
||||
// Physical frame buffers in internal SRAM memory
|
||||
//
|
||||
// Both frame buffers layes in the fixed addresses that
|
||||
// are shared between bootloaders and the firmware.
|
||||
extern uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE];
|
||||
extern uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE];
|
||||
|
||||
// The current frame buffer selector at fixed memory address
|
||||
//
|
||||
// The variable address is shared between bootloaders and the firmware
|
||||
extern uint32_t current_frame_buffer;
|
||||
|
||||
#endif // XFRAMEBUFFER
|
||||
|
||||
#endif // TREZOR_HAL_DISPLAY_INTERNAL_H
|
145
core/embed/trezorhal/stm32f4/display/st-7789/display_io.c
Normal file
145
core/embed/trezorhal/stm32f4/display/st-7789/display_io.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "display_io.h"
|
||||
#include "irq.h"
|
||||
|
||||
__IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS =
|
||||
(__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE);
|
||||
__IO DISP_MEM_TYPE *const DISPLAY_DATA_ADDRESS =
|
||||
(__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE |
|
||||
(DISPLAY_ADDR_SHIFT << DISPLAY_MEMORY_PIN));
|
||||
|
||||
void display_io_init_gpio(void) {
|
||||
// init peripherals
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_FMC_CLK_ENABLE();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
// LCD_RST/PC14
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStructure.Alternate = 0;
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_14;
|
||||
// default to keeping display in reset
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
#ifdef DISPLAY_TE_PIN
|
||||
// LCD_FMARK (tearing effect)
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Alternate = 0;
|
||||
GPIO_InitStructure.Pin = DISPLAY_TE_PIN;
|
||||
HAL_GPIO_Init(DISPLAY_TE_PORT, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF12_FMC;
|
||||
// LCD_CS/PD7 LCD_RS/PD11 LCD_RD/PD4 LCD_WR/PD5
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
// LCD_D0/PD14 LCD_D1/PD15 LCD_D2/PD0 LCD_D3/PD1
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
// LCD_D4/PE7 LCD_D5/PE8 LCD_D6/PE9 LCD_D7/PE10
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
#ifdef USE_DISP_I8080_16BIT_DW
|
||||
// LCD_D8/PE11 LCD_D9/PE12 LCD_D10/PE13 LCD_D11/PE14
|
||||
GPIO_InitStructure.Pin =
|
||||
GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
// LCD_D12/PE15
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_15;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
// LCD_D13/PD8 LCD_D14/PD9 LCD_D15/PD10
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_io_init_fmc(void) {
|
||||
// Reference UM1725 "Description of STM32F4 HAL and LL drivers",
|
||||
// section 64.2.1 "How to use this driver"
|
||||
SRAM_HandleTypeDef external_display_data_sram = {0};
|
||||
external_display_data_sram.Instance = FMC_NORSRAM_DEVICE;
|
||||
external_display_data_sram.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
|
||||
external_display_data_sram.Init.NSBank = FMC_NORSRAM_BANK1;
|
||||
external_display_data_sram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
|
||||
external_display_data_sram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
|
||||
#ifdef USE_DISP_I8080_16BIT_DW
|
||||
external_display_data_sram.Init.MemoryDataWidth =
|
||||
FMC_NORSRAM_MEM_BUS_WIDTH_16;
|
||||
#elif USE_DISP_I8080_8BIT_DW
|
||||
external_display_data_sram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
|
||||
#endif
|
||||
external_display_data_sram.Init.BurstAccessMode =
|
||||
FMC_BURST_ACCESS_MODE_DISABLE;
|
||||
external_display_data_sram.Init.WaitSignalPolarity =
|
||||
FMC_WAIT_SIGNAL_POLARITY_LOW;
|
||||
external_display_data_sram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
|
||||
external_display_data_sram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
|
||||
external_display_data_sram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
|
||||
external_display_data_sram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
|
||||
external_display_data_sram.Init.AsynchronousWait =
|
||||
FMC_ASYNCHRONOUS_WAIT_DISABLE;
|
||||
external_display_data_sram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
|
||||
external_display_data_sram.Init.ContinuousClock =
|
||||
FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
|
||||
external_display_data_sram.Init.PageSize = FMC_PAGE_SIZE_NONE;
|
||||
|
||||
// reference RM0090 section 37.5 Table 259, 37.5.4, Mode 1 SRAM, and 37.5.6
|
||||
FMC_NORSRAM_TimingTypeDef normal_mode_timing = {0};
|
||||
normal_mode_timing.AddressSetupTime = 5;
|
||||
normal_mode_timing.AddressHoldTime = 1; // don't care
|
||||
normal_mode_timing.DataSetupTime = 6;
|
||||
normal_mode_timing.BusTurnAroundDuration = 0; // don't care
|
||||
normal_mode_timing.CLKDivision = 2; // don't care
|
||||
normal_mode_timing.DataLatency = 2; // don't care
|
||||
normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A;
|
||||
|
||||
HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL);
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_TE_INTERRUPT_HANDLER
|
||||
void display_io_init_te_interrupt(void) {
|
||||
EXTI_HandleTypeDef EXTI_Handle = {0};
|
||||
EXTI_ConfigTypeDef EXTI_Config = {0};
|
||||
EXTI_Config.GPIOSel = DISPLAY_TE_INTERRUPT_GPIOSEL;
|
||||
EXTI_Config.Line = DISPLAY_TE_INTERRUPT_EXTI_LINE;
|
||||
EXTI_Config.Mode = EXTI_MODE_INTERRUPT;
|
||||
EXTI_Config.Trigger = EXTI_TRIGGER_RISING;
|
||||
HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config);
|
||||
|
||||
// setup interrupt for tearing effect pin
|
||||
HAL_NVIC_SetPriority(DISPLAY_TE_INTERRUPT_NUM, IRQ_PRI_DMA, 0);
|
||||
}
|
||||
#endif
|
67
core/embed/trezorhal/stm32f4/display/st-7789/display_io.h
Normal file
67
core/embed/trezorhal/stm32f4/display/st-7789/display_io.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_DISPLAY_IO_H
|
||||
#define TREZORHAL_DISPLAY_IO_H
|
||||
|
||||
#include STM32_HAL_H
|
||||
#include TREZOR_BOARD
|
||||
|
||||
void display_io_init_gpio(void);
|
||||
void display_io_init_fmc(void);
|
||||
void display_io_init_te_interrupt(void);
|
||||
|
||||
#ifndef FMC_BANK1
|
||||
#define FMC_BANK1 0x60000000U
|
||||
#endif
|
||||
|
||||
#define DISPLAY_MEMORY_BASE FMC_BANK1
|
||||
#define DISPLAY_MEMORY_PIN 16
|
||||
|
||||
#ifdef USE_DISP_I8080_16BIT_DW
|
||||
#define DISPLAY_ADDR_SHIFT 2
|
||||
#define DISP_MEM_TYPE uint16_t
|
||||
#elif USE_DISP_I8080_8BIT_DW
|
||||
#define DISPLAY_ADDR_SHIFT 1
|
||||
#define DISP_MEM_TYPE uint8_t
|
||||
#else
|
||||
#error "Unsupported display interface"
|
||||
#endif
|
||||
|
||||
/*#define DISPLAY_CMD_ADDRESS ((__IO DISP_MEM_TYPE *)(DISPLAY_MEMORY_BASE))
|
||||
#define DISPLAY_DATA_ADDRESS \
|
||||
((__IO DISP_MEM_TYPE *)(DISPLAY_MEMORY_BASE | \
|
||||
(DISPLAY_ADDR_SHIFT << DISPLAY_MEMORY_PIN)))
|
||||
*/
|
||||
|
||||
extern __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS;
|
||||
extern __IO DISP_MEM_TYPE *const DISPLAY_DATA_ADDRESS;
|
||||
|
||||
#define ISSUE_CMD_BYTE(X) (*(DISPLAY_CMD_ADDRESS) = (X))
|
||||
#define ISSUE_DATA_BYTE(X) (*(DISPLAY_DATA_ADDRESS) = (X))
|
||||
|
||||
#ifdef USE_DISP_I8080_16BIT_DW
|
||||
#define ISSUE_PIXEL_DATA(X) DATA(X)
|
||||
#elif USE_DISP_I8080_8BIT_DW
|
||||
#define ISSUE_PIXEL_DATA(X) \
|
||||
ISSUE_DATA_BYTE((X)&0xFF); \
|
||||
ISSUE_DATA_BYTE((X) >> 8)
|
||||
#endif
|
||||
|
||||
#endif // TREZORHAL_DISPLAY_IO_H
|
244
core/embed/trezorhal/stm32f4/display/st-7789/display_panel.c
Normal file
244
core/embed/trezorhal/stm32f4/display/st-7789/display_panel.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// using const volatile instead of #define results in binaries that change
|
||||
// only in 1-byte when the flag changes.
|
||||
// using #define leads compiler to over-optimize the code leading to bigger
|
||||
// differencies in the resulting binaries.
|
||||
|
||||
#include "display_panel.h"
|
||||
#include "display_io.h"
|
||||
|
||||
#ifdef TREZOR_MODEL_T
|
||||
#include "panels/154a.h"
|
||||
#include "panels/lx154a2411.h"
|
||||
#include "panels/lx154a2422.h"
|
||||
#include "panels/tf15411a.h"
|
||||
#else
|
||||
#include "panels/lx154a2422.h"
|
||||
#endif
|
||||
|
||||
// using const volatile instead of #define results in binaries that change
|
||||
// only in 1-byte when the flag changes.
|
||||
// using #define leads compiler to over-optimize the code leading to bigger
|
||||
// differencies in the resulting binaries.
|
||||
const volatile uint8_t DISPLAY_ST7789V_INVERT_COLORS2 = 1;
|
||||
|
||||
// Window padding (correction) when using 90dg or 270dg orientation
|
||||
// (internally the display is 240x320 but we use only 240x240)
|
||||
static display_padding_t g_window_padding;
|
||||
|
||||
#ifdef DISPLAY_IDENTIFY
|
||||
static uint32_t read_display_id(uint8_t command) {
|
||||
volatile uint8_t c = 0;
|
||||
uint32_t id = 0;
|
||||
ISSUE_CMD_BYTE(command);
|
||||
c = *DISPLAY_DATA_ADDRESS; // first returned value is a dummy value and
|
||||
// should be discarded
|
||||
c = *DISPLAY_DATA_ADDRESS;
|
||||
id |= (c << 16);
|
||||
c = *DISPLAY_DATA_ADDRESS;
|
||||
id |= (c << 8);
|
||||
c = *DISPLAY_DATA_ADDRESS;
|
||||
id |= c;
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t display_panel_identify(void) {
|
||||
static uint32_t id = 0x000000U;
|
||||
static bool id_initialized = false;
|
||||
|
||||
// Return immediately if id has been already initialized
|
||||
if (id_initialized) return id;
|
||||
|
||||
// RDDID: Read Display ID
|
||||
id = read_display_id(0x04);
|
||||
// the default RDDID for ILI9341 should be 0x8000.
|
||||
// some display modules return 0x0.
|
||||
// the ILI9341 has an extra id, let's check it here.
|
||||
if ((id != DISPLAY_ID_ST7789V) && (id != DISPLAY_ID_GC9307)) {
|
||||
// Read ID4
|
||||
uint32_t id4 = read_display_id(0xD3);
|
||||
if (id4 == DISPLAY_ID_ILI9341V) { // definitely found a ILI9341
|
||||
id = id4;
|
||||
}
|
||||
}
|
||||
id_initialized = true;
|
||||
return id;
|
||||
}
|
||||
#else
|
||||
uint32_t display_panel_identify(void) { return DISPLAY_ID_ST7789V; }
|
||||
#endif
|
||||
|
||||
bool display_panel_is_inverted() {
|
||||
bool inv_on = false;
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_ST7789V) {
|
||||
volatile uint8_t c = 0;
|
||||
ISSUE_CMD_BYTE(0x09); // read display status
|
||||
c = *DISPLAY_DATA_ADDRESS; // don't care
|
||||
c = *DISPLAY_DATA_ADDRESS; // don't care
|
||||
c = *DISPLAY_DATA_ADDRESS; // don't care
|
||||
c = *DISPLAY_DATA_ADDRESS;
|
||||
if (c & 0x20) {
|
||||
inv_on = true;
|
||||
}
|
||||
c = *DISPLAY_DATA_ADDRESS; // don't care
|
||||
}
|
||||
|
||||
return inv_on;
|
||||
}
|
||||
|
||||
void display_panel_sleep(void) {
|
||||
uint32_t id = display_panel_identify();
|
||||
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
|
||||
(id == DISPLAY_ID_ST7789V)) {
|
||||
ISSUE_CMD_BYTE(0x28); // DISPOFF: Display Off
|
||||
ISSUE_CMD_BYTE(0x10); // SLPIN: Sleep in
|
||||
HAL_Delay(5); // need to wait 5 milliseconds after "sleep in" before
|
||||
// sending any new commands
|
||||
}
|
||||
}
|
||||
|
||||
void display_panel_unsleep(void) {
|
||||
uint32_t id = display_panel_identify();
|
||||
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
|
||||
(id == DISPLAY_ID_ST7789V)) {
|
||||
ISSUE_CMD_BYTE(0x11); // SLPOUT: Sleep Out
|
||||
HAL_Delay(5); // need to wait 5 milliseconds after "sleep out" before
|
||||
// sending any new commands
|
||||
ISSUE_CMD_BYTE(0x29); // DISPON: Display On
|
||||
}
|
||||
}
|
||||
|
||||
void display_panel_set_window(uint16_t x0, uint16_t y0, uint16_t x1,
|
||||
uint16_t y1) {
|
||||
x0 += g_window_padding.x;
|
||||
x1 += g_window_padding.x;
|
||||
y0 += g_window_padding.y;
|
||||
y1 += g_window_padding.y;
|
||||
|
||||
uint32_t id = display_panel_identify();
|
||||
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
|
||||
(id == DISPLAY_ID_ST7789V)) {
|
||||
ISSUE_CMD_BYTE(0x2A);
|
||||
ISSUE_DATA_BYTE(x0 >> 8);
|
||||
ISSUE_DATA_BYTE(x0 & 0xFF);
|
||||
ISSUE_DATA_BYTE(x1 >> 8);
|
||||
ISSUE_DATA_BYTE(x1 & 0xFF); // column addr set
|
||||
ISSUE_CMD_BYTE(0x2B);
|
||||
ISSUE_DATA_BYTE(y0 >> 8);
|
||||
ISSUE_DATA_BYTE(y0 & 0xFF);
|
||||
ISSUE_DATA_BYTE(y1 >> 8);
|
||||
ISSUE_DATA_BYTE(y1 & 0xFF); // row addr set
|
||||
ISSUE_CMD_BYTE(0x2C);
|
||||
}
|
||||
}
|
||||
|
||||
void display_panel_set_little_endian(void) {
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_GC9307) {
|
||||
// CANNOT SET ENDIAN FOR GC9307
|
||||
} else if (id == DISPLAY_ID_ST7789V) {
|
||||
ISSUE_CMD_BYTE(0xB0);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0xF8);
|
||||
} else if (id == DISPLAY_ID_ILI9341V) {
|
||||
// Interface Control: XOR BGR as ST7789V does
|
||||
ISSUE_CMD_BYTE(0xF6);
|
||||
ISSUE_DATA_BYTE(0x09);
|
||||
ISSUE_DATA_BYTE(0x30);
|
||||
ISSUE_DATA_BYTE(0x20);
|
||||
}
|
||||
}
|
||||
|
||||
void display_panel_set_big_endian(void) {
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_GC9307) {
|
||||
// CANNOT SET ENDIAN FOR GC9307
|
||||
} else if (id == DISPLAY_ID_ST7789V) {
|
||||
ISSUE_CMD_BYTE(0xB0);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0xF0);
|
||||
} else if (id == DISPLAY_ID_ILI9341V) {
|
||||
// Interface Control: XOR BGR as ST7789V does
|
||||
ISSUE_CMD_BYTE(0xF6);
|
||||
ISSUE_DATA_BYTE(0x09);
|
||||
ISSUE_DATA_BYTE(0x30);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void display_panel_init(void) {
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // LCD_RST/PC14
|
||||
// wait 10 milliseconds. only needs to be low for 10 microseconds.
|
||||
// my dev display module ties display reset and touch panel reset together.
|
||||
// keeping this low for max(display_reset_time, ctpm_reset_time) aids
|
||||
// development and does not hurt.
|
||||
HAL_Delay(10);
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET); // LCD_RST/PC14
|
||||
// max wait time for hardware reset is 120 milliseconds
|
||||
// (experienced display flakiness using only 5ms wait before sending commands)
|
||||
HAL_Delay(120);
|
||||
|
||||
// identify the controller we will communicate with
|
||||
#ifdef TREZOR_MODEL_T
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_GC9307) {
|
||||
tf15411a_init_seq();
|
||||
} else if (id == DISPLAY_ID_ST7789V) {
|
||||
if (DISPLAY_ST7789V_INVERT_COLORS2) {
|
||||
lx154a2422_init_seq();
|
||||
} else {
|
||||
lx154a2411_init_seq();
|
||||
}
|
||||
} else if (id == DISPLAY_ID_ILI9341V) {
|
||||
_154a_init_seq();
|
||||
}
|
||||
#else
|
||||
lx154a2422_init_seq();
|
||||
#endif
|
||||
|
||||
display_panel_unsleep();
|
||||
}
|
||||
|
||||
void display_panel_init_gamma(void) {
|
||||
#ifdef TREZOR_MODEL_T
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_ST7789V && display_panel_is_inverted()) {
|
||||
// newest TT display - set proper gamma
|
||||
lx154a2422_gamma();
|
||||
} else if (id == DISPLAY_ID_ST7789V) {
|
||||
lx154a2411_gamma();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_panel_rotate(int angle) {
|
||||
#ifdef TREZOR_MODEL_T
|
||||
uint32_t id = display_panel_identify();
|
||||
if (id == DISPLAY_ID_GC9307) {
|
||||
tf15411a_rotate(angle, &g_window_padding);
|
||||
} else {
|
||||
lx154a2422_rotate(angle, &g_window_padding);
|
||||
}
|
||||
#else
|
||||
lx154a2422_rotate(angle, &g_window_padding);
|
||||
#endif
|
||||
}
|
57
core/embed/trezorhal/stm32f4/display/st-7789/display_panel.h
Normal file
57
core/embed/trezorhal/stm32f4/display/st-7789/display_panel.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_ST7789_PANEL_H
|
||||
#define TREZORHAL_ST7789_PANEL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// section "9.1.3 RDDID (04h): Read Display ID"
|
||||
// of ST7789V datasheet
|
||||
#define DISPLAY_ID_ST7789V 0x858552U
|
||||
// section "6.2.1. Read display identification information (04h)"
|
||||
// of GC9307 datasheet
|
||||
#define DISPLAY_ID_GC9307 0x009307U
|
||||
// section "8.3.23 Read ID4 (D3h)"
|
||||
// of ILI9341V datasheet
|
||||
#define DISPLAY_ID_ILI9341V 0x009341U
|
||||
|
||||
typedef struct {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} display_padding_t;
|
||||
|
||||
// Identifies the connected display panel and
|
||||
// returns one of DISPLAY_ID_xxx constant
|
||||
uint32_t display_panel_identify(void);
|
||||
bool display_panel_is_inverted();
|
||||
|
||||
void display_panel_init(void);
|
||||
void display_panel_init_gamma(void);
|
||||
void display_panel_set_little_endian(void);
|
||||
void display_panel_set_big_endian(void);
|
||||
|
||||
void display_panel_sleep(void);
|
||||
void display_panel_unsleep(void);
|
||||
void display_panel_set_window(uint16_t x0, uint16_t y0, uint16_t x1,
|
||||
uint16_t y1);
|
||||
void display_panel_rotate(int angle);
|
||||
|
||||
#endif // TREZORHAL_ST7789_PANEL_H
|
132
core/embed/trezorhal/stm32f4/display/st-7789/panels/154a.c
Normal file
132
core/embed/trezorhal/stm32f4/display/st-7789/panels/154a.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../display_io.h"
|
||||
|
||||
void _154a_init_seq(void) {
|
||||
// most recent manual: https://www.newhavendisplay.com/app_notes/ILI9341.pdf
|
||||
// TEON: Tearing Effect Line On; V-blanking only
|
||||
ISSUE_CMD_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits
|
||||
// input)
|
||||
ISSUE_CMD_BYTE(0x3A);
|
||||
ISSUE_DATA_BYTE(0x55);
|
||||
|
||||
// Display Function Control: gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xB6);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0xC2);
|
||||
ISSUE_DATA_BYTE(0x27);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// Interface Control: XOR BGR as ST7789V does
|
||||
ISSUE_CMD_BYTE(0xF6);
|
||||
ISSUE_DATA_BYTE(0x09);
|
||||
ISSUE_DATA_BYTE(0x30);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// the above config is the most important and definitely necessary
|
||||
|
||||
ISSUE_CMD_BYTE(0xCF);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0xC1);
|
||||
ISSUE_DATA_BYTE(0x30);
|
||||
|
||||
ISSUE_CMD_BYTE(0xED);
|
||||
ISSUE_DATA_BYTE(0x64);
|
||||
ISSUE_DATA_BYTE(0x03);
|
||||
ISSUE_DATA_BYTE(0x12);
|
||||
ISSUE_DATA_BYTE(0x81);
|
||||
|
||||
ISSUE_CMD_BYTE(0xE8);
|
||||
ISSUE_DATA_BYTE(0x85);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x7A);
|
||||
|
||||
ISSUE_CMD_BYTE(0xF7);
|
||||
ISSUE_DATA_BYTE(0x20);
|
||||
|
||||
ISSUE_CMD_BYTE(0xEA);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// power control VRH[5:0]
|
||||
ISSUE_CMD_BYTE(0xC0);
|
||||
ISSUE_DATA_BYTE(0x23);
|
||||
|
||||
// power control SAP[2:0] BT[3:0]
|
||||
ISSUE_CMD_BYTE(0xC1);
|
||||
ISSUE_DATA_BYTE(0x12);
|
||||
|
||||
// vcm control 1
|
||||
ISSUE_CMD_BYTE(0xC5);
|
||||
ISSUE_DATA_BYTE(0x60);
|
||||
ISSUE_DATA_BYTE(0x44);
|
||||
|
||||
// vcm control 2
|
||||
ISSUE_CMD_BYTE(0xC7);
|
||||
ISSUE_DATA_BYTE(0x8A);
|
||||
|
||||
// framerate
|
||||
ISSUE_CMD_BYTE(0xB1);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0x18);
|
||||
|
||||
// 3 gamma func disable
|
||||
ISSUE_CMD_BYTE(0xF2);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// gamma curve 1
|
||||
ISSUE_CMD_BYTE(0xE0);
|
||||
ISSUE_DATA_BYTE(0x0F);
|
||||
ISSUE_DATA_BYTE(0x2F);
|
||||
ISSUE_DATA_BYTE(0x2C);
|
||||
ISSUE_DATA_BYTE(0x0B);
|
||||
ISSUE_DATA_BYTE(0x0F);
|
||||
ISSUE_DATA_BYTE(0x09);
|
||||
ISSUE_DATA_BYTE(0x56);
|
||||
ISSUE_DATA_BYTE(0xD9);
|
||||
ISSUE_DATA_BYTE(0x4A);
|
||||
ISSUE_DATA_BYTE(0x0B);
|
||||
ISSUE_DATA_BYTE(0x14);
|
||||
ISSUE_DATA_BYTE(0x05);
|
||||
ISSUE_DATA_BYTE(0x0C);
|
||||
ISSUE_DATA_BYTE(0x06);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// gamma curve 2
|
||||
ISSUE_CMD_BYTE(0xE1);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x13);
|
||||
ISSUE_DATA_BYTE(0x04);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x06);
|
||||
ISSUE_DATA_BYTE(0x25);
|
||||
ISSUE_DATA_BYTE(0x26);
|
||||
ISSUE_DATA_BYTE(0x3B);
|
||||
ISSUE_DATA_BYTE(0x04);
|
||||
ISSUE_DATA_BYTE(0x0B);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x33);
|
||||
ISSUE_DATA_BYTE(0x39);
|
||||
ISSUE_DATA_BYTE(0x0F);
|
||||
}
|
27
core/embed/trezorhal/stm32f4/display/st-7789/panels/154a.h
Normal file
27
core/embed/trezorhal/stm32f4/display/st-7789/panels/154a.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _154A_H_
|
||||
#define _154A_H_
|
||||
|
||||
// ILI9341 IC controller
|
||||
|
||||
void _154a_init_seq(void);
|
||||
|
||||
#endif
|
@ -0,0 +1,82 @@
|
||||
|
||||
#include "../display_io.h"
|
||||
|
||||
void lx154a2411_gamma(void) {
|
||||
// positive voltage correction
|
||||
ISSUE_CMD_BYTE(0xE0);
|
||||
ISSUE_DATA_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0x03);
|
||||
ISSUE_DATA_BYTE(0x08);
|
||||
ISSUE_DATA_BYTE(0x0E);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
ISSUE_DATA_BYTE(0x2B);
|
||||
ISSUE_DATA_BYTE(0x3B);
|
||||
ISSUE_DATA_BYTE(0x44);
|
||||
ISSUE_DATA_BYTE(0x4C);
|
||||
ISSUE_DATA_BYTE(0x2B);
|
||||
ISSUE_DATA_BYTE(0x16);
|
||||
ISSUE_DATA_BYTE(0x15);
|
||||
ISSUE_DATA_BYTE(0x1E);
|
||||
ISSUE_DATA_BYTE(0x21);
|
||||
|
||||
// negative voltage correction
|
||||
ISSUE_CMD_BYTE(0xE1);
|
||||
ISSUE_DATA_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0x03);
|
||||
ISSUE_DATA_BYTE(0x08);
|
||||
ISSUE_DATA_BYTE(0x0E);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
ISSUE_DATA_BYTE(0x2B);
|
||||
ISSUE_DATA_BYTE(0x3B);
|
||||
ISSUE_DATA_BYTE(0x54);
|
||||
ISSUE_DATA_BYTE(0x4C);
|
||||
ISSUE_DATA_BYTE(0x2B);
|
||||
ISSUE_DATA_BYTE(0x16);
|
||||
ISSUE_DATA_BYTE(0x15);
|
||||
ISSUE_DATA_BYTE(0x1E);
|
||||
ISSUE_DATA_BYTE(0x21);
|
||||
}
|
||||
|
||||
void lx154a2411_init_seq(void) {
|
||||
// most recent manual:
|
||||
// https://www.newhavendisplay.com/appnotes/datasheets/LCDs/ST7789V.pdf
|
||||
// TEON: Tearing Effect Line On; V-blanking only
|
||||
ISSUE_CMD_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits
|
||||
// input)
|
||||
ISSUE_CMD_BYTE(0x3A);
|
||||
ISSUE_DATA_BYTE(0x55);
|
||||
|
||||
// CMD2EN: Commands in command table 2 can be executed when EXTC level is Low
|
||||
ISSUE_CMD_BYTE(0xDF);
|
||||
ISSUE_DATA_BYTE(0x5A);
|
||||
ISSUE_DATA_BYTE(0x69);
|
||||
ISSUE_DATA_BYTE(0x02);
|
||||
ISSUE_DATA_BYTE(0x01);
|
||||
|
||||
// LCMCTRL: LCM Control: XOR RGB setting
|
||||
ISSUE_CMD_BYTE(0xC0);
|
||||
ISSUE_DATA_BYTE(0x20);
|
||||
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is gate 80.;
|
||||
// gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
|
||||
// INVOFF (20h): Display Inversion Off
|
||||
// INVON (21h): Display Inversion On
|
||||
ISSUE_CMD_BYTE(0x20);
|
||||
|
||||
// the above config is the most important and definitely necessary
|
||||
|
||||
// PWCTRL1: Power Control 1
|
||||
ISSUE_CMD_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0xA4);
|
||||
ISSUE_DATA_BYTE(0xA1);
|
||||
|
||||
lx154a2411_gamma();
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LX154A2411_H_
|
||||
#define LX154A2411_H_
|
||||
|
||||
// ST7789_V IC controller
|
||||
void lx154a2411_gamma(void);
|
||||
void lx154a2411_init_seq(void);
|
||||
|
||||
#endif
|
159
core/embed/trezorhal/stm32f4/display/st-7789/panels/lx154a2422.c
Normal file
159
core/embed/trezorhal/stm32f4/display/st-7789/panels/lx154a2422.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "lx154a2422.h"
|
||||
|
||||
#include "../display_io.h"
|
||||
|
||||
void lx154a2422_gamma(void) {
|
||||
// positive voltage correction
|
||||
ISSUE_CMD_BYTE(0xE0);
|
||||
ISSUE_DATA_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x26);
|
||||
ISSUE_DATA_BYTE(0x36);
|
||||
ISSUE_DATA_BYTE(0x34);
|
||||
ISSUE_DATA_BYTE(0x4D);
|
||||
ISSUE_DATA_BYTE(0x18);
|
||||
ISSUE_DATA_BYTE(0x13);
|
||||
ISSUE_DATA_BYTE(0x14);
|
||||
ISSUE_DATA_BYTE(0x2F);
|
||||
ISSUE_DATA_BYTE(0x34);
|
||||
|
||||
// negative voltage correction
|
||||
ISSUE_CMD_BYTE(0xE1);
|
||||
ISSUE_DATA_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x09);
|
||||
ISSUE_DATA_BYTE(0x26);
|
||||
ISSUE_DATA_BYTE(0x36);
|
||||
ISSUE_DATA_BYTE(0x53);
|
||||
ISSUE_DATA_BYTE(0x4C);
|
||||
ISSUE_DATA_BYTE(0x18);
|
||||
ISSUE_DATA_BYTE(0x14);
|
||||
ISSUE_DATA_BYTE(0x14);
|
||||
ISSUE_DATA_BYTE(0x2F);
|
||||
ISSUE_DATA_BYTE(0x34);
|
||||
}
|
||||
|
||||
void lx154a2422_init_seq(void) {
|
||||
// most recent manual:
|
||||
// https://www.newhavendisplay.com/appnotes/datasheets/LCDs/ST7789V.pdf
|
||||
// TEON: Tearing Effect Line On; V-blanking only
|
||||
ISSUE_CMD_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits
|
||||
// input)
|
||||
ISSUE_CMD_BYTE(0x3A);
|
||||
ISSUE_DATA_BYTE(0x55);
|
||||
|
||||
// CMD2EN: Commands in command table 2 can be executed when EXTC level is Low
|
||||
ISSUE_CMD_BYTE(0xDF);
|
||||
ISSUE_DATA_BYTE(0x5A);
|
||||
ISSUE_DATA_BYTE(0x69);
|
||||
ISSUE_DATA_BYTE(0x02);
|
||||
ISSUE_DATA_BYTE(0x01);
|
||||
|
||||
// LCMCTRL: LCM Control: XOR RGB setting
|
||||
ISSUE_CMD_BYTE(0xC0);
|
||||
ISSUE_DATA_BYTE(0x20);
|
||||
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is gate 80.;
|
||||
// gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
|
||||
// INVOFF (20h): Display Inversion Off
|
||||
// INVON (21h): Display Inversion On
|
||||
ISSUE_CMD_BYTE(0x21);
|
||||
|
||||
// the above config is the most important and definitely necessary
|
||||
|
||||
// PWCTRL1: Power Control 1
|
||||
ISSUE_CMD_BYTE(0xD0);
|
||||
ISSUE_DATA_BYTE(0xA4);
|
||||
ISSUE_DATA_BYTE(0xA1);
|
||||
|
||||
lx154a2422_gamma();
|
||||
}
|
||||
|
||||
void lx154a2422_rotate(int degrees, display_padding_t* padding) {
|
||||
uint16_t shift = 0;
|
||||
char BX = 0, BY = 0;
|
||||
|
||||
#define RGB (1 << 3)
|
||||
#define ML (1 << 4) // vertical refresh order
|
||||
#define MH (1 << 2) // horizontal refresh order
|
||||
#define MV (1 << 5)
|
||||
#define MX (1 << 6)
|
||||
#define MY (1 << 7)
|
||||
// MADCTL: Memory Data Access Control - reference:
|
||||
// section 8.12 in the ST7789V manual
|
||||
uint8_t display_command_parameter = 0;
|
||||
switch (degrees) {
|
||||
case 0:
|
||||
display_command_parameter = 0;
|
||||
BY = 0;
|
||||
break;
|
||||
case 90:
|
||||
display_command_parameter = MV | MX | MH | ML;
|
||||
BX = 1;
|
||||
shift = 1;
|
||||
break;
|
||||
case 180:
|
||||
display_command_parameter = MX | MY | MH | ML;
|
||||
BY = 0;
|
||||
shift = 1;
|
||||
break;
|
||||
case 270:
|
||||
display_command_parameter = MV | MY;
|
||||
BX = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ISSUE_CMD_BYTE(0x36);
|
||||
ISSUE_DATA_BYTE(display_command_parameter);
|
||||
|
||||
if (shift) {
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is
|
||||
// gate 80.; gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
} else {
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is
|
||||
// gate 80.; gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
}
|
||||
|
||||
padding->x = BX ? (320 - DISPLAY_RESY) : 0;
|
||||
padding->y = BY ? (320 - DISPLAY_RESY) : 0;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LX154A2422_H_
|
||||
#define LX154A2422_H_
|
||||
|
||||
#include "../display_panel.h"
|
||||
|
||||
void lx154a2422_init_seq(void);
|
||||
void lx154a2422_gamma(void);
|
||||
void lx154a2422_rotate(int degrees, display_padding_t* padding);
|
||||
|
||||
#endif
|
174
core/embed/trezorhal/stm32f4/display/st-7789/panels/tf15411a.c
Normal file
174
core/embed/trezorhal/stm32f4/display/st-7789/panels/tf15411a.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tf15411a.h"
|
||||
#include "../display_io.h"
|
||||
|
||||
void tf15411a_init_seq(void) {
|
||||
// Inter Register Enable1
|
||||
ISSUE_CMD_BYTE(0xFE);
|
||||
|
||||
// Inter Register Enable2
|
||||
ISSUE_CMD_BYTE(0xEF);
|
||||
|
||||
// TEON: Tearing Effect Line On; V-blanking only
|
||||
ISSUE_CMD_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits
|
||||
// input)
|
||||
ISSUE_CMD_BYTE(0x3A);
|
||||
ISSUE_DATA_BYTE(0x55);
|
||||
|
||||
// Frame Rate
|
||||
// ISSUE_CMD_BYTE(0xE8); ISSUE_DATA_BYTE(0x12); ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
// Power Control 2
|
||||
ISSUE_CMD_BYTE(0xC3);
|
||||
ISSUE_DATA_BYTE(0x27);
|
||||
|
||||
// Power Control 3
|
||||
ISSUE_CMD_BYTE(0xC4);
|
||||
ISSUE_DATA_BYTE(0x18);
|
||||
|
||||
// Power Control 4
|
||||
ISSUE_CMD_BYTE(0xC9);
|
||||
ISSUE_DATA_BYTE(0x1F);
|
||||
|
||||
ISSUE_CMD_BYTE(0xC5);
|
||||
ISSUE_DATA_BYTE(0x0F);
|
||||
|
||||
ISSUE_CMD_BYTE(0xC6);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
|
||||
ISSUE_CMD_BYTE(0xC7);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
|
||||
ISSUE_CMD_BYTE(0xC8);
|
||||
ISSUE_DATA_BYTE(0x01);
|
||||
|
||||
ISSUE_CMD_BYTE(0xFF);
|
||||
ISSUE_DATA_BYTE(0x62);
|
||||
|
||||
ISSUE_CMD_BYTE(0x99);
|
||||
ISSUE_DATA_BYTE(0x3E);
|
||||
|
||||
ISSUE_CMD_BYTE(0x9D);
|
||||
ISSUE_DATA_BYTE(0x4B);
|
||||
|
||||
ISSUE_CMD_BYTE(0x8E);
|
||||
ISSUE_DATA_BYTE(0x0F);
|
||||
|
||||
// SET_GAMMA1
|
||||
ISSUE_CMD_BYTE(0xF0);
|
||||
ISSUE_DATA_BYTE(0x8F);
|
||||
ISSUE_DATA_BYTE(0x1B);
|
||||
ISSUE_DATA_BYTE(0x05);
|
||||
ISSUE_DATA_BYTE(0x06);
|
||||
ISSUE_DATA_BYTE(0x07);
|
||||
ISSUE_DATA_BYTE(0x42);
|
||||
|
||||
// SET_GAMMA3
|
||||
ISSUE_CMD_BYTE(0xF2);
|
||||
ISSUE_DATA_BYTE(0x5C);
|
||||
ISSUE_DATA_BYTE(0x1F);
|
||||
ISSUE_DATA_BYTE(0x12);
|
||||
ISSUE_DATA_BYTE(0x10);
|
||||
ISSUE_DATA_BYTE(0x07);
|
||||
ISSUE_DATA_BYTE(0x43);
|
||||
|
||||
// SET_GAMMA2
|
||||
ISSUE_CMD_BYTE(0xF1);
|
||||
ISSUE_DATA_BYTE(0x59);
|
||||
ISSUE_DATA_BYTE(0xCF);
|
||||
ISSUE_DATA_BYTE(0xCF);
|
||||
ISSUE_DATA_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x37);
|
||||
ISSUE_DATA_BYTE(0x8F);
|
||||
|
||||
// SET_GAMMA4
|
||||
ISSUE_CMD_BYTE(0xF3);
|
||||
ISSUE_DATA_BYTE(0x58);
|
||||
ISSUE_DATA_BYTE(0xCF);
|
||||
ISSUE_DATA_BYTE(0xCF);
|
||||
ISSUE_DATA_BYTE(0x35);
|
||||
ISSUE_DATA_BYTE(0x37);
|
||||
ISSUE_DATA_BYTE(0x8F);
|
||||
}
|
||||
|
||||
void tf15411a_rotate(int degrees, display_padding_t* padding) {
|
||||
uint16_t shift = 0;
|
||||
char BX = 0, BY = 0;
|
||||
|
||||
#define RGB (1 << 3)
|
||||
#define ML (1 << 4) // vertical refresh order
|
||||
#define MH (1 << 2) // horizontal refresh order
|
||||
#define MV (1 << 5)
|
||||
#define MX (1 << 6)
|
||||
#define MY (1 << 7)
|
||||
// MADCTL: Memory Data Access Control - reference:
|
||||
// section 9.3 in the ILI9341 manual
|
||||
// section 6.2.18 in the GC9307 manual
|
||||
// section 8.12 in the ST7789V manual
|
||||
uint8_t display_command_parameter = 0;
|
||||
switch (degrees) {
|
||||
case 0:
|
||||
display_command_parameter = 0;
|
||||
BY = 1;
|
||||
break;
|
||||
case 90:
|
||||
display_command_parameter = MV | MX | MH | ML;
|
||||
BX = 0;
|
||||
shift = 1;
|
||||
break;
|
||||
case 180:
|
||||
display_command_parameter = MX | MY | MH | ML;
|
||||
BY = 1;
|
||||
shift = 1;
|
||||
break;
|
||||
case 270:
|
||||
display_command_parameter = MV | MY;
|
||||
BX = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
display_command_parameter ^= RGB | MY; // XOR RGB and MY settings
|
||||
|
||||
ISSUE_CMD_BYTE(0x36);
|
||||
ISSUE_DATA_BYTE(display_command_parameter);
|
||||
|
||||
if (shift) {
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is
|
||||
// gate 80.; gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x00);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
} else {
|
||||
// GATECTRL: Gate Control; NL = 240 gate lines, first scan line is
|
||||
// gate 80.; gate scan direction 319 -> 0
|
||||
ISSUE_CMD_BYTE(0xE4);
|
||||
ISSUE_DATA_BYTE(0x1D);
|
||||
ISSUE_DATA_BYTE(0x0A);
|
||||
ISSUE_DATA_BYTE(0x11);
|
||||
}
|
||||
|
||||
padding->x = BX ? (320 - DISPLAY_RESY) : 0;
|
||||
padding->y = BY ? (320 - DISPLAY_RESY) : 0;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TF15411A_H_
|
||||
#define TF15411A_H_
|
||||
|
||||
#include "../display_panel.h"
|
||||
|
||||
// GC9307 IC controller
|
||||
|
||||
void tf15411a_init_seq(void);
|
||||
void tf15411a_rotate(int degrees, display_padding_t* padding);
|
||||
|
||||
#endif
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "display_internal.h"
|
||||
#include "ili9341_spi.h"
|
||||
#include "xdisplay.h"
|
||||
|
||||
#if (DISPLAY_RESX != 240) || (DISPLAY_RESY != 320)
|
||||
#error "Incompatible display resolution"
|
||||
#endif
|
||||
|
||||
// Display driver context.
|
||||
typedef struct {
|
||||
// Pointer to the frame buffer
|
||||
uint16_t *framebuf;
|
||||
// Current display orientation (0, 90, 180, 270)
|
||||
int orientation_angle;
|
||||
// Current backlight level ranging from 0 to 255
|
||||
int backlight_level;
|
||||
} display_driver_t;
|
||||
|
||||
// Display driver instance
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
void display_init(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR;
|
||||
|
||||
// Initialize LTDC controller
|
||||
BSP_LCD_Init();
|
||||
// Initialize external display controller
|
||||
ili9341_init();
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR;
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
// Not used and intentionally left empty
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
// Just emulation, not doing anything
|
||||
drv->backlight_level = level;
|
||||
return level;
|
||||
}
|
||||
|
||||
int display_get_backlight(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (angle == 0 || angle == 90 || angle == 180 || angle == 270) {
|
||||
// Just emulation, not doing anything
|
||||
drv->orientation_angle = angle;
|
||||
}
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
display_fb_info_t fb = {
|
||||
.ptr = (void *)drv->framebuf,
|
||||
.stride = DISPLAY_RESX * sizeof(uint16_t),
|
||||
};
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
void display_refresh(void) {
|
||||
// Do nothing as using just a single frame buffer
|
||||
}
|
||||
|
||||
void display_set_compatible_settings() {}
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t);
|
||||
|
||||
gl_rgb565_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_rgb565(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t);
|
||||
|
||||
gl_rgb565_copy_rgb565(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono4(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t);
|
||||
|
||||
gl_rgb565_copy_mono4(&bb_new);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_DISPLAY_INTERNAL_H
|
||||
#define TREZORHAL_DISPLAY_INTERNAL_H
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "sdram.h"
|
||||
|
||||
// Frame buffer address in external SDRAM
|
||||
#define FRAME_BUFFER_ADDR ((uint32_t)SDRAM_DEVICE_ADDR)
|
||||
// Frame buffer size (16-bit per pixel RGB565)
|
||||
#define FRAME_BUFFER_SIZE (DISPLAY_RESX * DISPLAY_RESY * 2)
|
||||
|
||||
// Initializes LTDC controller and I/O pins
|
||||
void BSP_LCD_Init(void);
|
||||
|
||||
#endif // TREZORHAL_DISPLAY_INTERNAL_H
|
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "display_internal.h"
|
||||
#include "ili9341_spi.h"
|
||||
#include "xdisplay.h"
|
||||
|
||||
#define MAX_LAYER_NUMBER 2
|
||||
|
||||
LTDC_HandleTypeDef LtdcHandler;
|
||||
static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
|
||||
/* Default LCD configuration with LCD Layer 1 */
|
||||
uint32_t ActiveLayer = 0;
|
||||
|
||||
/**
|
||||
* @brief Initializes the LCD layers.
|
||||
* @param LayerIndex: the layer foreground or background.
|
||||
* @param FB_Address: the layer frame buffer.
|
||||
*/
|
||||
void BSP_LCD_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) {
|
||||
LTDC_LayerCfgTypeDef Layercfg;
|
||||
|
||||
/* Layer Init */
|
||||
Layercfg.WindowX0 = 0;
|
||||
Layercfg.WindowX1 = DISPLAY_RESX;
|
||||
Layercfg.WindowY0 = 0;
|
||||
Layercfg.WindowY1 = DISPLAY_RESY;
|
||||
Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
|
||||
Layercfg.FBStartAdress = FB_Address;
|
||||
Layercfg.Alpha = 255;
|
||||
Layercfg.Alpha0 = 0;
|
||||
Layercfg.Backcolor.Blue = 0;
|
||||
Layercfg.Backcolor.Green = 0;
|
||||
Layercfg.Backcolor.Red = 0;
|
||||
Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
||||
Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
||||
Layercfg.ImageWidth = DISPLAY_RESX;
|
||||
Layercfg.ImageHeight = DISPLAY_RESY;
|
||||
|
||||
HAL_LTDC_ConfigLayer(&LtdcHandler, &Layercfg, LayerIndex);
|
||||
|
||||
// DrawProp[LayerIndex].BackColor = LCD_COLOR_WHITE;
|
||||
// DrawProp[LayerIndex].pFont = &Font24;
|
||||
// DrawProp[LayerIndex].TextColor = LCD_COLOR_BLACK;
|
||||
|
||||
/* Dithering activation */
|
||||
HAL_LTDC_EnableDither(&LtdcHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects the LCD Layer.
|
||||
* @param LayerIndex: the Layer foreground or background.
|
||||
*/
|
||||
void BSP_LCD_SelectLayer(uint32_t LayerIndex) { ActiveLayer = LayerIndex; }
|
||||
|
||||
/**
|
||||
* @brief Sets a LCD Layer visible.
|
||||
* @param LayerIndex: the visible Layer.
|
||||
* @param state: new state of the specified layer.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
*/
|
||||
void BSP_LCD_SetLayerVisible(uint32_t LayerIndex, FunctionalState state) {
|
||||
if (state == ENABLE) {
|
||||
__HAL_LTDC_LAYER_ENABLE(&LtdcHandler, LayerIndex);
|
||||
} else {
|
||||
__HAL_LTDC_LAYER_DISABLE(&LtdcHandler, LayerIndex);
|
||||
}
|
||||
__HAL_LTDC_RELOAD_CONFIG(&LtdcHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets an LCD Layer visible without reloading.
|
||||
* @param LayerIndex: Visible Layer
|
||||
* @param State: New state of the specified layer
|
||||
* This parameter can be one of the following values:
|
||||
* @arg ENABLE
|
||||
* @arg DISABLE
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_LCD_SetLayerVisible_NoReload(uint32_t LayerIndex,
|
||||
FunctionalState State) {
|
||||
if (State == ENABLE) {
|
||||
__HAL_LTDC_LAYER_ENABLE(&LtdcHandler, LayerIndex);
|
||||
} else {
|
||||
__HAL_LTDC_LAYER_DISABLE(&LtdcHandler, LayerIndex);
|
||||
}
|
||||
/* Do not Sets the Reload */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the Transparency.
|
||||
* @param LayerIndex: the Layer foreground or background.
|
||||
* @param Transparency: the Transparency,
|
||||
* This parameter must range from 0x00 to 0xFF.
|
||||
*/
|
||||
void BSP_LCD_SetTransparency(uint32_t LayerIndex, uint8_t Transparency) {
|
||||
HAL_LTDC_SetAlpha(&LtdcHandler, Transparency, LayerIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the transparency without reloading.
|
||||
* @param LayerIndex: Layer foreground or background.
|
||||
* @param Transparency: Transparency
|
||||
* This parameter must be a number between Min_Data = 0x00 and
|
||||
* Max_Data = 0xFF
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_LCD_SetTransparency_NoReload(uint32_t LayerIndex,
|
||||
uint8_t Transparency) {
|
||||
HAL_LTDC_SetAlpha_NoReload(&LtdcHandler, Transparency, LayerIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a LCD layer frame buffer address.
|
||||
* @param LayerIndex: specifies the Layer foreground or background
|
||||
* @param Address: new LCD frame buffer value
|
||||
*/
|
||||
void BSP_LCD_SetLayerAddress(uint32_t LayerIndex, uint32_t Address) {
|
||||
HAL_LTDC_SetAddress(&LtdcHandler, Address, LayerIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets an LCD layer frame buffer address without reloading.
|
||||
* @param LayerIndex: Layer foreground or background
|
||||
* @param Address: New LCD frame buffer value
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_LCD_SetLayerAddress_NoReload(uint32_t LayerIndex, uint32_t Address) {
|
||||
HAL_LTDC_SetAddress_NoReload(&LtdcHandler, Address, LayerIndex);
|
||||
}
|
||||
|
||||
void BSP_LCD_Init(void) {
|
||||
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||
|
||||
/* Enable the LTDC and DMA2D Clock */
|
||||
__HAL_RCC_LTDC_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2D_CLK_ENABLE();
|
||||
|
||||
/* Enable GPIOs clock */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
|
||||
/* GPIOs Configuration */
|
||||
/*
|
||||
+------------------------+-----------------------+----------------------------+
|
||||
+ LCD pins assignment +
|
||||
+------------------------+-----------------------+----------------------------+
|
||||
| LCD_TFT R2 <-> PC.10 | LCD_TFT G2 <-> PA.06 | LCD_TFT B2 <-> PD.06 | |
|
||||
LCD_TFT R3 <-> PB.00 | LCD_TFT G3 <-> PG.10 | LCD_TFT B3 <-> PG.11 |
|
||||
| LCD_TFT R4 <-> PA.11 | LCD_TFT G4 <-> PB.10 | LCD_TFT B4 <-> PG.12 | |
|
||||
LCD_TFT R5 <-> PA.12 | LCD_TFT G5 <-> PB.11 | LCD_TFT B5 <-> PA.03 |
|
||||
| LCD_TFT R6 <-> PB.01 | LCD_TFT G6 <-> PC.07 | LCD_TFT B6 <-> PB.08 | |
|
||||
LCD_TFT R7 <-> PG.06 | LCD_TFT G7 <-> PD.03 | LCD_TFT B7 <-> PB.09 |
|
||||
-------------------------------------------------------------------------------
|
||||
| LCD_TFT HSYNC <-> PC.06 | LCDTFT VSYNC <-> PA.04 |
|
||||
| LCD_TFT CLK <-> PG.07 | LCD_TFT DE <-> PF.10 |
|
||||
-----------------------------------------------------
|
||||
*/
|
||||
|
||||
/* GPIOA configuration */
|
||||
GPIO_InitStructure.Pin =
|
||||
GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_11 | GPIO_PIN_12;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF14_LTDC;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOB configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOC configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOD configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_3 | GPIO_PIN_6;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOF configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_10;
|
||||
HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOG configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_11;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOB configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF9_LTDC;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOG configuration */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_12;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
/* On STM32F429I-DISCO, it is not possible to read ILI9341 ID because */
|
||||
/* PIN EXTC is not connected to VDD and then LCD_READ_ID4 is not accessible.
|
||||
*/
|
||||
/* In this case, ReadID function is bypassed.*/
|
||||
/*if(ili9341_drv.ReadID() == ILI9341_ID)*/
|
||||
|
||||
/* LTDC Configuration ----------------------------------------------------*/
|
||||
LtdcHandler.Instance = LTDC;
|
||||
|
||||
/* Timing configuration (Typical configuration from ILI9341 datasheet)
|
||||
HSYNC=10 (9+1)
|
||||
HBP=20 (29-10+1)
|
||||
ActiveW=240 (269-20-10+1)
|
||||
HFP=10 (279-240-20-10+1)
|
||||
|
||||
VSYNC=2 (1+1)
|
||||
VBP=2 (3-2+1)
|
||||
ActiveH=320 (323-2-2+1)
|
||||
VFP=4 (327-320-2-2+1)
|
||||
*/
|
||||
|
||||
/* Configure horizontal synchronization width */
|
||||
LtdcHandler.Init.HorizontalSync = ILI9341_HSYNC;
|
||||
/* Configure vertical synchronization height */
|
||||
LtdcHandler.Init.VerticalSync = ILI9341_VSYNC;
|
||||
/* Configure accumulated horizontal back porch */
|
||||
LtdcHandler.Init.AccumulatedHBP = ILI9341_HBP;
|
||||
/* Configure accumulated vertical back porch */
|
||||
LtdcHandler.Init.AccumulatedVBP = ILI9341_VBP;
|
||||
/* Configure accumulated active width */
|
||||
LtdcHandler.Init.AccumulatedActiveW = 269;
|
||||
/* Configure accumulated active height */
|
||||
LtdcHandler.Init.AccumulatedActiveH = 323;
|
||||
/* Configure total width */
|
||||
LtdcHandler.Init.TotalWidth = 279;
|
||||
/* Configure total height */
|
||||
LtdcHandler.Init.TotalHeigh = 327;
|
||||
|
||||
/* Configure R,G,B component values for LCD background color */
|
||||
LtdcHandler.Init.Backcolor.Red = 0;
|
||||
LtdcHandler.Init.Backcolor.Blue = 0;
|
||||
LtdcHandler.Init.Backcolor.Green = 0;
|
||||
|
||||
/* LCD clock configuration */
|
||||
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
|
||||
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
|
||||
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */
|
||||
/* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
|
||||
PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
|
||||
PeriphClkInitStruct.PLLSAI.PLLSAIR = 4;
|
||||
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
|
||||
/* Polarity */
|
||||
LtdcHandler.Init.HSPolarity = LTDC_HSPOLARITY_AL;
|
||||
LtdcHandler.Init.VSPolarity = LTDC_VSPOLARITY_AL;
|
||||
LtdcHandler.Init.DEPolarity = LTDC_DEPOLARITY_AL;
|
||||
LtdcHandler.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
|
||||
|
||||
HAL_LTDC_Init(&LtdcHandler);
|
||||
|
||||
/* Initialize the LCD Layers */
|
||||
BSP_LCD_LayerDefaultInit(1, FRAME_BUFFER_ADDR);
|
||||
|
||||
memset((void *)FRAME_BUFFER_ADDR, 0, FRAME_BUFFER_SIZE);
|
||||
}
|
@ -0,0 +1,512 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include TREZOR_BOARD
|
||||
#include "ili9341_spi.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
/**
|
||||
* @brief ILI9341 chip IDs
|
||||
*/
|
||||
#define ILI9341_ID 0x9341
|
||||
|
||||
/**
|
||||
* @brief ILI9341 Size
|
||||
*/
|
||||
#define ILI9341_LCD_PIXEL_WIDTH ((uint16_t)240)
|
||||
#define ILI9341_LCD_PIXEL_HEIGHT ((uint16_t)320)
|
||||
|
||||
/**
|
||||
* @brief ILI9341 Timing
|
||||
*/
|
||||
/* Timing configuration (Typical configuration from ILI9341 datasheet)
|
||||
HSYNC=10 (9+1)
|
||||
HBP=20 (29-10+1)
|
||||
ActiveW=240 (269-20-10+1)
|
||||
HFP=10 (279-240-20-10+1)
|
||||
|
||||
VSYNC=2 (1+1)
|
||||
VBP=2 (3-2+1)
|
||||
ActiveH=320 (323-2-2+1)
|
||||
VFP=4 (327-320-2-2+1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ILI9341 Registers
|
||||
*/
|
||||
|
||||
/* Level 1 Commands */
|
||||
#define LCD_SWRESET 0x01 /* Software Reset */
|
||||
#define LCD_READ_DISPLAY_ID 0x04 /* Read display identification information */
|
||||
#define LCD_RDDST 0x09 /* Read Display Status */
|
||||
#define LCD_RDDPM 0x0A /* Read Display Power Mode */
|
||||
#define LCD_RDDMADCTL 0x0B /* Read Display MADCTL */
|
||||
#define LCD_RDDCOLMOD 0x0C /* Read Display Pixel Format */
|
||||
#define LCD_RDDIM 0x0D /* Read Display Image Format */
|
||||
#define LCD_RDDSM 0x0E /* Read Display Signal Mode */
|
||||
#define LCD_RDDSDR 0x0F /* Read Display Self-Diagnostic Result */
|
||||
#define LCD_SPLIN 0x10 /* Enter Sleep Mode */
|
||||
#define LCD_SLEEP_OUT 0x11 /* Sleep out register */
|
||||
#define LCD_PTLON 0x12 /* Partial Mode ON */
|
||||
#define LCD_NORMAL_MODE_ON 0x13 /* Normal Display Mode ON */
|
||||
#define LCD_DINVOFF 0x20 /* Display Inversion OFF */
|
||||
#define LCD_DINVON 0x21 /* Display Inversion ON */
|
||||
#define LCD_GAMMA 0x26 /* Gamma register */
|
||||
#define LCD_DISPLAY_OFF 0x28 /* Display off register */
|
||||
#define LCD_DISPLAY_ON 0x29 /* Display on register */
|
||||
#define LCD_COLUMN_ADDR 0x2A /* Colomn address register */
|
||||
#define LCD_PAGE_ADDR 0x2B /* Page address register */
|
||||
#define LCD_GRAM 0x2C /* GRAM register */
|
||||
#define LCD_RGBSET 0x2D /* Color SET */
|
||||
#define LCD_RAMRD 0x2E /* Memory Read */
|
||||
#define LCD_PLTAR 0x30 /* Partial Area */
|
||||
#define LCD_VSCRDEF 0x33 /* Vertical Scrolling Definition */
|
||||
#define LCD_TEOFF 0x34 /* Tearing Effect Line OFF */
|
||||
#define LCD_TEON 0x35 /* Tearing Effect Line ON */
|
||||
#define LCD_MAC 0x36 /* Memory Access Control register*/
|
||||
#define LCD_VSCRSADD 0x37 /* Vertical Scrolling Start Address */
|
||||
#define LCD_IDMOFF 0x38 /* Idle Mode OFF */
|
||||
#define LCD_IDMON 0x39 /* Idle Mode ON */
|
||||
#define LCD_PIXEL_FORMAT 0x3A /* Pixel Format register */
|
||||
#define LCD_WRITE_MEM_CONTINUE 0x3C /* Write Memory Continue */
|
||||
#define LCD_READ_MEM_CONTINUE 0x3E /* Read Memory Continue */
|
||||
#define LCD_SET_TEAR_SCANLINE 0x44 /* Set Tear Scanline */
|
||||
#define LCD_GET_SCANLINE 0x45 /* Get Scanline */
|
||||
#define LCD_WDB 0x51 /* Write Brightness Display register */
|
||||
#define LCD_RDDISBV 0x52 /* Read Display Brightness */
|
||||
#define LCD_WCD 0x53 /* Write Control Display register*/
|
||||
#define LCD_RDCTRLD 0x54 /* Read CTRL Display */
|
||||
#define LCD_WRCABC 0x55 /* Write Content Adaptive Brightness Control */
|
||||
#define LCD_RDCABC 0x56 /* Read Content Adaptive Brightness Control */
|
||||
#define LCD_WRITE_CABC 0x5E /* Write CABC Minimum Brightness */
|
||||
#define LCD_READ_CABC 0x5F /* Read CABC Minimum Brightness */
|
||||
#define LCD_READ_ID1 0xDA /* Read ID1 */
|
||||
#define LCD_READ_ID2 0xDB /* Read ID2 */
|
||||
#define LCD_READ_ID3 0xDC /* Read ID3 */
|
||||
|
||||
/* Level 2 Commands */
|
||||
#define LCD_RGB_INTERFACE 0xB0 /* RGB Interface Signal Control */
|
||||
#define LCD_FRMCTR1 0xB1 /* Frame Rate Control (In Normal Mode) */
|
||||
#define LCD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle Mode) */
|
||||
#define LCD_FRMCTR3 0xB3 /* Frame Rate Control (In Partial Mode) */
|
||||
#define LCD_INVTR 0xB4 /* Display Inversion Control */
|
||||
#define LCD_BPC 0xB5 /* Blanking Porch Control register */
|
||||
#define LCD_DFC 0xB6 /* Display Function Control register */
|
||||
#define LCD_ETMOD 0xB7 /* Entry Mode Set */
|
||||
#define LCD_BACKLIGHT1 0xB8 /* Backlight Control 1 */
|
||||
#define LCD_BACKLIGHT2 0xB9 /* Backlight Control 2 */
|
||||
#define LCD_BACKLIGHT3 0xBA /* Backlight Control 3 */
|
||||
#define LCD_BACKLIGHT4 0xBB /* Backlight Control 4 */
|
||||
#define LCD_BACKLIGHT5 0xBC /* Backlight Control 5 */
|
||||
#define LCD_BACKLIGHT7 0xBE /* Backlight Control 7 */
|
||||
#define LCD_BACKLIGHT8 0xBF /* Backlight Control 8 */
|
||||
#define LCD_POWER1 0xC0 /* Power Control 1 register */
|
||||
#define LCD_POWER2 0xC1 /* Power Control 2 register */
|
||||
#define LCD_VCOM1 0xC5 /* VCOM Control 1 register */
|
||||
#define LCD_VCOM2 0xC7 /* VCOM Control 2 register */
|
||||
#define LCD_NVMWR 0xD0 /* NV Memory Write */
|
||||
#define LCD_NVMPKEY 0xD1 /* NV Memory Protection Key */
|
||||
#define LCD_RDNVM 0xD2 /* NV Memory Status Read */
|
||||
#define LCD_READ_ID4 0xD3 /* Read ID4 */
|
||||
#define LCD_PGAMMA 0xE0 /* Positive Gamma Correction register */
|
||||
#define LCD_NGAMMA 0xE1 /* Negative Gamma Correction register */
|
||||
#define LCD_DGAMCTRL1 0xE2 /* Digital Gamma Control 1 */
|
||||
#define LCD_DGAMCTRL2 0xE3 /* Digital Gamma Control 2 */
|
||||
#define LCD_INTERFACE 0xF6 /* Interface control register */
|
||||
|
||||
/* Extend register commands */
|
||||
#define LCD_POWERA 0xCB /* Power control A register */
|
||||
#define LCD_POWERB 0xCF /* Power control B register */
|
||||
#define LCD_DTCA 0xE8 /* Driver timing control A */
|
||||
#define LCD_DTCB 0xEA /* Driver timing control B */
|
||||
#define LCD_POWER_SEQ 0xED /* Power on sequence register */
|
||||
#define LCD_3GAMMA_EN 0xF2 /* 3 Gamma enable register */
|
||||
#define LCD_PRC 0xF7 /* Pump ratio control register */
|
||||
|
||||
/* Size of read registers */
|
||||
#define LCD_READ_ID4_SIZE 3 /* Size of Read ID4 */
|
||||
|
||||
/*############################### SPIx #######################################*/
|
||||
#define DISCOVERY_SPIx SPI5
|
||||
#define DISCOVERY_SPIx_CLK_ENABLE() __HAL_RCC_SPI5_CLK_ENABLE()
|
||||
#define DISCOVERY_SPIx_GPIO_PORT GPIOF /* GPIOF */
|
||||
#define DISCOVERY_SPIx_AF GPIO_AF5_SPI5
|
||||
#define DISCOVERY_SPIx_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
#define DISCOVERY_SPIx_GPIO_CLK_DISABLE() __HAL_RCC_GPIOF_CLK_DISABLE()
|
||||
#define DISCOVERY_SPIx_SCK_PIN GPIO_PIN_7 /* PF.07 */
|
||||
#define DISCOVERY_SPIx_MISO_PIN GPIO_PIN_8 /* PF.08 */
|
||||
#define DISCOVERY_SPIx_MOSI_PIN GPIO_PIN_9 /* PF.09 */
|
||||
/* Maximum Timeout values for flags waiting loops. These timeouts are not based
|
||||
on accurate values, they just guarantee that the application will not remain
|
||||
stuck if the SPI communication is corrupted.
|
||||
You may modify these timeout values depending on CPU frequency and
|
||||
application conditions (interrupts routines ...). */
|
||||
#define SPIx_TIMEOUT_MAX ((uint32_t)0x1000)
|
||||
|
||||
/*################################ LCD #######################################*/
|
||||
/* Chip Select macro definition */
|
||||
#define LCD_CS_LOW() \
|
||||
HAL_GPIO_WritePin(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, GPIO_PIN_RESET)
|
||||
#define LCD_CS_HIGH() \
|
||||
HAL_GPIO_WritePin(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, GPIO_PIN_SET)
|
||||
|
||||
/* Set WRX High to send data */
|
||||
#define LCD_WRX_LOW() \
|
||||
HAL_GPIO_WritePin(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, GPIO_PIN_RESET)
|
||||
#define LCD_WRX_HIGH() \
|
||||
HAL_GPIO_WritePin(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, GPIO_PIN_SET)
|
||||
|
||||
/* Set WRX High to send data */
|
||||
#define LCD_RDX_LOW() \
|
||||
HAL_GPIO_WritePin(LCD_RDX_GPIO_PORT, LCD_RDX_PIN, GPIO_PIN_RESET)
|
||||
#define LCD_RDX_HIGH() \
|
||||
HAL_GPIO_WritePin(LCD_RDX_GPIO_PORT, LCD_RDX_PIN, GPIO_PIN_SET)
|
||||
|
||||
/**
|
||||
* @brief LCD Control pin
|
||||
*/
|
||||
#define LCD_NCS_PIN GPIO_PIN_2
|
||||
#define LCD_NCS_GPIO_PORT GPIOC
|
||||
#define LCD_NCS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
|
||||
#define LCD_NCS_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE()
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @brief LCD Command/data pin
|
||||
*/
|
||||
#define LCD_WRX_PIN GPIO_PIN_13
|
||||
#define LCD_WRX_GPIO_PORT GPIOD
|
||||
#define LCD_WRX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
|
||||
#define LCD_WRX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOD_CLK_DISABLE()
|
||||
|
||||
#define LCD_RDX_PIN GPIO_PIN_12
|
||||
#define LCD_RDX_GPIO_PORT GPIOD
|
||||
#define LCD_RDX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
|
||||
#define LCD_RDX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOD_CLK_DISABLE()
|
||||
|
||||
static SPI_HandleTypeDef SpiHandle;
|
||||
uint32_t SpixTimeout =
|
||||
SPIx_TIMEOUT_MAX; /*<! Value of Timeout when SPI communication fails */
|
||||
|
||||
/* SPIx bus function */
|
||||
static void SPIx_Init(void);
|
||||
static void ili9341_Write(uint16_t Value);
|
||||
static uint32_t ili9341_Read(uint8_t ReadSize);
|
||||
static void ili9341_Error(void);
|
||||
|
||||
/**
|
||||
* @brief SPIx Bus initialization
|
||||
*/
|
||||
static void SPIx_Init(void) {
|
||||
if (HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_RESET) {
|
||||
/* SPI configuration -----------------------------------------------------*/
|
||||
SpiHandle.Instance = DISCOVERY_SPIx;
|
||||
/* SPI baudrate is set to 5.6 MHz (PCLK2/SPI_BaudRatePrescaler = 90/16
|
||||
= 5.625 MHz) to verify these constraints:
|
||||
- ILI9341 LCD SPI interface max baudrate is 10MHz for write and 6.66MHz
|
||||
for read
|
||||
- l3gd20 SPI interface max baudrate is 10MHz for write/read
|
||||
- PCLK2 frequency is set to 90 MHz
|
||||
*/
|
||||
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
|
||||
|
||||
/* On STM32F429I-Discovery, LCD ID cannot be read then keep a common
|
||||
* configuration */
|
||||
/* for LCD and GYRO (SPI_DIRECTION_2LINES) */
|
||||
/* Note: To read a register a LCD, SPI_DIRECTION_1LINE should be set */
|
||||
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
|
||||
SpiHandle.Init.CRCPolynomial = 7;
|
||||
SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
SpiHandle.Init.NSS = SPI_NSS_SOFT;
|
||||
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
|
||||
SpiHandle.Init.Mode = SPI_MODE_MASTER;
|
||||
|
||||
HAL_SPI_Init(&SpiHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPIx error treatment function.
|
||||
*/
|
||||
static void ili9341_Error(void) {
|
||||
/* De-initialize the SPI communication BUS */
|
||||
HAL_SPI_DeInit(&SpiHandle);
|
||||
|
||||
/* Re- Initialize the SPI communication BUS */
|
||||
SPIx_Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads 4 bytes from device.
|
||||
* @param ReadSize: Number of bytes to read (max 4 bytes)
|
||||
* @retval Value read on the SPI
|
||||
*/
|
||||
static uint32_t ili9341_Read(uint8_t ReadSize) {
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t readvalue;
|
||||
|
||||
status =
|
||||
HAL_SPI_Receive(&SpiHandle, (uint8_t*)&readvalue, ReadSize, SpixTimeout);
|
||||
|
||||
/* Check the communication status */
|
||||
if (status != HAL_OK) {
|
||||
/* Re-Initialize the BUS */
|
||||
ili9341_Error();
|
||||
}
|
||||
|
||||
return readvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a byte to device.
|
||||
* @param Value: value to be written
|
||||
*/
|
||||
static void ili9341_Write(uint16_t Value) {
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
status = HAL_SPI_Transmit(&SpiHandle, (uint8_t*)&Value, 1, SpixTimeout);
|
||||
|
||||
/* Check the communication status */
|
||||
if (status != HAL_OK) {
|
||||
/* Re-Initialize the BUS */
|
||||
ili9341_Error();
|
||||
}
|
||||
}
|
||||
|
||||
void ili9341_spi_init(void) {
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Configure NCS in Output Push-Pull mode */
|
||||
LCD_WRX_GPIO_CLK_ENABLE();
|
||||
GPIO_InitStructure.Pin = LCD_WRX_PIN;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
|
||||
HAL_GPIO_Init(LCD_WRX_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
LCD_RDX_GPIO_CLK_ENABLE();
|
||||
GPIO_InitStructure.Pin = LCD_RDX_PIN;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
|
||||
HAL_GPIO_Init(LCD_RDX_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure the LCD Control pins ----------------------------------------*/
|
||||
LCD_NCS_GPIO_CLK_ENABLE();
|
||||
|
||||
/* Configure NCS in Output Push-Pull mode */
|
||||
GPIO_InitStructure.Pin = LCD_NCS_PIN;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
|
||||
HAL_GPIO_Init(LCD_NCS_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Set or Reset the control line */
|
||||
LCD_CS_LOW();
|
||||
LCD_CS_HIGH();
|
||||
|
||||
/* Enable SPIx clock */
|
||||
DISCOVERY_SPIx_CLK_ENABLE();
|
||||
|
||||
/* Enable DISCOVERY_SPI GPIO clock */
|
||||
DISCOVERY_SPIx_GPIO_CLK_ENABLE();
|
||||
|
||||
/* configure SPI SCK, MOSI and MISO */
|
||||
GPIO_InitStructure.Pin = (DISCOVERY_SPIx_SCK_PIN | DISCOVERY_SPIx_MOSI_PIN |
|
||||
DISCOVERY_SPIx_MISO_PIN);
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
|
||||
GPIO_InitStructure.Alternate = DISCOVERY_SPIx_AF;
|
||||
HAL_GPIO_Init(DISCOVERY_SPIx_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
SPIx_Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes register value.
|
||||
*/
|
||||
void ili9341_WriteData(uint16_t RegValue) {
|
||||
/* Set WRX to send data */
|
||||
LCD_WRX_HIGH();
|
||||
|
||||
/* Reset LCD control line(/CS) and Send data */
|
||||
LCD_CS_LOW();
|
||||
ili9341_Write(RegValue);
|
||||
|
||||
/* Deselect: Chip Select high */
|
||||
LCD_CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes register address.
|
||||
*/
|
||||
void ili9341_WriteReg(uint8_t Reg) {
|
||||
/* Reset WRX to send command */
|
||||
LCD_WRX_LOW();
|
||||
|
||||
/* Reset LCD control line(/CS) and Send command */
|
||||
LCD_CS_LOW();
|
||||
ili9341_Write(Reg);
|
||||
|
||||
/* Deselect: Chip Select high */
|
||||
LCD_CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads register value.
|
||||
* @param RegValue Address of the register to read
|
||||
* @param ReadSize Number of bytes to read
|
||||
* @retval Content of the register value
|
||||
*/
|
||||
uint32_t ili9341_ReadData(uint16_t RegValue, uint8_t ReadSize) {
|
||||
uint32_t readvalue = 0;
|
||||
|
||||
/* Select: Chip Select low */
|
||||
LCD_CS_LOW();
|
||||
|
||||
/* Reset WRX to send command */
|
||||
LCD_WRX_LOW();
|
||||
|
||||
ili9341_Write(RegValue);
|
||||
|
||||
readvalue = ili9341_Read(ReadSize);
|
||||
|
||||
/* Set WRX to send data */
|
||||
LCD_WRX_HIGH();
|
||||
|
||||
/* Deselect: Chip Select high */
|
||||
LCD_CS_HIGH();
|
||||
|
||||
return readvalue;
|
||||
}
|
||||
|
||||
void ili9341_init(void) {
|
||||
/* Initialize ILI9341 low level bus layer ----------------------------------*/
|
||||
ili9341_spi_init();
|
||||
|
||||
ili9341_WriteReg(LCD_DISPLAY_OFF);
|
||||
|
||||
/* Configure LCD */
|
||||
ili9341_WriteReg(0xCA);
|
||||
ili9341_WriteData(0xC3);
|
||||
ili9341_WriteData(0x08);
|
||||
ili9341_WriteData(0x50);
|
||||
ili9341_WriteReg(LCD_POWERB);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0xC1);
|
||||
ili9341_WriteData(0x30);
|
||||
ili9341_WriteReg(LCD_POWER_SEQ);
|
||||
ili9341_WriteData(0x64);
|
||||
ili9341_WriteData(0x03);
|
||||
ili9341_WriteData(0x12);
|
||||
ili9341_WriteData(0x81);
|
||||
ili9341_WriteReg(LCD_DTCA);
|
||||
ili9341_WriteData(0x85);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x78);
|
||||
ili9341_WriteReg(LCD_POWERA);
|
||||
ili9341_WriteData(0x39);
|
||||
ili9341_WriteData(0x2C);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x34);
|
||||
ili9341_WriteData(0x02);
|
||||
ili9341_WriteReg(LCD_PRC);
|
||||
ili9341_WriteData(0x20);
|
||||
ili9341_WriteReg(LCD_DTCB);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteReg(LCD_FRMCTR1);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x1B);
|
||||
ili9341_WriteReg(LCD_DFC);
|
||||
ili9341_WriteData(0x0A);
|
||||
ili9341_WriteData(0xA2);
|
||||
ili9341_WriteReg(LCD_POWER1);
|
||||
ili9341_WriteData(0x10);
|
||||
ili9341_WriteReg(LCD_POWER2);
|
||||
ili9341_WriteData(0x10);
|
||||
ili9341_WriteReg(LCD_VCOM1);
|
||||
ili9341_WriteData(0x45);
|
||||
ili9341_WriteData(0x15);
|
||||
ili9341_WriteReg(LCD_VCOM2);
|
||||
ili9341_WriteData(0x90);
|
||||
ili9341_WriteReg(LCD_MAC);
|
||||
ili9341_WriteData(0xC8);
|
||||
ili9341_WriteReg(LCD_3GAMMA_EN);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteReg(LCD_RGB_INTERFACE);
|
||||
ili9341_WriteData(0xC2);
|
||||
ili9341_WriteReg(LCD_DFC);
|
||||
ili9341_WriteData(0x0A);
|
||||
ili9341_WriteData(0xA7);
|
||||
ili9341_WriteData(0x27);
|
||||
ili9341_WriteData(0x04);
|
||||
|
||||
/* Colomn address set */
|
||||
ili9341_WriteReg(LCD_COLUMN_ADDR);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0xEF);
|
||||
/* Page address set */
|
||||
ili9341_WriteReg(LCD_PAGE_ADDR);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x01);
|
||||
ili9341_WriteData(0x3F);
|
||||
ili9341_WriteReg(LCD_INTERFACE);
|
||||
ili9341_WriteData(0x01);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x06);
|
||||
|
||||
ili9341_WriteReg(LCD_GRAM);
|
||||
HAL_Delay(200);
|
||||
|
||||
ili9341_WriteReg(LCD_GAMMA);
|
||||
ili9341_WriteData(0x01);
|
||||
|
||||
ili9341_WriteReg(LCD_PGAMMA);
|
||||
ili9341_WriteData(0x0F);
|
||||
ili9341_WriteData(0x29);
|
||||
ili9341_WriteData(0x24);
|
||||
ili9341_WriteData(0x0C);
|
||||
ili9341_WriteData(0x0E);
|
||||
ili9341_WriteData(0x09);
|
||||
ili9341_WriteData(0x4E);
|
||||
ili9341_WriteData(0x78);
|
||||
ili9341_WriteData(0x3C);
|
||||
ili9341_WriteData(0x09);
|
||||
ili9341_WriteData(0x13);
|
||||
ili9341_WriteData(0x05);
|
||||
ili9341_WriteData(0x17);
|
||||
ili9341_WriteData(0x11);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteReg(LCD_NGAMMA);
|
||||
ili9341_WriteData(0x00);
|
||||
ili9341_WriteData(0x16);
|
||||
ili9341_WriteData(0x1B);
|
||||
ili9341_WriteData(0x04);
|
||||
ili9341_WriteData(0x11);
|
||||
ili9341_WriteData(0x07);
|
||||
ili9341_WriteData(0x31);
|
||||
ili9341_WriteData(0x33);
|
||||
ili9341_WriteData(0x42);
|
||||
ili9341_WriteData(0x05);
|
||||
ili9341_WriteData(0x0C);
|
||||
ili9341_WriteData(0x0A);
|
||||
ili9341_WriteData(0x28);
|
||||
ili9341_WriteData(0x2F);
|
||||
ili9341_WriteData(0x0F);
|
||||
|
||||
ili9341_WriteReg(LCD_SLEEP_OUT);
|
||||
HAL_Delay(200);
|
||||
ili9341_WriteReg(LCD_DISPLAY_ON);
|
||||
/* GRAM start writing */
|
||||
ili9341_WriteReg(LCD_GRAM);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#ifndef _ILI9341_SPI_H
|
||||
#define _ILI9341_SPI_H
|
||||
|
||||
#define ILI9341_HSYNC ((uint32_t)9) /* Horizontal synchronization */
|
||||
#define ILI9341_HBP ((uint32_t)29) /* Horizontal back porch */
|
||||
#define ILI9341_HFP ((uint32_t)2) /* Horizontal front porch */
|
||||
#define ILI9341_VSYNC ((uint32_t)1) /* Vertical synchronization */
|
||||
#define ILI9341_VBP ((uint32_t)3) /* Vertical back porch */
|
||||
#define ILI9341_VFP ((uint32_t)2) /* Vertical front porch */
|
||||
|
||||
void ili9341_init(void);
|
||||
|
||||
#endif //_ILI9341_SPI_H
|
398
core/embed/trezorhal/stm32f4/display/ug-2828/display_driver.c
Normal file
398
core/embed/trezorhal/stm32f4/display/ug-2828/display_driver.c
Normal file
@ -0,0 +1,398 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "xdisplay.h"
|
||||
|
||||
#if (DISPLAY_RESX != 128) || (DISPLAY_RESY != 128)
|
||||
#error "Incompatible display resolution"
|
||||
#endif
|
||||
|
||||
// This file implements display driver for monochromatic display V-2864KSWEG01
|
||||
// with 128x128 resolution connected to CPU via SPI interface.
|
||||
//
|
||||
// This type of displayed was used on some preliminary dev kits for T3T1 (Trezor
|
||||
// TS3)
|
||||
|
||||
// Display driver context.
|
||||
typedef struct {
|
||||
// Frame buffer (8-bit Mono)
|
||||
uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY];
|
||||
// Current display orientation (0 or 180)
|
||||
int orientation_angle;
|
||||
// Current backlight level ranging from 0 to 255
|
||||
int backlight_level;
|
||||
} display_driver_t;
|
||||
|
||||
// Display driver instance
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
// Macros to access display parallel interface
|
||||
|
||||
// FSMC/FMC Bank 1 - NOR/PSRAM 1
|
||||
#define DISPLAY_MEMORY_BASE 0x60000000
|
||||
#define DISPLAY_MEMORY_PIN 16
|
||||
|
||||
#define CMD_ADDR *((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE)))
|
||||
#define DATA_ADDR \
|
||||
(*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | \
|
||||
(1 << DISPLAY_MEMORY_PIN)))))
|
||||
|
||||
#define ISSUE_CMD_BYTE(X) \
|
||||
do { \
|
||||
(CMD_ADDR) = (X); \
|
||||
} while (0)
|
||||
#define ISSUE_DATA_BYTE(X) \
|
||||
do { \
|
||||
(DATA_ADDR) = (X); \
|
||||
} while (0)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Display controller registers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define OLED_SETCONTRAST 0x81
|
||||
#define OLED_DISPLAYALLON_RESUME 0xA4
|
||||
#define OLED_DISPLAYALLON 0xA5
|
||||
#define OLED_NORMALDISPLAY 0xA6
|
||||
#define OLED_INVERTDISPLAY 0xA7
|
||||
#define OLED_DISPLAYOFF 0xAE
|
||||
#define OLED_DISPLAYON 0xAF
|
||||
#define OLED_SETDISPLAYOFFSET 0xD3
|
||||
#define OLED_SETCOMPINS 0xDA
|
||||
#define OLED_SETVCOMDETECT 0xDB
|
||||
#define OLED_SETDISPLAYCLOCKDIV 0xD5
|
||||
#define OLED_SETPRECHARGE 0xD9
|
||||
#define OLED_SETMULTIPLEX 0xA8
|
||||
#define OLED_SETLOWCOLUMN 0x00
|
||||
#define OLED_SETHIGHCOLUMN 0x10
|
||||
#define OLED_SETSTARTLINE 0x40
|
||||
#define OLED_MEMORYMODE 0x20
|
||||
#define OLED_COMSCANINC 0xC0
|
||||
#define OLED_COMSCANDEC 0xC8
|
||||
#define OLED_SEGREMAP 0xA0
|
||||
#define OLED_CHARGEPUMP 0x8D
|
||||
|
||||
// Dipslay specific initialization sequence
|
||||
static const uint8_t ug_2828tswig01_init_seq[] = {
|
||||
OLED_DISPLAYOFF,
|
||||
// Divide ratio 0, Oscillator Frequency +0%
|
||||
OLED_SETDISPLAYCLOCKDIV, 0x50,
|
||||
// Set Memory Addressing Mode - page addressing mode
|
||||
0x20,
|
||||
// Set Contrast Control Register
|
||||
OLED_SETCONTRAST, 0x8F,
|
||||
// Set DC-DC Setting: (Double Bytes Command)
|
||||
0xAD, 0x8A,
|
||||
// Set Segment Re-map
|
||||
OLED_SEGREMAP | 0x01,
|
||||
// Set COM Output Scan Direction
|
||||
OLED_COMSCANDEC,
|
||||
// Set Display Start Line:(Double Bytes Command)
|
||||
0xDC, 0x00,
|
||||
// Set Display Offset:(Double Bytes Command)
|
||||
OLED_SETDISPLAYOFFSET, 0x00,
|
||||
// Set Discharge / Pre-Charge Period (Double Bytes Command)
|
||||
OLED_SETPRECHARGE, 0x22,
|
||||
// Set VCOM Deselect Level
|
||||
OLED_SETVCOMDETECT, 0x35,
|
||||
// Set Multiplex Ratio
|
||||
OLED_SETMULTIPLEX, 0x7F,
|
||||
// Set Page
|
||||
0xB0,
|
||||
// Reset column
|
||||
OLED_SETLOWCOLUMN | 0, OLED_SETHIGHCOLUMN | 0,
|
||||
|
||||
// Set Entire Display Off
|
||||
// to be clear, this command turns off the function
|
||||
// which turns entire display on, but it does not clear
|
||||
// the data in display RAM
|
||||
OLED_DISPLAYALLON_RESUME,
|
||||
// Set Normal Display
|
||||
OLED_NORMALDISPLAY};
|
||||
|
||||
static void __attribute__((unused)) display_sleep(void) {
|
||||
// Display OFF
|
||||
ISSUE_CMD_BYTE(OLED_DISPLAYOFF);
|
||||
HAL_Delay(5);
|
||||
// Vpp disable
|
||||
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
static void display_resume(void) {
|
||||
// Vpp enable
|
||||
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_SET);
|
||||
// 100 ms mandatory wait
|
||||
HAL_Delay(100);
|
||||
// Display ON
|
||||
ISSUE_CMD_BYTE(OLED_DISPLAYON);
|
||||
}
|
||||
|
||||
// Sets the display cursor to the specific row and column
|
||||
static void display_set_page_and_col(uint8_t page, uint8_t col) {
|
||||
if (page < (DISPLAY_RESY / 8)) {
|
||||
ISSUE_CMD_BYTE(0xB0 | (page & 0xF));
|
||||
|
||||
if (col < DISPLAY_RESX) {
|
||||
ISSUE_CMD_BYTE(OLED_SETHIGHCOLUMN | ((col & 0x70) >> 4));
|
||||
ISSUE_CMD_BYTE(OLED_SETLOWCOLUMN | (col & 0x0F));
|
||||
} else {
|
||||
// Reset column to start
|
||||
ISSUE_CMD_BYTE(OLED_SETHIGHCOLUMN);
|
||||
ISSUE_CMD_BYTE(OLED_SETLOWCOLUMN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define COLLECT_ROW_BYTE(src) \
|
||||
(0 | (*(src + (0 * DISPLAY_RESX)) >= 128 ? 128 : 0) | \
|
||||
(*(src + (1 * DISPLAY_RESX)) >= 128 ? 64 : 0) | \
|
||||
(*(src + (2 * DISPLAY_RESX)) >= 128 ? 32 : 0) | \
|
||||
(*(src + (3 * DISPLAY_RESX)) >= 128 ? 16 : 0) | \
|
||||
(*(src + (4 * DISPLAY_RESX)) >= 128 ? 8 : 0) | \
|
||||
(*(src + (5 * DISPLAY_RESX)) >= 128 ? 4 : 0) | \
|
||||
(*(src + (6 * DISPLAY_RESX)) >= 128 ? 2 : 0) | \
|
||||
(*(src + (7 * DISPLAY_RESX)) >= 128 ? 1 : 0))
|
||||
|
||||
// Copies the framebuffer to the display via SPI interface
|
||||
static void display_sync_with_fb(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
for (int y = 0; y < DISPLAY_RESY / 8; y++) {
|
||||
display_set_page_and_col(y, 0);
|
||||
uint8_t *src = &drv->framebuf[y * DISPLAY_RESX * 8];
|
||||
for (int x = 0; x < DISPLAY_RESX; x++) {
|
||||
ISSUE_DATA_BYTE(COLLECT_ROW_BYTE(src));
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void display_init_controller(void) {
|
||||
// LCD_RST/PC14
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
|
||||
// wait 10 milliseconds. only needs to be low for 10 microseconds.
|
||||
// my dev display module ties display reset and touch panel reset together.
|
||||
// keeping this low for max(display_reset_time, ctpm_reset_time) aids
|
||||
// development and does not hurt.
|
||||
HAL_Delay(10);
|
||||
|
||||
// LCD_RST/PC14
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
|
||||
// max wait time for hardware reset is 120 milliseconds
|
||||
// (experienced display flakiness using only 5ms wait before sending commands)
|
||||
HAL_Delay(120);
|
||||
|
||||
// Apply initialization sequence specific to this display controller/panel
|
||||
for (int i = 0; i < sizeof(ug_2828tswig01_init_seq); i++) {
|
||||
ISSUE_CMD_BYTE(ug_2828tswig01_init_seq[i]);
|
||||
}
|
||||
|
||||
// Resume the suspended display
|
||||
display_resume();
|
||||
// Clear display internal framebuffer
|
||||
display_sync_with_fb();
|
||||
}
|
||||
|
||||
static void display_init_interface(void) {
|
||||
// init peripherals
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_FMC_CLK_ENABLE();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||
|
||||
// LCD_RST/PC14
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStructure.Alternate = 0;
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_14;
|
||||
// default to keeping display in reset
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
// VPP Enable
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStructure.Alternate = 0;
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_8;
|
||||
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF12_FMC;
|
||||
// LCD_CS/PD7 LCD_RS/PD11 LCD_RD/PD4 LCD_WR/PD5
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
// LCD_D0/PD14 LCD_D1/PD15 LCD_D2/PD0 LCD_D3/PD1
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
// LCD_D4/PE7 LCD_D5/PE8 LCD_D6/PE9 LCD_D7/PE10
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
// Reference UM1725 "Description of STM32F4 HAL and LL drivers",
|
||||
// section 64.2.1 "How to use this driver"
|
||||
SRAM_HandleTypeDef display_sram = {0};
|
||||
display_sram.Instance = FMC_NORSRAM_DEVICE;
|
||||
display_sram.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
|
||||
display_sram.Init.NSBank = FMC_NORSRAM_BANK1;
|
||||
display_sram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
|
||||
display_sram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
|
||||
display_sram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
|
||||
display_sram.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
|
||||
display_sram.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
|
||||
display_sram.Init.WrapMode = FMC_WRAP_MODE_DISABLE;
|
||||
display_sram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
|
||||
display_sram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
|
||||
display_sram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
|
||||
display_sram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
|
||||
display_sram.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
|
||||
display_sram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
|
||||
display_sram.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
|
||||
display_sram.Init.PageSize = FMC_PAGE_SIZE_NONE;
|
||||
|
||||
// reference RM0090 section 37.5 Table 259, 37.5.4, Mode 1 SRAM, and 37.5.6
|
||||
FMC_NORSRAM_TimingTypeDef normal_mode_timing = {0};
|
||||
normal_mode_timing.AddressSetupTime = 10;
|
||||
normal_mode_timing.AddressHoldTime = 10;
|
||||
normal_mode_timing.DataSetupTime = 10;
|
||||
normal_mode_timing.BusTurnAroundDuration = 0;
|
||||
normal_mode_timing.CLKDivision = 2;
|
||||
normal_mode_timing.DataLatency = 2;
|
||||
normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A;
|
||||
|
||||
HAL_SRAM_Init(&display_sram, &normal_mode_timing, NULL);
|
||||
}
|
||||
|
||||
void display_init(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
|
||||
// Initialize GPIO & FSMC controller
|
||||
display_init_interface();
|
||||
// Initialize display controller
|
||||
display_init_controller();
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
|
||||
// !@# TODO backlight level??
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
/// Not used and intentionally left empty
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (level != drv->backlight_level) {
|
||||
if (level >= 0 && level <= 255) {
|
||||
drv->backlight_level = level;
|
||||
// Set Contrast Control Register: (Double Bytes Command)
|
||||
ISSUE_CMD_BYTE(OLED_SETCONTRAST);
|
||||
ISSUE_CMD_BYTE(level & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_get_backlight(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (angle != drv->orientation_angle) {
|
||||
if (angle == 0 || angle == 180) {
|
||||
drv->orientation_angle = angle;
|
||||
if (angle == 0) {
|
||||
// Set Segment Re-map: (A0H - A1H)
|
||||
ISSUE_CMD_BYTE(OLED_SEGREMAP | 0x01);
|
||||
// Set COM Output Scan Direction
|
||||
ISSUE_CMD_BYTE(OLED_COMSCANDEC);
|
||||
} else {
|
||||
// Set Segment Re-map: (A0H - A1H)
|
||||
ISSUE_CMD_BYTE(OLED_SEGREMAP | 0x00);
|
||||
// Set COM Output Scan Direction
|
||||
ISSUE_CMD_BYTE(OLED_COMSCANINC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
display_fb_info_t fb = {
|
||||
.ptr = &drv->framebuf[0],
|
||||
.stride = DISPLAY_RESX,
|
||||
};
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
void display_refresh(void) { display_sync_with_fb(); }
|
||||
|
||||
void display_set_compatible_settings() {}
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y];
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
mono8_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y];
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
mono8_copy_mono1p(&bb_new);
|
||||
}
|
379
core/embed/trezorhal/stm32f4/display/vg-2864/display_driver.c
Normal file
379
core/embed/trezorhal/stm32f4/display/vg-2864/display_driver.c
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "xdisplay.h"
|
||||
|
||||
#ifdef USE_CONSUMPTION_MASK
|
||||
#include "consumption_mask.h"
|
||||
#endif
|
||||
|
||||
#if (DISPLAY_RESX != 128) || (DISPLAY_RESY != 64)
|
||||
#error "Incompatible display resolution"
|
||||
#endif
|
||||
|
||||
// This file implements display driver for monochromatic display V-2864KSWEG01
|
||||
// with 128x64 resolution connected to CPU via SPI interface.
|
||||
//
|
||||
// This type of display is used with T3T1 model (Trezor TS3)
|
||||
|
||||
// Display driver context.
|
||||
typedef struct {
|
||||
// SPI driver instance
|
||||
SPI_HandleTypeDef spi;
|
||||
// Frame buffer (8-bit Mono)
|
||||
uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY];
|
||||
// Current display orientation (0 or 180)
|
||||
int orientation_angle;
|
||||
// Current backlight level ranging from 0 to 255
|
||||
int backlight_level;
|
||||
} display_driver_t;
|
||||
|
||||
// Display driver instance
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
// Display controller registers
|
||||
#define OLED_SETCONTRAST 0x81
|
||||
#define OLED_DISPLAYALLON_RESUME 0xA4
|
||||
#define OLED_DISPLAYALLON 0xA5
|
||||
#define OLED_NORMALDISPLAY 0xA6
|
||||
#define OLED_INVERTDISPLAY 0xA7
|
||||
#define OLED_DISPLAYOFF 0xAE
|
||||
#define OLED_DISPLAYON 0xAF
|
||||
#define OLED_SETDISPLAYOFFSET 0xD3
|
||||
#define OLED_SETCOMPINS 0xDA
|
||||
#define OLED_SETVCOMDETECT 0xDB
|
||||
#define OLED_SETDISPLAYCLOCKDIV 0xD5
|
||||
#define OLED_SETPRECHARGE 0xD9
|
||||
#define OLED_SETMULTIPLEX 0xA8
|
||||
#define OLED_SETLOWCOLUMN 0x00
|
||||
#define OLED_SETHIGHCOLUMN 0x10
|
||||
#define OLED_SETSTARTLINE 0x40
|
||||
#define OLED_MEMORYMODE 0x20
|
||||
#define OLED_COMSCANINC 0xC0
|
||||
#define OLED_COMSCANDEC 0xC8
|
||||
#define OLED_SEGREMAP 0xA0
|
||||
#define OLED_CHARGEPUMP 0x8D
|
||||
|
||||
// Display controller initialization sequence
|
||||
static const uint8_t vg_2864ksweg01_init_seq[] = {OLED_DISPLAYOFF,
|
||||
OLED_SETDISPLAYCLOCKDIV,
|
||||
0x80,
|
||||
OLED_SETMULTIPLEX,
|
||||
0x3F, // 128x64
|
||||
OLED_SETDISPLAYOFFSET,
|
||||
0x00,
|
||||
OLED_SETSTARTLINE | 0x00,
|
||||
OLED_CHARGEPUMP,
|
||||
0x14,
|
||||
OLED_MEMORYMODE,
|
||||
0x00,
|
||||
OLED_SEGREMAP | 0x01,
|
||||
OLED_COMSCANDEC,
|
||||
OLED_SETCOMPINS,
|
||||
0x12, // 128x64
|
||||
OLED_SETCONTRAST,
|
||||
0xCF,
|
||||
OLED_SETPRECHARGE,
|
||||
0xF1,
|
||||
OLED_SETVCOMDETECT,
|
||||
0x40,
|
||||
OLED_DISPLAYALLON_RESUME,
|
||||
OLED_NORMALDISPLAY,
|
||||
OLED_DISPLAYON};
|
||||
|
||||
// Configures SPI driver/controller
|
||||
static bool display_init_spi(display_driver_t *drv) {
|
||||
drv->spi.Instance = OLED_SPI;
|
||||
drv->spi.State = HAL_SPI_STATE_RESET;
|
||||
drv->spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
|
||||
drv->spi.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
drv->spi.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
drv->spi.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
drv->spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
drv->spi.Init.CRCPolynomial = 7;
|
||||
drv->spi.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
drv->spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
drv->spi.Init.NSS = SPI_NSS_HARD_OUTPUT;
|
||||
drv->spi.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
drv->spi.Init.Mode = SPI_MODE_MASTER;
|
||||
|
||||
return (HAL_OK == HAL_SPI_Init(&drv->spi)) ? true : false;
|
||||
}
|
||||
|
||||
// Sends specified number of bytes to the display via SPI interface
|
||||
static void display_send_bytes(display_driver_t *drv, const uint8_t *data,
|
||||
size_t len) {
|
||||
volatile int32_t timeout = 1000;
|
||||
for (int i = 0; i < timeout; i++)
|
||||
;
|
||||
|
||||
if (HAL_OK != HAL_SPI_Transmit(&drv->spi, (uint8_t *)data, len, 1000)) {
|
||||
// TODO: error
|
||||
return;
|
||||
}
|
||||
while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&drv->spi)) {
|
||||
}
|
||||
}
|
||||
|
||||
#define COLLECT_ROW_BYTE(src) \
|
||||
(0 | (*(src + (0 * DISPLAY_RESX)) >= 128 ? 128 : 0) | \
|
||||
(*(src + (1 * DISPLAY_RESX)) >= 128 ? 64 : 0) | \
|
||||
(*(src + (2 * DISPLAY_RESX)) >= 128 ? 32 : 0) | \
|
||||
(*(src + (3 * DISPLAY_RESX)) >= 128 ? 16 : 0) | \
|
||||
(*(src + (4 * DISPLAY_RESX)) >= 128 ? 8 : 0) | \
|
||||
(*(src + (5 * DISPLAY_RESX)) >= 128 ? 4 : 0) | \
|
||||
(*(src + (6 * DISPLAY_RESX)) >= 128 ? 2 : 0) | \
|
||||
(*(src + (7 * DISPLAY_RESX)) >= 128 ? 1 : 0))
|
||||
|
||||
#define COLLECT_ROW_BYTE_REV(src) \
|
||||
(0 | (*(src + (0 * DISPLAY_RESX)) >= 128 ? 1 : 0) | \
|
||||
(*(src + (1 * DISPLAY_RESX)) >= 128 ? 2 : 0) | \
|
||||
(*(src + (2 * DISPLAY_RESX)) >= 128 ? 4 : 0) | \
|
||||
(*(src + (3 * DISPLAY_RESX)) >= 128 ? 8 : 0) | \
|
||||
(*(src + (4 * DISPLAY_RESX)) >= 128 ? 16 : 0) | \
|
||||
(*(src + (5 * DISPLAY_RESX)) >= 128 ? 32 : 0) | \
|
||||
(*(src + (6 * DISPLAY_RESX)) >= 128 ? 64 : 0) | \
|
||||
(*(src + (7 * DISPLAY_RESX)) >= 128 ? 128 : 0))
|
||||
|
||||
// Copies the framebuffer to the display via SPI interface
|
||||
static void display_sync_with_fb(display_driver_t *drv) {
|
||||
static const uint8_t cursor_set_seq[3] = {OLED_SETLOWCOLUMN | 0x00,
|
||||
OLED_SETHIGHCOLUMN | 0x00,
|
||||
OLED_SETSTARTLINE | 0x00};
|
||||
|
||||
// SPI select
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET);
|
||||
// Set the cursor to the screen top-left corner
|
||||
display_send_bytes(drv, &cursor_set_seq[0], sizeof(cursor_set_seq));
|
||||
|
||||
// SPI deselect
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET);
|
||||
// Set to DATA
|
||||
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET);
|
||||
// SPI select
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET);
|
||||
|
||||
// Send whole framebuffer to the display
|
||||
|
||||
if (drv->orientation_angle == 0) {
|
||||
for (int y = DISPLAY_RESY / 8 - 1; y >= 0; y--) {
|
||||
uint8_t buff[DISPLAY_RESX];
|
||||
uint8_t *src = &drv->framebuf[y * DISPLAY_RESX * 8];
|
||||
|
||||
for (int x = DISPLAY_RESX - 1; x >= 0; x--) {
|
||||
buff[x] = COLLECT_ROW_BYTE(src);
|
||||
src++;
|
||||
}
|
||||
|
||||
if (HAL_OK != HAL_SPI_Transmit(&drv->spi, &buff[0], sizeof(buff), 1000)) {
|
||||
// TODO: error
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < DISPLAY_RESY / 8; y++) {
|
||||
uint8_t buff[DISPLAY_RESX];
|
||||
uint8_t *src = &drv->framebuf[y * DISPLAY_RESX * 8];
|
||||
|
||||
for (int x = 0; x < DISPLAY_RESX; x++) {
|
||||
buff[x] = COLLECT_ROW_BYTE_REV(src);
|
||||
src++;
|
||||
}
|
||||
|
||||
if (HAL_OK != HAL_SPI_Transmit(&drv->spi, &buff[0], sizeof(buff), 1000)) {
|
||||
// TODO: error
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&drv->spi)) {
|
||||
}
|
||||
|
||||
// SPI deselect
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET);
|
||||
// Set to CMD
|
||||
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
void display_init(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
drv->backlight_level = 255;
|
||||
|
||||
OLED_DC_CLK_ENA();
|
||||
OLED_CS_CLK_ENA();
|
||||
OLED_RST_CLK_ENA();
|
||||
OLED_SPI_SCK_CLK_ENA();
|
||||
OLED_SPI_MOSI_CLK_ENA();
|
||||
OLED_SPI_CLK_ENA();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
// Set GPIO for OLED display
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Alternate = 0;
|
||||
GPIO_InitStructure.Pin = OLED_CS_PIN;
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(OLED_CS_PORT, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.Pin = OLED_DC_PIN;
|
||||
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(OLED_DC_PORT, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.Pin = OLED_RST_PIN;
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET);
|
||||
HAL_GPIO_Init(OLED_RST_PORT, &GPIO_InitStructure);
|
||||
|
||||
// Enable SPI 1 for OLED display
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStructure.Alternate = OLED_SPI_AF;
|
||||
GPIO_InitStructure.Pin = OLED_SPI_SCK_PIN;
|
||||
HAL_GPIO_Init(OLED_SPI_SCK_PORT, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.Pin = OLED_SPI_MOSI_PIN;
|
||||
HAL_GPIO_Init(OLED_SPI_MOSI_PORT, &GPIO_InitStructure);
|
||||
|
||||
// Initialize SPI controller
|
||||
display_init_spi(drv);
|
||||
|
||||
// Set to CMD
|
||||
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET);
|
||||
// SPI deselect
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET);
|
||||
|
||||
// Reset the LCD
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET);
|
||||
HAL_Delay(1);
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET);
|
||||
HAL_Delay(1);
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET);
|
||||
|
||||
// SPI select
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET);
|
||||
// Send initialization command sequence
|
||||
display_send_bytes(drv, &vg_2864ksweg01_init_seq[0],
|
||||
sizeof(vg_2864ksweg01_init_seq));
|
||||
// SPI deselect
|
||||
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET);
|
||||
|
||||
// Clear display internal framebuffer
|
||||
display_sync_with_fb(drv);
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
memset(drv, 0, sizeof(display_driver_t));
|
||||
drv->backlight_level = 255;
|
||||
|
||||
display_init_spi(drv);
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
/// Not used and intentionally left empty
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
drv->backlight_level = 255;
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_get_backlight(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (angle != drv->orientation_angle) {
|
||||
if (angle == 0 || angle == 180) {
|
||||
drv->orientation_angle = angle;
|
||||
display_sync_with_fb(drv);
|
||||
}
|
||||
}
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
display_fb_info_t fb = {
|
||||
.ptr = &drv->framebuf[0],
|
||||
.stride = DISPLAY_RESX,
|
||||
};
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
void display_refresh(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
#if defined USE_CONSUMPTION_MASK && !defined BOARDLOADER
|
||||
// This is an intentional randomization of the consumption masking algorithm
|
||||
// after every change on the display
|
||||
consumption_mask_randomize();
|
||||
#endif
|
||||
|
||||
// Sends the current frame buffer to the display
|
||||
display_sync_with_fb(drv);
|
||||
}
|
||||
|
||||
void display_set_compatible_settings() {}
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y];
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
gl_mono8_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y];
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
gl_mono8_copy_mono1p(&bb_new);
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include TREZOR_BOARD
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "memzero.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
@ -46,12 +46,12 @@ uint8_t *const DISPLAY_DATA_ADDRESS = 0;
|
||||
uint16_t cursor_x = 0;
|
||||
uint16_t cursor_y = 0;
|
||||
uint16_t window_x0 = 0;
|
||||
uint16_t window_y0 = MAX_DISPLAY_RESX - 1;
|
||||
uint16_t window_y0 = DISPLAY_RESX - 1;
|
||||
uint16_t window_x1 = 0;
|
||||
uint16_t window_y1 = MAX_DISPLAY_RESY - 1;
|
||||
uint16_t window_y1 = DISPLAY_RESY - 1;
|
||||
|
||||
void display_pixeldata(uint16_t c) {
|
||||
((uint16_t *)LCD_FRAME_BUFFER)[(cursor_y * MAX_DISPLAY_RESX) + cursor_x] = c;
|
||||
((uint16_t *)LCD_FRAME_BUFFER)[(cursor_y * DISPLAY_RESX) + cursor_x] = c;
|
||||
|
||||
cursor_x++;
|
||||
|
||||
@ -83,9 +83,9 @@ void BSP_LCD_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) {
|
||||
|
||||
/* Layer Init */
|
||||
Layercfg.WindowX0 = 0;
|
||||
Layercfg.WindowX1 = MAX_DISPLAY_RESX;
|
||||
Layercfg.WindowX1 = DISPLAY_RESX;
|
||||
Layercfg.WindowY0 = 0;
|
||||
Layercfg.WindowY1 = MAX_DISPLAY_RESY;
|
||||
Layercfg.WindowY1 = DISPLAY_RESY;
|
||||
Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
|
||||
Layercfg.FBStartAdress = FB_Address;
|
||||
Layercfg.Alpha = 255;
|
||||
@ -95,8 +95,8 @@ void BSP_LCD_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) {
|
||||
Layercfg.Backcolor.Red = 0;
|
||||
Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
||||
Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
||||
Layercfg.ImageWidth = MAX_DISPLAY_RESX;
|
||||
Layercfg.ImageHeight = MAX_DISPLAY_RESY;
|
||||
Layercfg.ImageWidth = DISPLAY_RESX;
|
||||
Layercfg.ImageHeight = DISPLAY_RESY;
|
||||
|
||||
HAL_LTDC_ConfigLayer(&LtdcHandler, &Layercfg, LayerIndex);
|
||||
|
||||
@ -380,7 +380,7 @@ void display_efficient_clear(void) {
|
||||
uint8_t *display_get_wr_addr(void) {
|
||||
uint32_t address = LCD_FRAME_BUFFER;
|
||||
/* Get the rectangle start address */
|
||||
address = (address + (2 * ((cursor_y)*MAX_DISPLAY_RESX + (cursor_x))));
|
||||
address = (address + (2 * ((cursor_y)*DISPLAY_RESX + (cursor_x))));
|
||||
|
||||
return (uint8_t *)address;
|
||||
}
|
||||
@ -413,7 +413,7 @@ void display_shift_window(uint16_t pixels) {
|
||||
}
|
||||
|
||||
uint16_t display_get_window_offset(void) {
|
||||
return MAX_DISPLAY_RESX - display_get_window_width();
|
||||
return DISPLAY_RESX - display_get_window_width();
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {}
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include STM32_HAL_H
|
||||
|
||||
#define TREZOR_FONT_BPP 4
|
||||
#define DISPLAY_FRAMEBUFFER_WIDTH MAX_DISPLAY_RESX
|
||||
#define DISPLAY_FRAMEBUFFER_HEIGHT MAX_DISPLAY_RESY
|
||||
#define DISPLAY_FRAMEBUFFER_WIDTH DISPLAY_RESX
|
||||
#define DISPLAY_FRAMEBUFFER_HEIGHT DISPLAY_RESY
|
||||
#define DISPLAY_FRAMEBUFFER_OFFSET_X 0
|
||||
#define DISPLAY_FRAMEBUFFER_OFFSET_Y 0
|
||||
#define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "displays/st7789v.h"
|
||||
#include "touch.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "displays/st7789v.h"
|
||||
|
||||
void tf15411a_init_seq(void) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include TREZOR_BOARD
|
||||
#include "backlight_pwm.h"
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "irq.h"
|
||||
#include "memzero.h"
|
||||
#include "st7789v.h"
|
||||
@ -34,6 +34,8 @@
|
||||
#include "displays/panels/lx154a2411.h"
|
||||
#include "displays/panels/lx154a2422.h"
|
||||
#include "displays/panels/tf15411a.h"
|
||||
#else
|
||||
#include "displays/panels/lx154a2422.h"
|
||||
#endif
|
||||
|
||||
// using const volatile instead of #define results in binaries that change
|
||||
@ -241,7 +243,7 @@ int display_orientation(int degrees) {
|
||||
lx154a2422_rotate(degrees, &DISPLAY_PADDING);
|
||||
}
|
||||
#else
|
||||
DISPLAY_PANEL_ROTATE(degrees, &DISPLAY_PADDING);
|
||||
lx154a2422_rotate(degrees, &DISPLAY_PADDING);
|
||||
#endif
|
||||
panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1);
|
||||
}
|
||||
@ -292,7 +294,7 @@ void display_init_seq(void) {
|
||||
_154a_init_seq();
|
||||
}
|
||||
#else
|
||||
DISPLAY_PANEL_INIT_SEQ();
|
||||
lx154a2422_init_seq();
|
||||
#endif
|
||||
|
||||
display_unsleep();
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include TREZOR_BOARD
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "memzero.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include TREZOR_BOARD
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
#ifdef USE_CONSUMPTION_MASK
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "dma2d.h"
|
||||
#include "colors.h"
|
||||
#include STM32_HAL_H
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
|
||||
typedef enum {
|
||||
DMA2D_LAYER_FG = 1,
|
||||
|
616
core/embed/trezorhal/stm32f4/dma2d_bitblt.c
Normal file
616
core/embed/trezorhal/stm32f4/dma2d_bitblt.c
Normal file
@ -0,0 +1,616 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dma2d_bitblt.h"
|
||||
#include "gl_color.h"
|
||||
|
||||
static DMA2D_HandleTypeDef dma2d_handle = {
|
||||
.Instance = (DMA2D_TypeDef*)DMA2D_BASE,
|
||||
};
|
||||
|
||||
bool dma2d_accessible(const void* ptr) {
|
||||
#ifdef STM32F4
|
||||
const void* ccm_start = (const void*)0x10000000;
|
||||
const void* ccm_end = (const void*)0x1000FFFF;
|
||||
return !(ptr >= ccm_start && ptr <= ccm_end);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dma2d_wait(void) {
|
||||
while (HAL_DMA2D_PollForTransfer(&dma2d_handle, 10) != HAL_OK)
|
||||
;
|
||||
}
|
||||
|
||||
void dma2d_rgb565_fill(const gl_bitblt_t* bb) {
|
||||
dma2d_wait();
|
||||
|
||||
if (bb->src_alpha == 255) {
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
||||
dma2d_handle.Init.Mode = DMA2D_R2M;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle, gl_color_to_color32(bb->src_fg),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t),
|
||||
bb->width, bb->height);
|
||||
/*
|
||||
|
||||
MODIFY_REG(dma2d_handle.Instance->CR, DMA2D_CR_MODE, DMA2D_R2M);
|
||||
MODIFY_REG(dma2d_handle.Instance->OPFCCR, DMA2D_OPFCCR_CM,
|
||||
DMA2D_OUTPUT_RGB565); MODIFY_REG(dma2d_handle.Instance->OOR,
|
||||
DMA2D_OOR_LO, bb->dst_stride / sizeof(uint16_t) - bb->width);
|
||||
MODIFY_REG(dma2d_handle.Instance->NLR, (DMA2D_NLR_NL|DMA2D_NLR_PL),
|
||||
(bb->height| (bb->width << 16))); WRITE_REG(dma2d_handle.Instance->OMAR,
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t));
|
||||
WRITE_REG(dma2d_handle.Instance->OCOLR,
|
||||
gl_color_to_color32(bb->src_fg));
|
||||
((dma2d_handle).Instance->CR |= DMA2D_CR_START);
|
||||
*/
|
||||
} else {
|
||||
#ifdef STM32U5
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_BLEND_FG;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = 0;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
||||
dma2d_handle.LayerCfg[0].InputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[0].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[0].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 0);
|
||||
|
||||
HAL_DMA2D_BlendingStart(
|
||||
&dma2d_handle, gl_color_to_color32(bb->src_fg),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), bb->width,
|
||||
bb->height);
|
||||
#else
|
||||
// STM32F4 can not accelerate blending with the fixed color
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t height = bb->height;
|
||||
uint8_t alpha = bb->src_alpha;
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color16_blend_a8(
|
||||
bb->src_fg, gl_color16_to_color(dst_ptr[x]), alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void dma2d_config_clut(uint32_t layer, gl_color_t fg, gl_color_t bg) {
|
||||
|
||||
#define LAYER_COUNT 2
|
||||
#define GRADIENT_STEPS 16
|
||||
|
||||
static struct {
|
||||
gl_color32_t gradient[GRADIENT_STEPS];
|
||||
} cache[LAYER_COUNT] = { 0 };
|
||||
|
||||
if (layer >= LAYER_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t c_fg = gl_color_to_color32(fg);
|
||||
uint32_t c_bg = gl_color_to_color32(bg);
|
||||
|
||||
uint32_t* gradient = cache[layer].gradient;
|
||||
|
||||
if (c_bg != gradient[0] || c_fg != gradient[GRADIENT_STEPS - 1]) {
|
||||
for (int step = 0; step < GRADIENT_STEPS; step++) {
|
||||
gradient[step] = gl_color32_blend_a4(fg, bg, step);
|
||||
}
|
||||
|
||||
DMA2D_CLUTCfgTypeDef clut;
|
||||
clut.CLUTColorMode = DMA2D_CCM_ARGB8888;
|
||||
clut.Size = GRADIENT_STEPS - 1;
|
||||
clut.pCLUT = gradient;
|
||||
|
||||
HAL_DMA2D_ConfigCLUT(&dma2d_handle, clut, layer);
|
||||
|
||||
while (HAL_DMA2D_PollForTransfer(&dma2d_handle, 10) != HAL_OK)
|
||||
;
|
||||
}
|
||||
}*/
|
||||
|
||||
static void dma2d_config_clut(uint32_t layer, gl_color_t fg, gl_color_t bg) {
|
||||
#define LAYER_COUNT 2
|
||||
#define GRADIENT_STEPS 16
|
||||
|
||||
static struct {
|
||||
gl_color_t c_fg;
|
||||
gl_color_t c_bg;
|
||||
} cache[LAYER_COUNT] = {0};
|
||||
|
||||
if (layer >= LAYER_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
volatile uint32_t* clut =
|
||||
layer ? dma2d_handle.Instance->FGCLUT : dma2d_handle.Instance->BGCLUT;
|
||||
|
||||
if (fg != cache[layer].c_fg || bg != cache[layer].c_bg) {
|
||||
cache[layer].c_fg = fg;
|
||||
cache[layer].c_bg = bg;
|
||||
|
||||
for (int step = 0; step < GRADIENT_STEPS; step++) {
|
||||
clut[step] = gl_color32_blend_a4(fg, bg, step);
|
||||
}
|
||||
|
||||
DMA2D_CLUTCfgTypeDef clut;
|
||||
clut.CLUTColorMode = DMA2D_CCM_ARGB8888;
|
||||
clut.Size = GRADIENT_STEPS - 1;
|
||||
clut.pCLUT = 0; // ???
|
||||
|
||||
HAL_DMA2D_ConfigCLUT(&dma2d_handle, clut, layer);
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgb565_copy_mono4_first_col(gl_bitblt_t* bb,
|
||||
const gl_color16_t* gradient) {
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_lum = src_ptr[0] >> 4;
|
||||
dst_ptr[0] = gradient[fg_lum];
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgb565_copy_mono4_last_col(gl_bitblt_t* bb,
|
||||
const gl_color16_t* gradient) {
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + (bb->dst_x + bb->width - 1);
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + (bb->src_x + bb->width - 1) / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_lum = src_ptr[0] & 0x0F;
|
||||
dst_ptr[0] = gradient[fg_lum];
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgb565_copy_mono4(const gl_bitblt_t* params) {
|
||||
const gl_color16_t* src_gradient = NULL;
|
||||
|
||||
gl_bitblt_t bb_copy = *params;
|
||||
gl_bitblt_t* bb = &bb_copy;
|
||||
|
||||
dma2d_wait();
|
||||
|
||||
if (bb->src_x & 1) {
|
||||
// First column of mono4 bitmap is odd
|
||||
// Use the CPU to draw the first column
|
||||
src_gradient = gl_color16_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
dma2d_rgb565_copy_mono4_first_col(bb, src_gradient);
|
||||
bb->dst_x += 1;
|
||||
bb->src_x += 1;
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0 && bb->width & 1) {
|
||||
// The width is odd
|
||||
// Use the CPU to draw the last column
|
||||
if (src_gradient == NULL) {
|
||||
src_gradient = gl_color16_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
}
|
||||
dma2d_rgb565_copy_mono4_last_col(bb, src_gradient);
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_PFC;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_config_clut(1, bb->src_fg, bb->src_bg);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2,
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t),
|
||||
bb->width, bb->height);
|
||||
}
|
||||
|
||||
void dma2d_rgb565_copy_rgb565(const gl_bitblt_t* bb) {
|
||||
dma2d_wait();
|
||||
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_PFC;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
||||
dma2d_handle.LayerCfg[1].InputOffset =
|
||||
bb->src_stride / sizeof(uint16_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle,
|
||||
(uint32_t)bb->src_row + bb->src_x * sizeof(uint16_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t),
|
||||
bb->width, bb->height);
|
||||
}
|
||||
|
||||
static void dma2d_rgb565_blend_mono4_first_col(const gl_bitblt_t* bb) {
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_alpha = src_ptr[0] >> 4;
|
||||
dst_ptr[0] = gl_color16_blend_a4(bb->src_fg,
|
||||
gl_color16_to_color(dst_ptr[0]), fg_alpha);
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgb565_blend_mono4_last_col(const gl_bitblt_t* bb) {
|
||||
uint16_t* dst_ptr = (uint16_t*)bb->dst_row + (bb->dst_x + bb->width - 1);
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + (bb->src_x + bb->width - 1) / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_alpha = src_ptr[0] & 0x0F;
|
||||
dst_ptr[0] = gl_color16_blend_a4(bb->src_fg,
|
||||
gl_color16_to_color(dst_ptr[0]), fg_alpha);
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgb565_blend_mono4(const gl_bitblt_t* params) {
|
||||
dma2d_wait();
|
||||
|
||||
gl_bitblt_t bb_copy = *params;
|
||||
gl_bitblt_t* bb = &bb_copy;
|
||||
|
||||
if (bb->src_x & 1) {
|
||||
// First column of mono4 bitmap is odd
|
||||
// Use the CPU to draw the first column
|
||||
dma2d_rgb565_blend_mono4_first_col(bb);
|
||||
bb->dst_x += 1;
|
||||
bb->src_x += 1;
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0 && bb->width & 1) {
|
||||
// The width is odd
|
||||
// Use the CPU to draw the last column
|
||||
dma2d_rgb565_blend_mono4_last_col(bb);
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0) {
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_BLEND;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_A4;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = gl_color_to_color32(bb->src_fg);
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
||||
dma2d_handle.LayerCfg[0].InputOffset =
|
||||
bb->dst_stride / sizeof(uint16_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[0].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[0].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 0);
|
||||
|
||||
HAL_DMA2D_BlendingStart(
|
||||
&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2,
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), bb->width,
|
||||
bb->height);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgba8888_fill(const gl_bitblt_t* bb) {
|
||||
dma2d_wait();
|
||||
|
||||
if (bb->src_alpha == 255) {
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_R2M;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle, gl_color_to_color32(bb->src_fg),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
bb->width, bb->height);
|
||||
} else {
|
||||
#ifdef STM32U5
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_BLEND_FG;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = 0;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||||
dma2d_handle.LayerCfg[0].InputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[0].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[0].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 0);
|
||||
|
||||
HAL_DMA2D_BlendingStart(
|
||||
&dma2d_handle, gl_color_to_color32(bb->src_fg),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width,
|
||||
bb->height);
|
||||
#else
|
||||
// STM32F4 can not accelerate blending with the fixed color
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint16_t height = bb->height;
|
||||
uint8_t alpha = bb->src_alpha;
|
||||
while (height-- > 0) {
|
||||
for (int x = 0; x < bb->width; x++) {
|
||||
dst_ptr[x] = gl_color32_blend_a8(
|
||||
bb->src_fg, gl_color32_to_color(dst_ptr[x]), alpha);
|
||||
}
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgba8888_copy_mono4_first_col(gl_bitblt_t* bb,
|
||||
const gl_color32_t* gradient) {
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_lum = src_ptr[0] >> 4;
|
||||
dst_ptr[0] = gradient[fg_lum];
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgba8888_copy_mono4_last_col(gl_bitblt_t* bb,
|
||||
const gl_color32_t* gradient) {
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + (bb->dst_x + bb->width - 1);
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + (bb->src_x + bb->width - 1) / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_lum = src_ptr[0] & 0x0F;
|
||||
dst_ptr[0] = gradient[fg_lum];
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgba8888_copy_mono4(const gl_bitblt_t* params) {
|
||||
const gl_color32_t* src_gradient = NULL;
|
||||
|
||||
gl_bitblt_t bb_copy = *params;
|
||||
gl_bitblt_t* bb = &bb_copy;
|
||||
|
||||
dma2d_wait();
|
||||
|
||||
if (bb->src_x & 1) {
|
||||
// First column of mono4 bitmap is odd
|
||||
// Use the CPU to draw the first column
|
||||
src_gradient = gl_color32_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
dma2d_rgba8888_copy_mono4_first_col(bb, src_gradient);
|
||||
bb->dst_x += 1;
|
||||
bb->src_x += 1;
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0 && bb->width & 1) {
|
||||
// The width is odd
|
||||
// Use the CPU to draw the last column
|
||||
if (src_gradient == NULL) {
|
||||
src_gradient = gl_color32_gradient_a4(bb->src_fg, bb->src_bg);
|
||||
}
|
||||
dma2d_rgba8888_copy_mono4_last_col(bb, src_gradient);
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_PFC;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_config_clut(1, bb->src_fg, bb->src_bg);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2,
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
bb->width, bb->height);
|
||||
}
|
||||
|
||||
void dma2d_rgba8888_copy_rgb565(const gl_bitblt_t* bb) {
|
||||
dma2d_wait();
|
||||
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_PFC;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
||||
dma2d_handle.LayerCfg[1].InputOffset =
|
||||
bb->src_stride / sizeof(uint16_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle,
|
||||
(uint32_t)bb->src_row + bb->src_x * sizeof(uint16_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
bb->width, bb->height);
|
||||
}
|
||||
|
||||
static void dma2d_rgba8888_blend_mono4_first_col(const gl_bitblt_t* bb) {
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x;
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_alpha = src_ptr[0] >> 4;
|
||||
dst_ptr[0] = gl_color32_blend_a4(bb->src_fg,
|
||||
gl_color32_to_color(dst_ptr[0]), fg_alpha);
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dma2d_rgba8888_blend_mono4_last_col(const gl_bitblt_t* bb) {
|
||||
uint32_t* dst_ptr = (uint32_t*)bb->dst_row + (bb->dst_x + bb->width - 1);
|
||||
uint8_t* src_ptr = (uint8_t*)bb->src_row + (bb->src_x + bb->width - 1) / 2;
|
||||
|
||||
int height = bb->height;
|
||||
|
||||
while (height-- > 0) {
|
||||
uint8_t fg_alpha = src_ptr[0] & 0x0F;
|
||||
dst_ptr[0] = gl_color32_blend_a4(bb->src_fg,
|
||||
gl_color32_to_color(dst_ptr[0]), fg_alpha);
|
||||
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
|
||||
src_ptr += bb->src_stride / sizeof(*src_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgba8888_blend_mono4(const gl_bitblt_t* params) {
|
||||
dma2d_wait();
|
||||
|
||||
gl_bitblt_t bb_copy = *params;
|
||||
gl_bitblt_t* bb = &bb_copy;
|
||||
|
||||
if (bb->src_x & 1) {
|
||||
// First column of mono4 bitmap is odd
|
||||
// Use the CPU to draw the first column
|
||||
dma2d_rgba8888_blend_mono4_first_col(bb);
|
||||
bb->dst_x += 1;
|
||||
bb->src_x += 1;
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0 && bb->width & 1) {
|
||||
// The width is odd
|
||||
// Use the CPU to draw the last column
|
||||
dma2d_rgba8888_blend_mono4_last_col(bb);
|
||||
bb->width -= 1;
|
||||
}
|
||||
|
||||
if (bb->width > 0) {
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_BLEND;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_A4;
|
||||
dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = gl_color_to_color32(bb->src_fg);
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||||
dma2d_handle.LayerCfg[0].InputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[0].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[0].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 0);
|
||||
|
||||
HAL_DMA2D_BlendingStart(
|
||||
&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2,
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width,
|
||||
bb->height);
|
||||
}
|
||||
}
|
||||
|
||||
void dma2d_rgba8888_copy_rgba8888(const gl_bitblt_t* bb) {
|
||||
dma2d_wait();
|
||||
|
||||
dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
dma2d_handle.Init.Mode = DMA2D_M2M_PFC;
|
||||
dma2d_handle.Init.OutputOffset =
|
||||
bb->dst_stride / sizeof(uint32_t) - bb->width;
|
||||
HAL_DMA2D_Init(&dma2d_handle);
|
||||
|
||||
dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||||
dma2d_handle.LayerCfg[1].InputOffset =
|
||||
bb->src_stride / sizeof(uint32_t) - bb->width;
|
||||
dma2d_handle.LayerCfg[1].AlphaMode = 0;
|
||||
dma2d_handle.LayerCfg[1].InputAlpha = 0;
|
||||
HAL_DMA2D_ConfigLayer(&dma2d_handle, 1);
|
||||
|
||||
HAL_DMA2D_Start(&dma2d_handle,
|
||||
(uint32_t)bb->src_row + bb->src_x * sizeof(uint32_t),
|
||||
(uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t),
|
||||
bb->width, bb->height);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include "secret.h"
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_draw.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
|
||||
|
@ -260,8 +260,8 @@ uint32_t touch_read(void) {
|
||||
// first touch) (tested with FT6206)
|
||||
const uint32_t event_flag = touch_data[3] & 0xC0;
|
||||
if (touch_data[1] == GESTURE_NO_GESTURE) {
|
||||
xy = TRANSFORM_TOUCH_COORDS((X_POS_MSB << 8) | X_POS_LSB,
|
||||
(Y_POS_MSB << 8) | Y_POS_LSB);
|
||||
xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB,
|
||||
(Y_POS_MSB << 8) | Y_POS_LSB);
|
||||
if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) {
|
||||
touching = 1;
|
||||
return TOUCH_START | xy;
|
||||
|
1
core/embed/trezorhal/stm32u5/display/st-7789
Symbolic link
1
core/embed/trezorhal/stm32u5/display/st-7789
Symbolic link
@ -0,0 +1 @@
|
||||
../../stm32f4/display/st-7789
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "display_internal.h"
|
||||
#include "xdisplay.h"
|
||||
|
||||
#if (DISPLAY_RESX != 240) || (DISPLAY_RESY != 240)
|
||||
#error "Incompatible display resolution"
|
||||
#endif
|
||||
|
||||
// Display driver context.
|
||||
typedef struct {
|
||||
// Current display orientation (0, 90, 180, 270)
|
||||
int orientation_angle;
|
||||
// Current backlight level ranging from 0 to 255
|
||||
int backlight_level;
|
||||
} display_driver_t;
|
||||
|
||||
// Display driver instance
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
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);
|
||||
|
||||
// Clear framebuffers
|
||||
memset(physical_frame_buffer_0, 0x00, PHYSICAL_FRAME_BUFFER_SIZE);
|
||||
memset(physical_frame_buffer_1, 0x00, PHYSICAL_FRAME_BUFFER_SIZE);
|
||||
|
||||
BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT);
|
||||
BSP_LCD_SetBrightness(0, 100);
|
||||
BSP_LCD_DisplayOn(0);
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
BSP_LCD_Reinit(0);
|
||||
if (current_frame_buffer == 0) {
|
||||
BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S);
|
||||
} else {
|
||||
BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S);
|
||||
}
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
// Not used and intentionally left empty
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
// Just emulation, not doing anything
|
||||
drv->backlight_level = level;
|
||||
return level;
|
||||
}
|
||||
|
||||
int display_get_backlight(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (angle == 0 || angle == 90 || angle == 180 || angle == 270) {
|
||||
// Just emulation, not doing anything
|
||||
drv->orientation_angle = angle;
|
||||
}
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
void display_set_compatible_settings() {}
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_fb_info_t fb = display_get_frame_buffer();
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y);
|
||||
bb_new.dst_stride = fb.stride;
|
||||
|
||||
gl_rgba8888_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_rgb565(const gl_bitblt_t *bb) {
|
||||
display_fb_info_t fb = display_get_frame_buffer();
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y);
|
||||
bb_new.dst_stride = fb.stride;
|
||||
|
||||
gl_rgba8888_copy_rgb565(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb) {
|
||||
display_fb_info_t fb = display_get_frame_buffer();
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y);
|
||||
bb_new.dst_stride = fb.stride;
|
||||
|
||||
gl_rgba8888_copy_mono1p(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono4(const gl_bitblt_t *bb) {
|
||||
display_fb_info_t fb = display_get_frame_buffer();
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y);
|
||||
bb_new.dst_stride = fb.stride;
|
||||
|
||||
gl_rgba8888_copy_mono4(&bb_new);
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include <xdisplay.h>
|
||||
#include "display_internal.h"
|
||||
|
||||
// Physical frame buffers in internal SRAM memory
|
||||
__attribute__((section(".fb1")))
|
||||
ALIGN_32BYTES(uint32_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]);
|
||||
|
||||
__attribute__((section(".fb2")))
|
||||
ALIGN_32BYTES(uint32_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]);
|
||||
|
||||
// The current frame buffer selector at fixed memory address
|
||||
// It's shared between bootloaders and the firmware
|
||||
__attribute__((section(".framebuffer_select"))) uint32_t current_frame_buffer =
|
||||
0;
|
||||
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
uintptr_t addr;
|
||||
|
||||
if (current_frame_buffer == 0) {
|
||||
addr = GFXMMU_VIRTUAL_BUFFER1_BASE_S;
|
||||
} else {
|
||||
addr = GFXMMU_VIRTUAL_BUFFER0_BASE_S;
|
||||
}
|
||||
|
||||
uint32_t fb_stride = FRAME_BUFFER_PIXELS_PER_LINE * sizeof(uint32_t);
|
||||
|
||||
// We do not utilize whole area of the display
|
||||
// (discovery kit display is 480x480 and we need just 240x240)
|
||||
addr += (480 - DISPLAY_RESY) / 2 * sizeof(uint32_t);
|
||||
addr += (480 - DISPLAY_RESX) / 2 * fb_stride;
|
||||
|
||||
display_fb_info_t fb = {
|
||||
.ptr = (void *)addr,
|
||||
.stride = fb_stride,
|
||||
};
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
void display_refresh(void) {
|
||||
if (current_frame_buffer == 0) {
|
||||
current_frame_buffer = 1;
|
||||
BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S);
|
||||
memcpy(physical_frame_buffer_0, physical_frame_buffer_1,
|
||||
sizeof(physical_frame_buffer_0));
|
||||
} else {
|
||||
current_frame_buffer = 0;
|
||||
BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S);
|
||||
memcpy(physical_frame_buffer_1, physical_frame_buffer_0,
|
||||
sizeof(physical_frame_buffer_1));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZOR_HAL_DISPLAY_INTERNAL_H
|
||||
#define TREZOR_HAL_DISPLAY_INTERNAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Size of the physical frame buffer in bytes
|
||||
//
|
||||
// It's smaller than size of the virtual frame buffer
|
||||
// due to used GFXMMU settings
|
||||
#define PHYSICAL_FRAME_BUFFER_SIZE 184320
|
||||
|
||||
// Pitch (in pixels) of the virtual frame buffer
|
||||
#define FRAME_BUFFER_PIXELS_PER_LINE 768
|
||||
|
||||
// Physical frame buffers in internal SRAM memory
|
||||
//
|
||||
// Both frame buffers layes in the fixed addresses that
|
||||
// are shared between bootloaders and the firmware.
|
||||
extern uint32_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE];
|
||||
extern uint32_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE];
|
||||
|
||||
// The current frame buffer selector at fixed memory address
|
||||
//
|
||||
// The variable address is shared between bootloaders and the firmware
|
||||
extern uint32_t current_frame_buffer;
|
||||
|
||||
// LCD orientations
|
||||
#define LCD_ORIENTATION_PORTRAIT 0U
|
||||
#define LCD_ORIENTATION_LANDSCAPE 1U
|
||||
#define LCD_ORIENTATION_PORTRAIT_ROT180 2U
|
||||
#define LCD_ORIENTATION_LANDSCAPE_ROT180 3U
|
||||
|
||||
int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation);
|
||||
int32_t BSP_LCD_Reinit(uint32_t Instance);
|
||||
int32_t BSP_LCD_SetBrightness(uint32_t Instance, uint32_t Brightness);
|
||||
int32_t BSP_LCD_DisplayOn(uint32_t Instance);
|
||||
int32_t BSP_LCD_SetFrameBuffer(uint32_t Instance, uint32_t fb_addr);
|
||||
|
||||
#endif // TREZOR_HAL_DISPLAY_INTERNAL_H
|
File diff suppressed because it is too large
Load Diff
1
core/embed/trezorhal/stm32u5/display/vg-2864
Symbolic link
1
core/embed/trezorhal/stm32u5/display/vg-2864
Symbolic link
@ -0,0 +1 @@
|
||||
../../stm32f4/display/vg-2864
|
@ -3,10 +3,6 @@
|
||||
|
||||
#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
|
||||
|
1
core/embed/trezorhal/stm32u5/dma2d_bitblt.c
Symbolic link
1
core/embed/trezorhal/stm32u5/dma2d_bitblt.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/dma2d_bitblt.c
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "display-unix.h"
|
||||
#include "display_interface.h"
|
||||
#include "display.h"
|
||||
#include "profile.h"
|
||||
|
||||
#define EMULATOR_BORDER 16
|
||||
@ -354,3 +354,5 @@ void display_clear_save(void) {
|
||||
uint8_t *display_get_wr_addr(void) { return (uint8_t *)DISPLAY_DATA_ADDRESS; }
|
||||
|
||||
void display_finish_actions(void) {}
|
||||
|
||||
void display_reinit(void) {}
|
||||
|
461
core/embed/trezorhal/unix/display_driver.c
Normal file
461
core/embed/trezorhal/unix/display_driver.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <xdisplay.h>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "profile.h"
|
||||
|
||||
#define EMULATOR_BORDER 16
|
||||
|
||||
#if defined TREZOR_MODEL_T
|
||||
|
||||
#ifdef TREZOR_EMULATOR_RASPI
|
||||
#define WINDOW_WIDTH 480
|
||||
#define WINDOW_HEIGHT 320
|
||||
#define TOUCH_OFFSET_X 110
|
||||
#define TOUCH_OFFSET_Y 40
|
||||
#else
|
||||
#define WINDOW_WIDTH 400
|
||||
#define WINDOW_HEIGHT 600
|
||||
#define TOUCH_OFFSET_X 80
|
||||
#define TOUCH_OFFSET_Y 110
|
||||
#endif
|
||||
|
||||
#elif defined TREZOR_MODEL_1
|
||||
|
||||
#define WINDOW_WIDTH 200
|
||||
#define WINDOW_HEIGHT 340
|
||||
#define TOUCH_OFFSET_X 36
|
||||
#define TOUCH_OFFSET_Y 92
|
||||
|
||||
#elif defined TREZOR_MODEL_R
|
||||
|
||||
#define WINDOW_WIDTH 193
|
||||
#define WINDOW_HEIGHT 339
|
||||
#define TOUCH_OFFSET_X 32
|
||||
#define TOUCH_OFFSET_Y 84
|
||||
|
||||
#elif defined TREZOR_MODEL_T3T1
|
||||
|
||||
#define WINDOW_WIDTH 400
|
||||
#define WINDOW_HEIGHT 600
|
||||
#define TOUCH_OFFSET_X 80
|
||||
#define TOUCH_OFFSET_Y 110
|
||||
|
||||
#else
|
||||
#error Unknown Trezor model
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// Current display orientation (0 or 180)
|
||||
int orientation_angle;
|
||||
// Current backlight level ranging from 0 to 255
|
||||
int backlight_level;
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Surface *buffer;
|
||||
SDL_Texture *texture;
|
||||
SDL_Texture *background;
|
||||
SDL_Surface *prev_saved;
|
||||
|
||||
#if DISPLAY_MONO
|
||||
// SDL2 does not support 8bit surface/texture
|
||||
// and we have to simulate it
|
||||
uint8_t mono_framebuf[DISPLAY_RESX * DISPLAY_RESY];
|
||||
#endif
|
||||
|
||||
} display_driver_t;
|
||||
|
||||
static display_driver_t g_display_driver;
|
||||
|
||||
//!@# TODO get rid of this...
|
||||
int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY;
|
||||
int sdl_touch_offset_x, sdl_touch_offset_y;
|
||||
|
||||
void display_deinit(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
SDL_FreeSurface(drv->prev_saved);
|
||||
SDL_FreeSurface(drv->buffer);
|
||||
if (drv->background != NULL) {
|
||||
SDL_DestroyTexture(drv->background);
|
||||
}
|
||||
if (drv->texture != NULL) {
|
||||
SDL_DestroyTexture(drv->texture);
|
||||
}
|
||||
if (drv->renderer != NULL) {
|
||||
SDL_DestroyRenderer(drv->renderer);
|
||||
}
|
||||
if (drv->window != NULL) {
|
||||
SDL_DestroyWindow(drv->window);
|
||||
}
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void display_init(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
printf("%s\n", SDL_GetError());
|
||||
ensure(secfalse, "SDL_Init error");
|
||||
}
|
||||
atexit(display_deinit);
|
||||
|
||||
char *window_title = NULL;
|
||||
char *window_title_alloc = NULL;
|
||||
if (asprintf(&window_title_alloc, "Trezor^emu: %s", profile_name()) > 0) {
|
||||
window_title = window_title_alloc;
|
||||
} else {
|
||||
window_title = "Trezor^emu";
|
||||
window_title_alloc = NULL;
|
||||
}
|
||||
|
||||
drv->window =
|
||||
SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT,
|
||||
#ifdef TREZOR_EMULATOR_RASPI
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN
|
||||
#else
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI
|
||||
#endif
|
||||
);
|
||||
free(window_title_alloc);
|
||||
if (!drv->window) {
|
||||
printf("%s\n", SDL_GetError());
|
||||
ensure(secfalse, "SDL_CreateWindow error");
|
||||
}
|
||||
drv->renderer = SDL_CreateRenderer(drv->window, -1, SDL_RENDERER_SOFTWARE);
|
||||
if (!drv->renderer) {
|
||||
printf("%s\n", SDL_GetError());
|
||||
SDL_DestroyWindow(drv->window);
|
||||
ensure(secfalse, "SDL_CreateRenderer error");
|
||||
}
|
||||
SDL_SetRenderDrawColor(drv->renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(drv->renderer);
|
||||
|
||||
drv->buffer = SDL_CreateRGBSurface(0, DISPLAY_RESX, DISPLAY_RESY, 16, 0xF800,
|
||||
0x07E0, 0x001F, 0x0000);
|
||||
drv->texture = SDL_CreateTexture(drv->renderer, SDL_PIXELFORMAT_RGB565,
|
||||
SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX,
|
||||
DISPLAY_RESY);
|
||||
SDL_SetTextureBlendMode(drv->texture, SDL_BLENDMODE_BLEND);
|
||||
#ifdef __APPLE__
|
||||
// macOS Mojave SDL black screen workaround
|
||||
SDL_PumpEvents();
|
||||
SDL_SetWindowSize(drv->window, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
#endif
|
||||
#ifdef TREZOR_EMULATOR_RASPI
|
||||
#include "background_raspi.h"
|
||||
drv->background = IMG_LoadTexture_RW(
|
||||
drv->renderer,
|
||||
SDL_RWFromMem(background_raspi_jpg, background_raspi_jpg_len), 0);
|
||||
#else
|
||||
#if defined TREZOR_MODEL_T
|
||||
#include "background_T.h"
|
||||
drv->background = IMG_LoadTexture_RW(
|
||||
drv->renderer, SDL_RWFromMem(background_T_jpg, background_T_jpg_len), 0);
|
||||
#elif defined TREZOR_MODEL_1
|
||||
#include "background_1.h"
|
||||
drv->background = IMG_LoadTexture_RW(
|
||||
drv->renderer, SDL_RWFromMem(background_1_jpg, background_1_jpg_len), 0);
|
||||
#elif defined TREZOR_MODEL_R
|
||||
#include "background_T2B1.h"
|
||||
drv->background = IMG_LoadTexture_RW(
|
||||
drv->renderer,
|
||||
SDL_RWFromMem(background_T2B1_png, background_T2B1_png_len), 0);
|
||||
#endif
|
||||
#endif
|
||||
if (drv->background) {
|
||||
SDL_SetTextureBlendMode(drv->background, SDL_BLENDMODE_NONE);
|
||||
sdl_touch_offset_x = TOUCH_OFFSET_X;
|
||||
sdl_touch_offset_y = TOUCH_OFFSET_Y;
|
||||
} else {
|
||||
SDL_SetWindowSize(drv->window, DISPLAY_RESX + 2 * EMULATOR_BORDER,
|
||||
DISPLAY_RESY + 2 * EMULATOR_BORDER);
|
||||
sdl_touch_offset_x = EMULATOR_BORDER;
|
||||
sdl_touch_offset_y = EMULATOR_BORDER;
|
||||
}
|
||||
#if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
|
||||
// T1 and TR do not have backlight capabilities in hardware, so
|
||||
// setting its value here for emulator to avoid
|
||||
// calling any `set_backlight` functions
|
||||
drv->backlight_level = 255;
|
||||
#else
|
||||
drv->backlight_level = 0;
|
||||
#endif
|
||||
#ifdef TREZOR_EMULATOR_RASPI
|
||||
drv->orientation_angle = 270;
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#else
|
||||
drv->orientation_angle = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_reinit(void) {
|
||||
// not used
|
||||
}
|
||||
|
||||
void display_finish_actions(void) {
|
||||
// not used
|
||||
}
|
||||
|
||||
int display_set_backlight(int level) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
#if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
|
||||
level = 255;
|
||||
#endif
|
||||
|
||||
if (drv->backlight_level != level && level >= 0 && level <= 255) {
|
||||
drv->backlight_level = level;
|
||||
display_refresh();
|
||||
}
|
||||
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_get_backlight(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
return drv->backlight_level;
|
||||
}
|
||||
|
||||
int display_set_orientation(int angle) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
if (angle != drv->orientation_angle) {
|
||||
#if defined TREZOR_MODEL_T || defined TREZOR_MODEL_T3T1
|
||||
if (angle == 0 || angle == 90 || angle == 180 || angle == 270) {
|
||||
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
|
||||
if (angle == 0 || angle == 180) {
|
||||
#else
|
||||
#error Unknown Trezor model
|
||||
#endif
|
||||
drv->orientation_angle = angle;
|
||||
display_refresh();
|
||||
}
|
||||
}
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
int display_get_orientation(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
return drv->orientation_angle;
|
||||
}
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
display_fb_info_t display_get_frame_buffer(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
#ifdef DISPLAY_MONO
|
||||
display_fb_info_t fb = {
|
||||
.ptr = drv->mono_framebuf,
|
||||
.stride = DISPLAY_RESX,
|
||||
};
|
||||
#else
|
||||
display_fb_info_t fb = {
|
||||
.ptr = drv->buffer->pixels,
|
||||
.stride = DISPLAY_RESX * sizeof(uint16_t),
|
||||
};
|
||||
#endif
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
#else // XFRAMEBUFFER
|
||||
|
||||
void display_wait_for_sync(void) {
|
||||
// not used
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_MONO
|
||||
// Copies driver's monochromatic framebuffer into the RGB framebuffer used by
|
||||
// SDL
|
||||
static void copy_mono_framebuf(display_driver_t *drv) {
|
||||
for (int y = 0; y < DISPLAY_RESY; y++) {
|
||||
uint16_t *dst =
|
||||
(uint16_t *)((uint8_t *)drv->buffer->pixels + drv->buffer->pitch * y);
|
||||
uint8_t *src = &drv->mono_framebuf[y * DISPLAY_RESX];
|
||||
for (int x = 0; x < DISPLAY_RESX; x++) {
|
||||
uint8_t lum = src[x] > 40 ? 255 : 0;
|
||||
dst[x] = gl_color16_rgb(lum, lum, lum);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void display_refresh(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (!drv->renderer) {
|
||||
display_init();
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_MONO
|
||||
copy_mono_framebuf(drv);
|
||||
#endif
|
||||
|
||||
if (drv->background) {
|
||||
const SDL_Rect r = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
SDL_RenderCopy(drv->renderer, drv->background, NULL, &r);
|
||||
} else {
|
||||
SDL_RenderClear(drv->renderer);
|
||||
}
|
||||
// Show the display buffer
|
||||
SDL_UpdateTexture(drv->texture, NULL, drv->buffer->pixels,
|
||||
drv->buffer->pitch);
|
||||
#define BACKLIGHT_NORMAL 150
|
||||
SDL_SetTextureAlphaMod(
|
||||
drv->texture, MIN(255, 255 * drv->backlight_level / BACKLIGHT_NORMAL));
|
||||
if (drv->background) {
|
||||
const SDL_Rect r = {TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX,
|
||||
DISPLAY_RESY};
|
||||
SDL_RenderCopyEx(drv->renderer, drv->texture, NULL, &r,
|
||||
drv->orientation_angle, NULL, 0);
|
||||
} else {
|
||||
const SDL_Rect r = {EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX,
|
||||
DISPLAY_RESY};
|
||||
SDL_RenderCopyEx(drv->renderer, drv->texture, NULL, &r,
|
||||
drv->orientation_angle, NULL, 0);
|
||||
}
|
||||
SDL_RenderPresent(drv->renderer);
|
||||
}
|
||||
|
||||
void display_set_compatible_settings(void) {
|
||||
// not used
|
||||
}
|
||||
|
||||
#ifndef DISPLAY_MONO
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row =
|
||||
(uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y);
|
||||
bb_new.dst_stride = drv->buffer->pitch;
|
||||
|
||||
gl_rgb565_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_rgb565(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row =
|
||||
(uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y);
|
||||
bb_new.dst_stride = drv->buffer->pitch;
|
||||
|
||||
gl_rgb565_copy_rgb565(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row =
|
||||
(uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
gl_rgb565_copy_mono1p(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono4(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row =
|
||||
(uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y);
|
||||
bb_new.dst_stride = drv->buffer->pitch;
|
||||
|
||||
gl_rgb565_copy_mono4(&bb_new);
|
||||
}
|
||||
|
||||
#else // DISPLAY_MONO
|
||||
|
||||
void display_fill(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
gl_mono8_fill(&bb_new);
|
||||
}
|
||||
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
gl_bitblt_t bb_new = *bb;
|
||||
bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y);
|
||||
bb_new.dst_stride = DISPLAY_RESX;
|
||||
|
||||
gl_mono8_copy_mono1p(&bb_new);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *display_save(const char *prefix) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
if (!drv->renderer) {
|
||||
display_init();
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_MONO
|
||||
copy_mono_framebuf(drv);
|
||||
#endif
|
||||
|
||||
static int count;
|
||||
static char filename[256];
|
||||
// take a cropped view of the screen contents
|
||||
const SDL_Rect rect = {0, 0, DISPLAY_RESX, DISPLAY_RESY};
|
||||
SDL_Surface *crop = SDL_CreateRGBSurface(
|
||||
drv->buffer->flags, rect.w, rect.h, drv->buffer->format->BitsPerPixel,
|
||||
drv->buffer->format->Rmask, drv->buffer->format->Gmask,
|
||||
drv->buffer->format->Bmask, drv->buffer->format->Amask);
|
||||
SDL_BlitSurface(drv->buffer, &rect, crop, NULL);
|
||||
// compare with previous screen, skip if equal
|
||||
if (drv->prev_saved != NULL) {
|
||||
if (memcmp(drv->prev_saved->pixels, crop->pixels, crop->pitch * crop->h) ==
|
||||
0) {
|
||||
SDL_FreeSurface(crop);
|
||||
return filename;
|
||||
}
|
||||
SDL_FreeSurface(drv->prev_saved);
|
||||
}
|
||||
// save to png
|
||||
snprintf(filename, sizeof(filename), "%s%08d.png", prefix, count++);
|
||||
IMG_SavePNG(crop, filename);
|
||||
drv->prev_saved = crop;
|
||||
return filename;
|
||||
}
|
||||
|
||||
void display_clear_save(void) {
|
||||
display_driver_t *drv = &g_display_driver;
|
||||
|
||||
SDL_FreeSurface(drv->prev_saved);
|
||||
drv->prev_saved = NULL;
|
||||
}
|
22
core/embed/trezorhal/unix/dma2d_bitblt.c
Normal file
22
core/embed/trezorhal/unix/dma2d_bitblt.c
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dma2d_bitblt.h"
|
||||
|
||||
void dma2d_wait(void) {}
|
152
core/embed/trezorhal/xdisplay.h
Normal file
152
core/embed/trezorhal/xdisplay.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_XDISPLAY_H
|
||||
#define TREZORHAL_XDISPLAY_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "gl_bitblt.h"
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
// This is a universal API for controlling different types of display
|
||||
// controllers.
|
||||
//
|
||||
// Currently, following displays displays are supported
|
||||
//
|
||||
// VG-2864KSWEG01 - OLED Mono / 128x64 pixels / SPI
|
||||
// - Model T1B1 / Model T2B1
|
||||
//
|
||||
// UG-2828SWIG01 - OLED Mono / 128x128 pixels / Parallel
|
||||
// - Early revisions of T2B1
|
||||
//
|
||||
// ST7789V - TFT RGB / 240x240 pixels / Parallel
|
||||
// - Model T2T1 / Model T3T1
|
||||
//
|
||||
// ILI9341 - TFT RGB / 320x240 pixels / Parallel / LTDC + SPI
|
||||
// - STM32F429I-DISC1 Discovery Board
|
||||
//
|
||||
// MIPI -
|
||||
// - STM32U5A9J-DK Discovery Board
|
||||
|
||||
// Fully initializes the display controller.
|
||||
void display_init(void);
|
||||
|
||||
// Called in application or bootloader to reinitialize an already initialized
|
||||
// display controller without any distrubing visible effect (blinking, etc.).
|
||||
void display_reinit(void);
|
||||
|
||||
// Waits for any backround operations (such as DMA copying) and returns.
|
||||
//
|
||||
// The function provides a barrier when jumping between
|
||||
// boardloader/bootloader and firmware.
|
||||
void display_finish_actions(void);
|
||||
|
||||
// Sets display backlight level ranging from 0 (off)..255 (maximum).
|
||||
//
|
||||
// The default backligt level is 0. Without settings it
|
||||
// to some higher value the displayed pixels are not visible.
|
||||
// Beware that his also applies to the emulator.
|
||||
//
|
||||
// Returns the set level (usually the same value or the
|
||||
// closest value to the `level` argument)
|
||||
int display_set_backlight(int level);
|
||||
|
||||
// Gets current display level ranging from 0 (off)..255 (maximum).
|
||||
int display_get_backlight(void);
|
||||
|
||||
// Sets the display orientation.
|
||||
//
|
||||
// May accept one of following values: 0, 90, 180, 270
|
||||
// but accepted values are model-dependent.
|
||||
// Default display orientation is always 0.
|
||||
//
|
||||
// Returns the set orientation
|
||||
int display_set_orientation(int angle);
|
||||
|
||||
// Gets the display's current orientation
|
||||
//
|
||||
// Returned value is one of 0, 90, 180, 270.
|
||||
int display_get_orientation(void);
|
||||
|
||||
#ifdef XFRAMEBUFFER
|
||||
|
||||
typedef struct {
|
||||
// Pointer to the top-left pixel
|
||||
void *ptr;
|
||||
// Stride in bytes
|
||||
size_t stride;
|
||||
|
||||
} display_fb_info_t;
|
||||
|
||||
// Provides pointer to the inactive (writeable) framebuffer.
|
||||
//
|
||||
// If framebuffer is not available yet due to display refreshing etc.,
|
||||
// the function may block until the buffer is ready to write.
|
||||
display_fb_info_t display_get_frame_buffer(void);
|
||||
|
||||
#else // XFRAMEBUFFER
|
||||
|
||||
// Waits for the vertical synchronization pulse.
|
||||
//
|
||||
// Used for synchronization with the display refresh cycle
|
||||
// to achieve tearless UX if possible when not using a frame buffer.
|
||||
void display_wait_for_sync(void);
|
||||
#endif
|
||||
|
||||
// Swaps the frame buffers
|
||||
//
|
||||
// The function waits for vertical synchronization and
|
||||
// swaps the active (currently displayed) and the inactive frame buffers.
|
||||
void display_refresh(void);
|
||||
|
||||
// Sets display to the mode compatible with the legacy bootloader code.
|
||||
//
|
||||
// This is used when switching between the firmware and the bootloader.
|
||||
void display_set_compatible_settings(void);
|
||||
|
||||
// Following function define display's bitblt interface.
|
||||
//
|
||||
// These functions draw directly to to display or to the
|
||||
// currently inactive framebuffer.
|
||||
//
|
||||
// bb->dst_row and bb->dst_stride must be 0
|
||||
|
||||
// Fills a rectangle with a solid color
|
||||
void display_fill(const gl_bitblt_t *bb);
|
||||
// Copies an RGB565 bitmap
|
||||
void display_copy_rgb565(const gl_bitblt_t *bb);
|
||||
// Copies a MONO4 bitmap
|
||||
void display_copy_mono4(const gl_bitblt_t *bb);
|
||||
// Copies a MONO1P bitmap
|
||||
void display_copy_mono1p(const gl_bitblt_t *bb);
|
||||
|
||||
#ifdef TREZOR_EMULATOR
|
||||
// Save the screen content to a file.
|
||||
// The function is available only on the emulator.
|
||||
const char *display_save(const char *prefix);
|
||||
void display_clear_save(void);
|
||||
#endif
|
||||
|
||||
// Adds some declarations needed to compile with the legacy code
|
||||
// (will be removed with the display legacy code)
|
||||
#include "xdisplay_legacy.h"
|
||||
|
||||
#endif // TREZORHAL_XDISPLAY_H
|
43
core/embed/trezorhal/xdisplay_legacy.c
Normal file
43
core/embed/trezorhal/xdisplay_legacy.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "xdisplay_legacy.h"
|
||||
#include "xdisplay.h"
|
||||
|
||||
// This code emulates the legacy display interface and will be
|
||||
// removed after final cleanup of display drivers when the legacy code
|
||||
// is removed.
|
||||
|
||||
int display_orientation(int angle) {
|
||||
if (angle >= 0) {
|
||||
return display_set_orientation(angle);
|
||||
} else {
|
||||
return display_get_orientation();
|
||||
}
|
||||
}
|
||||
|
||||
int display_backlight(int level) {
|
||||
if (level >= 0) {
|
||||
return display_set_backlight(level);
|
||||
} else {
|
||||
return display_get_backlight();
|
||||
}
|
||||
}
|
||||
|
||||
void display_sync(void) {}
|
56
core/embed/trezorhal/xdisplay_legacy.h
Normal file
56
core/embed/trezorhal/xdisplay_legacy.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_DISPLAY_LEGACY_H
|
||||
#define TREZORHAL_DISPLAY_LEGACY_H
|
||||
|
||||
#include <buffers.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// These declarationscode emulates will be removed after the
|
||||
// final cleanup of display drivers. They are here just to simplify
|
||||
// integration with the legacy code.
|
||||
//
|
||||
// Most of these function are not called when NEW_RENDERING=1
|
||||
// and they are only needed to for succesfully code compilation
|
||||
|
||||
#define DISPLAY_FRAMEBUFFER_WIDTH 768
|
||||
#define DISPLAY_FRAMEBUFFER_HEIGHT 480
|
||||
#define DISPLAY_FRAMEBUFFER_OFFSET_X 0
|
||||
#define DISPLAY_FRAMEBUFFER_OFFSET_Y 0
|
||||
|
||||
int display_orientation(int angle);
|
||||
int display_backlight(int level);
|
||||
void display_refresh(void);
|
||||
void display_shift_window(uint16_t pixels);
|
||||
uint16_t display_get_window_offset(void);
|
||||
void display_pixeldata_dirty(void);
|
||||
uint8_t* display_get_wr_addr(void);
|
||||
void display_sync(void);
|
||||
void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void display_pixeldata(uint16_t c);
|
||||
uint32_t* display_get_fb_addr(void);
|
||||
|
||||
void display_clear(void);
|
||||
void display_text_render_buffer(const char* text, int textlen, int font,
|
||||
buffer_text_t* buffer, int text_offset);
|
||||
|
||||
#define PIXELDATA(c) display_pixeldata(c)
|
||||
|
||||
#endif // TREZORHAL_DISPLAY_LEGACY_H
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "extmod/misc.h"
|
||||
#include "extmod/vfs_posix.h"
|
||||
#include "display.h"
|
||||
#include "flash.h"
|
||||
#include "flash_otp.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
@ -481,6 +482,8 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
pre_process_options(argc, argv);
|
||||
|
||||
display_init();
|
||||
|
||||
// Map trezor.flash to memory.
|
||||
flash_init();
|
||||
flash_otp_init();
|
||||
|
@ -36,9 +36,20 @@ def configure(
|
||||
sources += [
|
||||
"embed/models/model_D001_layout.c",
|
||||
]
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
sources += ["embed/trezorhal/stm32f4/displays/ili9341_spi.c"]
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
sources += [
|
||||
"embed/trezorhal/xdisplay_legacy.c",
|
||||
"embed/trezorhal/stm32f4/display/stm32f429i-disc1/display_driver.c",
|
||||
"embed/trezorhal/stm32f4/display/stm32f429i-disc1/display_ltdc.c",
|
||||
"embed/trezorhal/stm32f4/display/stm32f429i-disc1/ili9341_spi.c",
|
||||
]
|
||||
else:
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
sources += ["embed/trezorhal/stm32f4/displays/ili9341_spi.c"]
|
||||
|
||||
sources += ["embed/trezorhal/stm32f4/dma2d.c"]
|
||||
sources += ["embed/trezorhal/stm32f4/dma2d_bitblt.c"]
|
||||
sources += [
|
||||
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c"
|
||||
]
|
||||
@ -51,6 +62,11 @@ def configure(
|
||||
features_available.append("dma2d")
|
||||
features_available.append("framebuffer")
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
defines += ["XFRAMEBUFFER"]
|
||||
features_available.append("xframebuffer")
|
||||
features_available.append("display_rgb565")
|
||||
|
||||
if "input" in features_wanted:
|
||||
sources += ["embed/trezorhal/stm32f4/i2c.c"]
|
||||
sources += ["embed/trezorhal/stm32f4/touch/stmpe811.c"]
|
||||
@ -71,4 +87,10 @@ def configure(
|
||||
env.get("ENV")["TREZOR_BOARD"] = board
|
||||
env.get("ENV")["MCU_TYPE"] = mcu
|
||||
|
||||
rust_defs = env.get("ENV")["RUST_INCLUDES"]
|
||||
rust_defs += "-DFRAMEBUFFER;"
|
||||
if "new_rendering" in features_wanted:
|
||||
rust_defs += "-DXFRAMEBUFFER;"
|
||||
env.get("ENV")["RUST_INCLUDES"] = rust_defs
|
||||
|
||||
return features_available
|
||||
|
@ -43,9 +43,18 @@ def configure(
|
||||
sources += [
|
||||
"embed/models/model_D002_layout.c",
|
||||
]
|
||||
sources += [
|
||||
f"embed/trezorhal/stm32u5/displays/{display}",
|
||||
]
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
sources += [
|
||||
"embed/trezorhal/xdisplay_legacy.c",
|
||||
"embed/trezorhal/stm32u5/display/stm32u5a9j-dk/display_driver.c",
|
||||
"embed/trezorhal/stm32u5/display/stm32u5a9j-dk/display_fb.c",
|
||||
"embed/trezorhal/stm32u5/display/stm32u5a9j-dk/display_ltdc_dsi.c",
|
||||
]
|
||||
else:
|
||||
sources += [
|
||||
f"embed/trezorhal/stm32u5/displays/{display}",
|
||||
]
|
||||
|
||||
if "input" in features_wanted:
|
||||
sources += [
|
||||
@ -85,11 +94,17 @@ def configure(
|
||||
defines += ["USE_DMA2D", "FRAMEBUFFER", "FRAMEBUFFER32BIT"]
|
||||
sources += [
|
||||
"embed/trezorhal/stm32u5/dma2d.c",
|
||||
"embed/trezorhal/stm32u5/dma2d_bitblt.c",
|
||||
]
|
||||
features_available.append("dma2d")
|
||||
features_available.append("framebuffer")
|
||||
features_available.append("framebuffer32bit")
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
defines += ["XFRAMEBUFFER"]
|
||||
features_available.append("xframebuffer")
|
||||
features_available.append("display_rgba8888")
|
||||
|
||||
env.get("ENV")["TREZOR_BOARD"] = board
|
||||
env.get("ENV")["MCU_TYPE"] = mcu
|
||||
env.get("ENV")["LINKER_SCRIPT"] = linker_script
|
||||
@ -97,4 +112,10 @@ def configure(
|
||||
defs = env.get("CPPDEFINES_IMPLICIT")
|
||||
defs += ["__ARM_FEATURE_CMSE=3"]
|
||||
|
||||
rust_defs = env.get("ENV")["RUST_INCLUDES"]
|
||||
rust_defs += "-DFRAMEBUFFER;"
|
||||
if "new_rendering" in features_wanted:
|
||||
rust_defs += "-DXFRAMEBUFFER;"
|
||||
env.get("ENV")["RUST_INCLUDES"] = rust_defs
|
||||
|
||||
return features_available
|
||||
|
@ -17,6 +17,11 @@ def configure(
|
||||
board = "trezor_r_v10.h"
|
||||
display = "vg-2864ksweg01.c"
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
defines += ["XFRAMEBUFFER"]
|
||||
features_available.append("xframebuffer")
|
||||
features_available.append("display_mono")
|
||||
|
||||
mcu = "STM32F427xx"
|
||||
|
||||
stm32f4_common_files(env, defines, sources, paths)
|
||||
@ -36,7 +41,12 @@ def configure(
|
||||
sources += [
|
||||
"embed/models/model_T2B1_layout.c",
|
||||
]
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
sources += ["embed/trezorhal/xdisplay_legacy.c"]
|
||||
sources += ["embed/trezorhal/stm32f4/display/vg-2864/display_driver.c"]
|
||||
else:
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
|
||||
sources += ["embed/trezorhal/stm32f4/i2c.c"]
|
||||
|
||||
@ -76,4 +86,9 @@ def configure(
|
||||
env.get("ENV")["TREZOR_BOARD"] = board
|
||||
env.get("ENV")["MCU_TYPE"] = mcu
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
rust_defs = env.get("ENV")["RUST_INCLUDES"]
|
||||
rust_defs += "-DXFRAMEBUFFER;"
|
||||
env.get("ENV")["RUST_INCLUDES"] = rust_defs
|
||||
|
||||
return features_available
|
||||
|
@ -17,6 +17,11 @@ def configure(
|
||||
board = "trezor_r_v3.h"
|
||||
display = "ug-2828tswig01.c"
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
defines += ["XFRAMEBUFFER"]
|
||||
features_available.append("xframebuffer")
|
||||
features_available.append("display_mono")
|
||||
|
||||
mcu = "STM32F427xx"
|
||||
|
||||
stm32f4_common_files(env, defines, sources, paths)
|
||||
@ -36,7 +41,12 @@ def configure(
|
||||
sources += [
|
||||
"embed/models/model_T2B1_layout.c",
|
||||
]
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
sources += ["embed/trezorhal/xdisplay_legacy.c"]
|
||||
sources += ["embed/trezorhal/stm32f4/display/ug-2828/display_driver.c"]
|
||||
else:
|
||||
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
|
||||
|
||||
if "input" in features_wanted:
|
||||
sources += ["embed/trezorhal/stm32f4/button.c"]
|
||||
@ -64,4 +74,9 @@ def configure(
|
||||
env.get("ENV")["TREZOR_BOARD"] = board
|
||||
env.get("ENV")["MCU_TYPE"] = mcu
|
||||
|
||||
if "new_rendering" in features_wanted:
|
||||
rust_defs = env.get("ENV")["RUST_INCLUDES"]
|
||||
rust_defs += "-DXFRAMEBUFFER;"
|
||||
env.get("ENV")["RUST_INCLUDES"] = rust_defs
|
||||
|
||||
return features_available
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user