1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-25 06:40:58 +00:00

feat(core): Introdure driver for backlight_tps61062 + update prodtest with new control commands [no changelog]

This commit is contained in:
kopecdav 2025-01-09 15:45:09 +01:00
parent 6b76378d34
commit b2b2236769
9 changed files with 509 additions and 56 deletions

View File

@ -0,0 +1,321 @@
/*
* 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_bsp.h>
#include <trezor_rtl.h>
#include <sys/irq.h>
#include <sys/systick.h>
#include <sys/systimer.h>
#include "backlight_tps61062.h"
#ifdef KERNEL_MODE
#define BACKLIGHT_CONTROL_T_START_US 110 // may be in range 100-150
#define BACKLIGHT_CONTROL_T_UP_US 30 // may be in range 1-75
#define BACKLIGHT_CONTROL_T_DOWN_US 200 // may be in range 180-300
#define BACKLIGHT_CONTROL_T_D_US 2
#define BACKLIGHT_CONTROL_T_OFF_US 550
#define BACKLIGHT_CONTROL_T_DS_US 50000
// Backlight driver state
typedef struct {
// Set if driver is initialized
bool initialized;
// Current backlight level in range 0-32
int current_level;
// Timer used for backlide fading
systimer_t *timer;
int fade_target;
int fade_step_ms;
bool fade_in_progress;
} backlight_tps61062_driver_t;
static backlight_tps61062_driver_t g_backlight_driver = {
.initialized = false,
};
static void backlight_control_up(int num_of_ctr_steps);
static void backlight_control_down(int num_of_ctr_steps);
static void backlight_shutdown();
static void backlight_timer_callback(void *context);
// Initialize the backlight driver
//
// If the action is set to `BACKLIGHT_RESET`, the backlight level
// is set to zero level. If the action is set to `BACKLIGHT_RETAIN`,
// the backlight level is not changed (if possible).
void backlight_init(backlight_action_t action){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
if(drv->initialized){
return;
}
memset(drv, 0, sizeof(backlight_tps61062_driver_t));
BACKLIGHT_ILED_CLK_ENA();
BACKLIGHT_EN_CLK_ENA();
// Initialize ILED GPIO
GPIO_InitTypeDef GPIO_ILED_InitStructure = {0};
GPIO_ILED_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_ILED_InitStructure.Pull = GPIO_NOPULL;
GPIO_ILED_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_ILED_InitStructure.Pin = BACKLIGHT_ILED_PIN;
HAL_GPIO_Init(BACKLIGHT_ILED_PORT, &GPIO_ILED_InitStructure);
// Initialize EN GPIO
GPIO_InitTypeDef GPIO_EN_InitStructure = {0};
GPIO_EN_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_EN_InitStructure.Pull = GPIO_NOPULL;
GPIO_EN_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_EN_InitStructure.Pin = BACKLIGHT_EN_PIN;
HAL_GPIO_Init(BACKLIGHT_EN_PORT, &GPIO_EN_InitStructure);
switch (action)
{
case BACKLIGHT_KEEP_OFF:
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_RESET);
drv->current_level = 0;
break;
case BACKLIGHT_RESET:
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
systick_delay_us(BACKLIGHT_CONTROL_T_START_US);
drv->current_level = 16;
break;
default:
// Should not happen
break;
}
drv->initialized = true;
}
// Deinitialize the backlight driver
//
// If the action is set to `BACKLIGHT_RESET`, the backlight driver
// is completely deinitialized. If the action is set to `BACKLIGHT_RETAIN`,
// the driver is deinitialized as much as possible but the backlight
// is kept on.
void backlight_deinit(backlight_action_t action){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
if(!drv->initialized){
return;
}
HAL_GPIO_DeInit(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN);
HAL_GPIO_DeInit(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN);
drv->initialized = false;
}
// Sets the backlight level in range 0-32 and returns the actual level set.
//
// If the level is outside the range, the function has no effect
// and just returns the actual level set. If the backlight driver
// is not initialized, the function returns 0.
int backlight_set_level(int val){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
if(!drv->initialized || (drv->current_level == val)){
return 0;
}
// Clip max value
if(val > 32){
val = 32;
}
if(drv->current_level == 0 && val != 0){
// if brightness controll is shutdown, start with initial pulse
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
systick_delay_us(BACKLIGHT_CONTROL_T_START_US);
drv->current_level = 16; // DAC go to midpoint after reset
}
int irq_key = irq_lock();
if(val == 0){
backlight_shutdown();
}else if(val > drv->current_level){
backlight_control_up(val-drv->current_level);
}else if(val < drv->current_level){
backlight_control_down(drv->current_level-val);
}
irq_unlock(irq_key);
drv->current_level = val;
return drv->current_level;
}
// Gets the backlight level in range 0-25/5
//
// Returns 0 if the backlight driver is not initialized.
int backlight_get_level(void){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
return drv->current_level;
}
// Fade backlight to desired value with in range 0-32 and selected speed
//
// if the value is outside the range, backlight fade to mix or max backlight setting
// and stop
void backlight_fade(int val, int step_ms){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
if(!drv->initialized){
return;
}
drv->fade_in_progress = true;
drv->fade_target = val;
drv->fade_step_ms = step_ms;
drv->timer = systimer_create(backlight_timer_callback, drv);
systimer_set(drv->timer, drv->fade_step_ms);
}
bool backlight_fade_in_progress(){
backlight_tps61062_driver_t *drv = &g_backlight_driver;
return drv->fade_in_progress;
}
//void backlight_fade_abort();
static void backlight_control_up(int num_of_ctr_steps){
for(int i = 0; i < num_of_ctr_steps; i++){
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
systick_delay_us(BACKLIGHT_CONTROL_T_D_US);
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_RESET);
systick_delay_us(BACKLIGHT_CONTROL_T_UP_US);
}
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
}
static void backlight_control_down(int num_of_ctr_steps){
for(int i = 0; i < num_of_ctr_steps; i++){
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
systick_delay_us(BACKLIGHT_CONTROL_T_D_US);
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_RESET);
systick_delay_us(BACKLIGHT_CONTROL_T_DOWN_US);
}
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
}
static void backlight_shutdown(){
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_RESET);
}
static void backlight_timer_callback(void *context){
backlight_tps61062_driver_t *drv = (backlight_tps61062_driver_t *)context;
if(drv->current_level == 0 && drv->fade_target != 0){
// if brightness controll is shutdown, start with initial pulse
HAL_GPIO_WritePin(BACKLIGHT_EN_PORT, BACKLIGHT_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(BACKLIGHT_ILED_PORT, BACKLIGHT_ILED_PIN, GPIO_PIN_SET);
systick_delay_us(BACKLIGHT_CONTROL_T_START_US);
// DAC starts at zero and midpoint and controll down by 16 steps
backlight_control_down(15);
drv->current_level = 1;
} else if(drv->fade_target == 0 && drv->current_level == 1){
backlight_shutdown();
drv->current_level = 0;
} else if(drv->current_level < drv->fade_target){
backlight_control_up(1);
drv->current_level++;
} else if(drv->current_level > drv->fade_target){
backlight_control_down(1);
drv->current_level--;
}
if(drv->current_level == drv->fade_target){
drv->fade_in_progress = false;
systimer_delete(drv->timer);
return;
}
systimer_set(drv->timer, drv->fade_step_ms);
}
#endif

View 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_BACKLIGHT_TPS61062_H
#define TREZORHAL_BACKLIGHT_TPS61062_H
// Action to be taken when initializing or
// deinitializing the backlight driver
typedef enum {
BACKLIGHT_KEEP_OFF,
BACKLIGHT_RESET,
} backlight_action_t;
// Initialize the backlight driver
//
// If the action is set to `BACKLIGHT_RESET`, the backlight level
// is set to zero level. If the action is set to `BACKLIGHT_RETAIN`,
// the backlight level is not changed (if possible).
void backlight_init(backlight_action_t action);
// Deinitialize the backlight driver
//
// If the action is set to `BACKLIGHT_RESET`, the backlight driver
// is completely deinitialized. If the action is set to `BACKLIGHT_RETAIN`,
// the driver is deinitialized as much as possible but the backlight
// is kept on.
void backlight_deinit(backlight_action_t action);
// Sets the backlight level in range 0-32 and returns the actual level set.
//
// If the level is outside the range, the function has no effect
// and just returns the actual level set. If the backlight driver
// is not initialized, the function returns 0.
int backlight_set_level(int val);
// Gets the backlight level in range 0-255
//
// Returns 0 if the backlight driver is not initialized.
int backlight_get_level(void);
// Fade backlight to desired value with in range 0-32 and selected speed
//
// if the value is outside the range, backlight fade to mix or max backlight setting
// and stop
void backlight_fade(int val, int step_ms);
bool backlight_fade_in_progress();
#endif // TREZORHAL_BACKLIGHT_TPS61062_H

View File

@ -88,6 +88,12 @@ int display_set_backlight(int level);
// Gets current display level ranging from 0 (off)..255 (maximum).
int display_get_backlight(void);
// Fade display backlight to desired value.
void display_fade_backlight(int val, int step_ms);
bool display_fade_in_progress(void);
// Sets the display orientation.
//
// May accept one of following values: 0, 90, 180, 270

View File

@ -12,7 +12,7 @@
#include <sys/systick.h>
#ifdef USE_BACKLIGHT
#include "../backlight/backlight_pwm.h"
#include "../backlight_tps61062/backlight_tps61062.h"
#endif
#include "display_internal.h"
@ -308,7 +308,7 @@ void display_init(display_content_mode_t mode) {
#endif
#ifdef USE_BACKLIGHT
backlight_pwm_init(BACKLIGHT_RESET);
backlight_init(BACKLIGHT_RESET);
#endif
uint32_t fb_addr = display_fb_init();
@ -381,11 +381,11 @@ int display_set_backlight(int level) {
}
#ifdef USE_BACKLIGHT
if (level > backlight_pwm_get()) {
display_ensure_refreshed();
}
// if (level > backlight_pwm_get()) {
// display_ensure_refreshed();
// }
return backlight_pwm_set(level);
return backlight_set_level(level);
#else
// Just emulation, not doing anything
drv->backlight_level = level;
@ -400,12 +400,37 @@ int display_get_backlight(void) {
return 0;
}
#ifdef USE_BACKLIGHT
return backlight_pwm_get();
return backlight_get_level();
#else
return drv->backlight_level;
#endif
}
#ifdef USE_BACKLIGHT
void display_fade_backlight(int level, int step_ms) {
display_driver_t *drv = &g_display_driver;
if (!drv->initialized) {
return;
}
backlight_fade(level, step_ms);
}
bool display_fade_in_progress(void) {
display_driver_t *drv = &g_display_driver;
if (!drv->initialized) {
return false;
}
return backlight_fade_in_progress();
}
#endif
int display_set_orientation(int angle) { return angle; }
int display_get_orientation(void) { return 0; }

View File

@ -23,16 +23,13 @@
#define DISPLAY_PWREN_PORT GPIOE
#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
#define BACKLIGHT_PWM_FREQ 1000
#define BACKLIGHT_PWM_TIM TIM17
#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17
#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1
#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1
#define BACKLIGHT_PWM_TIM_CCR CCR1
#define BACKLIGHT_PWM_PIN GPIO_PIN_9
#define BACKLIGHT_PWM_PORT GPIOB
#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
#define BACKLIGHT_ILED_PIN GPIO_PIN_3
#define BACKLIGHT_ILED_PORT GPIOE
#define BACKLIGHT_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
#define BACKLIGHT_EN_PIN GPIO_PIN_9
#define BACKLIGHT_EN_PORT GPIOB
#define BACKLIGHT_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
#define NPM1300_I2C_INSTANCE 0

View File

@ -22,16 +22,13 @@
#define DISPLAY_PWREN_PORT GPIOE
#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
#define BACKLIGHT_PWM_FREQ 1000
#define BACKLIGHT_PWM_TIM TIM17
#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE
#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17
#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1
#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1
#define BACKLIGHT_PWM_TIM_CCR CCR1
#define BACKLIGHT_PWM_PIN GPIO_PIN_9
#define BACKLIGHT_PWM_PORT GPIOB
#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
#define BACKLIGHT_ILED_PIN GPIO_PIN_3
#define BACKLIGHT_ILED_PORT GPIOE
#define BACKLIGHT_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
#define BACKLIGHT_EN_PIN GPIO_PIN_9
#define BACKLIGHT_EN_PORT GPIOB
#define BACKLIGHT_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
#define NPM1300_I2C_INSTANCE 0

View File

@ -246,33 +246,48 @@ static void test_border(void) {
}
static void test_display(const char *colors) {
gfx_clear();
size_t l = strlen(colors);
size_t w = DISPLAY_RESX / l;
if(strncmp(colors, "TEXT", 4) == 0){
for (size_t i = 0; i < l; i++) {
gfx_color_t c = COLOR_BLACK; // black
switch (colors[i]) {
case 'R':
c = gfx_color_rgb(255, 0, 0);
break;
case 'G':
c = gfx_color_rgb(0, 255, 0);
break;
case 'B':
c = gfx_color_rgb(0, 0, 255);
break;
case 'W':
c = COLOR_WHITE;
break;
}
gfx_clear();
gfx_offset_t pos = gfx_offset(DISPLAY_RESX / 2, DISPLAY_RESY / 2);
gfx_draw_text(pos, "Example TEXT", -1, &bold, GFX_ALIGN_CENTER);
display_refresh();
vcp_println("OK");
return;
}else{
gfx_clear();
size_t l = strlen(colors);
size_t w = DISPLAY_RESX / l;
for (size_t i = 0; i < l; i++) {
gfx_color_t c = COLOR_BLACK; // black
switch (colors[i]) {
case 'R':
c = gfx_color_rgb(255, 0, 0);
break;
case 'G':
c = gfx_color_rgb(0, 255, 0);
break;
case 'B':
c = gfx_color_rgb(0, 0, 255);
break;
case 'W':
c = COLOR_WHITE;
break;
}
gfx_rect_t r = gfx_rect_wh(i * w, 0, i * w + w, DISPLAY_RESY);
gfx_draw_bar(r, c);
}
}
display_refresh();
vcp_println("OK");
}
}
#ifdef USE_BUTTON
@ -600,12 +615,37 @@ static void touch_version(void) {
}
#endif
static void test_pwm(const char *args) {
int v = atoi(args);
static void test_bl(const char *args) {
if (strncmp(args, "SET", 3) == 0) {
int v = atoi(&args[3]);
display_set_backlight(v);
display_refresh();
vcp_println("OK");
} else if (strncmp(args, "FADE", 4) == 0) {
int step_ms = atoi(&args[4]);
for(int i = 0; i < 3; i++){
display_fade_backlight(0, step_ms);
while(display_fade_in_progress());
display_fade_backlight(32, step_ms);
while(display_fade_in_progress());
}
display_refresh();
vcp_println("OK");
}
display_set_backlight(v);
display_refresh();
vcp_println("OK");
}
#ifdef USE_SD_CARD
@ -1202,8 +1242,8 @@ int main(void) {
test_sensitivity(line + 5);
#endif
} else if (startswith(line, "PWM ")) {
test_pwm(line + 4);
} else if (startswith(line, "BL ")) {
test_bl(line + 3);
#ifdef USE_SD_CARD
} else if (startswith(line, "SD")) {
test_sd();

View File

@ -46,7 +46,7 @@ def configure(
"embed/io/display/ltdc_dsi/display_fb_rgb888.c",
"embed/io/display/ltdc_dsi/display_gfxmmu.c",
"embed/io/display/fb_queue/fb_queue.c",
"embed/io/display/backlight/stm32/backlight_pwm.c",
"embed/io/display/backlight_tps61062/backlight_tps61062.c",
]
paths += ["embed/io/display/inc"]

View File

@ -45,7 +45,7 @@ def configure(
"embed/io/display/ltdc_dsi/display_fb.c",
"embed/io/display/ltdc_dsi/display_fb_rgb565.c",
"embed/io/display/fb_queue/fb_queue.c",
"embed/io/display/backlight/stm32/backlight_pwm.c",
"embed/io/display/backlight_tps61062/backlight_tps61062.c",
]
paths += ["embed/io/display/inc"]