10 Commits
1.3.0 ... 1.3.5

Author SHA1 Message Date
fsender
7bb2ba77f0 1.3.5: add send-text example&fix bugs 2024-03-04 13:53:35 +08:00
fsender
8e825c862a 1.3.5: add more examples&fix bugs 2024-03-04 13:48:01 +08:00
fsender
d88f1a3c5c feat: add 5.83 inch support 2023-11-24 22:38:28 +08:00
fsender
771ac6db80 feat: initSD option. init without SD is fine 2023-11-12 07:10:23 +08:00
fsender
c4e848730c perf: better button preformance 2023-11-12 06:19:31 +08:00
fsender
78438e36a7 fix: pin preset order 2023-11-12 05:01:10 +08:00
fsender
3ae6156886 1.3.3: fix 2.66BWR refresh & pre-add new driver 2023-11-12 04:08:29 +08:00
fsender
2aca106448 feat: new button gesture 2023-11-08 16:44:42 +08:00
fsender
d24639a962 fix memory bug 2023-11-07 21:26:51 +08:00
fsender
85a785eabd update to 1.3.1 ver 2023-11-07 16:41:37 +08:00
66 changed files with 37226 additions and 329 deletions

View File

@@ -1,3 +1,71 @@
## Release 1.3.5 - 2024/3/4
1. 2024/2/25更新: 修复了按键bug, 双按键有时候识别不灵, 三按键不支持移植到拨轮硬件操作, 现在全修好了
2. 2024/2/26更新: 增加了新环境 : 针对无串口芯片的 ESP32C3 新增的选项
3. 2024/2/28更新: 增加了新的示例: WiFi传文本
4. 优化ESP32C3的配置体验
## Release 1.3.4 - 2023/11/24
1. 添加5.83寸屏幕驱动. 默认开启, 嫌flash占用大的可以手动关
2. 修复别的一些bug
## Release 1.3.3 - 2023/11/12
1. 添加了2.66寸三色和黑白的不同驱动程序.
2. guy_epaper 文件夹内添加了一些文件. 为添加新版本驱动做准备.
3. 现在SD卡功能是可移除的. 可以自定义文件系统来初始化并使用. 但是对应的, SD卡引脚设定保留.
4. 优化按键手势的按动手感.
5. 重构了"固定引脚"(DYNAMIC_PIN_SETTINGS被注释)的宏定义逻辑代码. 现在如果在运行过"固定引脚"的程序之后, 再运行常规固件不需要二次配置.
6. 增大了S3的按钮任务栈空间, 避免因为stack overflow导致的任务终止.
7. 修复若干其他方面的bug, 比如配置引脚时, 屏幕没转向.
## Release 1.3.2 - 2023/11/8
1. 按键驱动 (guy_button) 获得新操作更新: (New button gesture)
- 单按键操作更新: 现在双击效果为选择/确定, 三击效果为返回, 长按效果为向上翻页;
- 单按键新增点按后长按操作;
- 双按键新增按住按键1点按按键2操作;
- 三按键新增按住按键1点按按键3操作.
2. 新增获取系统内存的API函数 getFreeMem().
3. 修复若干驱动层bug.
## Release 1.3.1 - 2023/11/7
1. 增加了分步绘制的支持. 可以使用 READGUY_FAST_START 等绘制选项来控制绘制过程:
- READGUY_SLOW 慢刷, 完整的进行一次慢刷, 等于连续执行慢刷开始和慢刷结束.
- READGUY_FAST 快刷, 完整的进行一次快刷, 需要等待刷完才能继续执行代码.
- READGUY_SLOW_START 慢刷开始, 此过程不会进行等待, 发送完要刷新的缓存之后立刻返回
- READGUY_FAST_START 快刷开始.
- READGUY_SLOW_END 慢刷结束, 调用慢刷开始之后才能执行. 会等待到屏幕刷完再执行后续操作.
- READGUY_FAST_END 快刷结束, 如果两次调用间隔时间屏幕已经刷完, 那么该函数会完成刷屏后续操作之后立刻返回.
2. 修复了首次配置驱动时, 墨水屏显示页面错位的bug (现在对于新设备, 配置起来会像以前一样丝滑)
3. 修复若干其他bug
## Release 1.3.0 - 2023/11/6
1. 增加了真.保姆级的教程 (详细到注释比代码多很多倍)

View File

