目录
基础组件实现
如何将图像和文字显示到OLED上
如何绘制图像
如何绘制文字
如何获取字体?
如何正确的访问字体
如何抽象字体
如何绘制字符串
绘制方案
文本绘制
更加方便的绘制
字体附录
ascii 6x8字体
ascii 8 x 16字体
基础组件实现
我们现在离手搓一个动态的多级菜单越来越近了。终于!我们来到了最基础的组件实现,我们现在搓的东西的代码库放到了:MCU_Libs/OLED/library/Graphic/widgets/base at main · Charliechen114514/MCU_Libs (github.com)当中,也就是手搓图像显示和文字显示。如果你对这篇博客所属的集合有任何疑问,可以到从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架-CSDN博客阅读。
如何将图像和文字显示到OLED上
三个字:画出来!带上一个KeysKing大跌手搓的取码地址:波特律动LED字模生成器 (baud-dance.com),实际上,你的悟性足够高,已经可以离开这篇博客自己继续手搓了。
好吧,你继续往下看了,那我就详细的好好说明。
如何绘制图像
绘制图像之前,我们还要遵循老步骤,思考一下如何设计我们的抽象。
我们如何描述一个给定的图像呢?我们可能着急于描述这个图像表达了什么,也就是图像的资源,在OLED中,我们习惯于阐述为一个字节的数组,这个数组描述了我们的图像,只要把它传递上去,一个图像就显示出来我们可以看了。
但是还是有问题:你这个图像放到哪里呢?画的要多大呢?这就是我们需要设计一个结构体抽象的原因了。请看VCR:
typedef struct __CCGraphic_Image{
CCGraphic_Point point;
CCGraphic_Size image_size;
uint8_t* sources_register;
}CCGraphic_Image;
关于CCGraphic_Size,并不复杂,可以到MCU_Libs/OLED/library/Graphic/widgets/common/CCGraphic_Size at main · Charliechen114514/MCU_Libs (github.com)中看到源码,实际上就是宽和高的一个封装,没什么大不了的。
此外,我们对图像的操作就是绘制了
void CCGraphicWidget_init_image(
CCGraphic_Image* image,
CCGraphic_Point tl_point,
CCGraphic_Size image_size,
uint8_t* sources_register
);
void CCGraphicWidget_draw_image(
CCDeviceHandler* handler,
CCGraphic_Image* image
);
出乎你意料的是。绘制图像远远比你想象的简单的多
#include "Graphic/widgets/base/CCGraphic_Image/CCGraphic_Image.h"
#include "Graphic/CCGraphic_device_adapter.h"
void CCGraphicWidget_init_image(
CCGraphic_Image* image,
CCGraphic_Point tl_point,
CCGraphic_Size image_size,
uint8_t* sources_register
)
{
image->image_size = image_size;
image->point = tl_point;
image->sources_register = sources_register;
}
void CCGraphicWidget_draw_image(
CCDeviceHandler* handler,
CCGraphic_Image* image
)
{
if(!image->sources_register) return;
handler->operations.draw_area_device_function(
handler, image->point.x, image->point.y,
image->image_size.width, image->image_size.height, image->sources_register
);
}
我们直接使用设备draw_area的方法,将图像资源传递上去了。
CCGraphicWidget_draw_image -> draw_area_device_function(draw_area_device_oled) -> oled_helper_draw_area
你看,干净利落!完事。
如何绘制文字
现在这个事情就需要深思熟虑了,设计到文字,就必然需要考虑字体大小,以及解析字符串的问题。笔者这里没有实现UTF-8字符的打印实现,但是笔者提示你,仍然是画出来字符。让我们看看该咋做。
typedef struct __CCGraphic_TextHandle{
char* sources_borrowed; // 这个就是所持有的字体资源指针
CCGraphic_Point tl_point; // 这个是所占有的左上角的绘制起点
CCGraphic_Point indexed_point; // 这个是现在的绘制指针,表明现在我们绘制到了那个地方
CCGraphic_Size TexthandleSize; // 整个Text所在的BoundingRect大小
Ascii_Font_Size font_size; // 字体多大?
}CCGraphic_AsciiTextItem;
如何获取字体?
关于ASCII字体的获取,笔者放到了附录里,值得一提的是,江科大的OLED_Data.h中对字体数组的初始化时不严谨的,不规范的,正确的初始化方案已经放到了附录,不再赘述。
如何正确的访问字体
C语言中,有一个著名的关键字叫extern,他随了汇编语言的关键字extern,在所属权层面上表达的同static完全相反,即这个资源的定义需要到其他文件中寻找。所以,当我们想要引用字体(这个字体被存放到了其他的C源文件中)的时候,只需要手动的extern一下,而且确保资源被正确的编译进来就OK了。
extern const uint8_t ascii6x8_sources[][6];
如何抽象字体
很简单,虽然说正常而言只需要抽象一个TextFont
结构体即可,但是笔者认为这里更多看重的是方法,而且,没有必要对用户暴露一个Font结构体,选择结构体更加不如暴露的是一个枚举和公开的方法。
#ifndef CCGraphic_TextConfig_H
#define CCGraphic_TextConfig_H
#include "Graphic/config/CCGraphic_config.h"
#include "Graphic/CCGraphic_common.h"
#include "Graphic/widgets/common/CCGraphic_Size/CCGraphic_Size.h"
/*
current version we only support
6x8 and 8x16. to register more, u should
provide the source and implement the functions
*/
typedef enum {
#if ENABLE_ASCII_6x8_SOURCES
ASCII_6x8,
#endif
#if ENABLE_ASCII_8x16_SOURCES
ASCII_8x16,
#endif
NO_ASCII_SIZE
}Ascii_Font_Size;
typedef enum {
Unicode_16x16
}Unicode_Font_Size;
#define UNSUPPORTIVE_FONT_SOURCE ((void*)0)
/**
* @brief Selects the font data array based on the specified font size.
*
* This function receives an `Ascii_Font_Size` value
* and returns a pointer to the corresponding font data array.
* The function helps in selecting
* the appropriate font data for display purposes, allowing for different
* font sizes (e.g., 8x16, 6x8, etc.).
*
* @param s The font size to be selected
* (from the `Ascii_Font_Size` enum).
* @param ch the character wanna display
* @return A pointer to the font data array corresponding to the selected font size.
* If an invalid font size is passed,
* the function returns UNSUPPORTIVE_FONT_SOURCE.
*/
uint8_t* __select_from_ascii_font_size(const Ascii_Font_Size s, const char ch);
CCGraphic_Size __fetch_font_size(const Ascii_Font_Size s);
#endif
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextConfig.h"
extern const uint8_t ascii8x16_sources[][16];
extern const uint8_t ascii6x8_sources[][6];
uint8_t* __select_from_ascii_font_size(
const Ascii_Font_Size s, const char ch)
{
switch(s)
{
#if ENABLE_ASCII_6x8_SOURCES
case ASCII_6x8:
return (uint8_t*)(ascii6x8_sources[ch - ' ']);
#endif
#if ENABLE_ASCII_8x16_SOURCES
case ASCII_8x16:
return (uint8_t*)(ascii8x16_sources[ch - ' ']);
#endif
/*
To programmers, if new ascii like sources is
registered, please implement follows
*/
default:
return UNSUPPORTIVE_FONT_SOURCE;
}
}
CCGraphic_Size __fetch_font_size(const Ascii_Font_Size s)
{
CCGraphic_Size size = {0, 0};
switch(s)
{
#if ENABLE_ASCII_6x8_SOURCES
case ASCII_6x8:
size.height = 8;
size.width = 6;
break;
#endif
#if ENABLE_ASCII_8x16_SOURCES
case ASCII_8x16:
size.height = 16;
size.width = 8;
break;
#endif
default:
break;
}
return size;
}
题外话:使用编译宏控制资源编译:GCC是一个智能的编译器,对于任何没有使用到的资源,概不参与编译,所以,对于使用GCC的编译器,只需要确保自己不额外使用其他资源,就不会将冗余的C符号纳入编译。
但还是那句话,为了确保语义更加清晰,仍然使用控制宏对资源进行编译控制和符号控制,让自己的代码语义更加的明确,是一件事半功倍的举措
如何绘制字符串
绘制字符串是一个复杂的活。但是在那之前,把杂活做了。
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextItem.h"
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextConfig.h"
#include "Graphic/widgets/base/CCGraphic_Image/CCGraphic_Image.h"
#include "Graphic/CCGraphic_device_adapter.h"
#include <string.h>
/**
* 初始化一个ASCII文本项。
* @param item 指向CCGraphic_AsciiTextItem的指针。
* @param tl_point 文本项的左上角起始坐标。
* @param textHandleSize 文本项的尺寸信息(宽度和高度)。
* @param text_size 字体大小枚举类型。
*/
void CCGraphicWidget_init_AsciiTextItem(
CCGraphic_AsciiTextItem* item,
CCGraphic_Point tl_point,
CCGraphic_Size textHandleSize,
Ascii_Font_Size text_size
)
{
item->font_size = text_size;
item->sources_borrowed = ""; // 初始化为空字符串,表示未设置内容。
item->tl_point = tl_point;
item->indexed_point = tl_point;
item->TexthandleSize = textHandleSize;
}
/**
* 设置ASCII文本项的内容。
* @param item 指向CCGraphic_AsciiTextItem的指针。
* @param text 待设置的文本内容字符串。
*/
void CCGraphicWidget_AsciiTextItem_setAsciiText(
CCGraphic_AsciiTextItem* item,
char* text
)
{
item->sources_borrowed = text;
}
/**
* 设置ASCII文本项的索引点。
* @param item 指向CCGraphic_AsciiTextItem的指针。
* @param p 索引点的指针。
*/
void CCGraphicWidget_AsciiTextItem_setIndexedPoint(
CCGraphic_AsciiTextItem* item,
CCGraphic_Point* p
)
{
item->indexed_point = *p;
}
/**
* 重新定位ASCII文本项。
* @param item 指向CCGraphic_AsciiTextItem的指针。
* @param tl_point 新的左上角起始坐标。
* @param textHandleSize 新的尺寸信息(宽度和高度)。
*/
void CCGraphicWidget_AsciiTextItem_relocate(
CCGraphic_AsciiTextItem* item,
CCGraphic_Point tl_point,
CCGraphic_Size textHandleSize
)
{
// 这个函数的一个重要的目的就是重定位文本框,为之后的文本显示做铺垫。
item->tl_point = tl_point;
item->TexthandleSize = textHandleSize;
}
绘制一个字符串本身就是绘制一串字符,掌握整个原理,事情就会变得非常简单,我们线讨论如何绘制字符本身
/**
* 绘制ASCII字符到设备。
* @param device_handle 设备句柄。
* @param borrowing_image 临时用于绘制的图像对象。
* @param ch 要绘制的字符。
* @param size 字体大小枚举类型。
*/
static void __pvt_draw_char_each(
CCDeviceHandler* device_handle,
CCGraphic_Image* borrowing_image,
const char ch, Ascii_Font_Size size
)
{
borrowing_image->image_size = __fetch_font_size(size);
uint8_t* ascii = __select_from_ascii_font_size(size, ch);
borrowing_image->sources_register = ascii;
CCGraphicWidget_draw_image(device_handle, borrowing_image);
#if CCGraphic_TextDebug
device_handle->operations.update_device_function(device_handle);
#endif
}
我们将一个字符的字体绘制文件放置到Image中,所以我强调:字符是画出来的。
设计缺陷:注意到,我这里并没有设置绘制的位置,这是因为这件事情在上层做好了,所以我也在参变量中警示自己:整个变量是部分初始化的。
绘制方案
我们绘制的时候,更多会去在乎:是在之前的文本基础上继续绘制呢?还是换一行继续绘制,还是直接清空文本重新绘制?为了防止反复的刷新,笔者设计了三个函数完成整个工作。
首先,设置游标点:
CCGraphic_Point indexed_point; // 这个是现在的绘制指针,表明现在我们绘制到了那个地方
整个在Text的结构体中,不由用户直接设置。
下面,就是依赖设置:
/**
* 判断当前字符是否需要换行。
* @param device_handle 设备句柄。
* @param brpoint 右下角边界点。
* @param cur_draw_p 当前绘制点的指针。
* @param s 字体大小枚举类型。
* @return 如果需要换行,返回非零值;否则返回零。
*/
static uint8_t inline __pvt_should_be_next_line(
CCDeviceHandler* device_handle,
CCGraphic_Point* brpoint,
CCGraphic_Point* cur_draw_p, Ascii_Font_Size s
)
{
return cur_draw_p->x +
(int16_t)(1.5 * __fetch_font_size(s).width) >= brpoint->x;
}
/**
* 计算有效的右下角点。
* @param device_handle 设备句柄。
* @param size 文本项的尺寸信息。
* @param tl 文本项的左上角起始点。
* @return 计算后的右下角点。
*/
static CCGraphic_Point inline __pvt_fetch_valid_final_point(
CCDeviceHandler* device_handle,
CCGraphic_Size* size, CCGraphic_Point* tl
)
{
CCGraphic_Point br;
int16_t device_width = 0;
device_handle->operations.property_function(
device_handle, &device_width, CommonProperty_WIDTH
);
int16_t device_height = 0;
device_handle->operations.property_function(
device_handle, &device_height, CommonProperty_HEIGHT
);
// 上面我们获取了设备的宽高,现在我们开获取最大的合法右下角的点
br.x = tl->x + size->width;
br.y = tl->y + size->height;
if(device_width < br.x) { br.x = device_width; }
if(device_height < br.y) { br.y = device_height; }
return br;
}
文本绘制
绘制文本的本质是绘图。这一点务必注意。下面的整个函数实现了自动的文本换行!
/**
* 绘制ASCII文本项。
* @param device_handle 设备句柄,用于控制绘制设备。
* @param item 要绘制的ASCII文本项,包含文本内容、位置及尺寸信息。
*/
void CCGraphicWidget_drawAsciiTextItem(
CCDeviceHandler* device_handle,
CCGraphic_AsciiTextItem* item)
{
// 如果文本内容为空,直接返回,不进行绘制。
if(strcmp(item->sources_borrowed, "") == 0) {
return;
}
// 定义用于绘制的图像结构体。
CCGraphic_Image handle_draw_image;
// 初始化绘制的起始点为当前索引位置。
CCGraphic_Point draw_tl_point = item->indexed_point;
// 获取当前文本字体的尺寸(宽度和高度)。
const Ascii_Font_Size font_size = item->font_size;
const CCGraphic_Size size = __fetch_font_size(font_size);
const SizeBaseType font_width = size.width;
const SizeBaseType font_height = size.height;
// 计算文本绘制区域的有效右下角点(即绘制边界)。
CCGraphic_Point br = __pvt_fetch_valid_final_point(
device_handle, &(item->TexthandleSize), &(item->tl_point)
);
// 定义x方向和y方向的字符偏移量,用于逐字符定位绘制。
uint8_t offseterx = 0;
uint8_t offsetery = 0;
// 遍历文本中的每个字符并绘制。
for(uint8_t i = 0; item->sources_borrowed[i] != '\0'; i++) {
// 计算当前字符的绘制位置。
draw_tl_point.x = item->indexed_point.x + offseterx * font_width;
draw_tl_point.y = item->indexed_point.y + offsetery * font_height;
// 设置图像绘制的左上角点。
handle_draw_image.point = draw_tl_point;
// 绘制当前字符到目标设备上。
__pvt_draw_char_each(
device_handle,
&handle_draw_image,
item->sources_borrowed[i],
item->font_size
);
// 判断是否需要换行绘制。
if(__pvt_should_be_next_line(device_handle, &br, &draw_tl_point, font_size)) {
// 如果需要换行,将x偏移量归零,并增加y方向的行数。
offseterx = 0;
offsetery++;
// 重置x方向的起点位置为文本的左上角点。
item->indexed_point.x = item->tl_point.x;
} else {
// 否则继续绘制当前行的下一个字符。
offseterx++;
}
}
// 更新文本项的索引点位置为最后一个字符的右侧位置。
item->indexed_point = draw_tl_point;
item->indexed_point.x += font_width;
}
更加方便的绘制
当然,还可以为了之后的组件方便生成一个返回绘制点的方便函数:
/**
* 绘制ASCII文本项,并返回绘制后的点。
* @param device_handle 设备句柄,用于控制绘制设备。
* @param item 要绘制的ASCII文本项,包含文本内容、位置及尺寸信息。
* @param method 文本追加方式,指示绘制后是否换行或连续追加。
* @return 绘制后的坐标点,表示下一个绘制位置。
*/
CCGraphic_Point CCGraphicWidget_drawAsciiTextItem_with_finPoint(
CCDeviceHandler* device_handle,
CCGraphic_AsciiTextItem* item,
AppendMethod method
)
{
// 如果文本内容为空,直接返回文本的初始左上角点。
if(strcmp(item->sources_borrowed, "") == 0) {
return item->tl_point;
}
// 定义绘制图像和绘制位置。
CCGraphic_Image handle_draw_image;
CCGraphic_Point draw_tl_point = item->indexed_point;
// 获取字体尺寸。
const Ascii_Font_Size font_size = item->font_size;
const CCGraphic_Size size = __fetch_font_size(font_size);
const SizeBaseType font_width = size.width;
const SizeBaseType font_height = size.height;
// 获取有效绘制区域的右下角点。
CCGraphic_Point br = __pvt_fetch_valid_final_point(
device_handle, &(item->TexthandleSize), &(item->tl_point)
);
// x方向和y方向的偏移量,用于字符定位。
uint8_t offseterx = 0;
uint8_t offsetery = 0;
// 遍历文本中的每个字符。
for(uint8_t i = 0; item->sources_borrowed[i] != '\0'; i++) {
// 计算当前字符的绘制位置。
draw_tl_point.x = item->indexed_point.x + offseterx * font_width;
draw_tl_point.y = item->indexed_point.y + offsetery * font_height;
// 设置图像的绘制点。
handle_draw_image.point = draw_tl_point;
// 绘制当前字符。
__pvt_draw_char_each(
device_handle,
&handle_draw_image,
item->sources_borrowed[i],
item->font_size
);
// 判断是否需要换行绘制。
if(__pvt_should_be_next_line(device_handle, &br, &draw_tl_point, font_size)) {
offseterx = 0; // x方向偏移归零
offsetery++; // y方向增加一行
item->indexed_point.x = item->tl_point.x; // 重置x起点
} else {
offseterx++; // 继续绘制当前行的下一个字符
}
}
// 更新文本项的索引点为最后一个字符位置。
item->indexed_point = draw_tl_point;
item->indexed_point.x += font_width;
// 根据文本追加方式调整返回的最终坐标点。
switch(method) {
case CCGraphic_AsciiTextItem_AppendNextLine:
// 追加到下一行开始位置。
draw_tl_point.x = item->tl_point.x;
draw_tl_point.y += font_height;
break;
case CCGraphic_AsciiTextItem_AppendContinously:
// 继续追加到同一行的下一个位置。
draw_tl_point.x += font_width;
break;
default:
break;
}
// 返回绘制完成后的坐标点。
return draw_tl_point;
}
/**
* 获取当前文本项的附加点(追加位置)。
* @param item ASCII文本项。
* @return 当前索引位置坐标点。
*/
CCGraphic_Point CCGraphicWidget_AsciiTextItem_on_append_point(CCGraphic_AsciiTextItem* item)
{
return item->indexed_point;
}
/**
* 获取文本项换行后的新行起点。
* @param item ASCII文本项。
* @return 新行的起始坐标点。
*/
CCGraphic_Point CCGraphicWidget_AsciiTextItem_on_newLine_point(CCGraphic_AsciiTextItem* item)
{
CCGraphic_Point draw_tl_point;
draw_tl_point.x = item->tl_point.x;
const CCGraphic_Size size = __fetch_font_size(item->font_size);
draw_tl_point.y = item->indexed_point.y + size.height;
return draw_tl_point;
}
为什么要给函数标记为inline
对于现代的编译器,inline只是起到了一种劝说的作用,他将调用转换为直接插入函数的汇编代码,节约了流水线刷新和代码跳转,这样来看,是一个不错的关键字,但是,一个过于庞大的函数标记为inline是一个无效的举措(几乎没有节约开销,所以编译器有的时候不会理睬,对于GCC,尝试使用force_inline标记符强制内联),现代的inline更加像是一种允许重复定义的关键字(因为他直接将汇编代码插入到了调用者上,符号直接被替换消失了)
字体附录
或者,你可以访问Github地址:MCU_Libs/OLED/library/Graphic/resources/default at main · Charliechen114514/MCU_Libs (github.com)
ascii 6x8字体
#include "Graphic/CCGraphic_common.h"
#include "Graphic/config/CCGraphic_config.h"
// This is an array of font data for a
// 6x8 OLED display using 6x8 pixel font representation.
// Each character in this font set is defined by an
// 6x8 pixel matrix (8 pixels wide, 16 pixels high).
/*
sources should be externed copy this for
the usage in application level
*/
// ---------------------------------------------
// extern const uint8_t ascii6x8_sources[][6];
// ---------------------------------------------
#if ENABLE_ASCII_6x8_SOURCES
const uint8_t ascii6x8_sources[][6] =
{
{0x00,0x00,0x00,0x00,0x00,0x00}, // 0
{0x00,0x00,0x00,0x2F,0x00,0x00}, // ! 1
{0x00,0x00,0x07,0x00,0x07,0x00}, // " 2
{0x00,0x14,0x7F,0x14,0x7F,0x14}, // # 3
{0x00,0x24,0x2A,0x7F,0x2A,0x12}, // $ 4
{0x00,0x23,0x13,0x08,0x64,0x62}, // % 5
{0x00,0x36,0x49,0x55,0x22,0x50}, // & 6
{0x00,0x00,0x00,0x07,0x00,0x00}, // ' 7
{0x00,0x00,0x1C,0x22,0x41,0x00}, // ( 8
{0x00,0x00,0x41,0x22,0x1C,0x00}, // ) 9
{0x00,0x14,0x08,0x3E,0x08,0x14}, // * 10
{0x00,0x08,0x08,0x3E,0x08,0x08}, // + 11
{0x00,0x00,0x00,0xA0,0x60,0x00}, // , 12
{0x00,0x08,0x08,0x08,0x08,0x08}, // - 13
{0x00,0x00,0x60,0x60,0x00,0x00}, // . 14
{0x00,0x20,0x10,0x08,0x04,0x02}, // / 15
{0x00,0x3E,0x51,0x49,0x45,0x3E}, // 0 16
{0x00,0x00,0x42,0x7F,0x40,0x00}, // 1 17
{0x00,0x42,0x61,0x51,0x49,0x46}, // 2 18
{0x00,0x21,0x41,0x45,0x4B,0x31}, // 3 19
{0x00,0x18,0x14,0x12,0x7F,0x10}, // 4 20
{0x00,0x27,0x45,0x45,0x45,0x39}, // 5 21
{0x00,0x3C,0x4A,0x49,0x49,0x30}, // 6 22
{0x00,0x01,0x71,0x09,0x05,0x03}, // 7 23
{0x00,0x36,0x49,0x49,0x49,0x36}, // 8 24
{0x00,0x06,0x49,0x49,0x29,0x1E}, // 9 25
{0x00,0x00,0x36,0x36,0x00,0x00}, // : 26
{0x00,0x00,0x56,0x36,0x00,0x00}, // ; 27
{0x00,0x08,0x14,0x22,0x41,0x00}, // < 28
{0x00,0x14,0x14,0x14,0x14,0x14}, // = 29
{0x00,0x00,0x41,0x22,0x14,0x08}, // > 30
{0x00,0x02,0x01,0x51,0x09,0x06}, // ? 31
{0x00,0x3E,0x49,0x55,0x59,0x2E}, // @ 32
{0x00,0x7C,0x12,0x11,0x12,0x7C}, // A 33
{0x00,0x7F,0x49,0x49,0x49,0x36}, // B 34
{0x00,0x3E,0x41,0x41,0x41,0x22}, // C 35
{0x00,0x7F,0x41,0x41,0x22,0x1C}, // D 36
{0x00,0x7F,0x49,0x49,0x49,0x41}, // E 37
{0x00,0x7F,0x09,0x09,0x09,0x01}, // F 38
{0x00,0x3E,0x41,0x49,0x49,0x7A}, // G 39
{0x00,0x7F,0x08,0x08,0x08,0x7F}, // H 40
{0x00,0x00,0x41,0x7F,0x41,0x00}, // I 41
{0x00,0x20,0x40,0x41,0x3F,0x01}, // J 42
{0x00,0x7F,0x08,0x14,0x22,0x41}, // K 43
{0x00,0x7F,0x40,0x40,0x40,0x40}, // L 44
{0x00,0x7F,0x02,0x0C,0x02,0x7F}, // M 45
{0x00,0x7F,0x04,0x08,0x10,0x7F}, // N 46
{0x00,0x3E,0x41,0x41,0x41,0x3E}, // O 47
{0x00,0x7F,0x09,0x09,0x09,0x06}, // P 48
{0x00,0x3E,0x41,0x51,0x21,0x5E}, // Q 49
{0x00,0x7F,0x09,0x19,0x29,0x46}, // R 50
{0x00,0x46,0x49,0x49,0x49,0x31}, // S 51
{0x00,0x01,0x01,0x7F,0x01,0x01}, // T 52
{0x00,0x3F,0x40,0x40,0x40,0x3F}, // U 53
{0x00,0x1F,0x20,0x40,0x20,0x1F}, // V 54
{0x00,0x3F,0x40,0x38,0x40,0x3F}, // W 55
{0x00,0x63,0x14,0x08,0x14,0x63}, // X 56
{0x00,0x07,0x08,0x70,0x08,0x07}, // Y 57
{0x00,0x61,0x51,0x49,0x45,0x43}, // Z 58
{0x00,0x00,0x7F,0x41,0x41,0x00}, // [ 59
{0x00,0x02,0x04,0x08,0x10,0x20}, // \ 60
{0x00,0x00,0x41,0x41,0x7F,0x00}, // ] 61
{0x00,0x04,0x02,0x01,0x02,0x04}, // ^ 62
{0x00,0x40,0x40,0x40,0x40,0x40}, // _ 63
{0x00,0x00,0x01,0x02,0x04,0x00}, // ` 64
{0x00,0x20,0x54,0x54,0x54,0x78}, // a 65
{0x00,0x7F,0x48,0x44,0x44,0x38}, // b 66
{0x00,0x38,0x44,0x44,0x44,0x20}, // c 67
{0x00,0x38,0x44,0x44,0x48,0x7F}, // d 68
{0x00,0x38,0x54,0x54,0x54,0x18}, // e 69
{0x00,0x08,0x7E,0x09,0x01,0x02}, // f 70
{0x00,0x18,0xA4,0xA4,0xA4,0x7C}, // g 71
{0x00,0x7F,0x08,0x04,0x04,0x78}, // h 72
{0x00,0x00,0x44,0x7D,0x40,0x00}, // i 73
{0x00,0x40,0x80,0x84,0x7D,0x00}, // j 74
{0x00,0x7F,0x10,0x28,0x44,0x00}, // k 75
{0x00,0x00,0x41,0x7F,0x40,0x00}, // l 76
{0x00,0x7C,0x04,0x18,0x04,0x78}, // m 77
{0x00,0x7C,0x08,0x04,0x04,0x78}, // n 78
{0x00,0x38,0x44,0x44,0x44,0x38}, // o 79
{0x00,0xFC,0x24,0x24,0x24,0x18}, // p 80
{0x00,0x18,0x24,0x24,0x18,0xFC}, // q 81
{0x00,0x7C,0x08,0x04,0x04,0x08}, // r 82
{0x00,0x48,0x54,0x54,0x54,0x20}, // s 83
{0x00,0x04,0x3F,0x44,0x40,0x20}, // t 84
{0x00,0x3C,0x40,0x40,0x20,0x7C}, // u 85
{0x00,0x1C,0x20,0x40,0x20,0x1C}, // v 86
{0x00,0x3C,0x40,0x30,0x40,0x3C}, // w 87
{0x00,0x44,0x28,0x10,0x28,0x44}, // x 88
{0x00,0x1C,0xA0,0xA0,0xA0,0x7C}, // y 89
{0x00,0x44,0x64,0x54,0x4C,0x44}, // z 90
{0x00,0x00,0x08,0x7F,0x41,0x00}, // { 91
{0x00,0x00,0x00,0x7F,0x00,0x00}, // | 92
{0x00,0x00,0x41,0x7F,0x08,0x00}, // } 93
{0x00,0x08,0x04,0x08,0x10,0x08}, // ~ 94
};
#endif
ascii 8 x 16字体
#include "Graphic/CCGraphic_common.h"
#include "Graphic/config/CCGraphic_config.h"
// This is an array of font data for a
// 8x16 OLED display using 8x16 pixel font representation.
// Each character in this font set is defined by an
// 8x16 pixel matrix (8 pixels wide, 16 pixels high).
/*
sources should be externed copy this for
the usage in application level
*/
// ---------------------------------------------
// extern const uint8_t ascii8x16_sources[][16];
// ---------------------------------------------
#if ENABLE_ASCII_8x16_SOURCES
const uint8_t ascii8x16_sources[][16] =
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// 0
{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},// ! 1
{0x00,0x16,0x0E,0x00,0x16,0x0E,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// " 2
{0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00},// # 3
{0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00},// $ 4
{0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00},// % 5
{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10},// & 6
{0x00,0x00,0x00,0x16,0x0E,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ' 7
{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},// ( 8
{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},// ) 9
{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},// * 10
{0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00},// + 11
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xB0,0x70,0x00,0x00,0x00,0x00,0x00},// , 12
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},// - 13
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},// . 14
{0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00},// / 15
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},// 0 16
{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// 1 17
{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},// 2 18
{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},// 3 19
{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},// 4 20
{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},// 5 21
{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},// 6 22
{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},// 7 23
{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},// 8 24
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},// 9 25
{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},// : 26
{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00},// ; 27
{0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},// < 28
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00},// = 29
{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},// > 30
{0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00},// ? 31
{0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00},// @ 32
{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},// A 33
{0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},// B 34
{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},// C 35
{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},// D 36
{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},// E 37
{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},// F 38
{0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},// G 39
{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},// H 40
{0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// I 41
{0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},// J 42
{0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},// K 43
{0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},// L 44
{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},// M 45
{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},// N 46
{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},// O 47
{0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},// P 48
{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},// Q 49
{0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},// R 50
{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},// S 51
{0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},// T 52
{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},// U 53
{0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},// V 54
{0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},// W 55
{0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},// X 56
{0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},// Y 57
{0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},// Z 58
{0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},// [ 59
{0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},// \ 60
{0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},// ] 61
{0x00,0x20,0x10,0x08,0x04,0x08,0x10,0x20,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ^ 62
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},// _ 63
{0x00,0x02,0x04,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ` 64
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20},// a 65
{0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},// b 66
{0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},// c 67
{0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},// d 68
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},// e 69
{0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// f 70
{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},// g 71
{0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},// h 72
{0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// i 73
{0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},// j 74
{0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},// k 75
{0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// l 76
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},// m 77
{0x00,0x80,0x80,0x00,0x80,0x80,0x00,0x00,
0x00,0x20,0x3F,0x21,0x00,0x20,0x3F,0x20},// n 78
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},// o 79
{0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},// p 80
{0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},// q 81
{0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},// r 82
{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},// s 83
{0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},// t 84
{0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},// u 85
{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},// v 86
{0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},// w 87
{0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},// x 88
{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},// y 89
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},// z 90
{0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40},// { 91
{0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},// | 92
{0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00},// } 93
{0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00},// ~ 94
};
#endif
目录导览
总览
协议层封装
OLED设备封装
绘图设备抽象
基础图形库封装
基础组件实现
动态菜单组件实现