mirror of
https://github.com/fsender/readguy.git
synced 2026-03-18 15:03:19 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bb2ba77f0 | ||
|
|
8e825c862a | ||
|
|
d88f1a3c5c | ||
|
|
771ac6db80 | ||
|
|
c4e848730c | ||
|
|
78438e36a7 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,19 @@
|
||||
## 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寸三色和黑白的不同驱动程序.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<img src="extra/artset/readguy_theme3.png" width="30%" height="auto">
|
||||
|
||||
**版本1.3.3正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
**版本1.3.5正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
|
||||
**即将发布7个全新的屏幕驱动: 欢迎支持! (详见后面的驱动表格)**
|
||||
|
||||
@@ -70,7 +70,7 @@ Supported displays: 1.54-inch, 2.13-inch, 2.66-inch, 2.9-inch, 4.2-inch.
|
||||
|14 |M5 Core.Ink 1.54寸 |即将支持|200*200|/|/|/|/|
|
||||
|15 |3.7寸低DPI版墨水屏 |即将支持|416*240|/|/|/|/|
|
||||
|16 |4.26寸高分辨率墨水屏|即将支持|800*480|/|/|/|/|
|
||||
|17 |5.83寸墨水屏幕 |即将支持|600*448|/|/|/|/|
|
||||
|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|/|/|/|/|
|
||||
@@ -247,5 +247,5 @@ firmware.bin 0x10000
|
||||
|
||||
Copyright © 2022-2023 FriendshipEnder. All Rights reserved.
|
||||
|
||||
版权声明:需要经过作者@friendshipender的许可才能商用。
|
||||
版权声明:需要经过作者@friendshipender的许可才能商用。 可以联系邮箱playyinzhe@qq.com询问商用事宜
|
||||
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -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.
|
||||
|
||||
137
examples/ex04_wifi/4_wifi_text_show/4_wifi_text_show.ino
Normal file
137
examples/ex04_wifi/4_wifi_text_show/4_wifi_text_show.ino
Normal 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. */
|
||||
26582
examples/ex04_wifi/4_wifi_text_show/ctg_u8g2_wqy12.c
Normal file
26582
examples/ex04_wifi/4_wifi_text_show/ctg_u8g2_wqy12.c
Normal file
File diff suppressed because it is too large
Load Diff
43
examples/ex04_wifi/4_wifi_text_show/ctg_u8g2_wqy12.h
Normal file
43
examples/ex04_wifi/4_wifi_text_show/ctg_u8g2_wqy12.h
Normal 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
@@ -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
|
||||
}
|
||||
|
||||
@@ -40,17 +40,24 @@ namespace guydev_template{
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
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;
|
||||
|
||||
@@ -43,20 +43,45 @@ constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
/** @brief 返回驱动程序ID. 此函数不需要在 cpp 文件内重写
|
||||
* @return int 直接返回对应宏定义就可以 */
|
||||
int drv_ID() const { return READGUY_DEV_template; }
|
||||
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); //设置显示颜色深度
|
||||
/// @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; //颜色深度
|
||||
uint8_t iLut=15; //颜色深度 1-15均为有效. 慢刷模式中 此数值为15.
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
|
||||
@@ -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
|
||||
|
||||
7
extra/platformio/readguy_4MB_largeAPP.csv
Normal file
7
extra/platformio/readguy_4MB_largeAPP.csv
Normal 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,
|
||||
|
1434
extra/platformio/sdkconfig.esp32c3_no_uart
Normal file
1434
extra/platformio/sdkconfig.esp32c3_no_uart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/fsender/readguy"
|
||||
},
|
||||
"version": "1.3.3",
|
||||
"version": "1.3.5",
|
||||
"frameworks": "arduino",
|
||||
"platforms": ["espressif32", "espressif8266"],
|
||||
"headers": "readguy.h",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=readguy
|
||||
version=1.3.3
|
||||
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.
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
|
||||
@@ -46,6 +46,7 @@ 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;
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
|
||||
@@ -35,34 +35,380 @@
|
||||
#include "guy_583A.h"
|
||||
#ifdef READGUY_DEV_583A
|
||||
namespace guydev_583A{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
/*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
|
||||
};
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
#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);
|
||||
}
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
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;
|
||||
//add driver code...
|
||||
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
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
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; //强制设置为慢刷新模式
|
||||
|
||||
@@ -36,13 +36,17 @@
|
||||
#define _GUY_EPD583A_H_FILE
|
||||
|
||||
namespace guydev_583A{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
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); //切换慢刷/快刷功能
|
||||
@@ -52,11 +56,36 @@ public:
|
||||
//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; }
|
||||
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.
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
//#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_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
|
||||
@@ -68,5 +68,7 @@
|
||||
|
||||
#define EPD_DRIVERS_NUM_MAX 21 //此选项请不要取消注释掉, 有几个屏幕就写多少.
|
||||
|
||||
#define READGUY_583A_DUAL_BUFFER //对于单缓存的5.83屏幕, 启用双缓存支持
|
||||
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -160,8 +160,8 @@ 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){
|
||||
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,
|
||||
@@ -172,9 +172,11 @@ 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
|
||||
};
|
||||
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()];
|
||||
floyd_tab[0] = new int16_t [fw];
|
||||
@@ -188,7 +190,7 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
|
||||
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);
|
||||
@@ -221,7 +223,7 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
|
||||
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()/fw]))<<(7-b);
|
||||
<greysc(readBuff[((j<<3)+b)*spr.width()/fw0]))<<(7-b);
|
||||
writeBuff[j]=buff8bit;
|
||||
}
|
||||
}
|
||||
@@ -236,12 +238,14 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
|
||||
}
|
||||
}
|
||||
//不支持的话使用单色抖动刷屏
|
||||
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){
|
||||
floyd_tab[0] = new int16_t [fw];
|
||||
@@ -263,7 +267,7 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
|
||||
//for(uint_fast8_t b=0;b<8;b++){
|
||||
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++;
|
||||
@@ -275,8 +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; }
|
||||
//uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw])>>4;
|
||||
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{
|
||||
@@ -288,7 +292,7 @@ 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));
|
||||
}
|
||||
if(_quality&2) for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
|
||||
sprbase.drawBitmap(x,i,writeBuff,fw,1,1,0);
|
||||
|
||||
@@ -48,9 +48,9 @@ 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];
|
||||
@@ -88,17 +88,19 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
//另外, 在提交新版本之前, 不要忘记在github上创建release, 否则Arduino IDE会读不到
|
||||
#define READGUY_V_MAJOR 1
|
||||
#define READGUY_V_MINOR 3
|
||||
#define READGUY_V_PATCH 3
|
||||
#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.3"
|
||||
#define READGUY_VERSION "1.3.5"
|
||||
|
||||
#ifdef ESP8266
|
||||
#define _READGUY_PLATFORM "ESP8266"
|
||||
|
||||
@@ -400,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按钮
|
||||
};
|
||||
@@ -516,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]);
|
||||
|
||||
@@ -79,7 +79,7 @@ ReadguyDriver::ReadguyDriver(){
|
||||
READGUY_sd_ok = 0; //初始默认SD卡未成功初始化
|
||||
READGUY_buttons = 0; //初始情况下没有按钮
|
||||
} //WiFiSet: 是否保持AP服务器一直处于打开状态
|
||||
uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd){
|
||||
uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd, bool initSD){
|
||||
if(READGUY_cali==127) //已经初始化过了一次了, 为了防止里面一些volatile的东西出现问题....还是退出吧
|
||||
return 0;
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
@@ -109,7 +109,7 @@ uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd){
|
||||
else if(WiFiSet==1) ap_setup();
|
||||
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
|
||||
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
|
||||
setSDcardDriver();
|
||||
if(initSD) setSDcardDriver();
|
||||
setButtonDriver();
|
||||
}
|
||||
#endif
|
||||
@@ -118,7 +118,7 @@ uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd){
|
||||
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.
|
||||
@@ -409,16 +409,16 @@ void ReadguyDriver::setButtonDriver(){
|
||||
//}
|
||||
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].long_press_ms = 50; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[0].long_press_ms = 20; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
//btn_rd[0].setLongRepeatMode(1);
|
||||
btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
|
||||
btn_rd[1].setLongRepeatMode(0);
|
||||
btn_rd[2].long_press_ms = 50; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
//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.
|
||||
@@ -535,11 +535,11 @@ void ReadguyDriver::display(std::function<uint8_t(int)> f, uint8_t part){
|
||||
//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::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 &sprbase,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;
|
||||
//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);
|
||||
@@ -547,7 +547,7 @@ void ReadguyDriver::drawImageStage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
|
||||
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);
|
||||
@@ -646,7 +646,8 @@ void ReadguyDriver::nvs_write(){
|
||||
#endif
|
||||
|
||||
uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
|
||||
static uint32_t last=0;
|
||||
static unsigned long last=0;
|
||||
static unsigned long last2=0;
|
||||
uint8_t res1,res2,res3,res4=0;
|
||||
switch(READGUY_buttons){
|
||||
case 1:
|
||||
@@ -658,22 +659,41 @@ uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
|
||||
else if(res1 == 5) res4 |= 3; //单击后长按-新增操作(可以连按)
|
||||
break;
|
||||
case 2:
|
||||
res1=btn_rd[0].read(); //两个按钮引脚都读取
|
||||
res2=btn_rd[1].read();
|
||||
if(millis()-last>500){
|
||||
if(res1 == 1) res4 |= 1; //左键点按-向下翻页
|
||||
else if(res1 == 4) {
|
||||
res4 |= 2; //左键长按-向上翻页
|
||||
//if(btn_rd[1].isPressedRaw()) res4 |= 1;
|
||||
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; //左键点按-向下翻页
|
||||
}
|
||||
}
|
||||
if(btn_rd[0].isPressedRaw() && res2){
|
||||
res4 |= 3; //右键点按-确定
|
||||
last=millis();
|
||||
//#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;
|
||||
}
|
||||
else{
|
||||
if(res2 == 1) res4 |= 4; //右键点按-确定
|
||||
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;
|
||||
@@ -689,6 +709,7 @@ uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
|
||||
//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;
|
||||
|
||||
@@ -179,9 +179,10 @@ class ReadguyDriver: public LGFX_Sprite{ // 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);
|
||||
uint8_t init(uint8_t WiFiSet = 0, bool initepd = 1, bool initSD = 1);
|
||||
/// @brief 设置显示亮度
|
||||
void setBright(int d);
|
||||
/// @brief 返回显示亮度
|
||||
@@ -206,11 +207,11 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
*/
|
||||
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代表支持.
|
||||
@@ -222,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次 来完成一次自定义灰度刷屏
|
||||
@@ -281,7 +282,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
/// @brief 检查按钮. 当配置未完成时,按钮不可用, 返回0.
|
||||
uint8_t getBtn() { return (READGUY_cali==127)?getBtn_impl():0; }
|
||||
/// @brief [此函数已弃用 非常不建议使用] 根据按钮ID来检查按钮. 注意这里如果按下返回0, 没按下或者按钮无效返回1
|
||||
//uint8_t getBtn(unsigned int btnID){return btnID<getButtonsCount()?(!(btn_rd[0].isPressedRaw())):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);
|
||||
@@ -426,10 +427,10 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
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){ drawImageStage(*this,spr,x,y,stage,totalstage,zoomw,zoomh); }
|
||||
void drawImageStage(LGFX_Sprite &sprbase,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. */
|
||||
Reference in New Issue
Block a user