- /*
- * Copyright (c) 2020. By WoodData
- *
- *
- * Change Logs:
- * Date Author Notes
- */
- #ifndef LCD_FONT__H_
- #define LCD_FONT__H_
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include "drv_lcd.h"
- #define lcd_color_t uint16_t
- /* type define ------------------------------------------------------------*/
- typedef struct _lcd_font
- {
- uint8_t font_height; //字库通用高度
- uint8_t * pfont_buff; //字库buff
- uint8_t * pfont_filename; //字库文件
- uint8_t (* get_font_w)(uint16_t ch); //获取指定字符宽度
- void (* draw_char)(uint16_t x,uint16_t y,uint16_t ch); //指定字符描点
- }lcd_font_t;
- typedef struct _lcd_font_display
- {
- lcd_font_t *pfont; //字库索引
- lcd_color_t font_fore; //字体前景颜色
- lcd_color_t font_back; //字体背景颜色
- uint16_t font_sx; //字符显示范围起点x
- uint16_t font_sy; //字符显示范围起点y
- uint16_t font_ex; //字符显示范围终点x
- uint16_t font_ey; //字符显示范围终点y
- }lcd_font_display_t;
- //common
- int GetGBKCode_from_sd(uint8_t *filename, uint16_t ch, uint8_t *pBuffer, uint16_t len);
- int GetASCCode_from_sd(uint8_t *filename, uint16_t ch, uint8_t *pBuffer, uint16_t len);
- //API
- lcd_font_t * lcd_set_font( const lcd_font_t *newfont);
- lcd_font_t * lcd_get_font(void);
- void lcd_set_font_color(lcd_color_t fore, lcd_color_t back);
- lcd_color_t lcd_get_font_color_fore(void);
- lcd_color_t lcd_get_font_color_back(void);
- void lcd_set_font_window(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey);
- void lcd_disp_char_at(uint16_t usX, uint16_t usY, uint16_t cChar);
- void lcd_disp_str_at(uint16_t usX, uint16_t usY, const char *pStr);
- void lcd_font_init(void);
- //字库
- extern const lcd_font_t Font_CH16X16;
- extern const lcd_font_t Font_ASCII16X8;
- extern const lcd_font_t Font_CH24X24;
- extern const lcd_font_t Font_ASCII24X12;
- extern const lcd_font_t Font_CH32X32;
- extern const lcd_font_t Font_ASCII32X16;
- extern const lcd_font_t Font_CH40X40;
- extern const lcd_font_t Font_ASCII40X20;
- extern const lcd_font_t Font_CH48X48;
- extern const lcd_font_t Font_ASCII48X24;
- #endif //LCD_FONT__H_
- /*
- * Copyright (c) 2020. By WoodData
- *
- *
- * Change Logs:
- * Date Author Notes
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include "drv_lcd.h"
- #include "lcd_font.h"
- lcd_font_display_t cur_lcd_font_display;
- /**
- * 设置当前字体
- * para: *newfont 新字体
- * return: none
- */
- lcd_font_t * lcd_set_font(const lcd_font_t * newfont)
- {
- lcd_font_t *oldfont;
- oldfont = cur_lcd_font_display.pfont;
- cur_lcd_font_display.pfont = newfont;
- return oldfont;
- }
- /**
- * 获取当前字体
- * para: none
- * return: 当前字体
- */
- lcd_font_t * lcd_get_font(void)
- {
- return cur_lcd_font_display.pfont;
- }
- /**
- * 设置当前字体颜色
- * para1: fore 前景色
- * para2: back 背景色
- * return: none
- */
- void lcd_set_font_color(lcd_color_t fore, lcd_color_t back)
- {
- cur_lcd_font_display.font_fore = fore;
- cur_lcd_font_display.font_back = back;
- }
- /**
- * 获取当前字体前景色
- * para: none
- * return: 当前字体前景色
- */
- lcd_color_t lcd_get_font_color_fore(void)
- {
- return cur_lcd_font_display.font_fore;
- }
- /**
- * 获取当前字体背景色
- * para: none
- * return: 当前字体背景色
- */
- lcd_color_t lcd_get_font_color_back(void)
- {
- return cur_lcd_font_display.font_back;
- }
- /**
- * 设置字符显示范围
- * para1: sx
- * para2: sy
- * para3: ex
- * para4: ey
- * return: none
- */
- void lcd_set_font_window(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey)
- {
- cur_lcd_font_display.font_sx = sx;
- cur_lcd_font_display.font_sy = sy;
- cur_lcd_font_display.font_ex = ex;
- cur_lcd_font_display.font_ey = ey;
- }
- /**
- * LCD 上显示字符
- * usX : 在特定扫描的方向下字符的起始 X 坐标
- * usY : 在特定扫描的方向下字符的起始 Y 坐标
- * cChar : 要显示的字符
- * 返回值 : 无
- */
- void lcd_disp_char_at(uint16_t usX, uint16_t usY, uint16_t cChar)
- {
- if((cur_lcd_font_display.pfont != NULL) && (cur_lcd_font_display.pfont->draw_char != NULL))
- {
- cur_lcd_font_display.pfont->draw_char(usX, usY, cChar);
- }
- }
- /**
- * 在 LCD 上显示英文字符串
- * usX : 在特定扫描方向下字符串的起始 X 坐标
- * usY : 在特定扫描方向下字符串的起始 Y 坐标
- * pStr : 要显示的英文字符串的首地址
- * 返回值 : 无
- */
- void lcd_disp_str_at(uint16_t usX, uint16_t usY, const char *pStr)
- {
- uint16_t w,ch;
- if(cur_lcd_font_display.pfont == NULL) return;
- while (*pStr != '\0')
- {
- if(*pStr > 126)
- {
- ch = (*pStr << 8);
- pStr++;
- ch += *pStr;
- }
- else
- {
- ch = *pStr;
- }
-
- w = cur_lcd_font_display.pfont->get_font_w(ch); //获取字符宽度
- #if 0
- if ((usX + w) > cur_lcd_font_display.font_ex)
- {
- usX = cur_lcd_font_display.font_sx;
- usY += cur_lcd_font_display.pfont->font_height;
- }
- if ((usY + cur_lcd_font_display.pfont->font_height) > cur_lcd_font_display.font_ey)
- {
- usX = cur_lcd_font_display.font_sx;
- usY = cur_lcd_font_display.font_sy;
- }
- #endif
-
- lcd_disp_char_at(usX, usY, ch);
- pStr++;
- usX += w;
- }
- }
- void lcd_font_init(void)
- {
- lcd_set_font(&Font_ASCII16X8);
- lcd_set_font_color(BLACK,WHITE);
- lcd_set_font_window(0,0,LCD_W-1,LCD_H-1);
- }
下面是各个字库实现基础。以16X16点阵为例:
- /*
- * Copyright (c) 2020. By WoodData
- *
- *
- * Change Logs:
- * Date Author Notes
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include "drv_lcd.h"
- #include "lcd_font.h"
- #define ASCII_W 8
- #define ASCII_H 16
- #define ASCII_NAME "/sd/font/ASC16.bin"
- #define ASCII_BUFFER_LEN 16
- #define HZK_W 16
- #define HZK_H 16
- #define HZK_FILENAME "/sd/font/HZK16.bin"
- #define HZK_BUFFER_LEN 32
- extern lcd_font_display_t cur_lcd_font_display;
- /**
- * �? lcd 上显示ASCII字符
- * x : 在特定扫描方向下字符串的起始 X 坐标
- * y : 在特定扫描方向下字符串的起始 Y 坐标
- * usChar : 要显示的字符
- *
- */
- void lcd_disp_ascii_16x8(uint16_t x, uint16_t y, uint16_t usChar)
- {
- uint8_t ucPage, ucColum, ucPoint8, *ucPtr;
- uint8_t ucBuffer[ASCII_BUFFER_LEN] = {0};
- if(usChar < 0x7f) //ASCII �?
- {
- if((x>=LCD_W) || (y>=LCD_H)) return;
- lcd_open_window(x, y, (x+ASCII_W >= LCD_W)?(LCD_W-x):ASCII_W, (y+ASCII_H >= LCD_H)?(LCD_H-y): ASCII_H);
- GetASCCode_from_sd(ASCII_NAME, usChar, ucBuffer, ASCII_BUFFER_LEN); //取字模数�?
- ucPtr = ucBuffer;
- for (ucPage = 0; ucPage < ASCII_H; ucPage++)
- {
- if((y+ucPage) >= LCD_H) break;
- for (ucColum = 0; ucColum < (ASCII_W); )
- {
- for(ucPoint8 = 0;ucPoint8 < 8;ucPoint8++)
- {
- if((x+ucColum) < LCD_W)
- {
- if( *ucPtr & (0x80 >> ucPoint8)) //高位在前
- {
- lcd_write_half_word(cur_lcd_font_display.font_fore);
- }
- else
- {
- lcd_write_half_word(cur_lcd_font_display.font_back);
- }
- }
- ucColum++;
- if(ucColum == ASCII_W) break;
- }
- ucPtr++;
- }
- }
- }else
- {
-
- }
- }
- uint8_t ascii16_get_font_w(uint16_t ch) //获取指定字符宽度
- {
- ch = ch;
- return ASCII_W;
- }
- const lcd_font_t Font_ASCII16X8 =
- {
- ASCII_H,
- ASCII_NAME,
- NULL,
- ascii16_get_font_w,
- lcd_disp_ascii_16x8,
- };
- /**
- * �? lcd 上显示中文字�?
- * x : 在特定扫描方向下字符串的起始 X 坐标
- * y : 在特定扫描方向下字符串的起始 Y 坐标
- * usChar : 要显示的字符
- *
- */
- void lcd_disp_ch16x16(uint16_t x, uint16_t y, uint16_t usChar)
- {
- uint8_t ucPage, ucColum, ucPoint8, *ucPtr;
- uint8_t ucBuffer[HZK_BUFFER_LEN] = {0};
- ucPage = usChar >> 8; /* 取高8位数�? */
- ucColum = usChar & 0x00FF; /* 取低8位数�? */
- if(usChar < 0x7f) //ASCII �?
- {
- lcd_disp_ascii_16x8(x,y,usChar);
- }else if((ucPage > 0xa0)&&(ucColum >0xa0)) //中文字符
- {
- if((x>=LCD_W) || (y>=LCD_H)) return;
- lcd_open_window(x, y, (x+HZK_W >= LCD_W)?(LCD_W-x):HZK_W, (y+HZK_H >= LCD_H)?(LCD_H-y): HZK_H);
- GetGBKCode_from_sd(HZK_FILENAME, usChar, ucBuffer, HZK_BUFFER_LEN); //取字模数�?
- ucPtr = ucBuffer;
- for (ucPage = 0; ucPage < HZK_H; ucPage++)
- {
- if((y+ucPage) >= LCD_H) break;
- for (ucColum = 0; ucColum < (HZK_W); )
- {
- for(ucPoint8 = 0;ucPoint8 < 8;ucPoint8++)
- {
- if((x+ucColum) < LCD_W)
- {
- if( *ucPtr & (0x80 >> ucPoint8)) //高位在前
- {
- lcd_write_half_word(cur_lcd_font_display.font_fore);
- }
- else
- {
- lcd_write_half_word(cur_lcd_font_display.font_back);
- }
- }
- ucColum++;
- if(ucColum == HZK_W) break;
- }
- ucPtr++;
- }
- }
- }else //不支持字�?
- {
-
- }
- }
- uint8_t CH16_get_font_w(uint16_t ch) //获取指定字符宽度
- {
- uint8_t ucPage, ucColum;
- ucPage = ch >> 8; /* 取高8位数�? */
- ucColum = ch & 0x00FF; /* 取低8位数�? */
- if(ch < 0x7f) //ASCII �?
- {
- return ASCII_W;
- }else if((ucPage > 0xa0)&&(ucColum >0xa0)) //中文字符
- {
- return HZK_W;
- }else
- {
- return 0;
- }
- }
- const lcd_font_t Font_CH16X16 =
- {
- HZK_H,
- ASCII_NAME,
- HZK_FILENAME,
- CH16_get_font_w,
- lcd_disp_ch16x16,
- };
测试:
- #include <rtthread.h>
- #include <rtdevice.h>
- #if defined RT_USING_LCD_TEST
- //添加 lcd 显示使用的头文件
- #include "drv_lcd.h"
- #include "lcd_font.h"
- int test_lcd_ch(int argc, char *argv[])
- {
- rt_err_t ret = RT_EOK;
- lcd_clear(BLUE);
- lcd_set_font(&Font_CH16X16);
- lcd_set_font_color(BLACK, RED);
- lcd_disp_str_at(0, 0, "RT-Thread物联网操作系统");
- rt_thread_mdelay(1000);
- lcd_set_font(&Font_CH24X24);
- lcd_set_font_color(GREEN, BLACK);
- lcd_disp_str_at(20,20, "小而美的物联网操作系统");
- rt_thread_mdelay(1000);
- lcd_set_font(&Font_CH32X32);
- lcd_set_font_color(GREEN, BLACK);
- lcd_disp_str_at(10, 50, "RT-Thread物联网操作系统");
- rt_thread_mdelay(1000);
- lcd_set_font(&Font_CH40X40);
- lcd_set_font_color(WHITE, BLACK);
- lcd_disp_str_at(3, 90, "RT-Thread物联网操作系统");
- rt_thread_mdelay(1000);
- lcd_set_font(&Font_CH48X48);
- lcd_set_font_color(RED, BLUE);
- lcd_disp_str_at(0, 140, "Hi,你好,小而美的物联网操作系统.");
-
- return ret;
- }
- MSH_CMD_EXPORT(test_lcd_ch, test_lcd_ch);
- #endif
最终效果:
字库bin文件:
实现代码: