Fire_RT1052_Pro_LVGL/src/app_lvgl.c

246 lines
7.5 KiB
C

/* Board */
#include "pin_mux.h"
/* LVGL */
#include "lvgl.h"
/* SDK drivers */
#include "fsl_debug_console.h"
#include "fsl_elcdif.h"
#include "fsl_gpio.h"
#include "fsl_gt911.h"
#include "fsl_lpi2c.h"
/* FreeRTOS */
#include "FreeRTOS.h"
#include "task.h"
/* App */
#include "app_lvgl.h"
#define APP_LCD_WIDTH (800)
#define APP_LCD_HEIGHT (480)
#define APP_LCD_HSW (20)
#define APP_LCD_HFP (210)
#define APP_LCD_HBP (46)
#define APP_LCD_VSW (10)
#define APP_LCD_VFP (22)
#define APP_LCD_VBP (23)
#define APP_LCD_FLAGS \
(kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnRisingClkEdge)
#define APP_LCD_BUFFER_SIZE (APP_LCD_WIDTH * APP_LCD_HEIGHT * 2)
SDK_ALIGN(static uint8_t s_lcd_buffers[2][APP_LCD_BUFFER_SIZE], 64);
AT_QUICKACCESS_SECTION_DATA(static lv_disp_draw_buf_t s_lcd_draw_buf);
AT_QUICKACCESS_SECTION_DATA(static lv_disp_drv_t s_lcd_drv);
AT_QUICKACCESS_SECTION_DATA(static lv_indev_drv_t s_ctp_drv);
AT_QUICKACCESS_SECTION_DATA(static volatile bool s_frame_done);
AT_QUICKACCESS_SECTION_DATA(static gt911_handle_t s_ctp_handle);
static void app_lvgl_task(void *parameters);
static void app_lvgl_ctp_reset(bool pullUp) {
if (pullUp) {
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_RST_GPIO, BOARD_INITLCDPINS_LCD_RST_PIN, 1U);
} else {
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_RST_GPIO, BOARD_INITLCDPINS_LCD_RST_PIN, 0U);
}
}
static void app_lvgl_ctp_int(gt911_int_pin_mode_t mode) {
switch (mode) {
case kGT911_IntPinInput:
BOARD_INITLCDPINS_LCD_INT_GPIO->GDIR &= ~(1UL << BOARD_INITLCDPINS_LCD_INT_PIN);
break;
case kGT911_IntPinPullDown:
BOARD_INITLCDPINS_LCD_INT_GPIO->GDIR |= (1UL << BOARD_INITLCDPINS_LCD_INT_PIN);
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_INT_GPIO, BOARD_INITLCDPINS_LCD_INT_PIN, 0U);
break;
case kGT911_IntPinPullUp:
BOARD_INITLCDPINS_LCD_INT_GPIO->GDIR |= (1UL << BOARD_INITLCDPINS_LCD_INT_PIN);
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_INT_GPIO, BOARD_INITLCDPINS_LCD_INT_PIN, 1U);
break;
default:
break;
}
}
RAMFUNCTION_SECTION_CODE(static void app_lvgl_delay_ms(uint32_t msec)) {
SDK_DelayAtLeastUs(msec * 1000, CLOCK_GetCoreSysClkFreq());
}
RAMFUNCTION_SECTION_CODE(static status_t app_lvgl_i2c_send(uint8_t deviceAddress, uint32_t subAddress,
uint8_t subaddressSize, const uint8_t *txBuff,
uint8_t txBuffSize)) {
lpi2c_master_transfer_t xfer = {
.direction = kLPI2C_Write,
.slaveAddress = deviceAddress,
.subaddress = subAddress,
.subaddressSize = subaddressSize,
.data = (void *)txBuff,
.dataSize = txBuffSize,
};
return LPI2C_MasterTransferBlocking(LPI2C1, &xfer);
}
RAMFUNCTION_SECTION_CODE(static status_t app_lvgl_i2c_recv(uint8_t deviceAddress, uint32_t subAddress,
uint8_t subaddressSize, uint8_t *rxBuff,
uint8_t txBuffSize)) {
lpi2c_master_transfer_t xfer = {
.direction = kLPI2C_Read,
.slaveAddress = deviceAddress,
.subaddress = subAddress,
.subaddressSize = subaddressSize,
.data = (void *)rxBuff,
.dataSize = txBuffSize,
};
return LPI2C_MasterTransferBlocking(LPI2C1, &xfer);
}
static void app_lvgl_backlight(const bool on) {
if (on) {
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_BL_GPIO, BOARD_INITLCDPINS_LCD_BL_PIN, 1U);
} else {
GPIO_PinWrite(BOARD_INITLCDPINS_LCD_BL_GPIO, BOARD_INITLCDPINS_LCD_BL_PIN, 0U);
}
}
RAMFUNCTION_SECTION_CODE(static void app_lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area,
lv_color_t *color_p)) {
SCB_CleanDCache_by_Addr(color_p, APP_LCD_BUFFER_SIZE);
ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)color_p);
s_frame_done = false;
while (s_frame_done == false) {
}
lv_disp_flush_ready(disp_drv);
}
RAMFUNCTION_SECTION_CODE(void app_lvgl_read_cb(lv_indev_drv_t *drv, lv_indev_data_t *data)) {
uint8_t t_count = 5;
touch_point_t t_arr[5];
GT911_GetMultiTouch(&s_ctp_handle, &t_count, t_arr);
for (uint8_t i = 0; i < t_count; i++) {
if (t_arr[i].valid && (t_arr[i].touchID == 0U)) {
data->point.x = t_arr[i].x;
data->point.y = t_arr[i].y;
data->state = LV_INDEV_STATE_PRESSED;
goto found_track;
}
}
data->state = LV_INDEV_STATE_RELEASED;
found_track:
}
int app_lvgl_init(void) {
BOARD_InitLCDPins();
CLOCK_EnableClock(kCLOCK_Lpi2c1);
lpi2c_master_config_t i2c_cfg;
i2c_cfg.baudRate_Hz = 400000;
LPI2C_MasterGetDefaultConfig(&i2c_cfg);
LPI2C_MasterInit(LPI2C1, &i2c_cfg, 24000000);
const gt911_config_t ctp_config = {
.i2cAddrMode = kGT911_I2cAddrAny,
.I2C_SendFunc = app_lvgl_i2c_send,
.I2C_ReceiveFunc = app_lvgl_i2c_recv,
.intPinFunc = app_lvgl_ctp_int,
.pullResetPinFunc = app_lvgl_ctp_reset,
.intTrigMode = kGT911_IntFallingEdge,
.touchPointNum = 5,
.timeDelayMsFunc = app_lvgl_delay_ms,
};
GT911_Init(&s_ctp_handle, &ctp_config);
const elcdif_rgb_mode_config_t rgb_cfg = {
.panelWidth = APP_LCD_WIDTH,
.panelHeight = APP_LCD_HEIGHT,
.hsw = APP_LCD_HSW,
.hfp = APP_LCD_HFP,
.hbp = APP_LCD_HBP,
.vsw = APP_LCD_VSW,
.vfp = APP_LCD_VFP,
.vbp = APP_LCD_VBP,
.polarityFlags = APP_LCD_FLAGS,
.bufferAddr = (uint32_t)s_lcd_buffers[1],
.pixelFormat = kELCDIF_PixelFormatRGB565,
.dataBus = kELCDIF_DataBus16Bit,
};
ELCDIF_RgbModeInit(LCDIF, &rgb_cfg);
ELCDIF_EnableInterrupts(LCDIF, kELCDIF_CurFrameDoneInterruptEnable);
NVIC_SetPriority(LCDIF_IRQn, 5);
EnableIRQ(LCDIF_IRQn);
ELCDIF_RgbModeStart(LCDIF);
app_lvgl_backlight(true);
s_frame_done = true;
lv_init();
lv_disp_draw_buf_init(&s_lcd_draw_buf, s_lcd_buffers[0], s_lcd_buffers[1], APP_LCD_WIDTH * APP_LCD_HEIGHT);
lv_disp_drv_init(&s_lcd_drv);
s_lcd_drv.hor_res = APP_LCD_WIDTH;
s_lcd_drv.ver_res = APP_LCD_HEIGHT;
s_lcd_drv.draw_buf = &s_lcd_draw_buf;
s_lcd_drv.flush_cb = app_lvgl_flush_cb;
s_lcd_drv.full_refresh = true;
lv_disp_drv_register(&s_lcd_drv);
lv_indev_drv_init(&s_ctp_drv);
s_ctp_drv.type = LV_INDEV_TYPE_POINTER;
s_ctp_drv.read_cb = app_lvgl_read_cb;
lv_indev_drv_register(&s_ctp_drv);
if (xTaskCreate(app_lvgl_task, "LVGL", 8192, NULL, 4, NULL) != pdPASS) {
return -1;
}
return 0;
}
uint32_t app_lvgl_ticks(void) {
return xTaskGetTickCount();
}
static void app_lvgl_task(void *parameters) {
for (;;) {
TickType_t t_start = xTaskGetTickCount();
lv_timer_handler();
TickType_t t_end = xTaskGetTickCount();
if (t_end - t_start < 10) {
vTaskDelay(10 - (t_end - t_start));
}
}
}
void LCDIF_IRQHandler(void) {
const uint32_t status = ELCDIF_GetInterruptStatus(LCDIF);
ELCDIF_ClearInterruptStatus(LCDIF, status);
if (status & kELCDIF_CurFrameDone) {
s_frame_done = true;
}
SDK_ISR_EXIT_BARRIER;
}