#include "include.h" #include "tft_font.h" #if GUI_SELECT #define TRACE_EN 0 #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #else #define TRACE(...) #endif /** @brief * 推点画矩形 * @param 窗口大小x * @param 窗口大小y * @param 左上角、右下角坐标,颜色 * @return void */ void tft_draw_rect(u16 x, u16 y, u16 wid, u16 hei, uint16_t color) { if (wid && hei) { u16 x1 = x + wid - 1; u16 y1 = y + hei - 1; TRACE("%s[%d %d %d %d 0x%x]\n", __func__, x, y, wid, hei, color); tft_set_window(x, y, x1, y1); tft_write_cmd(0x2C); for (int i = x; i <= x1; i++){ for (int j = y; j <= y1; j++){ WDT_CLR(); tft_write_data(color >> 8); tft_write_data(color); } } tft_write_end(); } } /** @brief * 创建进度条(默认画灰底,创建后进度为0%) * @param p_bar:进度条指针 * @param x,y,wid,hei:左上角坐标、宽高 * @return void */ void progress_bar_create(progress_bar_t *p_bar, u16 x, u16 y, u16 wid, u16 hei) { p_bar->x = x; p_bar->y = y; p_bar->wid = wid; p_bar->hei = hei; p_bar->progress = 0; TRACE("%s[%d %d %d %d]\n", __func__, p_bar->x, p_bar->y, p_bar->wid, p_bar->hei); tft_draw_rect(x, y, wid, hei, TFT_COLOR_GRAY); } /** @brief * 更新进度条(默认覆盖绿色矩形) * @param p_bar:进度条指针 * @param process:当前进度(0-100) * @return void */ void progress_bar_update(progress_bar_t *p_bar, u8 progress) { u16 x, w; if (p_bar->progress < progress) { x = p_bar->x + p_bar->wid * p_bar->progress / 100; if (progress >= 100) { w = p_bar->x + p_bar->wid - x; } else { w = p_bar->x + p_bar->wid * progress / 100 - x; } TRACE("%s:%d%%\n", __func__, progress); tft_draw_rect(x, p_bar->y, w, p_bar->hei, TFT_COLOR_GREEN); p_bar->progress = progress; } } /** @brief * 字符串显示(ASCII字库) * @param XY:坐标 * @param text:显示文本 * @param center:是否居中 * @param color:颜色 * @return void */ void tft_draw_string(u16 x, u16 y, char *text, bool center, uint16_t color, uint16_t bg_color) { /* 居中计算 */ if (center) { x = (GUI_SCREEN_WIDTH - (strlen(text) * gui_font.wid)) / 2; } while (*text != '\0') { /* 跳过非法字符 */ if (*text < gui_font.start || *text > gui_font.end) { continue; } /* 字符显示区域 */ u16 x1 = x + gui_font.wid - 1; u16 y1 = y + gui_font.hei - 1; if (x1 >= GUI_SCREEN_WIDTH || y1 >= GUI_SCREEN_HEIGHT) { return; } /* 获取字库数据偏移 */ uint16_t wid_offset = gui_font.wid % 8 != 0 ? gui_font.wid + gui_font.wid % 8 : gui_font.wid; uint32_t font_data_base = (*text - gui_font.start) * (wid_offset * gui_font.hei / 8); /* 绘制当前文字 */ tft_set_window(x, y, x1, y1); tft_write_cmd(0x2C); for (int j = 0; j < gui_font.hei; j++) { for (int i = 0; i < gui_font.wid; i++) { WDT_CLR(); if (gui_font.font[font_data_base] & BIT(8 - ((i % 8) + 1))) { tft_write_data(color >> 8); tft_write_data(color); } else { tft_write_data(bg_color >> 8); tft_write_data(bg_color); } if ((i + 1) % 8 == 0 || i == (gui_font.wid - 1)) { font_data_base++; } } } tft_write_end(); /* 偏移下一个文字 */ x += gui_font.wid; text++; } } void tft_init(void) { TRACE("tft_init\n"); power_gate_3v3_on(); // clk init CLKDIVCON2 = (CLKDIVCON2 & ~(BIT(4) * 0xF)) | BIT(4) * 2; // TFTDE div CLKGAT2 |= BIT(4); RSTCON0 |= BIT(8); /* 屏幕硬件脚位初始化 */ GPIOAFEN &= ~BIT(5); // CS GPIOADE |= BIT(5); GPIOASET = BIT(5); GPIOADIR &= ~BIT(5); GPIOAFEN |= BIT(4); // CLK GPIOADE |= BIT(4); GPIOACLR = BIT(4); GPIOADIR &= ~BIT(4); GPIOAFEN |= (BIT(2)|BIT(3)|BIT(1)|BIT(0)); // D0/D1/D2/D3 GPIOADE |= (BIT(2)|BIT(3)|BIT(1)|BIT(0)); GPIOADIR |= (BIT(2)|BIT(3)|BIT(1)|BIT(0)); GPIOADIR &= ~BIT(3); // DC脚 设置输出 FUNCMCON2 = BIT(28); /* RESET */ GPIOEFEN &= ~BIT(3); //RESET GPIOEDE |= BIT(3); GPIOESET = BIT(3); GPIOEDIR &= ~BIT(3); delay_ms(10); GPIOECLR = BIT(3); delay_ms(10); GPIOESET = BIT(3); delay_ms(20); /* 初始化 */ DESPICON = BIT(27) | BIT(2) | BIT(7) | BIT(0); //[28:27]IN RGB565, [9]MultiBit, [7]IE, [3:2]4BIT, [0]EN tft_driver_init(); tft_draw_rect(0, 0, GUI_SCREEN_WIDTH, GUI_SCREEN_HEIGHT, TFT_COLOR_BLACK); //黑底 delay_ms(50); //防止花屏 LCD_BL_EN(); } #endif