/* 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; }