fix(color): screen refresh may be slower on some radios after update to LVGL 8.4 (#6349)

This commit is contained in:
philmoz
2025-06-17 12:45:02 +10:00
committed by GitHub
parent 7c7558b67b
commit e9a9bde60d
16 changed files with 416 additions and 260 deletions
+1 -1
View File
@@ -192,7 +192,7 @@ list(TRANSFORM LVGL_FONT_SOURCES_MINIMAL PREPEND ${RADIO_SRC_DIR}/)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${LVGL_SOURCES_MINIMAL}
${LVGL_FONT_SOURCES_MINIMAL}
${RADIO_SRC_DIR}/gui/colorlcd/lcd.cpp
${RADIO_SRC_DIR}/gui/colorlcd/boot_lcd.cpp
${RADIO_SRC_DIR}/gui/colorlcd/fonts.cpp
${RADIO_SRC_DIR}/gui/colorlcd/colors.cpp
${RADIO_SRC_DIR}/gui/colorlcd/bitmaps.cpp
+217
View File
@@ -0,0 +1,217 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include "lcd.h"
#include <lvgl/lvgl.h>
#if LV_USE_GPU_STM32_DMA2D
#include <lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h>
#else
#include "dma2d.h"
#endif
#include "bitmapbuffer.h"
#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;
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;
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;
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);
}
lv_disp_flush_ready(disp_drv);
}
static void clear_frame_buffers()
{
memset(LCD_FIRST_FRAME_BUFFER, 0, sizeof(LCD_FIRST_FRAME_BUFFER));
memset(LCD_SECOND_FRAME_BUFFER, 0, sizeof(LCD_SECOND_FRAME_BUFFER));
}
static void init_lvgl_disp_drv()
{
lv_disp_draw_buf_init(&disp_buf, lcdFront->getData(), lcd->getData(), 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 !defined(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
}
void lcdInitDisplayDriver()
{
static bool lcdDriverStarted = false;
// we already have a display: exit
if (lcdDriverStarted) return;
lcdDriverStarted = true;
#if LV_USE_GPU_STM32_DMA2D
// Init only DMA2D
lv_draw_stm32_dma2d_init();
#else
DMAInit();
#endif
// Clear buffers first
clear_frame_buffers();
lcdSetInitalFrameBuffer(lcdFront->getData());
// Init hardware LCD driver
lcdInit();
backlightInit();
init_lvgl_disp_drv();
// allow drawing at any moment
lv_memset_00(&disp, sizeof(lv_disp_t));
disp.driver = &disp_drv;
_lv_refr_set_disp_refreshing(&disp);
if (disp_drv.draw_ctx == NULL) {
lv_draw_ctx_t* draw_ctx =
(lv_draw_ctx_t*)lv_mem_alloc(disp_drv.draw_ctx_size);
LV_ASSERT_MALLOC(draw_ctx);
if (draw_ctx == NULL) return;
disp_drv.draw_ctx_init(&disp_drv, draw_ctx);
disp_drv.draw_ctx = draw_ctx;
}
lv_draw_ctx_t* draw_ctx = disp_drv.draw_ctx;
lcd->setDrawCtx(draw_ctx);
lcdFront->setDrawCtx(draw_ctx);
}
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();
}
//
// Private code copied and adapted from LVGL / lv_refr.c
// (_call_flush_cb & _draw_buf_flush)
//
static void _call_flush_cb(lv_disp_drv_t* drv, const lv_area_t* area,
lv_color_t* color_p)
{
lv_area_t offset_area = {.x1 = (lv_coord_t)(area->x1 + drv->offset_x),
.y1 = (lv_coord_t)(area->y1 + drv->offset_y),
.x2 = (lv_coord_t)(area->x2 + drv->offset_x),
.y2 = (lv_coord_t)(area->y2 + drv->offset_y)};
drv->flush_cb(drv, &offset_area, color_p);
}
static void _draw_buf_flush(lv_disp_t* disp)
{
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;
if (disp->driver->flush_cb) {
_call_flush_cb(disp->driver, draw_ctx->buf_area,
(lv_color_t*)draw_ctx->buf);
}
/*If there are 2 buffers swap them. */
if (draw_buf->buf1 && draw_buf->buf2) {
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);
}
+16 -118
View File
@@ -23,14 +23,12 @@
#include <lvgl/lvgl.h>
#if LV_USE_GPU_STM32_DMA2D
#include <lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h>
#endif
#include "bitmapbuffer.h"
#include "board.h"
#include "dma2d.h"
#include "etx_lv_theme.h"
#if !LV_USE_GPU_STM32_DMA2D && !defined(SIMU)
#include "dma2d.h"
#endif
pixel_t LCD_FIRST_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
pixel_t LCD_SECOND_FRAME_BUFFER[DISPLAY_BUFFER_SIZE] __SDRAM;
@@ -40,16 +38,12 @@ BitmapBuffer lcdBuffer1(BMP_RGB565, LCD_W, LCD_H,
BitmapBuffer lcdBuffer2(BMP_RGB565, LCD_W, LCD_H,
(uint16_t*)LCD_SECOND_FRAME_BUFFER);
BitmapBuffer* lcdFront = &lcdBuffer1;
BitmapBuffer* lcd = &lcdBuffer2;
static BitmapBuffer* lcdFront = &lcdBuffer1;
static BitmapBuffer* lcd = &lcdBuffer2;
static lv_disp_draw_buf_t disp_buf;
static lv_disp_drv_t disp_drv;
#if defined(BOOT)
static lv_disp_t disp;
#endif
// Call backs
static void (*lcd_wait_cb)(lv_disp_drv_t*) = nullptr;
static void (*lcd_flush_cb)(lv_disp_drv_t*, uint16_t* buffer,
@@ -67,7 +61,7 @@ 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 (!defined(LCD_VERTICAL_INVERT) || defined(RADIO_F16)) && !defined(BOOT)
#if !defined(LCD_VERTICAL_INVERT) || defined(RADIO_F16)
#if defined(RADIO_F16)
if (hardwareOptions.pcbrev > 0)
#endif
@@ -123,13 +117,10 @@ static void init_lvgl_disp_drv()
disp_drv.full_refresh = 0;
#if !defined(LCD_VERTICAL_INVERT)
disp_drv.full_refresh = 1;
disp_drv.direct_mode = 1;
#elif defined(RADIO_F16)
disp_drv.full_refresh = 1;
disp_drv.direct_mode = (hardwareOptions.pcbrev > 0) ? 1 : 0;
#else
disp_drv.full_refresh = 0;
disp_drv.direct_mode = 0;
#endif
}
@@ -141,15 +132,14 @@ void lcdInitDisplayDriver()
if (lcdDriverStarted) return;
lcdDriverStarted = true;
#if !defined(BOOT)
#if !LV_USE_GPU_STM32_DMA2D && !defined(SIMU)
DMAInit();
#endif
// Full LVGL init in firmware mode
lv_init();
// Initialise styles
useMainStyle();
#elif LV_USE_GPU_STM32_DMA2D
// Otherwise init only DMA2D
lv_draw_stm32_dma2d_init();
#endif
// Clear buffers first
clear_frame_buffers();
@@ -161,115 +151,23 @@ void lcdInitDisplayDriver()
init_lvgl_disp_drv();
#if !defined(BOOT)
// Register the driver and save the created display object
lv_disp_t* d = lv_disp_drv_register(&disp_drv);
lv_disp_drv_register(&disp_drv);
// remove all styles on default screen (makes it transparent as well)
lv_obj_remove_style_all(lv_scr_act());
// transparent background:
// - this prevents LVGL overwritting things drawn directly into the bitmap
// buffer
lv_disp_set_bg_opa(d, LV_OPA_TRANSP);
// allow drawing at any moment
_lv_refr_set_disp_refreshing(d);
#else
// allow drawing at any moment
lv_memset_00(&disp, sizeof(lv_disp_t));
disp.driver = &disp_drv;
_lv_refr_set_disp_refreshing(&disp);
if (disp_drv.draw_ctx == NULL) {
lv_draw_ctx_t* draw_ctx =
(lv_draw_ctx_t*)lv_mem_alloc(disp_drv.draw_ctx_size);
LV_ASSERT_MALLOC(draw_ctx);
if (draw_ctx == NULL) return;
disp_drv.draw_ctx_init(&disp_drv, draw_ctx);
disp_drv.draw_ctx = draw_ctx;
}
#endif
lv_draw_ctx_t* draw_ctx = disp_drv.draw_ctx;
lcd->setDrawCtx(draw_ctx);
lcdFront->setDrawCtx(draw_ctx);
}
void lcdClear() { lcd->clear(); }
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);
}
// Direct drawing - used by boot loader and battery charging state
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();
}
//
// Private code copied and adapted from LVGL / lv_refr.c
// (_call_flush_cb & _draw_buf_flush)
//
static void _call_flush_cb(lv_disp_drv_t* drv, const lv_area_t* area,
lv_color_t* color_p)
{
lv_area_t offset_area = {.x1 = (lv_coord_t)(area->x1 + drv->offset_x),
.y1 = (lv_coord_t)(area->y1 + drv->offset_y),
.x2 = (lv_coord_t)(area->x2 + drv->offset_x),
.y2 = (lv_coord_t)(area->y2 + drv->offset_y)};
drv->flush_cb(drv, &offset_area, color_p);
}
static void _draw_buf_flush(lv_disp_t* disp)
{
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;
if (disp->driver->flush_cb) {
_call_flush_cb(disp->driver, draw_ctx->buf_area,
(lv_color_t*)draw_ctx->buf);
}
/*If there are 2 buffers swap them. */
if (draw_buf->buf1 && draw_buf->buf2) {
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);
}
#if defined(SIMU)
void lcdRefresh() {}
#endif
@@ -262,9 +262,3 @@ class BitmapBuffer
lv_obj_t* canvas = nullptr;
lv_draw_ctx_t* draw_ctx = nullptr;
};
// Back buffer to draw
extern BitmapBuffer* lcd;
// Buffer currently on display
extern BitmapBuffer* lcdFront;
+1 -5
View File
@@ -205,11 +205,7 @@
#define LV_USE_GPU_ARM2D 0
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
#if defined(SIMU)
#define LV_USE_GPU_STM32_DMA2D 0
#else //SIMU
#define LV_USE_GPU_STM32_DMA2D 1
#endif
#define LV_USE_GPU_STM32_DMA2D 0
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
@@ -25,6 +25,35 @@
#include "libopenui_defines.h"
#include "dma2d.h"
#if !LV_USE_GPU_STM32_DMA2D
/**
* Turn on the peripheral and set output color mode, this only needs to be done once
*
* Copied from LVGL code
*/
void DMAInit(void)
{
// Enable DMA2D clock
#if defined(STM32F4) || defined(STM32F7) || defined(STM32U5)
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; // enable DMA2D
// wait for hardware access to complete
__asm volatile("DSB\n");
volatile uint32_t temp = RCC->AHB1ENR;
LV_UNUSED(temp);
#elif defined(STM32H7)
RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN;
// wait for hardware access to complete
__asm volatile("DSB\n");
volatile uint32_t temp = RCC->AHB3ENR;
LV_UNUSED(temp);
#else
# warning "LVGL can't enable the clock of DMA2D"
#endif
// AHB master timer configuration
DMA2D->AMTCR = 0; // AHB bus guaranteed dead time disabled
}
#endif
void DMACopyBitmap(uint16_t *dest, uint16_t destw, uint16_t desth, uint16_t x,
uint16_t y, const uint16_t *src, uint16_t srcw,
uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w,
+2 -1
View File
@@ -23,7 +23,7 @@
#include "edgetx_types.h"
#if !defined(SIMU)
#if !defined(SIMU) && !defined(BOOT)
static inline void DMAWait()
{
while(DMA2D->CR & DMA2D_CR_START);
@@ -32,6 +32,7 @@ static inline void DMAWait()
static inline void DMAWait() {}
#endif
void DMAInit();
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h);
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h);
-8
View File
@@ -234,14 +234,6 @@ void boardInit()
#else
ledGreen();
#endif
#if !defined(LCD_VERTICAL_INVERT)
lcdSetInitalFrameBuffer(lcdFront->getData());
#elif defined(RADIO_F16)
if(hardwareOptions.pcbrev > 0) {
lcdSetInitalFrameBuffer(lcdFront->getData());
}
#endif
}
#endif
-2
View File
@@ -218,8 +218,6 @@ void boardInit()
#if defined(RTCLOCK)
rtcInit(); // RTC must be initialized before rambackupRestore() is called
#endif
lcdSetInitalFrameBuffer(lcdFront->getData());
}
extern void rtcDisableBackupReg();
+71 -47
View File
@@ -315,47 +315,75 @@ void ledChargingInfo(uint16_t chargeState) {
#endif
}
static Window* chargeWindow = nullptr;
void drawChargingInfo(uint16_t chargeState) {
static int progress = 0;
const char* text = chargeState == CHARGE_STARTED ? STR_BATTERYCHARGING : STR_BATTERYFULL;
int h = 0;
LcdFlags color = 0;
if (CHARGE_STARTED == chargeState)
{
if (progress >= 100)
{
progress = 0;
}
else
{
progress += 25;
}
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 100);
color = COLOR_THEME_EDIT;
static int progress = -1;
static StaticText* stateText = nullptr;
static lv_obj_t* battBox = nullptr;
const char* text;
int h;
LcdColorIndex color = COLOR_THEME_EDIT_INDEX;
switch (chargeState) {
case CHARGE_STARTED:
progress += 1;
if (progress > 4) progress = 0;
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 4);
break;
case CHARGE_FINISHED:
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
break;
default:
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = COLOR_THEME_PRIMARY1_INDEX;
break;
}
else if (CHARGE_FINISHED == chargeState)
{
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
color = COLOR_THEME_EDIT;
}
else
{
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = COLOR_THEME_PRIMARY1;
if (chargeWindow == nullptr) {
chargeWindow = new Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H});
etx_solid_bg(chargeWindow->getLvObj(), COLOR_THEME_PRIMARY1_INDEX);
stateText = new StaticText(chargeWindow, {0, LCD_H - 50, LCD_W, 50}, "", COLOR_THEME_PRIMARY2_INDEX, CENTERED);
lv_obj_t* box = lv_obj_create(chargeWindow->getLvObj());
lv_obj_set_pos(box, (LCD_W - BATTERY_W) / 2, BATTERY_TOP);
lv_obj_set_size(box, BATTERY_W, BATTERY_H);
lv_obj_set_style_border_opa(box, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_border_width(box, 2, LV_PART_MAIN);
etx_border_color(box, COLOR_THEME_PRIMARY2_INDEX);
box = lv_obj_create(chargeWindow->getLvObj());
lv_obj_set_pos(box, (LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H);
lv_obj_set_size(box, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H);
etx_solid_bg(box, COLOR_THEME_PRIMARY2_INDEX);
battBox = lv_obj_create(chargeWindow->getLvObj());
}
stateText->setText(text);
lv_obj_set_pos(battBox, (LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h);
lv_obj_set_size(battBox, BATTERY_W_INNER, h);
etx_solid_bg(battBox, color);
LvglWrapper::instance()->run();
lv_refr_now(nullptr);
BACKLIGHT_ENABLE();
lcd->drawSizedText(LCD_W / 2, LCD_H - 50, text, strlen(text), CENTERED | COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W) / 2, BATTERY_TOP, BATTERY_W, BATTERY_H, SOLID, COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER, BATTERY_W_INNER, BATTERY_H_INNER, SOLID, COLOR_THEME_PRIMARY1);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h, BATTERY_W_INNER, h, SOLID, color);
lcd->drawFilledRect((LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H, SOLID, COLOR_THEME_PRIMARY2);
}
void battery_charge_end()
{
chargeWindow->clear();
delete chargeWindow;
chargeWindow = nullptr;
}
#define CHARGE_INFO_DURATION 5000 // ms
//this method should be called by timer interrupt or by GPIO interrupt
@@ -385,6 +413,12 @@ void handle_battery_charge(uint32_t last_press_time)
lastState = chargeState;
}
if (!lcdInited) {
lcdInited = true;
backlightInit();
lcdInitDisplayDriver();
}
if (updateTime == 0 || ((timersGetMsTick() - updateTime) >= 500))
{
updateTime = timersGetMsTick();
@@ -392,25 +426,17 @@ void handle_battery_charge(uint32_t last_press_time)
if(now > info_until) {
info_until = 0;
lcd->clear();
BACKLIGHT_DISABLE();
if(lcdInited) {
lcdOff();
}
} else {
if (!lcdInited) {
backlightInit();
lcdInit();
lcdInitDisplayDriver();
lcdInited = true;
} else {
if (lcdInited) {
lcdOn();
}
lcdInitDirectDrawing();
lcd->clear();
drawChargingInfo(chargeState);
// DEBUG INFO
// DEBUG INFO - TODO delete or replace with LVGL objects
#if 0
char buffer[1024];
@@ -431,8 +457,6 @@ void handle_battery_charge(uint32_t last_press_time)
sprintf(buffer, "%d", isChargerActive());
lcd->drawSizedText(100, 130, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
#endif
lcdRefresh();
}
}
+2 -10
View File
@@ -19,14 +19,7 @@
* GNU General Public License for more details.
*/
/***************************************************************************************************
***************************************************************************************************/
#ifndef __BATTERY_DRIVER_H__
#define __BATTERY_DRIVER_H__
/***************************************************************************************************
***************************************************************************************************/
#pragma once
#include "board.h"
#include "hal.h"
@@ -54,5 +47,4 @@ extern void handle_battery_charge(uint32_t last_press_time);
extern uint16_t get_battery_charge_state();
extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
extern bool isChargerActive();
#endif
extern void battery_charge_end();
+1 -2
View File
@@ -260,6 +260,7 @@ void boardInit()
press_end = 0;
}
}
battery_charge_end();
}
keysInit();
@@ -287,8 +288,6 @@ void boardInit()
ledGreen();
#endif
#endif
lcdSetInitalFrameBuffer(lcdFront->getData());
}
extern void rtcDisableBackupReg();
+71 -47
View File
@@ -230,47 +230,75 @@ void ledChargingInfo(uint16_t chargeState) {
#endif
}
static Window* chargeWindow = nullptr;
void drawChargingInfo(uint16_t chargeState) {
static int progress = 0;
const char* text = chargeState == CHARGE_STARTED ? STR_BATTERYCHARGING : STR_BATTERYFULL;
int h = 0;
LcdFlags color = 0;
if (CHARGE_STARTED == chargeState)
{
if (progress >= 100)
{
progress = 0;
}
else
{
progress += 25;
}
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 100);
color = COLOR_THEME_EDIT;
static int progress = -1;
static StaticText* stateText = nullptr;
static lv_obj_t* battBox = nullptr;
const char* text;
int h;
LcdColorIndex color = COLOR_THEME_EDIT_INDEX;
switch (chargeState) {
case CHARGE_STARTED:
progress += 1;
if (progress > 4) progress = 0;
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 4);
break;
case CHARGE_FINISHED:
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
break;
default:
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = COLOR_THEME_PRIMARY1_INDEX;
break;
}
else if (CHARGE_FINISHED == chargeState)
{
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
color = COLOR_THEME_EDIT;
}
else
{
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = COLOR_THEME_PRIMARY1;
if (chargeWindow == nullptr) {
chargeWindow = new Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H});
etx_solid_bg(chargeWindow->getLvObj(), COLOR_THEME_PRIMARY1_INDEX);
stateText = new StaticText(chargeWindow, {0, LCD_H - 50, LCD_W, 50}, "", COLOR_THEME_PRIMARY2_INDEX, CENTERED);
lv_obj_t* box = lv_obj_create(chargeWindow->getLvObj());
lv_obj_set_pos(box, (LCD_W - BATTERY_W) / 2, BATTERY_TOP);
lv_obj_set_size(box, BATTERY_W, BATTERY_H);
lv_obj_set_style_border_opa(box, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_border_width(box, 2, LV_PART_MAIN);
etx_border_color(box, COLOR_THEME_PRIMARY2_INDEX);
box = lv_obj_create(chargeWindow->getLvObj());
lv_obj_set_pos(box, (LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H);
lv_obj_set_size(box, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H);
etx_solid_bg(box, COLOR_THEME_PRIMARY2_INDEX);
battBox = lv_obj_create(chargeWindow->getLvObj());
}
stateText->setText(text);
lv_obj_set_pos(battBox, (LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h);
lv_obj_set_size(battBox, BATTERY_W_INNER, h);
etx_solid_bg(battBox, color);
LvglWrapper::instance()->run();
lv_refr_now(nullptr);
BACKLIGHT_ENABLE();
lcd->drawSizedText(LCD_W / 2, LCD_H - 50, text, strlen(text), CENTERED | COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W) / 2, BATTERY_TOP, BATTERY_W, BATTERY_H, SOLID, COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER, BATTERY_W_INNER, BATTERY_H_INNER, SOLID, COLOR_THEME_PRIMARY1);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h, BATTERY_W_INNER, h, SOLID, color);
lcd->drawFilledRect((LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H, SOLID, COLOR_THEME_PRIMARY2);
}
void battery_charge_end()
{
chargeWindow->clear();
delete chargeWindow;
chargeWindow = nullptr;
}
#define CHARGE_INFO_DURATION 5000 // ms
//this method should be called by timer interrupt or by GPIO interrupt
@@ -300,6 +328,12 @@ void handle_battery_charge(uint32_t last_press_time)
lastState = chargeState;
}
if (!lcdInited) {
lcdInited = true;
backlightInit();
lcdInitDisplayDriver();
}
if (updateTime == 0 || ((timersGetMsTick() - updateTime) >= 500))
{
updateTime = timersGetMsTick();
@@ -307,25 +341,17 @@ void handle_battery_charge(uint32_t last_press_time)
if(now > info_until) {
info_until = 0;
lcd->clear();
BACKLIGHT_DISABLE();
if(lcdInited) {
lcdOff();
}
} else {
if (!lcdInited) {
backlightInit();
lcdInit();
lcdInitDisplayDriver();
lcdInited = true;
} else {
if (lcdInited) {
lcdOn();
}
lcdInitDirectDrawing();
lcd->clear();
drawChargingInfo(chargeState);
// DEBUG INFO
// DEBUG INFO - TODO delete or replace with LVGL objects
#if 0
char buffer[1024];
@@ -338,8 +364,6 @@ void handle_battery_charge(uint32_t last_press_time)
sprintf(buffer, "%d", isChargerActive());
lcd->drawSizedText(100, 130, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
#endif
lcdRefresh();
}
}
+2 -10
View File
@@ -19,14 +19,7 @@
* GNU General Public License for more details.
*/
/***************************************************************************************************
***************************************************************************************************/
#ifndef __BATTERY_DRIVER_H__
#define __BATTERY_DRIVER_H__
/***************************************************************************************************
***************************************************************************************************/
#pragma once
#include "board.h"
#include "hal.h"
@@ -47,5 +40,4 @@ extern void handle_battery_charge(uint32_t last_press_time);
extern uint16_t get_battery_charge_state();
extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
extern bool isChargerActive();
#endif
extern void battery_charge_end();
+3 -2
View File
@@ -233,6 +233,8 @@ void boardInit()
boardOff();
} else {
uint32_t press_end_touch = press_end;
extern void rotaryEncoderCheck();
rotaryEncoderCheck();
rotenc_t value = rotaryEncoderGetValue();
if (value != lastEncoderValue) {
lastEncoderValue = value;
@@ -244,6 +246,7 @@ void boardInit()
press_end = 0;
}
}
battery_charge_end();
}
#endif
@@ -259,8 +262,6 @@ void boardInit()
#if defined(RTCLOCK)
rtcInit(); // RTC must be initialized before rambackupRestore() is called
#endif
lcdSetInitalFrameBuffer(lcdFront->getData());
}
extern void rtcDisableBackupReg();
@@ -126,7 +126,6 @@ void boardInit()
delay_ms(50); // GT911 is a bit slow on power ON
touchPanelInit();
lcdSetInitalFrameBuffer(lcdFront->getData());
}
extern void rtcDisableBackupReg();