@@ -4,7 +4,11 @@
<img src="extra/artset/readguy_theme3.png" width="30%" height="auto">
**版本1.3.0正式发布欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
**版本1.3.5正式发布欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
**即将发布7个全新的屏幕驱动: 欢迎支持! (详见后面的驱动表格)**
**发布好的全新驱动程序版本号将会是2.0.0!**
欢迎克隆, 项目交流QQ群: 926824162 (萌新可以进来问问题的哟), 项目的 Bilibili 主页: [BV1f94y187wz](https://www.bilibili.com/video/BV1f94y187wz/) 记得三连+关注我这个宝藏up主哦~
@@ -53,14 +57,23 @@ Supported displays: 1.54-inch, 2.13-inch, 2.66-inch, 2.9-inch, 4.2-inch.
| 1 |1.54寸标准 |原创自研 |200*200| 16阶 | 不支持 | 1.3s | 0.35s |
| 2 |1.54寸Lilygo |原创自研 |200*200| 16阶 | 支持 | 2.3s | 0.6s |
| 3 |2.13寸汉朔价签 |原创自研 |122*250| 16阶 | 不支持 | 1.6s | 0.31s |
| 4 |2.13寸三色 |原创自研 |104*212| 16阶 | 支持 | 2s | 0.2s |
| 5 |2.66寸Vusion价签 |和4号相同|152*296| 16阶 | 支持 | 2s | 0.2s |
| 4 |2.13寸低分辨率版 |原创自研 |104*212| 16阶 | 支持 | 1.12s | 0.17s |
| 5 |2.66寸Vusion价签 |和4号相同|152*296| 16阶 | 支持 | 1.12s | 0.17s |
| 6 |2.7寸佳显触摸屏 |和2号相同|176*264| 16阶 | 支持 | 2.3s | 0.6s |
| 7 |2.9寸A01 |和1号相同|128*296| 16阶 | 不支持 | 1.8s | 0.55s |
| 8 |2.9寸T94背光 |和2号相同|128*296| 16阶 | 支持 | 2.3s | 0.6s |
| 9 |3.7寸高dpi墨水屏 |原创自研 |280*480| 16阶 | 不支持 | 1.3s | 0.5s |
|10 |4.2寸HINK黑白价签 |原创自研 |400*300| 16阶 | 支持 | 1.72s | 0.38s |
|11 |4.2寸WF丝印 |原创自研 |400*300| 16阶 | 不支持 | 3.6s | 0.8s |
|12 |2.13寸三色 |和4号相同|122*250| 16阶 | 支持 | 未知 | 未知 |
|13 |2.66寸三色价签 |和4号相同|152*296| 16阶 | 支持 | 2.48s | 0.65s |
|14 |M5 Core.Ink 1.54寸 |即将支持|200*200|/|/|/|/|
|15 |3.7寸低DPI版墨水屏 |即将支持|416*240|/|/|/|/|
|16 |4.26寸高分辨率墨水屏|即将支持|800*480|/|/|/|/|
|17 |5.83寸墨水屏幕 |原创自研|600*448| 16阶 | 支持 | 1.7s | 0.8s |
|18 |5.83寸GDEQ0583T31 |即将支持|640*480|/|/|/|/|
|19 |7.5寸三色墨水屏幕 |即将支持|800*480|/|/|/|/|
|20 |10.2寸GDEQ102T90 |即将支持|960*640|/|/|/|/|
可以自己在代码中加入你想要的屏幕型号
@@ -234,5 +247,5 @@ firmware.bin 0x10000
Copyright © 2022-2023 FriendshipEnder. All Rights reserved.
版权声明:需要经过作者@friendshipender的许可才能商用
版权声明:需要经过作者@friendshipender的许可才能商用 可以联系邮箱playyinzhe@qq.com询问商用事宜

View File

@@ -157,8 +157,8 @@ void setup(){ //Arduino的setup函数. 这个函数在上电之后仅执行一
//guy.setCursor(10,10); //设置显示的坐标
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
guy.display(true); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上. 可简写为 guy.display(), 效果一样.
//guy.display(false); // 慢速刷新.
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上. 可简写为 guy.display(), 效果一样.
//guy.display(READGUY_SLOW); // 慢速刷新.
//想知道更多内容, 欢迎移步到其他示例.
}

View File

@@ -11,6 +11,25 @@
* @brief ReadGuy功能演示.
* 将根目录下的data文件夹 上传到LittleFS之后运行效果更佳
* 或者可以准备一张SD卡,并准备在卡的根目录下放置data文件夹内的文件.
* 就是SD卡内放data文件夹内的所有文件, 不能额外套文件夹.
* 如果你的SD卡插入电脑上显示为可移动磁盘, 那么双击SD卡目录就要看到这个文件夹里的文件
*
* 默认的文件系统为SD卡. 当没有插入SD卡时, 会读取LittleFS文件系统.
* 没有条件准备SD卡的, 可以烧录LittleFS文件系统.
*
* 对于ESP8266 Arduino 用户, 在项目草图文件夹内新建一个data文件夹, 并放入文件 (示例已提供data文件夹)
* 再在 arduinoIDE 的工具选项里选择 ESP8266 LittleFS Data Upload.
* 没有这个选项的需要参考以下文档安装ESP8266 Sketch upload tool
* https://randomnerdtutorials.com/install-esp8266-nodemcu-littlefs-arduino/
*
* 对于ESP32 Arduino 用户, 也要在项目草图文件夹内放一个data文件夹, 并把文件放入其中 (示例已提供data文件夹)
* 再在 arduinoIDE 的工具选项里选择 ESP32 Sketch data upload, 最后选择LittleFS.
* 没有这个选项的需要参考以下文档安装ESP32 LittleFS upload tool
* https://randomnerdtutorials.com/esp32-littlefs-arduino-ide/
*
* 对于PlatformIO 用户, 需要进入platformIO扩展界面, 选择Upload Filesystem Image, 上传项目文件.
* ESP8266和ESP32都要用这种方法.
*
* 用于演示BMP格式图片灰度显示.
*
* @note 食用方法:
@@ -76,14 +95,15 @@ void setup(){
guy.drawString("Hello Readguy!",10,10); //用此函数将字符串显示到屏幕缓存内
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
guy.display(true); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
//guy.display(false); // 慢速刷新.
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
// 但是, 上电初始化之后的首次刷新必为慢速刷新
//guy.display(READGUY_SLOW); // 慢速刷新.
guy.setCursor(10,30); //设置显示的坐标
guy.print("Hello~"); //或者用print函数在屏幕上打印字符串, 数值, 字符等等... 两种函数都行
guy.display(false); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
guy.display(READGUY_SLOW); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
guy.drawString(guy.SDinside()?"SD card OK.":"No SD card!",10,50); //检查readguy是否插入了SD卡
@@ -134,7 +154,7 @@ void setup(){
guy.fillScreen(1);
guy.display(false); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
guy.display(READGUY_SLOW); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
for(int i=1;i<16;i++){ //灰度测试, 循环设置不同灰度
@@ -203,7 +223,7 @@ void setup(){
guy.setFont(&FreeMonoBold9pt7b); //设置文本字体
guy.setTextColor(0); //设置文本颜色
guy.fillScreen(1); //用白色清屏.
guy.display(false); //慢刷. 注意, 进行慢刷操作之后, 所有之前显示的灰度内容均会被重新刷成纯黑色
guy.display(READGUY_SLOW); //慢刷. 注意, 进行慢刷操作之后, 所有之前显示的灰度内容均会被重新刷成纯黑色
//不管是浅灰色还是深灰色, 进行慢刷之后只有黑白色. 原来的非白色像素(浅灰色,深灰色和黑色等) 会全刷成白色.
guy.drawString("Rotation 0",10,12); //默认旋转方向为0. 实际的默认方向取决于屏幕IC. 大多数屏幕IC是竖屏.
@@ -239,13 +259,13 @@ void setup(){
guy.setTextColor(1); //设置文本颜色为白色,因为被反色的屏幕的当前像素颜色以黑色像素为主
guy.drawString("Wake Up! ~\\(^_^)/~",10,50); //退出睡眠状态
guy.display(false); //使用慢刷 来唤醒处于低功耗状态下的屏幕.
guy.display(READGUY_SLOW); //使用慢刷 来唤醒处于低功耗状态下的屏幕.
// ------------------ 6 - 可以利用灰度来达到的一些显示效果 --<<<<<<
guy.fillScreen(1); //清屏
guy.display(FILL_WHITE,false); //慢刷清屏. 左侧的FILL_WHITE表示 不写入屏幕缓存, 直接刷全白
guy.display(FILL_WHITE,READGUY_SLOW); //慢刷清屏. 左侧的FILL_WHITE表示 不写入屏幕缓存, 直接刷全白
//可以改为FILL_BLACK来设置写入缓存全黑.
//以上的方式均不会修改屏幕缓存中的内容. 右侧的false表示全屏慢刷.

View File

@@ -6,8 +6,9 @@
*
* @file ex03_buttons.ino
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @version 1.0
* @date 2023-10-20
* @version 1.1 增加了新的手势功能
*
* @date created: 2023-10-20 last modify: 2024-02-25
* @brief ReadGuy 按键功能演示. ReadGuy自带的按键驱动程序是非常好用的
* @attention
@@ -64,6 +65,11 @@ void loop(){
else if(c==2) guy.println("Left key long pressed!");
else if(c==3) guy.println("Right key clicked!");
break;
case 3:
if(c==1) guy.println("key triple clicked!");
else if(c==2) guy.println("Right clicked at left pressing!");
else if(c==3) guy.println("Centre key double clicked!");
break;
case 4:
if(c==1) guy.println("key long pressed!");
else if(c==2) guy.println("Right key clicked!");

View File

@@ -6,10 +6,13 @@
*
* @file 2_wifi_config.ino
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @version 1.0
* @date 2023-10-14
* @version 1.1
* @date create: 2023-10-14 last modify: 2024-02-26
* @note 本版本主要更新了NTP对时机制, 以及扫描wifi时可以在屏幕上显示到底扫描了多少wifi
* @brief ReadGuy配网服务器 配置并连接附近的WiFi网络演示程序.
编译烧录后, 本程序将使用AP方式配网并在连接到网络时访问NTP服务器来在墨水屏上显示时间.
*** 推荐文章 解决2038千年虫: (本程序未使用该文章内容)
*** https://blog.csdn.net/qdlyd/article/details/131199628
同时开启在STA上的服务器, 供这个WiFi上的用户访问此墨水屏阅读器.
// 注意, 为了避免此项目占用的flash空间过大, 故库内中不再提供配网的相关功能函数.
@@ -40,6 +43,7 @@
#include <Arduino.h> //arduino功能基础库. 在platformIO平台上此语句不可或缺
#include "readguy.h" //包含readguy_driver 基础驱动库
#include <lwip/apps/sntp.h>
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
@@ -48,7 +52,9 @@ typedef ReadguyDriver::serveFunc event_t ; //存储一个WiFi功能事
void f1(server_t sv); //服务器响应回调函数. 当启动AP配网服务器时, 这些函数将会被调用
void f2(server_t sv);
time_t getNTPTime(); //NTP获取时间的函数
/// @brief NTP获取时间的函数, 必须联网才能调用
time_t getNTPTime();
int conf_status = 0; //标记WiFi配网状态: 当此值为1时, 说明配网程序收到了WiFi SSID和密码信息, 尝试连接.
//此变量为2 说明配网成功了. 连接到了WiFi并显示当前时间.
@@ -81,8 +87,8 @@ void setup(){
scanres = WiFi.scanNetworks(); //开始扫描网络
Serial.println("[readguy] WiFi Scan OK."); //关闭服务器, 尝试连接, 连接成功之后将会在屏幕上显示
guy.println("WiFi Scan OK."); //连接失败则会重新进入循环
Serial.printf("[readguy] WiFi Scan %d OK.\n",scanres); //关闭服务器, 尝试连接, 连接成功之后将会在屏幕上显示
guy.printf("WiFi Scan %d OK.\n",scanres); //连接失败则会重新进入循环
guy.display();
IPAddress local_IP(192,168,4,1); //设置本地AP的IP地址, 网关和子网掩码.
@@ -135,9 +141,15 @@ void setup(){
Serial.println("[readguy] Getting NTP time..."); //连接成功之后尝试获取NTP时间
guy.display();
time_t now = getNTPTime(); //下方的函数演示了如何使用NTP来对时
guy.println(ctime(&now));
Serial.println(ctime(&now));
time_t now = getNTPTime(); //下方的函数演示了如何使用NTP来对时. 此函数必须连接上wifi才能调用
now=time(nullptr); //通过Unix API获取时间
struct tm now_tm;
gmtime_r(&now,&now_tm); //转换为GMT时间
guy.println(asctime(&now_tm));
Serial.println(asctime(&now_tm));
localtime_r(&now,&now_tm); //转换为本地时间(包含了时区数据的)
guy.println(asctime(&now_tm));
Serial.println(asctime(&now_tm));
guy.display();
guy.server_setup("现在是联网的STA模式."); //如果没有调用server_end函数 连续调用server_setup将自动结束之前的服务器
@@ -216,7 +228,6 @@ void f2(server_t sv){
PSTR("<html><body><meta charset=\"utf-8\">配置失败,缺少信息</body></html>"));
}
/*----------------- NTP code ------------------*/
WiFiUDP udp;
uint8_t packetBuffer[48];
@@ -271,25 +282,32 @@ time_t get_ntp_time_impl(uint8_t _server)
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * 3600;
return secsSince1900 - 2208988800UL; // + timeZone * 3600; //时区数据 舍弃即可
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
time_t getNTPTime(){
time_t _now = 0;
if(!WiFi.isConnected()) return 0;
udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(localPort);
for(int i=0;i<4;i++){//最多尝试10次对时请求
_now=get_ntp_time_impl(i);
if(_now) break; //成功后立即退出
yield();
Serial.print("Local port: ");
Serial.println(localPort);
for(int i=0;i<4;i++){//最多尝试10次对时请求
_now=get_ntp_time_impl(i);
if(_now) break; //成功后立即退出
yield();
}
if(_now){
if(time(nullptr) < 1577836800){ //时区未设置 (比较时间为2020年1月1日 00:00:00)
setenv("TZ", "CST-8", 1); //设置时区变量 (当前设置为北京时间)
tzset();
}
return _now;
timeval tm_now={_now, 0};
settimeofday(&tm_now,nullptr);
}
return _now;
}
/* END OF FILE. ReadGuy project.

View File

@@ -70,8 +70,8 @@ void setup(){
//guy.setCursor(10,10); //设置显示的坐标
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
guy.display(true); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
//guy.display(false); // 慢速刷新.
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
//guy.display(READGUY_SLOW); // 慢速刷新.
//想知道更多内容, 欢迎移步到其他示例.
}

View File

@@ -0,0 +1,137 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
*
* @file 4_wifi_text_show.ino
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @version 1.0
* @date 2024-02-28
* @brief ReadGuy通过wifi传输文本并显示.
// 注意, 为了避免此项目占用的flash空间过大, 故库内中不再提供配网的相关功能函数.
// 此示例程序提供了文本传输的功能, 可以通过网页端输入文本并显示到墨水屏上. 自适应字体大小.
// ******** 在进行此示例之前, 不要将 DYNAMIC_PIN_SETTINGS 和 READGUY_ENABLE_WIFI 注释掉. ********
// ******************************** 此示例需要用到 WiFi 的特性. ********************************
*
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//在这里包含程序需要用到的库函数
#include <Arduino.h> //arduino功能基础库. 在platformIO平台上此语句不可或缺
#include "readguy.h" //包含readguy_driver 基础驱动库
#include "ctg_u8g2_wqy12.h" //中文字体库
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
//extern const uint8_t ctg_u8g2_wqy12_chinese1[]; //声明中文字体文件, 本字体只包含很少的字, 不建议用
extern const uint8_t ctg_u8g2_wqy12_gb2312[]; //声明中文字体文件, 本字体包含常用字, 体积较大
//extern const uint8_t ctg_u8g2_wqy12[]; //声明中文字体文件, 本字体包含绝大多数的字, 但体积也更大
const lgfx::U8g2font cn_font(ctg_u8g2_wqy12_gb2312); //U8G2格式中文字体转化为LGFX格式字体
typedef ReadguyDriver::ReadguyWebServer* server_t; //类型名太长太繁琐, 使用typedef减短
typedef ReadguyDriver::serveFunc event_t ; //存储一个WiFi功能事件.
const PROGMEM char textShowHtml[]= R"EOF(<!DOCTYPE html>
<html lang=\"zh-cn\">
<head>
<meta charset=\"utf-8\">
<title>WiFi传文字</title>
</head>
<body>
<h1>WiFi传文字 </h1>
<p><br /></p>
<form action="/showtext" method="GET"><input type='text' name='txt' placeholder="ReadGuy" maxlength="63" />
<br /><input type='submit' value='!' /><br /></form><br />
<p>ReadGuy<br />Copyright © FriendshipEnder
<a href="https://github.com/fsender/readguy">GitHub</a>
<a href="https://space.bilibili.com/180327370/">Bilibili</a></p>
</body>
</html>
)EOF"; //网页文本
void textShow(server_t sv); //服务器响应回调函数. 当启动AP配网服务器时, 这些函数将会被调用
void textShowGet(server_t sv);
void setup(){
Serial.begin(115200); //初始化串口
guy.init(); //初始化readguy_driver 基础驱动库. 尽管初始化过程会刷屏, 但此示例不会用到屏幕.
if(guy.width()<guy.height()) guy.setRotation(1);
guy.setFont(&cn_font);
guy.println("Web一键传文本 正在启用热点...");
guy.display();
event_t server_event[2]={
{"一键传文字","/textshow",textShow},
{"","/showtext",textShowGet},
};
guy.ap_setup(); //初始化WiFi AP模式 (可以理解为路由器模式)
guy.server_setup(String(F("配网服务器演示:可以放置自己的链接和回调函数")),server_event,2); //初始化服务器.
//这些服务器响应回调函数会打包进入初始化参数列表中.
//上方的字符串可以在用户访问主页时, 显示在主页的第二行.(作为通知显示, 但并不是通知)
guy.println("名称:readguy 密码:12345678");
guy.display();
}
void loop(){
guy.server_loop(); //让服务器一直运行
}
// 以下演示了如何向配网服务器添加回调函数.
//其中, sv 参数指向了一个服务器类型的变量. 当有来自客户端的请求时, 需要通过sv来发送响应消息.
void textShow(server_t sv){ //点击链接即可出现发送文本框, 点击发送按钮即可将输入的文本显示到屏幕上
sv->send_P(200, PSTR("text/html"), textShowHtml);
}
void textShowGet(server_t sv){ //注册Web服务函数回调 (就是显示接口)
const String ok_str_1=F("<html><body><meta charset=\"utf-8\">"); //网页前半部分
const String ok_str_2=F("<a href=\"/textshow\">重新传文字</a></body></html>"); //网页后半部分
if(sv->hasArg("txt")){ //检查请求的报文 是否包含键值txt (详见前面的网页声明)
String txt=sv->arg("txt"); //找到字段
//-----------------showTextEpd(txt)------------------ //显示到墨水屏幕上
guy.setTextSize(1); //先设置为默认字体大小, 方便后续计算
int twidth = guy.textWidth(txt); //获取字符串在当前字体的宽度
if(!twidth) { //宽度数值必须为非0
sv->send(200, String(F("text/html")), ok_str_1+"只包含空格, 不显示. "+ok_str_2);
Serial.println("Arg width == 0."); //字符串为空 或者总宽度为零
return;
}
sv->send(200, String(F("text/html")), ok_str_1+"文字显示完成: "+txt+ok_str_2); //报告显示完成
float tsize = ((float)guy.width())/twidth; //计算字体大小, 此大小的目的是填满屏幕
float fsize = ((float)guy.height())/guy.fontHeight(); //计算垂直方向的字体大小, 制定合适的显示方法
if(tsize>fsize){ //字符太短, 字体大小取决于屏幕垂直高度
guy.setTextSize(fsize);
}
else{ //字符可以顶到宽度
guy.setTextSize(tsize, std::max(1.0f,tsize)); //显示的字体大小会根据文本动态变化
} //水平方向太小的话, 垂直方向大小设置为1.0倍(字体原高度)
guy.fillScreen(1);//清屏
guy.setTextDatum(MC_DATUM); //居中显示
guy.drawString(txt,guy.width()/2,guy.height()/2);//居中显示
guy.display(READGUY_SLOW); //慢刷
Serial.print("Show successful:"); //显示成功
Serial.println(txt);
}
else{
Serial.println("No arg."); //找不到txt字段参数
sv->send(200, String(F("text/html")), ok_str_1+"显示失败:缺少参数 "+ok_str_2);
}
}/* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
*
* @file ctg_u8g2_wqy12.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @version 1.0
* @date 2023-09-24
* @brief ReadGuy示例字体文件
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef _CTG_U8G2_WQY12_H_FILE
#define _CTG_U8G2_WQY12_H_FILE
#include <Arduino.h>
#include <pgmspace.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const uint8_t ctg_u8g2_wqy12_chinese1[14241] ;
extern const uint8_t ctg_u8g2_wqy12_gb2312[208522] ;
extern const uint8_t ctg_u8g2_wqy12[626234] ;
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,7 @@
extern "C" {
#endif
extern const uint8_t ctg_u8g2_wqy12_chinese1[14241] ;
extern const uint8_t ctg_u8g2_wqy12_gb2312[208522] ;
extern const uint8_t ctg_u8g2_wqy12[626234] ;
#ifdef __cplusplus
}

View File

@@ -15,6 +15,29 @@
* - 运行的会很缓慢, 因为示例的图片文件比较大.
* 1. 在运行过ex01或者ex02的开发板上 编译烧录本程序.
* 2. 将该项目data文件夹内的所有文件放置于SD卡的根目录上.
* 就是SD卡内放data文件夹内的所有文件, 不能额外套文件夹.
* 如果你的SD卡插入电脑上显示为可移动磁盘, 那么双击SD卡目录就要看到这个文件夹里的文件
*
* 将根目录下的data文件夹 上传到LittleFS之后运行效果更佳
* 或者可以准备一张SD卡,并准备在卡的根目录下放置data文件夹内的文件.
* 就是SD卡内放data文件夹内的所有文件, 不能额外套文件夹.
* 如果你的SD卡插入电脑上显示为可移动磁盘, 那么双击SD卡目录就要看到这个文件夹里的文件
*
* 默认的文件系统为SD卡. 当没有插入SD卡时, 会读取LittleFS文件系统.
* 没有条件准备SD卡的, 可以烧录LittleFS文件系统.
*
* 对于ESP8266 Arduino 用户, 在项目草图文件夹内新建一个data文件夹, 并放入文件 (示例已提供data文件夹)
* 再在 arduinoIDE 的工具选项里选择 ESP8266 LittleFS Data Upload.
* 没有这个选项的需要参考以下文档安装ESP8266 Sketch upload tool
* https://randomnerdtutorials.com/install-esp8266-nodemcu-littlefs-arduino/
*
* 对于ESP32 Arduino 用户, 也要在项目草图文件夹内放一个data文件夹, 并把文件放入其中 (示例已提供data文件夹)
* 再在 arduinoIDE 的工具选项里选择 ESP32 Sketch data upload, 最后选择LittleFS.
* 没有这个选项的需要参考以下文档安装ESP32 LittleFS upload tool
* https://randomnerdtutorials.com/esp32-littlefs-arduino-ide/
*
* 对于PlatformIO 用户, 需要进入platformIO扩展界面, 选择Upload Filesystem Image, 上传项目文件.
* ESP8266和ESP32都要用这种方法.
*
* {0} 代码食用注意事项:
* 这一部分的代码很难读, 或者按维莫斯小姐的说法, 很 "抽象" .
@@ -174,13 +197,13 @@ void setup(){
delay(2000);
guy.display(FILL_WHITE,true); //在保持屏幕缓存不变的时候快速刷新白屏.
guy.display(FILL_WHITE,READGUY_FAST); //在保持屏幕缓存不变的时候快速刷新白屏.
guy.drawImage(sp,0,0,guy.width(),guy.height()); //绘画的画布可以被放大或者缩小到任意宽度和高度.
//此处的参数调用表示将会在屏幕坐标(0,0)开始显示, 显示的画布宽度缩放到屏幕宽度, 画布高度缩放到屏幕高度.
guy.display(); //调用display函数刷屏.
delay(2000);
guy.display(FILL_WHITE,true); //在保持屏幕缓存不变的时候快速刷新白屏
guy.display(FILL_WHITE,READGUY_FAST); //在保持屏幕缓存不变的时候快速刷新白屏
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
guy.drawImage(sp,10,10,65,50); //缩放: 缩小到65X50
guy.display(); //调用display函数刷屏.
@@ -244,7 +267,7 @@ void setup(){
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将的图片刷新.
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将的图片刷新.
//建议在使用drawImageFile函数之前, 使用慢刷刷白屏, 可以保证显示效果清晰可见.
im.drawImageFile(); //显示BMP格式.图片. im会自动识别文件扩展名并绘制.
@@ -265,7 +288,7 @@ void setup(){
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将的图片刷新.
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将的图片刷新.
im.drawImageFile(); //显示JPG格式.图片. im会自动识别文件扩展名并绘制.
delay(2000);
@@ -279,7 +302,7 @@ void setup(){
im.scalex=400.0f/1280.0f;
im.scaley=300.0f/576.0f;
guy.display(FILL_WHITE, false);//显示. 此处的功能就是将显示缓存输出到屏幕上
guy.display(FILL_WHITE, READGUY_SLOW);//显示. 此处的功能就是将显示缓存输出到屏幕上
im.drawImageFile(); //显示PNG格式.图片. ESP8266可能不会绘制.
delay(2000);
@@ -308,7 +331,7 @@ void setup(){
im.exPoolSize=MEM_POOL; //设置外部缓存内存大小
guy.setGreyQuality(1); //设置灰度模式为默认灰度显示模式
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将显示灰度图.
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将显示灰度图.
im.enableFloyd=0; //禁用掉抖动算法.
@@ -316,7 +339,7 @@ void setup(){
delay(2000);
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将显示灰度图.
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将显示灰度图.
im.enableFloyd=1; // 重新启用抖动算法.
@@ -351,7 +374,7 @@ void setup(){
}
guy.drawLine(guy.width(),0,0,guy.height(),0);
guy.display(false); //刷新屏幕, 显示绘画的线段
guy.display(READGUY_SLOW); //刷新屏幕, 显示绘画的线段
//im.baseFs=&guy.guyFS(); //直接更改im内的数据即可设置绘制参数. 在此处就是设置文件系统.
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.

View File

@@ -61,16 +61,16 @@ uint8_t readguyImage::drawImgHandler(int r, LGFX_Sprite *spr){
//_x=y-r/stage*_h; yd=0;
//_y=x;//(widthDiv8<<3)-x-1;
_x=x-r/stage*_h;
_y=y; yd=0;
_y=y+w-guy->drvWidth(); yd=0;
if(_x<0){ xd=-_x; _x=0; }
break;
case 2:
_x=x; xd=0;
_y=y-(GUY_STAGES-r/stage-1)*_h;
_x=x+w-guy->drvWidth(); xd=0;
_y=y+(r/stage+1)*_h-h;
if(_y<0){ yd=-_y; _y=0; }
break;
case 3:
_x=x-(GUY_STAGES-r/stage-1)*_h;
_x=x+(r/stage+1)*_h-h;
_y=y; yd=0;
if(_x<0){ xd=-_x; _x=0; }
break;
@@ -234,7 +234,7 @@ void readguyImage::drawImageFile(bool use16grey){
_pool=exPool;
}
if(_pool==nullptr) {
_h=(h+7)>>3; //设置缓存区的高度. 更多内存将可以更快显示
_h=h>>3; //设置缓存区的高度. 更多内存将可以更快显示
_pool=(uint8_t *)guy->getBuffer();
}
//(guy->guyMemoryHeight()+7)>>3 返回高度,并补齐后右移三位 (等效于除以2³, 分成8份)
@@ -275,7 +275,7 @@ void readguyImage::drawImageFile(bool use16grey){
}
else{
// ************* 提示: 编写此示例时的最新版本LovyanGFX库不提供此函数. 请看ex06_Image.ino文件开头的解决方法!
guy->display(std::bind(&readguyImage::drawImgHandler,this,std::placeholders::_1,&bmpspr));
guy->display(std::bind(&readguyImage::drawImgHandler,this,std::placeholders::_1,&bmpspr),READGUY_FAST);
// 此函数过不了编译 需要改库.
}

View File

@@ -0,0 +1,81 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_template.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 template 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 template 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_template.h"
#ifdef READGUY_DEV_template
namespace guydev_template{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷/快刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
/* 关于这里的f函数指针: f(n)代表访问屏幕缓存的第n字节
若设N=(((屏幕宽度+7)/8)*屏幕高度), 则n的取值范围为 0<=n<N .
比如一个缓存buffer, 有N字节, 那么可以用f(n)=buffer[n]
函数语法为 drv_dispWriter([&](int n)->uint8_t{return buffer[n];},3);
呃 你就把里面的f(n)理解为buffer[n]就行.
*/
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,88 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_template.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 template 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 template 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPDtemplate_H_FILE) && (defined(READGUY_DEV_template)))
#define _GUY_EPDtemplate_H_FILE
namespace guydev_template{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
/** @brief 返回驱动程序ID. 此函数不需要在 cpp 文件内重写
* @return int 直接返回对应宏定义就可以 */
int drv_ID() const { return READGUY_DEV_template; }
/// @brief 初始化屏幕 不过大多数时候此函数只需要初始化启动变量就行
// 比如将模式设为慢刷, 设置为未上电状态 这样下次刷新必为全屏慢刷
void drv_init();
/// @brief 切换慢刷/快刷功能
/// @param part 为1则为快刷, 为0则为慢刷
void drv_fullpart(bool part);
/** @brief 刷屏函数. 程序接口按照此函数刷新
/ @param f 读取像素数据的函数. 这个函数用于替代屏幕缓存数组.
/ 因为有时候屏幕缓存数组不能满足一些显示场景, 比如存储空间复用, 缩放显示等
/ @param m 刷新模式:
/ 1-仅执行前半部分 执行前半部分之后将会向屏幕发送数据后立即退出. (不等busy信号)
/ 2-仅执行后半部分 执行后半部分之后会进行屏幕刷新完之后该执行的操作
/ 3-完整刷屏: 执行1部分->等待busy信号->执行2部分 */
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3);
/// @brief 开始屏幕睡眠/低功耗模式
void drv_sleep() ;
/// @brief 返回显示区域宽度
int drv_width() const { return GUY_D_WIDTH; };
/// @brief 返回显示区域高度
int drv_height() const{ return GUY_D_HEIGHT; };
/** @brief 设置显示颜色深度. 只有在受支持 屏幕上才可以设置灰度
/ @param i 有效值 1~16 0必须为无效 */
void drv_setDepth(uint8_t i);
/** @brief 设置屏幕是否支持连续灰度刷新.
/ @return 设置为 0 不支持灰度 16 支持灰度 -16 支持连续刷新灰度
/ 连续刷新灰度: 先刷深色部分 再刷浅色部分, 原来的深色部分每次刷新都会逐渐越来越深色.
/ 如果不提供连续刷新灰度接口 则使用setDepth函数 先刷浅色部分 再刷深色部分
/ 可以在支持连续刷新的屏幕上烧录范例程序查看效果. 通常都是好于非连续刷新的灰度 */
int drv_supportGreyscaling() const { return 16; }
// 在支持连续灰度刷新的屏幕上 还要额外实现一个函数用于连续刷新接口
/// @brief 设置连续刷新功能函数. 范例可以看guy_420a文件内的示例,分步执行连续刷灰度
//void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度 1-15均为有效. 慢刷模式中 此数值为15.
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,23 @@
# 添加新驱动程序
1. 将文件夹 guy_template 整个拷贝到 guy_epaper 文件夹下
2. 根据里面的模板文件, 添加自定义驱动.
3. 使用查找工具搜索 src 下的以下文本.
```
//添加新屏幕型号 add displays here
```
然后把新加入的屏幕驱动 define 给加上
4. 更新 `EPD_DRIVERS_NUM_MAX` 变量, 表明一共有多少个驱动可用.
5. 加好了之后, 应该就可以使用这个驱动了.
6. 记得更改项目根目录的 readme 文件
# 禁用驱动程序
前往 guy_epaper_config.h 文件, 注释掉不需要编译的驱动文件即可

View File

@@ -45,9 +45,6 @@ default_envs = nodemcuv2
board_build.filesystem = littlefs ; SPIFFS mode
upload_speed = 921600 ; If using USB-JTAG, this selection is dummy
monitor_speed = 115200
build_flags =
-Wall
-Wextra
[env:esp32dev] ; 适用于ESP32的项目配置方案 注意是经典的ESP32...
platform = espressif32
@@ -60,6 +57,8 @@ framework = espidf, arduino
monitor_filters = esp32_exception_decoder
;build_type = debug
build_flags =
-Wall
-Wextra
; -DCORE_DEBUG_LEVEL=4
[env:nodemcuv2] ; 适用于ESP8266的项目配置方案
@@ -72,6 +71,8 @@ monitor_filters = esp8266_exception_decoder
;build_type = debug
build_flags =
-Wall
-Wextra
; -DNON32XFER_HANDLER ;不需要PROGMEM保留字也可以访问flash中的内容
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;增大可用的HEAP内存
; -fstack-protector ;打开栈溢出保护器
@@ -90,7 +91,9 @@ board_build.partitions = readguy_4MB.csv ; defined
monitor_filters = esp32_exception_decoder
;build_type = debug
build_flags =
build_flags =
-Wall
-Wextra
;-DARDUINO_USB_MODE=1
;-DARDUINO_USB_CDC_ON_BOOT=1 ; 是否需要使用USB串口调试如果需要调试则打开否则禁用
; 如果打开了这个选项但是不连接串口在有串口输出的地方会卡顿1秒左右
@@ -117,7 +120,9 @@ board_build.flash_mode = dio
board_build.partitions = readguy_16MB.csv
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-Wall
-Wextra
;-DARDUINO_USB_MODE=1
;-DARDUINO_USB_CDC_ON_BOOT=1 ; 是否需要使用USB串口调试如果需要调试则打开否则禁用
; 如果打开了这个选项但是不连接串口在有串口输出的地方会卡顿1秒左右
@@ -142,6 +147,31 @@ board_build.f_flash = 80000000L
board_build.flash_mode = dio
board_build.partitions = readguy_4MB.csv ; 2MB的芯片就选readguy_2MB_noOTA.csv
build_flags =
-Wall
-Wextra
;-DARDUINO_USB_MODE=1
;-DARDUINO_USB_CDC_ON_BOOT=1 ; 是否需要使用USB串口调试如果需要调试则打开否则禁用
; 如果打开了这个选项但是不连接串口在有串口输出的地方会卡顿1秒左右
; 合宙无串口开发板请选择此选项为1.
-DCORE_DEBUG_LEVEL=1 ; None 0, Error 1, Warn 2, Info 3, Debug 4, Verbose 5
[env:esp32c3_no_uart] ;适用于ESP32C3 的项目配置方案.
platform = espressif32 ;注意在使用不带串口芯片的ESP32C3时, 尽量不要使用引脚18和19.
board = esp32-c3-devkitm-1 ;那俩是连接的板载USB串口 (USB-CDC, 可以下载程序或是当免驱串口)
framework = espidf, arduino ;合宙你真该死啊出这种没串口芯片的ESP32C3 甚至旧版本arduino无法编程!
board_build.f_cpu = 160000000L ;芯片速率默认160MHz, 不支持高频240MHz.
;board_build.flash_size=2MB ;2MB的芯片就选readguy_2MB_noOTA.csv
board_build.flash_size=4MB ;根据你自己的改, 不得小于4MB. 2MB的芯片就选readguy_2MB_noOTA.csv
board_build.f_flash = 80000000L
board_build.flash_mode = dio
board_build.partitions = readguy_4MB.csv ; 2MB的芯片就选readguy_2MB_noOTA.csv
build_flags =
-Wall
-Wextra
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1 ; 是否需要使用USB串口调试如果需要调试则打开否则禁用
; 如果打开了这个选项但是不连接串口在有串口输出的地方会卡顿1秒左右
; 合宙无串口开发板请选择此选项为1.
-DCORE_DEBUG_LEVEL=1 ; None 0, Error 1, Warn 2, Info 3, Debug 4, Verbose 5
@@ -149,10 +179,14 @@ build_flags =
platform = espressif32
board = nodemcu-32s2
framework = espidf, arduino
board_build.f_cpu = 240000000L
build_type = debug
board_build.f_cpu = 160000000L
board_build.flash_size=4MB ;根据你自己的改, 不得小于4MB
board_build.f_flash = 80000000L
board_build.flash_mode = dio
board_build.partitions = readguy_4MB.csv ; defined
build_flags =
-Wall
-Wextra
-DCORE_DEBUG_LEVEL=1 ; None 0, Error 1, Warn 2, Info 3, Debug 4, Verbose 5
monitor_filters = esp32_exception_decoder

View File

@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1E0000,
app1, app, ota_1, 0x1F0000,0x1E0000,
spiffs, data, spiffs, 0x3D0000,0x20000,
coredump, data, coredump,0x3F0000,0x10000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x1E0000
5 app1 app ota_1 0x1F0000 0x1E0000
6 spiffs data spiffs 0x3D0000 0x20000
7 coredump data coredump 0x3F0000 0x10000

View File

@@ -971,7 +971,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
#
# TLS Key Exchange Methods
#
# CONFIG_MBEDTLS_PSK_MODES is not set
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y

File diff suppressed because it is too large Load Diff

View File

@@ -1012,7 +1012,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
#
# TLS Key Exchange Methods
#
# CONFIG_MBEDTLS_PSK_MODES is not set
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y

View File

@@ -978,7 +978,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
#
# TLS Key Exchange Methods
#
# CONFIG_MBEDTLS_PSK_MODES is not set
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y

View File

@@ -11,7 +11,7 @@
"type": "git",
"url": "https://github.com/fsender/readguy"
},
"version": "1.3.0",
"version": "1.3.5",
"frameworks": "arduino",
"platforms": ["espressif32", "espressif8266"],
"headers": "readguy.h",

View File

@@ -1,5 +1,5 @@
name=readguy
version=1.3.0
version=1.3.5
author=fsender <f_ender@163.com>
maintainer=fsender <f_ender@163.com>
sentence=A free E-paper display driver library supports 16-level greyscale.

View File

@@ -78,11 +78,18 @@ void guy_button::begin(uint8_t _pin, std_U8_function_U8 f, bool activeLow /* = t
state = get_state_cb(pin);
min_debounce =25; //去抖时间
long_press_ms =300; //长按持续时间+双击识别间隔最大时间
long_repeat_ms =150; //长按连按间隔时间
long_repeat_ms =200; //长按连按间隔时间
multibtn =0;
lk=0;
}
bool guy_button::isPressedRaw() {
int mi=millis();
while(lk) if(millis()-mi>GUYBTN_READ_TIMEOUT) return 0; //等待数据读完
lk=3;
bool willreturn = (get_state_cb(pin) == _pressedState);
lk=0;
return willreturn;
}
uint8_t guy_button::read() { //注意ticker不能在此触发
int mi=millis();
while(lk) if(millis()-mi>GUYBTN_READ_TIMEOUT) return 0; //等待数据读完
@@ -91,13 +98,14 @@ uint8_t guy_button::read() { //注意ticker不能在此触发
if(state == _pressedState && n - down_ms>= long_press_ms && long_clicked < n){
long_clicked = trig_mode?(n+long_repeat_ms):0xfffffffful;
lk=0;
return GUYBUTTON_long_click;
return (click_count>=3)?GUYBUTTON_xxlong_click:\
((click_count==2)?GUYBUTTON_xlong_click:GUYBUTTON_long_click);
}
uint8_t res = last_click_type;
last_click_type = GUYBUTTON_empty;
was_pressed = false;
lk=0;
return (res==GUYBUTTON_long_click)?GUYBUTTON_empty:res;
return (res>=GUYBUTTON_long_click)?GUYBUTTON_empty:res;
}
void guy_button::loop() {
@@ -140,8 +148,9 @@ void guy_button::loop() {
// was there a longclick?
if (longclick_detected) {
// was it part of a combination?
if (click_count == 1) {
last_click_type = GUYBUTTON_long_click;
if (click_count) {
last_click_type = (click_count>=3)?GUYBUTTON_xxlong_click:\
((click_count==2)?GUYBUTTON_xlong_click:GUYBUTTON_long_click);
was_pressed = true;
}
longclick_detected = false;

View File

@@ -76,14 +76,17 @@ SOFTWARE.
#define GUYBUTTON_double_click 2
#define GUYBUTTON_triple_click 3
#define GUYBUTTON_long_click 4
#define GUYBUTTON_xlong_click 5
#define GUYBUTTON_xxlong_click 6
#define GUYBTN_READ_TIMEOUT 100
#define GUYBTN_LOOP_TIMEOUT 10
class guy_button{
protected:
public:
uint16_t min_debounce ; //去抖时间
uint16_t long_press_ms ; //长按持续时间+双击识别间隔最大时间
uint16_t long_repeat_ms ; //长按连按间隔时间
protected:
uint8_t pin = 255; //未定义引脚
uint8_t state;
uint8_t prev_state;
@@ -114,16 +117,19 @@ class guy_button{
void setLongRepeatMode(bool trigMode) { trig_mode = trigMode; }
unsigned int wasPressedFor() const { return down_time_ms; }
bool isPressed() const { return (state == _pressedState); }
bool isPressedRaw() { return (get_state_cb(pin) == _pressedState); }
bool isPressedRaw(); // { return (get_state_cb(pin) == _pressedState); }
bool wasPressed(){ if(was_pressed){ was_pressed = false; return true; } return false; }
uint8_t getNumberOfClicks() const{ return click_count;}
uint8_t getType() const { return last_click_type; }
uint8_t read();
void loop();
void setMultiBtn(uint8_t btns) { multibtn = btns; }
void setMinDebounce(short n) { min_debounce =n;} //去抖时间
/* void setMinDebounce(short n) { min_debounce =n;} //去抖时间
void setLongPressMs(short n) { long_press_ms =n;} //长按持续时间+双击识别间隔最大时间
void setLongRepeat(short n) { long_repeat_ms =n;} //长按连按间隔时间
void getMinDebounce(short n) { min_debounce =n;} //去抖时间
void getLongPressMs(short n) { long_press_ms =n;} //长按持续时间+双击识别间隔最大时间
void getLongRepeat(short n) { long_repeat_ms =n;} //长按连按间隔时间 */
};
#endif /* END OF FILE. ReadGuy project. */

View File

@@ -6,11 +6,16 @@
* @file guy_driver_config.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief readguy 基础配置文件. 用户可以根据自己对库的编译需求来修改此文件.
*
* 如果你希望在程序代码内包含引脚定义, 请参考此文件下方的注释来确定并编译
* !!!但是这样编译得到的程序不具备跨平台特性.!!!
* 可以禁用WiFi功能来减少ESP32的flash消耗
* @version 1.0
* @date 2023-09-21
* 这样就可以只针对你设计的这一个硬件来设定引脚功能.
* 关于屏幕配置, 请参考 guy_epaper/guy_epaper_config.h 文件来配置到底哪些屏幕型号的屏幕会被包含进来
* 可以禁用WiFi功能来减少程序的flash消耗
* @version 1.1
* @date create: 2023-09-21
* last modify: 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
@@ -61,6 +66,7 @@
/// @brief 使用静态的数据 !!!注意:注释此选项编写的程序是不支持跨平台运行的!!!
/// @note 相比于禁用WiFi配网功能, 禁用此功能减少的flash并不多, 为保证程序可在不同屏幕上运行, 请不要注释此选项
// 关闭此选项自动禁用wifi功能. 如需wifi功能需要自己在程序里加.
#define DYNAMIC_PIN_SETTINGS
/// @brief 启用WIFI配网功能.必须先启用 #define DYNAMIC_PIN_SETTINGS. 此选项对 ESP32xx 会减少大量flash.
@@ -69,11 +75,20 @@
/// @brief 启用I2C功能. 可用于联网时钟, 温度计, 陀螺仪等外设. 目前暂不支持库内使用类似函数. 仅可以提供引脚定义
#define READGUY_ENABLE_I2C
/** @brief (即将推出) 启用SD卡功能. 开启此功能将会使用内置SD卡管理功能. 关闭后仅可保存SD卡用到的引脚.
@note 会破坏兼容性. 若没有启用通用的SD卡驱动程序, 那么那些跨屏台编译的程序将无法用guyFS读取到SD卡.
若用户程序希望能从外部加载SD卡, 可以使用getSdMiso()等函数获取SD卡的Miso等引脚, 再由用户程序初始化SD卡. */
#define READGUY_ENABLE_SD
/// @brief 使用LittleFS作为片上文件系统, 注释此行则用SPIFFS(功能少, 不好用)
#define READGUY_USE_LITTLEFS 1
/// @brief ESP32按键服务任务的栈空间大小, 不建议普通用户更改. 默认值1024字节. 小于此大小会使程序栈溢出.
#ifdef CONFIG_IDF_TARGET_ESP32S3
#define BTN_LOOPTASK_STACK 1280
#else
#define BTN_LOOPTASK_STACK 1024
#endif
/// @brief ESP32按键服务任务运行在哪个核心. 通常运行在核心0上.
#define BTN_LOOPTASK_CORE_ID 0

View File

@@ -0,0 +1,75 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_1020A.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 1020A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 1020A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_1020A.h"
#ifdef READGUY_DEV_1020A
namespace guydev_1020A{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,63 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_1020A.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 1020A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 1020A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD1020A_H_FILE) && (defined(READGUY_DEV_1020A)))
#define _GUY_EPD1020A_H_FILE
namespace guydev_1020A{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_1020A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,70 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_154c.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸墨水屏 驱动库函数
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_154C.h"
#ifdef READGUY_DEV_154C
namespace guydev_154C{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,58 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_154c.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD154C_H_FILE) && (defined(READGUY_DEV_154C)))
#define _GUY_EPD154C_H_FILE
namespace guydev_154C{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_154C; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -98,6 +98,7 @@ void drvBase::drv_init(){ //new init method can init without freshing.
//drv_color(0xffu); //睡眠模式下始终需要慢刷
}
void drvBase::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(lastRefresh) return;
if(!part) iLut=15;
if(sleeping) iLut=15;
else Init(part?lut_fast:lut_slow);
@@ -110,7 +111,9 @@ void drvBase::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(!part) iLut=15; //恢复默认的灰度模式
Init(part?lut_fast:lut_slow);
}*/
void drvBase::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新等功能
void drvBase::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新等功能
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
if(sleeping) Init(lut_slow);
BeginTransfer();
SetMemory(); // bit set = white, bit reset = black
@@ -123,14 +126,22 @@ void drvBase::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新等
guy_epdCmd(0x20);
guy_epdCmd(0xff);
EndTransfer();
guy_epdBusy((this->lut == (const uint8_t*)lut_fast)?idleFastRf:idleSlowRf);
BeginTransfer();
SetMemory(); // bit set = white, bit reset = black
guy_epdBusy(90);
guy_epdCmd(0x26); /* will send the color data */
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
SpiTransfer(f(i));
EndTransfer();
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=(this->lut == (const uint8_t*)lut_fast)?idleFastRf:idleSlowRf;
if(ms<u) guy_epdBusy(u-ms);
lastRefresh=0;
BeginTransfer();
SetMemory(); // bit set = white, bit reset = black
guy_epdBusy(90);
guy_epdCmd(0x26); /* will send the color data */
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
SpiTransfer(f(i));
EndTransfer();
}
}
void drvBase::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒

View File

@@ -42,7 +42,7 @@ public:
virtual int drv_ID() const=0;
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度

View File

@@ -144,11 +144,14 @@ void drvSSD168x::drv_init(){
//drv_color(0xffu);
}
void drvSSD168x::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(lastRefresh) return;
if(!epd_PowerOn) part=0; //未上电 无法局刷
if(!part) { iLut=15; greyScaling=0; }
_part=part;
}
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
BeginTransfer();
if(_part){
//Reset();
@@ -196,7 +199,15 @@ void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
guy_epdParam(_part?0x0f:0xc7);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(_part?600:2300);
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=_part?600:2300;
if(ms<u) guy_epdBusy(u-ms);
lastRefresh=0;
}
//guy_epdBusy(_part?600:2300);
}
void drvSSD168x::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //无法唤醒

View File

@@ -40,7 +40,7 @@ public:
virtual int drv_ID() const =0;
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度

View File

@@ -113,13 +113,16 @@ void drv::drv_init(){ //初始化屏幕
//drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
if(!epd_PowerOn) part=0; //未上电 无法局刷
//if(part==epdFull) return;
if(!part) iLut=15; //恢复默认的灰度模式
epdFull = !part;
//epd_Init();
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
BeginTransfer();
if(epdFull) { //当刷新模式从快刷切换为慢刷时, 需要发送一次init
epdFull=0;
@@ -143,7 +146,15 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
guy_epdParam(epdFull?0xc4:0x04);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(epdFull?1600:310);
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?1600:310;
if(ms<u) guy_epdBusy(u-ms);
lastRefresh=0;
}
//guy_epdBusy(epdFull?1600:310);
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒

View File

@@ -47,7 +47,7 @@ public:
int drv_ID() const { return READGUY_DEV_213A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return EPD_REAL_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度

View File

@@ -30,7 +30,8 @@
#include <stdlib.h>
#include "guy_213b_266a.h"
// #define MEPD_DEBUG_WAVE
#ifdef READGUY_DEV_266A
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C))
namespace guydev_213B_266A{
static const PROGMEM unsigned char lutSlow_vcom0[] ={
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
@@ -68,21 +69,30 @@ static const PROGMEM unsigned char lutSlow_b_b[] ={
static const PROGMEM unsigned char lutFast_[]={
0x00,0x18,0x5a,0xa5,0x24
};
static const PROGMEM unsigned char greyLutLevel[]={
0, 3, 6, 9,12,15,18,21,24,28,31,34,37,42,48,54, //for BWR displays
0, 3, 5, 7,10,13,16,19,22,25,29,32,35,38,43,49,
0, 3, 5, 6, 8,11,14,17,20,23,26,29,32,35,39,44,
0, 2, 4, 5, 6, 8,10,13,15,18,21,24,27,31,35,39,
0, 2, 3, 5, 6, 7, 8,10,12,15,17,19,22,24,27,30,
0, 2, 3, 4, 5, 6, 7, 8,10,12,14,16,18,20,22,24,
0, 3, 3, 3, 4, 4, 5, 6, 7, 9,12,16,21,28,36,48,
};
drv_base::drv_base(){
guy_lutArray[0] = lutSlow_vcom0;
guy_lutArray[1] = lutSlow_w_w;
guy_lutArray[2] = lutSlow_b_w;
guy_lutArray[3] = lutSlow_w_b;
guy_lutArray[4] = lutSlow_b_b;
guy_lutArray[5] = lutFast_;
}
void drv_base::epd_init(){
//if(!Power_is_on) Reset();
guy_epdCmd(0x01);
guy_epdParam(0x03);
guy_epdParam(0x00);
guy_epdParam(0x2b);
guy_epdParam(0x2b);
guy_epdParam(0x10);
guy_epdParam(isBWR?0x3f:0x2b);
guy_epdParam(isBWR?0x3f:0x2b);
guy_epdParam(0x03);
guy_epdCmd(0x06);
guy_epdParam(0x17);
@@ -92,7 +102,7 @@ void drv_base::epd_init(){
guy_epdParam(0xbf);
guy_epdParam(0x0d);
guy_epdCmd(0x30);
guy_epdParam(0x29); //0x3a:100Hz, 0x29:150Hz
guy_epdParam(isBWR?0x3b:0x29); //0x3a:100Hz, 0x29:150Hz
guy_epdCmd(0x61);
guy_epdParam(0x98);
guy_epdParam(0x01);
@@ -118,9 +128,9 @@ void drv_base::SendLuts(bool part_lut){
guy_epdCmd(i+0x20);
for(int j=0;j<(i==0?44:42);j++){
if(part_lut){
if(j==4 && ((i==2) || (greyHQ==3 && i==4))) guy_epdParam(15);
else if(j==greyHQ) guy_epdParam(greyLut);
else if(j==0) guy_epdParam(pgm_read_byte(guy_lutArray[5]+(i)));
if(j==4 && ((i==2) || (greyHQ==3 && i==4))) guy_epdParam(isBWR?0x2f:0x0f); //刷黑->白
else if(j==greyHQ) guy_epdParam(isBWR?pgm_read_byte(greyLutLevel+(greyLut+refTime*16)):greyLut);
else if(j==0) guy_epdParam(pgm_read_byte(lutFast_+(i)));
else if(j==5) guy_epdParam(1);
else guy_epdParam(0x0);
}
@@ -141,6 +151,7 @@ void drv_base::drv_init(){
//drv_color(0xff);
}
void drv_base::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(lastRefresh) return;
if(!Power_is_on) part=0;
if(!part) greyLut=15; //恢复默认的灰度模式
part_mode = part;
@@ -152,7 +163,9 @@ void drv_base::drv_setDepth(uint8_t i){
SendLuts(1);
EndTransfer();
}
void drv_base::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv_base::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
BeginTransfer();
epd_init();
SendLuts(part_mode);
@@ -165,21 +178,30 @@ void drv_base::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
guy_epdCmd(0x92);
if(part_mode){
guy_epdCmd(0x30);
guy_epdParam(0x3a); //0x3a:100Hz, 0x29:150Hz
//guy_epdParam(0x3a); //黑白色用此行, 三色用下一行
guy_epdParam(isBWR?0x19:(refTime?0x21:0x3a)); //0x3a:100Hz, 0x29:150Hz
send_zoneInfo();
guy_epdCmd(0x12);
EndTransfer();
guy_epdBusy(-200);
}
else{
guy_epdCmd(0x12);
EndTransfer();
guy_epdBusy(-2000);
BeginTransfer();
epd_init();
SendLuts(1);
guy_epdCmd(0x92);
EndTransfer();
guy_epdCmd(0x12);
EndTransfer();
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
if(part_mode){
if((int32_t)ms<fastRefTime) guy_epdBusy((int32_t)ms-fastRefTime);
refTime+=(refTime<5);
}
else{
if((int32_t)ms<slowRefTime) guy_epdBusy((int32_t)ms-slowRefTime);
BeginTransfer();
epd_init();
SendLuts(1);
guy_epdCmd(0x92);
EndTransfer();
refTime=0;
}
lastRefresh=0;
}
}
void drv_base::drv_sleep() { //开始屏幕睡眠
@@ -199,6 +221,7 @@ void drv_base::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
if(step==1){
greyHQ=3;
refTime=6;
drv_setDepth(3);
drv_fullpart(1); //开始快刷
}
@@ -207,6 +230,7 @@ void drv_base::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
drv_dispWriter(f);
if(step==15){
greyHQ=4;
refTime=5;
drv_setDepth(15);
}
} //据说可以设置灰度渲染方式. 好像是调用setGreyQuality函数就行来着

View File

@@ -6,8 +6,10 @@
* @file guy_213b_266a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 2.13英寸B型墨水屏和 2.66英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* 增加了对三色屏幕的支持
* @version 1.1
* @date create: 2023-09-21
* last modify: 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
@@ -29,7 +31,8 @@
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD213B_266A_H_FILE) && \
(defined(READGUY_DEV_266A) || defined(READGUY_DEV_213B)))
(defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C)))
#define _GUY_EPD213B_266A_H_FILE
namespace guydev_213B_266A{
@@ -39,7 +42,7 @@ public:
virtual int drv_ID() const=0;
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度
@@ -49,7 +52,6 @@ public:
protected:
int epdWidth;
int epdHeight;
private:
void epd_init();
void send_zoneInfo();
void SendLuts(bool part_lut);
@@ -57,22 +59,40 @@ private:
uint8_t Power_is_on = 2; //初始为未上电
uint8_t greyLut=15;
uint8_t greyHQ=4; // greyHQ==3 时 为高品质刷新灰度 否则为常规方式刷新灰度
const uint8_t *guy_lutArray[6];
uint8_t refTime=0;
uint8_t isBWR=0; //三色2.66将此屏幕数值改为1.
int16_t slowRefTime;
int16_t fastRefTime;
const uint8_t *guy_lutArray[5];
};
#ifdef READGUY_DEV_213B
class dev213B : public drv_base {
public:
dev213B(){ epdWidth=104; epdHeight=212; }
dev213B(){ epdWidth=104; epdHeight=212; slowRefTime=1300; fastRefTime=200; }
int drv_ID() const { return READGUY_DEV_213B; }
};
#endif
#ifdef READGUY_DEV_213B3C
class dev213B3C : public drv_base {
public:
dev213B3C(){ epdWidth=104; epdHeight=212; isBWR=1; slowRefTime=2800; fastRefTime=800; }
int drv_ID() const { return READGUY_DEV_213B3C; }
};
#endif
#ifdef READGUY_DEV_266A
class dev266A : public drv_base {
public:
dev266A(){ epdWidth=152; epdHeight=296; }
dev266A(){ epdWidth=152; epdHeight=296; slowRefTime=1300; fastRefTime=200; }
int drv_ID() const { return READGUY_DEV_266A; }
};
#endif
#ifdef READGUY_DEV_266A3C
class dev266A3C : public drv_base {
public:
dev266A3C(){ epdWidth=152; epdHeight=296; isBWR=1; slowRefTime=2800; fastRefTime=800; }
int drv_ID() const { return READGUY_DEV_266A3C; }
};
#endif
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,75 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_370B.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 370B 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 370B 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_370B.h"
#ifdef READGUY_DEV_370B
namespace guydev_370B{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,63 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_370B.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 370B 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 370B 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD370B_H_FILE) && (defined(READGUY_DEV_370B)))
#define _GUY_EPD370B_H_FILE
namespace guydev_370B{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_370B; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -110,7 +110,7 @@ void drv::drv_init(){ //初始化屏幕
//drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(sleeping) return;
if(lastRefresh || sleeping) return;
if(!part) {
greyScaling=15; //恢复默认的灰度模式
BeginTransfer();
@@ -120,7 +120,9 @@ void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
}
part_mode=part;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
if(sleeping) Init();
BeginTransfer();
guy_epdCmd(0x4E); guy_epdParam(0x00); guy_epdParam(0x00);
@@ -138,7 +140,15 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
Load_LUT(!part_mode);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(part_mode?500:1300);
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=part_mode?500:1300;
if(ms<u) guy_epdBusy(u-ms);
lastRefresh=0;
}
//guy_epdBusy(part_mode?500:1300);
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){

View File

@@ -40,7 +40,7 @@ public:
int drv_ID() const { return READGUY_DEV_370A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度

View File

@@ -182,10 +182,13 @@ void drv::drv_init(){ //初始化屏幕
//drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
if(epdFull<=1) epdFull = !part; //epdFull==2代表睡眠中, 不能快刷
if(epdFull) GreyScaling=0;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
BeginTransfer();
epd_Init();
SetMemory();
@@ -211,9 +214,7 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
SetLut(lut_213_B72_Full);
guy_epdCmd(0x22);
guy_epdParam(0xc4);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(1600); //等待刷完
//guy_epdBusy(1600); //等待刷完
}
else{ //快刷
guy_epdCmd(0x2c); //may a mistake? 此处不需要设置vcom
@@ -221,17 +222,24 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
SetLut(GreyScalingHighQuality?lut_213_B72_16grey:lut_213_B72);
guy_epdCmd(0x22);
guy_epdParam(0x04);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(260); //等待屏幕刷新完成
}
BeginTransfer(); //write again
SetMemory();
guy_epdCmd(0x26);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
SpiTransfer(f(i)); //按照给定的RAM写入数据
guy_epdCmd(0x20);
EndTransfer();
if(epdFull) power_down();
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?1600:260;
if(ms<u) guy_epdBusy(u-ms); //等待屏幕刷新完成
lastRefresh=0;
BeginTransfer(); //write again
SetMemory();
guy_epdCmd(0x26);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
SpiTransfer(f(i)); //按照给定的RAM写入数据
EndTransfer();
if(epdFull) power_down();
}
}
void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);

View File

@@ -41,7 +41,7 @@ public:
int drv_ID() const { return READGUY_DEV_420A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度

View File

@@ -147,7 +147,9 @@ const PROGMEM unsigned char drv::lutFast_b_w[] ={ 0x5a,2,0,63,0,1 };
const PROGMEM unsigned char drv::lutFast_w_b[] ={ 0x84,2,0,48,0,1 };
const PROGMEM unsigned char drv::lutFast_b_b[] ={ 0x01,2,0,48,0,1 };
//void drv::epd_display(){
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
BeginTransfer();
Init(part_mode);
if(part_mode){
@@ -181,7 +183,13 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
}
guy_epdCmd(0x12);
EndTransfer();
guy_epdBusy(part_mode?-800:-3600);
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
int32_t u=part_mode?800:3600;
if((int32_t)ms<u) guy_epdBusy((int32_t)ms-u);
lastRefresh=0;
BeginTransfer();
if(part_mode){
sendArea();
@@ -189,7 +197,6 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++)
SpiTransfer(f(i));
guy_epdCmd(0x92);
EndTransfer();
}
else{
Init(2);
@@ -199,6 +206,7 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
SpiTransfer(f(i));
guy_epdCmd(0x92);
guy_epdCmd(0x02);
}
EndTransfer();
guy_epdBusy(-20);
}
@@ -216,6 +224,7 @@ void drv::drv_init(){
//drv_color(0xffu);
}
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(lastRefresh) return;
if(Power_is_on) {
if(!part) customLut = CUSTOM_LUT_DISABLE;
part_mode = part;

View File

@@ -44,7 +44,7 @@ public:
void drv_init(); //初始化屏幕
//void drv_draw16grey(uint8_t *d16bit);
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度

View File

@@ -0,0 +1,75 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_426A.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 426A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 426A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_426A.h"
#ifdef READGUY_DEV_426A
namespace guydev_426A{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,63 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_426A.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 426A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 426A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD426A_H_FILE) && (defined(READGUY_DEV_426A)))
#define _GUY_EPD426A_H_FILE
namespace guydev_426A{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_426A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,420 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_583A.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 583A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 583A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_583A.h"
#ifdef READGUY_DEV_583A
namespace guydev_583A{
/*LUT格式
重复次数xnnnxnnn...(000=0,001=VSH,010=VSL,011=VSH_LV,100=VSL_LV,101=VSH_LVX,110=VSL_LVX,111=浮动),持续时间.......
0x01, 0x00, 0x00, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
0x01, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x01, 0x21, 0x21, 0x21, 0x21, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
0x01, 0x12, 0x12, 0x12, 0x10, 0x14, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00
0x01, 0x11, 0x21, 0x21, 0x22, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
0x01, 0x21, 0x21, 0x21, 0x20, 0x14, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x01, 0x12, 0x12, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02
0x01, 0x21, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
*/
const PROGMEM unsigned char drv::lut_20_LUTC[] =
{ 0x01, 0x00, 0x00, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B};
const PROGMEM unsigned char drv::lut_20_LUTCFAST[] =
{ 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::lut_21_LUTB[] =//000
{ 0x01, 0x21, 0x21, 0x21, 0x21, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
const PROGMEM unsigned char drv::lut_21_LUTBFAST[] =
{ 0x01, 0x12, 0x12, 0x12, 0x10, 0x1f, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00};
const PROGMEM unsigned char drv::lut_22_LUTW[] =//011
{ 0x01, 0x11, 0x21, 0x21, 0x22, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
const PROGMEM unsigned char drv::lut_22_LUTWFAST[] =
{ 0x01, 0x21, 0x21, 0x21, 0x20, 0x1f, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x00};
const PROGMEM unsigned char drv::lut_23_LUTG1[] =//001
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::lut_24_LUTG2[] =//010
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::lut_25_LUTR0[] =//100//WW
{ 0x01, 0x12, 0x12, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
const PROGMEM unsigned char drv::lut_26_LUTR1[] =//101//BB
{ 0x00/*0x01*/, 0x21, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
const PROGMEM unsigned char drv::lut_27_LUTR2[] =//110
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::lut_28_LUTR3[] =//111//局刷
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::lut_29_LUTXON[] =
{ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const PROGMEM unsigned char drv::customGrey[] =
{ 0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1e,
0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
const PROGMEM unsigned char *drv::luts[10]={
lut_20_LUTC,lut_21_LUTB,lut_22_LUTW,lut_23_LUTG1,lut_24_LUTG2,
lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
};
const unsigned char *drv::luts_fast[10]={
lut_20_LUTCFAST,lut_21_LUTBFAST,lut_22_LUTWFAST,lut_23_LUTG1,lut_24_LUTG2,
lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
};
#ifdef READGUY_583A_DUAL_BUFFER
drv::drv(){ //构造时, 分配内存.
buf_2nd=(uint8_t *)malloc(GUY_D_WIDTH*GUY_D_HEIGHT/8);
if(buf_2nd) {
Serial.println(F("[GUY MEM] allocate 33600B for 5.83' EPD."));
//memset(buf_2nd,0,GUY_D_WIDTH*GUY_D_HEIGHT/8);
}
}
drv::~drv(){ //构造时, 分配内存.
if(buf_2nd) free(buf_2nd);
Serial.println(F("[GUY MEM] unallocate 33600B."));
}
#endif
void drv::sendLut(int lutid){
int lutlen=13,lutlen2=247;
if(lutid==0){lutlen=11;lutlen2=209;}
else if(lutid==9){lutlen=10;lutlen2=190;}
guy_epdCmd(0x20+lutid);
if(epdFull){
for(int i=0;i<lutlen;i++){
guy_epdParam(pgm_read_byte(luts[lutid]+i));
}
}
else{
for(int i=0;i<lutlen;i++){
if(lutid==1 && i==5) guy_epdParam(pgm_read_byte(customGrey+iLut+greyscalingHighQuality));
else
guy_epdParam(pgm_read_byte(luts_fast[lutid]+i));
}
}
for(int i=0;i<lutlen2;i++){
guy_epdParam(0);
}
}
void drv::epd_init(){
if(!epd_PowerOn) Reset(); //设定为已上电
guy_epdCmd(0x01);
guy_epdParam(0x37);
guy_epdParam(0x00);
guy_epdParam(0x07);
guy_epdParam(0x07);
guy_epdCmd(0x00);
guy_epdParam(0xcf);
guy_epdParam(0x88);
guy_epdCmd(0x06);
guy_epdParam(0xc7);
guy_epdParam(0xcc);
guy_epdParam(0x28);
guy_epdCmd(0x30);
guy_epdParam(0x3a);
guy_epdCmd(0x41);
guy_epdParam(0x00);
guy_epdCmd(0x50);
guy_epdParam(0x77);
guy_epdCmd(0x60);
guy_epdParam(0x22);
guy_epdCmd(0x61);
guy_epdParam(0x02);
guy_epdParam(0x58);
guy_epdParam(0x01);
guy_epdParam(0xc0);
guy_epdCmd(0x82);
guy_epdParam(0x28);
for(int i=0;i<10;i++){
sendLut(i);
}
guy_epdCmd(0xe5);
guy_epdParam(0x03);
}
void drv::epd_sendZoneInfo(){
guy_epdCmd(0x91);
//send area info
guy_epdCmd(0x90);
guy_epdParam(0x00);
guy_epdParam(0x00);
guy_epdParam(0x02);
guy_epdParam(0x57);
guy_epdParam(0x00);
guy_epdParam(0x00);
guy_epdParam(0x01);
guy_epdParam(0xbf);
guy_epdParam(0x01);
}
void drv::epd_sendWriter(std::function<uint8_t(int)> f){
guy_epdCmd(0x10); //Then write image data 显示数据
#ifdef READGUY_583A_DUAL_BUFFER
if(epdFull || buf_2nd==nullptr || greyscalingHighQuality){
#endif
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){ //fill 0x03 for test
uint8_t dat=0,dat_r=f(i);
dat |= ((dat_r&0x80)?0x30:0);
dat |= ((dat_r&0x40)?0x03:0);
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x20)?0x30:0);
dat |= ((dat_r&0x10)?0x03:0);
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x08)?0x30:0);
dat |= ((dat_r&0x04)?0x03:0);
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x02)?0x30:0);
dat |= ((dat_r&0x01)?0x03:0);
guy_epdParam(dat);
#ifdef READGUY_583A_DUAL_BUFFER
buf_2nd[i]=dat_r;
}
}
else{
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){ //fill 0x03 for test
//guy_epdParam(0x03); //for data test
uint8_t dat=0,dat_r=f(i);
dat |= ((dat_r&0x80)?((buf_2nd[i]&0x80)?0x40:0x30):((buf_2nd[i]&0x80)?0x00:0x50));
//0x3?黑->白色, 0x0?白->黑色 0x4? 白->白色 0x5? 黑->黑色
dat |= ((dat_r&0x40)?((buf_2nd[i]&0x40)?0x4:0x3):((buf_2nd[i]&0x40)?0x0:0x5));
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x20)?((buf_2nd[i]&0x20)?0x40:0x30):((buf_2nd[i]&0x20)?0x00:0x50));
dat |= ((dat_r&0x10)?((buf_2nd[i]&0x10)?0x4:0x3):((buf_2nd[i]&0x10)?0x0:0x5));
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x8)?((buf_2nd[i]&0x8)?0x40:0x30):((buf_2nd[i]&0x8)?0x00:0x50));
dat |= ((dat_r&0x4)?((buf_2nd[i]&0x4)?0x4:0x3):((buf_2nd[i]&0x4)?0x0:0x5));
guy_epdParam(dat);
dat&=0;
dat |= ((dat_r&0x2)?((buf_2nd[i]&0x2)?0x40:0x30):((buf_2nd[i]&0x2)?0x00:0x50));
dat |= ((dat_r&0x1)?((buf_2nd[i]&0x1)?0x4:0x3):((buf_2nd[i]&0x1)?0x0:0x5));
guy_epdParam(dat);
buf_2nd[i]=dat_r;
}
#endif
}
}
void drv::drv_init(){ //初始化屏幕
epdFull=1;
epd_PowerOn=0;
}
void drv::drv_fullpart(bool part){ //初始化慢刷/快刷功能
if(lastRefresh) return;
if(!epd_PowerOn) part=0;
epdFull=!part;
if(epdFull) iLut=15;
}
void drv::drv_setDepth(uint8_t i){
if(!epd_PowerOn) return; //不支持切换到快刷的情形
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
BeginTransfer();
if(epdFull){
if(!epd_PowerOn){
epdFull=0; //发送快刷的lut
epd_init();
epdFull=1; //发送快刷的lut
guy_epdCmd(0x04); //power on
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
guy_epdCmd(0x10);
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x33
guy_epdParam(0x33);
}
epd_PowerOn=1; //设定为已上电
}
else{ //full refresh need power on
guy_epdCmd(0x04); //power on
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
}
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test
}
guy_epdCmd(0x92);
epd_init();
//epd_init(); //repeat call in GxEPD2
epd_sendWriter(f); //write image data
}
else{
epd_init();
//Power on fx
guy_epdCmd(0x04);
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
epd_sendZoneInfo();
epd_sendWriter(f);
guy_epdCmd(0x92);
epd_sendZoneInfo();
}
guy_epdCmd(0x12); //开始刷屏
EndTransfer();
lastRefresh=millis();
}
if(m&2){//stage 2
int ms=millis()-lastRefresh;
Serial.printf("epdFull? %d, epd_PowerOn? %d \n",epdFull,epd_PowerOn);
int u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(ms-u); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
BeginTransfer();
if(epdFull){
epdFull=0; //发送快刷的lut
epd_init(); //repeat init in part mode
epdFull=1; //发送快刷的lut
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test
}
guy_epdCmd(0x02); //power off for test...
//guy_epdBusy(-30);
}
else{
guy_epdCmd(0x92);
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data 显示数据
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test:全白
}
guy_epdCmd(0x92);
}
EndTransfer();
}
/* test code , with stageless ------------------------------------------------------
if(epdFull){ //慢刷
BeginTransfer();
if(!epd_PowerOn){
epdFull=0; //发送快刷的lut
epd_init();
epdFull=1; //发送快刷的lut
guy_epdCmd(0x04); //power on
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
guy_epdCmd(0x10);
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x33
guy_epdParam(0x33);
}
epd_PowerOn=1; //设定为已上电
}
else{ //full refresh need power on
guy_epdCmd(0x04); //power on
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
}
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test
}
guy_epdCmd(0x92);
epd_init();
//epd_init(); //repeat call in GxEPD2
epd_sendWriter(f); //write image data
guy_epdCmd(0x12);
EndTransfer();
guy_epdBusy(-4000);
BeginTransfer();
epdFull=0; //发送快刷的lut
epd_init(); //repeat init in part mode
epdFull=1; //发送快刷的lut
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test
}
guy_epdCmd(0x02); //power off for test...
EndTransfer();
//guy_epdBusy(-30);
}
else{ //partmode
BeginTransfer();
epd_init();
//Power on fx
guy_epdCmd(0x04);
EndTransfer();
guy_epdBusy(-60);
BeginTransfer();
epd_sendZoneInfo();
epd_sendWriter(f);
guy_epdCmd(0x92);
epd_sendZoneInfo();
guy_epdCmd(0x12); //快刷
EndTransfer();
guy_epdBusy(-1000); //1秒钟刷屏时间
BeginTransfer();
guy_epdCmd(0x92);
epd_sendZoneInfo();
guy_epdCmd(0x10); //Then write image data 显示数据
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
guy_epdParam(0x33); //for test:全白
}
guy_epdCmd(0x92);
EndTransfer();
}
// test code , with stageless ------------------------------------------------------ */
}
void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
if(step==1) drv_fullpart(1);//初始阶段,完成准备工作 //设置为快刷模式
greyscalingHighQuality=16; //开启高品质灰度模式
iLut=step;
drv_dispWriter(f);
//DelayMs(10); //未知原因()
if(step==15) greyscalingHighQuality=0;//初始阶段,完成准备工作 //设置为快刷模式
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
guy_epdCmd(0x07); // deep sleep
guy_epdParam(0xA5); // check code
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,92 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_583A.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 583A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 583A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD583A_H_FILE) && (defined(READGUY_DEV_583A)))
#define _GUY_EPD583A_H_FILE
namespace guydev_583A{
constexpr int GUY_D_WIDTH =600; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =448; //驱动屏幕高度
constexpr int slowRefTime =1600; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =560; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
#ifdef READGUY_583A_DUAL_BUFFER
drv();
virtual ~drv();
#endif
int drv_ID() const { return READGUY_DEV_583A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return (_quality&1)?16:-16; } //暂不支持灰度功能移植
void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
uint8_t greyscalingHighQuality = 0;
static const unsigned char *luts[10];
static const unsigned char *luts_fast[10];
static const unsigned char lut_20_LUTC[];
static const unsigned char lut_20_LUTCFAST[];
static const unsigned char lut_21_LUTB[];
static const unsigned char lut_21_LUTBFAST[];
static const unsigned char lut_22_LUTW[];
static const unsigned char lut_22_LUTWFAST[];
static const unsigned char lut_23_LUTG1[];
static const unsigned char lut_24_LUTG2[];
static const unsigned char lut_25_LUTR0[];
static const unsigned char lut_26_LUTR1[];
static const unsigned char lut_27_LUTR2[];
static const unsigned char lut_28_LUTR3[];
static const unsigned char lut_29_LUTXON[];
static const unsigned char customGrey[];
void sendLut(int lutid);
void epd_init();
void epd_sendZoneInfo();
void epd_sendWriter(std::function<uint8_t(int)> f);
#ifdef READGUY_583A_DUAL_BUFFER
uint8_t *buf_2nd=nullptr; //second Buffer for luts
#endif
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,75 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_583B.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 583B 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 583B 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_583B.h"
#ifdef READGUY_DEV_583B
namespace guydev_583B{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,63 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_583B.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 583B 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 583B 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD583B_H_FILE) && (defined(READGUY_DEV_583B)))
#define _GUY_EPD583B_H_FILE
namespace guydev_583B{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_583B; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,75 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_750A.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 源代码模板
* 使用前, 先查找替换 750A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 750A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "guy_750A.h"
#ifdef READGUY_DEV_750A
namespace guydev_750A{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::drv_init(){ //初始化屏幕
//add driver code...
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(lastRefresh) return;
//add driver code...
}
void drv::drv_setDepth(uint8_t i){
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(m&1){//stage 1
if(lastRefresh) drv_dispWriter(f,2);
//add driver code...
lastRefresh=millis();
}
if(m&2){//stage 2
uint32_t ms=millis()-lastRefresh;
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
lastRefresh=0;
//add driver code...
}
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
//add driver code...
}
epd_PowerOn = 0;
epdFull = 1; //强制设置为慢刷新模式
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,63 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_750A.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 墨水屏 驱动库函数 头文件模板
* 使用前, 先查找替换 750A 改为你需要的驱动名称
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
* 此时需要将 750A 替换为300A.
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
* 最后把这个brief替换掉
* @version 1.0
* @date 2023-11-11
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../guy_epdbase.h"
#if (!defined(_GUY_EPD750A_H_FILE) && (defined(READGUY_DEV_750A)))
#define _GUY_EPD750A_H_FILE
namespace guydev_750A{
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
class drv : public readguyEpdBase {
public:
int drv_ID() const { return READGUY_DEV_750A; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t iLut=15; //颜色深度
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -44,7 +44,7 @@
#define READGUY_DEV_154A 0 //1.54寸标准, 甘草酸不酸使用的1.54默认屏幕型号. 1.54汉朔价签也选这个
#define READGUY_DEV_154B 1 //1.54寸Lilygo, lilygo的1.54触摸和1.54背光墨水屏. GDEH0154D67
#define READGUY_DEV_213A 2 //2.13寸汉朔价签, 价格便宜, 兼容性好. 夏襄居士单词卡用 GDE0213B1
#define READGUY_DEV_213B 3 //2.13寸三色, 分辨率低212x104, 部分价签也用这个屏 易老化
#define READGUY_DEV_213B 3 //2.13寸, 分辨率低212x104, 部分2.13驱动不了的情况下用这个屏驱动
#define READGUY_DEV_266A 4 //2.66寸Vusion价签, 黑白双色.
#define READGUY_DEV_270B 5 //2.7寸佳显触摸墨水屏, 佳显官方店有售: 2.7寸触摸墨水屏.
#define READGUY_DEV_290A 6 //2.9寸A01, 甘草酸不酸2.9寸A01型号. 显示性能一般
@@ -53,6 +53,22 @@
#define READGUY_DEV_420A 9 //4.2寸HINK黑白价签, 汉朔价签, 汉朔三色价签通用. 速度快, 但效果一般
#define READGUY_DEV_420B 10 //4.2寸WF丝印, 部分价签也用此型号屏, 排线有WF开头的丝印
#define MEPD_DEBUG_DISPLAY 11 //使用LCD显示屏幕来debug. 前往ctg_stack_c_defines.h修改兼容的屏幕.
#define READGUY_DEV_213B3C 12 //2.13寸三色, 分辨率低212x104, 部分价签也用这个屏 易老化
#define READGUY_DEV_266A3C 13 //2.66寸三色. 驱动只能支持黑白色, 分辨率 296x152,
//#define READGUY_DEV_154C 14 //(即将推出) 1.54寸M09墨水屏 (M5Stack Core-Ink 同款; GDEW0154M09)
//#define READGUY_DEV_370B 15 //(即将推出) 3.7寸低DPI墨水屏, 分辨率416*240, b站 @叫我武哒哒 的项目用
//#define READGUY_DEV_426A 16 //(即将推出) 4.26寸高分辨率墨水屏, 800*480. GDEQ0426T82 支持硬件四灰
#define READGUY_DEV_583A 17 //(即将推出) 5.83寸墨水屏幕, 分辨率为600*448. 有黑白有三色
//#define READGUY_DEV_583B 18 //(即将推出) 5.83寸高分辨率, 640*480. GDEQ0583T31 只有黑白
//#define READGUY_DEV_750A 19 //(即将推出) 7.5 寸墨水屏幕, 800*480. 只有三色(买不到黑白)
//#define READGUY_DEV_1020A 20 //(即将推出) 10.2寸墨水屏GDEQ102T90, 芯片SSD1677. 黑白色分辨率960*640
//添加新屏幕型号 add displays here
#define EPD_DRIVERS_NUM_MAX 21 //此选项请不要取消注释掉, 有几个屏幕就写多少.
#define READGUY_583A_DUAL_BUFFER //对于单缓存的5.83屏幕, 启用双缓存支持
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -77,6 +77,7 @@ int readguyEpdBase::IfInit(SPIClass &c,int8_t cs,int8_t dc,int8_t rst,int8_t bus
DigitalWrite(DC_PIN,HIGH);
if(BUSY_PIN>=0) pinMode(BUSY_PIN, INPUT);
_spi = &c;
lastRefresh=0;
//_spi->begin();
//_spi->beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
@@ -159,10 +160,9 @@ void readguyEpdBase::Reset(uint32_t minTime)
}
//void readguyEpdBase::drv_draw16grey(const uint8_t *d16bit){ //不支持的话什么都不做
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o,
uint16_t fw, uint16_t fh){
#ifndef FLOYD_STEINBERG_DITHERING
static const uint8_t bayer_tab [64]={
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,int o,
int32_t fw0, int32_t fh){
static const PROGMEM uint8_t bayer_tab [64]={
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
@@ -172,26 +172,25 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
#endif
if(!fw) fw=spr.width();
if(!fh) fh=spr.height();
if((!fw) || (!fh)) return;
if(!fw0) fw0=spr.width();
if(!fh) fh=spr.height();
if((!fw0) || (!fh)) return;
int32_t fw=(fw0>0?std::min(fw0,sprbase.width()):-fw0);
fw0=std::abs(fw0); //无视缩放优化, 0~3:常规的三种渲染模式, 4~7: 无视缩放优化
if(o==0 || o==1){
readBuff = new uint16_t[spr.width()];
#ifdef FLOYD_STEINBERG_DITHERING
floyd_tab[0] = new int16_t [fw];
floyd_tab[1] = new int16_t [fw];
for(int j=0;j<fw;j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
#endif
writeBuff = new uint8_t[(fw+7)>>3];
}
sprbase.fillRect(x,y,fw,fh,1);
for(int32_t i=y;i<(int32_t)fh+y;i++){
spr.readRect(0,(i-y)*spr.height()/fh,spr.width(),1,readBuff);
#ifdef FLOYD_STEINBERG_DITHERING
uint_fast8_t buff8bit=0;
spr.readRect(0,(i-y)*spr.height()/fh,spr.width(),1,readBuff);
if(_quality&2){
for(int32_t j=0;j<fw;j++){
int gv=greysc(readBuff[j*spr.width()/fw]);
int gv=greysc(readBuff[j*spr.width()/fw0]);
int32_t flodelta = floyd_tab[i&1][j]+(int32_t)((gv<<8)|gv);
if(flodelta>=0x8000) {
//spr.drawPixel(j,i,1);
@@ -218,39 +217,39 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
{ floyd_tab[!(i&1)][j+1] += (flodelta )>>4; }
}
for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
#else
for(int32_t j=0;j<w;j++){
uint_fast8_t buff8bit=0;
for(uint_fast8_t b=0;b<8;b++)
buff8bit |= (bayer_tab[(b<<3)|(i&7)]<(greysc(readBuff[j*spr.width()/fw])>>2))<<(7-b);
writeBuff[j]=buff8bit;
}
#endif
else{
for(int32_t j=0;j<((fw+7)>>3);j++){
buff8bit=0;
for(uint_fast8_t b=0;b<8;b++)
buff8bit |= ((pgm_read_byte(bayer_tab+((b<<3)|(i&7)))<<2)+2
<greysc(readBuff[((j<<3)+b)*spr.width()/fw0]))<<(7-b);
writeBuff[j]=buff8bit;
}
}
sprbase.drawBitmap(x,i,writeBuff,fw,1,1,0);
}
//_display((const uint8_t*)sprbase.getBuffer()); //显示
if(o==0 || o==3){
delete []readBuff;
delete []writeBuff;
#ifdef FLOYD_STEINBERG_DITHERING
delete [] floyd_tab[0] ;
delete [] floyd_tab[1] ;
#endif
}
}
//不支持的话使用单色抖动刷屏
void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,
uint16_t fw, uint16_t fh){
void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,
int32_t fw0, int32_t fh){
//Serial.println("drv_draw16grey fx");
if(!fw) fw=spr.width();
if(!fh) fh=spr.height();
if((!fw) || (!fh)) return;
if(!fw0) fw0=spr.width();
if(!fh) fh=spr.height();
if((!fw0) || (!fh)) return;
int32_t fw=(fw0>0?std::min(fw0,sprbase.width()):-fw0);
fw0=std::abs(fw0); //无视缩放优化, 0~3:常规的三种渲染模式, 4~7: 无视缩放优化
readBuff = new uint16_t[spr.width()];
if(_quality&2){
#ifdef FLOYD_DITHERING_16GREY
floyd_tab[0] = new int16_t [fw];
floyd_tab[1] = new int16_t [fw];
#endif
}
writeBuff = new uint8_t[(fw+7)>>3];
sprbase.fillRect(x,y,fw,fh,1);
@@ -260,18 +259,15 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
drv_dispWriter(FILL_WHITE);
drv_fullpart(1);
for(uint_fast8_t k=1;k<16;k++){ //亮度为15的不用绘制,因为本来就是白色
#ifdef FLOYD_DITHERING_16GREY
if(_quality&2) for(int j=0;j<fw;j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
#endif
for(int i=y;i<(int32_t)fh+y;i++){
uint_fast8_t buff8bit=0;
spr.readRect(0,(i-y)*spr.height()/fh,spr.width(),1,readBuff);
for(int32_t j=0;j<fw;j++){
//for(uint_fast8_t b=0;b<8;b++){
#ifdef FLOYD_DITHERING_16GREY
uint_fast8_t cg=0;
if(_quality&2){
int gv=greysc(readBuff[j*spr.width()/fw]);
int gv=greysc(readBuff[j*spr.width()/fw0]);
int32_t fd = floyd_tab[i&1][j]+((gv<<8)|gv);
while(fd>=0x800) {
cg++;
@@ -283,10 +279,8 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
{ floyd_tab[!(i&1)][j ] += (fd*5)>>4; }
if(j!=fw-1) { floyd_tab[!(i&1)][j+1] += (fd )>>4; }
}
else{ cg=greysc(readBuff[j*spr.width()/fw])>>4; }
#else
uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw])>>4;
#endif
else{ cg=greysc(readBuff[j*spr.width()/fw0])>>4; }
//uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw0])>>4;
if(negativeOrder)
buff8bit |= (cg<k)<<((~j)&7);
else{
@@ -298,11 +292,9 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
buff8bit=0;
}
//}
//sprbase.drawPixel(x+j,i,(greysc(readBuff[j*spr.width()/fw])/16)==(15-k));
//sprbase.drawPixel(x+j,i,(greysc(readBuff[j*spr.width()/fw0])/16)==(15-k));
}
#ifdef FLOYD_DITHERING_16GREY
if(_quality&2) for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
#endif
sprbase.drawBitmap(x,i,writeBuff,fw,1,1,0);
}
drv_draw16grey_step((const uint8_t*)sprbase.getBuffer(),k); //使用灰度显示函数
@@ -310,10 +302,8 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
delete []readBuff;
delete []writeBuff;
if(_quality&2){
#ifdef FLOYD_DITHERING_16GREY
delete [] floyd_tab[0] ;
delete [] floyd_tab[1] ;
#endif
}
} /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -36,7 +36,6 @@
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include "guy_epaper_config.h"
#define EPD_DRIVERS_NUM_MAX 12 //此选项请不要取消注释掉
#define FILL_WHITE ([](int)->uint8_t{return 0xff;})
#define FILL_BLACK ([](int)->uint8_t{return 0x00;})
@@ -49,15 +48,14 @@ protected:
int8_t CS_PIN ;
int8_t BUSY_PIN;
uint8_t in_trans=0;
uint8_t _quality=2; //灰度显示品质 0(默认)-高品质 1-低品质 部分屏幕支持高品质的连续刷灰度.
uint8_t _quality=2;//灰度显示品质 默认2 0,2-高品质 1,3-低品质高兼容性. 0,1使用bayer灰度二值表 2,3使用floyd算法
#ifdef MEPD_DEBUG_WAVE
uint16_t dat_combo = 0; //dc引脚状态 0 command, 1 data
int dat_combo = 0; //dc引脚状态 0 command, 1 data
#endif
uint16_t *readBuff;// = new uint16_t[spr.width()];
uint8_t *writeBuff;// = new uint8_t[w];
#if (defined(FLOYD_DITHERING_16GREY) || defined(FLOYD_STEINBERG_DITHERING))
int16_t *floyd_tab[2];
#endif
uint32_t lastRefresh;
public:
readguyEpdBase(void);
@@ -82,25 +80,27 @@ public:
virtual int drv_ID() const =0; //返回驱动代号
virtual void drv_init()=0; //初始化屏幕
virtual void drv_fullpart(bool part)=0; //初始化慢刷功能
void _display(const uint8_t *d){ drv_dispWriter([&](int n)->uint8_t{return d[n];}); }
virtual void drv_dispWriter(std::function<uint8_t(int)>)=0; //按照显示函数刷新
void drv_color(uint8_t c){ drv_dispWriter([=](int)->uint8_t{return c;}); } //单色刷新
void _display(const uint8_t *d,uint8_t m=3){ drv_dispWriter([&](int n)->uint8_t{return d[n];},m); }
virtual void drv_dispWriter(std::function<uint8_t(int)>,uint8_t m=3)=0; //按照显示函数刷新
void drv_color(uint8_t c,uint8_t m=3){ drv_dispWriter([=](int)->uint8_t{return c;},m); } //单色刷新
virtual void drv_sleep() =0; //开始屏幕睡眠
virtual int drv_width() const=0; //返回显示区域宽度, 即使旋转了也不能影响此函数输出
virtual int drv_height()const=0; //返回显示区域高度, 即使旋转了也不能影响此函数输出
virtual int drv_supportGreyscaling() const { return 0; }
virtual void drv_setDepth(uint8_t i){} //设置显示颜色深度, 不支持的话什么都不做
virtual void drv_setDepth(uint8_t i){ (void)i; } //设置显示颜色深度, 不支持的话什么都不做
/** @brief 获取某一像素颜色, 并转化为256阶灰度
* @param x, y 坐标
* @param gamma_on 是否对灰度值进行gamma校正(速度慢)
* @return uint32_t 颜色的灰度值
*/
IRAM_ATTR static int greysc(int c){return(((c>>3)&0x1F)*79+(((c<<3)+(c>>13))&0x3F)*76+((c>>8)&0x1F)*30)>>5;}
void drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o=0,
uint16_t fw=0, uint16_t fh=0); //分步完成灰度刷新
void drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,
uint16_t fw=0, uint16_t fh=0);//省内存方式
/// @brief 显示sprite图像, 使用floyd算法
/// @param o 无视缩放优化, 0~3:分步的三种渲染模式, 0完整 1开始 2中间 3结束
void drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,int o=0,
int32_t fw0=0, int32_t fh=0); //分步完成灰度刷新
void drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,
int32_t fw0=0, int32_t fh=0);//省内存方式
void drv_draw16grey_step(const uint8_t *buf, int step){ //分步完成灰度刷新
drv_draw16grey_step([&](int n)->uint8_t{return buf[n];},step);
}
@@ -115,8 +115,6 @@ public:
#ifdef MEPD_DEBUG_DISPLAY
friend class LGFX;
#endif
private:
int16_t guy_width=0,guy_height=0;
};
#endif /* END OF FILE. ReadGuy project.

View File

@@ -73,7 +73,7 @@
//#define _DEFINA_SD_CS_PIN 0
// * for NodeMcu ctg stack LCF board
#define WHITE_GAP 8
#define WHITE_GAP 2
#ifdef ESP8266
#define DISPLAY_TYPE_ST7789_240320 //2.0寸的ST7789 IPS TFT模块

View File

@@ -38,9 +38,11 @@ void drv::drv_init(){
ips.fillScreen(0xffff);
}
void drv::drv_fullpart(bool part){
if(lastRefresh) return;
partMode=part;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
if(!(m&1)) return; //stage 1
uint16_t dat[8];
unsigned short xbits=(drv_width()+7)/8;
if(partMode==0){
@@ -79,7 +81,6 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
}
}
}
yield();
}
}
void drv::drv_sleep() {}

View File

@@ -41,7 +41,7 @@ public:
int drv_ID() const { return MEPD_DEBUG_DISPLAY; }
void drv_init(); //初始化屏幕
void drv_fullpart(bool part); //切换慢刷/快刷功能
void drv_dispWriter(std::function<uint8_t(int)> f); //单色刷新
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //单色刷新
void drv_sleep() ; //开始屏幕睡眠
int drv_width() const { return ips.width()-2*WHITE_GAP; } //返回显示区域宽度
int drv_height() const{ return ips.height()-2*WHITE_GAP; } //返回显示区域高度

View File

@@ -6,7 +6,7 @@
* @file guy_version.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief readguy 版本控制文件.
* @version 1.0
* @version 1.3.2
* @date 2023-09-21
* @attention
@@ -41,9 +41,9 @@
//另外, 在提交新版本之前, 不要忘记在github上创建release, 否则Arduino IDE会读不到
#define READGUY_V_MAJOR 1
#define READGUY_V_MINOR 3
#define READGUY_V_PATCH 0
#define READGUY_V_PATCH 5
#define READGUY_VERSION_VAL (READGUY_V_MAJOR*1000+READGUY_V_MINOR*100+READGUY_V_PATCH*10)
#define READGUY_VERSION "1.3.0"
#define READGUY_VERSION "1.3.5"
#ifdef ESP8266
#define _READGUY_PLATFORM "ESP8266"

View File

@@ -59,7 +59,7 @@ static const PROGMEM char args_name[23][8]={
static const char *NAME_guyDev266=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_213B
static const PROGMEM char NAME_guyDev213M21[]="2.13寸三色";
static const PROGMEM char NAME_guyDev213M21[]="2.13寸低分辨率版";
#else
static const char *NAME_guyDev213M21=NOT_SUPPORTED;
#endif
@@ -98,6 +98,53 @@ static const PROGMEM char args_name[23][8]={
#else
static const char *NAME_guyDev270_V2=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_213B3C
static const PROGMEM char NAME_guyDev213B3C[]="2.13寸三色";
#else
static const char *NAME_guyDev213B3C=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_266A3C
static const PROGMEM char NAME_guyDev266A3C[]="2.66寸三色价签";
#else
static const char *NAME_guyDev266A3C=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_154C
static const PROGMEM char NAME_guyDev154M5CoreInk[]="1.54寸Core.Ink";
#else
static const char *NAME_guyDev154M5CoreInk=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_370B
static const PROGMEM char NAME_guyDev370LoRes[]="3.7寸低分版本416x240";
#else
static const char *NAME_guyDev370LoRes=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_426A
static const PROGMEM char NAME_guyDev426HiRes[]="4.26寸GDEQ0426T82高分辨率";
#else
static const char *NAME_guyDev426HiRes=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_583A
static const PROGMEM char NAME_guyDev583Normal[]="5.83寸黑白/三色价签";
#else
static const char *NAME_guyDev583Normal=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_583B
static const PROGMEM char NAME_guyDev583HiResBW[]="5.83寸高分辨率版本";
#else
static const char *NAME_guyDev583HiResBW=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_750A
static const PROGMEM char NAME_guyDev750A3C[]="7.5寸三色价签";
#else
static const char *NAME_guyDev750A3C=NOT_SUPPORTED;
#endif
#ifdef READGUY_DEV_1020A
static const PROGMEM char NAME_guyDev1020BW[]="10.2寸黑白";
#else
static const char *NAME_guyDev1020BW=NOT_SUPPORTED;
#endif
//添加新屏幕型号 add displays here
const char *ReadguyDriver::epd_drivers_list[EPD_DRIVERS_NUM_MAX]={
NAME_guyDev154, //此处的顺序必须和 guy_epaper_config.h 里面的一样
NAME_guyDev154_V2,
@@ -110,7 +157,18 @@ const char *ReadguyDriver::epd_drivers_list[EPD_DRIVERS_NUM_MAX]={
NAME_guyDev370,
NAME_guyDev420Hink,
NAME_guyDev420WF,
NAME_epdLcd
NAME_epdLcd,
NAME_guyDev213B3C,
NAME_guyDev266A3C,
NAME_guyDev154M5CoreInk,
NAME_guyDev370LoRes,
NAME_guyDev426HiRes,
NAME_guyDev583Normal,
NAME_guyDev583HiResBW,
NAME_guyDev750A3C,
NAME_guyDev1020BW
//添加新屏幕型号 add displays here
};
//static const char *index_cn_html;
//static const uint8_t faviconData[1150];
@@ -191,7 +249,7 @@ bool ReadguyDriver::server_loop(){ //此时等待网页操作完成响应...
}
if(refFlag!=127) {
Serial.printf("randch: %d %c\n",randomch[refFlag],(char)(randomch[refFlag]));
drawChar((width()>>1)-46+refFlag*24,(height()>>1)-14,randomch[refFlag],true,false,4);
drawChar((guy_dev->drv_width()>>1)-46+refFlag*24,(guy_dev->drv_height()>>1)-14,randomch[refFlag],true,false,4);
guy_dev->drv_fullpart(1);
guy_dev->_display((const uint8_t*)getBuffer());
}
@@ -223,14 +281,18 @@ void ReadguyDriver::handleInitPost(){
READGUY_sd_ok=0;
#if defined(ESP8266)
//Esp8266无视SPI的设定, 固定为唯一的硬件SPI (D5=SCK, D6=MISO, D7=MOSI)
#ifdef READGUY_ENABLE_SD
SDFS.end();//关闭SD卡
#endif
btnTask.detach();
#else
#ifdef READGUY_ENABLE_SD
SD.end();//关闭SD卡
if(sd_spi != epd_spi) { //共线时, 不要删除SD
delete sd_spi;
sd_spi=nullptr;
}
#endif
vTaskDelete(btn_handle);
#endif
}
@@ -311,13 +373,14 @@ void ReadguyDriver::handleInitPost(){
setEpdDriver(); //尝试初始化屏幕
Serial.println(F("[Guy] Init details..."));
setTextSize(1);
drawCenterString(setSDcardDriver()?"SD Init OK!":"SD Init failed!",width()>>1,(height()>>1)+20);
drawCenterString(setSDcardDriver()?"SD Init OK!":"SD Init failed!",
guy_dev->drv_width()>>1,(guy_dev->drv_height()>>1)+20);
setButtonDriver(); //初始化按钮..
//} //尝试初始化按键, 调用后, 若SD卡初始化成功, READGUY_sd_ok的值会变成1
drawRect((width()>>1)-46 ,(height()>>1)-14,20,28,0);
drawRect((width()>>1)-46+24,(height()>>1)-14,20,28,0);
drawRect((width()>>1)-46+48,(height()>>1)-14,20,28,0);
drawRect((width()>>1)-46+72,(height()>>1)-14,20,28,0);
drawRect((guy_dev->drv_width()>>1)-46 ,(guy_dev->drv_height()>>1)-14,20,28,0);
drawRect((guy_dev->drv_width()>>1)-46+24,(guy_dev->drv_height()>>1)-14,20,28,0);
drawRect((guy_dev->drv_width()>>1)-46+48,(guy_dev->drv_height()>>1)-14,20,28,0);
drawRect((guy_dev->drv_width()>>1)-46+72,(guy_dev->drv_height()>>1)-14,20,28,0);
spibz++;
guy_dev->drv_fullpart(1);
guy_dev->_display((const uint8_t*)getBuffer());
@@ -337,7 +400,7 @@ void ReadguyDriver::handlePinSetup(){
args_name[15],args_name[17],args_name[19],args_name[21],args_name[12],args_name[13]
};
static const PROGMEM int dem_args_val[DRIVER_TEMPLATE_N][DRIVER_TEMPLATE_ARRAY_L]={
{ 6,15, 0, 2, 4, 5, 2, 3, 0,-1,-1,13,14},
{ 6,15, 0, 2, 4, 5, 2, 0, 3,-1,-1,13,14},
//{ 0,10, 9, 8, 7, 4, 3, 2, 3, 5, 6,SDA,SCL},
//{ 0,15, 4, 2, 5,-1, 1, 0,-1,-1,-1,-1,-1} //微雪官方例程板子不支持SD卡, 也不支持I2C. 按钮为boot按钮
};
@@ -453,12 +516,16 @@ void ReadguyDriver::handlePinSetup(){
#if defined(ESP8266)
for(int i=2;i<12;i++){
if(i>=6 && i<=8) continue;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
for(int i=2;i<12;i++){
#else
for(int i=0;i<12;i++){
#endif
s += F("<br/>");
#if defined(CONFIG_IDF_TARGET_ESP32C3)
if(i==7) {
i+=2; //优化ESP32C3的SPI配置体验 (C3只能共线)
s += F("(ESP32C3不支持SD卡独立SPI总线! SD_MOSI和SD_SCLK沿用EPDMOSI和EPDSCLK)<br/>");
}
#endif
#endif
s += FPSTR(args_name[i+2]);
s += F("<input type=\"number\" id=\"");
s += FPSTR(args_name[i+2]);
@@ -515,6 +582,7 @@ void ReadguyDriver::handleFinal(){
}
s+=F("<br/><hr/>"); //换行
}
#ifdef READGUY_ENABLE_SD
if(!READGUY_sd_ok) s+=F("SD卡不可用!!!<br/>");
#if (defined(ESP8266)) //此函数速度太慢了, 因此删掉不用了
/*else{
@@ -544,6 +612,7 @@ void ReadguyDriver::handleFinal(){
s+=(uint32_t)(SD.usedBytes()/1024);
s+=F("KB.<br/>");
}
#endif
#endif
s+=F("当前WiFi模式: ");
s+=(WiFi.getMode()==WIFI_STA)?F("正常联网模式"):F("AP配网模式");
@@ -644,7 +713,7 @@ const PROGMEM char ReadguyDriver::verify2_html[] =
"al\" method=\"POST\"><input type=\'text\' name=\'t_verify\' maxlength=\"6";
const PROGMEM char ReadguyDriver::verifybtn_html[3][200] = {
"一个按键, 操作可能比较繁琐, 但功能还都可以的.<br/>"
"点按: 下一个/向下翻页<br/>双击: 上一个/向上翻页<br/>三连击: 返回/切换输入法<br/>长按: 确定/选择",
"点按: 下一个/向下翻页<br/>双击: 确定/选择<br/>三连击: 返回/切换输入法<br/>长按: 上一个/向上翻页",
"两个按键, 操作可以满足需求.<br/>"
"按键1点按: 下一个/向下翻页<br/>按键1长按: 上一个/向上翻页<br/>按键2点按: 确定/选择<br/>按键2长按: 返回/切换输入法",
"三个按键, 操作非常流畅.<br/>"

View File

@@ -38,6 +38,36 @@ int8_t ReadguyDriver::pin_cmx=-1;
const PROGMEM char ReadguyDriver::projname[8] = "readguy";
const PROGMEM char ReadguyDriver::tagname[7] = "hwconf";
volatile uint8_t ReadguyDriver::spibz=0;
#ifndef DYNAMIC_PIN_SETTINGS
const int8_t ReadguyDriver::config_data[22] = {
127 , //READGUY_cali
READGUY_shareSpi ,
READGUY_epd_type ,// 对应的epd驱动程序代号, -1为未指定
//显示驱动部分, 显示默认使用vspi (vspi也是默认SPI库的通道)
READGUY_epd_mosi ,// 目标显示器的 MOSI 引脚
READGUY_epd_sclk ,// 目标显示器的 SCLK 引脚
READGUY_epd_cs ,// 目标显示器的 CS 引脚
READGUY_epd_dc ,// 目标显示器的 DC 引脚
READGUY_epd_rst ,// 目标显示器的 RST 引脚
READGUY_epd_busy ,// 目标显示器的 BUSY 引脚
//sd卡驱动部分, 默认使用hspi (sd卡建议用hspi)
READGUY_sd_miso ,// 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
READGUY_sd_mosi ,// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
READGUY_sd_sclk ,// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
READGUY_sd_cs ,// 目标sd卡的 CS 引脚.
READGUY_i2c_sda ,// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
READGUY_i2c_scl ,// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
//按键驱动部分, 为负代表高触发, 否则低触发,
//注意, 这里的io编号是加1的, 即 1或-1 代表 gpio0 的低触发/高触发
READGUY_btn1 ,
READGUY_btn2 ,
READGUY_btn3 ,
READGUY_bl_pin ,//前置光接口引脚IO
READGUY_rtc_type ,//使用的RTC型号(待定, 还没用上)
0 ,//READGUY_sd_ok SD卡已经成功初始化
0 //READGUY_buttons 按钮个数, 0-3都有可能
};
#endif
#ifndef ESP8266
SPIClass *ReadguyDriver::sd_spi =nullptr;
SPIClass *ReadguyDriver::epd_spi=nullptr;
@@ -49,7 +79,7 @@ ReadguyDriver::ReadguyDriver(){
READGUY_sd_ok = 0; //初始默认SD卡未成功初始化
READGUY_buttons = 0; //初始情况下没有按钮
} //WiFiSet: 是否保持AP服务器一直处于打开状态
uint8_t ReadguyDriver::init(uint8_t WiFiSet,bool initepd/* ,int g_width,int g_height */){
uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd, bool initSD){
if(READGUY_cali==127) //已经初始化过了一次了, 为了防止里面一些volatile的东西出现问题....还是退出吧
return 0;
#ifdef DYNAMIC_PIN_SETTINGS
@@ -79,16 +109,21 @@ uint8_t ReadguyDriver::init(uint8_t WiFiSet,bool initepd/* ,int g_width,int g_he
else if(WiFiSet==1) ap_setup();
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
setSDcardDriver();
if(initSD) setSDcardDriver();
setButtonDriver();
}
#endif
nvs_deinit();
#else
nvs_init();
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
setSDcardDriver();
if(initSD) setSDcardDriver();
setButtonDriver();
if(!nvs_read()){
nvs_write(); //全部成功之后, 写入引脚信息到NVS.
}
nvs_deinit();
#endif
Serial.println(F("[Guy init] init done."));
READGUY_cali=127;
@@ -111,47 +146,124 @@ uint8_t ReadguyDriver::checkEpdDriver(){
#endif
if(guy_dev != nullptr && READGUY_epd_type!=guy_dev->drv_ID()) delete guy_dev; //释放多余的内存
//Serial.printf("initing epd %s...\n",epd_drivers_list[READGUY_epd_type]);
#ifdef DYNAMIC_PIN_SETTINGS
switch (READGUY_epd_type){
#ifdef READGUY_DEV_154A
case READGUY_DEV_154A: guy_dev = new guydev_154A_290A ::dev154A; break; //适用于一般的价签黑白屏
case READGUY_DEV_154A: guy_dev = new guydev_154A_290A ::dev154A; break; //适用于一般的价签黑白屏
#endif
#ifdef READGUY_DEV_154B
case READGUY_DEV_154B: guy_dev = new guydev_154B_270B_290B ::dev154B; break; //适用于
case READGUY_DEV_154B: guy_dev = new guydev_154B_270B_290B ::dev154B; break; //适用于
#endif
#ifdef READGUY_DEV_213A
case READGUY_DEV_213A: guy_dev = new guydev_213A ::drv; break;
case READGUY_DEV_213A: guy_dev = new guydev_213A ::drv; break;
#endif
#ifdef READGUY_DEV_266A
case READGUY_DEV_266A: guy_dev = new guydev_213B_266A ::dev266A; break;
case READGUY_DEV_266A: guy_dev = new guydev_213B_266A ::dev266A; break;
#endif
#ifdef READGUY_DEV_213B
case READGUY_DEV_213B: guy_dev = new guydev_213B_266A ::dev213B; break;
case READGUY_DEV_213B: guy_dev = new guydev_213B_266A ::dev213B; break;
#endif
#ifdef READGUY_DEV_290A
case READGUY_DEV_290A: guy_dev = new guydev_154A_290A ::dev290A; break;
case READGUY_DEV_290A: guy_dev = new guydev_154A_290A ::dev290A; break;
#endif
#ifdef READGUY_DEV_290B
case READGUY_DEV_290B: guy_dev = new guydev_154B_270B_290B ::dev290B; break;
case READGUY_DEV_290B: guy_dev = new guydev_154B_270B_290B ::dev290B; break;
#endif
#ifdef READGUY_DEV_420A
case READGUY_DEV_420A: guy_dev = new guydev_420A ::drv; break;
case READGUY_DEV_420A: guy_dev = new guydev_420A ::drv; break;
#endif
#ifdef READGUY_DEV_420B
case READGUY_DEV_420B: guy_dev = new guydev_420B ::drv; break;
case READGUY_DEV_420B: guy_dev = new guydev_420B ::drv; break;
#endif
#ifdef READGUY_DEV_370A
case READGUY_DEV_370A: guy_dev = new guydev_370A ::drv; break;
case READGUY_DEV_370A: guy_dev = new guydev_370A ::drv; break;
#endif
#ifdef MEPD_DEBUG_DISPLAY
case MEPD_DEBUG_DISPLAY:guy_dev = new EpdLcdDebug ::drv; break;
case MEPD_DEBUG_DISPLAY: guy_dev = new EpdLcdDebug ::drv; break;
#endif
#ifdef READGUY_DEV_270B
case READGUY_DEV_270B: guy_dev = new guydev_154B_270B_290B ::dev270B; break;
case READGUY_DEV_270B: guy_dev = new guydev_154B_270B_290B ::dev270B; break;
#endif
#ifdef READGUY_DEV_213B3C
case READGUY_DEV_213B3C: guy_dev = new guydev_213B_266A ::dev213B3C; break;
#endif
#ifdef READGUY_DEV_266A3C
case READGUY_DEV_266A3C: guy_dev = new guydev_213B_266A ::dev266A3C; break;
#endif
#ifdef READGUY_DEV_154C
case READGUY_DEV_154C: guy_dev = new guydev_154C ::drv; break;
#endif
#ifdef READGUY_DEV_370B
case READGUY_DEV_370B: guy_dev = new guydev_370B ::drv; break;
#endif
#ifdef READGUY_DEV_426A
case READGUY_DEV_426A: guy_dev = new guydev_426A ::drv; break;
#endif
#ifdef READGUY_DEV_583A
case READGUY_DEV_583A: guy_dev = new guydev_583A ::drv; break;
#endif
#ifdef READGUY_DEV_583B
case READGUY_DEV_583B: guy_dev = new guydev_583B ::drv; break;
#endif
#ifdef READGUY_DEV_750A
case READGUY_DEV_750A: guy_dev = new guydev_750A ::drv; break;
#endif
#ifdef READGUY_DEV_1020A
case READGUY_DEV_1020A: guy_dev = new guydev_1020A ::drv; break;
#endif
//添加新屏幕型号 add displays here
default:
Serial.println(F("[GUY ERR] EPD DRIVER IC NOT SUPPORTED!\n"));
return 127;
}
#else
#if (defined(READGUY_DEV_154A) && (READGUY_epd_type==READGUY_DEV_154A))
guy_dev = new guydev_154A_290A ::dev154A; //适用于一般的价签黑白屏
#elif (defined(READGUY_DEV_154B) && (READGUY_epd_type==READGUY_DEV_154B))
guy_dev = new guydev_154B_270B_290B ::dev154B; //适用于
#elif (defined(READGUY_DEV_213A) && (READGUY_epd_type==READGUY_DEV_213A))
guy_dev = new guydev_213A ::drv;
#elif (defined(READGUY_DEV_266A) && (READGUY_epd_type==READGUY_DEV_266A))
guy_dev = new guydev_213B_266A ::dev266A;
#elif (defined(READGUY_DEV_213B) && (READGUY_epd_type==READGUY_DEV_213B))
guy_dev = new guydev_213B_266A ::dev213B;
#elif (defined(READGUY_DEV_290A) && (READGUY_epd_type==READGUY_DEV_290A))
guy_dev = new guydev_154A_290A ::dev290A;
#elif (defined(READGUY_DEV_290B) && (READGUY_epd_type==READGUY_DEV_290B))
guy_dev = new guydev_154B_270B_290B ::dev290B;
#elif (defined(READGUY_DEV_420A) && (READGUY_epd_type==READGUY_DEV_420A))
guy_dev = new guydev_420A ::drv;
#elif (defined(READGUY_DEV_420B) && (READGUY_epd_type==READGUY_DEV_420B))
guy_dev = new guydev_420B ::drv;
#elif (defined(READGUY_DEV_370A) && (READGUY_epd_type==READGUY_DEV_370A))
guy_dev = new guydev_370A ::drv;
#elif (defined(MEPD_DEBUG_DISPLAY) && (READGUY_epd_type==MEPD_DEBUG_DISPLAY))
guy_dev = new EpdLcdDebug ::drv;
#elif (defined(READGUY_DEV_270B) && (READGUY_epd_type==READGUY_DEV_270B))
guy_dev = new guydev_154B_270B_290B ::dev270B;
#elif (defined(READGUY_DEV_213B3C) && (READGUY_epd_type==READGUY_DEV_213B3C))
guy_dev = new guydev_213B_266A ::dev213B3C;
#elif (defined(READGUY_DEV_266A3C) && (READGUY_epd_type==READGUY_DEV_266A3C))
guy_dev = new guydev_213B_266A ::dev266B3C;
#elif (defined(READGUY_DEV_154C) && (READGUY_epd_type==READGUY_DEV_154C))
guy_dev = new guydev_154C ::drv;
#elif (defined(READGUY_DEV_370B) && (READGUY_epd_type==READGUY_DEV_370B))
guy_dev = new guydev_370B ::drv;
#elif (defined(READGUY_DEV_426A) && (READGUY_epd_type==READGUY_DEV_426A))
guy_dev = new guydev_426A ::drv;
#elif (defined(READGUY_DEV_583A) && (READGUY_epd_type==READGUY_DEV_583A))
guy_dev = new guydev_583A ::drv;
#elif (defined(READGUY_DEV_583B) && (READGUY_epd_type==READGUY_DEV_583B))
guy_dev = new guydev_583B ::drv;
#elif (defined(READGUY_DEV_750A) && (READGUY_epd_type==READGUY_DEV_750A))
guy_dev = new guydev_750A ::drv;
#elif (defined(READGUY_DEV_1020A) && (READGUY_epd_type==READGUY_DEV_1020A))
guy_dev = new guydev_1020A ::drv;
#endif
//添加新屏幕型号 add displays here
#endif
#if (defined(ESP8266))
SPI.begin();
SPI.setFrequency(ESP8266_SPI_FREQUENCY); ///< 1MHz
@@ -172,7 +284,7 @@ uint8_t ReadguyDriver::checkEpdDriver(){
Serial.println(F("[Guy SPI] drvBase Init OK"));
return READGUY_epd_type;
}
void ReadguyDriver::setEpdDriver(bool initepd/* ,int g_width,int g_height */){
void ReadguyDriver::setEpdDriver(bool initepd, bool initGFX){
guy_dev->spi_tr_release = in_release;
guy_dev->spi_tr_press = in_press;
if(initepd) guy_dev->drv_init(); //初始化epd驱动层
@@ -180,23 +292,24 @@ void ReadguyDriver::setEpdDriver(bool initepd/* ,int g_width,int g_height */){
//else guy_width = guy_dev->drv_width(); //宽度必须是8的倍数, 但这个可以由GFX自动计算
//if(g_height) guy_height = g_height;
//else guy_height = guy_dev->drv_height();
Serial.println(F("[Guy EPD] EPD init OK"));
//以下依赖于你的图形驱动
setColorDepth(1); //单色模式
createPalette(); //初始化颜色系统
Serial.printf_P(PSTR("[Guy EPD] mono set: w: %d, h: %d\n"),guy_dev->drv_width(),guy_dev->drv_height());
//创建画布. 根据LovyanGFX的特性, 如果以前有画布会自动重新生成新画布
//此外, 即使画布宽度不是8的倍数(如2.13寸单色),也支持自动补全8的倍数 ( 250x122 => 250x128 )
//为了保证图片显示功能的正常使用, 高度也必须是8的倍数.
createSprite(guy_dev->drv_width(),(guy_dev->drv_height()+7)&0x7ffffff8);
//这里发现如果用自定义的内存分配方式会更好一些. 不会导致返回的height不对. 但是因为LovyanGFX库未更新 暂时不能这么用.
//setRotation(1); //旋转之后操作更方便
setRotation(0);
setFont(&fonts::Font0);
setCursor(0,0);
setTextColor(0);
fillScreen(1); //开始先全屏白色
if(initGFX){
setColorDepth(1); //单色模式
createPalette(); //初始化颜色系统
//创建画布. 根据LovyanGFX的特性, 如果以前有画布会自动重新生成新画布
//此外, 即使画布宽度不是8的倍数(如2.13寸单色),也支持自动补全8的倍数 ( 250x122 => 250x128 )
//为了保证图片显示功能的正常使用, 高度也必须是8的倍数.
createSprite(guy_dev->drv_width(),guy_dev->drv_height());
//这里发现如果用自定义的内存分配方式会更好一些. 不会导致返回的height不对. 但是因为LovyanGFX库未更新 暂时不能这么用.
setRotation(0); //默认的旋转方向就是0咯
setFont(&fonts::Font0);
setCursor(0,0);
setTextColor(0);
fillScreen(1); //开始先全屏白色
}
Serial.printf_P(PSTR("[Guy EPD] EPD init OK(%d): w: %d, h: %d\n"),guy_dev->drv_ID(),guy_dev->drv_width(),guy_dev->drv_height());
}
#ifdef READGUY_ENABLE_SD
bool ReadguyDriver::setSDcardDriver(){
/*重要信息: 有些引脚冲突是难以避免的, 比如8266 尤其需要重写这部分代码
对于esp32也要注意这个引脚是否是一个合法的引脚
@@ -237,6 +350,17 @@ bool ReadguyDriver::setSDcardDriver(){
}
return READGUY_sd_ok;
}
#else
bool ReadguyDriver::setSDcardDriver(){
READGUY_sd_ok=0;
#ifdef READGUY_USE_LITTLEFS
LittleFS.begin();
#else
SPIFFS.begin();
#endif
return false;
}
#endif
void ReadguyDriver::setButtonDriver(){
if(READGUY_btn1) { //初始化按键. 注意高电平触发的引脚在初始化时要设置为下拉
int8_t btn_pin=abs(READGUY_btn1)-1;
@@ -280,18 +404,21 @@ void ReadguyDriver::setButtonDriver(){
if(READGUY_btn1) btn_rd[0].begin(abs(READGUY_btn1)-1,rd_btn_f,(READGUY_btn1>0));
if(READGUY_btn2) btn_rd[1].begin(abs(READGUY_btn2)-1,rd_btn_f,(READGUY_btn2>0));
if(READGUY_btn3) btn_rd[2].begin(abs(READGUY_btn3)-1,rd_btn_f,(READGUY_btn3>0));
//if(READGUY_buttons==1){
btn_rd[0].setLongRepeatMode(1); //允许连按
//}
if(READGUY_buttons==2){
btn_rd[0].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
btn_rd[0].setLongRepeatMode(1);
//btn_rd[0].setLongRepeatMode(1); //双按键 选择按键 设置为允许连按
btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
btn_rd[1].setLongRepeatMode(0);
btn_rd[1].setLongRepeatMode(0); //双按键 确定按键 设置为不允许连按
}
else if(READGUY_buttons==3){
btn_rd[0].setLongPressMs(1); //不识别双击三击, 只有按一下或者长按, 并且开启连按
btn_rd[0].setLongRepeatMode(1);
btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
btn_rd[1].setLongRepeatMode(0);
btn_rd[2].setLongPressMs(1); //不识别双击三击, 只有按一下或者长按, 并且开启连按
btn_rd[0].long_press_ms = 20; //不识别双击三击, 只有按一下或者长按, 并且开启连按
//btn_rd[0].setLongRepeatMode(1);
//btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击 2024/2/25更新:需要支持连按适配拨轮
btn_rd[1].setLongRepeatMode(0); //三按键 确定按键 设置为不允许连按
btn_rd[2].long_press_ms = 20; //不识别双击三击, 只有按一下或者长按, 并且开启连按
btn_rd[2].setLongRepeatMode(1);
}
#ifdef ESP8266 //对于esp8266, 需要注册到ticker. 这是因为没freertos.
@@ -341,6 +468,7 @@ void ReadguyDriver::setButtonDriver(){
}
} //关于按键策略, 我们在此使用多个Button2的类, 然后在一个task共享变量来确定上一个按键状态
}
#ifdef READGUY_ENABLE_SD
fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
if(initSD==2 || (!READGUY_sd_ok && initSD)) setSDcardDriver();
if(READGUY_sd_ok){
@@ -356,6 +484,16 @@ fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
return SPIFFS;
#endif
}
#else
fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
(void)initSD; //avoid GCC warning
#ifdef READGUY_USE_LITTLEFS
return LittleFS;
#else
return SPIFFS;
#endif
}
#endif
void ReadguyDriver::setBright(int d){
if(currentBright>=0 && d>=0 && d<=255){
currentBright=d;
@@ -370,37 +508,46 @@ void ReadguyDriver::setBright(int d){
digitalWrite(READGUY_bl_pin,d?HIGH:LOW);
}
}
void ReadguyDriver::display(bool part){
void ReadguyDriver::display(uint8_t part){
//真的是我c++的盲区了啊....搜索了半天才找到可以这么玩的
//......可惜'dynamic_cast' not permitted with -fno-rtti
// static bool _part = 0; 记忆上次到底是full还是part, 注意启动时默认为full
if(READGUY_cali==127){
//in_press(); //暂停, 然后读取按键状态 spibz
guy_dev->drv_fullpart(part);
guy_dev->_display((const uint8_t*)getBuffer());
guy_dev->drv_fullpart(part&1);
guy_dev->_display((const uint8_t*)getBuffer(),((part>>1)?part>>1:3));
//in_release(); //恢复
}
}
void ReadguyDriver::display(std::function<uint8_t(int)> f, bool part){
void ReadguyDriver::displayBuffer(const uint8_t *buf, uint8_t part){
if(READGUY_cali==127){
//in_press(); //暂停, 然后读取按键状态 spibz
guy_dev->drv_fullpart(part);
guy_dev->drv_dispWriter(f);
guy_dev->drv_fullpart(part&1);
guy_dev->_display(buf,((part>>1)?part>>1:3));
//in_release(); //恢复
}
}
void ReadguyDriver::drawImage(LGFX_Sprite &base, LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw, uint16_t zoomh) {
void ReadguyDriver::display(std::function<uint8_t(int)> f, uint8_t part){
if(READGUY_cali==127){
//in_press(); //暂停, 然后读取按键状态 spibz
guy_dev->drv_fullpart(part&1);
guy_dev->drv_dispWriter(f,((part>>1)?part>>1:3));
//in_release(); //恢复
}
}
void ReadguyDriver::drawImage(LGFX_Sprite &base, LGFX_Sprite &spr,int32_t x,int32_t y,int32_t zoomw, int32_t zoomh) {
if(READGUY_cali==127) guy_dev->drv_drawImage(base, spr, x, y, 0, zoomw, zoomh);
}
void ReadguyDriver::drawImageStage(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint8_t stage,
uint8_t totalstage,uint16_t zoomw,uint16_t zoomh) {
void ReadguyDriver::drawImageStage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,uint8_t stage,
uint8_t totalstage,int32_t zoomw,int32_t zoomh) {
if(READGUY_cali!=127 || stage>=totalstage) return;
guy_dev->drv_drawImage(*this, spr, x, y, (totalstage<=1)?0:(stage==0?1:(stage==(totalstage-1)?3:2)),zoomw,zoomh);
//Serial.printf("stage: %d/%d\n",stage+1,totalstage);
guy_dev->drv_drawImage(sprbase, spr, x, y, (totalstage<=1)?0:(stage==0?1:(stage==(totalstage-1)?3:2)),zoomw,zoomh);
}
void ReadguyDriver::setDepth(uint8_t d){
if(READGUY_cali==127 && guy_dev->drv_supportGreyscaling()) guy_dev->drv_setDepth(d);
}
void ReadguyDriver::draw16grey(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw,uint16_t zoomh){
void ReadguyDriver::draw16grey(LGFX_Sprite &spr,int32_t x,int32_t y,int32_t zoomw,int32_t zoomh){
if(READGUY_cali!=127) return;
if(guy_dev->drv_supportGreyscaling() && (spr.getColorDepth()&0xff)>1)
return guy_dev->drv_draw16grey(*this,spr,x,y,zoomw,zoomh);
@@ -429,8 +576,7 @@ void ReadguyDriver::sleepEPD(){
if(READGUY_cali==127) guy_dev->drv_sleep();
}
#if (!defined(DYNAMIC_PIN_SETTINGS)) //do nothing here.
#elif (defined(INDEV_DEBUG))
#if (defined(INDEV_DEBUG))
void ReadguyDriver::nvs_init(){
}
void ReadguyDriver::nvs_deinit(){
@@ -450,12 +596,19 @@ void ReadguyDriver::nvs_deinit(){
}
bool ReadguyDriver::nvs_read(){
char s[8];
for(unsigned int i=0;i<sizeof(config_data)+8;i++){
for(unsigned int i=0;i<
#ifdef DYNAMIC_PIN_SETTINGS
sizeof(config_data)+
#endif
8;i++){
int8_t rd=(int8_t)EEPROM.read(2+i);
#ifdef DYNAMIC_PIN_SETTINGS
if(i>=8) config_data[i-8] = rd;
else s[i]=(char)rd;
else
#endif
s[i]=(char)rd;
}
Serial.printf("[Guy NVS] Get NVS...%d\n", config_data[0]);
Serial.printf("[Guy NVS] Get EEPROM...%d\n", config_data[0]);
return !(strcmp_P(s,projname));
}
void ReadguyDriver::nvs_write(){
@@ -472,6 +625,7 @@ void ReadguyDriver::nvs_deinit(){
}
bool ReadguyDriver::nvs_read(){ //此处需要处理一些有关I2C的内容
if(!nvsData.isKey(tagname)) return 0; //没有这个键值
#ifdef DYNAMIC_PIN_SETTINGS
size_t len=nvsData.getBytes(tagname,config_data,sizeof(config_data)); //读取的数据长度
/*if(len<sizeof(config_data)){ //旧版本格式无法获取I2C相关数据, 设置为-1.
for(int i=sizeof(config_data)-1;i>=15;i--) //使用新版本格式来存储相关数据
@@ -481,6 +635,9 @@ bool ReadguyDriver::nvs_read(){ //此处需要处理一些有关I2C的内容
nvsData.putBytes(tagname,config_data,sizeof(config_data)); //用新版本格式保存
}*/
return len==sizeof(config_data);
#else
return 1;
#endif
}
void ReadguyDriver::nvs_write(){
if(nvsData.isKey(tagname)) nvsData.remove(tagname);
@@ -489,31 +646,70 @@ void ReadguyDriver::nvs_write(){
#endif
uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
static unsigned long last=0;
static unsigned long last2=0;
uint8_t res1,res2,res3,res4=0;
switch(READGUY_buttons){
case 1:
res1=btn_rd[0].read();
if(res1 == 1) res4 |= 1; //点按
else if(res1 == 2) res4 |= 2; //双击
else if(res1 == 4) res4 |= 4; //长按-确定
else if(res1 == 2) res4 |= 4; //双击-确定
else if(res1 == 3) res4 |= 8; //三击-返回
else if(res1 == 4) res4 |= 2; //长按-向上翻页
else if(res1 == 5) res4 |= 3; //单击后长按-新增操作(可以连按)
break;
case 2:
res1=btn_rd[0].read(); //两个按钮引脚都读取
res2=btn_rd[1].read();
if(res1 == 1) res4 |= 1; //左键点按-向下翻页
else if(res1 == 4) res4 |= 2; //左键长按-向上翻页
if(res2 == 1) res4 |= 4; //右键点按-确定
else if(res2 == 4) res4 |= 8; //右键长按-返回
res1=btn_rd[0].read(); //选项上下键 两个按钮引脚都读取
res2=btn_rd[1].read(); //确定/返回键
//#if 1
{
bool newval=btn_rd[0].isPressedRaw();
if(newval && last2) last2=0;
else if(!(newval || last2)) last2=millis(); //捕获按钮松开的行为
if(res1 && (millis()-last>=btn_rd[1].long_press_ms) && (!btn_rd[1].isPressedRaw())){
//Serial.printf("[%9d] res 1 state: %d %d\n",millis(),longpresstest,pressedRawtest);
res4 = (res1 == 1)?1:2; //左键点按-向下翻页
}
}
//#endif
/*
uint32_t nowm = millis();
if(res1 && nowm-last >= btn_rd[1].long_press_ms && (!btn_rd[1].isPressedRaw())){
res4 = (res1 == 1)?1:2; //左键点按-向下翻页
last=nowm;
}
if(res2) {
if(btn_rd[0].isPressedRaw()) res4 |= 3; //避免GCC警告(我常年喜欢-Werror=all
else if(res2 == 1 && nowm>last) res4 |= 4; //右键点按-确定
else if(res2 == 4 && nowm>last) res4 |= 8; //右键长按-返回
last=nowm;
}
*/
if(res2) {
unsigned long ts=millis();
//Serial.printf("[%9lu] now last2: %lu, threshold %lu\n",ts,last2,ts-last2);
if(btn_rd[0].isPressedRaw() || ts-last2<=20) { //2024.2.25新增: 20毫秒的去抖时间 防误判
res4 |= 3; //避免GCC警告(我常年喜欢-Werror=all
}
else if(res2 == 1) res4 |= 4; //右键点按-确定
else if(res2 == 4) res4 |= 8; //右键长按-返回
last=ts;
}
if(res4==5 || res4==6) res4=3;
break;
case 3:
res1=btn_rd[0].read();
res2=btn_rd[1].read();
res3=btn_rd[2].read();
if(res1 == 4) res4 |= 1;
if(res3 == 4) res4 |= 2;
if(res1 && millis()-last >= btn_rd[1].long_repeat_ms && (!btn_rd[2].isPressedRaw())) res4 |= 2;
if(res3) {
res4 |= ((btn_rd[0].isPressedRaw()<<1)|1);
last=millis();
}
//if(res3 && ((millis()-last)<btn_rd[0].long_repeat_ms)) res4 |=3;
if(res2 == 1) res4 |= 4;
else if(res2 == 4) res4 |= 8;
else if(res2 == 2) res4 |= 3; //新增: 双击进入操作5
break;
}
return res4;

View File

@@ -49,7 +49,8 @@
#ifdef READGUY_DEV_213A
#include "guy_epaper/guy_213a/guy_213a.h"
#endif
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_266A))
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C))
#include "guy_epaper/guy_213b_266a/guy_213b_266a.h"
#endif
#ifdef READGUY_DEV_370A
@@ -65,6 +66,29 @@
#include "guy_epaper/lcdDebug/lcdDebug.h"
#endif
#ifdef READGUY_DEV_154C
#include "guy_epaper/guy_154C/guy_154C.h"
#endif
#ifdef READGUY_DEV_370B
#include "guy_epaper/guy_370B/guy_370B.h"
#endif
#ifdef READGUY_DEV_426A
#include "guy_epaper/guy_426A/guy_426A.h"
#endif
#ifdef READGUY_DEV_583A
#include "guy_epaper/guy_583A/guy_583A.h"
#endif
#ifdef READGUY_DEV_583B
#include "guy_epaper/guy_583B/guy_583B.h"
#endif
#ifdef READGUY_DEV_750A
#include "guy_epaper/guy_750A/guy_750A.h"
#endif
#ifdef READGUY_DEV_1020A
#include "guy_epaper/guy_1020A/guy_1020A.h"
#endif
//添加新屏幕型号 add displays here
#include "guy_button.h" //改自Button2精简而来
#include "guy_version.h"
#include "guy_driver_config.h" //config
@@ -77,28 +101,28 @@
#endif
#if defined(ESP8266) //for ESP8266
#ifdef DYNAMIC_PIN_SETTINGS
#include <EEPROM.h> //ESP32需要NVS才可以读取引脚信息
#endif
#include <EEPROM.h> //ESP32需要NVS才可以读取引脚信息,
#ifdef READGUY_ESP_ENABLE_WIFI
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include "ESP8266HTTPUpdateServer.h"
#endif
#ifdef READGUY_ENABLE_SD
#include <SDFS.h>
#endif
#include <Ticker.h>
#else //for ESP32
#ifdef DYNAMIC_PIN_SETTINGS
#include <Preferences.h> //ESP32需要NVS才可以读取引脚信息
#endif
#ifdef READGUY_ESP_ENABLE_WIFI
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include "HTTPUpdateServer.h"
#endif
#ifdef READGUY_ENABLE_SD
#include <SD.h>
#endif
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#endif
@@ -132,6 +156,13 @@
#define READGUY_buttons (config_data[21]) //按钮个数, 0-3都有可能
#endif
#define READGUY_SLOW 0
#define READGUY_FAST 1
#define READGUY_SLOW_START 2
#define READGUY_FAST_START 3
#define READGUY_SLOW_END 4
#define READGUY_FAST_END 5
class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
public:
#ifdef READGUY_ESP_ENABLE_WIFI
@@ -147,15 +178,19 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
/** @brief 初始化readguy
* @param WiFiSet 是否保持AP模式关闭. 0:配网完成自动关WiFi, 1:需要手动调用 WiFi.mode(WIFI_OFF) 关闭WiFi.
* 2:自动连接到已存的WiFi, 但不等待连接成功
* @param initepd 是否初始化墨水屏. 初始化后的首次刷屏必为慢刷. 如果是不断电复位, 可以不初始化墨水屏直接刷屏
* @param initSD 是否初始化文件系统. 选是-初始化SD失败则初始化LittleFs; 选否-不初始化SD也不初始化littlefs.
* @return SD卡是否就绪
*/
uint8_t init(uint8_t WiFiSet = 0,bool initepd = 1/* ,int g_width = 0,int g_height = 0 */);
uint8_t init(uint8_t WiFiSet = 0, bool initepd = 1, bool initSD = 1);
/// @brief 设置显示亮度
void setBright(int d);
/// @brief 返回显示亮度
int getBright() const { return currentBright; }
/// @brief 刷新显示到屏幕上
void display(bool part = true);
void display(uint8_t part = READGUY_FAST);
/// @brief 刷新显示到屏幕上
void displayBuffer(const uint8_t *buf, uint8_t part);
/** @brief 刷新显示到屏幕上, 可以自定义读取指定位置像素的函数
* @param f 自定义的函数. 此函数将在读取像素并输出到墨水屏时被调用.
* 每次调用需要返回 "参数对应位置" 的8个像素的颜色信息(凑成一字节). 其中左侧应在高位,右侧应在低位.
@@ -170,13 +205,13 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
* @endcode
* 该函数会将参数从0开始,每次逐渐增加1的顺序来被调用. 即先调用f(0),再f(1),f(2),f(3)... 以此类推.
*/
void display(std::function<uint8_t(int)> f, bool part = true);
void display(std::function<uint8_t(int)> f, uint8_t part);
/// @brief 显示图片, 使用抖动算法. 可以用省内存的方法显示, 可以缩放到指定的宽度和高度
void drawImage(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw=0, uint16_t zoomh=0){
void drawImage(LGFX_Sprite &spr,int32_t x,int32_t y,int32_t zoomw=0, int32_t zoomh=0){
if(READGUY_cali==127) drawImage(*this,spr,x,y,zoomw,zoomh);
}
/// @brief 显示图片, 将图片(任意颜色格式)显示到一个黑白色的sprite(必须是黑白二值型)上 (未经测试)
void drawImage(LGFX_Sprite &base,LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw=0,uint16_t zoomh=0);
void drawImage(LGFX_Sprite &base,LGFX_Sprite &spr,int32_t x,int32_t y,int32_t zoomw=0,int32_t zoomh=0);
/// @brief 设置显示对比度(灰度)
void setDepth(uint8_t d);
/** @brief 返回目标屏幕是否支持16级灰度 返回非0代表支持.
@@ -188,7 +223,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
* 2-关闭连续刷屏 关闭16阶灰度抖动 3-开启连续刷屏 关闭16阶灰度抖动 */
void setGreyQuality(uint8_t q) { if(READGUY_cali==127) guy_dev->setGreyQuality(q); }
/// @brief 显示灰度图片,如果支持,否则就不显示灰度图片了. 可以用省内存的方法显示
void draw16grey(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw=0,uint16_t zoomh=0);
void draw16grey(LGFX_Sprite &spr,int32_t x,int32_t y,int32_t zoomw=0,int32_t zoomh=0);
/** @brief 按照自定义分步显示灰度图片,如果支持,否则就不显示灰度图片了. 可以用省内存的方法显示
* @param step 步骤代号. 从1开始到15,依次调用此函数来自定义的灰度显示显存内容. 没有0和16.
* @note 必须按照 "慢刷全屏->绘图->设置参数1->绘图->设置参数2... 调用15次 来完成一次自定义灰度刷屏
@@ -203,13 +238,13 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
void invertDisplay();
/// @brief 进入EPD的低功耗模式
void sleepEPD(void);
#ifdef READGUY_ESP_ENABLE_WIFI
/// @brief ap配网设置页面
typedef struct {
String linkname;
String event; //链接名称 事件URI
std::function<void(ReadguyWebServer*)> func; //触发时执行的函数
} serveFunc;
#ifdef READGUY_ESP_ENABLE_WIFI
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
void ap_setup();
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
@@ -217,6 +252,12 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
bool server_loop();
void server_end();
#else
/// @brief ap配网设置页面
typedef struct {
String linkname;
String event; //链接名称 事件URI
std::function<void(void*)> func; //触发时执行的函数
} serveFunc;
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
void ap_setup(){}
/// @brief 初始化服务器模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
@@ -229,7 +270,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
/** @brief 初始化屏幕, 设置驱动代号, 引脚排列顺序. 过程会检验引脚可用性.
* @param g_width, g_height 显示区域的宽度和高度. 为0表示直接使用屏幕的宽度和高度
* @note 这两个参数转专为指定分辨率的程序画面设计, 其他分辨率的画面会自动拉伸. [1.2新增] */
void setEpdDriver(bool initepd = 1/* ,int g_width = 0,int g_height = 0 */);
void setEpdDriver(bool initepd = 1, bool initGFX = 1);
/** @brief 初始化SD卡, 设置驱动代号, 引脚排列顺序. 过程会检验引脚可用性.
* @return SD卡初始化成功与否 */
bool setSDcardDriver();
@@ -240,6 +281,8 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
bool SDinside(bool check=true) { return check?setSDcardDriver():READGUY_sd_ok; };
/// @brief 检查按钮. 当配置未完成时,按钮不可用, 返回0.
uint8_t getBtn() { return (READGUY_cali==127)?getBtn_impl():0; }
/// @brief [此函数已弃用 非常不建议使用] 根据按钮ID来检查按钮. 注意这里如果按下返回0, 没按下或者按钮无效返回1
//uint8_t getBtn(int btnID){return btnID<getButtonsCount()?(!(btn_rd[btnID].isPressedRaw())):1;}
/** @brief 返回可用的文件系统. 当SD卡可用时, 返回SD卡. 否则根据情况返回最近的可用文件系统
* @param initSD 2:总是重新初始化SD卡; 1:若SD卡不可用则初始化; 0:SD卡不可用则返回LittleFS. */
fs::FS &guyFS(uint8_t initSD = 0);
@@ -251,14 +294,15 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
static const char projname[8];
static const char tagname[7];
//uint8_t config_wifi=0; //是否强行在初始化期间设置WiFi.
#ifdef DYNAMIC_PIN_SETTINGS//数据是否已经校准
int8_t config_data[22];
char randomch[4]; //校验用字符串
void nvs_init(); //初始化持久存储器.
void nvs_deinit();//保存持久存储器的内容
bool nvs_read(); //从持久存储器读取, 返回是否读取成功
void nvs_write(); //写入到持久存储器
#ifdef DYNAMIC_PIN_SETTINGS//数据是否已经校准
int8_t config_data[22];
char randomch[4]; //校验用字符串
#else
static const int8_t config_data[22];
int8_t READGUY_sd_ok = 0;
int8_t READGUY_cali = 0;
int8_t READGUY_buttons = 0; //按钮个数, 0-3都有可能
@@ -277,10 +321,8 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
//对于esp8266, 需要注册到ticker
Ticker btnTask;
#else
#ifdef DYNAMIC_PIN_SETTINGS
//NVS数据操作函数, 无NVS的使用EEProm的最后几个字节块
Preferences nvsData;
#endif
static SPIClass *sd_spi;
static SPIClass *epd_spi;
static TaskHandle_t btn_handle;
@@ -328,54 +370,67 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
static uint8_t rd_btn_f(uint8_t btn);
uint8_t getBtn_impl(); //按钮不可用, 返回0.
static void in_press(){ //SPI开始传输屏幕数据
#ifndef ESP8266
#ifdef ESP8266
if(!spibz) SPI.beginTransaction(SPISettings(ESP8266_SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
#else
if(!spibz) epd_spi->beginTransaction(SPISettings(ESP32_DISP_FREQUENCY, MSBFIRST, SPI_MODE0));
#endif
spibz ++;
}
static void in_release(){//SPI结束传输屏幕数据
spibz --;
#ifndef ESP8266
#ifdef ESP8266
if(!spibz) SPI.endTransaction();
#else
if(!spibz) epd_spi->endTransaction();
#endif
}
public: //增加了一些返回系统状态变量的函数, 它们是静态的, 而且不会对程序造成任何影响.
constexpr int getShareSpi() const { return config_data[1]; }
constexpr int getEpdType () const { return config_data[2]; } // 对应的epd驱动程序代号, -1为未指定
constexpr int getShareSpi() const { return READGUY_shareSpi; }
constexpr int getEpdType () const { return READGUY_epd_type; } // 对应的epd驱动程序代号, -1为未指定
//显示驱动部分, 显示默认使用vspi (vspi也是默认SPI库的通道)
constexpr int getEpdMosi () const { return config_data[3]; } // 目标显示器的 MOSI 引脚
constexpr int getEpdSclk () const { return config_data[4]; } // 目标显示器的 SCLK 引脚
constexpr int getEpdCs () const { return config_data[5]; } // 目标显示器的 CS 引脚
constexpr int getEpdDc () const { return config_data[6]; } // 目标显示器的 DC 引脚
constexpr int getEpdRst () const { return config_data[7]; } // 目标显示器的 RST 引脚
constexpr int getEpdBusy () const { return config_data[8]; } // 目标显示器的 BUSY 引脚
constexpr int getEpdMosi () const { return READGUY_epd_mosi; } // 目标显示器的 MOSI 引脚
constexpr int getEpdSclk () const { return READGUY_epd_sclk; } // 目标显示器的 SCLK 引脚
constexpr int getEpdCs () const { return READGUY_epd_cs; } // 目标显示器的 CS 引脚
constexpr int getEpdDc () const { return READGUY_epd_dc; } // 目标显示器的 DC 引脚
constexpr int getEpdRst () const { return READGUY_epd_rst; } // 目标显示器的 RST 引脚
constexpr int getEpdBusy () const { return READGUY_epd_busy; } // 目标显示器的 BUSY 引脚
//sd卡驱动部分, 默认使用hspi (sd卡建议用hspi)
constexpr int getSdMiso () const { return config_data[9]; } // 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
constexpr int getSdMosi () const { return config_data[10]; }// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
constexpr int getSdSclk () const { return config_data[11]; }// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
constexpr int getSdCs () const { return config_data[12]; }// 目标sd卡的 CS 引脚.
constexpr int getI2cSda () const { return config_data[13]; }// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
constexpr int getI2cScl () const { return config_data[14]; }// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
constexpr int getSdMiso () const { return READGUY_sd_miso; } // 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
constexpr int getSdMosi () const { return READGUY_sd_mosi; }// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
constexpr int getSdSclk () const { return READGUY_sd_sclk; }// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
constexpr int getSdCs () const { return READGUY_sd_cs; }// 目标sd卡的CS引脚. 对ESP32S3, 返回127代表使用SDMMC
constexpr int getI2cSda () const { return READGUY_i2c_sda; }// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
constexpr int getI2cScl () const { return READGUY_i2c_scl; }// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
//按键驱动部分, 为负代表高触发, 否则低触发,
//注意, 这里的io编号是加1的, 即 1或-1 代表 gpio0 的低触发/高触发
constexpr int getBtn1Pin () const { return config_data[15]; }
constexpr int getBtn2Pin () const { return config_data[16]; }
constexpr int getBtn3Pin () const { return config_data[17]; }
constexpr int getBlPin () const { return config_data[18]; } //前置光接口引脚IO
constexpr int getRtcType () const { return config_data[19]; } //使用的RTC型号(待定, 还没用上)
constexpr int getButtonsCount() const { return config_data[21]; } //按钮个数, 0-3都有可能
constexpr int getBtn1Pin () const { return READGUY_btn1; }
constexpr int getBtn2Pin () const { return READGUY_btn2; }
constexpr int getBtn3Pin () const { return READGUY_btn3; }
constexpr int getBlPin () const { return READGUY_bl_pin; } //前置光接口引脚IO
constexpr int getRtcType () const { return READGUY_rtc_type; } //使用的RTC型号(待定, 还没用上)
constexpr int getButtonsCount() const { return READGUY_buttons; } //按钮个数, 0-3都有可能
//constexpr int memWidth () const { return guy_width ; } //返回显存宽度(不是画幅宽度),不会随着画布旋转改变
//constexpr int memHeight () const { return guy_height ; } //返回显存高度(不是画幅高度),不会随着画布旋转改变
int drvWidth () const { return READGUY_cali==127?guy_dev->drv_width():0; } //返回显示屏硬件宽度(不是画幅宽度)
int drvHeight() const { return READGUY_cali==127?guy_dev->drv_height():0; } //返回显示屏硬件高度(不是画幅高度)
int width () const { return READGUY_cali==127?((getRotation()&1)?drvHeight():drvWidth()):0; }
int height() const { return READGUY_cali==127?((getRotation()&1)?drvWidth():drvHeight()):0; }
//int width () const { return (getRotation()&1)?drvHeight():drvWidth(); }
//int height() const { return (getRotation()&1)?drvWidth():drvHeight(); }
size_t getFreeMem() const { return
#ifdef ESP8266
ESP.getFreeHeap();
#else
esp_get_free_heap_size();
#endif
}
// private:
void implBeginTransfer() { guy_dev->BeginTransfer(); } //此函数用于开启SPI传输, 只能在自定义刷屏函数中使用!!
void implEndTransfer() { guy_dev->EndTransfer(); } //此函数用于开启SPI传输, 只能在自定义刷屏函数中使用!!
/// @brief 分阶段显示图片, 使用抖动算法. 更加的省内存.目前函数
void drawImageStage(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint8_t stage,uint8_t totalstage,
uint16_t zoomw=0,uint16_t zoomh=0);
void drawImageStage(LGFX_Sprite &spr,int32_t x,int32_t y,uint8_t stage,uint8_t totalstage,
int32_t zoomw=0,int32_t zoomh=0){ drawImageStage(*this,spr,x,y,stage,totalstage,zoomw,zoomh); }
void drawImageStage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,int32_t x,int32_t y,
uint8_t stage,uint8_t totalstage,int32_t zoomw=0,int32_t zoomh=0);
};
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */