chore(color): reduce busy wait time on LCD refresh (#7483)

This commit is contained in:
philmoz
2026-07-22 09:38:29 +10:00
committed by GitHub
parent 19aa6d5f20
commit 50d12c7cea
19 changed files with 230 additions and 380 deletions
+4 -16
View File
@@ -24,9 +24,7 @@
#include "stm32_hal.h"
#include "stm32_gpio_driver.h"
#include "edgetx_types.h"
#include "dma2d.h"
#include "hal.h"
#include "delays_driver.h"
#include "debug.h"
#include "lcd.h"
#include "lcd_driver.h"
@@ -35,15 +33,12 @@
#include "stm32_gpio.h"
#include "hal/gpio.h"
uint8_t TouchControllerType = 0; // 0: other; 1: CST836U
static volatile uint16_t lcd_phys_w = LCD_H;
static volatile uint16_t lcd_phys_h = LCD_W;
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
@@ -54,16 +49,11 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
// faster than cleaning by address
SCB_CleanDCache();
// LTDC_Layer1->CFBAR &= ~(LTDC_LxCFBAR_CFBADD);
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
lcdSpiInitFucPtr lcdInitFunction;
@@ -71,8 +61,6 @@ lcdSpiInitFucPtr lcdOffFunction;
lcdSpiInitFucPtr lcdOnFunction;
uint32_t lcdPixelClock;
volatile uint8_t LCD_ReadBuffer[24] = { 0, 0 };
static void LCD_Delay(void) {
volatile unsigned int i;
@@ -1884,7 +1872,6 @@ void LCD_Init_LTDC() {
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
void LCD_LayerInit() {
@@ -2009,5 +1996,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
}
lcdFlushed();
}
+1 -5
View File
@@ -19,8 +19,7 @@
* GNU General Public License for more details.
*/
#ifndef __LCD_DRIVER_H__
#define __LCD_DRIVER_H__
#pragma once
#define HBP ( 24 ) // TODO use names from FlySky
#define VBP ( 10 )
@@ -66,12 +65,9 @@ extern lcdSpiInitFucPtr lcdOnFunction;
#define LCD_READ_DATA_PIN() LL_GPIO_IsInputPinSet(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN)
#define HORIZONTAL_SYNC_WIDTH ( 4 )
#define HORIZONTAL_BACK_PORCH ( 24 )
#define HORIZONTAL_FRONT_PORCH ( 140 - HORIZONTAL_BACK_PORCH )
#define VERTICAL_SYNC_HEIGHT ( 2 )
#define VERTICAL_BACK_PORCH ( 10 )
#define VERTICAL_FRONT_PORCH ( 22 - VERTICAL_BACK_PORCH )
#endif
+12 -36
View File
@@ -22,9 +22,7 @@
#include "stm32_hal_ll.h"
#include "stm32_hal.h"
#include "edgetx_types.h"
#include "dma2d.h"
#include "hal.h"
#include "delays_driver.h"
#include "debug.h"
#include "lcd.h"
#include "lcd_driver_480.h"
@@ -34,15 +32,9 @@
#include "stm32_gpio.h"
#include "stm32_qspi.h"
uint8_t TouchControllerType = 0; // 0: other; 1: CST836U
static volatile uint16_t lcd_phys_w = LCD_PHYS_W;
static volatile uint16_t lcd_phys_h = LCD_PHYS_H;
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
@@ -55,23 +47,11 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
}
lcdSpiInitFucPtr lcdInitFunction;
lcdSpiInitFucPtr lcdOffFunction;
lcdSpiInitFucPtr lcdOnFunction;
uint32_t lcdPixelClock;
volatile uint8_t LCD_ReadBuffer[24] = { 0, 0 };
static void LCD_Delay(void) {
volatile unsigned int i;
@@ -424,13 +404,13 @@ void LCD_Init_LTDC() {
/* Configure accumulated vertical back porch */
hltdc.Init.AccumulatedVBP = VSH+VBP-1;
/* Configure accumulated active width */
hltdc.Init.AccumulatedActiveW = lcd_phys_w + HBP+HSW-1;
hltdc.Init.AccumulatedActiveW = LCD_PHYS_W + HBP+HSW-1;
/* Configure accumulated active height */
hltdc.Init.AccumulatedActiveH = lcd_phys_h + VBP+VSH-1;
hltdc.Init.AccumulatedActiveH = LCD_PHYS_H + VBP+VSH-1;
/* Configure total width */
hltdc.Init.TotalWidth = lcd_phys_w + HBP + HFP + HSW -1;
hltdc.Init.TotalWidth = LCD_PHYS_W + HBP + HFP + HSW -1;
/* Configure total height */
hltdc.Init.TotalHeigh = lcd_phys_h + VBP + VFP+VSH-1;
hltdc.Init.TotalHeigh = LCD_PHYS_H + VBP + VFP+VSH-1;
HAL_LTDC_Init(&hltdc);
@@ -439,8 +419,7 @@ void LCD_Init_LTDC() {
NVIC_EnableIRQ(LTDC_IRQn);
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
HAL_LTDC_ProgramLineEvent(&hltdc, LCD_PHYS_H);
}
void LCD_LayerInit() {
@@ -448,9 +427,9 @@ void LCD_LayerInit() {
/* Windowing configuration */
layer.WindowX0 = 0;
layer.WindowX1 = lcd_phys_w;
layer.WindowX1 = LCD_PHYS_W;
layer.WindowY0 = 0;
layer.WindowY1 = lcd_phys_h;
layer.WindowY1 = LCD_PHYS_H;
/* Pixel Format configuration*/
layer.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
@@ -468,8 +447,8 @@ void LCD_LayerInit() {
layer.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
layer.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
layer.ImageWidth = lcd_phys_w;
layer.ImageHeight = lcd_phys_h;
layer.ImageWidth = LCD_PHYS_W;
layer.ImageHeight = LCD_PHYS_H;
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */
layer.FBStartAdress = (intptr_t)initialFrameBuffer;
@@ -508,12 +487,9 @@ void lcdInit(void)
/* Send LCD initialization commands */
TRACE("LCD INIT (default): ST7365");
boardLcdType = "ST7365 (Default)";
lcdInitFunction = LCD_ST7365_Init;
lcdOffFunction = LCD_ST7365_Off;
lcdOnFunction = LCD_ST7365_On;
__HAL_RCC_LTDC_CLK_ENABLE();
lcdInitFunction();
LCD_ST7365_Init();
LCD_Init_LTDC();
LCD_LayerInit();
@@ -533,6 +509,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
}
lcdFlushed();
}
+1 -13
View File
@@ -19,10 +19,7 @@
* GNU General Public License for more details.
*/
#ifndef __LCD_DRIVER_H__
#define __LCD_DRIVER_H__
#include "bsp_io.h"
#pragma once
#define HBP ( 20 )
#define VBP ( 10 )
@@ -35,9 +32,6 @@
#define LCD_DELAY() LCD_Delay()
typedef void (*lcdSpiInitFucPtr)(void);
typedef unsigned int LcdReadIDFucPtr( void );
#define SET_IO_INPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_INPUT )
#define SET_IO_OUTPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_OUTPUT )
@@ -57,9 +51,3 @@ typedef unsigned int LcdReadIDFucPtr( void );
#define LCD_MOSI_AS_OUTPUT() SET_IO_OUTPUT( LCD_SPI_MOSI_GPIO, LCD_SPI_MOSI_GPIO_PIN )
#define LCD_READ_DATA_PIN() LL_GPIO_IsInputPinSet(LCD_SPI_MOSI_GPIO, LCD_SPI_MOSI_GPIO_PIN)
#endif
+11 -33
View File
@@ -22,9 +22,7 @@
#include "stm32_hal_ll.h"
#include "stm32_hal.h"
#include "edgetx_types.h"
#include "dma2d.h"
#include "hal.h"
#include "delays_driver.h"
#include "debug.h"
#include "lcd.h"
#include "lcd_driver_800.h"
@@ -34,15 +32,9 @@
#include "stm32_gpio.h"
#include "stm32_qspi.h"
uint8_t TouchControllerType = 0; // 0: other; 1: CST836U
static const uint16_t lcd_phys_w = LCD_PHYS_W;
static const uint16_t lcd_phys_h = LCD_PHYS_H;
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
@@ -55,23 +47,11 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
}
lcdSpiInitFucPtr lcdInitFunction;
lcdSpiInitFucPtr lcdOffFunction;
lcdSpiInitFucPtr lcdOnFunction;
uint32_t lcdPixelClock;
volatile uint8_t LCD_ReadBuffer[24] = { 0, 0 };
static void LCD_AF_GPIOConfig(void)
{
const gpio_t _lcd_af_gpios[] = {
@@ -121,8 +101,6 @@ static void lcdReset() {
delay_ms(100);
}
void LCD_Init_LTDC() {
hltdc.Instance = LTDC;
@@ -166,13 +144,13 @@ void LCD_Init_LTDC() {
/* Configure accumulated vertical back porch */
hltdc.Init.AccumulatedVBP = VSH+VBP-1;
/* Configure accumulated active width */
hltdc.Init.AccumulatedActiveW = lcd_phys_w + HBP+HSW-1;
hltdc.Init.AccumulatedActiveW = LCD_PHYS_W + HBP+HSW-1;
/* Configure accumulated active height */
hltdc.Init.AccumulatedActiveH = lcd_phys_h + VBP+VSH-1;
hltdc.Init.AccumulatedActiveH = LCD_PHYS_H + VBP+VSH-1;
/* Configure total width */
hltdc.Init.TotalWidth = lcd_phys_w + HBP + HFP + HSW -1;
hltdc.Init.TotalWidth = LCD_PHYS_W + HBP + HFP + HSW -1;
/* Configure total height */
hltdc.Init.TotalHeigh = lcd_phys_h + VBP + VFP+VSH-1;
hltdc.Init.TotalHeigh = LCD_PHYS_H + VBP + VFP+VSH-1;
HAL_LTDC_Init(&hltdc);
@@ -181,8 +159,7 @@ void LCD_Init_LTDC() {
NVIC_EnableIRQ(LTDC_IRQn);
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
HAL_LTDC_ProgramLineEvent(&hltdc, LCD_PHYS_H);
}
void LCD_LayerInit() {
@@ -190,9 +167,9 @@ void LCD_LayerInit() {
/* Windowing configuration */
layer.WindowX0 = 0;
layer.WindowX1 = lcd_phys_w;
layer.WindowX1 = LCD_PHYS_W;
layer.WindowY0 = 0;
layer.WindowY1 = lcd_phys_h;
layer.WindowY1 = LCD_PHYS_H;
/* Pixel Format configuration*/
layer.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
@@ -210,8 +187,8 @@ void LCD_LayerInit() {
layer.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
layer.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
layer.ImageWidth = lcd_phys_w;
layer.ImageHeight = lcd_phys_h;
layer.ImageWidth = LCD_PHYS_W;
layer.ImageHeight = LCD_PHYS_H;
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */
layer.FBStartAdress = (intptr_t)initialFrameBuffer;
@@ -271,5 +248,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
lcdFlushed();
}
@@ -32,13 +32,6 @@
#define HFP ( 16 )
#define VFP ( 8 )
typedef void (*lcdSpiInitFucPtr)(void);
typedef unsigned int LcdReadIDFucPtr( void );
extern lcdSpiInitFucPtr lcdInitFunction;
extern lcdSpiInitFucPtr lcdOffFunction;
extern lcdSpiInitFucPtr lcdOnFunction;
#define SET_IO_INPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_INPUT )
#define SET_IO_OUTPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_OUTPUT )
+46 -64
View File
@@ -33,46 +33,40 @@
#include "board.h"
#include "etx_lv_theme.h"
pixel_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
pixel_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
BitmapBuffer lcdBuffer1(BMP_RGB565, LCD_W, LCD_H,
(uint16_t*)LCD_FIRST_FRAME_BUFFER);
BitmapBuffer lcdBuffer2(BMP_RGB565, LCD_W, LCD_H,
(uint16_t*)LCD_SECOND_FRAME_BUFFER);
BitmapBuffer* lcdFront = &lcdBuffer1;
BitmapBuffer* lcd = &lcdBuffer2;
BitmapBuffer lcd(BMP_RGB565, LCD_W, LCD_H, (uint16_t*)LCD_FIRST_FRAME_BUFFER);
static lv_disp_draw_buf_t disp_buf;
static lv_disp_drv_t disp_drv;
static lv_disp_t disp;
// Call backs
static void (*lcd_flush_cb)(lv_disp_drv_t*, uint16_t* buffer,
const rect_t& area) = nullptr;
extern "C" void lcdFlushed()
{
lv_disp_flush_ready(&disp_drv);
}
void lcdSetFlushCb(void (*cb)(lv_disp_drv_t*, uint16_t*, const rect_t&))
{
lcd_flush_cb = cb;
}
static lv_disp_drv_t* refr_disp = nullptr;
static void flushLcd(lv_disp_drv_t* disp_drv, const lv_area_t* area,
lv_color_t* color_p)
{
if (lcd_flush_cb) {
refr_disp = disp_drv;
rect_t copy_area = {area->x1, area->y1, area->x2 - area->x1 + 1,
area->y2 - area->y1 + 1};
lcd_flush_cb(disp_drv, (uint16_t*)color_p, copy_area);
} else {
lcdFlushed();
}
lv_disp_flush_ready(disp_drv);
}
static void clear_frame_buffers()
@@ -83,24 +77,27 @@ static void clear_frame_buffers()
static void init_lvgl_disp_drv()
{
lv_disp_draw_buf_init(&disp_buf, lcdFront->getData(), lcd->getData(), LCD_W * LCD_H);
int direct_mode = 1;
#if LCD_VERTICAL_INVERT
#if defined(RADIO_F16)
direct_mode = (hardwareOptions.pcbrev > 0) ? 1 : 0;
#else
direct_mode = 0;
#endif
#endif
lv_disp_draw_buf_init(&disp_buf,
LCD_FIRST_FRAME_BUFFER,
direct_mode ? LCD_SECOND_FRAME_BUFFER : nullptr,
LCD_W * LCD_H);
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.draw_buf = &disp_buf; /*Set an initialized buffer*/
disp_drv.flush_cb = flushLcd; /*Set a flush callback to draw to the display*/
disp_drv.wait_cb = nullptr; /*Set a wait callback*/
disp_drv.hor_res = LCD_W; /*Set the horizontal resolution in pixels*/
disp_drv.ver_res = LCD_H; /*Set the vertical resolution in pixels*/
disp_drv.full_refresh = 0;
#if !LCD_VERTICAL_INVERT
disp_drv.direct_mode = 1;
#elif defined(RADIO_F16)
disp_drv.direct_mode = (hardwareOptions.pcbrev > 0) ? 1 : 0;
#else
disp_drv.direct_mode = 0;
#endif
disp_drv.direct_mode = direct_mode;
}
void lcdInitDisplayDriver()
@@ -119,7 +116,7 @@ void lcdInitDisplayDriver()
// Clear buffers first
clear_frame_buffers();
lcdSetInitalFrameBuffer(lcdFront->getData());
lcdSetInitalFrameBuffer(lcd.getData());
// Init hardware LCD driver
lcdInit();
@@ -141,32 +138,24 @@ void lcdInitDisplayDriver()
}
lv_draw_ctx_t* draw_ctx = disp_drv.draw_ctx;
lcd->setDrawCtx(draw_ctx);
lcdFront->setDrawCtx(draw_ctx);
lcd.setDrawCtx(draw_ctx);
#if defined(LCD_BACKLIGHT_INIT_DELAY_MS)
delay_ms(LCD_BACKLIGHT_INIT_DELAY_MS);
#endif
backlightInit();
}
void lcdClear() { lcd->clear(); }
// Direct drawing - used by boot loader
void lcdInitDirectDrawing()
{
static lv_area_t screen_area = {0, 0, LCD_W - 1, LCD_H - 1};
lv_draw_ctx_t* draw_ctx = disp_drv.draw_ctx;
draw_ctx->buf = disp_drv.draw_buf->buf_act;
draw_ctx->buf_area = &screen_area;
draw_ctx->clip_area = &screen_area;
lcd->setData((pixel_t*)draw_ctx->buf);
lcd->reset();
#if defined(LCD_BACKLIGHT_INIT_DELAY_MS)
delay_ms(LCD_BACKLIGHT_INIT_DELAY_MS);
#endif
backlightInit();
}
void lcdClear() { lcd.clear(); }
// Direct drawing - used by boot loader
//
// Private code copied and adapted from LVGL / lv_refr.c
// (_call_flush_cb & _draw_buf_flush)
@@ -182,21 +171,12 @@ static void _call_flush_cb(lv_disp_drv_t* drv, const lv_area_t* area,
drv->flush_cb(drv, &offset_area, color_p);
}
static void _draw_buf_flush(lv_disp_t* disp)
void lcdRefresh()
{
/* Flush the rendered content to the display */
lv_disp_t* disp = _lv_refr_get_disp_refreshing();
lv_disp_draw_buf_t* draw_buf = lv_disp_get_draw_buf(disp);
/*Flush the rendered content to the display*/
lv_draw_ctx_t* draw_ctx = disp->driver->draw_ctx;
if (draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
/* In double buffered mode wait until the other buffer is freed
* and driver is ready to receive the new buffer */
if (draw_buf->buf1 && draw_buf->buf2) {
while (draw_buf->flushing) {
if (disp->driver->wait_cb) disp->driver->wait_cb(disp->driver);
}
}
draw_buf->flushing = 1;
draw_buf->flushing_last = 1;
@@ -208,15 +188,17 @@ static void _draw_buf_flush(lv_disp_t* disp)
/*If there are 2 buffers swap them. */
if (draw_buf->buf1 && draw_buf->buf2) {
/* In double buffered mode wait until the other buffer is freed
* and driver is ready to receive the new buffer */
while (draw_buf->flushing);
if (draw_buf->buf_act == draw_buf->buf1)
draw_buf->buf_act = draw_buf->buf2;
else
draw_buf->buf_act = draw_buf->buf1;
}
}
void lcdRefresh()
{
lv_disp_t* d = _lv_refr_get_disp_refreshing();
_draw_buf_flush(d);
// Update draw context and lcd bitmap
draw_ctx->buf = draw_buf->buf_act;
lcd.setData((pixel_t*)draw_buf->buf_act);
lcd.reset();
}
+47 -50
View File
@@ -55,7 +55,7 @@ constexpr coord_t PROGRESS_W = LCD_W * 3 / 4;
constexpr coord_t PROGRESS_X = (LCD_W - PROGRESS_W) / 2;
LAYOUT_VAL_SCALED(PROGRESS_H, 31)
extern BitmapBuffer * lcd;
extern BitmapBuffer lcd;
#if defined(USB_SW_GPIO)
#include "hal/gpio.h"
@@ -74,28 +74,28 @@ void blExit(void)
static void bootloaderDrawTitle(const char* text)
{
lcd->drawText(LCD_W / 2, TITLE_Y1, text, CENTERED | BL_FOREGROUND);
lcd->drawSolidFilledRect(PAD_LARGE, TITLE_Y2, LCD_W - PAD_LARGE * 2, LINE_H, BL_FOREGROUND);
lcd.drawText(LCD_W / 2, TITLE_Y1, text, CENTERED | BL_FOREGROUND);
lcd.drawSolidFilledRect(PAD_LARGE, TITLE_Y2, LCD_W - PAD_LARGE * 2, LINE_H, BL_FOREGROUND);
}
static void bootloaderDrawFooter()
{
lcd->drawSolidFilledRect(PAD_LARGE, LCD_H - FOOTER_LY, LCD_W - PAD_LARGE * 2, LINE_H, BL_FOREGROUND);
lcd.drawSolidFilledRect(PAD_LARGE, LCD_H - FOOTER_LY, LCD_W - PAD_LARGE * 2, LINE_H, BL_FOREGROUND);
}
static void bootloaderDrawVerFooter()
{
bootloaderDrawFooter();
if (LCD_W < LCD_H)
lcd->drawText(LCD_W / 2, LCD_H - FOOTER_Y2 + PAD_TINY, TR_BL_CURRENT_FW, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H - FOOTER_Y2 + PAD_TINY, TR_BL_CURRENT_FW, CENTERED | BL_FOREGROUND);
const char* fw_ver = getFirmwareVersion();
if (!fw_ver) fw_ver = TR_BL_NO_VERSION;
lcd->drawText(LCD_W / 2, LCD_H - FOOTER_Y1, fw_ver, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H - FOOTER_Y1, fw_ver, CENTERED | BL_FOREGROUND);
}
static void bootloaderDrawBackground()
{
lcd->clear(BL_BACKGROUND);
lcd.clear(BL_BACKGROUND);
}
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
@@ -157,14 +157,12 @@ void bootloaderInitScreen()
void bootloaderDrawDFUScreen()
{
lcdInitDirectDrawing();
bootloaderDrawBackground();
lcd->drawText(LCD_W / 2, LCD_H / 2, TR_BL_DFU_MODE, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2, TR_BL_DFU_MODE, CENTERED | BL_FOREGROUND);
}
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
{
lcdInitDirectDrawing();
bootloaderDrawBackground();
bootloaderDrawTitle(BOOTLOADER_TITLE);
@@ -173,9 +171,9 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
const char* msg = (st == ST_START) ? TR_BL_PLUG_USB : TR_BL_COPY_UF2;
lcd->drawText(LCD_W / 2, LCD_H / 2 - TITLE_Y1, msg, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2 - TITLE_Y1, msg, CENTERED | BL_FOREGROUND);
if (st != ST_USB)
lcd->drawText(LCD_W / 2, LCD_H / 2 + TITLE_Y1, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2 + TITLE_Y1, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, CENTERED | BL_FOREGROUND);
bootloaderDrawVerFooter();
@@ -184,11 +182,11 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
const coord_t pb_y = (LCD_H - PROGRESS_H) / 2;
const char* msg = (st == ST_FLASH_DONE) ? TR_BL_WRITING_COMPL : TR_BL_WRITING_FW;
lcd->drawText(PROGRESS_X, pb_y - TITLE_Y1, msg, BL_FOREGROUND);
lcd->drawRect(PROGRESS_X, pb_y, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED);
lcd.drawText(PROGRESS_X, pb_y - TITLE_Y1, msg, BL_FOREGROUND);
lcd.drawRect(PROGRESS_X, pb_y, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED);
LcdFlags color = (st == ST_FLASH_DONE) ? BL_GREEN : BL_RED;
lcd->drawSolidFilledRect(PROGRESS_X + PAD_SMALL, pb_y + PAD_SMALL, ((PROGRESS_W - PAD_SMALL * 2) * opt) / 100, PROGRESS_H - PAD_SMALL * 2, color);
lcd.drawSolidFilledRect(PROGRESS_X + PAD_SMALL, pb_y + PAD_SMALL, ((PROGRESS_W - PAD_SMALL * 2) * opt) / 100, PROGRESS_H - PAD_SMALL * 2, color);
}
}
@@ -247,8 +245,8 @@ void bootloaderInitScreen()
void bootloaderDrawItem(const char* symbol, const char* text, coord_t& y, coord_t& lastX, coord_t symXO = 0)
{
lcd->drawText(SYM_X - symXO, y, symbol, BL_FOREGROUND);
coord_t nx = lcd->drawText(LBL_X, y, text, BL_FOREGROUND) + BOX_GAP;
lcd.drawText(SYM_X - symXO, y, symbol, BL_FOREGROUND);
coord_t nx = lcd.drawText(LBL_X, y, text, BL_FOREGROUND) + BOX_GAP;
if (nx > lastX) lastX = nx;
y += SYM_H;
}
@@ -256,12 +254,11 @@ void bootloaderDrawItem(const char* symbol, const char* text, coord_t& y, coord_
void bootloaderDrawSelected(coord_t boxX2, int opt)
{
boxX2 -= OPTBOX_X;
lcd->drawSolidRect(OPTBOX_X, BOX_Y + (opt * SYM_H), boxX2, BOX_H, PAD_TINY, BL_SELECTED);
lcd.drawSolidRect(OPTBOX_X, BOX_Y + (opt * SYM_H), boxX2, BOX_H, PAD_TINY, BL_SELECTED);
}
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
{
lcdInitDirectDrawing();
bootloaderDrawBackground();
coord_t y = SYM_Y, boxX2 = 0;
@@ -286,9 +283,9 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
bootloaderDrawSelected(boxX2, opt);
lcd->drawBitmap(USB_ICN_X, LCD_H - USB_ICN_Y, (const BitmapBuffer*)&BMP_PLUG_USB);
lcd->drawText(USB_TXT_X, LCD_H - USB_TXT_Y1, TR_BL_USB_PLUGIN, USB_TXT_ALIGN | BL_FOREGROUND);
lcd->drawText(USB_TXT_X, LCD_H - USB_TXT_Y2, TR_BL_USB_MASS_STORE, USB_TXT_ALIGN | BL_FOREGROUND);
lcd.drawBitmap(USB_ICN_X, LCD_H - USB_ICN_Y, (const BitmapBuffer*)&BMP_PLUG_USB);
lcd.drawText(USB_TXT_X, LCD_H - USB_TXT_Y1, TR_BL_USB_PLUGIN, USB_TXT_ALIGN | BL_FOREGROUND);
lcd.drawText(USB_TXT_X, LCD_H - USB_TXT_Y2, TR_BL_USB_MASS_STORE, USB_TXT_ALIGN | BL_FOREGROUND);
bootloaderDrawVerFooter();
}
@@ -301,7 +298,7 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
bootloaderDrawSelected(boxX2, opt);
bootloaderDrawFooter();
int pos = lcd->drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_SD_CARD " " TR_BL_ERASE_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
int pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_SD_CARD " " TR_BL_ERASE_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
#if LANDSCAPE
pos = 0;
#else
@@ -309,12 +306,12 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
pos = (pos - FOOTER_X1) / 2;
}
#endif
lcd->drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, FOOTER_ALIGN2 | BL_FOREGROUND);
lcd.drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, FOOTER_ALIGN2 | BL_FOREGROUND);
}
else if (st == ST_CLEAR_FLASH) {
bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH);
lcd->drawText(LCD_W / 2, SYM_Y, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, SYM_Y, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND);
bootloaderDrawFooter();
}
#endif
@@ -327,7 +324,7 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
bootloaderDrawSelected(boxX2, opt);
bootloaderDrawFooter();
int pos = lcd->drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_USB " " TR_BL_TOGGLE_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
int pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_USB " " TR_BL_TOGGLE_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
#if LANDSCAPE
pos = 0;
#else
@@ -335,13 +332,13 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
pos = (pos - FOOTER_X1) / 2;
}
#endif
lcd->drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, FOOTER_ALIGN2 | BL_FOREGROUND);
lcd.drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, FOOTER_ALIGN2 | BL_FOREGROUND);
}
#endif
else if (st == ST_USB) {
y = (LCD_H - BMP_USB_PLUGGED.height()) / 2;
lcd->drawBitmap(USB_PLG_X, y, (const BitmapBuffer*)&BMP_USB_PLUGGED);
lcd->drawText(USB_TXT_X, y + USB_PLG_TXT_YO, TR_BL_USB_CONNECTED, USB_TXT_ALIGN | BL_FOREGROUND);
lcd.drawBitmap(USB_PLG_X, y, (const BitmapBuffer*)&BMP_USB_PLUGGED);
lcd.drawText(USB_TXT_X, y + USB_PLG_TXT_YO, TR_BL_USB_CONNECTED, USB_TXT_ALIGN | BL_FOREGROUND);
}
else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK ||
st == ST_FLASHING || st == ST_FLASH_DONE) {
@@ -356,37 +353,37 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
opt = 100; // Completed > 100%
}
lcd->drawRect(PROGRESS_X, (LCD_H - PROGRESS_H) / 2, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED);
lcd->drawSolidFilledRect(PROGRESS_X + PAD_SMALL, (LCD_H - PROGRESS_H) / 2 + PAD_SMALL, ((PROGRESS_W - PAD_SMALL * 2) * opt) / 100, PROGRESS_H - PAD_SMALL * 2, color);
lcd.drawRect(PROGRESS_X, (LCD_H - PROGRESS_H) / 2, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED);
lcd.drawSolidFilledRect(PROGRESS_X + PAD_SMALL, (LCD_H - PROGRESS_H) / 2 + PAD_SMALL, ((PROGRESS_W - PAD_SMALL * 2) * opt) / 100, PROGRESS_H - PAD_SMALL * 2, color);
} else if (st == ST_DIR_CHECK) {
if (opt == FR_NO_PATH) {
lcd->drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_DIR_MISSING, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_DIR_MISSING, CENTERED | BL_FOREGROUND);
} else {
lcd->drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_DIR_EMPTY, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_DIR_EMPTY, CENTERED | BL_FOREGROUND);
}
} else if (st == ST_FLASH_CHECK) {
bootloaderDrawFilename(str, 0, true);
if (opt == FC_ERROR) {
lcd->drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE, CENTERED | BL_FOREGROUND);
} else if (opt == FC_OK) {
VersionTag tag;
memset(&tag, 0, sizeof(tag));
getFileFirmwareVersion(&tag);
if (strcmp(tag.flavour, FLAVOUR)) {
lcd->drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE, CENTERED | BL_FOREGROUND);
lcd.drawText(LCD_W / 2, LCD_H / 2, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE, CENTERED | BL_FOREGROUND);
} else {
lcd->drawText(VERCHK_X, VERCHK_Y, TR_BL_FORK, RIGHT | BL_FOREGROUND);
lcd->drawSizedText(VERCHK_X + PAD_MEDIUM, VERCHK_Y, tag.fork, 6, BL_FOREGROUND);
lcd.drawText(VERCHK_X, VERCHK_Y, TR_BL_FORK, RIGHT | BL_FOREGROUND);
lcd.drawSizedText(VERCHK_X + PAD_MEDIUM, VERCHK_Y, tag.fork, 6, BL_FOREGROUND);
lcd->drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, TR_BL_VERSION, RIGHT | BL_FOREGROUND);
lcd->drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, tag.version, BL_FOREGROUND);
lcd.drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, TR_BL_VERSION, RIGHT | BL_FOREGROUND);
lcd.drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, tag.version, BL_FOREGROUND);
lcd->drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, TR_BL_RADIO, RIGHT | BL_FOREGROUND);
lcd->drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, tag.flavour, BL_FOREGROUND);
lcd.drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, TR_BL_RADIO, RIGHT | BL_FOREGROUND);
lcd.drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, tag.flavour, BL_FOREGROUND);
lcd->drawText(VERCHK_ICN_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, LV_SYMBOL_OK, BL_GREEN);
lcd.drawText(VERCHK_ICN_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, LV_SYMBOL_OK, BL_GREEN);
}
}
}
@@ -397,16 +394,16 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
int align = FOOTER_ALIGN2;
if ( st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
if (st == ST_FILE_LIST) {
pos = lcd->drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_SELECT_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_SELECT_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
}
else if (st == ST_FLASH_CHECK && opt == FC_OK) {
pos = lcd->drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_FLASH_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_FLASH_KEY, FOOTER_ALIGN1 | BL_FOREGROUND);
}
else if (st == ST_FLASHING) {
pos = lcd->drawText(LCD_W / 2, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_WRITING_FW, CENTERED | BL_FOREGROUND);
pos = lcd.drawText(LCD_W / 2, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_WRITING_FW, CENTERED | BL_FOREGROUND);
}
else if (st == ST_FLASH_DONE) {
pos = lcd->drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_WRITING_COMPL, FOOTER_ALIGN1 | BL_FOREGROUND);
pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_WRITING_COMPL, FOOTER_ALIGN1 | BL_FOREGROUND);
}
}
#if LANDSCAPE
@@ -419,18 +416,18 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
}
#endif
if (st != ST_FLASHING) {
lcd->drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, align | BL_FOREGROUND);
lcd.drawText(FOOTER_X2 - pos, LCD_H - FOOTER_Y2, LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, align | BL_FOREGROUND);
}
}
}
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
{
lcd->drawText(FILENAM_X1, FILENAM_Y1 + (line * FILENAM_H), LV_SYMBOL_FILE, BL_FOREGROUND);
lcd->drawText(FILENAM_X2, FILENAM_Y1 + (line * FILENAM_H), str, BL_FOREGROUND);
lcd.drawText(FILENAM_X1, FILENAM_Y1 + (line * FILENAM_H), LV_SYMBOL_FILE, BL_FOREGROUND);
lcd.drawText(FILENAM_X2, FILENAM_Y1 + (line * FILENAM_H), str, BL_FOREGROUND);
if (selected) {
lcd->drawSolidRect(FILESEL_X, BOX_Y + (line * FILENAM_H), FILESEL_W, BOX_H, PAD_TINY, BL_SELECTED);
lcd.drawSolidRect(FILESEL_X, BOX_Y + (line * FILENAM_H), FILESEL_W, BOX_H, PAD_TINY, BL_SELECTED);
}
}
+37 -54
View File
@@ -40,49 +40,43 @@ char* get_lvgl_mem(int nbytes)
}
#endif
pixel_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
BitmapBuffer lcdBuffer1(BMP_RGB565, LCD_W, LCD_H,
(uint16_t*)LCD_FIRST_FRAME_BUFFER);
BitmapBuffer lcdBuffer2(BMP_RGB565, LCD_W, LCD_H,
(uint16_t*)LCD_SECOND_FRAME_BUFFER);
static BitmapBuffer* lcdFront = &lcdBuffer1;
static BitmapBuffer* lcd = &lcdBuffer2;
pixel_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
static lv_disp_draw_buf_t disp_buf;
static lv_disp_drv_t disp_drv;
// Call backs
static void (*lcd_wait_cb)(lv_disp_drv_t*) = nullptr;
static void (*lcd_flush_cb)(lv_disp_drv_t*, uint16_t* buffer,
const rect_t& area) = nullptr;
void lcdSetWaitCb(void (*cb)(lv_disp_drv_t*)) { lcd_wait_cb = cb; }
void lcdSetFlushCb(void (*cb)(lv_disp_drv_t*, uint16_t*, const rect_t&))
{
lcd_flush_cb = cb;
}
static lv_disp_drv_t* refr_disp = nullptr;
#if defined(SIMU)
// Only used in simulator to prevent lock up when closing simulator
// TODO: find a better way to handle this
static void (*lcd_wait_cb)(lv_disp_drv_t*) = nullptr;
void lcdSetWaitCb(void (*cb)(lv_disp_drv_t*)) { lcd_wait_cb = cb; }
#endif
extern "C" void lcdFlushed()
{
lv_disp_flush_ready(&disp_drv);
}
void lcdRefresh() {}
static void flushLcd(lv_disp_drv_t* disp_drv, const lv_area_t* area,
lv_color_t* color_p)
{
#if !LCD_VERTICAL_INVERT || defined(RADIO_F16)
#if defined(RADIO_F16)
if (hardwareOptions.pcbrev > 0)
#endif
{
// we're only interested in the last flush in direct mode
if (!lv_disp_flush_is_last(disp_drv)) {
lv_disp_flush_ready(disp_drv);
return;
}
// we're only interested in the last flush in direct mode
if (disp_drv->direct_mode && !lv_disp_flush_is_last(disp_drv)) {
lv_disp_flush_ready(disp_drv);
return;
}
#endif
#if defined(DEBUG_WINDOWS)
if (area->x1 != 0 || area->x2 != LCD_W - 1 || area->y1 != 0 ||
@@ -95,15 +89,13 @@ static void flushLcd(lv_disp_drv_t* disp_drv, const lv_area_t* area,
#endif
if (lcd_flush_cb) {
refr_disp = disp_drv;
rect_t copy_area = {area->x1, area->y1, area->x2 - area->x1 + 1,
area->y2 - area->y1 + 1};
lcd_flush_cb(disp_drv, (uint16_t*)color_p, copy_area);
} else {
lcdFlushed();
}
lv_disp_flush_ready(disp_drv);
}
static void clear_frame_buffers()
@@ -114,25 +106,30 @@ static void clear_frame_buffers()
static void init_lvgl_disp_drv()
{
lv_disp_draw_buf_init(&disp_buf, lcdFront->getData(), lcd->getData(),
int direct_mode = 1;
#if LCD_VERTICAL_INVERT
#if defined(RADIO_F16)
direct_mode = (hardwareOptions.pcbrev > 0) ? 1 : 0;
#else
direct_mode = 0;
#endif
#endif
lv_disp_draw_buf_init(&disp_buf,
LCD_FIRST_FRAME_BUFFER,
direct_mode ? LCD_SECOND_FRAME_BUFFER : nullptr,
LCD_W * LCD_H);
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.draw_buf = &disp_buf; /*Set an initialized buffer*/
disp_drv.flush_cb = flushLcd; /*Set a flush callback to draw to the display*/
#if defined(SIMU)
disp_drv.wait_cb = lcd_wait_cb; /*Set a wait callback*/
#endif
disp_drv.hor_res = LCD_W; /*Set the horizontal resolution in pixels*/
disp_drv.ver_res = LCD_H; /*Set the vertical resolution in pixels*/
disp_drv.full_refresh = 0;
#if !LCD_VERTICAL_INVERT
disp_drv.direct_mode = 1;
#elif defined(RADIO_F16)
disp_drv.direct_mode = (hardwareOptions.pcbrev > 0) ? 1 : 0;
#else
disp_drv.direct_mode = 0;
#endif
disp_drv.direct_mode = direct_mode;
}
void lcdInitDisplayDriver()
@@ -153,7 +150,7 @@ void lcdInitDisplayDriver()
// Clear buffers first
clear_frame_buffers();
lcdSetInitalFrameBuffer(lcdFront->getData());
lcdSetInitalFrameBuffer(LCD_FIRST_FRAME_BUFFER);
// Init hardware LCD driver
lcdInit();
@@ -167,17 +164,3 @@ void lcdInitDisplayDriver()
// remove all styles on default screen (makes it transparent as well)
lv_obj_remove_style_all(lv_scr_act());
}
void lcdFlushed()
{
// Only used in simulator
// its possible to get here before flushLcd is ever called.
// so check for nullptr first. (Race condition if you put breakpoints in
// startup code)
if (refr_disp != nullptr) lv_disp_flush_ready(refr_disp);
}
#if defined(SIMU)
void lcdRefresh() {}
#endif
+4 -5
View File
@@ -39,17 +39,16 @@ struct _lv_disp_drv_t;
typedef _lv_disp_drv_t lv_disp_drv_t;
// Call backs
void lcdSetWaitCb(void (*cb)(lv_disp_drv_t *));
void lcdSetFlushCb(void (*cb)(lv_disp_drv_t *, uint16_t*, const rect_t&));
#if defined(SIMU)
void lcdSetWaitCb(void (*cb)(lv_disp_drv_t *));
#endif
// Init LVGL and its display driver
void lcdInitDisplayDriver();
void lcdClear();
// Patch the draw context to allow for direct drawing
void lcdInitDirectDrawing();
void lcdRefresh();
void lcdFlushed();
extern "C" void lcdFlushed();
+2
View File
@@ -173,3 +173,5 @@ void drawTelemetryTopBar();
void lcdDraw1bitBitmap(coord_t x, coord_t y, const unsigned char * img, uint8_t idx, LcdFlags att=0);
uint8_t getTextWidth(const char * s, uint8_t len=0, LcdFlags flags=0);
void lcdFlushed();
+51 -53
View File
@@ -32,6 +32,7 @@
#include "lcd.h"
#include <lvgl/lvgl.h>
#include <vector>
#if defined(RADIO_T18)
#define HBP 43
@@ -60,17 +61,29 @@ static void* initialFrameBuffer = nullptr;
#if LCD_VERTICAL_INVERT
typedef uint16_t pixel_t;
static pixel_t _LCD_BUF_1[DISPLAY_BUFFER_SIZE] __SDRAM;
static pixel_t _LCD_BUF_2[DISPLAY_BUFFER_SIZE] __SDRAM;
static pixel_t _line_buffer[LCD_W];
static pixel_t _LCD_BUF_1[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
#if defined(RADIO_F16)
// F16 can be either normal or inverted
static pixel_t _LCD_BUF_2[DISPLAY_BUFFER_SIZE] __SDRAM __ALIGNED(64);
#else
// LVGL will only use one buffer when display is inverted so reuse 2nd
// buffer here
extern pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE];
#define _LCD_BUF_2 LCD_SECOND_FRAME_BUFFER
#endif
// Frame buffer pointers
static uint16_t* _front_buffer = _LCD_BUF_1;
static uint16_t* _back_buffer = _LCD_BUF_2;
// Vector to save areas that need to be copied from front buffer to back buffer
static std::vector<lv_area_t> dma_areas;
// Copy 2 pixels at once to speed up a little
static void _copy_rotate_180(uint16_t* dst, uint16_t* src, const rect_t& copy_area)
{
static pixel_t _line_buffer[LCD_W];
coord_t x1 = LCD_W - copy_area.w - copy_area.x;
coord_t y1 = LCD_H - copy_area.h - copy_area.y;
@@ -106,50 +119,44 @@ static void _copy_rotate_180(uint16_t* dst, uint16_t* src, const rect_t& copy_ar
dst -= LCD_W;
}
}
static void _rotate_area_180(lv_area_t& area)
{
lv_coord_t tmp_coord;
tmp_coord = area.y2;
area.y2 = LCD_H - area.y1 - 1;
area.y1 = LCD_H - tmp_coord - 1;
tmp_coord = area.x2;
area.x2 = LCD_W - area.x1 - 1;
area.x1 = LCD_W - tmp_coord - 1;
}
#endif
static volatile uint8_t _frame_addr_reloaded = 0;
static void _update_frame_buffer_addr(uint16_t* addr)
{
LTDC_Layer1->CFBAR = (uint32_t)addr;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
#if LCD_VERTICAL_INVERT
#if defined(RADIO_F16)
if(hardwareOptions.pcbrev > 0) {
// Direct mode
if (disp_drv->direct_mode) {
// Direct mode / not inverted
_update_frame_buffer_addr(buffer);
} else
#endif
{
return;
}
// Copy areas that were updated last frame to the back buffer
if (dma_areas.size() > 0) {
for (auto a: dma_areas) {
DMACopyBitmap(_back_buffer, LCD_W, LCD_H, a.x1, a.y1,
_front_buffer, LCD_W, LCD_H, a.x1, a.y1,
a.x2 - a.x1 + 1, a.y2 - a.y1 + 1);
}
dma_areas.clear();
DMAWait();
}
// Copy changes from LVGL to LCD back buffer with 180 degree rotation
_copy_rotate_180(_back_buffer, buffer, copy_area);
// Check for last LVGL update before we need to swap buffers
if (lv_disp_flush_is_last(disp_drv)) {
// swap back/front
// swap back/front buffers
if (_front_buffer == _LCD_BUF_1) {
_front_buffer = _LCD_BUF_2;
_back_buffer = _LCD_BUF_1;
@@ -161,30 +168,22 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
// Trigger async refresh
_update_frame_buffer_addr(_front_buffer);
// Copy refreshed & rotated areas into new back buffer
uint16_t* src = _front_buffer;
uint16_t* dst = _back_buffer;
// Save areas that need to be updated next time around
lv_disp_t* disp = _lv_refr_get_disp_refreshing();
for(int i = 0; i < disp->inv_p; i++) {
if(disp->inv_area_joined[i]) continue;
// Rotate area 180 degrees
lv_area_t refr_area;
lv_area_copy(&refr_area, &disp->inv_areas[i]);
refr_area.x1 = LCD_W - disp->inv_areas[i].x2 - 1;
refr_area.x2 = LCD_W - disp->inv_areas[i].x1 - 1;
refr_area.y1 = LCD_H - disp->inv_areas[i].y2 - 1;
refr_area.y2 = LCD_H - disp->inv_areas[i].y1 - 1;
// TRACE("Vert invert refresh {%d,%d,%d,%d}", refr_area.x1,
// refr_area.y1, refr_area.x2 - refr_area.x1 + 1, refr_area.y2 - refr_area.y1 + 1);
_rotate_area_180(refr_area);
auto area_w = refr_area.x2 - refr_area.x1 + 1;
auto area_h = refr_area.y2 - refr_area.y1 + 1;
DMACopyBitmap(dst, LCD_W, LCD_H, refr_area.x1, refr_area.y1,
src, LCD_W, LCD_H, refr_area.x1, refr_area.y1,
area_w, area_h);
dma_areas.push_back(refr_area);
}
}
} else {
lv_disp_flush_ready(disp_drv);
}
#else
// Direct mode
@@ -337,7 +336,6 @@ void LCD_Init_LTDC()
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, LCD_PHYS_H);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
#if 0
DMA2D_ITConfig(DMA2D_CR_TCIE, ENABLE);
@@ -425,8 +423,8 @@ void lcdInit()
{
#if LCD_VERTICAL_INVERT
// Clear buffer first
memset(_LCD_BUF_1, 0, sizeof(_LCD_BUF_1));
memset(_LCD_BUF_2, 0, sizeof(_LCD_BUF_2));
memset(_LCD_BUF_1, 0, DISPLAY_BUFFER_SIZE * sizeof(pixel_t));
memset(_LCD_BUF_2, 0, DISPLAY_BUFFER_SIZE * sizeof(pixel_t));
#endif
// Initialize the LCD
@@ -439,11 +437,11 @@ void lcdInit()
lcdSetFlushCb(startLcdRefresh);
}
extern "C" void LTDC_IRQHandler(void)
{
// clear interrupt flag
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
_frame_addr_reloaded = 1;
}
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
lcdFlushed();
}
+3 -10
View File
@@ -36,24 +36,17 @@
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t* disp_drv, uint16_t* buffer,
const rect_t& copy_area)
{
(void)disp_drv;
(void)copy_area;
LTDC_Layer1->CFBAR &= ~(LTDC_LxCFBAR_CFBADD);
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while (_frame_addr_reloaded == 0);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
uint32_t lcdPixelClock;
@@ -389,7 +382,6 @@ void LCD_Init_LTDC()
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, LCD_W);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
void LCD_LayerInit()
@@ -466,5 +458,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
lcdFlushed();
}
+2
View File
@@ -120,6 +120,8 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
set_row_addr(y1, y2);
memory_write(buffer, copy_area.w * copy_area.h);
lcdFlushed();
}
lcdSpiInitFucPtr lcdInitFunction;
+3 -11
View File
@@ -40,24 +40,17 @@ static void* initialFrameBuffer = nullptr;
#define GPIO_AF_LTDC GPIO_AF14
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
(void)disp_drv;
(void)copy_area;
LTDC_Layer1->CFBAR &= ~(LTDC_LxCFBAR_CFBADD);
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
lcdSpiInitFucPtr lcdInitFunction;
@@ -2763,7 +2756,6 @@ void LCD_Init_LTDC() {
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
void LCD_LayerInit() {
@@ -2887,6 +2879,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
}
lcdFlushed();
}
+2 -2
View File
@@ -84,7 +84,6 @@ rotenc_t rotaryEncoderGetValue()
extern const etx_hal_adc_driver_t simu_adc_driver;
void lcdCopy(void * dest, void * src);
void lcdFlushed();
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
static void hostSerialInit();
@@ -733,7 +732,8 @@ void simuLuaReloadPermanentScripts()
void simuLcdFlushed()
{
::lcdFlushed();
if (simu_running)
lcdFlushed();
}
uint8_t simuGetMaxTrainerChannels()
+2 -10
View File
@@ -40,8 +40,6 @@ static volatile uint16_t lcd_phys_h = LCD_PHYS_H;
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
@@ -53,16 +51,10 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
SCB_CleanDCache();
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
}
lcdSpiInitFucPtr lcdInitFunction;
@@ -2760,7 +2752,6 @@ void LCD_Init_LTDC() {
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
void LCD_LayerInit() {
@@ -2885,5 +2876,6 @@ extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
lcdFlushed();
}
+2 -10
View File
@@ -417,8 +417,6 @@ extern "C" void backlightInit()
LPTIMx_PWM_Init(&hlcd_lptim);
}
static volatile uint8_t _frame_addr_reloaded = 0;
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
@@ -427,18 +425,11 @@ static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
SCB_CleanDCache();
LTDC_Layer1->CFBAR &= ~(LTDC_LxCFBAR_CFBADD);
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hlcd_ltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
}
extern "C" void lcdSetInitalFrameBuffer(void* fbAddress)
@@ -460,5 +451,6 @@ extern "C" void LTDC_IRQHandler(void)
// clear interrupt flag
__HAL_LTDC_CLEAR_FLAG(&hlcd_ltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hlcd_ltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
lcdFlushed();
}
-1
View File
@@ -312,7 +312,6 @@ void lcdSetInvert(bool invert);
#ifdef __cplusplus
void lcdSetContrast(bool useDefault = false);
#endif
void lcdFlushed();
// Top LCD driver
#if defined(TOPLCD_GPIO)