前言
这算是基础任务的最终实现环节了吧(不考虑传文本置板卡,板卡识别文本的前提下)。文本可以显示了,剩下的就是文本翻页逻辑的添加。
代码实现
功能定义
结合目前资源和基础任务要求,将按键定义如下:
功能实
现按键功能
基于之前已经实现的按键检测功能,此处仅仅需要实现按键对应功能入口的设置,即按KeyA,调用向上翻页入口,按KeyB时,调用向下翻页入口,按KeyC时,调用文本切换入口。具体实现如下:
main.c
int main(void) { char key = 0x00, key_new; unsigned char txtIndex = 0; system_init(); LED_init(); key_init(); epd_init(); DEV_Delay_ms(2000); // main_EPD_test(); while (true) { key_new = get_key(); if (key == key_new) { continue; } key = key_new; if (key) { LED_ON(); } else { LED_OFF(); } switch (key) { case KEYA_MASK: epd_show(txtIndex, 2); break; case KEYB_MASK: epd_show(txtIndex, 1); break; case KEYC_MASK: txtIndex = (txtIndex ? 0 : 1); epd_show(txtIndex, 0); break; default: break; } } return 0; }
翻页和文本切换实现
文本翻页,说简单也简单,就是在上一版本文本显示的基础上,计算出新文本的偏移地址并显示即可。但实现并没有那么容易。其中遇到了不少问题,如:
1. 不确定是否可以动态内存申请,只能做实验验证后看是否可导入。
做实验验证后,发现有戏,直接写双向链表实现。
2. 有点奇葩的是,keil工程中,char类型的变量,居然范围是0~255,不是-128~127,导致一次性写好的代码逻辑和预想的不一致
编译环境问题,也没别的招,只能把char型数据按照unsigned char型数据计算了
3. GB2312字库和ASCII字库的高度不一致,导致计算显示数量时误差大
直接使用简化后的逻辑,GB2312字库,补8行空白,确保缩进一致。
4. 显示屏刷新速度过慢(显示内容刷新了,但后台还在执行收尾动作,且收尾动作耗时过长),导致不知道实际操作状态
保留前面点灯的按键按下亮灯,松开灭灯逻辑,让人有一定感知容忍度
由于之前过程贴已提供前期的实现部分,因此这里仅提供有修改的部分,以期减少文本量。具体代码如下:
my_epd.c
void draw_fb_GB2132(int x, int y, int bankCode, int posCode) { const unsigned char *pData = NULL; unsigned char idxX, idxY; int lineData; int pos; pos = ((bankCode - 0xA1) * 94 + (posCode - 0xA1)) * (GB2312_FONT_H * GB2312_FONT_W / 8); pData = acHZK16C + pos; for (idxY = 0; idxY < GB2312_FONT_W; idxY++) { lineData = pData[idxY * 2]; lineData = lineData << 8; lineData = lineData | pData[idxY * 2 + 1]; for (idxX = 0; idxX < GB2312_FONT_H; idxX++) { if (lineData & (0x01 << idxX)) { draw_fb_point(x + GB2312_FONT_H - idxX, y + idxY); } else { clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY); } } } for (idxY = GB2312_FONT_W; idxY < ASCII_FONT_W; idxY++) { for (idxX = 0; idxX < GB2312_FONT_H; idxX++) { clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY); } } } int draw_fb(int x, int y, char *data) { int j, k, i = 0, dataLen = My_strlen(data); for (i = 0; i < dataLen;) { if (data[i] > 127) { // if (data[i] < 0) { if ((x + GB2312_FONT_H) > EPD_H) { x = 0; y += ASCII_FONT_W; if ((y + ASCII_FONT_W) > EPD_W) { goto RET; } } draw_fb_GB2132(x, y, data[i], data[i + 1]); x += GB2312_FONT_H; i += 2; } else { if ((x + ASCII_FONT_H) > EPD_H) { x = 0; y += ASCII_FONT_W; if ((y + ASCII_FONT_W) > EPD_W) { goto RET; } } draw_fb_ASCII(x, y, data[i]); x += ASCII_FONT_H; i++; } } // clear lase line screen if (x) { for (j = x; j < EPD_H; j++) { for (k = y; k < (y + ASCII_FONT_W); k++) { clear_fb_point(j, k); } } y += ASCII_FONT_W; } RET: // clear other line for (j = 0; j < EPD_H; j++) { for (k = y; k < EPD_W; k++) { clear_fb_point(j, k); } } return i; } int get_next_text(int x, int y, char *data) { int i = 0, dataLen = My_strlen(data); for (i = 0; i < dataLen;) { if (data[i] > 127) { if ((x + GB2312_FONT_H) > EPD_H) { x = 0; y += ASCII_FONT_W; if ((y + ASCII_FONT_W) > EPD_W) { goto RET; } } x += GB2312_FONT_H; i += 2; } else { if ((x + ASCII_FONT_H) > EPD_H) { x = 0; y += ASCII_FONT_W; if ((y + ASCII_FONT_W) > EPD_W) { goto RET; } } x += ASCII_FONT_H; i++; } } RET: return i; } struct epd_pos { int pos; struct epd_pos *next; struct epd_pos *prev; }; struct epd_pos *posTbl = NULL, *currentPos = NULL; void posTbl_free(struct epd_pos *tbl) { struct epd_pos *nextTbl; if (tbl == NULL) { return; } while (tbl->next) { nextTbl = tbl->next; free(tbl); tbl = nextTbl; } free(tbl); return; } void posTbl_link(struct epd_pos *tbl, struct epd_pos *new_node) { while (tbl->next) { tbl = tbl->next; } tbl->next = new_node; new_node->prev = tbl; return; } int epd_show(unsigned char txtIndex, char direction) { char *pText; static unsigned char lastIndex = 0xFF; static unsigned int showCount = 0; static int pos = 0; int textLen; struct epd_pos *new_node, *oldPos = currentPos; if (txtIndex == 0) { pText = rj_dzs; // doc1 } else { pText = dx_dzs; // doc2 } textLen = My_strlen(pText); if (lastIndex != txtIndex) { posTbl_free(posTbl); posTbl = (struct epd_pos *)malloc(sizeof(struct epd_pos)); posTbl->prev = NULL; posTbl->next = NULL; posTbl->pos = 0; currentPos = posTbl; } if (direction == 1) { if (currentPos->next) { // Saved pos, just goto next pos currentPos = currentPos->next; } else if (currentPos->pos < (textLen - 1)) { // Find for new pos pos = currentPos->pos + get_next_text(0, 0, pText + currentPos->pos); if (pos <= (textLen - 1)) { new_node = (struct epd_pos *)malloc(sizeof(struct epd_pos)); new_node->pos = pos; new_node->next = NULL; posTbl_link(currentPos, new_node); currentPos = new_node; } } } else if (direction == 2) { // just jump to prev pos if exist if (currentPos->prev) { currentPos = currentPos->prev; } } // update display if ((oldPos != currentPos) || (lastIndex != txtIndex)) { draw_fb(0, 0, pText + currentPos->pos); showCount++; if (showCount > 40) { showCount = 0; updata_to_epd(DISPLAY_ALL); } else { updata_to_epd(DISPLAY_PART); } } // update flag lastIndex = txtIndex; return pos; }my_epd.h
int epd_show(unsigned char txtIndex, char direction);
最终显示效果
其实这位置使用动图或者视频看效果更好,但奈何无环境录制视频,因此直接贴图片。
最终代码
https://www.bilibili.com/video/BV1fHaXenEcz/