246 lines
7.5 KiB
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;
|
|
} |