1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-15 09:02:02 +00:00

feat(core): initial Model R display implementation with framebuffer

This commit is contained in:
tychovrahe 2022-04-25 12:05:19 +02:00 committed by matejcik
parent 936c84bac6
commit f7a3aad9bd
11 changed files with 357 additions and 5 deletions

View File

@ -0,0 +1 @@
Add basic Trezor Model R hardware support

View File

@ -48,6 +48,9 @@ SOURCE_MOD += [
'embed/extmod/modtrezorui/font_bitmap.c',
'embed/extmod/modtrezorui/font_roboto_regular_20.c',
'embed/extmod/modtrezorui/font_robotomono_regular_20.c',
'embed/extmod/modtrezorui/font_pixeloperator_bold_8.c',
'embed/extmod/modtrezorui/font_pixeloperator_regular_8.c',
'embed/extmod/modtrezorui/font_pixeloperatormono_regular_8.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
@ -108,7 +111,7 @@ SOURCE_TREZORHAL = [
'embed/trezorhal/vectortable.s',
]
if TREZOR_MODEL in ['1', 'R']:
if TREZOR_MODEL in ('1', 'R'):
SOURCE_TREZORHAL.append('embed/trezorhal/button.c')
if TREZOR_MODEL in ('T',):
SOURCE_TREZORHAL.append('embed/trezorhal/touch.c')

View File

@ -151,7 +151,7 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
SOURCE_MOD += [
'embed/extmod/modtrezorio/modtrezorio.c',
]
if TREZOR_MODEL in ("T",):
if TREZOR_MODEL in ('T',):
SOURCE_MOD += [
'embed/extmod/modtrezorio/ff.c',
'embed/extmod/modtrezorio/ffunicode.c',

View File

@ -32,6 +32,7 @@ SOURCE_MOD += [
'embed/extmod/modtrezorui/display.c',
'embed/extmod/modtrezorui/font_bitmap.c',
'embed/extmod/modtrezorui/font_roboto_bold_20.c',
'embed/extmod/modtrezorui/font_pixeloperator_bold_8.c',
'embed/extmod/modtrezorui/qr-code-generator/qrcodegen.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',

View File

@ -147,7 +147,7 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
SOURCE_MOD += [
'embed/extmod/modtrezorio/modtrezorio.c',
]
if TREZOR_MODEL in ("T",):
if TREZOR_MODEL in ('T',):
SOURCE_MOD += [
'embed/extmod/modtrezorio/ff.c',
'embed/extmod/modtrezorio/ffunicode.c',

View File

@ -0,0 +1 @@
Add basic Trezor Model R hardware support

View File

@ -0,0 +1 @@
Add basic Trezor Model R hardware support

View File

@ -0,0 +1 @@
Add basic Trezor Model R hardware support

View File

@ -0,0 +1,337 @@
/*
* 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
// FSMC/FMC Bank 1 - NOR/PSRAM 1
#define DISPLAY_MEMORY_BASE 0x60000000
#define DISPLAY_MEMORY_PIN 16
#define CMD(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE))) = (X))
#define ADDR \
(*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | \
(1 << DISPLAY_MEMORY_PIN)))))
#define DATA(X) (ADDR) = (X)
// noop on TR as we don't need to push data to display
#define PIXELDATA_DIRTY()
struct {
uint8_t RAM[DISPLAY_RESY / 8][DISPLAY_RESX];
uint32_t row;
uint32_t col;
uint32_t window_x0;
uint32_t window_x1;
uint32_t window_y0;
uint32_t window_y1;
} DISPLAY_STATE;
static void display_set_page_and_col(uint8_t page, uint8_t col) {
if (page < (DISPLAY_RESY / 8)) {
CMD(0xB0 | (page & 0xF));
if (col < DISPLAY_RESX) {
CMD(0x10 | ((col & 0x70) >> 4));
CMD(0x00 | (col & 0x0F));
} else {
// Reset column to start
CMD(0x10);
CMD(0x00);
}
}
}
void PIXELDATA(uint16_t c) {
uint8_t data = DISPLAY_STATE.RAM[DISPLAY_STATE.row / 8][DISPLAY_STATE.col];
uint8_t bit = 1 << (DISPLAY_STATE.row % 8);
// set to white if highest bits of all R, G, B values are set to 1
// bin(10000 100000 10000) = hex(0x8410)
// otherwise set to black
if (c & 0x8410) {
data |= bit;
} else {
data &= ~bit;
}
DISPLAY_STATE.RAM[DISPLAY_STATE.row / 8][DISPLAY_STATE.col] = data;
DATA(data);
DISPLAY_STATE.col++;
if (DISPLAY_STATE.col > DISPLAY_STATE.window_x1) {
// next line
DISPLAY_STATE.col = DISPLAY_STATE.window_x0;
DISPLAY_STATE.row++;
if (DISPLAY_STATE.row > DISPLAY_STATE.window_y1) {
// reached end of the window, go to start
DISPLAY_STATE.row = DISPLAY_STATE.window_y1;
}
// set display to start of next line, sets also page, even if it stays on
// the same one
display_set_page_and_col(DISPLAY_STATE.row / 8, DISPLAY_STATE.col);
}
}
static void display_reset_state(void) {
memset(DISPLAY_STATE.RAM, 0, sizeof(DISPLAY_STATE.RAM));
DISPLAY_STATE.row = 0;
DISPLAY_STATE.col = 0;
DISPLAY_STATE.window_x0 = 0;
DISPLAY_STATE.window_x1 = DISPLAY_RESX - 1;
DISPLAY_STATE.window_y0 = 0;
DISPLAY_STATE.window_y1 = DISPLAY_RESY - 1;
}
static void __attribute__((unused)) display_sleep(void) {
CMD(0xAE); // DISPOFF: Display Off
HAL_Delay(5);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET); // Vpp disable
}
static void display_unsleep(void) {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_SET); // Vpp enable
HAL_Delay(100); // 100 ms mandatory wait
CMD(0xAF); // Display ON
}
static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1,
uint16_t y1) {
if (x1 >= DISPLAY_RESX) {
x1 = DISPLAY_RESX - 1;
}
if (y1 >= DISPLAY_RESY) {
y1 = DISPLAY_RESY - 1;
}
if (x0 < DISPLAY_RESX && x1 < DISPLAY_RESX && x0 <= x1 && y0 < DISPLAY_RESY &&
y1 < DISPLAY_RESY && y0 <= y1) {
DISPLAY_STATE.window_x0 = x0;
DISPLAY_STATE.window_x1 = x1;
DISPLAY_STATE.window_y0 = y0;
DISPLAY_STATE.window_y1 = y1;
DISPLAY_STATE.row = y0;
DISPLAY_STATE.col = x0;
display_set_page_and_col(DISPLAY_STATE.row / 8, DISPLAY_STATE.col);
}
}
static void display_set_orientation(int degrees) {
if (degrees == 0) {
// Set Segment Re-map: (A0H - A1H)
CMD(0xA1);
// Set COM Output Scan Direction
CMD(0xC8);
}
if (degrees == 180) {
// Set Segment Re-map: (A0H - A1H)
CMD(0xA0);
// Set COM Output Scan Direction
CMD(0xC0);
}
}
static void display_set_backlight(int val) {
// Set Contrast Control Register: (Double Bytes Command)
CMD(0x81);
CMD(val & 0xFF);
}
static void send_init_seq_SH1107(void) {
// Display OFF
CMD(0xAE);
// Set Display Clock Divide Ratio/Oscillator Frequency: (Double Bytes Command)
CMD(0xD5);
// Divide ratio 0, Oscillator Frequency +0%
CMD(0x50);
// Set Memory Addressing Mode - page addressing mode
CMD(0x20);
// Set Contrast Control Register: (Double Bytes Command)
CMD(0x81);
CMD(0x8F);
// Set DC-DC Setting: (Double Bytes Command)
CMD(0xAD);
CMD(0x8A);
// Set Segment Re-map: (A0H - A1H)
// CMD(0xA0);
CMD(0xA1);
// Set COM Output Scan Direction
CMD(0xC8);
// CMD(0xC0);
// Set Display Start Line:Double Bytes Command
CMD(0xDC);
CMD(0x00);
// Set Display Offset:Double Bytes Command
CMD(0xD3);
CMD(0x00);
// Set Discharge / Pre-Charge Period (Double Bytes Command)
CMD(0xD9);
CMD(0x22);
// Set VCOM Deselect Level
CMD(0xDB);
CMD(0x35);
// Set Multiplex Ratio
CMD(0xA8);
CMD(0x7F);
// Set Page
CMD(0xB0);
// Set Column
CMD(0x00);
CMD(0x10);
// Set Entire Display Off
// to be clear, this command turns of the function
// which turns entire display on, but it does not clear
// the data in display RAM
CMD(0xA4);
// Set Normal Display
CMD(0xA6);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_SET); // Vpp enable
// Vpp stabilization period
HAL_Delay(100);
// Display ON
CMD(0xAF);
}
void display_init_seq(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);
send_init_seq_SH1107();
display_clear();
display_unsleep();
}
void display_init(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;
// 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 external_display_data_sram;
external_display_data_sram.Instance = FMC_NORSRAM_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;
external_display_data_sram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
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.WrapMode = FMC_WRAP_MODE_DISABLE;
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;
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(&external_display_data_sram, &normal_mode_timing, NULL);
display_init_seq();
}
void display_refresh(void) {}
const char *display_save(const char *prefix) { return NULL; }
void display_clear_save(void) {}

View File

@ -117,8 +117,10 @@ static struct { int x, y; } DISPLAY_OFFSET;
#else
#if defined TREZOR_MODEL_T
#include "display-stm32_T.h"
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#elif defined TREZOR_MODEL_1
#include "display-stm32_1.h"
#elif defined TREZOR_MODEL_R
#include "display-stm32_R.h"
#else
#error Unknown Trezor model
#endif
@ -930,7 +932,7 @@ int display_orientation(int degrees) {
}
int display_backlight(int val) {
#if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#if defined TREZOR_MODEL_1
val = 255;
#endif
if (DISPLAY_BACKLIGHT != val && val >= 0 && val <= 255) {

View File

@ -91,6 +91,11 @@ int main(void) {
button_init();
#endif
#if defined TREZOR_MODEL_R
button_init();
display_clear();
#endif
#if defined TREZOR_MODEL_T
// display_init_seq();
sdcard_init();