diff --git a/MAINTAINERS b/MAINTAINERS index eff482b886..ac961d3c1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -75,3 +75,6 @@ tag: workflow path: .github owners: supper thomas(supperthomas)<78900636@qq.com>, Bingru Zhang(Rbb666)<751061401@qq.com>, Yuqiang Wang(kurisaW)<2053731441@qq.com> +tag: gd32470z-lckfb-lcd +path: bsp/gd32/arm/gd32470z-lckfb/board/ports +owners: Wu Ying Xiang(godmial)<2633967641@qq.com> diff --git a/bsp/gd32/arm/gd32470z-lckfb/README.md b/bsp/gd32/arm/gd32470z-lckfb/README.md index 93c1e6f463..b20546911b 100644 --- a/bsp/gd32/arm/gd32470z-lckfb/README.md +++ b/bsp/gd32/arm/gd32470z-lckfb/README.md @@ -51,7 +51,7 @@ GD32470Z-LCKFB梁山派是立创开发板推出的一款GD32F470系列的开发 | GPIO | 支持 | PA0, PA1... ---> PIN: 0, 1...113 | | UART | 支持 | UART0 - UART7 | | **扩展模块** | **支持情况** | **备注** | -| 暂无 | 暂不支持 | 暂不支持 | +| LCD+触摸屏 | 支持 | 暂不支持中文显示(因 Keil5 编码限制),使用方法请查看bsp\gd32\arm\gd32470z-lckfb\board\ports\README.md | ## 使用说明 diff --git a/bsp/gd32/arm/gd32470z-lckfb/SConstruct b/bsp/gd32/arm/gd32470z-lckfb/SConstruct index ae4f8f787c..310bd17625 100644 --- a/bsp/gd32/arm/gd32470z-lckfb/SConstruct +++ b/bsp/gd32/arm/gd32470z-lckfb/SConstruct @@ -56,5 +56,8 @@ objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConsc # include drivers objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) +# include lcd and drivers +objs.extend(SConscript(os.path.join(RTT_ROOT, 'bsp', 'gd32', 'arm', 'gd32470z-lckfb', 'board', 'ports', 'SConscript'))) + # make a building DoBuilding(TARGET, objs) diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/Kconfig b/bsp/gd32/arm/gd32470z-lckfb/board/Kconfig index 843690f080..6d36887be5 100644 --- a/bsp/gd32/arm/gd32470z-lckfb/board/Kconfig +++ b/bsp/gd32/arm/gd32470z-lckfb/board/Kconfig @@ -433,6 +433,37 @@ endmenu menu "Board extended module Drivers" + menuconfig BSP_USING_LCD + bool "Enable LCD" + select RT_USING_LCD + default n + if BSP_USING_LCD + + config BSP_USING_TLI + bool "Enable TLI" + default y + + config BSP_USING_SDRAM + bool "Enable SDRAM" + select RT_USING_SDRAM + default y + + config BSP_USING_TOUCH + bool "Enable TOUCH" + select RT_USING_TOUCH + default n + + config BSP_USING_GPU + bool "Enable GPU" + select RT_USING_GPU + default y + + config BSP_USING_DRAW_PANEL_EXAMPLE + bool "Enable DRAW PANEL EXAMPLE" + select RT_USING_DRAW_PANEL_EXAMPLE + default n + endif + endmenu endmenu diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/README.md b/bsp/gd32/arm/gd32470z-lckfb/board/ports/README.md new file mode 100644 index 0000000000..2570ca7875 --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/README.md @@ -0,0 +1,44 @@ +#### 1. 简介 + +用于 GD32F470 立创开发板配套 RGB LCD 屏幕的驱动,支持触摸。 + +> **原作者:LCKFB** +> 本驱动最初由 LCKFB 开发,由 godmial 移植到本BSP。 + +#### 2. 在 ENV 中的开启 +ps:建议全部开启 +``` +Hardware Drivers Config ---> + Board extended module Drivers ---> + Enable LCD ---> + - [*]Enable TLI + - [*]Enable SDRAM + - [*]Enable TOUCH + - [*]Enable GPU + - [*]Enable DRAW PANEL EXAMPLE +``` + +#### 3. 注意事项 + +1. 如果屏幕出现刷新抖动,触摸屏出现连点的情况,可以尝试在 `libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c` 将时钟值修改为 + `#define __SYSTEM_CLOCK_240M_PLL_25M_HXTAL (uint32_t)(240000000)` + 然后重新编译即可 + +2. 由于代码格式审查原因,本驱动未包含中文显示函数。但可直接移植官方源码中的中文显示函数进行使用。 + +3. 为避免 `scons` 命令编译不通过,代码使用了如下代码段以适配不同编译器: + ``` + #if defined(__CC_ARM) || defined(__ARMCC_VERSION) + // Keil MDK + uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR))); + #elif defined(__GNUC__) + // GCC (RT-Thread) + uint16_t ltdc_lcd_framebuf0[10][10]; // 此行为避免 scons 编译错误而添加 + #endif + + + +#### 4. 联系方式 + +- 维护:godmial +- 主页: diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/SConscript b/bsp/gd32/arm/gd32470z-lckfb/board/ports/SConscript new file mode 100644 index 0000000000..80273b4ffe --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/SConscript @@ -0,0 +1,25 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Split(""" +""") + +# add lcd drivers. +if GetDepend('BSP_USING_LCD'): + src += ['drv_lcd.c'] + +if GetDepend('BSP_USING_TOUCH'): + src += ['drv_touch.c'] + +if GetDepend('BSP_USING_DRAW_PANEL_EXAMPLE'): + src += ['draw_panel.c'] + +path = [cwd] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = path) + +Return('group') diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/draw_panel.c b/bsp/gd32/arm/gd32470z-lckfb/board/ports/draw_panel.c new file mode 100644 index 0000000000..f09025f072 --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/draw_panel.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#include +#include +#include +#include "drv_lcd.h" +#include "drv_touch.h" + +#define COLOR_MAX 14 + +/* Maximum magnification of pixels */ +#define PIXEL_SIZE_MAX 20 + +typedef struct button_struct +{ + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; + uint16_t color; + uint16_t value; +} widget_object_t; + +uint16_t color_buf[COLOR_MAX] = {GRAYBLUE, BLACK, BLUE, BRED, GRED, GBLUE, RED, MAGENTA, GREEN, YELLOW, CYAN, BROWN, BRRED, GRAY}; +widget_object_t button_clear, button_color, button_pixel, button_eraser; + + +/** + * @brief Initialize a widget button with given properties. + * + * @param obj Pointer to the widget object. + * @param x X coordinate of the top-left corner. + * @param y Y coordinate of the top-left corner. + * @param w Width of the widget. + * @param h Height of the widget. + * @param color Color value of the widget. + * @param value Initial value of the widget. + * + * @return None. + */ +void widget_object_init(widget_object_t *obj, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color, uint16_t value) +{ + obj->x = x; + obj->y = y; + obj->h = h; + obj->w = w; + obj->color = color; + obj->value = value; +} + + +/** + * @brief Initialize and display the user interface. + * + * This function draws the control buttons for clear, color, + * pixel size, and eraser on the screen. + * + * @return None. + */ +void ui_init(void) +{ + char temp_buf[20] = {0}; + + tli_show_button(button_clear.x, button_clear.y, button_clear.w, button_clear.h, 12, button_clear.color); + tli_show_string(button_clear.x + 20, button_clear.y + 20, WHITE, button_clear.color, 2, "clear", 0); + + tli_show_button(button_color.x, button_color.y, button_color.w, button_color.h, 12, button_color.color); + tli_show_string(button_color.x + 20, button_color.y + 20, WHITE, button_color.color, 2, "color", 0); + + tli_show_button(button_pixel.x, button_pixel.y, button_pixel.w, button_pixel.h, 12, button_pixel.color); + if (button_pixel.value == 0) + { + tli_show_string(button_pixel.x + 20, button_pixel.y + 20, WHITE, button_pixel.color, 2, "pixel", 0); + button_pixel.value = 1; + } + else + { + sprintf(temp_buf, "%d", button_pixel.value); + tli_show_string(button_pixel.x + (button_pixel.w / 2) - (strlen(temp_buf) / 2 * 16), button_pixel.y + 20, WHITE, button_pixel.color, 2, (uint8_t *)temp_buf, 0); + } + + tli_show_button(button_eraser.x, button_eraser.y, button_eraser.w, button_eraser.h, 12, button_eraser.color); + tli_show_string(button_eraser.x + (button_eraser.w / 2) - (strlen("eraser") / 2 * 16), button_eraser.y + 20, WHITE, button_eraser.color, 2, "eraser", 0); +} + +/** + * @brief Main routine to test the drawing panel with touch interaction. + * + * Initializes LCD and touch interface, sets up buttons and handles user input + * to draw or erase on the screen based on touch events. + * + * @return Always returns 0. + */ +int draw_panel_test(void) +{ + int touch_state = 0; + char color_num = 0; + char pixel_size = 0; + + lcd_disp_config(); + FT5206_Init(); + tli_draw_rectangle(0, 0, 800, 480, WHITE, 1); + + widget_object_init(&button_clear, 800 - 130, 480 - 80, 120, 70, BLUE, 0); + widget_object_init(&button_color, 10, 480 - 80, 120, 70, BLUE, 0); + widget_object_init(&button_pixel, 400 - 60, 480 - 80, 120, 70, BLUE, pixel_size); + widget_object_init(&button_eraser, 800 - 130 - 130, 480 - 80, 120, 70, BLUE, 0); + + ui_init(); + + while (1) + { + touch_state = FT5206_Scan(0); + if (touch_state == 1) + { + if (tp_dev.x[0] >= button_color.x && tp_dev.x[0] <= (button_color.x + button_color.w)) + { + if (tp_dev.y[0] >= button_color.y && tp_dev.y[0] <= (button_color.y + button_color.h)) + { + letgo_scan(0, button_color.x, button_color.y, (button_color.x + button_color.w), (button_color.y + button_color.h)); + color_num = (color_num + 1) % COLOR_MAX; + widget_object_init(&button_color, button_color.x, button_color.y, button_color.w, button_color.h, color_buf[color_num], 0); + ui_init(); + } + } + if (tp_dev.x[0] >= button_clear.x && tp_dev.x[0] <= (button_clear.x + button_clear.w)) + { + if (tp_dev.y[0] >= button_clear.y && tp_dev.y[0] <= (button_clear.y + button_clear.h)) + { + letgo_scan(0, button_clear.x, button_clear.y, (button_clear.x + button_clear.w), (button_clear.y + button_clear.h)); + tli_draw_rectangle(0, 0, 800, 480, WHITE, 1); + ui_init(); + } + } + if (tp_dev.x[0] >= button_pixel.x && tp_dev.x[0] <= (button_pixel.x + button_pixel.w)) + { + if (tp_dev.y[0] >= button_pixel.y && tp_dev.y[0] <= (button_pixel.y + button_pixel.h)) + { + letgo_scan(0, button_pixel.x, button_pixel.y, (button_pixel.x + button_pixel.w), (button_pixel.y + button_pixel.h)); + pixel_size++; + if (pixel_size > PIXEL_SIZE_MAX) pixel_size = 1; + widget_object_init(&button_pixel, button_pixel.x, button_pixel.y, button_pixel.w, button_pixel.h, button_pixel.color, pixel_size); + ui_init(); + } + } + + if (tp_dev.x[0] >= button_eraser.x && tp_dev.x[0] <= (button_eraser.x + button_eraser.w)) + { + if (tp_dev.y[0] >= button_eraser.y && tp_dev.y[0] <= (button_eraser.y + button_eraser.h)) + { + letgo_scan(0, button_eraser.x, button_eraser.y, (button_eraser.x + button_eraser.w), (button_eraser.y + button_eraser.h)); + button_eraser.value = !button_eraser.value; + if (button_eraser.value) + { + widget_object_init(&button_eraser, 800 - 130 - 130, 480 - 80, 120, 70, BLACK, button_eraser.value); + } + else + { + widget_object_init(&button_eraser, 800 - 130 - 130, 480 - 80, 120, 70, BLUE, button_eraser.value); + } + + ui_init(); + } + } + + + if (!button_eraser.value) + { + tli_point_enlarge(tp_dev.x[0], tp_dev.y[0], color_buf[color_num], button_pixel.value); + } + else + { + tli_point_enlarge(tp_dev.x[0], tp_dev.y[0], WHITE, button_pixel.value); + } + } + } +} + +INIT_COMPONENT_EXPORT(draw_panel_test); diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.c b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.c new file mode 100644 index 0000000000..e8c52b30d0 --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#include +#include "gd32f4xx.h" +#include "gd32f4xx_tli.h" +#include "drv_lcd.h" +#include "font.h" + + +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +/* Keil MDK Compiler */ +uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR))); +#elif defined(__GNUC__) +/* GCC Compiler (used by RT-Thread) */ +uint16_t ltdc_lcd_framebuf0[10][10]; +#endif + +static void tli_gpio_config(void); +static void tli_config(void); +static void ipa_config(void); +static void lcd_disp_en_config(void); +static void lcd_disp_off(void); +static void lcd_disp_on(void); + + +/** + * @brief Configure and initialize the LCD display. + * + * @note This function enables display power, initializes TLI GPIO and IPA, + * and sets up TLI and its layer configuration. + * + * @param None + * + * @return None + * + * @warning Should be called during system initialization phase. + */ +void lcd_disp_config(void) +{ + lcd_disp_en_config(); + lcd_disp_off(); + + /* configure the GPIO of TLI */ + tli_gpio_config(); + lcd_disp_on(); + + tli_config(); + tli_layer_enable(LAYER0); + tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN); + tli_enable(); + ipa_config(); +} + +/** + * @brief Initialize the TLI peripheral and layer configuration. + * + * @note This function sets up the TLI clock, background color, timing parameters, + * and layer 0 settings including framebuffer and blending configuration. + * + * @param None + * + * @return None + * + * @warning Must be called after clock and GPIO initialization. + */ +static void tli_config(void) +{ + tli_parameter_struct tli_init_struct; + tli_layer_parameter_struct tli_layer_init_struct; + + rcu_periph_clock_enable(RCU_TLI); + tli_gpio_config(); + /* configure PLLSAI to generate TLI clock */ + // if(ERROR == rcu_pllsai_config(216, 2, 3)){ + if (ERROR == rcu_pllsai_config(192, 2, 3)) + { + while (1); + } + rcu_tli_clock_div_config(RCU_PLLSAIR_DIV2); + + rcu_osci_on(RCU_PLLSAI_CK); + + if (ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK)) + { + while (1); + } + + /* configure TLI parameter struct */ + tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; + tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; + tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW; + tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI; + /* LCD display timing configuration */ + tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1; + tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1; + tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1; + tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1; + tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1; + tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1; + tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1; + tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1; + /* configure LCD background R,G,B values */ + tli_init_struct.backcolor_red = 0xFF; + tli_init_struct.backcolor_green = 0xFF; + tli_init_struct.backcolor_blue = 0xFF; + tli_init(&tli_init_struct); + +#if 1 + /* TLI layer0 configuration */ + /* TLI window size configuration */ + tli_layer_init_struct.layer_window_leftpos = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH; + tli_layer_init_struct.layer_window_rightpos = (ACTIVE_WIDTH + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); + tli_layer_init_struct.layer_window_toppos = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH; + tli_layer_init_struct.layer_window_bottompos = (ACTIVE_HEIGHT + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1); + /* TLI window pixel format configuration */ + tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565; + /* TLI window specified alpha configuration */ + tli_layer_init_struct.layer_sa = 255; + /* TLI layer default alpha R,G,B value configuration */ + tli_layer_init_struct.layer_default_blue = 0x00; + tli_layer_init_struct.layer_default_green = 0x00; + tli_layer_init_struct.layer_default_red = 0x00; + tli_layer_init_struct.layer_default_alpha = 0x00; + /* TLI window blend configuration */ + tli_layer_init_struct.layer_acf1 = LAYER_ACF1_SA; + tli_layer_init_struct.layer_acf2 = LAYER_ACF2_SA; + /* TLI layer frame buffer base address configuration */ + tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)ltdc_lcd_framebuf0; + tli_layer_init_struct.layer_frame_line_length = ((ACTIVE_WIDTH * 2) + 3); + tli_layer_init_struct.layer_frame_buf_stride_offset = (ACTIVE_WIDTH * 2); + tli_layer_init_struct.layer_frame_total_line_number = ACTIVE_HEIGHT; + tli_layer_init(LAYER0, &tli_layer_init_struct); + tli_dither_config(TLI_DITHER_ENABLE); +#endif +} + +/** + * @brief Initialize the IPA peripheral. + * + * @note Enable clock and interrupt for the IPA module. + * + * @param None + * + * @return None + */ +static void ipa_config(void) +{ + rcu_periph_clock_enable(RCU_IPA); + nvic_irq_enable(IPA_IRQn, 0, 2); +} + +/** + * @brief Configure the GPIO pins used for TLI display. + * + * @note Includes alternate function mapping and output mode setup + * for RGB and sync signals. + * + * @param None + * + * @return None + */ +static void tli_gpio_config(void) +{ + /* enable the periphral clock */ + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_GPIOF); + rcu_periph_clock_enable(RCU_GPIOG); + + /* configure HSYNC(PC6), VSYNC(PA4), PCLK(PG7), DE(PF10) */ + /* configure LCD_R7(PG6), LCD_R6(PA8), LCD_R5(PA12), LCD_R4(PA11), LCD_R3(PB0), + LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PB11), LCD_G4(PB10), LCD_G3(PG10), LCD_G2(PA6), + LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PA3), LCD_B4(PG12), LCD_B3(PG11) */ + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_3); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_4); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_8); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_11); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_12); + + gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_0); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_10); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_11); + + gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7); + + gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3); + + gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10); + + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7); + gpio_af_set(GPIOG, GPIO_AF_9, GPIO_PIN_10); + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11); + gpio_af_set(GPIOG, GPIO_AF_9, GPIO_PIN_12); + + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12); + + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11); + + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6 | GPIO_PIN_7); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); + + gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3); + gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3); + + gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10); + gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); + + gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); +} + +/** + * @brief Configure the GPIO pin for DISP enable control. + * + * @note This function enables the clock for GPIOD and sets up pin 13 + * as push-pull output to control the display on/off signal. + * + * @param None + * + * @return None + * + * @warning Must be called before attempting to control the LCD display. + */ +static void lcd_disp_en_config(void) +{ + /* enable the periphral clock */ + rcu_periph_clock_enable(RCU_GPIOD); + gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_13); + gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); +} + +/** + * @brief Turn off the LCD display by resetting the DISP GPIO. + * + * @note This function clears the DISP control pin to disable + * the LCD backlight or power depending on hardware design. + * + * @param None + * + * @return None + * + * @warning Only valid if the DISP GPIO has been previously configured. + */ +static void lcd_disp_off(void) +{ + gpio_bit_reset(GPIOD, GPIO_PIN_13); +} + +/** + * @brief Turn on the LCD display by setting the DISP GPIO. + * + * @note This function sets the DISP control pin to enable + * the LCD backlight or power depending on hardware design. + * + * @param None + * + * @return None + * + * @warning Only valid if the DISP GPIO has been previously configured. + */ +static void lcd_disp_on(void) +{ + gpio_bit_set(GPIOD, GPIO_PIN_13); +} + + +/** + * @brief Draw a pixel on the LCD at specified coordinates. + * + * @note This function writes a color value directly to the framebuffer. + * Coordinates must be within the valid LCD dimensions. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param color Color of the pixel in RGB565 format. + * + * @return None + */ +void tli_draw_point(uint16_t x, uint16_t y, uint16_t color) +{ + *(ltdc_lcd_framebuf0[0] + (LCD_WIDTH * y + x)) = color; +} + +/** + * @brief Draw a straight line between two points. + * + * @note Uses Bresenham's line drawing algorithm to connect two points. + * Coordinates should be within LCD bounds. + * + * @param sx Start point X coordinate. + * @param sy Start point Y coordinate. + * @param ex End point X coordinate. + * @param ey End point Y coordinate. + * @param color Line color in RGB565 format. + * + * @return None + */ +void tli_draw_line(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color) +{ + uint16_t t; + int xerr = 0, yerr = 0, delta_x, delta_y, distance; + int incx, incy, uRow, uCol; + + delta_x = ex - sx; + delta_y = ey - sy; + uRow = sx; + uCol = sy; + if (delta_x > 0) + incx = 1; + else if (delta_x == 0) + incx = 0; + else + { + incx = -1; + delta_x = -delta_x; + } + if (delta_y > 0) + incy = 1; + else if (delta_y == 0) + incy = 0; + else + { + incy = -1; + delta_y = -delta_y; + } + if (delta_x > delta_y) + distance = delta_x; + else + distance = delta_y; + for (t = 0; t <= distance + 1; t++) + { + tli_draw_point(uRow, uCol, color); + xerr += delta_x; + yerr += delta_y; + if (xerr > distance) + { + xerr -= distance; + uRow += incx; + } + if (yerr > distance) + { + yerr -= distance; + uCol += incy; + } + } +} +/** + * @brief Draw a rectangle on the screen, optionally filled. + * + * @note The rectangle is defined by top-left and bottom-right corners. + * If fill is set to 1, the rectangle will be filled with the color. + * + * @param sx X coordinate of the top-left corner. + * @param sy Y coordinate of the top-left corner. + * @param ex X coordinate of the bottom-right corner. + * @param ey Y coordinate of the bottom-right corner. + * @param color Color of the rectangle in RGB565 format. + * @param fill Fill mode: 1 = filled, 0 = only borders. + * + * @return None + */ +void tli_draw_rectangle(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color, uint16_t fill) +{ + int i = 0, j = 0; + if (fill) + { + for (i = sx; i < ex; i++) + { + for (j = sy; j < ey; j++) + { + tli_draw_point(i, j, color); + } + } + } + else + { + tli_draw_line(sx, sy, ex, sy, color); + tli_draw_line(sx, sy, sx, ey, color); + tli_draw_line(sx, ey, ex, ey, color); + tli_draw_line(ex, sy, ex, ey, color); + } +} + +/** + * @brief Draw eight symmetric points of a circle. + * + * @note This function is used internally to draw points in all eight + * symmetrical positions around a circle center. + * + * @param xc X coordinate of the circle center. + * @param yc Y coordinate of the circle center. + * @param x Relative X offset from the center. + * @param y Relative Y offset from the center. + * @param c Color of the point in RGB565 format. + * + * @return None + */ + +static void _draw_circle_8(int xc, int yc, int x, int y, uint16_t c) +{ + tli_draw_point(xc + x, yc + y, c); + + tli_draw_point(xc - x, yc + y, c); + + tli_draw_point(xc + x, yc - y, c); + + tli_draw_point(xc - x, yc - y, c); + + tli_draw_point(xc + y, yc + x, c); + + tli_draw_point(xc - y, yc + x, c); + + tli_draw_point(xc + y, yc - x, c); + + tli_draw_point(xc - y, yc - x, c); +} + +/** + * @brief Draw a circle on the screen with optional fill. + * + * @note Uses the midpoint circle algorithm to render the circle. + * When fill is enabled, the circle is drawn as a filled disk. + * + * @param xc X coordinate of the circle center. + * @param yc Y coordinate of the circle center. + * @param c Color of the circle in RGB565 format. + * @param r Radius of the circle. + * @param fill Fill mode: 1 = filled, 0 = outline only. + * + * @return None + */ +void tli_draw_circle(int xc, int yc, uint16_t c, int r, int fill) +{ + int x = 0, y = r, yi, d; + + d = 3 - 2 * r; + + if (fill) + { + while (x <= y) + { + for (yi = x; yi <= y; yi++) + _draw_circle_8(xc, yc, x, yi, c); + + if (d < 0) + { + d = d + 4 * x + 6; + } + else + { + d = d + 4 * (x - y) + 10; + y--; + } + x++; + } + } + else + { + while (x <= y) + { + _draw_circle_8(xc, yc, x, y, c); + if (d < 0) + { + d = d + 4 * x + 6; + } + else + { + d = d + 4 * (x - y) + 10; + y--; + } + x++; + } + } +} + +/** + * @brief Swap the values of two 16-bit unsigned integers. + * + * @note This utility function is used internally to simplify sorting + * or reordering logic, such as coordinate alignment. + * + * @param a Pointer to the first variable. + * @param b Pointer to the second variable. + * + * @return None + */ +static void _swap(uint16_t *a, uint16_t *b) +{ + uint16_t tmp; + tmp = *a; + *a = *b; + *b = tmp; +} + +/** + * @brief Draw a triangle with optional fill. + * + * @note The triangle is defined by three vertex points. When fill is set, + * it is rendered as a filled triangle using scan-line rasterization. + * + * @param x0 X coordinate of the first vertex. + * @param y0 Y coordinate of the first vertex. + * @param x1 X coordinate of the second vertex (typically the top). + * @param y1 Y coordinate of the second vertex. + * @param x2 X coordinate of the third vertex. + * @param y2 Y coordinate of the third vertex. + * @param color Color of the triangle in RGB565 format. + * @param fill Fill mode: 1 = filled, 0 = outline only. + * + * @return None + */ +void tli_draw_triangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, uint16_t fill) +{ + uint16_t a, b, y, last; + int dx01, dy01, dx02, dy02, dx12, dy12; + long sa = 0; + long sb = 0; + + if (fill == 0) + { + tli_draw_line(x0, y0, x1, y1, color); + tli_draw_line(x1, y1, x2, y2, color); + tli_draw_line(x2, y2, x0, y0, color); + } + else + { + if (y0 > y1) + { + _swap(&y0, &y1); + _swap(&x0, &x1); + } + if (y1 > y2) + { + _swap(&y2, &y1); + _swap(&x2, &x1); + } + if (y0 > y1) + { + _swap(&y0, &y1); + _swap(&x0, &x1); + } + if (y0 == y2) + { + a = b = x0; + if (x1 < a) + { + a = x1; + } + else if (x1 > b) + { + b = x1; + } + if (x2 < a) + { + a = x2; + } + else if (x2 > b) + { + b = x2; + } + tli_draw_rectangle(a, y0, b, y0, color, 0); + return; + } + dx01 = x1 - x0; + dy01 = y1 - y0; + dx02 = x2 - x0; + dy02 = y2 - y0; + dx12 = x2 - x1; + dy12 = y2 - y1; + + if (y1 == y2) + { + last = y1; + } + else + { + last = y1 - 1; + } + for (y = y0; y <= last; y++) + { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + if (a > b) + { + _swap(&a, &b); + } + tli_draw_rectangle(a, y, b, y, color, 0); + } + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for (; y <= y2; y++) + { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + if (a > b) + { + _swap(&a, &b); + } + + tli_draw_rectangle(a, y, b, y, color, 0); + } + } +} + + +/** + * @brief Enlarge a single point by drawing a square block. + * + * @note The enlarged point is drawn as a 2D cross pattern made of four + * rectangles centered at (x, y) with specified magnification. + * + * @param x X coordinate of the center point. + * @param y Y coordinate of the center point. + * @param color Color to fill the enlarged point. + * @param magnify Enlargement factor (minimum value is 1). + * + * @return None + */ +void tli_point_enlarge(uint16_t x, uint16_t y, uint16_t color, char magnify) +{ + tli_draw_rectangle(x - magnify, y - magnify, x, y, color, 1); + + tli_draw_rectangle(x, y - magnify, x + magnify, y, color, 1); + + tli_draw_rectangle(x - magnify, y, x, y + magnify, color, 1); + + tli_draw_rectangle(x, y, x + magnify, y + magnify, color, 1); +} + +/** + * @brief Display a single ASCII character at the specified position. + * + * @note Uses a fixed-size 16x8 font to render the character with optional + * enlargement and overlay mode. + * + * @param x X coordinate of the character start position. + * @param y Y coordinate of the character start position. + * @param fc Foreground color. + * @param bc Background color. + * @param num ASCII character to display. + * @param size Enlargement factor (minimum 1). + * @param mode Overlay mode: 0 = non-overlay, 1 = overlay. + * + * @return None + */ +void tli_show_char(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t num, uint8_t size, uint8_t mode) +{ + uint8_t temp; + uint8_t pos, t; + uint16_t x0 = 0; + uint16_t y0 = 0; + num = num - ' '; + + for (pos = 0; pos < 16; pos++) + { + temp = asc2_1608[num][pos]; + for (t = 0; t < 16 / 2; t++) + { + if (!mode) + { + if (temp & 0x01) + tli_point_enlarge(x + x0, y + y0, fc, size); + else + tli_point_enlarge(x + x0, y + y0, bc, size); + } + else + { + if (temp & 0x01) tli_point_enlarge(x + x0, y + y0, fc, size); + } + temp >>= 1; + x0 = x0 + size; + } + x0 = 0; + y0 = y0 + size; + } +} + +/** + * @brief Display a null-terminated ASCII string on the screen. + * + * @note Automatically handles line boundaries and skips illegal characters. + * + * @param x X coordinate of the start position. + * @param y Y coordinate of the start position. + * @param fc Foreground color. + * @param bc Background color. + * @param size Font enlargement factor (base size is 16x8). + * @param p Pointer to the string. + * @param mode Overlay mode: 0 = non-overlay, 1 = overlay. + * + * @return None + */ +void tli_show_string(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t size, uint8_t *p, uint8_t mode) +{ + while ((*p <= '~') && (*p >= ' ')) + { + if (x > (LCD_WIDTH - 1) || y > (LCD_HEIGHT - 1)) return; + + tli_show_char(x, y, fc, bc, *p, size, mode); + x += 16 * size / 2; + p++; + } +} + + +/** + * @brief Display a picture at a specified position on the screen. + * + * @note The image data is expected to be in RGB565 format, with each pixel + * occupying two consecutive bytes in the array. + * + * @param x X coordinate of the top-left corner. + * @param y Y coordinate of the top-left corner. + * @param w Width of the image in pixels. + * @param h Height of the image in pixels. + * @param pic Pointer to the image data array. + * + * @return None + */ +void tli_show_picture(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const unsigned char pic[]) +{ + uint16_t i, j; + uint32_t k = 0; + uint16_t x0 = x, y0 = y; + for (i = y; i < h + y0; i++) + { + for (j = x; j < w + x0; j++) + { + tli_draw_point(j, i, pic[k * 2] << 8 | pic[k * 2 + 1]); + k++; + } + } +} + + +/** + * @brief Draw a filled rounded rectangle button. + * + * @note This function draws a button with four rounded corners and fills + * the background. The radius must be less than half of the height. + * + * @param x X coordinate of the top-left corner. + * @param y Y coordinate of the top-left corner. + * @param width Width of the button. + * @param height Height of the button. + * @param radius Radius of the corners. + * @param color Fill color of the button. + * + * @return None + */ +void tli_show_button(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius, uint16_t color) +{ + int i = 0; + int j = 0; + + + if (radius >= (height / 2)) return; + + + tli_draw_circle(x + radius, y + radius, color, radius, 1); + tli_draw_circle(x + width - radius - 1, y + radius, color, radius, 1); + tli_draw_circle(x + radius, y + height - radius - 1, color, radius, 1); + tli_draw_circle(x + width - radius - 1, y + height - radius - 1, color, radius, 1); + + tli_draw_line(x + radius, y, x + width - radius - 1, y, color); + tli_draw_line(x + radius, y + height - 1, x + width - radius - 1, y + height - 1, color); + tli_draw_line(x, y + radius, x, y + height - radius - 1, color); + tli_draw_line(x + width - 1, y + radius, x + width - 1, y + height - radius - 1, color); + + tli_draw_rectangle(x + radius, y + radius, x + width - radius, y + height - radius, color, 1); + tli_draw_rectangle(x + radius, y, x + width - radius, y + radius, color, 1); + tli_draw_rectangle(x, y + radius, x + width, y + height - radius, color, 1); + tli_draw_rectangle(x + radius, y + height - radius, x + width - radius, y + height, color, 1); +} + +/** + * @brief Draw a switch (toggle) component with visual state. + * + * @note The switch has a rounded rectangle base with a circular knob + * indicating on or off state. Automatically validates layout rules. + * + * @param x X coordinate of the top-left corner. + * @param y Y coordinate of the top-left corner. + * @param width Total width of the switch. + * @param height Total height of the switch. + * @param on_color Color of the switch when turned on. + * @param off_color Color of the switch when turned off. + * @param sw Switch state: 1 = on, 0 = off. + * + * @return None + */ +void tli_show_switch(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t on_color, uint16_t off_color, char sw) +{ + int radius = height / 2 - 1; + + if (width < 2 * (radius + 1)) return; + + if (sw == 0) + { + tli_show_button(x, y, width, height, radius, off_color); + tli_draw_circle(x + radius, y + radius, WHITE, radius / 2, 1); + } + else + { + tli_show_button(x, y, width, height, radius, on_color); + tli_draw_circle(x + width - radius, y + radius, WHITE, radius / 2, 1); + } +} + + diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.h b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.h new file mode 100644 index 0000000000..70284fd46d --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_lcd.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#ifndef __DRV_LCD_H__ +#define __DRV_LCD_H__ + +#include +#include +#include +#ifdef BSP_USING_SDRAM +#include +#endif /* BSP_USING_SDRAM */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* LCD resolution and pixel format */ +#define LCD_WIDTH 800 +#define LCD_HEIGHT 480 +#define LCD_FB_BYTE_PER_PIXEL 1 + +/* Timing parameters for horizontal synchronization */ +#define HORIZONTAL_SYNCHRONOUS_PULSE 10 +#define HORIZONTAL_BACK_PORCH 150 +#define ACTIVE_WIDTH 800 +#define HORIZONTAL_FRONT_PORCH 15 + +/* Timing parameters for vertical synchronization */ +#define VERTICAL_SYNCHRONOUS_PULSE 10 +#define VERTICAL_BACK_PORCH 140 +#define ACTIVE_HEIGHT 480 +#define VERTICAL_FRONT_PORCH 40 + +/* Framebuffer address in SDRAM */ +#define LCD_FRAME_BUF_ADDR 0xC0000000 /* SDRAM address for LCD frame buffer */ + +/* Pen color definitions (RGB565) */ +#define WHITE 0xFFFF /* White */ +#define BLACK 0x0000 /* Black */ +#define BLUE 0x001F /* Blue */ +#define BRED 0xF81F /* Blue-Red */ +#define GRED 0xFFE0 /* Green-Red */ +#define GBLUE 0x07FF /* Green-Blue */ +#define RED 0xF800 /* Red */ +#define MAGENTA 0xF81F /* Magenta */ +#define GREEN 0x07E0 /* Green */ +#define CYAN 0x7FFF /* Cyan */ +#define YELLOW 0xFFE0 /* Yellow */ +#define BROWN 0xBC40 /* Brown */ +#define BRRED 0xFC07 /* Brownish red */ +#define GRAY 0x8430 /* Gray */ + +/* GUI color definitions */ +#define DARKBLUE 0x01CF /* Dark blue */ +#define LIGHTBLUE 0x7D7C /* Light blue */ +#define GRAYBLUE 0x5458 /* Grayish blue */ +#define LIGHTGREEN 0x841F /* Light green */ +#define LGRAY 0xC618 /* Light gray (panel background) */ +#define LGRAYBLUE 0xA651 /* Light gray-blue (layer color) */ +#define LBBLUE 0x2B12 /* Light brown-blue (selected item reverse color) */ + +/* Frame buffer declaration based on compiler */ +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) +/* Keil MDK Compiler */ +extern uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR))); +#elif defined(__GNUC__) +/* GCC Compiler (used by RT-Thread) */ +extern uint16_t ltdc_lcd_framebuf0[10][10]; /* Dummy for GCC compilation */ +#endif + +/******************************************************************************* + * API + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configure the LCD display controller. + * + * @note This function initializes display timing and output settings. + */ +void lcd_disp_config(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_LCD_H__ */ diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.c b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.c new file mode 100644 index 0000000000..e4fe366cdf --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#include +#include +#include +#include "drv_touch.h" +#include "drv_lcd.h" + +#define DRV_DEBUG +#define LOG_TAG "drv.touch" +#include + +_m_tp_dev tp_dev; + +const uint16_t FT5206_TPX_TBL[5] = {FT_TP1_REG, FT_TP2_REG, FT_TP3_REG, FT_TP4_REG, FT_TP5_REG}; +uint8_t g_gt_tnum = 5; /**< Default number of supported touch points (5-point touch) */ + + +/** + * @brief Delay for a specified number of microseconds. + * + * @note This function uses the SysTick timer to implement microsecond delay by polling. + * + * @param _nus Number of microseconds to delay. + */ +void delay_us(uint32_t _nus) +{ + uint8_t fac_us = 0; + uint32_t ticks; + uint32_t t_old, t_now, t_cnt = 0; + uint32_t reload = SysTick->LOAD; + + fac_us = SystemCoreClock / 1000000; + ticks = _nus * fac_us - fac_us * 7 / 20; + t_old = SysTick->VAL; + + while (1) + { + t_now = SysTick->VAL; + + if (t_now < t_old) + { + t_cnt += t_old - t_now; + } + else + { + t_cnt += t_old + (reload - t_now); + } + + if (t_cnt >= ticks) + { + break; + } + + t_old = t_now; + }; +} + + +/** + * @brief Delay function wrapper for touch operations. + * + * @param us Number of microseconds to delay. + */ +void touch_delay_1us(uint16_t us) +{ + delay_us(us); +} + +/** + * @brief Delay to control I2C speed. + * + * @note Used between I2C signal toggles to ensure proper timing. + */ +void CT_Delay(void) +{ + touch_delay_1us(2); +} + +/** + * @brief Initialize the I2C interface for the capacitive touch chip. + * + * @note Configures GPIO ports for SCL and SDA lines as outputs with pull-up resistors. + */ +void CT_IIC_Init(void) +{ + /* enable the led clock */ + rcu_periph_clock_enable(SCL_RCU); + /* configure led GPIO port */ + gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SCL_PIN); + gpio_output_options_set(SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SCL_PIN); + + rcu_periph_clock_enable(SDA_RCU); + gpio_mode_set(SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SDA_PIN); + gpio_output_options_set(SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SDA_PIN); +} + +/** + * @brief Generate I2C start condition. + * + * @note Starts communication by pulling SDA low while SCL is high. + */ +void CT_IIC_Start(void) +{ + CT_SDA_OUT(); + SDA_ON; + SCL_ON; + touch_delay_1us(30); + SDA_OFF; + CT_Delay(); + SCL_OFF; +} + +/** + * @brief Generate I2C stop condition. + * + * @note Ends communication by pulling SDA high while SCL is high. + */ +void CT_IIC_Stop(void) +{ + CT_SDA_OUT(); + SCL_ON; + touch_delay_1us(30); + SDA_OFF; + CT_Delay(); + SDA_ON; +} + +/** + * @brief Wait for I2C ACK signal. + * + * @return 0 if ACK received successfully, 1 if timeout occurred. + * + * @warning If ACK is not received within 250 iterations, a stop condition is generated. + */ +uint8_t CT_IIC_Wait_Ack(void) +{ + uint8_t ucErrTime = 0; + CT_SDA_IN(); + SDA_ON; + SCL_ON; + CT_Delay(); + while (CT_READ_SDA) + { + ucErrTime++; + if (ucErrTime > 250) + { + CT_IIC_Stop(); + return 1; + } + CT_Delay(); + } + SCL_OFF; + return 0; +} + +/** + * @brief Generate I2C ACK signal. + * + * @note This is used to acknowledge receipt of a byte in I2C communication. + */ +void CT_IIC_Ack(void) +{ + SCL_OFF; + CT_SDA_OUT(); + CT_Delay(); + SDA_OFF; + CT_Delay(); + SCL_ON; + CT_Delay(); + SCL_OFF; +} + +/** + * @brief Generate I2C NACK signal. + * + * @note This is used to indicate the end of reading in I2C communication. + */ +void CT_IIC_NAck(void) +{ + SCL_OFF; + CT_SDA_OUT(); + CT_Delay(); + SDA_ON; + CT_Delay(); + SCL_ON; + CT_Delay(); + SCL_OFF; +} + + +/** + * @brief Send a byte over I2C. + * + * @param txd Byte to send. + * + * @note Sends 8 bits starting from the MSB over the SDA line. + */ +void CT_IIC_Send_Byte(uint8_t txd) +{ + uint8_t t; + CT_SDA_OUT(); + SCL_OFF; + CT_Delay(); + for (t = 0; t < 8; t++) + { + if ((txd & 0x80) >> 7) + { + gpio_bit_set(SDA_PORT, SDA_PIN); + } + else + { + gpio_bit_reset(SDA_PORT, SDA_PIN); + } + + txd <<= 1; + SCL_ON; + CT_Delay(); + SCL_OFF; + CT_Delay(); + } +} + +/** + * @brief Read a byte over I2C. + * + * @param ack If 1, send ACK after receiving; if 0, send NACK. + * + * @return The received byte. + */ +uint8_t CT_IIC_Read_Byte(unsigned char ack) +{ + volatile uint8_t i, receive = 0; + CT_SDA_IN(); + touch_delay_1us(30); + for (i = 0; i < 8; i++) + { + SCL_OFF; + CT_Delay(); + SCL_ON; + receive <<= 1; + + if (CT_READ_SDA) + receive++; + } + + if (!ack) + CT_IIC_NAck(); + else + CT_IIC_Ack(); + return receive; +} + +/** + * @brief Write data to FT5206 register. + * + * @param reg Register address. + * @param buf Pointer to data buffer. + * @param len Length of data to write. + * + * @return 0 if successful, non-zero if any write fails. + */ +uint8_t FT5206_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len) +{ + uint8_t i; + uint8_t ret = 0; + CT_IIC_Start(); + CT_IIC_Send_Byte(FT_CMD_WR); + CT_IIC_Wait_Ack(); + CT_IIC_Send_Byte(reg & 0XFF); + CT_IIC_Wait_Ack(); + for (i = 0; i < len; i++) + { + CT_IIC_Send_Byte(buf[i]); + ret = CT_IIC_Wait_Ack(); + if (ret) + break; + } + CT_IIC_Stop(); + return ret; +} + +/** + * @brief Read data from FT5206 register. + * + * @param reg Register address. + * @param buf Pointer to buffer to store read data. + * @param len Number of bytes to read. + */ +void FT5206_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len) +{ + uint8_t i; + CT_IIC_Start(); + CT_IIC_Send_Byte(FT_CMD_WR); + CT_IIC_Wait_Ack(); + CT_IIC_Send_Byte(reg & 0XFF); + CT_IIC_Wait_Ack(); + CT_IIC_Start(); + CT_IIC_Send_Byte(FT_CMD_RD); + CT_IIC_Wait_Ack(); + for (i = 0; i < len; i++) + { + buf[i] = CT_IIC_Read_Byte(i == (len - 1) ? 0 : 1); + } + CT_IIC_Stop(); +} + +/** + * @brief Initialize the FT5206 touch screen controller. + * + * @note Initializes I2C, sets operational modes and touch sensitivity. + * + * @return 0 if initialization is successful. + */ +uint8_t FT5206_Init(void) +{ + uint8_t temp[5]; + /* enable the led clock */ + rcu_periph_clock_enable(INT_RCU); + /* configure led GPIO port */ + gpio_mode_set(INT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, INT_PIN); + + + CT_IIC_Init(); + + FT5206_WR_Reg(FT_DEVIDE_MODE, temp, 1); + FT5206_WR_Reg(FT_ID_G_MODE, temp, 1); + temp[0] = 22; + FT5206_WR_Reg(FT_ID_G_THGROUP, temp, 1); + temp[0] = 12; + FT5206_WR_Reg(FT_ID_G_PERIODACTIVE, temp, 1); + + FT5206_RD_Reg(FT_ID_G_LIB_VERSION, &temp[0], 2); + printf("CTP ID:%x\r\n", ((uint16_t)temp[0] << 8) + temp[1]); + return 0; +} + +/** + * @brief Scan the touch screen using polling. + * + * @param mode 0 for normal scan mode. + * + * @return 1 if a touch is detected, 0 otherwise. + */ +uint8_t FT5206_Scan(uint8_t mode) +{ + uint8_t buf[4]; + uint8_t i = 0; + uint8_t res = 0; + uint8_t temp; + uint16_t tempsta; + static uint8_t t = 0; + t++; + if ((t % 10) == 0 || t < 10) + { + FT5206_RD_Reg(FT_REG_NUM_FINGER, &mode, 1); + if ((mode & 0XF) && ((mode & 0XF) <= g_gt_tnum)) + { + temp = 0XFF << (mode & 0XF); + tempsta = tp_dev.sta; + tp_dev.sta = (~temp) | TP_PRES_DOWN | TP_CATH_PRES; + tp_dev.x[g_gt_tnum - 1] = tp_dev.x[0]; + tp_dev.y[g_gt_tnum - 1] = tp_dev.y[0]; + + for (i = 0; i < g_gt_tnum; i++) + { + if (tp_dev.sta & (1 << i)) + { + FT5206_RD_Reg(FT5206_TPX_TBL[i], buf, 4); + if (tp_dev.touchtype & 0X01) + { + tp_dev.y[i] = ((uint16_t)(buf[0] & 0X0F) << 8) + buf[1]; + tp_dev.x[i] = ((uint16_t)(buf[2] & 0X0F) << 8) + buf[3]; + } + else + { + tp_dev.x[i] = (((uint16_t)(buf[0] & 0X0F) << 8) + buf[1]); + tp_dev.y[i] = ((uint16_t)(buf[2] & 0X0F) << 8) + buf[3]; + } + } + } + res = 1; + if (tp_dev.x[0] > ACTIVE_WIDTH || tp_dev.y[0] > ACTIVE_HEIGHT) + { + if ((mode & 0XF) > 1) + { + tp_dev.x[0] = tp_dev.x[1]; + tp_dev.y[0] = tp_dev.y[1]; + t = 0; + } + else + { + tp_dev.x[0] = tp_dev.x[g_gt_tnum - 1]; + tp_dev.y[0] = tp_dev.y[g_gt_tnum - 1]; + mode = 0X80; + tp_dev.sta = tempsta; + } + } + else + t = 0; + } + } + + if ((mode & 0X1F) == 0) + { + if (tp_dev.sta & TP_PRES_DOWN) + { + tp_dev.sta &= ~TP_PRES_DOWN; + } + else + { + tp_dev.x[0] = 0xffff; + tp_dev.y[0] = 0xffff; + tp_dev.sta &= 0XE0; + } + } + + if (t > 240) + t = 10; + return res; +} + +/** + * @brief Detect touch release by monitoring a specific touch point. + * + * @param contact Index of touch contact to check. + * @param sx Start X coordinate. + * @param sy Start Y coordinate. + * @param ex End X coordinate. + * @param ey End Y coordinate. + * + * @note Returns when the touch point leaves the specified rectangle. + */ +void letgo_scan(uint16_t contact, uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey) +{ + while (FT5206_Scan(0)) + { + if (tp_dev.x[contact] <= sx || tp_dev.x[contact] >= ex) + { + return; + } + + if (tp_dev.y[contact] <= sy && tp_dev.y[contact] >= ey) + { + return; + } + } +} + +/** + * @brief Example application to test the touch screen functionality. + * + * @return Always returns 0. + * + * @warning This function runs an infinite loop and is intended for manual test only. + */ +int touch_test(void) +{ + int touch_state = 0; + FT5206_Init(); + + while (1) + { + touch_state = FT5206_Scan(0); + + if (touch_state == 1) + { + rt_kprintf("touch\r\n"); + } + rt_thread_mdelay(10); + } +} +MSH_CMD_EXPORT(touch_test, touch test) diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.h b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.h new file mode 100644 index 0000000000..3e11db37a2 --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/drv_touch.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#ifndef __TOUCH_H__ +#define __TOUCH_H__ + +#include "stdio.h" +#include "string.h" +#include "gd32f4xx.h" + + +#define SCL_RCU RCU_GPIOB +#define SCL_PORT GPIOB +#define SCL_PIN GPIO_PIN_6 +#define SCL_ON gpio_bit_set(SCL_PORT, SCL_PIN) +#define SCL_OFF gpio_bit_reset(SCL_PORT, SCL_PIN) +#define SCL_TOGGLE gpio_bit_toggle(SCL_PORT, SCL_PIN) + +#define SDA_RCU RCU_GPIOB +#define SDA_PORT GPIOB +#define SDA_PIN GPIO_PIN_7 +#define SDA_ON gpio_bit_set(SDA_PORT, SDA_PIN) +#define SDA_OFF gpio_bit_reset(SDA_PORT, SDA_PIN) +#define SDA_TOGGLE gpio_bit_toggle(SDA_PORT, SDA_PIN) + +/* IO direction settings */ +#define CT_SDA_IN() gpio_mode_set(SCL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SDA_PIN); //{GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=0<<2*11;} //PF11输入模式 +#define CT_SDA_OUT() gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SDA_PIN); //{GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=1<<2*11;} //PF11输出模式 +/* IO operations */ +#define CT_IIC_SCL // PBout(0) //SCL +#define CT_IIC_SDA(val) ((val) == 1 ? SDA_ON : SDA_OFF) // PFout(11) //SDA +#define CT_READ_SDA gpio_input_bit_get(SDA_PORT, SDA_PIN) // PFin(11) //输入SDA +/* Reset and interrupt pin definitions */ +#define RST_RCU RCU_GPIOD +#define RST_PORT GPIOD +#define RST_PIN GPIO_PIN_12 +#define RST_ON gpio_bit_set(RST_PORT, RST_PIN); +#define RST_OFF gpio_bit_reset(RST_PORT, RST_PIN); +#define RST_TOGGLE gpio_bit_toggle(RST_PORT, RST_PIN); + +#define INT_RCU RCU_GPIOD +#define INT_PORT GPIOD +#define INT_PIN GPIO_PIN_11 +#define INT_ON gpio_bit_set(INT_PORT, INT_PIN); +#define INT_OFF gpio_bit_reset(INT_PORT, INT_PIN); +#define INT_TOGGLE gpio_bit_toggle(INT_PORT, INT_PIN); + +/* I2C command definitions */ +#define FT_CMD_WR 0X70 /**< FT5206 write command */ +#define FT_CMD_RD 0X71 /**< FT5206 read command */ +/* FT5206 register definitions */ +#define FT_DEVIDE_MODE 0x00 /**< Mode control register */ +#define FT_REG_NUM_FINGER 0x02 /**< Touch status register */ +#define FT_TP1_REG 0x03 /**< Touch point 1 data */ +#define FT_TP2_REG 0x09 /**< Touch point 2 data */ +#define FT_TP3_REG 0x0F /**< Touch point 3 data */ +#define FT_TP4_REG 0x15 /**< Touch point 4 data */ +#define FT_TP5_REG 0x1B /**< Touch point 5 data */ +#define FT_ID_G_LIB_VERSION 0xA1 /**< Firmware version */ +#define FT_ID_G_MODE 0xA4 /**< Interrupt mode control */ +#define FT_ID_G_THGROUP 0x80 /**< Touch sensitivity */ +#define FT_ID_G_PERIODACTIVE 0x88 /**< Active period register */ + +#define TP_PRES_DOWN 0x80 /**< Touch pressed flag */ +#define TP_CATH_PRES 0x40 /**< Key press detected flag */ +#define CT_MAX_TOUCH 5 /**< Maximum number of supported touch points */ +/** + * @brief Touch point device structure. + */ +typedef struct +{ + uint16_t x[CT_MAX_TOUCH]; /**< X coordinates of touch points */ + uint16_t y[CT_MAX_TOUCH]; /**< Y coordinates of touch points */ + uint8_t sta; /**< Touch status flag */ + float xfac; /**< X axis scaling factor */ + float yfac; /**< Y axis scaling factor */ + short xoff; /**< X axis offset */ + short yoff; /**< Y axis offset */ + uint8_t touchtype; /**< Touch type flag */ +} _m_tp_dev; + +extern _m_tp_dev tp_dev; + +/** + * @brief Initialize I2C GPIO lines. + */ +void CT_IIC_Init(void); + +/** + * @brief Generate I2C start condition. + */ +void CT_IIC_Start(void); + +/** + * @brief Generate I2C stop condition. + */ +void CT_IIC_Stop(void); + +/** + * @brief Send a byte over I2C. + * + * @param txd Byte to send. + */ +void CT_IIC_Send_Byte(uint8_t txd); + +/** + * @brief Read a byte over I2C. + * + * @param ack 1 to send ACK after read, 0 for NACK. + * + * @return The received byte. + */ +uint8_t CT_IIC_Read_Byte(unsigned char ack); + +/** + * @brief Wait for I2C ACK. + * + * @return 0 on success, non-zero on timeout. + */ +uint8_t CT_IIC_Wait_Ack(void); + +/** + * @brief Generate I2C ACK. + */ +void CT_IIC_Ack(void); + +/** + * @brief Generate I2C NACK. + */ +void CT_IIC_NAck(void); + +/** + * @brief Write data to FT5206 register. + * + * @param reg Register address. + * @param buf Pointer to data. + * @param len Number of bytes to write. + * + * @return 0 if success, non-zero otherwise. + */ +uint8_t FT5206_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len); + +/** + * @brief Read data from FT5206 register. + * + * @param reg Register address. + * @param buf Buffer to store data. + * @param len Number of bytes to read. + */ +void FT5206_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len); + +/** + * @brief Initialize the FT5206 touch controller. + * + * @return 0 if successful. + */ +uint8_t FT5206_Init(void); + +/** + * @brief Poll the FT5206 for touch input. + * + * @param mode Scan mode. + * + * @return 1 if touch detected, 0 otherwise. + */ +uint8_t FT5206_Scan(uint8_t mode); + +/** + * @brief Wait until touch contact leaves specified area. + * + * @param contact Touch point index. + * @param sx Start X coordinate. + * @param sy Start Y coordinate. + * @param ex End X coordinate. + * @param ey End Y coordinate. + */ +void letgo_scan(uint16_t contact, uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey); + + +#endif diff --git a/bsp/gd32/arm/gd32470z-lckfb/board/ports/font.h b/bsp/gd32/arm/gd32470z-lckfb/board/ports/font.h new file mode 100644 index 0000000000..567068a9ee --- /dev/null +++ b/bsp/gd32/arm/gd32470z-lckfb/board/ports/font.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-05-23 godmial Refactor to conform to RT-Thread coding style. + */ + +#ifndef __FONT_H__ +#define __FONT_H__ + +const unsigned char asc2_1608[95][16] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/ + {0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, /*"!",1*/ + {0x00, 0x48, 0x6C, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",2*/ + {0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x7F, 0x12, 0x12, 0x12, 0x7F, 0x12, 0x12, 0x12, 0x00, 0x00}, /*"#",3*/ + {0x00, 0x00, 0x08, 0x1C, 0x2A, 0x2A, 0x0A, 0x0C, 0x18, 0x28, 0x28, 0x2A, 0x2A, 0x1C, 0x08, 0x08}, /*"$",4*/ + {0x00, 0x00, 0x00, 0x22, 0x25, 0x15, 0x15, 0x15, 0x2A, 0x58, 0x54, 0x54, 0x54, 0x22, 0x00, 0x00}, /*"%",5*/ + {0x00, 0x00, 0x00, 0x0C, 0x12, 0x12, 0x12, 0x0A, 0x76, 0x25, 0x29, 0x11, 0x91, 0x6E, 0x00, 0x00}, /*"&",6*/ + {0x00, 0x06, 0x06, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"'",7*/ + {0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00}, /*"(",8*/ + {0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00}, /*")",9*/ + {0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x1C, 0x1C, 0x6B, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, /*"*",10*/ + {0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x7F, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00}, /*"+",11*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x03}, /*",",12*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"-",13*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, /*".",14*/ + {0x00, 0x00, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00}, /*"/",15*/ + {0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00}, /*"0",16*/ + {0x00, 0x00, 0x00, 0x08, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"1",17*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x20, 0x20, 0x10, 0x08, 0x04, 0x42, 0x7E, 0x00, 0x00}, /*"2",18*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x20, 0x18, 0x20, 0x40, 0x40, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"3",19*/ + {0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x24, 0x22, 0x22, 0x7E, 0x20, 0x20, 0x78, 0x00, 0x00}, /*"4",20*/ + {0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x02, 0x1A, 0x26, 0x40, 0x40, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"5",21*/ + {0x00, 0x00, 0x00, 0x38, 0x24, 0x02, 0x02, 0x1A, 0x26, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00}, /*"6",22*/ + {0x00, 0x00, 0x00, 0x7E, 0x22, 0x22, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /*"7",23*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"8",24*/ + {0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0x40, 0x24, 0x1C, 0x00, 0x00}, /*"9",25*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, /*":",26*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04}, /*";",27*/ + {0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00}, /*"<",28*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"=",29*/ + {0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /*">",30*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x40, 0x20, 0x10, 0x10, 0x00, 0x18, 0x18, 0x00, 0x00}, /*"?",31*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x5A, 0x55, 0x55, 0x55, 0x55, 0x2D, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"@",32*/ + {0x00, 0x00, 0x00, 0x08, 0x08, 0x18, 0x14, 0x14, 0x24, 0x3C, 0x22, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"A",33*/ + {0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x1E, 0x22, 0x42, 0x42, 0x42, 0x22, 0x1F, 0x00, 0x00}, /*"B",34*/ + {0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"C",35*/ + {0x00, 0x00, 0x00, 0x1F, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1F, 0x00, 0x00}, /*"D",36*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x42, 0x42, 0x3F, 0x00, 0x00}, /*"E",37*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"F",38*/ + {0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x01, 0x01, 0x01, 0x71, 0x21, 0x22, 0x22, 0x1C, 0x00, 0x00}, /*"G",39*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"H",40*/ + {0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"I",41*/ + {0x00, 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x0F}, /*"J",42*/ + {0x00, 0x00, 0x00, 0x77, 0x22, 0x12, 0x0A, 0x0E, 0x0A, 0x12, 0x12, 0x22, 0x22, 0x77, 0x00, 0x00}, /*"K",43*/ + {0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x7F, 0x00, 0x00}, /*"L",44*/ + {0x00, 0x00, 0x00, 0x77, 0x36, 0x36, 0x36, 0x36, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x6B, 0x00, 0x00}, /*"M",45*/ + {0x00, 0x00, 0x00, 0xE3, 0x46, 0x46, 0x4A, 0x4A, 0x52, 0x52, 0x52, 0x62, 0x62, 0x47, 0x00, 0x00}, /*"N",46*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00}, /*"O",47*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"P",48*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x4D, 0x53, 0x32, 0x1C, 0x60, 0x00}, /*"Q",49*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x42, 0x3E, 0x12, 0x12, 0x22, 0x22, 0x42, 0xC7, 0x00, 0x00}, /*"R",50*/ + {0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x02, 0x04, 0x18, 0x20, 0x40, 0x42, 0x42, 0x3E, 0x00, 0x00}, /*"S",51*/ + {0x00, 0x00, 0x00, 0x7F, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /*"T",52*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"U",53*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x22, 0x24, 0x24, 0x14, 0x14, 0x18, 0x08, 0x08, 0x00, 0x00}, /*"V",54*/ + {0x00, 0x00, 0x00, 0x6B, 0x49, 0x49, 0x49, 0x49, 0x55, 0x55, 0x36, 0x22, 0x22, 0x22, 0x00, 0x00}, /*"W",55*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0xE7, 0x00, 0x00}, /*"X",56*/ + {0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /*"Y",57*/ + {0x00, 0x00, 0x00, 0x7E, 0x21, 0x20, 0x10, 0x10, 0x08, 0x04, 0x04, 0x42, 0x42, 0x3F, 0x00, 0x00}, /*"Z",58*/ + {0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}, /*"[",59*/ + {0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40}, /*"\",60*/ + {0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00}, /*"]",61*/ + {0x00, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"^",62*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, /*"_",63*/ + {0x00, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"`",64*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x78, 0x44, 0x42, 0x42, 0xFC, 0x00, 0x00}, /*"a",65*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x1A, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1A, 0x00, 0x00}, /*"b",66*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00}, /*"c",67*/ + {0x00, 0x00, 0x00, 0x60, 0x40, 0x40, 0x40, 0x78, 0x44, 0x42, 0x42, 0x42, 0x64, 0xD8, 0x00, 0x00}, /*"d",68*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00}, /*"e",69*/ + {0x00, 0x00, 0x00, 0xF0, 0x88, 0x08, 0x08, 0x7E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"f",70*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x22, 0x22, 0x1C, 0x02, 0x3C, 0x42, 0x42, 0x3C}, /*"g",71*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"h",72*/ + {0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"i",73*/ + {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1E}, /*"j",74*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x72, 0x12, 0x0A, 0x16, 0x12, 0x22, 0x77, 0x00, 0x00}, /*"k",75*/ + {0x00, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"l",76*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x92, 0x92, 0x92, 0x92, 0x92, 0xB7, 0x00, 0x00}, /*"m",77*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"n",78*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"o",79*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x26, 0x42, 0x42, 0x42, 0x22, 0x1E, 0x02, 0x07}, /*"p",80*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x40, 0xE0}, /*"q",81*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x4C, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x00, 0x00}, /*"r",82*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x02, 0x3C, 0x40, 0x42, 0x3E, 0x00, 0x00}, /*"s",83*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00}, /*"t",84*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xDC, 0x00, 0x00}, /*"u",85*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x14, 0x08, 0x08, 0x00, 0x00}, /*"v",86*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x49, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00}, /*"w",87*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x24, 0x18, 0x18, 0x18, 0x24, 0x6E, 0x00, 0x00}, /*"x",88*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x14, 0x18, 0x08, 0x08, 0x07}, /*"y",89*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x22, 0x10, 0x08, 0x08, 0x44, 0x7E, 0x00, 0x00}, /*"z",90*/ + {0x00, 0xC0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x00}, /*"{",91*/ + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /*"|",92*/ + {0x00, 0x06, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00}, /*"}",93*/ + {0x0C, 0x32, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"~",94*/ +}; + +#endif diff --git a/bsp/gd32/arm/libraries/GD32F4xx_Firmware_Library/SConscript b/bsp/gd32/arm/libraries/GD32F4xx_Firmware_Library/SConscript index 8639928ed4..c654f46c00 100644 --- a/bsp/gd32/arm/libraries/GD32F4xx_Firmware_Library/SConscript +++ b/bsp/gd32/arm/libraries/GD32F4xx_Firmware_Library/SConscript @@ -53,6 +53,12 @@ if GetDepend(['BSP_USING_SDRAM']): src += ['GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c'] src += ['GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c'] +if GetDepend(['BSP_USING_TLI']): + src += ['GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c'] + +if GetDepend(['BSP_USING_GPU']): + src += ['GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c'] + path = [ cwd + '/CMSIS/GD/GD32F4xx/Include', cwd + '/CMSIS',