mirror of
https://github.com/fsender/readguy.git
synced 2026-03-25 21:39:49 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aca106448 | ||
|
|
d24639a962 | ||
|
|
85a785eabd |
36
CHANGELOG.md
36
CHANGELOG.md
@@ -1,3 +1,39 @@
|
||||
## 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. 增加了真.保姆级的教程 (详细到注释比代码多很多倍)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<img src="extra/artset/readguy_theme3.png" width="30%" height="auto">
|
||||
|
||||
**版本1.3.0正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
**版本1.3.2正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
|
||||
欢迎克隆, 项目交流QQ群: 926824162 (萌新可以进来问问题的哟), 项目的 Bilibili 主页: [BV1f94y187wz](https://www.bilibili.com/video/BV1f94y187wz/) 记得三连+关注我这个宝藏up主哦~
|
||||
|
||||
|
||||
@@ -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); // 慢速刷新.
|
||||
|
||||
//想知道更多内容, 欢迎移步到其他示例.
|
||||
}
|
||||
|
||||
@@ -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,14 @@ 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 +153,7 @@ void setup(){
|
||||
|
||||
guy.fillScreen(1);
|
||||
|
||||
guy.display(false); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
guy.display(READGUY_SLOW); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
|
||||
for(int i=1;i<16;i++){ //灰度测试, 循环设置不同灰度
|
||||
|
||||
@@ -203,7 +222,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 +258,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表示全屏慢刷.
|
||||
|
||||
|
||||
@@ -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); // 慢速刷新.
|
||||
|
||||
//想知道更多内容, 欢迎移步到其他示例.
|
||||
}
|
||||
|
||||
@@ -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; //在此直接设置文件路径和文件名.
|
||||
|
||||
@@ -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);
|
||||
// 此函数过不了编译 需要改库.
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/fsender/readguy"
|
||||
},
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.2",
|
||||
"frameworks": "arduino",
|
||||
"platforms": ["espressif32", "espressif8266"],
|
||||
"headers": "readguy.h",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=readguy
|
||||
version=1.3.0
|
||||
version=1.3.2
|
||||
author=fsender <f_ender@163.com>
|
||||
maintainer=fsender <f_ender@163.com>
|
||||
sentence=A free E-paper display driver library supports 16-level greyscale.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
@@ -110,7 +110,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 +125,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时无法唤醒
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
|
||||
@@ -148,7 +148,9 @@ void drvSSD168x::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
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 +198,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){ //无法唤醒
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
|
||||
@@ -119,7 +119,9 @@ void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
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 +145,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 无法唤醒
|
||||
|
||||
@@ -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; }; //返回缓存的数据宽度
|
||||
|
||||
@@ -152,7 +152,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);
|
||||
@@ -169,17 +171,29 @@ void drv_base::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
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();
|
||||
}
|
||||
lastRefresh=millis();
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
if(part_mode){
|
||||
if(ms<200) guy_epdBusy(ms-200);
|
||||
//guy_epdBusy(-200);
|
||||
}
|
||||
else{
|
||||
if(ms<2000) guy_epdBusy(ms-2000);
|
||||
//guy_epdBusy(-2000);
|
||||
BeginTransfer();
|
||||
epd_init();
|
||||
SendLuts(1);
|
||||
guy_epdCmd(0x92);
|
||||
EndTransfer();
|
||||
}
|
||||
lastRefresh=0;
|
||||
}
|
||||
}
|
||||
void drv_base::drv_sleep() { //开始屏幕睡眠
|
||||
|
||||
@@ -39,7 +39,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; }; //返回显示区域高度
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
|
||||
@@ -185,7 +185,9 @@ void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
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 +213,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 +221,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);
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
|
||||
@@ -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;
|
||||
uint32_t u=part_mode?800:3600;
|
||||
if(ms<u) guy_epdBusy(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);
|
||||
}
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
|
||||
@@ -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));
|
||||
@@ -161,8 +162,7 @@ void readguyEpdBase::Reset(uint32_t minTime)
|
||||
|
||||
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]={
|
||||
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,24 +172,21 @@ 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(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]);
|
||||
int32_t flodelta = floyd_tab[i&1][j]+(int32_t)((gv<<8)|gv);
|
||||
@@ -218,24 +215,24 @@ 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()/fw]))<<(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
|
||||
}
|
||||
}
|
||||
//不支持的话使用单色抖动刷屏
|
||||
@@ -247,10 +244,8 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
|
||||
if((!fw) || (!fh)) return;
|
||||
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,15 +255,12 @@ 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]);
|
||||
@@ -284,9 +276,7 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
|
||||
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
|
||||
//uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw])>>4;
|
||||
if(negativeOrder)
|
||||
buff8bit |= (cg<k)<<((~j)&7);
|
||||
else{
|
||||
@@ -300,9 +290,7 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
|
||||
//}
|
||||
//sprbase.drawPixel(x+j,i,(greysc(readBuff[j*spr.width()/fw])/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 +298,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. */
|
||||
@@ -55,9 +55,8 @@ protected:
|
||||
#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,9 +81,9 @@ 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; //返回显示区域高度, 即使旋转了也不能影响此函数输出
|
||||
|
||||
@@ -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模块
|
||||
|
||||
@@ -40,7 +40,8 @@ void drv::drv_init(){
|
||||
void drv::drv_fullpart(bool part){
|
||||
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 +80,6 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
}
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() {}
|
||||
|
||||
@@ -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; } //返回显示区域高度
|
||||
|
||||
@@ -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 2
|
||||
#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.2"
|
||||
|
||||
#ifdef ESP8266
|
||||
#define _READGUY_PLATFORM "ESP8266"
|
||||
|
||||
@@ -191,7 +191,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());
|
||||
}
|
||||
@@ -311,13 +311,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());
|
||||
@@ -644,7 +645,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/>"
|
||||
|
||||
@@ -49,7 +49,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){
|
||||
if(READGUY_cali==127) //已经初始化过了一次了, 为了防止里面一些volatile的东西出现问题....还是退出吧
|
||||
return 0;
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
@@ -180,15 +180,14 @@ 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());
|
||||
Serial.printf_P(PSTR("[Guy EPD] EPD init OK: 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);
|
||||
createSprite(guy_dev->drv_width(),guy_dev->drv_height());
|
||||
//这里发现如果用自定义的内存分配方式会更好一些. 不会导致返回的height不对. 但是因为LovyanGFX库未更新 暂时不能这么用.
|
||||
//setRotation(1); //旋转之后操作更方便
|
||||
setRotation(0);
|
||||
@@ -280,18 +279,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);
|
||||
}
|
||||
else if(READGUY_buttons==3){
|
||||
btn_rd[0].setLongPressMs(1); //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[0].setLongRepeatMode(1);
|
||||
btn_rd[0].long_press_ms = 150; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
//btn_rd[0].setLongRepeatMode(1);
|
||||
btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
|
||||
btn_rd[1].setLongRepeatMode(0);
|
||||
btn_rd[2].setLongPressMs(1); //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[2].long_press_ms = 1; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[2].setLongRepeatMode(1);
|
||||
}
|
||||
#ifdef ESP8266 //对于esp8266, 需要注册到ticker. 这是因为没freertos.
|
||||
@@ -370,32 +372,41 @@ 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::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,uint16_t x,uint16_t y,uint16_t zoomw, uint16_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,
|
||||
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) {
|
||||
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);
|
||||
@@ -489,29 +500,47 @@ void ReadguyDriver::nvs_write(){
|
||||
#endif
|
||||
|
||||
uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
|
||||
static uint32_t last=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; //右键长按-返回
|
||||
if(millis()-last>500){
|
||||
if(res1 == 1) res4 |= 1; //左键点按-向下翻页
|
||||
else if(res1 == 4) {
|
||||
res4 |= 2; //左键长按-向上翻页
|
||||
//if(btn_rd[1].isPressedRaw()) res4 |= 1;
|
||||
}
|
||||
}
|
||||
if(btn_rd[0].isPressedRaw() && res2){
|
||||
res4 |= 3; //右键点按-确定
|
||||
last=millis();
|
||||
}
|
||||
else{
|
||||
if(res2 == 1) res4 |= 4; //右键点按-确定
|
||||
else if(res2 == 4) res4 |= 8; //右键长按-返回
|
||||
}
|
||||
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;
|
||||
break;
|
||||
|
||||
@@ -132,6 +132,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 +154,18 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
/** @brief 初始化readguy
|
||||
* @param WiFiSet 是否保持AP模式关闭. 0:配网完成自动关WiFi, 1:需要手动调用 WiFi.mode(WIFI_OFF) 关闭WiFi.
|
||||
* 2:自动连接到已存的WiFi, 但不等待连接成功
|
||||
* @param initepd 是否初始化墨水屏. 初始化后的首次刷屏必为慢刷. 如果是不断电复位, 可以不初始化墨水屏直接刷屏
|
||||
* @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);
|
||||
/// @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,7 +180,7 @@ 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){
|
||||
if(READGUY_cali==127) drawImage(*this,spr,x,y,zoomw,zoomh);
|
||||
@@ -240,6 +250,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(unsigned int btnID){return btnID<getButtonsCount()?(!(btn_rd[0].isPressedRaw())):1;}
|
||||
/** @brief 返回可用的文件系统. 当SD卡可用时, 返回SD卡. 否则根据情况返回最近的可用文件系统
|
||||
* @param initSD 2:总是重新初始化SD卡; 1:若SD卡不可用则初始化; 0:SD卡不可用则返回LittleFS. */
|
||||
fs::FS &guyFS(uint8_t initSD = 0);
|
||||
@@ -328,14 +340,18 @@ 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
|
||||
}
|
||||
@@ -368,14 +384,23 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
//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);
|
||||
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);
|
||||
};
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
Reference in New Issue
Block a user