mirror of
https://github.com/fsender/readguy.git
synced 2026-03-28 23:19:51 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d88f1a3c5c | ||
|
|
771ac6db80 | ||
|
|
c4e848730c | ||
|
|
78438e36a7 | ||
|
|
3ae6156886 | ||
|
|
2aca106448 | ||
|
|
d24639a962 | ||
|
|
85a785eabd | ||
|
|
a8b2540468 |
90
CHANGELOG.md
90
CHANGELOG.md
@@ -1,3 +1,93 @@
|
||||
## Release 1.3.4 - 2023/11/24
|
||||
|
||||
1. 添加5.83寸屏幕驱动. 默认开启, 嫌flash占用大的可以手动关
|
||||
|
||||
2. 修复别的一些bug
|
||||
|
||||
## Release 1.3.3 - 2023/11/12
|
||||
|
||||
1. 添加了2.66寸三色和黑白的不同驱动程序.
|
||||
|
||||
2. guy_epaper 文件夹内添加了一些文件. 为添加新版本驱动做准备.
|
||||
|
||||
3. 现在SD卡功能是可移除的. 可以自定义文件系统来初始化并使用. 但是对应的, SD卡引脚设定保留.
|
||||
|
||||
4. 优化按键手势的按动手感.
|
||||
|
||||
5. 重构了"固定引脚"(DYNAMIC_PIN_SETTINGS被注释)的宏定义逻辑代码. 现在如果在运行过"固定引脚"的程序之后, 再运行常规固件不需要二次配置.
|
||||
|
||||
6. 增大了S3的按钮任务栈空间, 避免因为stack overflow导致的任务终止.
|
||||
|
||||
7. 修复若干其他方面的bug, 比如配置引脚时, 屏幕没转向.
|
||||
|
||||
## Release 1.3.2 - 2023/11/8
|
||||
|
||||
1. 按键驱动 (guy_button) 获得新操作更新: (New button gesture)
|
||||
|
||||
- 单按键操作更新: 现在双击效果为选择/确定, 三击效果为返回, 长按效果为向上翻页;
|
||||
|
||||
- 单按键新增点按后长按操作;
|
||||
|
||||
- 双按键新增按住按键1点按按键2操作;
|
||||
|
||||
- 三按键新增按住按键1点按按键3操作.
|
||||
|
||||
2. 新增获取系统内存的API函数 getFreeMem().
|
||||
|
||||
3. 修复若干驱动层bug.
|
||||
|
||||
## Release 1.3.1 - 2023/11/7
|
||||
|
||||
1. 增加了分步绘制的支持. 可以使用 READGUY_FAST_START 等绘制选项来控制绘制过程:
|
||||
|
||||
- READGUY_SLOW 慢刷, 完整的进行一次慢刷, 等于连续执行慢刷开始和慢刷结束.
|
||||
|
||||
- READGUY_FAST 快刷, 完整的进行一次快刷, 需要等待刷完才能继续执行代码.
|
||||
|
||||
- READGUY_SLOW_START 慢刷开始, 此过程不会进行等待, 发送完要刷新的缓存之后立刻返回
|
||||
|
||||
- READGUY_FAST_START 快刷开始.
|
||||
|
||||
- READGUY_SLOW_END 慢刷结束, 调用慢刷开始之后才能执行. 会等待到屏幕刷完再执行后续操作.
|
||||
|
||||
- READGUY_FAST_END 快刷结束, 如果两次调用间隔时间屏幕已经刷完, 那么该函数会完成刷屏后续操作之后立刻返回.
|
||||
|
||||
2. 修复了首次配置驱动时, 墨水屏显示页面错位的bug (现在对于新设备, 配置起来会像以前一样丝滑)
|
||||
|
||||
3. 修复若干其他bug
|
||||
|
||||
## Release 1.3.0 - 2023/11/6
|
||||
|
||||
1. 增加了真.保姆级的教程 (详细到注释比代码多很多倍)
|
||||
|
||||
2. 目前所有支持的屏幕设备都可以在主控复位之后, 不需要调用init函数即可直接快刷(也不会变成慢刷). 为此, 调用init函数之后, 会让屏幕的下一次刷新变为慢刷.
|
||||
|
||||
3. 优化了所有的驱动程序. 包括灰度效果, 内存占用等.
|
||||
|
||||
4. 增加了更多的图片显示示例程序. 现在支持多种图片显示方式:
|
||||
|
||||
4.1. 在内存中开辟新画布(sprite). 支持颜色格式有1,2,4,8bit灰度(greyscale), 1,2,4,8bit调色板(palette), 8bit-RGB332, 16bit-RGB565, 24bit-RGB888.
|
||||
|
||||
4.2. 画布可以用抖动算法在屏幕上显示为二值图.
|
||||
|
||||
4.3. 画布可以在屏幕上显示为16级灰度图.
|
||||
|
||||
4.4. 画布可以显示在屏幕缓存中, 此过程不刷新屏幕. 下次刷新屏幕时, 画布内容将呈现在屏幕缓存中.
|
||||
|
||||
4.5. 将画布缩放到指定的宽度和高度后显示.
|
||||
|
||||
4.6. 显示BMP, JPG, PNG(仅限ESP32系列)图片文件到画布上.
|
||||
|
||||
4.7. 直接将图片文件刷新到屏幕上, 无需画布(sprite).
|
||||
|
||||
4.8. 将图片文件显示到屏幕缓存内, (不显示).
|
||||
|
||||
4.9. 将图片文件以16级灰度显示到屏幕上, 无需画布(sprite).
|
||||
|
||||
4.10. 缩放显示图片文件, 需要指定缩放比例. >1.0为放大, <1.0为缩小. (float scale_x, float scale_y).
|
||||
|
||||
5. 修复若干bug.
|
||||
|
||||
## Release 1.2.0 - 2023/11/3
|
||||
|
||||
1. 添加了图片demo, 和 可选关闭的WiFi 的示例程序。其中图片相关功能相当节省内存, 还请大胆使用。
|
||||
|
||||
21
README.md
21
README.md
@@ -4,7 +4,11 @@
|
||||
|
||||
<img src="extra/artset/readguy_theme3.png" width="30%" height="auto">
|
||||
|
||||
**版本1.1.1正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
**版本1.3.4正式发布!欢迎分享、star和fork~** 上面的图是项目看板娘, 盖. 可爱的盖姐在等你哟~
|
||||
|
||||
**即将发布7个全新的屏幕驱动: 欢迎支持! (详见后面的驱动表格)**
|
||||
|
||||
**发布好的全新驱动程序版本号将会是2.0.0!**
|
||||
|
||||
欢迎克隆, 项目交流QQ群: 926824162 (萌新可以进来问问题的哟), 项目的 Bilibili 主页: [BV1f94y187wz](https://www.bilibili.com/video/BV1f94y187wz/) 记得三连+关注我这个宝藏up主哦~
|
||||
|
||||
@@ -53,14 +57,23 @@ Supported displays: 1.54-inch, 2.13-inch, 2.66-inch, 2.9-inch, 4.2-inch.
|
||||
| 1 |1.54寸标准 |原创自研 |200*200| 16阶 | 不支持 | 1.3s | 0.35s |
|
||||
| 2 |1.54寸Lilygo |原创自研 |200*200| 16阶 | 支持 | 2.3s | 0.6s |
|
||||
| 3 |2.13寸汉朔价签 |原创自研 |122*250| 16阶 | 不支持 | 1.6s | 0.31s |
|
||||
| 4 |2.13寸三色 |原创自研 |104*212| 16阶 | 支持 | 2s | 0.2s |
|
||||
| 5 |2.66寸Vusion价签 |和4号相同|152*296| 16阶 | 支持 | 2s | 0.2s |
|
||||
| 4 |2.13寸低分辨率版 |原创自研 |104*212| 16阶 | 支持 | 1.12s | 0.17s |
|
||||
| 5 |2.66寸Vusion价签 |和4号相同|152*296| 16阶 | 支持 | 1.12s | 0.17s |
|
||||
| 6 |2.7寸佳显触摸屏 |和2号相同|176*264| 16阶 | 支持 | 2.3s | 0.6s |
|
||||
| 7 |2.9寸A01 |和1号相同|128*296| 16阶 | 不支持 | 1.8s | 0.55s |
|
||||
| 8 |2.9寸T94背光 |和2号相同|128*296| 16阶 | 支持 | 2.3s | 0.6s |
|
||||
| 9 |3.7寸高dpi墨水屏 |原创自研 |280*480| 16阶 | 不支持 | 1.3s | 0.5s |
|
||||
|10 |4.2寸HINK黑白价签 |原创自研 |400*300| 16阶 | 支持 | 1.72s | 0.38s |
|
||||
|11 |4.2寸WF丝印 |原创自研 |400*300| 16阶 | 不支持 | 3.6s | 0.8s |
|
||||
|12 |2.13寸三色 |和4号相同|122*250| 16阶 | 支持 | 未知 | 未知 |
|
||||
|13 |2.66寸三色价签 |和4号相同|152*296| 16阶 | 支持 | 2.48s | 0.65s |
|
||||
|14 |M5 Core.Ink 1.54寸 |即将支持|200*200|/|/|/|/|
|
||||
|15 |3.7寸低DPI版墨水屏 |即将支持|416*240|/|/|/|/|
|
||||
|16 |4.26寸高分辨率墨水屏|即将支持|800*480|/|/|/|/|
|
||||
|17 |5.83寸墨水屏幕 |原创自研|600*448| 16阶 | 支持 | 1.7s | 0.8s |
|
||||
|18 |5.83寸GDEQ0583T31 |即将支持|640*480|/|/|/|/|
|
||||
|19 |7.5寸三色墨水屏幕 |即将支持|800*480|/|/|/|/|
|
||||
|20 |10.2寸GDEQ102T90 |即将支持|960*640|/|/|/|/|
|
||||
|
||||
可以自己在代码中加入你想要的屏幕型号
|
||||
|
||||
@@ -234,5 +247,5 @@ firmware.bin 0x10000
|
||||
|
||||
Copyright © 2022-2023 FriendshipEnder. All Rights reserved.
|
||||
|
||||
版权声明:需要经过作者@friendshipender的许可才能商用。
|
||||
版权声明:需要经过作者@friendshipender的许可才能商用。 可以联系邮箱playyinzhe@qq.com询问商用事宜
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
*
|
||||
* @file ex01_helloWorld.ino
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @version 1.0
|
||||
* @date 2023-09-19
|
||||
* @version 1.1
|
||||
* @date create: 2023-09-19
|
||||
* last modify: 2023-11-06
|
||||
* @brief ReadGuy最基础的HelloWorld显示.
|
||||
*
|
||||
* @note 食用方法:
|
||||
@@ -27,6 +28,79 @@
|
||||
* 你需要知道你的哪个引脚对应哪个GPIO, 才能使用这个库 (带来的不便请谅解nia~)
|
||||
* 配置好了, 代码就开始正常运行了.
|
||||
*
|
||||
* 以下是看不懂代码的解决方法. 仔细看就行了
|
||||
* {0} 代码食用注意事项:
|
||||
* 这一部分的代码很难读, 或者按维莫斯小姐的说法, 很 "抽象" .
|
||||
* 如果你要开始一行一行读取下去, 不妨先在这里停顿一下, 看一下一些需要你提前知道的东西.
|
||||
*
|
||||
* {1} 画布, 或者叫sprite. 是一块专门存储图像的数据结构.
|
||||
* 画布需要大量的内存来存放图像的像素, 但是你可以对画布进行任何图像操作, 就像是在墨水屏上能进行的操作一样多.
|
||||
* 画布类型的数据结构至少需要包含3个要素: 宽度, 高度, 每像素需要的字节数.
|
||||
* 画布需要的内存为 宽度*高度*每像素需要的字节数. (1bit图像需要8分之一字节)
|
||||
* 在画布上可以进行几乎任何图像操作, 就像是在墨水屏上能进行的操作一样多.
|
||||
* 而且你还可以获取像素的颜色 (这和你创建的画布的颜色格式有关).
|
||||
* 画布可以随时被快速的显示到墨水屏上, 显示完了之后再使用display方法, 你刚才创建的画布就显示出来了.
|
||||
*
|
||||
* {2} 屏幕缓存. 你就从来没好奇过, 墨水屏上怎么呈现图像的? 我好奇过.
|
||||
* 我翻看了里面那些错综复杂又是深奥的C++骚操作又是类继承又是虚函数指针...反正就是抽象而且难懂的的源代码,
|
||||
* 简而言之, 墨水屏显示的原理就是墨水屏驱动里面也有个画布, 不过这个画布是1bit的(每8像素消耗1字节内存).
|
||||
* 所有对墨水屏进行的操作其实都是对那个内部的画布进行的操作.
|
||||
* 在你使用墨水屏的display方法时, 呃, 墨水屏的驱动程序可以读取到这个屏幕缓存的所有字节.
|
||||
* 并且根据驱动手册的方法将这个画布上的字节发送到屏幕上.
|
||||
* 发送完成之后再通过一些代码, 墨水屏就会刷屏, 将这个屏幕缓存里的内容显示出来了.
|
||||
* 维莫斯小姐: 苏滴嘶内~
|
||||
* 下面的库其实用了一些更加骚气的方法, 直接读取了这块画布, 从而能允许你在ESP8266上也可以...显示不小的图片
|
||||
*
|
||||
* {3} 灰度显示. ReadGuy这个库的一大特色就是支持灰度显示.
|
||||
* 欸, 可是屏幕缓存画布只有1bit啊, 怎么显示灰度啊?
|
||||
* 不用急, 原理也不难.
|
||||
* 16级灰度颜色的刷屏分为15个步骤. 因为白色不需要刷.
|
||||
* 在开始刷屏之前, 务必进行一次慢刷, 确保所有的白色像素都足够白.
|
||||
* 第一次刷屏, 通常会刷最浅的灰色.
|
||||
* 此时, 首先将屏幕缓存内所有需要显示为这个颜色的像素全写入为黑色(只是名义上的黑色, 实际上是设定的颜色).
|
||||
* 再初始化墨水屏的刷屏功能.
|
||||
* - 此处需要额外设定刷屏的颜色的参数. 此参数设定是可以由驱动程序自动完成的, 不过也可以通过你调用函数完成.
|
||||
* - 用户只需要用简单的setDepth函数设置颜色即可. 用户设定的颜色深度通常用于显示字符串或者形状等GUI控件.
|
||||
* - 刷图程序的灰度图片刷新功能会自动控制刷屏颜色, 不需要手动调用.
|
||||
* 最后刷屏. 因为之前刷图程序已经设定过刷的颜色了, 所以此时刷屏呈现的颜色就是之前设定的颜色.
|
||||
* 第2-15次刷屏原理类似.
|
||||
* 每次追加黑色像素, 追加的像素就是来显示灰度的像素. 而原本的黑色像素就是之前那些灰度颜色的像素.
|
||||
*
|
||||
* \*(^_^)*/ /** 我相信你应该还不懂. 我就举个例子吧.
|
||||
* 比如要显示一个渐变色, 从左到右为白色→黑色的渐变图.
|
||||
* 首先进行一次慢刷, 确保要刷图的地方都是纯洁的白色.
|
||||
* ≡=-(1)-=≡
|
||||
* 筛选出最浅的灰色设为灰1, (灰X代表灰度颜色, 灰15代表黑色)
|
||||
* 再把图片内所有颜色和灰1最接近的颜色写入到屏幕缓存内.
|
||||
* 此时屏幕缓存内的"黑色"部分都是与灰1最接近的颜色, 其他颜色均为"白色"部分.
|
||||
* 刷好了之后, 进行一次刷屏. (系统自动调用setDepth(1)来保证接下来图片的黑色部分其实是灰1).
|
||||
* ≡=-(2)-=≡
|
||||
* 筛选出比最浅的灰色深一点的颜色设为灰2, 把图片内和灰2最接近的颜色写入屏幕缓存, 但保持原本代表灰1的"黑色"不变.
|
||||
* (也就是说, 把灰2的像素写入之后, 屏幕缓存的黑色像素只多不少. 写入过程中, 只能是白→黑, 不存在黑→白)
|
||||
* 此时屏幕缓存内的"黑色"部分包含了与灰2最接近的颜色, 和刚才刷完的与灰1最接近的颜色. 其他颜色均为"白色"部分.
|
||||
* 刷好了之后, 进行一次刷屏. (系统自动调用setDepth(2)来保证接下来图片的黑色部分其实是灰2)
|
||||
* 注意屏幕显示, 原本的灰1并没有颜色变化, 变化的都是本次追加的"灰2"代表的"黑色".
|
||||
* 追加的像素会显示为新设定的颜色.
|
||||
* ≡=-(3)-=≡
|
||||
* 对于灰3, 和灰2一样, 追加显示到屏幕缓存内.
|
||||
* (也就是说, 屏幕缓存的黑色像素还是只多不少. 写入过程中, 只能是白→黑, 不存在黑→白)
|
||||
* 此时屏幕缓存内的"黑色"部分包含了与灰3, 灰2和灰1最接近的颜色. 其他颜色均为"白色"部分.
|
||||
* 设置颜色深度, 刷屏.
|
||||
* 对于灰4~灰15, 都这么做
|
||||
* ≡=-(5)-=≡
|
||||
* 刷完灰15之后, 灰度图就刷完了.
|
||||
*
|
||||
* {4} 自定义刷屏函数. 到底是什么决定了刷屏时的每一像素是什么颜色? 是黑是白?
|
||||
* 其实刷屏的本质就是通过调用一个外部函数.
|
||||
* 该函数可以根据输入的像素坐标位置来决定输出的像素颜色.
|
||||
* 为了简化程序调用过程并提高调用速度, 此处的像素坐标位置参数为一个整数(而不是两个)
|
||||
* 至于该怎么调用这个函数, 并不是你需要了解的事情.
|
||||
*
|
||||
* 关于图形函数:
|
||||
* 用过 LovyanGFX / Adafruit GFX / GxEPD2 / TFT_eSPI 库的用户, 可以直接套用他们的接口函数
|
||||
* 用过 U8G2 的用户, 接口函数和U8G2不一样的,
|
||||
* 请参考上述库的示例程序.
|
||||
*
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
@@ -46,14 +120,17 @@
|
||||
*/
|
||||
|
||||
//在这里包含程序需要用到的库函数
|
||||
//就像是你在C语言里面总是用的 #include <stdio.h> 一样,
|
||||
//为了能在这里使用readguy库, 你需要在这里调用 #include "readguy.h" 来包含此库
|
||||
//在platformio中, 还要额外 #include <Arduino.h> 来确保你用的是Arduino环境.
|
||||
|
||||
#include <Arduino.h> //arduino功能基础库. 在platformIO平台上此语句不可或缺
|
||||
#include "readguy.h" //包含readguy_driver 基础驱动库
|
||||
#include "readguy.h" //包含readguy_driver 基础驱动库
|
||||
|
||||
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
|
||||
//所有对墨水屏的操作都是对guy这个对象进行的操作.
|
||||
|
||||
void drawLines(); //声明一个函数, 用于显示一些线条. 此函数在后面的程序中会用到的
|
||||
|
||||
void setup(){
|
||||
void setup(){ //Arduino的setup函数. 这个函数在上电之后仅执行一次.
|
||||
|
||||
// --------------------- 1 - 初始化和启动ReadGuy -------<
|
||||
Serial.begin(115200); //初始化串口
|
||||
@@ -64,19 +141,24 @@ void setup(){
|
||||
guy.init(); //初始化readguy_driver 基础驱动库.
|
||||
|
||||
//首次初始化完成之后, 以后再初始化就不需要配网了, 除非你抹除了芯片的flash
|
||||
//完成之后会全屏刷新一次
|
||||
//完成之后会让下一次刷屏 全屏慢速刷新一次, 之后的刷屏即可自由定义是全刷还是局刷.
|
||||
|
||||
guy.setFont(&FreeMonoBold9pt7b); //设置显示的字体
|
||||
//字体可以参考LovyanGFX的示例程序.
|
||||
|
||||
guy.setTextColor(0,1); //设置显示的颜色. 0代表黑色, 1代表白色
|
||||
//此函数的作用是设置显示颜色. 左边的0代表前景色(文字颜色: 黑色), 右边的1代表背景色(白色)
|
||||
//类似于 guy.setTextColor(0) 的用法说明此颜色为透明背景.
|
||||
|
||||
guy.drawString("Hello Readguy!",10,10); //用此函数将字符串显示到屏幕缓存内
|
||||
//调用此函数并不会立即刷屏, 而是会将文本字符串写入到屏幕缓存, 在下一次调用display()函数之后就会显示出来.
|
||||
|
||||
//也可以用print函数来显示.
|
||||
//guy.setCursor(10,10); //设置显示的坐标
|
||||
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
|
||||
|
||||
guy.display(true); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
|
||||
//guy.display(false); // 慢速刷新.
|
||||
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上. 可简写为 guy.display(), 效果一样.
|
||||
//guy.display(READGUY_SLOW); // 慢速刷新.
|
||||
|
||||
//想知道更多内容, 欢迎移步到其他示例.
|
||||
}
|
||||
@@ -85,6 +167,7 @@ void loop(){
|
||||
|
||||
//什么也不做, 毕竟刷新墨水屏要消耗墨水屏的阳寿.
|
||||
//盖姐说它们也是有阳寿的. 刷多了会老化.
|
||||
delay(1);
|
||||
|
||||
}/* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -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 食用方法:
|
||||
@@ -66,7 +85,6 @@ void setup(){
|
||||
guy.init(); //初始化readguy_driver 基础驱动库.
|
||||
|
||||
//首次初始化完成之后, 以后再初始化就不需要配网了, 除非你抹除了芯片的flash
|
||||
//完成之后会全屏刷新一次
|
||||
|
||||
// ------------------- 2 - 使用ReadGuy来显示字符串 ------<<
|
||||
|
||||
@@ -77,14 +95,15 @@ void setup(){
|
||||
guy.drawString("Hello Readguy!",10,10); //用此函数将字符串显示到屏幕缓存内
|
||||
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
|
||||
|
||||
guy.display(true); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
|
||||
//guy.display(false); // 慢速刷新.
|
||||
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
|
||||
// 但是, 上电初始化之后的首次刷新必为慢速刷新
|
||||
//guy.display(READGUY_SLOW); // 慢速刷新.
|
||||
|
||||
guy.setCursor(10,30); //设置显示的坐标
|
||||
|
||||
guy.print("Hello~"); //或者用print函数在屏幕上打印字符串, 数值, 字符等等... 两种函数都行
|
||||
|
||||
guy.display(false); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
guy.display(READGUY_SLOW); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
|
||||
|
||||
guy.drawString(guy.SDinside()?"SD card OK.":"No SD card!",10,50); //检查readguy是否插入了SD卡
|
||||
@@ -135,7 +154,7 @@ void setup(){
|
||||
|
||||
guy.fillScreen(1);
|
||||
|
||||
guy.display(false); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
guy.display(READGUY_SLOW); // 慢速刷新. 慢刷的对比度显著高于快速刷新, 而且可以消除残影
|
||||
|
||||
for(int i=1;i<16;i++){ //灰度测试, 循环设置不同灰度
|
||||
|
||||
@@ -204,7 +223,7 @@ void setup(){
|
||||
guy.setFont(&FreeMonoBold9pt7b); //设置文本字体
|
||||
guy.setTextColor(0); //设置文本颜色
|
||||
guy.fillScreen(1); //用白色清屏.
|
||||
guy.display(false); //慢刷. 注意, 进行慢刷操作之后, 所有之前显示的灰度内容均会被重新刷成纯黑色
|
||||
guy.display(READGUY_SLOW); //慢刷. 注意, 进行慢刷操作之后, 所有之前显示的灰度内容均会被重新刷成纯黑色
|
||||
//不管是浅灰色还是深灰色, 进行慢刷之后只有黑白色. 原来的非白色像素(浅灰色,深灰色和黑色等) 会全刷成白色.
|
||||
|
||||
guy.drawString("Rotation 0",10,12); //默认旋转方向为0. 实际的默认方向取决于屏幕IC. 大多数屏幕IC是竖屏.
|
||||
@@ -240,13 +259,13 @@ void setup(){
|
||||
guy.setTextColor(1); //设置文本颜色为白色,因为被反色的屏幕的当前像素颜色以黑色像素为主
|
||||
guy.drawString("Wake Up! ~\\(^_^)/~",10,50); //退出睡眠状态
|
||||
|
||||
guy.display(false); //使用慢刷 来唤醒处于低功耗状态下的屏幕.
|
||||
guy.display(READGUY_SLOW); //使用慢刷 来唤醒处于低功耗状态下的屏幕.
|
||||
|
||||
// ------------------ 6 - 可以利用灰度来达到的一些显示效果 --<<<<<<
|
||||
|
||||
guy.fillScreen(1); //清屏
|
||||
|
||||
guy.display(FILL_WHITE,false); //慢刷清屏. 左侧的FILL_WHITE表示 不写入屏幕缓存, 直接刷全白
|
||||
guy.display(FILL_WHITE,READGUY_SLOW); //慢刷清屏. 左侧的FILL_WHITE表示 不写入屏幕缓存, 直接刷全白
|
||||
//可以改为FILL_BLACK来设置写入缓存全黑.
|
||||
//以上的方式均不会修改屏幕缓存中的内容. 右侧的false表示全屏慢刷.
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
*
|
||||
* @file 3_build_without_wifi.ino
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @version 1.0
|
||||
* @date 2023-11-06
|
||||
* @brief ReadGuy最基础的HelloWorld显示, 但不编译WiFi库.
|
||||
*
|
||||
* @note 打开方式:
|
||||
* 1. 深入库文件夹, 找到guy_driver_config.h文件
|
||||
* 2. 找到宏定义 READGUY_ENABLE_WIFI
|
||||
* 3. 注释掉这一行, 就像这样
|
||||
* ```C++
|
||||
* /// 启用WIFI配网功能.必须先启用 #define DYNAMIC_PIN_SETTINGS. 此选项对 ESP32xx 会减少大量flash.
|
||||
* //#define READGUY_ENABLE_WIFI
|
||||
* ```
|
||||
* 4. 回到这里编译运行.
|
||||
* 5. 其实那里的很多功能都能被禁用掉, 直接注释对应的功能定义即可
|
||||
* 但我懒得测试哪些注释掉之后会导致编译不过去, 或是, 鬼找上门.
|
||||
* 6. 运行完本示例之后想要跑其他示例, 记得注释回去, 免得有些功能用不了
|
||||
*
|
||||
* @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 基础驱动库
|
||||
|
||||
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
|
||||
|
||||
void setup(){
|
||||
|
||||
// --------------------- 1 - 初始化和启动ReadGuy -------<
|
||||
Serial.begin(115200); //初始化串口
|
||||
|
||||
//注意: 首次烧录此程序时, 这一步需要你打开手机联esp8266/32的 WiFi, 用于配网.
|
||||
//名称是 readguy 密码 12345678. 连接后访问 192.168.4.1 再在网页中完成后续步骤
|
||||
//后续启动就可以不用这个配置了
|
||||
guy.init(); //初始化readguy_driver 基础驱动库.
|
||||
|
||||
//首次初始化完成之后, 以后再初始化就不需要配网了, 除非你抹除了芯片的flash
|
||||
|
||||
guy.setFont(&FreeMonoBold9pt7b); //设置显示的字体
|
||||
|
||||
guy.setTextColor(0,1); //设置显示的颜色. 0代表黑色, 1代表白色
|
||||
|
||||
guy.drawString("Hello Readguy!",10,10); //用此函数将字符串显示到屏幕缓存内
|
||||
|
||||
guy.drawString("Without WiFi!",10,30); //用此函数将字符串显示到屏幕缓存内
|
||||
|
||||
//guy.setCursor(10,10); //设置显示的坐标
|
||||
//guy.print("Hello Readguy!"); //使用这个函数也能显示出字符串, 但是需要提前使用setCursor确定显示坐标
|
||||
|
||||
guy.display(READGUY_FAST); // 快速刷新. 将屏幕缓存内的内容显示到墨水屏幕上
|
||||
//guy.display(READGUY_SLOW); // 慢速刷新.
|
||||
|
||||
//想知道更多内容, 欢迎移步到其他示例.
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
//什么也不做, 毕竟刷新墨水屏要消耗墨水屏的阳寿.
|
||||
//盖姐说它们也是有阳寿的. 刷多了会老化.
|
||||
|
||||
}/* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 980 KiB After Width: | Height: | Size: 221 KiB |
411
examples/ex06_Image/ex06_Image.ino
Normal file
411
examples/ex06_Image/ex06_Image.ino
Normal file
@@ -0,0 +1,411 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
*
|
||||
* @file ex06_Image.ino
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @version 1.0
|
||||
* @date create: 2023-11-01
|
||||
* last modify: 2023-11-06
|
||||
* @brief ReadGuy 图片显示功能演示.
|
||||
*
|
||||
* - 演示如何将比较大的图片通过多种方法显示到屏幕上.
|
||||
* - 运行的会很缓慢, 因为示例的图片文件比较大.
|
||||
* 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} 代码食用注意事项:
|
||||
* 这一部分的代码很难读, 或者按维莫斯小姐的说法, 很 "抽象" .
|
||||
* 如果你要开始一行一行读取下去, 不妨先在这里停顿一下, 看一下一些需要你提前知道的东西.
|
||||
*
|
||||
* {1} 画布, 或者叫sprite. 是一块专门存储图像的数据结构.
|
||||
* 画布需要大量的内存来存放图像的像素, 但是你可以对画布进行任何图像操作, 就像是在墨水屏上能进行的操作一样多.
|
||||
* 画布类型的数据结构至少需要包含3个要素: 宽度, 高度, 每像素需要的字节数.
|
||||
* 画布需要的内存为 宽度*高度*每像素需要的字节数. (1bit图像需要8分之一字节)
|
||||
* 在画布上可以进行几乎任何图像操作, 就像是在墨水屏上能进行的操作一样多.
|
||||
* 而且你还可以获取像素的颜色 (这和你创建的画布的颜色格式有关).
|
||||
* 画布可以随时被快速的显示到墨水屏上, 显示完了之后再使用display方法, 你刚才创建的画布就显示出来了.
|
||||
*
|
||||
* {2} 屏幕缓存. 你就从来没好奇过, 墨水屏上怎么呈现图像的? 我好奇过.
|
||||
* 我翻看了里面那些错综复杂又是深奥的C++骚操作又是类继承又是虚函数指针...反正就是抽象而且难懂的的源代码,
|
||||
* 简而言之, 墨水屏显示的原理就是墨水屏驱动里面也有个画布, 不过这个画布是1bit的(每8像素消耗1字节内存).
|
||||
* 所有对墨水屏进行的操作其实都是对那个内部的画布进行的操作.
|
||||
* 在你使用墨水屏的display方法时, 呃, 墨水屏的驱动程序可以读取到这个屏幕缓存的所有字节.
|
||||
* 并且根据驱动手册的方法将这个画布上的字节发送到屏幕上.
|
||||
* 发送完成之后再通过一些代码, 墨水屏就会刷屏, 将这个屏幕缓存里的内容显示出来了.
|
||||
* 维莫斯小姐: 苏滴嘶内~
|
||||
* 下面的库其实用了一些更加骚气的方法, 直接读取了这块画布, 从而能允许你在ESP8266上也可以...显示不小的图片
|
||||
*
|
||||
* {3} 灰度显示. ReadGuy这个库的一大特色就是支持灰度显示.
|
||||
* 欸, 可是屏幕缓存画布只有1bit啊, 怎么显示灰度啊?
|
||||
* 不用急, 原理也不难.
|
||||
* 16级灰度颜色的刷屏分为15个步骤. 因为白色不需要刷.
|
||||
* 在开始刷屏之前, 务必进行一次慢刷, 确保所有的白色像素都足够白.
|
||||
* 第一次刷屏, 通常会刷最浅的灰色.
|
||||
* 此时, 首先将屏幕缓存内所有需要显示为这个颜色的像素全写入为黑色(只是名义上的黑色, 实际上是设定的颜色).
|
||||
* 再初始化墨水屏的刷屏功能.
|
||||
* - 此处需要额外设定刷屏的颜色的参数. 此参数设定是可以由驱动程序自动完成的, 不过也可以通过你调用函数完成.
|
||||
* - 用户只需要用简单的setDepth函数设置颜色即可. 用户设定的颜色深度通常用于显示字符串或者形状等GUI控件.
|
||||
* - 刷图程序的灰度图片刷新功能会自动控制刷屏颜色, 不需要手动调用.
|
||||
* 最后刷屏. 因为之前刷图程序已经设定过刷的颜色了, 所以此时刷屏呈现的颜色就是之前设定的颜色.
|
||||
* 第2-15次刷屏原理类似.
|
||||
* 每次追加黑色像素, 追加的像素就是来显示灰度的像素. 而原本的黑色像素就是之前那些灰度颜色的像素.
|
||||
*
|
||||
* \*(^_^)*/ /** 我相信你应该还不懂. 我就举个例子吧.
|
||||
* 比如要显示一个渐变色, 从左到右为白色→黑色的渐变图.
|
||||
* 首先进行一次慢刷, 确保要刷图的地方都是纯洁的白色.
|
||||
* ≡=-(1)-=≡
|
||||
* 筛选出最浅的灰色设为灰1, (灰X代表灰度颜色, 灰15代表黑色)
|
||||
* 再把图片内所有颜色和灰1最接近的颜色写入到屏幕缓存内.
|
||||
* 此时屏幕缓存内的"黑色"部分都是与灰1最接近的颜色, 其他颜色均为"白色"部分.
|
||||
* 刷好了之后, 进行一次刷屏. (系统自动调用setDepth(1)来保证接下来图片的黑色部分其实是灰1).
|
||||
* ≡=-(2)-=≡
|
||||
* 筛选出比最浅的灰色深一点的颜色设为灰2, 把图片内和灰2最接近的颜色写入屏幕缓存, 但保持原本代表灰1的"黑色"不变.
|
||||
* (也就是说, 把灰2的像素写入之后, 屏幕缓存的黑色像素只多不少. 写入过程中, 只能是白→黑, 不存在黑→白)
|
||||
* 此时屏幕缓存内的"黑色"部分包含了与灰2最接近的颜色, 和刚才刷完的与灰1最接近的颜色. 其他颜色均为"白色"部分.
|
||||
* 刷好了之后, 进行一次刷屏. (系统自动调用setDepth(2)来保证接下来图片的黑色部分其实是灰2)
|
||||
* 注意屏幕显示, 原本的灰1并没有颜色变化, 变化的都是本次追加的"灰2"代表的"黑色".
|
||||
* 追加的像素会显示为新设定的颜色.
|
||||
* ≡=-(3)-=≡
|
||||
* 对于灰3, 和灰2一样, 追加显示到屏幕缓存内.
|
||||
* (也就是说, 屏幕缓存的黑色像素还是只多不少. 写入过程中, 只能是白→黑, 不存在黑→白)
|
||||
* 此时屏幕缓存内的"黑色"部分包含了与灰3, 灰2和灰1最接近的颜色. 其他颜色均为"白色"部分.
|
||||
* 设置颜色深度, 刷屏.
|
||||
* 对于灰4~灰15, 都这么做
|
||||
* ≡=-(5)-=≡
|
||||
* 刷完灰15之后, 灰度图就刷完了.
|
||||
*
|
||||
* {4} 自定义刷屏函数. 到底是什么决定了刷屏时的每一像素是什么颜色? 是黑是白?
|
||||
* 其实刷屏的本质就是通过调用一个外部函数.
|
||||
* 该函数可以根据输入的像素坐标位置来决定输出的像素颜色.
|
||||
* 为了简化程序调用过程并提高调用速度, 此处的像素坐标位置参数为一个整数(而不是两个)
|
||||
* 至于该怎么调用这个函数, 并不是你需要了解的事情.
|
||||
*
|
||||
* @note 重要消息: 这是一个实验性功能. 可能你所使用的LGFX库版本较旧而无法通过编译.
|
||||
* 如果你的项目中无法成功编译源码中的setBuffer, 请更改LovyanGFX库的函数!
|
||||
* 位于文件 LovyanGFX/src/lgfx/v1/LGFX_Sprite.hpp
|
||||
* 第155行 void setBuffer 函数:
|
||||
* 修改为如下内容并保存
|
||||
*
|
||||
``` C++
|
||||
void setBuffer(void* buffer, int32_t w, int32_t h, color_depth_t bpp = rgb565_2Byte)
|
||||
{
|
||||
deleteSprite();
|
||||
if (bpp != 0) {
|
||||
_write_conv.setColorDepth(bpp);
|
||||
_read_conv = _write_conv;
|
||||
_panel_sprite.setColorDepth(bpp);
|
||||
}
|
||||
|
||||
_panel_sprite.setBuffer(buffer, w, h, &_write_conv);
|
||||
_img = _panel_sprite.getBuffer();
|
||||
|
||||
_sw = w;
|
||||
_clip_r = w - 1;
|
||||
_xpivot = w >> 1;
|
||||
|
||||
_sh = h;
|
||||
_clip_b = h - 1;
|
||||
_ypivot = h >> 1;
|
||||
}
|
||||
```
|
||||
* 完成后请再次尝试编译
|
||||
* [已经向lovyan03/LovyanGFX发布issue, 等待解决]
|
||||
*
|
||||
* @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 "guy_image.h" //包含 readguy_image 图片功能库. 此库文件放在项目文件夹内.
|
||||
|
||||
constexpr const char * BMP_FILE = "/bmp.bmp"; //在此更改你的图片文件路径名
|
||||
constexpr const char * JPG_FILE = "/jpg.jpg"; //在此更改你的图片文件路径名
|
||||
constexpr const char * PNG_FILE = "/png.png"; //在此更改你的图片文件路径名
|
||||
|
||||
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
|
||||
|
||||
void setup(){
|
||||
|
||||
// 1 - 初始化和启动ReadGuy --------------------- 1 - 初始化和启动ReadGuy -------<
|
||||
Serial.begin(115200); //初始化串口
|
||||
|
||||
guy.init(); //初始化readguy_driver 基础驱动库.
|
||||
|
||||
guy.setRotation(3); //设置旋转方向. 因为此库的功能不随旋转而发生变化.
|
||||
|
||||
// 2 - 显示图片 方式1 --------------------- 2 - 显示图片 方式1:使用readguy提供的drawImage方法. ------<<
|
||||
|
||||
//此功能可以在 画布{1}(Sprite) 绘制图片, 再使用内置的drawImage方法来显示出这个sprite.
|
||||
//此方法消耗的内存颇多, 需要为整个sprite分配所有内存才能成功绘制.
|
||||
//由于目前版本LovyanGFX的限制, 不能分配4bit的画布, 只能分配大小至少为8bit的画布.
|
||||
|
||||
guy.fillScreen(1); //清屏
|
||||
//guy.display(); //显示白屏,用于将来显示图片.
|
||||
LGFX_Sprite sp(&guy); //创建一个 画布(Sprite) (可以存储一些像素, 快速读写)
|
||||
sp.setColorDepth(lgfx::v1::color_depth_t::grayscale_8bit); //设置画布sprite的色彩深度
|
||||
sp.createSprite(80,80); //为刚刚创建的画布对象分配内存 (像素宽度*像素高度). 此处为80(宽)*80(高)像素
|
||||
sp.drawBmpFile(guy.guyFS(),BMP_FILE,0,0); //从文件创建BMP图像信息. 文件系统内必须要有这个BMP图像.
|
||||
//默认的文件系统为SD卡. 当没有插入SD卡时, 会读取LittleFS文件系统.
|
||||
//没有条件准备文件系统的, 可以烧录文件系统.
|
||||
Serial.printf("[%lu] sp.w: %d, h: %d, res: %im.\n",millis(),sp.width(),sp.height(),ESP.getFreeHeap());
|
||||
guy.drawImage(sp,9,11); //使用抖动像素的方式显示图片(不是灰度, 只有黑点和白点的那种显示效果)
|
||||
//sp为要显示的画布, 后面的9 11都是要显示的目标坐标位置. 此处代表将画布显示在 屏幕缓存{2} 的第9列, 第11行.
|
||||
Serial.printf("[%lu] drawn dithering bmp.\n",millis()); //显示信息
|
||||
guy.display(); //1.2.0版本之后, drawImage不再刷屏, 需要额外调用display函数刷屏.
|
||||
delay(2000);
|
||||
|
||||
|
||||
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,READGUY_FAST); //在保持屏幕缓存不变的时候快速刷新白屏
|
||||
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
|
||||
guy.drawImage(sp,10,10,65,50); //缩放: 缩小到65X50
|
||||
guy.display(); //调用display函数刷屏.
|
||||
delay(2000);
|
||||
|
||||
|
||||
//以下函数可以允许你用灰度显示画布.
|
||||
//在刷灰度之前, 该函数可以对刷屏区域自动慢刷白屏.
|
||||
//0-关闭连续刷屏 开启16阶灰度抖动. 连续刷屏并非所有的屏幕都支持. 所以此处使用了一个函数检验.
|
||||
if(guy.supportGreyscaling()==-16){ //此函数返回-16代表支持连续刷屏. 返回16代表支持灰度, 返回0代表仅黑白.
|
||||
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
|
||||
guy.setGreyQuality(0); //设置刷屏方式:0-关闭连续刷屏, 开启16阶灰度抖动.
|
||||
guy.draw16grey(sp,9,9); //使用16级灰度的方式显示图片 需要的时间比较长
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
//1-开启连续刷屏 开启16阶灰度抖动 (默认值)
|
||||
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
|
||||
guy.setGreyQuality(1); //设置刷屏方式:1-开启连续刷屏, 开启16阶灰度抖动. 在初始化时, 这是默认值.
|
||||
guy.draw16grey(sp,12,12,120,120); //使用16级灰度的方式显示图片. 后两个参数120代表缩放之后的宽度高度
|
||||
delay(2000);
|
||||
|
||||
//2-关闭连续刷屏 关闭16阶灰度抖动. 连续刷屏并非所有的屏幕都支持. 所以此处使用了一个函数检验.
|
||||
if(guy.supportGreyscaling()==-16){ //此函数返回-16代表支持连续刷屏. 返回16代表支持灰度, 返回0代表仅黑白.
|
||||
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
|
||||
guy.setGreyQuality(2); //2-关闭连续刷屏, 关闭16阶灰度抖动
|
||||
guy.draw16grey(sp,9,9,50,100); //使用16级灰度的方式显示图片. 参数50和100分别代表宽度缩放和高度缩放
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
//3-开启连续刷屏 关闭16阶灰度抖动
|
||||
guy.fillScreen(1); //白屏清屏(清屏幕缓存)
|
||||
guy.setGreyQuality(3); //3-打开连续刷屏, 关闭16阶灰度抖动
|
||||
guy.draw16grey(sp,3,3,100,50); //使用16级灰度的方式显示图片 参数100和50分别代表宽度缩放和高度缩放
|
||||
delay(2000);
|
||||
|
||||
//灰度显示画布到此显示完了
|
||||
sp.deleteSprite(); //关闭画布, 释放图片占用的大量内存
|
||||
Serial.printf("[%lu] drawn 16-layer greyscale bmp.\n",millis()); //显示信息
|
||||
delay(2000);
|
||||
|
||||
|
||||
// 3 - 显示图片 方式2 --------------------- 3 - 显示图片 方式2:使用readguyImage类. -----<<<
|
||||
|
||||
//readguy驱动程序的内部有一个屏幕缓存, 可以用于存储显示引擎显示的内容, 在刷屏时 直接发送此缓存的内容.
|
||||
//显示引擎会通过显示函数, 来改写屏幕缓存的内容. (显示就是这样显示的. 类似于print, drawPixel, fillRect...)
|
||||
|
||||
//此绘制方式可以做到几乎不消耗额外的内存, 仅需要屏幕缓存即可显示图片.
|
||||
//适合用在esp8266或者消耗的内存较多的项目上.
|
||||
//显示原理比较复杂, 因为显示函数的限制, 图片不能直接显示到屏幕缓存中.
|
||||
//大体上说就是用屏幕缓存作为显示图片的中间内存, 再分阶段解码图片, 最后通过自定义刷屏函数, 完成刷新图片
|
||||
//使用此方法, 因为屏幕缓存被复用作图片解码中间内存, 屏幕缓存上原本的内容会因为图片解码而发生改变.
|
||||
|
||||
//不需要指定额外的外部内存.
|
||||
|
||||
//显示BMP格式
|
||||
readguyImage im(guy); //定义一个绘制器, 此类中的函数用于绘制图片.
|
||||
//所有的绘制图片的参数均需要放入此结构内
|
||||
//直接更改im内的数据即可设置绘制参数. (就像结构体一样用它)
|
||||
im.baseFs=&guy.guyFS(); //在此处就是设置文件系统.
|
||||
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
//建议在使用drawImageFile函数之前, 使用慢刷刷白屏, 可以保证显示效果清晰可见.
|
||||
|
||||
im.drawImageFile(); //显示BMP格式.图片. im会自动识别文件扩展名并绘制.
|
||||
//此处不再需要调用 guy.display() 函数即可显示.
|
||||
//此时显示缓存已经清空(因为显示缓存内原本是用来解码图片用的)
|
||||
//此时直接使用guy.display()将刷白屏.
|
||||
|
||||
delay(2000);
|
||||
|
||||
|
||||
//显示JPG格式
|
||||
im.filename=JPG_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
im.scalex=0.3333333f; //设置横坐标图片缩放
|
||||
im.scaley=0.3333333f; //设置纵坐标图片缩放.
|
||||
im.offsetx=70; //设置显示偏移. 此处的70说明 JPG图像应该从图片文件的(70,40)坐标处开始解码
|
||||
im.offsety=40; //设置显示偏移Y轴方向.
|
||||
|
||||
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
|
||||
im.drawImageFile(); //显示JPG格式.图片. im会自动识别文件扩展名并绘制.
|
||||
delay(2000);
|
||||
|
||||
|
||||
#ifndef ESP8266 //显示PNG格式. ESP8266不支持PNG格式.
|
||||
im.filename=PNG_FILE; //PNG图片. ESP8266的内存不够, 所以不能显示PNG格式~(T_T)~
|
||||
|
||||
im.x=10; //设置在哪里绘制图片. 在此编辑图片绘制起始点的 X, Y 坐标
|
||||
im.y=5 ; //
|
||||
im.scalex=400.0f/1280.0f;
|
||||
im.scaley=300.0f/576.0f;
|
||||
|
||||
guy.display(FILL_WHITE, READGUY_SLOW);//显示. 此处的功能就是将显示缓存输出到屏幕上
|
||||
|
||||
im.drawImageFile(); //显示PNG格式.图片. ESP8266可能不会绘制.
|
||||
delay(2000);
|
||||
|
||||
#endif
|
||||
|
||||
//开启灰度显示, 然后显示BMP格式
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
im.scalex=0.75f; //设置横坐标图片缩放
|
||||
im.scaley=0.5625f; //设置纵坐标图片缩放.
|
||||
im.offsetx=0; //设置显示偏移. 此处的70说明 JPG图像应该从图片文件的(70,40)坐标处开始解码
|
||||
im.offsety=0; //设置显示偏移Y轴方向.
|
||||
|
||||
im.background=1; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
//预分配内存, 可以用作显示缓存.
|
||||
#ifdef ESP8266
|
||||
#define MEM_POOL 10000
|
||||
#else
|
||||
#define MEM_POOL 60000
|
||||
#endif
|
||||
|
||||
uint8_t *buf = new uint8_t [MEM_POOL]; //分配缓存
|
||||
im.exPool=buf; //设置外部缓存内存地址
|
||||
im.exPoolSize=MEM_POOL; //设置外部缓存内存大小
|
||||
|
||||
guy.setGreyQuality(1); //设置灰度模式为默认灰度显示模式
|
||||
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将显示灰度图.
|
||||
|
||||
im.enableFloyd=0; //禁用掉抖动算法.
|
||||
|
||||
im.drawImageFile(1); //显示JPG格式.图片.
|
||||
|
||||
delay(2000);
|
||||
|
||||
guy.display(FILL_WHITE,READGUY_SLOW); //将屏幕全刷成白屏. 为了即将显示灰度图.
|
||||
|
||||
im.enableFloyd=1; // 重新启用抖动算法.
|
||||
|
||||
im.drawImageFile(1); //显示JPG格式.图片.
|
||||
|
||||
delay(5000);
|
||||
|
||||
delete [] buf; //缓存用完了, 释放内存.
|
||||
im.exPool=nullptr; //用完之后将这个内存地址置为null, 避免重复使用导致内存不可访问.
|
||||
im.exPoolSize=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------- 4 - 显示图片 使用readguyImage类的externalBuffer绘制到主屏幕缓存. -----<<<
|
||||
|
||||
//实现原理: 通过一个额外的缓存, 显示引擎可以分多次将图片显示在这个额外的内存中, 再将这块内存写入到缓存内.
|
||||
//由于用了外部内存, 所以可以分多次显示一张大图片, 相比于分配整张大图片的内存, 要更节省内存.代价是速度更慢
|
||||
|
||||
//readguy驱动程序的内部有一个屏幕缓存, 如果使用这个缓存来显示图片, 屏幕上原本的东西也会变得混乱.(上个示例)
|
||||
//因此, readguyImage类提供了使用外部内存的显示功能.
|
||||
//分为多次, 每次将图片的一小部分显示到外部内存中, 再写入到屏幕缓存内.
|
||||
|
||||
//需要提供额外分配好的内存, 但此函数不会更改显示区域之外的显示缓存.
|
||||
|
||||
guy.fillScreen(1); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
|
||||
for(int i=1;i<10;i++){ //在屏幕上绘画线段. 本质是更改显示缓存.
|
||||
guy.drawLine(i*guy.width()/10,0,0,i*guy.height()/10,0);
|
||||
guy.drawLine(i*guy.width()/10,guy.height()-1,guy.width()-1,i*guy.height()/10,0);
|
||||
}
|
||||
guy.drawLine(guy.width(),0,0,guy.height(),0);
|
||||
|
||||
guy.display(READGUY_SLOW); //刷新屏幕, 显示绘画的线段
|
||||
|
||||
//im.baseFs=&guy.guyFS(); //直接更改im内的数据即可设置绘制参数. 在此处就是设置文件系统.
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
im.x=15; //设置将要显示的横坐标
|
||||
im.y=15; //设置将要显示的纵坐标
|
||||
im.w=180; //设置将要显示区域的宽度
|
||||
im.h=270; //设置将要显示区域的高度
|
||||
im.offsetx=0; //如果不从左上角开始解码图片, 从哪个坐标开始显示/解码图片?
|
||||
im.offsety=0;
|
||||
im.scalex=0.5625f; //设置横坐标缩放.
|
||||
im.scaley=0.5625f; //设置纵坐标缩放. 为0代表与横坐标缩放相同.
|
||||
|
||||
buf = new uint8_t [ 60*270 ]; //分配缓存
|
||||
im.exPool=buf; //设置外部缓存内存地址
|
||||
im.exPoolSize=60*270; //设置外部缓存内存大小
|
||||
|
||||
im.drawImageToBuffer(); //将图片写入到屏幕缓存. im会自动识别文件扩展名并绘制.
|
||||
|
||||
guy.display(); //显示缓存.此时应当能看到图片.
|
||||
|
||||
delete [] buf; //缓存用完了, 释放内存.
|
||||
im.exPool=nullptr; //用完之后将这个内存地址置为null, 避免重复使用导致内存不可访问.
|
||||
im.exPoolSize=0;
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
delay(1);
|
||||
}/* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -80,9 +80,11 @@ uint8_t readguyImage::drawImgHandler(int r, LGFX_Sprite *spr){
|
||||
case 1:
|
||||
spr->drawBmpFile(*baseFs,filename,_x,_y,0,0,offsetx+xd,offsety+yd,scalex,scaley,datum);
|
||||
break;
|
||||
#ifndef ESP8266
|
||||
case 2:
|
||||
spr->drawPngFile(*baseFs,filename,_x,_y,0,0,offsetx+xd,offsety+yd,scalex,scaley,datum);
|
||||
break;
|
||||
#endif
|
||||
case 3:
|
||||
spr->drawJpgFile(*baseFs,filename,_x,_y,0,0,offsetx+xd,offsety+yd,scalex,scaley,datum);
|
||||
break;
|
||||
@@ -224,15 +226,15 @@ void readguyImage::drawImageFile(bool use16grey){
|
||||
//Serial.printf("filename: %s, exname: %s\n",filename,ex);
|
||||
|
||||
//图片将会分割成8个部分, 分块绘制, 节省内存.
|
||||
w=(guy->memWidth()+7)&0x7ffffff8; //guy->guyMemoryWidth() 返回不随旋转参数而改变的显示内存宽度
|
||||
w=(guy->drvWidth()+7)&0x7ffffff8; //guy->guyMemoryWidth() 返回不随旋转参数而改变的显示内存宽度
|
||||
if(!w) return; //保证宽度>0
|
||||
h=guy->memHeight();
|
||||
h=guy->drvHeight();
|
||||
if(exPoolSize>guy->bufferLength()){ //当外部缓存的像素超过屏幕缓存时,使用外部缓存作为主缓冲区
|
||||
_h=exPoolSize/w;
|
||||
_pool=exPool;
|
||||
}
|
||||
if(_pool==nullptr) {
|
||||
_h=(h+7)>>3; //设置缓存区的高度. 更多内存将可以更快显示
|
||||
_h=h>>3; //设置缓存区的高度. 更多内存将可以更快显示
|
||||
_pool=(uint8_t *)guy->getBuffer();
|
||||
}
|
||||
//(guy->guyMemoryHeight()+7)>>3 返回高度,并补齐后右移三位 (等效于除以2³, 分成8份)
|
||||
@@ -250,8 +252,10 @@ void readguyImage::drawImageFile(bool use16grey){
|
||||
//随后打开图片进行解码. 可选显示的位置和宽度高度参数, 屏幕上的其他部分则会变成白色.
|
||||
if(strcmp(ex,"bmp") == 0 || strcmp(ex,"BMP") == 0) //BMP格式, 绘制BMP图片
|
||||
format|=1; //BMP格式
|
||||
#ifndef ESP8266
|
||||
else if(strcmp(ex,"png") == 0 || strcmp(ex,"PNG") == 0) //PNG格式, 绘制PNG图片
|
||||
format|=2; //PNG格式
|
||||
#endif
|
||||
else if(strcmp(ex,"jpg") == 0 || strcmp(ex,"JPG") == 0 || strcmp(ex,"jpeg") == 0 || strcmp(ex,"JPEG") == 0)
|
||||
format|=3; //JPG格式
|
||||
else return; //未知格式
|
||||
@@ -271,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);
|
||||
// 此函数过不了编译 需要改库.
|
||||
}
|
||||
|
||||
@@ -291,8 +295,10 @@ uint8_t readguyImage::drawImageToBuffer(){
|
||||
|
||||
if(strcmp(ex,"bmp") == 0 || strcmp(ex,"BMP") == 0) //BMP格式, 绘制BMP图片
|
||||
format|=1; //BMP格式
|
||||
#ifndef ESP8266
|
||||
else if(strcmp(ex,"png") == 0 || strcmp(ex,"PNG") == 0) //PNG格式, 绘制PNG图片
|
||||
format|=2; //PNG格式
|
||||
#endif
|
||||
else if(strcmp(ex,"jpg") == 0 || strcmp(ex,"JPG") == 0 || strcmp(ex,"jpeg") == 0 || strcmp(ex,"JPEG") == 0)
|
||||
format|=3; //JPG格式
|
||||
else return 2; //未知格式
|
||||
@@ -310,9 +316,11 @@ uint8_t readguyImage::drawImageToBuffer(){
|
||||
case 1:
|
||||
spr.drawBmpFile(*baseFs,filename,0,0,0,0,offsetx,offsety+_h*i,scalex,scaley);
|
||||
break;
|
||||
#ifndef ESP8266
|
||||
case 2:
|
||||
spr.drawPngFile(*baseFs,filename,0,0,0,0,offsetx,offsety+_h*i,scalex,scaley);
|
||||
break;
|
||||
#endif
|
||||
case 3:
|
||||
spr.drawJpgFile(*baseFs,filename,0,0,0,0,offsetx,offsety+_h*i,scalex,scaley);
|
||||
break;
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
*
|
||||
* @file ex06_Image.ino
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @version 1.0
|
||||
* @date 2023-11-01
|
||||
* @brief ReadGuy 图片显示功能演示.
|
||||
* 1. 在运行过ex01或者ex02的开发板上 编译烧录本程序.
|
||||
* 2. 将该项目data文件夹内的所有文件放置于SD卡的根目录上.
|
||||
*
|
||||
* @note 重要消息: 这是一个实验性功能. 可能你所使用的LGFX库版本较旧而无法通过编译.
|
||||
* 如果你的项目中无法成功编译源码中的setBuffer, 请更改LovyanGFX库的函数!
|
||||
* 位于文件 LovyanGFX/src/lgfx/v1/LGFX_Sprite.hpp
|
||||
* 第155行 void setBuffer 函数:
|
||||
* 修改为如下内容并保存
|
||||
*
|
||||
``` C++
|
||||
void setBuffer(void* buffer, int32_t w, int32_t h, color_depth_t bpp = rgb565_2Byte)
|
||||
{
|
||||
deleteSprite();
|
||||
if (bpp != 0) {
|
||||
_write_conv.setColorDepth(bpp);
|
||||
_read_conv = _write_conv;
|
||||
_panel_sprite.setColorDepth(bpp);
|
||||
}
|
||||
|
||||
_panel_sprite.setBuffer(buffer, w, h, &_write_conv);
|
||||
_img = _panel_sprite.getBuffer();
|
||||
|
||||
_sw = w;
|
||||
_clip_r = w - 1;
|
||||
_xpivot = w >> 1;
|
||||
|
||||
_sh = h;
|
||||
_clip_b = h - 1;
|
||||
_ypivot = h >> 1;
|
||||
}
|
||||
```
|
||||
* 完成后请再次尝试编译
|
||||
* [已经向lovyan03/LovyanGFX发布issue, 等待解决]
|
||||
*
|
||||
* @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 "guy_image.h" //包含 readguy_image 图片功能库. 此库文件放在项目文件夹内.
|
||||
|
||||
constexpr const char * BMP_FILE = "/bmp.bmp"; //在此更改你的图片文件路径名
|
||||
constexpr const char * JPG_FILE = "/jpg.jpg"; //在此更改你的图片文件路径名
|
||||
constexpr const char * PNG_FILE = "/png.png"; //在此更改你的图片文件路径名
|
||||
|
||||
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
|
||||
|
||||
void setup(){
|
||||
|
||||
// 1 - 初始化和启动ReadGuy --------------------- 1 - 初始化和启动ReadGuy -------<
|
||||
Serial.begin(115200); //初始化串口
|
||||
|
||||
guy.init(); //初始化readguy_driver 基础驱动库.
|
||||
guy.setRotation(3); //设置旋转. 旋转属性不会影响图片显示的所有功能
|
||||
|
||||
// 2 - 显示图片 方式1 --------------------- 2 - 显示图片 方式1:使用readguy提供的drawImage方法. ------<<
|
||||
|
||||
//此功能可以在Sprite绘制图片, 再使用内置的drawImage方法来显示出这个sprite.
|
||||
//此方法消耗的内存颇多, 需要整个sprite才能成功绘制.
|
||||
guy.fillScreen(1); //清屏
|
||||
guy.display(); //显示白屏,用于将来显示图片.
|
||||
LGFX_Sprite sp(&guy); //创建一个Sprite (可以存储一些像素, 快速读写)
|
||||
sp.setColorDepth(lgfx::v1::color_depth_t::grayscale_8bit); //设置sprite的色彩深度
|
||||
sp.createSprite(80,80); //从文件创建BMP图像信息.
|
||||
sp.drawBmpFile(guy.guyFS(),BMP_FILE,0,0); //显示JPG文件
|
||||
Serial.printf("[%lu] sp.w: %d, h: %d, res: %im.\n",millis(),sp.width(),sp.height(),ESP.getFreeHeap());
|
||||
guy.drawImage(sp,9,9); //使用抖动像素的方式显示图片(不是灰度, 只有黑点和白点的那种显示效果)
|
||||
Serial.printf("[%lu] drawn dithering bmp.\n",millis()); //显示信息
|
||||
guy.display(); //1.2.0版本之后, drawImage不再刷屏, 需要额外调用display函数刷屏.
|
||||
delay(2000);
|
||||
|
||||
//0-关闭连续刷屏 开启16阶灰度抖动
|
||||
guy.setGreyQuality(0); //部分屏幕允许使用不同的灰度显示模式.
|
||||
guy.draw16grey(sp,9,9); //使用16级灰度的方式显示图片 需要的时间比较长
|
||||
delay(2000);
|
||||
|
||||
//1-开启连续刷屏 开启16阶灰度抖动 (默认值)
|
||||
guy.setGreyQuality(1); //部分屏幕允许使用不同的灰度显示模式.
|
||||
guy.draw16grey(sp,9,9); //使用16级灰度的方式显示图片 需要的时间比较长
|
||||
delay(2000);
|
||||
|
||||
//2-关闭连续刷屏 关闭16阶灰度抖动
|
||||
guy.setGreyQuality(2); //部分屏幕允许使用不同的灰度显示模式.
|
||||
guy.draw16grey(sp,9,9); //使用16级灰度的方式显示图片 需要的时间比较长
|
||||
delay(2000);
|
||||
|
||||
//3-开启连续刷屏 关闭16阶灰度抖动
|
||||
guy.setGreyQuality(3); //部分屏幕允许使用不同的灰度显示模式.
|
||||
guy.draw16grey(sp,9,9); //使用16级灰度的方式显示图片 需要的时间比较长
|
||||
delay(2000);
|
||||
|
||||
sp.deleteSprite(); //关闭图片文件, 释放图片占用的大量内存
|
||||
Serial.printf("[%lu] drawn 16-layer greyscale bmp.\n",millis()); //显示信息
|
||||
delay(2000);
|
||||
|
||||
|
||||
// 3 - 显示图片 方式2 --------------------- 3 - 显示图片 方式2:使用readguyImage类. -----<<<
|
||||
|
||||
//readguy驱动程序的内部有一个屏幕缓存, 可以用于存储显示引擎显示的内容, 在刷屏时 直接发送此缓存的内容.
|
||||
//显示引擎会通过显示函数, 来改写屏幕缓存的内容. (显示就是这样显示的. 类似于print, drawPixel, fillRect...)
|
||||
|
||||
//此绘制方式可以做到几乎不消耗额外的内存, 仅需要屏幕缓存即可显示图片.
|
||||
//适合用在esp8266或者消耗的内存较多的项目上.
|
||||
//显示原理比较复杂, 因为显示函数的限制, 图片不能直接显示到屏幕缓存中.
|
||||
//大体上说就是用屏幕缓存作为显示图片的中间内存, 再分阶段解码图片, 最后通过自定义刷屏函数, 完成刷新图片
|
||||
//使用此方法, 因为屏幕缓存被复用作图片解码中间内存, 屏幕缓存上原本的内容会因为图片解码而发生改变.
|
||||
|
||||
//不需要指定额外的外部内存.
|
||||
|
||||
//显示BMP格式
|
||||
readguyImage im(guy); //定义一个绘制器, 此类中的函数用于绘制图片.
|
||||
//所有的绘制图片的参数均需要放入此结构内
|
||||
//直接更改im内的数据即可设置绘制参数. (就像结构体一样用它)
|
||||
im.baseFs=&guy.guyFS(); //在此处就是设置文件系统.
|
||||
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
//建议在使用drawImageFile函数之前, 使用慢刷刷白屏, 可以保证显示效果清晰可见.
|
||||
|
||||
im.drawImageFile(); //显示BMP格式.图片. im会自动识别文件扩展名并绘制.
|
||||
//此处不再需要调用 guy.display() 函数即可显示.
|
||||
//此时显示缓存已经清空(因为显示缓存内原本是用来解码图片用的)
|
||||
//此时直接使用guy.display()将刷白屏.
|
||||
|
||||
delay(2000);
|
||||
|
||||
|
||||
//显示JPG格式
|
||||
im.filename=JPG_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
im.scalex=0.3333333f; //设置横坐标图片缩放
|
||||
im.scaley=0.3333333f; //设置纵坐标图片缩放.
|
||||
im.offsetx=70; //设置显示偏移. 此处的70说明 JPG图像应该从图片文件的(70,40)坐标处开始解码
|
||||
im.offsety=40; //设置显示偏移Y轴方向.
|
||||
|
||||
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
|
||||
im.drawImageFile(); //显示JPG格式.图片. im会自动识别文件扩展名并绘制.
|
||||
delay(2000);
|
||||
|
||||
|
||||
#ifndef ESP8266 //显示PNG格式. ESP8266不支持PNG格式
|
||||
im.filename=PNG_FILE; //PNG图片. ESP8266的内存不够, 所以不能显示PNG格式~(T_T)~
|
||||
|
||||
im.x=10; //设置在哪里绘制图片. 在此编辑图片绘制起始点的 X, Y 坐标
|
||||
im.y=5 ; //
|
||||
im.scalex=400.0f/1280.0f;
|
||||
im.scaley=300.0f/576.0f;
|
||||
|
||||
guy.display(FILL_WHITE, false); //显示. 此处的功能就是将显示缓存输出到屏幕上
|
||||
|
||||
im.drawImageFile(); //显示JPG格式.图片. ESP8266可能不会绘制.
|
||||
delay(2000);
|
||||
|
||||
#endif
|
||||
|
||||
//开启灰度显示, 然后显示BMP格式
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
im.scalex=0.75f; //设置横坐标图片缩放
|
||||
im.scaley=0.5625f; //设置纵坐标图片缩放.
|
||||
im.offsetx=0; //设置显示偏移. 此处的70说明 JPG图像应该从图片文件的(70,40)坐标处开始解码
|
||||
im.offsety=0; //设置显示偏移Y轴方向.
|
||||
|
||||
im.background=1; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
#ifdef ESP8266
|
||||
#define MEM_POOL 10000
|
||||
#else
|
||||
#define MEM_POOL 60000
|
||||
#endif
|
||||
|
||||
uint8_t *buffer = new uint8_t [ MEM_POOL ]; //分配缓存
|
||||
im.exPool=buffer; //设置外部缓存内存地址
|
||||
im.exPoolSize=MEM_POOL; //设置外部缓存内存大小
|
||||
|
||||
guy.setGreyQuality(1); //设置灰度模式为默认灰度显示模式
|
||||
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将显示灰度图.
|
||||
|
||||
im.enableFloyd=0; //禁用掉抖动算法.
|
||||
|
||||
im.drawImageFile(1); //显示JPG格式.图片.
|
||||
|
||||
delay(2000);
|
||||
|
||||
guy.display(FILL_WHITE,false); //将屏幕全刷成白屏. 为了即将显示灰度图.
|
||||
|
||||
im.enableFloyd=1; // 重新启用抖动算法.
|
||||
|
||||
im.drawImageFile(1); //显示JPG格式.图片.
|
||||
|
||||
delay(5000);
|
||||
|
||||
delete []buffer;
|
||||
im.exPool=nullptr; //用完之后将这个内存地址置为null, 避免重复使用导致内存不可访问.
|
||||
im.exPoolSize=0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// 灰度测试代码 -------------------------------------------------------------------------- 灰度测试代码
|
||||
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
guy.setGreyQuality(0);
|
||||
|
||||
guy.display(FILL_WHITE, false);
|
||||
|
||||
#ifdef ESP8266
|
||||
#define MEM_POOL 10000
|
||||
#else
|
||||
#define MEM_POOL 60000
|
||||
#endif
|
||||
uint8_t *buffer = new uint8_t [ MEM_POOL ]; //分配缓存
|
||||
im.exPool=buffer; //设置外部缓存内存地址
|
||||
im.exPoolSize=MEM_POOL; //设置外部缓存内存大小
|
||||
|
||||
im.enableFloyd = 0;
|
||||
im.drawImageFile(true); //显示BMP格式.图片. im会自动识别文件扩展名并绘制.
|
||||
//此处不再需要调用 guy.display() 函数即可显示.
|
||||
//此时显示缓存已经清空(因为显示缓存内原本是用来解码图片用的)
|
||||
//此时直接使用guy.display()将刷白屏.
|
||||
|
||||
delay(3000);
|
||||
|
||||
guy.display(FILL_WHITE,false);
|
||||
|
||||
im.enableFloyd = 1;
|
||||
guy.setGreyQuality(1);
|
||||
im.drawImageFile(true); //显示BMP格式.图片. im会自动识别文件扩展名并绘制.
|
||||
|
||||
delay(3000);
|
||||
|
||||
//显示JPG格式
|
||||
im.filename=JPG_FILE; //在此直接设置文件路径和文件名.
|
||||
|
||||
im.scalex=1.3333333f;
|
||||
im.scaley=1.3333333f;
|
||||
|
||||
//im.scalex=0.3333333f; //设置横坐标图片缩放
|
||||
//im.scaley=0.3333333f; //设置纵坐标图片缩放.
|
||||
//im.offsetx=70; //设置显示偏移. 此处的70说明 JPG图像应该从图片文件的(70,40)坐标处开始解码
|
||||
//im.offsety=40; //设置显示偏移Y轴方向.
|
||||
|
||||
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
guy.display(FILL_WHITE, false);
|
||||
|
||||
im.drawImageFile(); //显示JPG格式.图片. im会自动识别文件扩展名并绘制.
|
||||
delete []buffer;
|
||||
|
||||
// 灰度测试代码 -------------------------------------------------------------------------- 灰度测试代码
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------- 4 - 显示图片 使用readguyImage类的externalBuffer绘制到主屏幕缓存. -----<<<
|
||||
|
||||
//实现原理: 通过一个额外的缓存, 显示引擎可以分多次将图片显示在这个额外的内存中, 再将这块内存写入到缓存内.
|
||||
//由于用了外部内存, 所以可以分多次显示一张大图片, 相比于分配整张大图片的内存, 要更节省内存.代价是速度更慢
|
||||
|
||||
//readguy驱动程序的内部有一个屏幕缓存, 如果使用这个缓存来显示图片, 屏幕上原本的东西也会变得混乱.(上个示例)
|
||||
//因此, readguyImage类提供了使用外部内存的显示功能.
|
||||
//分为多次, 每次将图片的一小部分显示到外部内存中, 再写入到屏幕缓存内.
|
||||
|
||||
//需要提供额外分配好的内存, 但此函数不会更改显示区域之外的显示缓存.
|
||||
|
||||
guy.fillScreen(1); //将屏幕全刷成白屏. 为了即将的图片刷新.
|
||||
|
||||
for(int i=1;i<10;i++){ //在屏幕上绘画线段. 本质是更改显示缓存.
|
||||
guy.drawLine(i*guy.width()/10,0,0,i*guy.height()/10,0);
|
||||
guy.drawLine(i*guy.width()/10,guy.height()-1,guy.width()-1,i*guy.height()/10,0);
|
||||
}
|
||||
guy.drawLine(guy.width(),0,0,guy.height(),0);
|
||||
|
||||
guy.display(false); //刷新屏幕, 显示绘画的线段
|
||||
|
||||
//im.baseFs=&guy.guyFS(); //直接更改im内的数据即可设置绘制参数. 在此处就是设置文件系统.
|
||||
im.filename=BMP_FILE; //在此直接设置文件路径和文件名.
|
||||
im.background=0; //设置背景颜色, 0黑1白, 此处设为背景色为黑色.
|
||||
|
||||
im.x=15; //设置将要显示的横坐标
|
||||
im.y=15; //设置将要显示的纵坐标
|
||||
im.w=180; //设置将要显示区域的宽度
|
||||
im.h=270; //设置将要显示区域的高度
|
||||
im.offsetx=0; //如果不从左上角开始解码图片, 从哪个坐标开始显示/解码图片?
|
||||
im.offsety=0;
|
||||
im.scalex=0.5625f; //设置横坐标缩放.
|
||||
im.scaley=0.5625f; //设置纵坐标缩放. 为0代表与横坐标缩放相同.
|
||||
|
||||
buffer = new uint8_t [ 60*270 ]; //分配缓存
|
||||
im.exPool=buffer; //设置外部缓存内存地址
|
||||
im.exPoolSize=60*270; //设置外部缓存内存大小
|
||||
|
||||
im.drawImageToBuffer(); //将图片写入到屏幕缓存. im会自动识别文件扩展名并绘制.
|
||||
|
||||
guy.display(); //显示缓存.此时应当能看到图片.
|
||||
|
||||
delete []buffer;
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
delay(1);
|
||||
}/* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
74
extra/guy_driver_template/guy_template/guy_template.cpp
Normal file
74
extra/guy_driver_template/guy_template/guy_template.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_template.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 template 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 template 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_template.h"
|
||||
#ifdef READGUY_DEV_template
|
||||
namespace guydev_template{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
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...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
extra/guy_driver_template/guy_template/guy_template.h
Normal file
63
extra/guy_driver_template/guy_template/guy_template.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_template.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 template 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 template 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPDtemplate_H_FILE) && (defined(READGUY_DEV_template)))
|
||||
#define _GUY_EPDtemplate_H_FILE
|
||||
|
||||
namespace guydev_template{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
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); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
23
extra/guy_driver_template/readme.md
Normal file
23
extra/guy_driver_template/readme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# 添加新驱动程序
|
||||
|
||||
1. 将文件夹 guy_template 整个拷贝到 guy_epaper 文件夹下
|
||||
|
||||
2. 根据里面的模板文件, 添加自定义驱动.
|
||||
|
||||
3. 使用查找工具搜索 src 下的以下文本.
|
||||
|
||||
```
|
||||
//添加新屏幕型号 add displays here
|
||||
```
|
||||
|
||||
然后把新加入的屏幕驱动 define 给加上
|
||||
|
||||
4. 更新 `EPD_DRIVERS_NUM_MAX` 变量, 表明一共有多少个驱动可用.
|
||||
|
||||
5. 加好了之后, 应该就可以使用这个驱动了.
|
||||
|
||||
6. 记得更改项目根目录的 readme 文件
|
||||
|
||||
# 禁用驱动程序
|
||||
|
||||
前往 guy_epaper_config.h 文件, 注释掉不需要编译的驱动文件即可
|
||||
@@ -971,7 +971,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
|
||||
#
|
||||
# TLS Key Exchange Methods
|
||||
#
|
||||
# CONFIG_MBEDTLS_PSK_MODES is not set
|
||||
CONFIG_MBEDTLS_PSK_MODES=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
|
||||
|
||||
@@ -1012,7 +1012,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
|
||||
#
|
||||
# TLS Key Exchange Methods
|
||||
#
|
||||
# CONFIG_MBEDTLS_PSK_MODES is not set
|
||||
CONFIG_MBEDTLS_PSK_MODES=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
|
||||
|
||||
@@ -978,7 +978,11 @@ CONFIG_MBEDTLS_TLS_ENABLED=y
|
||||
#
|
||||
# TLS Key Exchange Methods
|
||||
#
|
||||
# CONFIG_MBEDTLS_PSK_MODES is not set
|
||||
CONFIG_MBEDTLS_PSK_MODES=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/fsender/readguy"
|
||||
},
|
||||
"version": "1.1.1",
|
||||
"version": "1.3.4",
|
||||
"frameworks": "arduino",
|
||||
"platforms": ["espressif32", "espressif8266"],
|
||||
"headers": "readguy.h",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=readguy
|
||||
version=1.1.1
|
||||
version=1.3.4
|
||||
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. */
|
||||
@@ -6,11 +6,16 @@
|
||||
* @file guy_driver_config.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief readguy 基础配置文件. 用户可以根据自己对库的编译需求来修改此文件.
|
||||
*
|
||||
* 如果你希望在程序代码内包含引脚定义, 请参考此文件下方的注释来确定并编译
|
||||
* !!!但是这样编译得到的程序不具备跨平台特性.!!!
|
||||
* 可以禁用WiFi功能来减少ESP32的flash消耗
|
||||
* @version 1.0
|
||||
* @date 2023-09-21
|
||||
* 这样就可以只针对你设计的这一个硬件来设定引脚功能.
|
||||
* 关于屏幕配置, 请参考 guy_epaper/guy_epaper_config.h 文件来配置到底哪些屏幕型号的屏幕会被包含进来
|
||||
|
||||
* 可以禁用WiFi功能来减少程序的flash消耗
|
||||
|
||||
* @version 1.1
|
||||
* @date create: 2023-09-21
|
||||
* last modify: 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
@@ -61,6 +66,7 @@
|
||||
|
||||
/// @brief 使用静态的数据 !!!注意:注释此选项编写的程序是不支持跨平台运行的!!!
|
||||
/// @note 相比于禁用WiFi配网功能, 禁用此功能减少的flash并不多, 为保证程序可在不同屏幕上运行, 请不要注释此选项
|
||||
// 关闭此选项自动禁用wifi功能. 如需wifi功能需要自己在程序里加.
|
||||
#define DYNAMIC_PIN_SETTINGS
|
||||
|
||||
/// @brief 启用WIFI配网功能.必须先启用 #define DYNAMIC_PIN_SETTINGS. 此选项对 ESP32xx 会减少大量flash.
|
||||
@@ -69,11 +75,20 @@
|
||||
/// @brief 启用I2C功能. 可用于联网时钟, 温度计, 陀螺仪等外设. 目前暂不支持库内使用类似函数. 仅可以提供引脚定义
|
||||
#define READGUY_ENABLE_I2C
|
||||
|
||||
/** @brief (即将推出) 启用SD卡功能. 开启此功能将会使用内置SD卡管理功能. 关闭后仅可保存SD卡用到的引脚.
|
||||
@note 会破坏兼容性. 若没有启用通用的SD卡驱动程序, 那么那些跨屏台编译的程序将无法用guyFS读取到SD卡.
|
||||
若用户程序希望能从外部加载SD卡, 可以使用getSdMiso()等函数获取SD卡的Miso等引脚, 再由用户程序初始化SD卡. */
|
||||
#define READGUY_ENABLE_SD
|
||||
|
||||
/// @brief 使用LittleFS作为片上文件系统, 注释此行则用SPIFFS(功能少, 不好用)
|
||||
#define READGUY_USE_LITTLEFS 1
|
||||
|
||||
/// @brief ESP32按键服务任务的栈空间大小, 不建议普通用户更改. 默认值1024字节. 小于此大小会使程序栈溢出.
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#define BTN_LOOPTASK_STACK 1280
|
||||
#else
|
||||
#define BTN_LOOPTASK_STACK 1024
|
||||
#endif
|
||||
|
||||
/// @brief ESP32按键服务任务运行在哪个核心. 通常运行在核心0上.
|
||||
#define BTN_LOOPTASK_CORE_ID 0
|
||||
|
||||
74
src/guy_epaper/guy_1020A/guy_1020A.cpp
Normal file
74
src/guy_epaper/guy_1020A/guy_1020A.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_1020A.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 1020A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 1020A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_1020A.h"
|
||||
#ifdef READGUY_DEV_1020A
|
||||
namespace guydev_1020A{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
src/guy_epaper/guy_1020A/guy_1020A.h
Normal file
63
src/guy_epaper/guy_1020A/guy_1020A.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_1020A.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 1020A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 1020A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD1020A_H_FILE) && (defined(READGUY_DEV_1020A)))
|
||||
#define _GUY_EPD1020A_H_FILE
|
||||
|
||||
namespace guydev_1020A{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_1020A; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
69
src/guy_epaper/guy_154C/guy_154C.cpp
Normal file
69
src/guy_epaper/guy_154C/guy_154C.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_154c.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 1.54英寸墨水屏 驱动库函数
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_154C.h"
|
||||
#ifdef READGUY_DEV_154C
|
||||
namespace guydev_154C{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
58
src/guy_epaper/guy_154C/guy_154C.h
Normal file
58
src/guy_epaper/guy_154C/guy_154C.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_154c.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 1.54英寸墨水屏 驱动库函数 头文件
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD154C_H_FILE) && (defined(READGUY_DEV_154C)))
|
||||
#define _GUY_EPD154C_H_FILE
|
||||
|
||||
namespace guydev_154C{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_154C; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -56,16 +56,7 @@ int drvBase::Init(const unsigned char* lut) {
|
||||
guy_epdParam((iLut==1)?0x02:((iLut==3 || iLut==5)?0x05:0x08)); // 2us per line
|
||||
guy_epdCmd(0x11);
|
||||
guy_epdParam(0x03); // X increment; Y increment
|
||||
SetLut(this->lut);
|
||||
// * EPD hardware init end /
|
||||
EndTransfer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drvBase::SetLut(const unsigned char* lut) {
|
||||
this->lut = lut;
|
||||
guy_epdCmd(0x32);
|
||||
// * the length of look-up table is 30 bytes /
|
||||
for (int i = 0; i < 30; i++) {
|
||||
if(iLut>0 && iLut<15 && i>19 && i<23){
|
||||
guy_epdParam(pgm_read_byte(lut_grey_update+iLut*2+i-(i==20?22:23)));
|
||||
@@ -73,6 +64,8 @@ void drvBase::SetLut(const unsigned char* lut) {
|
||||
else
|
||||
guy_epdParam(pgm_read_byte(this->lut+i));
|
||||
}
|
||||
EndTransfer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const PROGMEM unsigned char lut_slow[] =
|
||||
@@ -99,15 +92,28 @@ const PROGMEM unsigned char lut_grey_update[]={ //从上到下是依次加深
|
||||
0x12, 0x44, 0x13, 0x44
|
||||
};
|
||||
|
||||
void drvBase::drv_init(){
|
||||
void drvBase::drv_init(){ //new init method can init without freshing.
|
||||
iLut = 15; //新的初始化方式可以允许不初始化直接显示
|
||||
sleeping=1;
|
||||
//drv_color(0xffu); //睡眠模式下始终需要慢刷
|
||||
}
|
||||
void drvBase::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
if(lastRefresh) return;
|
||||
if(!part) iLut=15;
|
||||
if(sleeping) iLut=15;
|
||||
else Init(part?lut_fast:lut_slow);
|
||||
}
|
||||
/*void drvBase::drv_init(){
|
||||
Init(lut_slow);
|
||||
drv_color(0xffu); //睡眠模式下始终需要慢刷
|
||||
}
|
||||
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
|
||||
@@ -120,14 +126,22 @@ void drvBase::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新等
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdCmd(0xff);
|
||||
EndTransfer();
|
||||
guy_epdBusy((this->lut == (const uint8_t*)lut_fast)?idleFastRf:idleSlowRf);
|
||||
BeginTransfer();
|
||||
SetMemory(); // bit set = white, bit reset = black
|
||||
guy_epdBusy(90);
|
||||
guy_epdCmd(0x26); /* will send the color data */
|
||||
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
|
||||
SpiTransfer(f(i));
|
||||
EndTransfer();
|
||||
lastRefresh=millis();
|
||||
}
|
||||
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=(this->lut == (const uint8_t*)lut_fast)?idleFastRf:idleSlowRf;
|
||||
if(ms<u) guy_epdBusy(u-ms);
|
||||
lastRefresh=0;
|
||||
BeginTransfer();
|
||||
SetMemory(); // bit set = white, bit reset = black
|
||||
guy_epdBusy(90);
|
||||
guy_epdCmd(0x26); /* will send the color data */
|
||||
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
|
||||
SpiTransfer(f(i));
|
||||
EndTransfer();
|
||||
}
|
||||
}
|
||||
void drvBase::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒
|
||||
@@ -136,8 +150,8 @@ void drvBase::drv_sleep() { //开始屏幕睡眠
|
||||
EndTransfer();
|
||||
guy_epdBusy(150);
|
||||
DigitalWrite(RST_PIN, LOW);
|
||||
sleeping=1;
|
||||
}
|
||||
sleeping=1;
|
||||
}
|
||||
void drvBase::drv_setDepth(uint8_t i){
|
||||
iLut = i?(i>15?15:i):15;
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
@@ -57,9 +57,7 @@ private:
|
||||
int Init(const unsigned char* lut);
|
||||
const unsigned char* lut;
|
||||
uint8_t iLut = 15;
|
||||
uint8_t sleeping=1;
|
||||
|
||||
void SetLut(const unsigned char* lut);
|
||||
uint8_t sleeping=0;
|
||||
};
|
||||
|
||||
#ifdef READGUY_DEV_154A
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace guydev_154B_270B_290B{
|
||||
0x22,0x17,0x41,0xB0,0x32,0x28
|
||||
};*/
|
||||
|
||||
const unsigned char drvSSD168x::WS_20_30[48] =
|
||||
const unsigned char drvSSD168x::WS_20_30[42] =
|
||||
{ /*
|
||||
0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0,
|
||||
0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
|
||||
@@ -93,40 +93,25 @@ const unsigned char drvSSD168x::WS_20_30[48] =
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, */
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
|
||||
0x22, 0x17, 0x41, 0xA8, 0x32, 0x28
|
||||
};
|
||||
const unsigned char drvSSD168x::VSH_table[32]=
|
||||
{0x00,0x24,0x24,0x24,0x25,0x26,0x27,0x28,0x2a,0x2c,0x2e,0x32,0x35,0x39,0x3d,0x41,
|
||||
0x46,0x45,0x44,0x42,0x41,0x40,0x3f,0x3f,0x3c,0x39,0x36,0x34,0x32,0x31,0x30,0x2f};
|
||||
{/*0x00,0xbc,0xc1,0xc6,0xcb,0x23,0x26,0x28,0x2a,0x2c,0x2e,0x32,0x35,0x39,0x3d,0x41,*/
|
||||
0x00,0x24,0x28,0x2c,0x30,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x40,0x42,0x44,0x45,0x46,
|
||||
0x00,0x41,0x3c,0x37,0x32,0x2d,0x28,0x23,0xcb,0xc6,0xc1,0xbc,0xb7,0xb2,0xb0,0xae};
|
||||
|
||||
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
void drvSSD168x::epd_init() {
|
||||
if(epd_PowerOn==0) {
|
||||
Reset();
|
||||
epd_PowerOn=1;
|
||||
_part=0;
|
||||
iLut=15;
|
||||
}
|
||||
guy_epdCmd(0x12); //SWRESET
|
||||
guy_epdBusy(10);
|
||||
|
||||
guy_epdCmd(0x01); //Driver output control
|
||||
guy_epdParam((epdHeight-1)&0xff);
|
||||
guy_epdParam(((epdHeight-1)>>8)&0xff);
|
||||
guy_epdParam(0x00);
|
||||
|
||||
guy_epdCmd(0x11); //data entry mode
|
||||
guy_epdParam(0x03);
|
||||
SetMemory();
|
||||
SetLut();
|
||||
}
|
||||
|
||||
void drvSSD168x::DisplayFrame(void) {
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(_part?0x0f:0xc7);
|
||||
guy_epdCmd(0x20);
|
||||
}
|
||||
void drvSSD168x::SetLut() {
|
||||
guy_epdCmd(0x3f);
|
||||
guy_epdParam(greyScaling?0x07:0x22);
|
||||
guy_epdCmd(0x03); // gate voltage
|
||||
guy_epdParam(0x17);
|
||||
guy_epdCmd(0x04); // source voltage
|
||||
guy_epdParam(greyScaling?pgm_read_byte(VSH_table+16+iLut):pgm_read_byte(VSH_table+iLut));
|
||||
guy_epdParam(0xA8); // VSH2
|
||||
guy_epdParam(0x32); // VSL
|
||||
guy_epdCmd(0x2c); // VCOM
|
||||
guy_epdParam(0x28);
|
||||
unsigned char i;
|
||||
guy_epdCmd(0x32);
|
||||
if(_part){
|
||||
@@ -134,10 +119,10 @@ void drvSSD168x::SetLut() {
|
||||
guy_epdParam(i==1?0x80:(i==(greyScaling?0:2)?0x40:0x00));
|
||||
for(int j=0;j<11;j++) guy_epdParam(0);
|
||||
}
|
||||
guy_epdParam(greyScaling?(iLut<5?4-((iLut+1)>>1):1):iLut);
|
||||
guy_epdParam(greyScaling?1:iLut);
|
||||
for(i=0;i<83;i++) guy_epdParam(0);
|
||||
for(i=0;i<6;i++) guy_epdParam(0x22);
|
||||
for(i=0;i<3;i++) guy_epdParam(0);
|
||||
guy_epdParam(0x22);
|
||||
for(i=0;i<8;i++) guy_epdParam(0);
|
||||
}
|
||||
else{
|
||||
//for(i=0; i<153; i++) guy_epdParam(lut[i]==0xff?iLut:lut[i]);
|
||||
@@ -151,29 +136,24 @@ void drvSSD168x::SetLut() {
|
||||
for(i=0;i<66;i++) guy_epdParam(0);
|
||||
for(i=0;i<9;i++) guy_epdParam(pgm_read_byte(WS_20_30+i+33));
|
||||
}
|
||||
guy_epdCmd(0x3f);
|
||||
guy_epdParam(pgm_read_byte(WS_20_30+42));
|
||||
guy_epdCmd(0x03); // gate voltage
|
||||
guy_epdParam(pgm_read_byte(WS_20_30+43));
|
||||
guy_epdCmd(0x04); // source voltage
|
||||
guy_epdParam(greyScaling?pgm_read_byte(VSH_table+16+iLut):pgm_read_byte(VSH_table+iLut));
|
||||
guy_epdParam(pgm_read_byte(WS_20_30+45)); // VSH2
|
||||
guy_epdParam(pgm_read_byte(WS_20_30+46)); // VSL
|
||||
guy_epdCmd(0x2c); // VCOM
|
||||
guy_epdParam(pgm_read_byte(WS_20_30+47));
|
||||
}
|
||||
|
||||
void drvSSD168x::drv_init(){
|
||||
_part=0;
|
||||
drv_color(0xffu);
|
||||
epd_PowerOn=0;
|
||||
//drv_color(0xffu);
|
||||
}
|
||||
void drvSSD168x::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
if(lastRefresh) return;
|
||||
if(!epd_PowerOn) part=0; //未上电 无法局刷
|
||||
if(!part) { iLut=15; greyScaling=0; }
|
||||
_part=part;
|
||||
}
|
||||
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
BeginTransfer();
|
||||
if(_part && epd_PowerOn){
|
||||
if(_part){
|
||||
//Reset();
|
||||
SetLut();
|
||||
guy_epdCmd(0x37);
|
||||
@@ -186,7 +166,26 @@ void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdBusy(140);
|
||||
}
|
||||
else epd_init();
|
||||
else{
|
||||
if(epd_PowerOn==0) {
|
||||
Reset();
|
||||
epd_PowerOn=1;
|
||||
_part=0;
|
||||
iLut=15;
|
||||
}
|
||||
guy_epdCmd(0x12); //SWRESET
|
||||
guy_epdBusy(10);
|
||||
|
||||
guy_epdCmd(0x01); //Driver output control
|
||||
guy_epdParam((epdHeight-1)&0xff);
|
||||
guy_epdParam(((epdHeight-1)>>8)&0xff);
|
||||
guy_epdParam(0x00);
|
||||
|
||||
guy_epdCmd(0x11); //data entry mode
|
||||
guy_epdParam(0x03);
|
||||
SetMemory();
|
||||
SetLut();
|
||||
}
|
||||
SetMemory();
|
||||
guy_epdCmd(0x24);
|
||||
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
|
||||
@@ -196,9 +195,19 @@ void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
|
||||
SpiTransfer(f(i));
|
||||
}
|
||||
DisplayFrame();
|
||||
guy_epdCmd(0x22);
|
||||
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){ //无法唤醒
|
||||
@@ -206,8 +215,8 @@ void drvSSD168x::drv_sleep() { //开始屏幕睡眠
|
||||
guy_epdCmd(0x10);
|
||||
guy_epdParam(0x01);
|
||||
EndTransfer();
|
||||
epd_PowerOn=0;
|
||||
}
|
||||
epd_PowerOn=0;
|
||||
}
|
||||
void drvSSD168x::drv_setDepth(uint8_t i){ //设置显示颜色深度, 不支持的话什么都不做
|
||||
if(i>0 && i<16) {
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
@@ -52,16 +52,13 @@ protected:
|
||||
int epdWidth;
|
||||
int epdHeight;
|
||||
private:
|
||||
uint8_t _part;
|
||||
uint8_t epd_PowerOn = 0;
|
||||
uint8_t _part=1;
|
||||
uint8_t epd_PowerOn = 1;
|
||||
uint8_t iLut=15;
|
||||
uint8_t greyScaling=0;
|
||||
//static const unsigned char _WF_PARTIAL_2IN9[48] ;
|
||||
static const unsigned char WS_20_30[48] ;
|
||||
static const unsigned char WS_20_30[42] ;
|
||||
static const unsigned char VSH_table[32];
|
||||
|
||||
void epd_init();
|
||||
void DisplayFrame(void);
|
||||
void SetLut();
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace guydev_213A{
|
||||
|
||||
const PROGMEM uint8_t drv::_ed_lut_full[] = { // command //慢刷lut
|
||||
0x22, 0x55, 0xaa, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x13, 0x13, 0x13, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
0x00, 0x13, 0x16, 0x16, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
const PROGMEM uint8_t drv::_ed_lut_part[] = { // command //快刷lut
|
||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -106,18 +106,23 @@ void drv::epd_Init(void){
|
||||
}
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
epdFull = 1;
|
||||
BeginTransfer();
|
||||
epd_PowerOn = 0;
|
||||
/*BeginTransfer();
|
||||
epd_Init();
|
||||
EndTransfer();
|
||||
drv_color(0xff);
|
||||
EndTransfer();*/
|
||||
//drv_color(0xff);
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
if(!epd_PowerOn) part=0; //未上电 无法局刷
|
||||
//if(part==epdFull) return;
|
||||
if(!part) iLut=15; //恢复默认的灰度模式
|
||||
epdFull = !part;
|
||||
//epd_Init();
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
BeginTransfer();
|
||||
if(epdFull) { //当刷新模式从快刷切换为慢刷时, 需要发送一次init
|
||||
epdFull=0;
|
||||
@@ -141,24 +146,33 @@ 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) return; //无法唤醒
|
||||
BeginTransfer();
|
||||
if(epd_PowerOn){
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0xc3);
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdBusy(200);
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
BeginTransfer();
|
||||
if(epd_PowerOn){
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0xc3);
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdBusy(200);
|
||||
}
|
||||
guy_epdCmd(0x10); //enter deep sleep
|
||||
guy_epdParam(0x01);
|
||||
EndTransfer();
|
||||
DelayMs(200);
|
||||
DigitalWrite(RST_PIN, LOW);
|
||||
}
|
||||
guy_epdCmd(0x10); //enter deep sleep
|
||||
guy_epdParam(0x01);
|
||||
EndTransfer();
|
||||
DelayMs(200);
|
||||
DigitalWrite(RST_PIN, LOW);
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
|
||||
@@ -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; }; //返回缓存的数据宽度
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
void epd_Init(void);
|
||||
uint8_t epdFull; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t epd_PowerOn = 0; //是否上电
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t epd_PowerOn = 1; //是否上电
|
||||
uint8_t iLut = 15; //颜色深度(灰度模式用)
|
||||
// uint8_t dc_d = 0; //dc引脚状态 0 command, 1 data
|
||||
static const PROGMEM uint8_t _ed_lut_full[];
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
#include <stdlib.h>
|
||||
#include "guy_213b_266a.h"
|
||||
// #define MEPD_DEBUG_WAVE
|
||||
#ifdef READGUY_DEV_266A
|
||||
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|
||||
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C))
|
||||
namespace guydev_213B_266A{
|
||||
static const PROGMEM unsigned char lutSlow_vcom0[] ={
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
|
||||
@@ -68,26 +69,30 @@ static const PROGMEM unsigned char lutSlow_b_b[] ={
|
||||
static const PROGMEM unsigned char lutFast_[]={
|
||||
0x00,0x18,0x5a,0xa5,0x24
|
||||
};
|
||||
static const PROGMEM unsigned char greyLutLevel[]={
|
||||
0, 3, 6, 9,12,15,18,21,24,28,31,34,37,42,48,54, //for BWR displays
|
||||
0, 3, 5, 7,10,13,16,19,22,25,29,32,35,38,43,49,
|
||||
0, 3, 5, 6, 8,11,14,17,20,23,26,29,32,35,39,44,
|
||||
0, 2, 4, 5, 6, 8,10,13,15,18,21,24,27,31,35,39,
|
||||
0, 2, 3, 5, 6, 7, 8,10,12,15,17,19,22,24,27,30,
|
||||
0, 2, 3, 4, 5, 6, 7, 8,10,12,14,16,18,20,22,24,
|
||||
|
||||
0, 3, 3, 3, 4, 4, 5, 6, 7, 9,12,16,21,28,36,48,
|
||||
};
|
||||
drv_base::drv_base(){
|
||||
guy_lutArray[0] = lutSlow_vcom0;
|
||||
guy_lutArray[1] = lutSlow_w_w;
|
||||
guy_lutArray[2] = lutSlow_b_w;
|
||||
guy_lutArray[3] = lutSlow_w_b;
|
||||
guy_lutArray[4] = lutSlow_b_b;
|
||||
guy_lutArray[5] = lutFast_;
|
||||
}
|
||||
void drv_base::pre(){
|
||||
guy_epdCmd(0x91);
|
||||
send_zoneInfo();
|
||||
guy_epdCmd(0x13);
|
||||
}
|
||||
void drv_base::epd_init(){
|
||||
if(!Power_is_on) Reset();
|
||||
//if(!Power_is_on) Reset();
|
||||
guy_epdCmd(0x01);
|
||||
guy_epdParam(0x03);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x2b);
|
||||
guy_epdParam(0x2b);
|
||||
guy_epdParam(0x10);
|
||||
guy_epdParam(isBWR?0x3f:0x2b);
|
||||
guy_epdParam(isBWR?0x3f:0x2b);
|
||||
guy_epdParam(0x03);
|
||||
guy_epdCmd(0x06);
|
||||
guy_epdParam(0x17);
|
||||
@@ -97,7 +102,7 @@ void drv_base::epd_init(){
|
||||
guy_epdParam(0xbf);
|
||||
guy_epdParam(0x0d);
|
||||
guy_epdCmd(0x30);
|
||||
guy_epdParam(0x29); //0x3a:100Hz, 0x29:150Hz
|
||||
guy_epdParam(isBWR?0x3b:0x29); //0x3a:100Hz, 0x29:150Hz
|
||||
guy_epdCmd(0x61);
|
||||
guy_epdParam(0x98);
|
||||
guy_epdParam(0x01);
|
||||
@@ -110,11 +115,11 @@ void drv_base::epd_init(){
|
||||
void drv_base::send_zoneInfo(){
|
||||
guy_epdCmd(0x90);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x97);
|
||||
guy_epdParam(epdWidth-1);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x01);
|
||||
guy_epdParam(0x27);
|
||||
guy_epdParam((epdHeight-1)>>8);
|
||||
guy_epdParam((epdHeight-1)&0xff);
|
||||
guy_epdParam(0x00);
|
||||
}
|
||||
void drv_base::SendLuts(bool part_lut){
|
||||
@@ -123,9 +128,9 @@ void drv_base::SendLuts(bool part_lut){
|
||||
guy_epdCmd(i+0x20);
|
||||
for(int j=0;j<(i==0?44:42);j++){
|
||||
if(part_lut){
|
||||
if(j==4 && ((i==2) || (greyHQ==3 && i==4))) guy_epdParam(15);
|
||||
else if(j==greyHQ) guy_epdParam(greyLut);
|
||||
else if(j==0) guy_epdParam(pgm_read_byte(guy_lutArray[5]+(i)));
|
||||
if(j==4 && ((i==2) || (greyHQ==3 && i==4))) guy_epdParam(isBWR?0x2f:0x0f); //刷黑->白
|
||||
else if(j==greyHQ) guy_epdParam(isBWR?pgm_read_byte(greyLutLevel+(greyLut+refTime*16)):greyLut);
|
||||
else if(j==0) guy_epdParam(pgm_read_byte(lutFast_+(i)));
|
||||
else if(j==5) guy_epdParam(1);
|
||||
else guy_epdParam(0x0);
|
||||
}
|
||||
@@ -134,17 +139,20 @@ void drv_base::SendLuts(bool part_lut){
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!Power_is_on){
|
||||
if(!Power_is_on || Power_is_on==2){
|
||||
guy_epdCmd(0x04);
|
||||
guy_epdBusy(-60);
|
||||
Power_is_on = 1;
|
||||
}
|
||||
}
|
||||
void drv_base::drv_init(){
|
||||
part_mode=0;
|
||||
drv_color(0xff);
|
||||
part_mode = 0;
|
||||
Power_is_on = 0; //初始为未上电
|
||||
//drv_color(0xff);
|
||||
}
|
||||
void drv_base::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
if(lastRefresh) return;
|
||||
if(!Power_is_on) part=0;
|
||||
if(!part) greyLut=15; //恢复默认的灰度模式
|
||||
part_mode = part;
|
||||
}
|
||||
@@ -155,78 +163,65 @@ 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();
|
||||
pre();
|
||||
//send pixel data -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
|
||||
//Total 5624 data written.
|
||||
//for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++)
|
||||
// guy_epdParam(c);
|
||||
epd_init();
|
||||
SendLuts(part_mode);
|
||||
guy_epdCmd(0x91);
|
||||
send_zoneInfo();
|
||||
guy_epdCmd(0x13);
|
||||
for (int i = 0; i < epdHeight*epdWidth/8; i++)
|
||||
SpiTransfer(f(i)); //按照给定的RAM写入数据
|
||||
|
||||
guy_epdCmd(0x92);
|
||||
if(part_mode){
|
||||
guy_epdCmd(0x30);
|
||||
guy_epdParam(0x3a); //0x3a:100Hz, 0x29:150Hz
|
||||
//[EPDrg_BW<>] refresh fx
|
||||
//guy_epdParam(0x3a); //黑白色用此行, 三色用下一行
|
||||
guy_epdParam(isBWR?0x19:(refTime?0x21:0x3a)); //0x3a:100Hz, 0x29:150Hz
|
||||
send_zoneInfo();
|
||||
|
||||
guy_epdCmd(0x12);
|
||||
EndTransfer();
|
||||
//[EPDrg_EPD] wait_until_idle fx: 1300
|
||||
guy_epdBusy(-200);
|
||||
//[EPDrg_BW<>] writeImageAgain fx
|
||||
//guy_epdCmd(0x91);
|
||||
//send_zoneInfo();
|
||||
|
||||
//guy_epdCmd(0x13);
|
||||
//send image data -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
|
||||
//Total 5624 data written.
|
||||
//guy_epdCmd(0x92);
|
||||
}
|
||||
else{
|
||||
epd_init();
|
||||
SendLuts(0);
|
||||
guy_epdCmd(0x12);
|
||||
//[EPDrg_EPD] wait_until_idle fx: 1600
|
||||
EndTransfer();
|
||||
guy_epdBusy(-2000);
|
||||
|
||||
//[EPDrg_BW<>] writeImageAgain fx
|
||||
BeginTransfer();
|
||||
epd_init();
|
||||
SendLuts(1);
|
||||
pre();
|
||||
//send image data -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
|
||||
//Total 5624 data written.
|
||||
for (int i = 0; i < epdHeight*epdWidth/8; i++)
|
||||
SpiTransfer(f(i)); //按照给定的RAM写入数据
|
||||
guy_epdCmd(0x92);
|
||||
EndTransfer();
|
||||
//[EPDrg_BW<>] powerOff fx
|
||||
//guy_epdCmd(0x02);
|
||||
//[EPDrg_EPD] wait_until_idle fx: 20
|
||||
//guy_epdBusy(-20);
|
||||
guy_epdCmd(0x12);
|
||||
EndTransfer();
|
||||
lastRefresh=millis();
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
if(part_mode){
|
||||
if((int32_t)ms<fastRefTime) guy_epdBusy((int32_t)ms-fastRefTime);
|
||||
refTime+=(refTime<5);
|
||||
}
|
||||
else{
|
||||
if((int32_t)ms<slowRefTime) guy_epdBusy((int32_t)ms-slowRefTime);
|
||||
BeginTransfer();
|
||||
epd_init();
|
||||
SendLuts(1);
|
||||
guy_epdCmd(0x92);
|
||||
EndTransfer();
|
||||
refTime=0;
|
||||
}
|
||||
lastRefresh=0;
|
||||
}
|
||||
}
|
||||
void drv_base::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒
|
||||
part_mode = 0;
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x02); // power off
|
||||
guy_epdBusy(-20);
|
||||
guy_epdCmd(0X10);
|
||||
guy_epdParam(0x01);
|
||||
EndTransfer();
|
||||
Power_is_on = 0;
|
||||
}
|
||||
//if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x02); // power off
|
||||
guy_epdBusy(-20);
|
||||
guy_epdCmd(0X10);
|
||||
guy_epdParam(0x01);
|
||||
EndTransfer();
|
||||
//}
|
||||
part_mode = 0;
|
||||
Power_is_on = 0;
|
||||
}
|
||||
|
||||
void drv_base::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
|
||||
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
|
||||
if(step==1){
|
||||
greyHQ=3;
|
||||
refTime=6;
|
||||
drv_setDepth(3);
|
||||
drv_fullpart(1); //开始快刷
|
||||
}
|
||||
@@ -235,6 +230,7 @@ void drv_base::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
|
||||
drv_dispWriter(f);
|
||||
if(step==15){
|
||||
greyHQ=4;
|
||||
refTime=5;
|
||||
drv_setDepth(15);
|
||||
}
|
||||
} //据说可以设置灰度渲染方式. 好像是调用setGreyQuality函数就行来着
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
* @file guy_213b_266a.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 2.13英寸B型墨水屏和 2.66英寸墨水屏 驱动库函数 头文件
|
||||
* @version 1.0
|
||||
* @date 2023-09-21
|
||||
* 增加了对三色屏幕的支持
|
||||
* @version 1.1
|
||||
* @date create: 2023-09-21
|
||||
* last modify: 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
@@ -29,7 +31,8 @@
|
||||
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD213B_266A_H_FILE) && \
|
||||
(defined(READGUY_DEV_266A) || defined(READGUY_DEV_213B)))
|
||||
(defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|
||||
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C)))
|
||||
#define _GUY_EPD213B_266A_H_FILE
|
||||
|
||||
namespace guydev_213B_266A{
|
||||
@@ -39,7 +42,7 @@ public:
|
||||
virtual int drv_ID() const=0;
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f); //按照函数刷新
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return epdWidth; }; //返回显示区域宽度
|
||||
int drv_height() const{ return epdHeight; }; //返回显示区域高度
|
||||
@@ -49,31 +52,47 @@ public:
|
||||
protected:
|
||||
int epdWidth;
|
||||
int epdHeight;
|
||||
private:
|
||||
void pre();
|
||||
void epd_init();
|
||||
void send_zoneInfo();
|
||||
void SendLuts(bool part_lut);
|
||||
uint8_t part_mode = 0;
|
||||
uint8_t Power_is_on = 0; //初始为未上电
|
||||
uint8_t part_mode = 1;
|
||||
uint8_t Power_is_on = 2; //初始为未上电
|
||||
uint8_t greyLut=15;
|
||||
uint8_t greyHQ=4; // greyHQ==3 时 为高品质刷新灰度 否则为常规方式刷新灰度
|
||||
const uint8_t *guy_lutArray[6];
|
||||
uint8_t refTime=0;
|
||||
uint8_t isBWR=0; //三色2.66将此屏幕数值改为1.
|
||||
int16_t slowRefTime;
|
||||
int16_t fastRefTime;
|
||||
const uint8_t *guy_lutArray[5];
|
||||
};
|
||||
#ifdef READGUY_DEV_213B
|
||||
class dev213B : public drv_base {
|
||||
public:
|
||||
dev213B(){ epdWidth=104; epdHeight=212; }
|
||||
dev213B(){ epdWidth=104; epdHeight=212; slowRefTime=1300; fastRefTime=200; }
|
||||
int drv_ID() const { return READGUY_DEV_213B; }
|
||||
};
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213B3C
|
||||
class dev213B3C : public drv_base {
|
||||
public:
|
||||
dev213B3C(){ epdWidth=104; epdHeight=212; isBWR=1; slowRefTime=2800; fastRefTime=800; }
|
||||
int drv_ID() const { return READGUY_DEV_213B3C; }
|
||||
};
|
||||
#endif
|
||||
#ifdef READGUY_DEV_266A
|
||||
class dev266A : public drv_base {
|
||||
public:
|
||||
dev266A(){ epdWidth=152; epdHeight=296; }
|
||||
dev266A(){ epdWidth=152; epdHeight=296; slowRefTime=1300; fastRefTime=200; }
|
||||
int drv_ID() const { return READGUY_DEV_266A; }
|
||||
};
|
||||
#endif
|
||||
#ifdef READGUY_DEV_266A3C
|
||||
class dev266A3C : public drv_base {
|
||||
public:
|
||||
dev266A3C(){ epdWidth=152; epdHeight=296; isBWR=1; slowRefTime=2800; fastRefTime=800; }
|
||||
int drv_ID() const { return READGUY_DEV_266A3C; }
|
||||
};
|
||||
#endif
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
74
src/guy_epaper/guy_370B/guy_370B.cpp
Normal file
74
src/guy_epaper/guy_370B/guy_370B.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_370B.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 370B 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 370B 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_370B.h"
|
||||
#ifdef READGUY_DEV_370B
|
||||
namespace guydev_370B{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
src/guy_epaper/guy_370B/guy_370B.h
Normal file
63
src/guy_epaper/guy_370B/guy_370B.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_370B.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 370B 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 370B 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD370B_H_FILE) && (defined(READGUY_DEV_370B)))
|
||||
#define _GUY_EPD370B_H_FILE
|
||||
|
||||
namespace guydev_370B{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_370B; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -103,10 +103,14 @@ void drv::Load_LUT(unsigned char mode) {
|
||||
}
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
sleeping = 1;
|
||||
Init();
|
||||
drv_color(0xff);
|
||||
sleeping = 1;
|
||||
part_mode=0;
|
||||
//drv_color(0xff);
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
if(lastRefresh || sleeping) return;
|
||||
if(!part) {
|
||||
greyScaling=15; //恢复默认的灰度模式
|
||||
BeginTransfer();
|
||||
@@ -116,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);
|
||||
@@ -134,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){
|
||||
@@ -142,8 +156,9 @@ void drv::drv_sleep() { //开始屏幕睡眠
|
||||
guy_epdCmd(0X10); //deep sleep
|
||||
guy_epdParam(0x03);
|
||||
EndTransfer();
|
||||
sleeping = true;
|
||||
}
|
||||
sleeping = true;
|
||||
part_mode=0;
|
||||
}
|
||||
|
||||
void drv::drv_setDepth(uint8_t i){ //设置显示颜色深度, 不支持的话什么都不做
|
||||
|
||||
@@ -40,16 +40,16 @@ 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; }; //返回显示区域高度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度, 不支持的话什么都不做
|
||||
private:
|
||||
uint8_t part_mode;
|
||||
uint8_t part_mode=1;
|
||||
uint8_t greyScaling = 15;
|
||||
uint8_t sleeping = true;
|
||||
uint8_t sleeping = false;
|
||||
int Init(void);
|
||||
void Load_LUT(unsigned char mode);
|
||||
};
|
||||
|
||||
@@ -159,16 +159,6 @@ void drv::epd_Init(void){
|
||||
guy_epdCmd(0x11); //Data Entry mode
|
||||
guy_epdParam(0x03); //0x03 or 0x01
|
||||
}
|
||||
void drv::power_up(){
|
||||
if(!Power_is_on){
|
||||
//Power is not On
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0xc0);
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdBusy(120);
|
||||
Power_is_on=1;
|
||||
}
|
||||
}
|
||||
void drv::power_down(){
|
||||
Power_is_on=0;
|
||||
BeginTransfer();
|
||||
@@ -187,18 +177,28 @@ void drv::SetLut(const unsigned char* lut){
|
||||
}
|
||||
}
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
epdFull = 2;
|
||||
drv_color(0xff);
|
||||
Power_is_on = 0; //初始为未上电
|
||||
epdFull = 2; //初始设为正在休眠
|
||||
//drv_color(0xff);
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(!part) GreyScaling=0;
|
||||
if(lastRefresh) return;
|
||||
if(epdFull<=1) epdFull = !part; //epdFull==2代表睡眠中, 不能快刷
|
||||
if(epdFull) GreyScaling=0;
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
BeginTransfer();
|
||||
epd_Init();
|
||||
SetMemory();
|
||||
power_up();
|
||||
if(!Power_is_on){ //Power is not On, Power up.
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0xc0);
|
||||
guy_epdCmd(0x20);
|
||||
guy_epdBusy(120);
|
||||
Power_is_on=1;
|
||||
}
|
||||
SetMemory();
|
||||
if(epdFull){ //慢刷
|
||||
guy_epdCmd(0x26);
|
||||
@@ -214,9 +214,7 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
SetLut(lut_213_B72_Full);
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0xc4);
|
||||
guy_epdCmd(0x20);
|
||||
EndTransfer();
|
||||
guy_epdBusy(1600); //等待刷完
|
||||
//guy_epdBusy(1600); //等待刷完
|
||||
}
|
||||
else{ //快刷
|
||||
guy_epdCmd(0x2c); //may a mistake? 此处不需要设置vcom
|
||||
@@ -224,17 +222,24 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
SetLut(GreyScalingHighQuality?lut_213_B72_16grey:lut_213_B72);
|
||||
guy_epdCmd(0x22);
|
||||
guy_epdParam(0x04);
|
||||
guy_epdCmd(0x20);
|
||||
EndTransfer();
|
||||
guy_epdBusy(260); //等待屏幕刷新完成
|
||||
}
|
||||
BeginTransfer(); //write again
|
||||
SetMemory();
|
||||
guy_epdCmd(0x26);
|
||||
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
|
||||
SpiTransfer(f(i)); //按照给定的RAM写入数据
|
||||
guy_epdCmd(0x20);
|
||||
EndTransfer();
|
||||
if(epdFull) power_down();
|
||||
lastRefresh=millis();
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?1600:260;
|
||||
if(ms<u) guy_epdBusy(u-ms); //等待屏幕刷新完成
|
||||
lastRefresh=0;
|
||||
BeginTransfer(); //write again
|
||||
SetMemory();
|
||||
guy_epdCmd(0x26);
|
||||
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
|
||||
SpiTransfer(f(i)); //按照给定的RAM写入数据
|
||||
EndTransfer();
|
||||
if(epdFull) power_down();
|
||||
}
|
||||
}
|
||||
void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
|
||||
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
|
||||
@@ -260,13 +265,14 @@ void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
|
||||
}*/
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒
|
||||
epdFull=2; //睡眠
|
||||
power_down();
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x10); // deep sleep mode
|
||||
guy_epdParam(0x01); // enter deep sleep
|
||||
EndTransfer();
|
||||
}
|
||||
epdFull=2; //睡眠
|
||||
Power_is_on=0;
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
@@ -53,14 +53,13 @@ private:
|
||||
void epd_Init(void);
|
||||
void SetLut(const unsigned char* lut);
|
||||
uint8_t Power_is_on = 0; //初始为未上电
|
||||
uint8_t epdFull = 2; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t epdFull = 1; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t GreyScaling = 0; //是否正在灰度显示
|
||||
uint8_t GreyScalingHighQuality = 0; //是否正在16阶高品质灰度显示
|
||||
static const PROGMEM unsigned char epd42_lut_full[];
|
||||
static const PROGMEM unsigned char lut_213_B72[];
|
||||
static const PROGMEM unsigned char lut_213_B72_Full[];
|
||||
static const PROGMEM unsigned char lut_213_B72_16grey[];
|
||||
void power_up();
|
||||
void power_down();
|
||||
//std::function<void(int)> send; //此处不能用 void (*send)(int); 是因为lambda函数是std的
|
||||
};
|
||||
|
||||
@@ -49,35 +49,55 @@ void drv::Init(uint8_t pt) {
|
||||
Reset();
|
||||
guy_epdCmd(0x00); //Software reset
|
||||
guy_epdParam(0x00);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x00);
|
||||
guy_epdParam(0x1f);
|
||||
guy_epdParam(0x0d);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x50);
|
||||
guy_epdParam(0x97);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x01);
|
||||
guy_epdParam(0x03);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x2b);
|
||||
guy_epdParam(0x2b);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x06);
|
||||
guy_epdParam(0x17);
|
||||
guy_epdParam(0x17);
|
||||
guy_epdParam(0x17);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x00);
|
||||
guy_epdParam(0x3f);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x30);
|
||||
guy_epdParam(0x3a);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x61);
|
||||
guy_epdParam(0x01);
|
||||
guy_epdParam(0x90);
|
||||
guy_epdParam(0x01);
|
||||
guy_epdParam(0x2c);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x82); //vcom setting: 0x00:-0.1V, 0x3a: -3.0V
|
||||
guy_epdParam(0x1a);
|
||||
delayMicroseconds(40);
|
||||
guy_epdCmd(0x50);
|
||||
guy_epdParam(0xd7);
|
||||
SendLuts(pt?1:0); //不知为何, 此处需要快刷lut
|
||||
delayMicroseconds(40);
|
||||
//不知为何, 此处需要快刷lut
|
||||
for(uint8_t i=0;i<=4;i++){ //for(uint8_t i=0;i<=(lutOption==2?5:4);i++){
|
||||
guy_epdCmd(i+0x20);
|
||||
for(int j=0;j<(pt?6:(i+pt==0?44:42));j++){
|
||||
if(j==2 && customGreyscale) guy_epdParam(63);
|
||||
else if(j==3 && i!=2) guy_epdParam(customLut);
|
||||
else guy_epdParam(j<18?pgm_read_byte(guy_lutArray[i+(pt?1:0)*5]+j):0x00);
|
||||
delayMicroseconds(40);
|
||||
}
|
||||
}
|
||||
if(pt!=2) guy_epdCmd(0x04);
|
||||
delayMicroseconds(40);
|
||||
}
|
||||
|
||||
void drv::sendArea(){
|
||||
@@ -96,18 +116,6 @@ void drv::sendAreaRaw(){
|
||||
guy_epdParam(0x2b);
|
||||
guy_epdParam(0x01);
|
||||
}
|
||||
void drv::SendLuts(uint8_t lutOption){ // -------- 在此发送你的Lut数据 --------<<<<
|
||||
//Serial.printf("SendLuts fx: %d\n",lutOption);
|
||||
for(uint8_t i=0;i<=4;i++){ //for(uint8_t i=0;i<=(lutOption==2?5:4);i++){
|
||||
guy_epdCmd(i+0x20);
|
||||
//Serial.printf("%d th lut loaded.\n",i+lutOption*5);
|
||||
for(int j=0;j<(lutOption==1?6:(i+lutOption==0?44:42));j++){
|
||||
if(j==2 && customGreyscale) guy_epdParam(63);
|
||||
else if(j==3 && i!=2) guy_epdParam(customLut);
|
||||
else guy_epdParam(j<18?pgm_read_byte(guy_lutArray[i+lutOption*5]+j):0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
const PROGMEM unsigned char drv::lut_vcom0[] ={
|
||||
0x00, 0x08, 0x08, 0x00, 0x00, 0x02,
|
||||
0x00, 0x0F, 0x0F, 0x00, 0x00, 0x01,
|
||||
@@ -139,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){
|
||||
@@ -153,6 +163,7 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
//[EPDrg_BW<>] refresh fx
|
||||
}
|
||||
else{
|
||||
Power_is_on=1;
|
||||
guy_epdCmd(0x10);
|
||||
//刷新数据
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++)
|
||||
@@ -172,7 +183,13 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
}
|
||||
guy_epdCmd(0x12);
|
||||
EndTransfer();
|
||||
guy_epdBusy(part_mode?-800:-3600);
|
||||
lastRefresh=millis();
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
int32_t u=part_mode?800:3600;
|
||||
if((int32_t)ms<u) guy_epdBusy((int32_t)ms-u);
|
||||
lastRefresh=0;
|
||||
BeginTransfer();
|
||||
if(part_mode){
|
||||
sendArea();
|
||||
@@ -180,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);
|
||||
@@ -190,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);
|
||||
}
|
||||
@@ -198,15 +215,21 @@ const PROGMEM uint8_t drv::greyTable[16]={
|
||||
32,23,18,15,12,10,9,8,
|
||||
7,6,5,5,5,5,5,0
|
||||
};
|
||||
|
||||
void drv::drv_init(){
|
||||
//Init(0);
|
||||
drv_color(0xffu);
|
||||
part_mode=0;
|
||||
Power_is_on=0;
|
||||
BeginTransfer();
|
||||
Init(0);
|
||||
EndTransfer();
|
||||
//drv_color(0xffu);
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
|
||||
if(!part) customLut = CUSTOM_LUT_DISABLE;
|
||||
part_mode = part;
|
||||
//Init(part);
|
||||
if(lastRefresh) return;
|
||||
if(Power_is_on) {
|
||||
if(!part) customLut = CUSTOM_LUT_DISABLE;
|
||||
part_mode = part;
|
||||
//Init(part);
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //未定义RST_PIN时无法唤醒
|
||||
@@ -219,6 +242,8 @@ void drv::drv_sleep() { //开始屏幕睡眠
|
||||
guy_epdParam(0xA5);
|
||||
EndTransfer();
|
||||
}
|
||||
Power_is_on=0;
|
||||
part_mode=0;
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
|
||||
@@ -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; }; //返回显示区域高度
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
|
||||
private:
|
||||
uint8_t part_mode = 0;
|
||||
//uint8_t Power_is_on = 0; //初始为未上电
|
||||
uint8_t part_mode = 1;
|
||||
uint8_t Power_is_on = 1; //初始为未上电
|
||||
|
||||
static const PROGMEM unsigned char lut_vcom0[];
|
||||
static const PROGMEM unsigned char lut_ww[];
|
||||
@@ -76,8 +76,6 @@ private:
|
||||
void Init(uint8_t pt);
|
||||
void sendArea();
|
||||
void sendAreaRaw();
|
||||
|
||||
void SendLuts(uint8_t lutOption); //0:慢刷, 1:快刷, 2:四阶灰度
|
||||
uint8_t customLut, customGreyscale; //customLut 是灰度刷新时的自定义lut
|
||||
static const PROGMEM uint8_t greyTable[16];
|
||||
};
|
||||
|
||||
74
src/guy_epaper/guy_426A/guy_426A.cpp
Normal file
74
src/guy_epaper/guy_426A/guy_426A.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_426A.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 426A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 426A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_426A.h"
|
||||
#ifdef READGUY_DEV_426A
|
||||
namespace guydev_426A{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
src/guy_epaper/guy_426A/guy_426A.h
Normal file
63
src/guy_epaper/guy_426A/guy_426A.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_426A.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 426A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 426A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD426A_H_FILE) && (defined(READGUY_DEV_426A)))
|
||||
#define _GUY_EPD426A_H_FILE
|
||||
|
||||
namespace guydev_426A{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_426A; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
420
src/guy_epaper/guy_583A/guy_583A.cpp
Normal file
420
src/guy_epaper/guy_583A/guy_583A.cpp
Normal file
@@ -0,0 +1,420 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_583A.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 583A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 583A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_583A.h"
|
||||
#ifdef READGUY_DEV_583A
|
||||
namespace guydev_583A{
|
||||
/*LUT格式:
|
||||
重复次数,xnnnxnnn...(000=0,001=VSH,010=VSL,011=VSH_LV,100=VSL_LV,101=VSH_LVX,110=VSL_LVX,111=浮动),持续时间.......
|
||||
0x01, 0x00, 0x00, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
|
||||
0x01, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
0x01, 0x21, 0x21, 0x21, 0x21, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
|
||||
0x01, 0x12, 0x12, 0x12, 0x10, 0x14, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00
|
||||
0x01, 0x11, 0x21, 0x21, 0x22, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B
|
||||
0x01, 0x21, 0x21, 0x21, 0x20, 0x14, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x00
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
0x01, 0x12, 0x12, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02
|
||||
0x01, 0x21, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
*/
|
||||
const PROGMEM unsigned char drv::lut_20_LUTC[] =
|
||||
{ 0x01, 0x00, 0x00, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B};
|
||||
const PROGMEM unsigned char drv::lut_20_LUTCFAST[] =
|
||||
{ 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_21_LUTB[] =//000
|
||||
{ 0x01, 0x21, 0x21, 0x21, 0x21, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
|
||||
const PROGMEM unsigned char drv::lut_21_LUTBFAST[] =
|
||||
{ 0x01, 0x12, 0x12, 0x12, 0x10, 0x1f, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_22_LUTW[] =//011
|
||||
{ 0x01, 0x11, 0x21, 0x21, 0x22, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
|
||||
const PROGMEM unsigned char drv::lut_22_LUTWFAST[] =
|
||||
{ 0x01, 0x21, 0x21, 0x21, 0x20, 0x1f, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_23_LUTG1[] =//001
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_24_LUTG2[] =//010
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_25_LUTR0[] =//100//WW
|
||||
{ 0x01, 0x12, 0x12, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
|
||||
const PROGMEM unsigned char drv::lut_26_LUTR1[] =//101//BB
|
||||
{ 0x00/*0x01*/, 0x21, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
|
||||
const PROGMEM unsigned char drv::lut_27_LUTR2[] =//110
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_28_LUTR3[] =//111//局刷
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::lut_29_LUTXON[] =
|
||||
{ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const PROGMEM unsigned char drv::customGrey[] =
|
||||
{ 0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1e,
|
||||
0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
|
||||
const PROGMEM unsigned char *drv::luts[10]={
|
||||
lut_20_LUTC,lut_21_LUTB,lut_22_LUTW,lut_23_LUTG1,lut_24_LUTG2,
|
||||
lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
|
||||
};
|
||||
const unsigned char *drv::luts_fast[10]={
|
||||
lut_20_LUTCFAST,lut_21_LUTBFAST,lut_22_LUTWFAST,lut_23_LUTG1,lut_24_LUTG2,
|
||||
lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
|
||||
};
|
||||
|
||||
#ifdef READGUY_583A_DUAL_BUFFER
|
||||
drv::drv(){ //构造时, 分配内存.
|
||||
buf_2nd=(uint8_t *)malloc(GUY_D_WIDTH*GUY_D_HEIGHT/8);
|
||||
if(buf_2nd) {
|
||||
Serial.println(F("[GUY MEM] allocate 33600B for 5.83' EPD."));
|
||||
//memset(buf_2nd,0,GUY_D_WIDTH*GUY_D_HEIGHT/8);
|
||||
}
|
||||
}
|
||||
drv::~drv(){ //构造时, 分配内存.
|
||||
if(buf_2nd) free(buf_2nd);
|
||||
Serial.println(F("[GUY MEM] unallocate 33600B."));
|
||||
}
|
||||
#endif
|
||||
void drv::sendLut(int lutid){
|
||||
int lutlen=13,lutlen2=247;
|
||||
if(lutid==0){lutlen=11;lutlen2=209;}
|
||||
else if(lutid==9){lutlen=10;lutlen2=190;}
|
||||
guy_epdCmd(0x20+lutid);
|
||||
if(epdFull){
|
||||
for(int i=0;i<lutlen;i++){
|
||||
guy_epdParam(pgm_read_byte(luts[lutid]+i));
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(int i=0;i<lutlen;i++){
|
||||
if(lutid==1 && i==5) guy_epdParam(pgm_read_byte(customGrey+iLut+greyscalingHighQuality));
|
||||
else
|
||||
guy_epdParam(pgm_read_byte(luts_fast[lutid]+i));
|
||||
}
|
||||
}
|
||||
for(int i=0;i<lutlen2;i++){
|
||||
guy_epdParam(0);
|
||||
}
|
||||
}
|
||||
void drv::epd_init(){
|
||||
if(!epd_PowerOn) Reset(); //设定为已上电
|
||||
guy_epdCmd(0x01);
|
||||
guy_epdParam(0x37);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x07);
|
||||
guy_epdParam(0x07);
|
||||
guy_epdCmd(0x00);
|
||||
guy_epdParam(0xcf);
|
||||
guy_epdParam(0x88);
|
||||
guy_epdCmd(0x06);
|
||||
guy_epdParam(0xc7);
|
||||
guy_epdParam(0xcc);
|
||||
guy_epdParam(0x28);
|
||||
guy_epdCmd(0x30);
|
||||
guy_epdParam(0x3a);
|
||||
guy_epdCmd(0x41);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdCmd(0x50);
|
||||
guy_epdParam(0x77);
|
||||
guy_epdCmd(0x60);
|
||||
guy_epdParam(0x22);
|
||||
guy_epdCmd(0x61);
|
||||
guy_epdParam(0x02);
|
||||
guy_epdParam(0x58);
|
||||
guy_epdParam(0x01);
|
||||
guy_epdParam(0xc0);
|
||||
guy_epdCmd(0x82);
|
||||
guy_epdParam(0x28);
|
||||
for(int i=0;i<10;i++){
|
||||
sendLut(i);
|
||||
}
|
||||
guy_epdCmd(0xe5);
|
||||
guy_epdParam(0x03);
|
||||
}
|
||||
void drv::epd_sendZoneInfo(){
|
||||
guy_epdCmd(0x91);
|
||||
//send area info
|
||||
guy_epdCmd(0x90);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x02);
|
||||
guy_epdParam(0x57);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x00);
|
||||
guy_epdParam(0x01);
|
||||
guy_epdParam(0xbf);
|
||||
guy_epdParam(0x01);
|
||||
}
|
||||
void drv::epd_sendWriter(std::function<uint8_t(int)> f){
|
||||
guy_epdCmd(0x10); //Then write image data 显示数据
|
||||
#ifdef READGUY_583A_DUAL_BUFFER
|
||||
if(epdFull || buf_2nd==nullptr || greyscalingHighQuality){
|
||||
#endif
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){ //fill 0x03 for test
|
||||
uint8_t dat=0,dat_r=f(i);
|
||||
dat |= ((dat_r&0x80)?0x30:0);
|
||||
dat |= ((dat_r&0x40)?0x03:0);
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x20)?0x30:0);
|
||||
dat |= ((dat_r&0x10)?0x03:0);
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x08)?0x30:0);
|
||||
dat |= ((dat_r&0x04)?0x03:0);
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x02)?0x30:0);
|
||||
dat |= ((dat_r&0x01)?0x03:0);
|
||||
guy_epdParam(dat);
|
||||
#ifdef READGUY_583A_DUAL_BUFFER
|
||||
buf_2nd[i]=dat_r;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){ //fill 0x03 for test
|
||||
//guy_epdParam(0x03); //for data test
|
||||
uint8_t dat=0,dat_r=f(i);
|
||||
dat |= ((dat_r&0x80)?((buf_2nd[i]&0x80)?0x40:0x30):((buf_2nd[i]&0x80)?0x00:0x50));
|
||||
//0x3?黑->白色, 0x0?白->黑色 0x4? 白->白色 0x5? 黑->黑色
|
||||
dat |= ((dat_r&0x40)?((buf_2nd[i]&0x40)?0x4:0x3):((buf_2nd[i]&0x40)?0x0:0x5));
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x20)?((buf_2nd[i]&0x20)?0x40:0x30):((buf_2nd[i]&0x20)?0x00:0x50));
|
||||
dat |= ((dat_r&0x10)?((buf_2nd[i]&0x10)?0x4:0x3):((buf_2nd[i]&0x10)?0x0:0x5));
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x8)?((buf_2nd[i]&0x8)?0x40:0x30):((buf_2nd[i]&0x8)?0x00:0x50));
|
||||
dat |= ((dat_r&0x4)?((buf_2nd[i]&0x4)?0x4:0x3):((buf_2nd[i]&0x4)?0x0:0x5));
|
||||
guy_epdParam(dat);
|
||||
dat&=0;
|
||||
dat |= ((dat_r&0x2)?((buf_2nd[i]&0x2)?0x40:0x30):((buf_2nd[i]&0x2)?0x00:0x50));
|
||||
dat |= ((dat_r&0x1)?((buf_2nd[i]&0x1)?0x4:0x3):((buf_2nd[i]&0x1)?0x0:0x5));
|
||||
guy_epdParam(dat);
|
||||
buf_2nd[i]=dat_r;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
epdFull=1;
|
||||
epd_PowerOn=0;
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷/快刷功能
|
||||
if(lastRefresh) return;
|
||||
if(!epd_PowerOn) part=0;
|
||||
epdFull=!part;
|
||||
if(epdFull) iLut=15;
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
if(!epd_PowerOn) return; //不支持切换到快刷的情形
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
BeginTransfer();
|
||||
if(epdFull){
|
||||
if(!epd_PowerOn){
|
||||
epdFull=0; //发送快刷的lut
|
||||
epd_init();
|
||||
epdFull=1; //发送快刷的lut
|
||||
guy_epdCmd(0x04); //power on
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x10);
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x33
|
||||
guy_epdParam(0x33);
|
||||
}
|
||||
epd_PowerOn=1; //设定为已上电
|
||||
}
|
||||
else{ //full refresh need power on
|
||||
guy_epdCmd(0x04); //power on
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
}
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test
|
||||
}
|
||||
guy_epdCmd(0x92);
|
||||
epd_init();
|
||||
//epd_init(); //repeat call in GxEPD2
|
||||
epd_sendWriter(f); //write image data
|
||||
}
|
||||
else{
|
||||
epd_init();
|
||||
//Power on fx
|
||||
guy_epdCmd(0x04);
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
epd_sendZoneInfo();
|
||||
epd_sendWriter(f);
|
||||
guy_epdCmd(0x92);
|
||||
epd_sendZoneInfo();
|
||||
}
|
||||
guy_epdCmd(0x12); //开始刷屏
|
||||
EndTransfer();
|
||||
lastRefresh=millis();
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
int ms=millis()-lastRefresh;
|
||||
Serial.printf("epdFull? %d, epd_PowerOn? %d \n",epdFull,epd_PowerOn);
|
||||
int u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(ms-u); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
BeginTransfer();
|
||||
if(epdFull){
|
||||
epdFull=0; //发送快刷的lut
|
||||
epd_init(); //repeat init in part mode
|
||||
epdFull=1; //发送快刷的lut
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test
|
||||
}
|
||||
guy_epdCmd(0x02); //power off for test...
|
||||
//guy_epdBusy(-30);
|
||||
}
|
||||
else{
|
||||
guy_epdCmd(0x92);
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data 显示数据
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test:全白
|
||||
}
|
||||
guy_epdCmd(0x92);
|
||||
}
|
||||
EndTransfer();
|
||||
}
|
||||
/* test code , with stageless ------------------------------------------------------
|
||||
if(epdFull){ //慢刷
|
||||
BeginTransfer();
|
||||
if(!epd_PowerOn){
|
||||
epdFull=0; //发送快刷的lut
|
||||
epd_init();
|
||||
epdFull=1; //发送快刷的lut
|
||||
guy_epdCmd(0x04); //power on
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x10);
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x33
|
||||
guy_epdParam(0x33);
|
||||
}
|
||||
epd_PowerOn=1; //设定为已上电
|
||||
}
|
||||
else{ //full refresh need power on
|
||||
guy_epdCmd(0x04); //power on
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
}
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test
|
||||
}
|
||||
guy_epdCmd(0x92);
|
||||
epd_init();
|
||||
//epd_init(); //repeat call in GxEPD2
|
||||
epd_sendWriter(f); //write image data
|
||||
guy_epdCmd(0x12);
|
||||
EndTransfer();
|
||||
guy_epdBusy(-4000);
|
||||
BeginTransfer();
|
||||
epdFull=0; //发送快刷的lut
|
||||
epd_init(); //repeat init in part mode
|
||||
epdFull=1; //发送快刷的lut
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test
|
||||
}
|
||||
guy_epdCmd(0x02); //power off for test...
|
||||
EndTransfer();
|
||||
//guy_epdBusy(-30);
|
||||
}
|
||||
else{ //partmode
|
||||
BeginTransfer();
|
||||
epd_init();
|
||||
//Power on fx
|
||||
guy_epdCmd(0x04);
|
||||
EndTransfer();
|
||||
guy_epdBusy(-60);
|
||||
BeginTransfer();
|
||||
epd_sendZoneInfo();
|
||||
epd_sendWriter(f);
|
||||
guy_epdCmd(0x92);
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x12); //快刷
|
||||
EndTransfer();
|
||||
guy_epdBusy(-1000); //1秒钟刷屏时间
|
||||
BeginTransfer();
|
||||
guy_epdCmd(0x92);
|
||||
epd_sendZoneInfo();
|
||||
guy_epdCmd(0x10); //Then write image data 显示数据
|
||||
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
|
||||
guy_epdParam(0x33); //for test:全白
|
||||
}
|
||||
guy_epdCmd(0x92);
|
||||
EndTransfer();
|
||||
}
|
||||
// test code , with stageless ------------------------------------------------------ */
|
||||
}
|
||||
void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
|
||||
if(_quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
|
||||
if(step==1) drv_fullpart(1);//初始阶段,完成准备工作 //设置为快刷模式
|
||||
greyscalingHighQuality=16; //开启高品质灰度模式
|
||||
iLut=step;
|
||||
drv_dispWriter(f);
|
||||
//DelayMs(10); //未知原因()
|
||||
if(step==15) greyscalingHighQuality=0;//初始阶段,完成准备工作 //设置为快刷模式
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
guy_epdCmd(0x07); // deep sleep
|
||||
guy_epdParam(0xA5); // check code
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
92
src/guy_epaper/guy_583A/guy_583A.h
Normal file
92
src/guy_epaper/guy_583A/guy_583A.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_583A.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 583A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 583A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD583A_H_FILE) && (defined(READGUY_DEV_583A)))
|
||||
#define _GUY_EPD583A_H_FILE
|
||||
|
||||
namespace guydev_583A{
|
||||
constexpr int GUY_D_WIDTH =600; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =448; //驱动屏幕高度
|
||||
constexpr int slowRefTime =1600; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =560; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
#ifdef READGUY_583A_DUAL_BUFFER
|
||||
drv();
|
||||
virtual ~drv();
|
||||
#endif
|
||||
int drv_ID() const { return READGUY_DEV_583A; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return (_quality&1)?16:-16; } //暂不支持灰度功能移植
|
||||
void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
uint8_t greyscalingHighQuality = 0;
|
||||
static const unsigned char *luts[10];
|
||||
static const unsigned char *luts_fast[10];
|
||||
static const unsigned char lut_20_LUTC[];
|
||||
static const unsigned char lut_20_LUTCFAST[];
|
||||
static const unsigned char lut_21_LUTB[];
|
||||
static const unsigned char lut_21_LUTBFAST[];
|
||||
static const unsigned char lut_22_LUTW[];
|
||||
static const unsigned char lut_22_LUTWFAST[];
|
||||
static const unsigned char lut_23_LUTG1[];
|
||||
static const unsigned char lut_24_LUTG2[];
|
||||
static const unsigned char lut_25_LUTR0[];
|
||||
static const unsigned char lut_26_LUTR1[];
|
||||
static const unsigned char lut_27_LUTR2[];
|
||||
static const unsigned char lut_28_LUTR3[];
|
||||
static const unsigned char lut_29_LUTXON[];
|
||||
static const unsigned char customGrey[];
|
||||
void sendLut(int lutid);
|
||||
void epd_init();
|
||||
void epd_sendZoneInfo();
|
||||
void epd_sendWriter(std::function<uint8_t(int)> f);
|
||||
#ifdef READGUY_583A_DUAL_BUFFER
|
||||
uint8_t *buf_2nd=nullptr; //second Buffer for luts
|
||||
#endif
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
74
src/guy_epaper/guy_583B/guy_583B.cpp
Normal file
74
src/guy_epaper/guy_583B/guy_583B.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_583B.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 583B 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 583B 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_583B.h"
|
||||
#ifdef READGUY_DEV_583B
|
||||
namespace guydev_583B{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
src/guy_epaper/guy_583B/guy_583B.h
Normal file
63
src/guy_epaper/guy_583B/guy_583B.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_583B.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 583B 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 583B 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD583B_H_FILE) && (defined(READGUY_DEV_583B)))
|
||||
#define _GUY_EPD583B_H_FILE
|
||||
|
||||
namespace guydev_583B{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_583B; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
74
src/guy_epaper/guy_750A/guy_750A.cpp
Normal file
74
src/guy_epaper/guy_750A/guy_750A.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_750A.cpp
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 源代码模板
|
||||
* 使用前, 先查找替换 750A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 750A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "guy_750A.h"
|
||||
#ifdef READGUY_DEV_750A
|
||||
namespace guydev_750A{
|
||||
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
|
||||
|
||||
void drv::drv_init(){ //初始化屏幕
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_fullpart(bool part){ //初始化慢刷功能
|
||||
if(lastRefresh) return;
|
||||
//add driver code...
|
||||
}
|
||||
void drv::drv_setDepth(uint8_t i){
|
||||
epdFull=0; iLut = i?(i>15?15:i):15; //如果需要, 改成自己的代码
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(m&1){//stage 1
|
||||
if(lastRefresh) drv_dispWriter(f,2);
|
||||
//add driver code...
|
||||
}
|
||||
if(m&2){//stage 2
|
||||
uint32_t ms=millis()-lastRefresh;
|
||||
uint32_t u=epdFull?slowRefTime:fastRefTime; //全刷:局刷 busy时间
|
||||
if(ms<u) guy_epdBusy(u-ms); //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
|
||||
lastRefresh=0;
|
||||
//add driver code...
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() { //开始屏幕睡眠
|
||||
if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
|
||||
//add driver code...
|
||||
}
|
||||
epd_PowerOn = 0;
|
||||
epdFull = 1; //强制设置为慢刷新模式
|
||||
}
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
|
||||
|
||||
63
src/guy_epaper/guy_750A/guy_750A.h
Normal file
63
src/guy_epaper/guy_750A/guy_750A.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/******************** F r i e n d s h i p E n d e r ********************
|
||||
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
|
||||
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
|
||||
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
|
||||
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
|
||||
* @file guy_750A.h
|
||||
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
|
||||
* @brief 墨水屏 驱动库函数 头文件模板
|
||||
* 使用前, 先查找替换 750A 改为你需要的驱动名称
|
||||
* 比如3英寸的屏幕驱动程序应该叫 guy_dev_300a
|
||||
* 此时需要将 750A 替换为300A.
|
||||
* 替换好之后, 改文件名, 大小写也要注意改 (文件名最好不要出现大写)
|
||||
* 最后把这个brief替换掉
|
||||
* @version 1.0
|
||||
* @date 2023-11-11
|
||||
|
||||
* @attention
|
||||
* Copyright (c) 2022-2023 FriendshipEnder
|
||||
*
|
||||
* Apache License, Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "../guy_epdbase.h"
|
||||
#if (!defined(_GUY_EPD750A_H_FILE) && (defined(READGUY_DEV_750A)))
|
||||
#define _GUY_EPD750A_H_FILE
|
||||
|
||||
namespace guydev_750A{
|
||||
constexpr int GUY_D_WIDTH =200; //驱动屏幕宽度
|
||||
constexpr int GUY_D_HEIGHT =200; //驱动屏幕高度
|
||||
constexpr int slowRefTime =2000; //驱动屏幕慢刷时间, 单位毫秒
|
||||
constexpr int fastRefTime =500; //驱动屏幕快刷时间, 单位毫秒
|
||||
|
||||
class drv : public readguyEpdBase {
|
||||
public:
|
||||
int drv_ID() const { return READGUY_DEV_750A; }
|
||||
void drv_init(); //初始化屏幕
|
||||
void drv_fullpart(bool part); //切换慢刷/快刷功能
|
||||
void drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m=3); //按照函数刷新
|
||||
void drv_sleep() ; //开始屏幕睡眠
|
||||
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
|
||||
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
|
||||
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
|
||||
void drv_setDepth(uint8_t i); //设置显示颜色深度
|
||||
int drv_supportGreyscaling() const { return 16; }
|
||||
private:
|
||||
uint8_t epd_PowerOn=1; //是否上电. 睡眠则设为0
|
||||
uint8_t epdFull=0; //是partical模式/快速刷新模式 0快刷, 1慢刷
|
||||
uint8_t iLut=15; //颜色深度
|
||||
};
|
||||
}
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -44,7 +44,7 @@
|
||||
#define READGUY_DEV_154A 0 //1.54寸标准, 甘草酸不酸使用的1.54默认屏幕型号. 1.54汉朔价签也选这个
|
||||
#define READGUY_DEV_154B 1 //1.54寸Lilygo, lilygo的1.54触摸和1.54背光墨水屏. GDEH0154D67
|
||||
#define READGUY_DEV_213A 2 //2.13寸汉朔价签, 价格便宜, 兼容性好. 夏襄居士单词卡用 GDE0213B1
|
||||
#define READGUY_DEV_213B 3 //2.13寸三色, 分辨率低212x104, 部分价签也用这个屏 易老化
|
||||
#define READGUY_DEV_213B 3 //2.13寸, 分辨率低212x104, 部分2.13驱动不了的情况下用这个屏驱动
|
||||
#define READGUY_DEV_266A 4 //2.66寸Vusion价签, 黑白双色.
|
||||
#define READGUY_DEV_270B 5 //2.7寸佳显触摸墨水屏, 佳显官方店有售: 2.7寸触摸墨水屏.
|
||||
#define READGUY_DEV_290A 6 //2.9寸A01, 甘草酸不酸2.9寸A01型号. 显示性能一般
|
||||
@@ -53,6 +53,22 @@
|
||||
#define READGUY_DEV_420A 9 //4.2寸HINK黑白价签, 汉朔价签, 汉朔三色价签通用. 速度快, 但效果一般
|
||||
#define READGUY_DEV_420B 10 //4.2寸WF丝印, 部分价签也用此型号屏, 排线有WF开头的丝印
|
||||
#define MEPD_DEBUG_DISPLAY 11 //使用LCD显示屏幕来debug. 前往ctg_stack_c_defines.h修改兼容的屏幕.
|
||||
#define READGUY_DEV_213B3C 12 //2.13寸三色, 分辨率低212x104, 部分价签也用这个屏 易老化
|
||||
#define READGUY_DEV_266A3C 13 //2.66寸三色. 驱动只能支持黑白色, 分辨率 296x152,
|
||||
|
||||
//#define READGUY_DEV_154C 14 //(即将推出) 1.54寸M09墨水屏 (M5Stack Core-Ink 同款; GDEW0154M09)
|
||||
//#define READGUY_DEV_370B 15 //(即将推出) 3.7寸低DPI墨水屏, 分辨率416*240, b站 @叫我武哒哒 的项目用
|
||||
//#define READGUY_DEV_426A 16 //(即将推出) 4.26寸高分辨率墨水屏, 800*480. GDEQ0426T82 支持硬件四灰
|
||||
#define READGUY_DEV_583A 17 //(即将推出) 5.83寸墨水屏幕, 分辨率为600*448. 有黑白有三色
|
||||
//#define READGUY_DEV_583B 18 //(即将推出) 5.83寸高分辨率, 640*480. GDEQ0583T31 只有黑白
|
||||
//#define READGUY_DEV_750A 19 //(即将推出) 7.5 寸墨水屏幕, 800*480. 只有三色(买不到黑白)
|
||||
//#define READGUY_DEV_1020A 20 //(即将推出) 10.2寸墨水屏GDEQ102T90, 芯片SSD1677. 黑白色分辨率960*640
|
||||
|
||||
//添加新屏幕型号 add displays here
|
||||
|
||||
#define EPD_DRIVERS_NUM_MAX 21 //此选项请不要取消注释掉, 有几个屏幕就写多少.
|
||||
|
||||
#define READGUY_583A_DUAL_BUFFER //对于单缓存的5.83屏幕, 启用双缓存支持
|
||||
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
@@ -70,11 +70,14 @@ int readguyEpdBase::IfInit(SPIClass &c,int8_t cs,int8_t dc,int8_t rst,int8_t bus
|
||||
RST_PIN = rst;
|
||||
BUSY_PIN = busy;
|
||||
if(CS_PIN>=0) pinMode(CS_PIN , OUTPUT);
|
||||
DigitalWrite(CS_PIN,HIGH);
|
||||
if(RST_PIN>=0) pinMode(RST_PIN , OUTPUT);
|
||||
DigitalWrite(RST_PIN,HIGH);
|
||||
if(DC_PIN>=0) pinMode(DC_PIN , OUTPUT);
|
||||
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));
|
||||
@@ -157,9 +160,9 @@ void readguyEpdBase::Reset(uint32_t minTime)
|
||||
}
|
||||
//void readguyEpdBase::drv_draw16grey(const uint8_t *d16bit){ //不支持的话什么都不做
|
||||
|
||||
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o){
|
||||
#ifndef FLOYD_STEINBERG_DITHERING
|
||||
static const uint8_t bayer_tab [64]={
|
||||
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o,
|
||||
uint16_t fw, uint16_t fh){
|
||||
static const PROGMEM uint8_t bayer_tab [64]={
|
||||
0, 32, 8, 40, 2, 34, 10, 42,
|
||||
48, 16, 56, 24, 50, 18, 58, 26,
|
||||
12, 44, 4, 36, 14, 46, 6, 38,
|
||||
@@ -169,31 +172,30 @@ 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
|
||||
const uint32_t w = (spr.width()+7)>>3;
|
||||
if((!w) || (!spr.height())) return;
|
||||
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 [spr.width()];
|
||||
floyd_tab[1] = new int16_t [spr.width()];
|
||||
for(int j=0;j<spr.width();j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
|
||||
#endif
|
||||
writeBuff = new uint8_t[w];
|
||||
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; }
|
||||
writeBuff = new uint8_t[(fw+7)>>3];
|
||||
}
|
||||
sprbase.fillRect(x,y,spr.width(),spr.height(),1);
|
||||
for(int32_t i=y;i<(int32_t)spr.height()+y;i++){
|
||||
spr.readRect(0,i-y,spr.width(),1,readBuff);
|
||||
#ifdef FLOYD_STEINBERG_DITHERING
|
||||
sprbase.fillRect(x,y,fw,fh,1);
|
||||
for(int32_t i=y;i<(int32_t)fh+y;i++){
|
||||
uint_fast8_t buff8bit=0;
|
||||
for(int32_t j=0;j<spr.width();j++){
|
||||
int32_t flodelta = floyd_tab[i&1][j]+(int32_t)((greysc(readBuff[j])<<8)|greysc(readBuff[j]));
|
||||
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);
|
||||
if(flodelta>=0x8000) {
|
||||
//spr.drawPixel(j,i,1);
|
||||
buff8bit |= 1<<((~j)&7);
|
||||
flodelta -= 0xffff;
|
||||
}
|
||||
if((j&7)==7 || j==((int32_t)spr.width()-1)){
|
||||
if((j&7)==7 || j==((int32_t)fw-1)){
|
||||
writeBuff[j>>3]=buff8bit;
|
||||
buff8bit=0;
|
||||
}
|
||||
@@ -205,110 +207,99 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
|
||||
}
|
||||
if(j) { floyd_tab[!(i&1)][j-1] += (flodelta*3)>>4; }
|
||||
{ floyd_tab[!(i&1)][j ] += (flodelta*5)>>4; }*/
|
||||
if(j!=spr.width()-1)
|
||||
if(j!=fw-1)
|
||||
{ floyd_tab[i&1] [j+1] += (flodelta*7)>>4; }
|
||||
if(j) { floyd_tab[!(i&1)][j-1] += (flodelta*3)>>4; }
|
||||
{ floyd_tab[!(i&1)][j ] += (flodelta*5)>>4; }
|
||||
if(j!=spr.width()-1)
|
||||
if(j!=fw-1)
|
||||
{ floyd_tab[!(i&1)][j+1] += (flodelta )>>4; }
|
||||
}
|
||||
for(int floi=0;floi<spr.width();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<<3)+b])>>2))<<(7-b);
|
||||
writeBuff[j]=buff8bit;
|
||||
for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
|
||||
}
|
||||
#endif
|
||||
sprbase.drawBitmap(x,i,writeBuff,spr.width(),1,1,0);
|
||||
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
|
||||
}
|
||||
}
|
||||
//不支持的话使用单色抖动刷屏
|
||||
void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y){
|
||||
void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,
|
||||
uint16_t fw, uint16_t fh){
|
||||
//Serial.println("drv_draw16grey fx");
|
||||
const uint32_t w = (spr.width()+7)>>3;
|
||||
if((!w) || (!spr.height())) return;
|
||||
if(!fw) fw=spr.width();
|
||||
if(!fh) fh=spr.height();
|
||||
if((!fw) || (!fh)) return;
|
||||
readBuff = new uint16_t[spr.width()];
|
||||
if(_quality&2){
|
||||
#ifdef FLOYD_DITHERING_16GREY
|
||||
floyd_tab[0] = new int16_t [spr.width()];
|
||||
floyd_tab[1] = new int16_t [spr.width()];
|
||||
#endif
|
||||
floyd_tab[0] = new int16_t [fw];
|
||||
floyd_tab[1] = new int16_t [fw];
|
||||
}
|
||||
writeBuff = new uint8_t[w];
|
||||
sprbase.fillRect(x,y,spr.width(),spr.height(),1);
|
||||
writeBuff = new uint8_t[(fw+7)>>3];
|
||||
sprbase.fillRect(x,y,fw,fh,1);
|
||||
bool negativeOrder=(drv_supportGreyscaling()==-16);
|
||||
drv_fullpart(0);
|
||||
//_display((const uint8_t*)sprbase.getBuffer()); //先对区域慢刷白屏确保颜色正确
|
||||
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<spr.width();j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
|
||||
#endif
|
||||
for(int i=y;i<spr.height()+y;i++){
|
||||
if(_quality&2) for(int j=0;j<fw;j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
|
||||
for(int i=y;i<(int32_t)fh+y;i++){
|
||||
uint_fast8_t buff8bit=0;
|
||||
spr.readRect(0,i-y,spr.width(),1,readBuff);
|
||||
for(int32_t j=0;j<spr.width();j++){
|
||||
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]);
|
||||
int gv=greysc(readBuff[j*spr.width()/fw]);
|
||||
int32_t fd = floyd_tab[i&1][j]+((gv<<8)|gv);
|
||||
while(fd>=0x800) {
|
||||
cg++;
|
||||
if(fd>=0) fd -= 0x1000;
|
||||
}
|
||||
if(fd<0) fd++;
|
||||
if(j!=spr.width()-1)
|
||||
{ floyd_tab[i&1] [j+1] += (fd*7)>>4; }
|
||||
if(j) { floyd_tab[!(i&1)][j-1] += (fd*3)>>4; }
|
||||
{ floyd_tab[!(i&1)][j ] += (fd*5)>>4; }
|
||||
if(j!=spr.width()-1)
|
||||
{ floyd_tab[!(i&1)][j+1] += (fd )>>4; }
|
||||
if(j!=fw-1) { floyd_tab[i&1] [j+1] += (fd*7)>>4; }
|
||||
if(j) { floyd_tab[!(i&1)][j-1] += (fd*3)>>4; }
|
||||
{ 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])>>4; }
|
||||
#else
|
||||
uint_fast8_t cg=greysc(readBuff[j])>>4;
|
||||
#endif
|
||||
else{ cg=greysc(readBuff[j*spr.width()/fw])>>4; }
|
||||
//uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw])>>4;
|
||||
if(negativeOrder)
|
||||
buff8bit |= (cg<k)<<((~j)&7);
|
||||
else{
|
||||
if(cg<15) //白色不考虑
|
||||
buff8bit |= (cg>=((~k)&15))<<((~j)&7);
|
||||
}
|
||||
if((j&7)==7 || j==((int32_t)spr.width()-1)){
|
||||
if((j&7)==7 || j==((int32_t)fw-1)){
|
||||
writeBuff[j>>3]=buff8bit^0xff;
|
||||
buff8bit=0;
|
||||
}
|
||||
//}
|
||||
//sprbase.drawPixel(x+j,i,(greysc(readBuff[j])/16)==(15-k));
|
||||
//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<spr.width();floi++) floyd_tab[i&1][floi]=0;
|
||||
#endif
|
||||
sprbase.drawBitmap(x,i,writeBuff,spr.width(),1,1,0);
|
||||
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);
|
||||
}
|
||||
drv_draw16grey_step((const uint8_t*)sprbase.getBuffer(),k); //使用灰度显示函数
|
||||
}
|
||||
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. */
|
||||
@@ -36,7 +36,6 @@
|
||||
#define LGFX_USE_V1
|
||||
#include <LovyanGFX.hpp>
|
||||
#include "guy_epaper_config.h"
|
||||
#define EPD_DRIVERS_NUM_MAX 12 //此选项请不要取消注释掉
|
||||
|
||||
#define FILL_WHITE ([](int)->uint8_t{return 0xff;})
|
||||
#define FILL_BLACK ([](int)->uint8_t{return 0x00;})
|
||||
@@ -51,13 +50,12 @@ protected:
|
||||
uint8_t in_trans=0;
|
||||
uint8_t _quality=2; //灰度显示品质 0(默认)-高品质 1-低品质 部分屏幕支持高品质的连续刷灰度.
|
||||
#ifdef MEPD_DEBUG_WAVE
|
||||
uint16_t dat_combo = 0; //dc引脚状态 0 command, 1 data
|
||||
int dat_combo = 0; //dc引脚状态 0 command, 1 data
|
||||
#endif
|
||||
uint16_t *readBuff;// = new uint16_t[spr.width()];
|
||||
uint8_t *writeBuff;// = new uint8_t[w];
|
||||
#if (defined(FLOYD_DITHERING_16GREY) || defined(FLOYD_STEINBERG_DITHERING))
|
||||
int16_t *floyd_tab[2];
|
||||
#endif
|
||||
uint32_t lastRefresh;
|
||||
|
||||
public:
|
||||
readguyEpdBase(void);
|
||||
@@ -82,9 +80,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; //返回显示区域高度, 即使旋转了也不能影响此函数输出
|
||||
@@ -97,8 +95,10 @@ public:
|
||||
* @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); //分步完成灰度刷新
|
||||
void drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y);//省内存方式
|
||||
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);//省内存方式
|
||||
void drv_draw16grey_step(const uint8_t *buf, int step){ //分步完成灰度刷新
|
||||
drv_draw16grey_step([&](int n)->uint8_t{return buf[n];},step);
|
||||
}
|
||||
|
||||
@@ -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模块
|
||||
|
||||
@@ -38,9 +38,11 @@ void drv::drv_init(){
|
||||
ips.fillScreen(0xffff);
|
||||
}
|
||||
void drv::drv_fullpart(bool part){
|
||||
if(lastRefresh) return;
|
||||
partMode=part;
|
||||
}
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
void drv::drv_dispWriter(std::function<uint8_t(int)> f,uint8_t m){ //单色刷新
|
||||
if(!(m&1)) return; //stage 1
|
||||
uint16_t dat[8];
|
||||
unsigned short xbits=(drv_width()+7)/8;
|
||||
if(partMode==0){
|
||||
@@ -79,7 +81,6 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
|
||||
}
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
void drv::drv_sleep() {}
|
||||
|
||||
@@ -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
|
||||
@@ -30,11 +30,20 @@
|
||||
#ifndef _READGUY_VERSION_H_FILE
|
||||
#define _READGUY_VERSION_H_FILE
|
||||
|
||||
//在进行版本更迭之前, 需要检查以下文件的版本号是否为最新
|
||||
//1. ChangeLog.md
|
||||
//2. library.json
|
||||
//3. library.properities
|
||||
//4. README.md
|
||||
//5. git commit 信息
|
||||
//6. 下面的三行 以及下面的这个字符串
|
||||
//务必保证这些版本号是一致的.
|
||||
//另外, 在提交新版本之前, 不要忘记在github上创建release, 否则Arduino IDE会读不到
|
||||
#define READGUY_V_MAJOR 1
|
||||
#define READGUY_V_MINOR 1
|
||||
#define READGUY_V_PATCH 1
|
||||
#define READGUY_V_MINOR 3
|
||||
#define READGUY_V_PATCH 4
|
||||
#define READGUY_VERSION_VAL (READGUY_V_MAJOR*1000+READGUY_V_MINOR*100+READGUY_V_PATCH*10)
|
||||
#define READGUY_VERSION "1.1.1"
|
||||
#define READGUY_VERSION "1.3.4"
|
||||
|
||||
#ifdef ESP8266
|
||||
#define _READGUY_PLATFORM "ESP8266"
|
||||
|
||||
@@ -59,7 +59,7 @@ static const PROGMEM char args_name[23][8]={
|
||||
static const char *NAME_guyDev266=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213B
|
||||
static const PROGMEM char NAME_guyDev213M21[]="2.13寸三色";
|
||||
static const PROGMEM char NAME_guyDev213M21[]="2.13寸低分辨率版";
|
||||
#else
|
||||
static const char *NAME_guyDev213M21=NOT_SUPPORTED;
|
||||
#endif
|
||||
@@ -98,6 +98,53 @@ static const PROGMEM char args_name[23][8]={
|
||||
#else
|
||||
static const char *NAME_guyDev270_V2=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213B3C
|
||||
static const PROGMEM char NAME_guyDev213B3C[]="2.13寸三色";
|
||||
#else
|
||||
static const char *NAME_guyDev213B3C=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_266A3C
|
||||
static const PROGMEM char NAME_guyDev266A3C[]="2.66寸三色价签";
|
||||
#else
|
||||
static const char *NAME_guyDev266A3C=NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
#ifdef READGUY_DEV_154C
|
||||
static const PROGMEM char NAME_guyDev154M5CoreInk[]="1.54寸Core.Ink";
|
||||
#else
|
||||
static const char *NAME_guyDev154M5CoreInk=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_370B
|
||||
static const PROGMEM char NAME_guyDev370LoRes[]="3.7寸低分版本416x240";
|
||||
#else
|
||||
static const char *NAME_guyDev370LoRes=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_426A
|
||||
static const PROGMEM char NAME_guyDev426HiRes[]="4.26寸GDEQ0426T82高分辨率";
|
||||
#else
|
||||
static const char *NAME_guyDev426HiRes=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583A
|
||||
static const PROGMEM char NAME_guyDev583Normal[]="5.83寸黑白/三色价签";
|
||||
#else
|
||||
static const char *NAME_guyDev583Normal=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583B
|
||||
static const PROGMEM char NAME_guyDev583HiResBW[]="5.83寸高分辨率版本";
|
||||
#else
|
||||
static const char *NAME_guyDev583HiResBW=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_750A
|
||||
static const PROGMEM char NAME_guyDev750A3C[]="7.5寸三色价签";
|
||||
#else
|
||||
static const char *NAME_guyDev750A3C=NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_1020A
|
||||
static const PROGMEM char NAME_guyDev1020BW[]="10.2寸黑白";
|
||||
#else
|
||||
static const char *NAME_guyDev1020BW=NOT_SUPPORTED;
|
||||
#endif
|
||||
//添加新屏幕型号 add displays here
|
||||
const char *ReadguyDriver::epd_drivers_list[EPD_DRIVERS_NUM_MAX]={
|
||||
NAME_guyDev154, //此处的顺序必须和 guy_epaper_config.h 里面的一样
|
||||
NAME_guyDev154_V2,
|
||||
@@ -110,7 +157,18 @@ const char *ReadguyDriver::epd_drivers_list[EPD_DRIVERS_NUM_MAX]={
|
||||
NAME_guyDev370,
|
||||
NAME_guyDev420Hink,
|
||||
NAME_guyDev420WF,
|
||||
NAME_epdLcd
|
||||
NAME_epdLcd,
|
||||
NAME_guyDev213B3C,
|
||||
NAME_guyDev266A3C,
|
||||
|
||||
NAME_guyDev154M5CoreInk,
|
||||
NAME_guyDev370LoRes,
|
||||
NAME_guyDev426HiRes,
|
||||
NAME_guyDev583Normal,
|
||||
NAME_guyDev583HiResBW,
|
||||
NAME_guyDev750A3C,
|
||||
NAME_guyDev1020BW
|
||||
//添加新屏幕型号 add displays here
|
||||
};
|
||||
//static const char *index_cn_html;
|
||||
//static const uint8_t faviconData[1150];
|
||||
@@ -126,7 +184,7 @@ void ReadguyDriver::ap_setup(){
|
||||
IPAddress subnet(255,255,255,0);
|
||||
WiFi.softAPConfig(local_IP, gateway, subnet);
|
||||
WiFi.softAP("readguy","12345678");
|
||||
Serial.println(F("ap_setup SSID: readguy, Pass: 12345678"));
|
||||
Serial.println(F("[Guy AP] ap_setup SSID: readguy, Pass: 12345678"));
|
||||
}
|
||||
void ReadguyDriver::server_setup(const String ¬ify, const serveFunc *serveFuncs, int funcs){
|
||||
//启动WiFi服务器端, 这样就可以进行配网工作
|
||||
@@ -163,7 +221,7 @@ void ReadguyDriver::server_setup(const String ¬ify, const serveFunc *serveFun
|
||||
sv.begin();
|
||||
MDNS.begin("readguy");
|
||||
//MDNS.addService("http","tcp",80);
|
||||
Serial.println(F("server_setup done! visit "));
|
||||
Serial.print(F("[Guy server] Done! visit "));
|
||||
if(WiFi.getMode() == WIFI_AP) Serial.println(F("192.168.4.1"));
|
||||
else Serial.println(WiFi.localIP());
|
||||
}
|
||||
@@ -191,7 +249,7 @@ bool ReadguyDriver::server_loop(){ //此时等待网页操作完成响应...
|
||||
}
|
||||
if(refFlag!=127) {
|
||||
Serial.printf("randch: %d %c\n",randomch[refFlag],(char)(randomch[refFlag]));
|
||||
drawChar((width()>>1)-46+refFlag*24,(height()>>1)-14,randomch[refFlag],true,false,4);
|
||||
drawChar((guy_dev->drv_width()>>1)-46+refFlag*24,(guy_dev->drv_height()>>1)-14,randomch[refFlag],true,false,4);
|
||||
guy_dev->drv_fullpart(1);
|
||||
guy_dev->_display((const uint8_t*)getBuffer());
|
||||
}
|
||||
@@ -218,19 +276,23 @@ void ReadguyDriver::handleInitPost(){
|
||||
// 此时返回一个文本输入框, 定位到 handleFinalPost 函数
|
||||
uint8_t btn_count_=0;
|
||||
if(READGUY_cali){ //再次初始化已经初始化的东西, 此时需要关闭一些外设什么的
|
||||
Serial.println(F("Reconfig pins and hardwares..."));
|
||||
Serial.println(F("[Guy Pin] Reconfig pins and hardwares..."));
|
||||
READGUY_cali=0;
|
||||
READGUY_sd_ok=0;
|
||||
#if defined(ESP8266)
|
||||
//Esp8266无视SPI的设定, 固定为唯一的硬件SPI (D5=SCK, D6=MISO, D7=MOSI)
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
SDFS.end();//关闭SD卡
|
||||
#endif
|
||||
btnTask.detach();
|
||||
#else
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
SD.end();//关闭SD卡
|
||||
if(sd_spi != epd_spi) { //共线时, 不要删除SD
|
||||
delete sd_spi;
|
||||
sd_spi=nullptr;
|
||||
}
|
||||
#endif
|
||||
vTaskDelete(btn_handle);
|
||||
#endif
|
||||
}
|
||||
@@ -280,7 +342,7 @@ void ReadguyDriver::handleInitPost(){
|
||||
uint8_t ck=checkEpdDriver();
|
||||
if(btn_count_<2) config_data[16]=0;
|
||||
if(btn_count_<3) config_data[17]=0;
|
||||
Serial.println(F("Config OK. Now init devices."));
|
||||
Serial.println(F("[Guy Pin] Config OK. Now init devices."));
|
||||
if(ck>=125) {
|
||||
const char *pNotify[3]={ PSTR("Necessary pin NOT connected."),\
|
||||
PSTR("Pin conflicted."),PSTR("Display not supported.") };
|
||||
@@ -304,24 +366,26 @@ void ReadguyDriver::handleInitPost(){
|
||||
randomch[1] = 48+((rdm>>12)%10);//R2CHAR((rdm>>12)%10);
|
||||
randomch[2] = 48+((rdm>> 6)%10);//R2CHAR((rdm>> 6)%10);
|
||||
randomch[3] = 48+((rdm )%10);//R2CHAR((rdm )%10);
|
||||
Serial.print(F("rand string: "));
|
||||
Serial.print(F("[Guy] rand string: "));
|
||||
for(int i=0;i<4;i++) Serial.write(randomch[i]);
|
||||
Serial.write('\n');
|
||||
Serial.println(F("Init EPD...")); //此时引脚io数据已经录入, 如果没有问题, 此处屏幕应当可以显示
|
||||
Serial.println(F("[Guy] Init EPD...")); //此时引脚io数据已经录入, 如果没有问题, 此处屏幕应当可以显示
|
||||
setEpdDriver(); //尝试初始化屏幕
|
||||
Serial.println(F("Init details..."));
|
||||
drawCenterString(setSDcardDriver()?"SD Init OK!":"SD Init failed!",width()>>1,(height()>>1)+20);
|
||||
Serial.println(F("[Guy] Init details..."));
|
||||
setTextSize(1);
|
||||
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());
|
||||
spibz--;
|
||||
Serial.println(F("Display done!"));
|
||||
Serial.println(F("[Guy] Display done!"));
|
||||
READGUY_cali=1; //显示初始化完成
|
||||
}
|
||||
void ReadguyDriver::handlePinSetup(){
|
||||
@@ -336,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按钮
|
||||
};
|
||||
@@ -514,6 +578,7 @@ void ReadguyDriver::handleFinal(){
|
||||
}
|
||||
s+=F("<br/><hr/>"); //换行
|
||||
}
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
if(!READGUY_sd_ok) s+=F("SD卡不可用!!!<br/>");
|
||||
#if (defined(ESP8266)) //此函数速度太慢了, 因此删掉不用了
|
||||
/*else{
|
||||
@@ -543,6 +608,7 @@ void ReadguyDriver::handleFinal(){
|
||||
s+=(uint32_t)(SD.usedBytes()/1024);
|
||||
s+=F("KB.<br/>");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
s+=F("当前WiFi模式: ");
|
||||
s+=(WiFi.getMode()==WIFI_STA)?F("正常联网模式"):F("AP配网模式");
|
||||
@@ -592,7 +658,7 @@ void ReadguyDriver::handleFinal(){
|
||||
//s+=F("<br/>"); //换行
|
||||
sv.send_P(200, TEXT_HTML, (s+FPSTR(end_html)).c_str());
|
||||
if(READGUY_cali == 63){
|
||||
Serial.println(F("Data saved to NVS."));
|
||||
Serial.println(F("[Guy NVS] Data saved to NVS."));
|
||||
READGUY_cali = 127;
|
||||
nvs_init();
|
||||
nvs_write();
|
||||
@@ -643,7 +709,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/>"
|
||||
|
||||
318
src/readguy.cpp
318
src/readguy.cpp
@@ -38,6 +38,36 @@ int8_t ReadguyDriver::pin_cmx=-1;
|
||||
const PROGMEM char ReadguyDriver::projname[8] = "readguy";
|
||||
const PROGMEM char ReadguyDriver::tagname[7] = "hwconf";
|
||||
volatile uint8_t ReadguyDriver::spibz=0;
|
||||
#ifndef DYNAMIC_PIN_SETTINGS
|
||||
const int8_t ReadguyDriver::config_data[22] = {
|
||||
127 , //READGUY_cali
|
||||
READGUY_shareSpi ,
|
||||
READGUY_epd_type ,// 对应的epd驱动程序代号, -1为未指定
|
||||
//显示驱动部分, 显示默认使用vspi (vspi也是默认SPI库的通道)
|
||||
READGUY_epd_mosi ,// 目标显示器的 MOSI 引脚
|
||||
READGUY_epd_sclk ,// 目标显示器的 SCLK 引脚
|
||||
READGUY_epd_cs ,// 目标显示器的 CS 引脚
|
||||
READGUY_epd_dc ,// 目标显示器的 DC 引脚
|
||||
READGUY_epd_rst ,// 目标显示器的 RST 引脚
|
||||
READGUY_epd_busy ,// 目标显示器的 BUSY 引脚
|
||||
//sd卡驱动部分, 默认使用hspi (sd卡建议用hspi)
|
||||
READGUY_sd_miso ,// 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
|
||||
READGUY_sd_mosi ,// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
|
||||
READGUY_sd_sclk ,// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
|
||||
READGUY_sd_cs ,// 目标sd卡的 CS 引脚.
|
||||
READGUY_i2c_sda ,// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
|
||||
READGUY_i2c_scl ,// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
|
||||
//按键驱动部分, 为负代表高触发, 否则低触发,
|
||||
//注意, 这里的io编号是加1的, 即 1或-1 代表 gpio0 的低触发/高触发
|
||||
READGUY_btn1 ,
|
||||
READGUY_btn2 ,
|
||||
READGUY_btn3 ,
|
||||
READGUY_bl_pin ,//前置光接口引脚IO
|
||||
READGUY_rtc_type ,//使用的RTC型号(待定, 还没用上)
|
||||
0 ,//READGUY_sd_ok SD卡已经成功初始化
|
||||
0 //READGUY_buttons 按钮个数, 0-3都有可能
|
||||
};
|
||||
#endif
|
||||
#ifndef ESP8266
|
||||
SPIClass *ReadguyDriver::sd_spi =nullptr;
|
||||
SPIClass *ReadguyDriver::epd_spi=nullptr;
|
||||
@@ -48,8 +78,8 @@ ReadguyDriver::ReadguyDriver(){
|
||||
READGUY_cali = 0; // config_data[0] 的初始值为0
|
||||
READGUY_sd_ok = 0; //初始默认SD卡未成功初始化
|
||||
READGUY_buttons = 0; //初始情况下没有按钮
|
||||
}
|
||||
uint8_t ReadguyDriver::init(uint8_t WiFiSet){ //WiFiSet: 是否保持AP服务器一直处于打开状态
|
||||
} //WiFiSet: 是否保持AP服务器一直处于打开状态
|
||||
uint8_t ReadguyDriver::init(uint8_t WiFiSet, bool initepd, bool initSD){
|
||||
if(READGUY_cali==127) //已经初始化过了一次了, 为了防止里面一些volatile的东西出现问题....还是退出吧
|
||||
return 0;
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
@@ -77,20 +107,25 @@ uint8_t ReadguyDriver::init(uint8_t WiFiSet){ //WiFiSet: 是否保持AP服务器
|
||||
else{ //看来NVS有数据, //从NVS加载数据, 哪怕前面的数据刚刚写入, 还没读取
|
||||
if(WiFiSet>=2) WiFi.begin(); //连接到上次存储在flash NVS中的WiFi.
|
||||
else if(WiFiSet==1) ap_setup();
|
||||
if(checkEpdDriver()!=127) setEpdDriver(); //初始化屏幕
|
||||
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
|
||||
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
|
||||
setSDcardDriver();
|
||||
if(initSD) setSDcardDriver();
|
||||
setButtonDriver();
|
||||
}
|
||||
#endif
|
||||
nvs_deinit();
|
||||
#else
|
||||
if(checkEpdDriver()!=127) setEpdDriver(); //初始化屏幕
|
||||
nvs_init();
|
||||
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
|
||||
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
|
||||
setSDcardDriver();
|
||||
if(initSD) setSDcardDriver();
|
||||
setButtonDriver();
|
||||
if(!nvs_read()){
|
||||
nvs_write(); //全部成功之后, 写入引脚信息到NVS.
|
||||
}
|
||||
nvs_deinit();
|
||||
#endif
|
||||
Serial.println(F("init done."));
|
||||
Serial.println(F("[Guy init] init done."));
|
||||
READGUY_cali=127;
|
||||
return READGUY_sd_ok;
|
||||
}
|
||||
@@ -101,7 +136,7 @@ uint8_t ReadguyDriver::checkEpdDriver(){
|
||||
#else
|
||||
#define TEST_ONLY_VALUE 3
|
||||
#endif
|
||||
Serial.printf_P(PSTR("READGUY_shareSpi? %d\n"),READGUY_shareSpi);
|
||||
Serial.printf_P(PSTR("[Guy SPI] shareSpi? %d\n"),READGUY_shareSpi);
|
||||
for(int i=TEST_ONLY_VALUE;i<8;i++){
|
||||
if(i<7 && config_data[i]<0) return 125;//必要的引脚没连接
|
||||
for(int j=1;j<=8-i;j++)
|
||||
@@ -111,47 +146,124 @@ uint8_t ReadguyDriver::checkEpdDriver(){
|
||||
#endif
|
||||
if(guy_dev != nullptr && READGUY_epd_type!=guy_dev->drv_ID()) delete guy_dev; //释放多余的内存
|
||||
//Serial.printf("initing epd %s...\n",epd_drivers_list[READGUY_epd_type]);
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
switch (READGUY_epd_type){
|
||||
#ifdef READGUY_DEV_154A
|
||||
case READGUY_DEV_154A: guy_dev = new guydev_154A_290A ::dev154A; break; //适用于一般的价签黑白屏
|
||||
case READGUY_DEV_154A: guy_dev = new guydev_154A_290A ::dev154A; break; //适用于一般的价签黑白屏
|
||||
#endif
|
||||
#ifdef READGUY_DEV_154B
|
||||
case READGUY_DEV_154B: guy_dev = new guydev_154B_270B_290B ::dev154B; break; //适用于
|
||||
case READGUY_DEV_154B: guy_dev = new guydev_154B_270B_290B ::dev154B; break; //适用于
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213A
|
||||
case READGUY_DEV_213A: guy_dev = new guydev_213A ::drv; break;
|
||||
case READGUY_DEV_213A: guy_dev = new guydev_213A ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_266A
|
||||
case READGUY_DEV_266A: guy_dev = new guydev_213B_266A ::dev266A; break;
|
||||
case READGUY_DEV_266A: guy_dev = new guydev_213B_266A ::dev266A; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213B
|
||||
case READGUY_DEV_213B: guy_dev = new guydev_213B_266A ::dev213B; break;
|
||||
case READGUY_DEV_213B: guy_dev = new guydev_213B_266A ::dev213B; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_290A
|
||||
case READGUY_DEV_290A: guy_dev = new guydev_154A_290A ::dev290A; break;
|
||||
case READGUY_DEV_290A: guy_dev = new guydev_154A_290A ::dev290A; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_290B
|
||||
case READGUY_DEV_290B: guy_dev = new guydev_154B_270B_290B ::dev290B; break;
|
||||
case READGUY_DEV_290B: guy_dev = new guydev_154B_270B_290B ::dev290B; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_420A
|
||||
case READGUY_DEV_420A: guy_dev = new guydev_420A ::drv; break;
|
||||
case READGUY_DEV_420A: guy_dev = new guydev_420A ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_420B
|
||||
case READGUY_DEV_420B: guy_dev = new guydev_420B ::drv; break;
|
||||
case READGUY_DEV_420B: guy_dev = new guydev_420B ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_370A
|
||||
case READGUY_DEV_370A: guy_dev = new guydev_370A ::drv; break;
|
||||
case READGUY_DEV_370A: guy_dev = new guydev_370A ::drv; break;
|
||||
#endif
|
||||
#ifdef MEPD_DEBUG_DISPLAY
|
||||
case MEPD_DEBUG_DISPLAY:guy_dev = new EpdLcdDebug ::drv; break;
|
||||
case MEPD_DEBUG_DISPLAY: guy_dev = new EpdLcdDebug ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_270B
|
||||
case READGUY_DEV_270B: guy_dev = new guydev_154B_270B_290B ::dev270B; break;
|
||||
case READGUY_DEV_270B: guy_dev = new guydev_154B_270B_290B ::dev270B; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_213B3C
|
||||
case READGUY_DEV_213B3C: guy_dev = new guydev_213B_266A ::dev213B3C; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_266A3C
|
||||
case READGUY_DEV_266A3C: guy_dev = new guydev_213B_266A ::dev266A3C; break;
|
||||
#endif
|
||||
|
||||
#ifdef READGUY_DEV_154C
|
||||
case READGUY_DEV_154C: guy_dev = new guydev_154C ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_370B
|
||||
case READGUY_DEV_370B: guy_dev = new guydev_370B ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_426A
|
||||
case READGUY_DEV_426A: guy_dev = new guydev_426A ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583A
|
||||
case READGUY_DEV_583A: guy_dev = new guydev_583A ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583B
|
||||
case READGUY_DEV_583B: guy_dev = new guydev_583B ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_750A
|
||||
case READGUY_DEV_750A: guy_dev = new guydev_750A ::drv; break;
|
||||
#endif
|
||||
#ifdef READGUY_DEV_1020A
|
||||
case READGUY_DEV_1020A: guy_dev = new guydev_1020A ::drv; break;
|
||||
#endif
|
||||
//添加新屏幕型号 add displays here
|
||||
default:
|
||||
Serial.println(F("[ERR] EPD DRIVER IC NOT SUPPORTED!\n"));
|
||||
Serial.println(F("[GUY ERR] EPD DRIVER IC NOT SUPPORTED!\n"));
|
||||
return 127;
|
||||
}
|
||||
#else
|
||||
#if (defined(READGUY_DEV_154A) && (READGUY_epd_type==READGUY_DEV_154A))
|
||||
guy_dev = new guydev_154A_290A ::dev154A; //适用于一般的价签黑白屏
|
||||
#elif (defined(READGUY_DEV_154B) && (READGUY_epd_type==READGUY_DEV_154B))
|
||||
guy_dev = new guydev_154B_270B_290B ::dev154B; //适用于
|
||||
#elif (defined(READGUY_DEV_213A) && (READGUY_epd_type==READGUY_DEV_213A))
|
||||
guy_dev = new guydev_213A ::drv;
|
||||
#elif (defined(READGUY_DEV_266A) && (READGUY_epd_type==READGUY_DEV_266A))
|
||||
guy_dev = new guydev_213B_266A ::dev266A;
|
||||
#elif (defined(READGUY_DEV_213B) && (READGUY_epd_type==READGUY_DEV_213B))
|
||||
guy_dev = new guydev_213B_266A ::dev213B;
|
||||
#elif (defined(READGUY_DEV_290A) && (READGUY_epd_type==READGUY_DEV_290A))
|
||||
guy_dev = new guydev_154A_290A ::dev290A;
|
||||
#elif (defined(READGUY_DEV_290B) && (READGUY_epd_type==READGUY_DEV_290B))
|
||||
guy_dev = new guydev_154B_270B_290B ::dev290B;
|
||||
#elif (defined(READGUY_DEV_420A) && (READGUY_epd_type==READGUY_DEV_420A))
|
||||
guy_dev = new guydev_420A ::drv;
|
||||
#elif (defined(READGUY_DEV_420B) && (READGUY_epd_type==READGUY_DEV_420B))
|
||||
guy_dev = new guydev_420B ::drv;
|
||||
#elif (defined(READGUY_DEV_370A) && (READGUY_epd_type==READGUY_DEV_370A))
|
||||
guy_dev = new guydev_370A ::drv;
|
||||
#elif (defined(MEPD_DEBUG_DISPLAY) && (READGUY_epd_type==MEPD_DEBUG_DISPLAY))
|
||||
guy_dev = new EpdLcdDebug ::drv;
|
||||
#elif (defined(READGUY_DEV_270B) && (READGUY_epd_type==READGUY_DEV_270B))
|
||||
guy_dev = new guydev_154B_270B_290B ::dev270B;
|
||||
#elif (defined(READGUY_DEV_213B3C) && (READGUY_epd_type==READGUY_DEV_213B3C))
|
||||
guy_dev = new guydev_213B_266A ::dev213B3C;
|
||||
#elif (defined(READGUY_DEV_266A3C) && (READGUY_epd_type==READGUY_DEV_266A3C))
|
||||
guy_dev = new guydev_213B_266A ::dev266B3C;
|
||||
|
||||
#elif (defined(READGUY_DEV_154C) && (READGUY_epd_type==READGUY_DEV_154C))
|
||||
guy_dev = new guydev_154C ::drv;
|
||||
#elif (defined(READGUY_DEV_370B) && (READGUY_epd_type==READGUY_DEV_370B))
|
||||
guy_dev = new guydev_370B ::drv;
|
||||
#elif (defined(READGUY_DEV_426A) && (READGUY_epd_type==READGUY_DEV_426A))
|
||||
guy_dev = new guydev_426A ::drv;
|
||||
#elif (defined(READGUY_DEV_583A) && (READGUY_epd_type==READGUY_DEV_583A))
|
||||
guy_dev = new guydev_583A ::drv;
|
||||
#elif (defined(READGUY_DEV_583B) && (READGUY_epd_type==READGUY_DEV_583B))
|
||||
guy_dev = new guydev_583B ::drv;
|
||||
#elif (defined(READGUY_DEV_750A) && (READGUY_epd_type==READGUY_DEV_750A))
|
||||
guy_dev = new guydev_750A ::drv;
|
||||
#elif (defined(READGUY_DEV_1020A) && (READGUY_epd_type==READGUY_DEV_1020A))
|
||||
guy_dev = new guydev_1020A ::drv;
|
||||
#endif
|
||||
//添加新屏幕型号 add displays here
|
||||
#endif
|
||||
#if (defined(ESP8266))
|
||||
SPI.begin();
|
||||
SPI.setFrequency(ESP8266_SPI_FREQUENCY); ///< 1MHz
|
||||
@@ -169,33 +281,35 @@ uint8_t ReadguyDriver::checkEpdDriver(){
|
||||
epd_spi->begin(READGUY_epd_sclk,READGUY_shareSpi?READGUY_sd_miso:-1,READGUY_epd_mosi);
|
||||
guy_dev->IfInit(*epd_spi, READGUY_epd_cs, READGUY_epd_dc, READGUY_epd_rst, READGUY_epd_busy);
|
||||
#endif
|
||||
Serial.println(F("IfInit OK"));
|
||||
Serial.println(F("[Guy SPI] drvBase Init OK"));
|
||||
return READGUY_epd_type;
|
||||
}
|
||||
void ReadguyDriver::setEpdDriver(int g_width,int g_height){
|
||||
void ReadguyDriver::setEpdDriver(bool initepd, bool initGFX){
|
||||
guy_dev->spi_tr_release = in_release;
|
||||
guy_dev->spi_tr_press = in_press;
|
||||
guy_dev->drv_init(); //初始化epd驱动层
|
||||
if(g_width) guy_width = g_width;
|
||||
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("EPD init OK"));
|
||||
if(initepd) guy_dev->drv_init(); //初始化epd驱动层
|
||||
//if(g_width) guy_width = g_width;
|
||||
//else guy_width = guy_dev->drv_width(); //宽度必须是8的倍数, 但这个可以由GFX自动计算
|
||||
//if(g_height) guy_height = g_height;
|
||||
//else guy_height = guy_dev->drv_height();
|
||||
//以下依赖于你的图形驱动
|
||||
setColorDepth(1); //单色模式
|
||||
createPalette(); //初始化颜色系统
|
||||
Serial.printf_P(PSTR("mono set: w: %d, h: %d\n"),guy_width,guy_height);
|
||||
//创建画布. 根据LovyanGFX的特性, 如果以前有画布会自动重新生成新画布
|
||||
//此外, 即使画布宽度不是8的倍数(如2.13寸单色),也支持自动补全8的倍数 ( 250x122 => 250x128 )
|
||||
//为了保证图片显示功能的正常使用, 高度也必须是8的倍数.
|
||||
createSprite(guy_width,(guy_height+7)&0x7ffffff8);
|
||||
//setRotation(1); //旋转之后操作更方便
|
||||
setRotation(0);
|
||||
setFont(&fonts::Font0);
|
||||
setCursor(0,0);
|
||||
setTextColor(0);
|
||||
fillScreen(1); //开始先全屏白色
|
||||
if(initGFX){
|
||||
setColorDepth(1); //单色模式
|
||||
createPalette(); //初始化颜色系统
|
||||
//创建画布. 根据LovyanGFX的特性, 如果以前有画布会自动重新生成新画布
|
||||
//此外, 即使画布宽度不是8的倍数(如2.13寸单色),也支持自动补全8的倍数 ( 250x122 => 250x128 )
|
||||
//为了保证图片显示功能的正常使用, 高度也必须是8的倍数.
|
||||
createSprite(guy_dev->drv_width(),guy_dev->drv_height());
|
||||
//这里发现如果用自定义的内存分配方式会更好一些. 不会导致返回的height不对. 但是因为LovyanGFX库未更新 暂时不能这么用.
|
||||
setRotation(0); //默认的旋转方向就是0咯
|
||||
setFont(&fonts::Font0);
|
||||
setCursor(0,0);
|
||||
setTextColor(0);
|
||||
fillScreen(1); //开始先全屏白色
|
||||
}
|
||||
Serial.printf_P(PSTR("[Guy EPD] EPD init OK(%d): w: %d, h: %d\n"),guy_dev->drv_ID(),guy_dev->drv_width(),guy_dev->drv_height());
|
||||
}
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
bool ReadguyDriver::setSDcardDriver(){
|
||||
/*重要信息: 有些引脚冲突是难以避免的, 比如8266 尤其需要重写这部分代码
|
||||
对于esp32也要注意这个引脚是否是一个合法的引脚
|
||||
@@ -226,6 +340,7 @@ bool ReadguyDriver::setSDcardDriver(){
|
||||
}
|
||||
else READGUY_sd_ok=0; //引脚不符合规则,或冲突或不可用
|
||||
if(!READGUY_sd_ok){
|
||||
Serial.println(F("[Guy SD] SD Init Failed!"));
|
||||
//guyFS().begin(); //初始化内部FS
|
||||
#ifdef READGUY_USE_LITTLEFS
|
||||
LittleFS.begin();
|
||||
@@ -235,6 +350,17 @@ bool ReadguyDriver::setSDcardDriver(){
|
||||
}
|
||||
return READGUY_sd_ok;
|
||||
}
|
||||
#else
|
||||
bool ReadguyDriver::setSDcardDriver(){
|
||||
READGUY_sd_ok=0;
|
||||
#ifdef READGUY_USE_LITTLEFS
|
||||
LittleFS.begin();
|
||||
#else
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void ReadguyDriver::setButtonDriver(){
|
||||
if(READGUY_btn1) { //初始化按键. 注意高电平触发的引脚在初始化时要设置为下拉
|
||||
int8_t btn_pin=abs(READGUY_btn1)-1;
|
||||
@@ -278,18 +404,21 @@ void ReadguyDriver::setButtonDriver(){
|
||||
if(READGUY_btn1) btn_rd[0].begin(abs(READGUY_btn1)-1,rd_btn_f,(READGUY_btn1>0));
|
||||
if(READGUY_btn2) btn_rd[1].begin(abs(READGUY_btn2)-1,rd_btn_f,(READGUY_btn2>0));
|
||||
if(READGUY_btn3) btn_rd[2].begin(abs(READGUY_btn3)-1,rd_btn_f,(READGUY_btn3>0));
|
||||
//if(READGUY_buttons==1){
|
||||
btn_rd[0].setLongRepeatMode(1); //允许连按
|
||||
//}
|
||||
if(READGUY_buttons==2){
|
||||
btn_rd[0].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
|
||||
btn_rd[0].setLongRepeatMode(1);
|
||||
//btn_rd[0].setLongRepeatMode(1);
|
||||
btn_rd[1].setMultiBtn(1); //设置为多个按钮,不识别双击或三击
|
||||
btn_rd[1].setLongRepeatMode(0);
|
||||
}
|
||||
else if(READGUY_buttons==3){
|
||||
btn_rd[0].setLongPressMs(1); //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[0].setLongRepeatMode(1);
|
||||
btn_rd[0].long_press_ms = 50; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
//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 = 50; //不识别双击三击, 只有按一下或者长按, 并且开启连按
|
||||
btn_rd[2].setLongRepeatMode(1);
|
||||
}
|
||||
#ifdef ESP8266 //对于esp8266, 需要注册到ticker. 这是因为没freertos.
|
||||
@@ -339,6 +468,7 @@ void ReadguyDriver::setButtonDriver(){
|
||||
}
|
||||
} //关于按键策略, 我们在此使用多个Button2的类, 然后在一个task共享变量来确定上一个按键状态
|
||||
}
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
|
||||
if(initSD==2 || (!READGUY_sd_ok && initSD)) setSDcardDriver();
|
||||
if(READGUY_sd_ok){
|
||||
@@ -354,6 +484,16 @@ fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
|
||||
return SPIFFS;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
fs::FS &ReadguyDriver::guyFS(uint8_t initSD){
|
||||
(void)initSD; //avoid GCC warning
|
||||
#ifdef READGUY_USE_LITTLEFS
|
||||
return LittleFS;
|
||||
#else
|
||||
return SPIFFS;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void ReadguyDriver::setBright(int d){
|
||||
if(currentBright>=0 && d>=0 && d<=255){
|
||||
currentBright=d;
|
||||
@@ -368,40 +508,50 @@ void ReadguyDriver::setBright(int d){
|
||||
digitalWrite(READGUY_bl_pin,d?HIGH:LOW);
|
||||
}
|
||||
}
|
||||
void ReadguyDriver::display(bool part){
|
||||
void ReadguyDriver::display(uint8_t part){
|
||||
//真的是我c++的盲区了啊....搜索了半天才找到可以这么玩的
|
||||
//......可惜'dynamic_cast' not permitted with -fno-rtti
|
||||
// static bool _part = 0; 记忆上次到底是full还是part, 注意启动时默认为full
|
||||
if(READGUY_cali==127){
|
||||
//in_press(); //暂停, 然后读取按键状态 spibz
|
||||
guy_dev->drv_fullpart(part);
|
||||
guy_dev->_display((const uint8_t*)getBuffer());
|
||||
guy_dev->drv_fullpart(part&1);
|
||||
guy_dev->_display((const uint8_t*)getBuffer(),((part>>1)?part>>1:3));
|
||||
//in_release(); //恢复
|
||||
}
|
||||
}
|
||||
void ReadguyDriver::display(std::function<uint8_t(int)> f, bool part){
|
||||
void ReadguyDriver::displayBuffer(const uint8_t *buf, uint8_t part){
|
||||
if(READGUY_cali==127){
|
||||
//in_press(); //暂停, 然后读取按键状态 spibz
|
||||
guy_dev->drv_fullpart(part);
|
||||
guy_dev->drv_dispWriter(f);
|
||||
guy_dev->drv_fullpart(part&1);
|
||||
guy_dev->_display(buf,((part>>1)?part>>1:3));
|
||||
//in_release(); //恢复
|
||||
}
|
||||
}
|
||||
void ReadguyDriver::drawImage(LGFX_Sprite &spr,uint16_t x,uint16_t y) {
|
||||
if(READGUY_cali==127) guy_dev->drv_drawImage(*this, spr, x, y);
|
||||
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::drawImageStage(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint8_t stage,uint8_t totalstage) {
|
||||
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 &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)));
|
||||
//Serial.printf("stage: %d/%d\n",stage+1,totalstage);
|
||||
guy_dev->drv_drawImage(sprbase, spr, x, y, (totalstage<=1)?0:(stage==0?1:(stage==(totalstage-1)?3:2)),zoomw,zoomh);
|
||||
}
|
||||
void ReadguyDriver::setDepth(uint8_t d){
|
||||
if(READGUY_cali==127 && guy_dev->drv_supportGreyscaling()) guy_dev->drv_setDepth(d);
|
||||
}
|
||||
void ReadguyDriver::draw16grey(LGFX_Sprite &spr,uint16_t x,uint16_t y){
|
||||
void ReadguyDriver::draw16grey(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw,uint16_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);
|
||||
guy_dev->drv_drawImage(*this, spr, x, y);
|
||||
return guy_dev->drv_draw16grey(*this,spr,x,y,zoomw,zoomh);
|
||||
guy_dev->drv_drawImage(*this, spr, x, y, 0, zoomw, zoomh);
|
||||
}
|
||||
void ReadguyDriver::draw16greyStep(int step){
|
||||
if(READGUY_cali==127 && guy_dev->drv_supportGreyscaling() && step>0 && step<16 ){
|
||||
@@ -417,7 +567,7 @@ void ReadguyDriver::draw16greyStep(std::function<uint8_t(int)> f, int step){
|
||||
}
|
||||
void ReadguyDriver::invertDisplay(){
|
||||
if(READGUY_cali==127){
|
||||
const int pixels=((guy_width+7)>>3)*guy_height;
|
||||
const int pixels=((guy_dev->drv_width()+7)>>3)*guy_dev->drv_height();
|
||||
for(int i=0;i<pixels;i++)
|
||||
((uint8_t*)(getBuffer()))[i]=uint8_t(~(((uint8_t*)(getBuffer()))[i]));
|
||||
}
|
||||
@@ -426,8 +576,7 @@ void ReadguyDriver::sleepEPD(){
|
||||
if(READGUY_cali==127) guy_dev->drv_sleep();
|
||||
}
|
||||
|
||||
#if (!defined(DYNAMIC_PIN_SETTINGS)) //do nothing here.
|
||||
#elif (defined(INDEV_DEBUG))
|
||||
#if (defined(INDEV_DEBUG))
|
||||
void ReadguyDriver::nvs_init(){
|
||||
}
|
||||
void ReadguyDriver::nvs_deinit(){
|
||||
@@ -447,12 +596,19 @@ void ReadguyDriver::nvs_deinit(){
|
||||
}
|
||||
bool ReadguyDriver::nvs_read(){
|
||||
char s[8];
|
||||
for(unsigned int i=0;i<sizeof(config_data)+8;i++){
|
||||
for(unsigned int i=0;i<
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
sizeof(config_data)+
|
||||
#endif
|
||||
8;i++){
|
||||
int8_t rd=(int8_t)EEPROM.read(2+i);
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
if(i>=8) config_data[i-8] = rd;
|
||||
else s[i]=(char)rd;
|
||||
else
|
||||
#endif
|
||||
s[i]=(char)rd;
|
||||
}
|
||||
Serial.printf("Get NVS...%d\n", config_data[0]);
|
||||
Serial.printf("[Guy NVS] Get EEPROM...%d\n", config_data[0]);
|
||||
return !(strcmp_P(s,projname));
|
||||
}
|
||||
void ReadguyDriver::nvs_write(){
|
||||
@@ -469,6 +625,7 @@ void ReadguyDriver::nvs_deinit(){
|
||||
}
|
||||
bool ReadguyDriver::nvs_read(){ //此处需要处理一些有关I2C的内容
|
||||
if(!nvsData.isKey(tagname)) return 0; //没有这个键值
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
size_t len=nvsData.getBytes(tagname,config_data,sizeof(config_data)); //读取的数据长度
|
||||
/*if(len<sizeof(config_data)){ //旧版本格式无法获取I2C相关数据, 设置为-1.
|
||||
for(int i=sizeof(config_data)-1;i>=15;i--) //使用新版本格式来存储相关数据
|
||||
@@ -478,6 +635,9 @@ bool ReadguyDriver::nvs_read(){ //此处需要处理一些有关I2C的内容
|
||||
nvsData.putBytes(tagname,config_data,sizeof(config_data)); //用新版本格式保存
|
||||
}*/
|
||||
return len==sizeof(config_data);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
void ReadguyDriver::nvs_write(){
|
||||
if(nvsData.isKey(tagname)) nvsData.remove(tagname);
|
||||
@@ -486,29 +646,41 @@ 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(res1 && millis()-last >= btn_rd[1].long_press_ms && (!btn_rd[1].isPressedRaw()))
|
||||
res4 = (res1 == 1)?1:2; //左键点按-向下翻页
|
||||
if(res2) {
|
||||
if(btn_rd[0].isPressedRaw()) res4 |= 3; //避免GCC警告(我常年喜欢-Werror=all
|
||||
else if(res2 == 1) res4 |= 4; //右键点按-确定
|
||||
else if(res2 == 4) res4 |= 8; //右键长按-返回
|
||||
last=millis();
|
||||
}
|
||||
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;
|
||||
|
||||
153
src/readguy.h
153
src/readguy.h
@@ -49,7 +49,8 @@
|
||||
#ifdef READGUY_DEV_213A
|
||||
#include "guy_epaper/guy_213a/guy_213a.h"
|
||||
#endif
|
||||
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_266A))
|
||||
#if (defined(READGUY_DEV_213B) || defined(READGUY_DEV_213B3C) \
|
||||
|| defined(READGUY_DEV_266A) || defined(READGUY_DEV_266A3C))
|
||||
#include "guy_epaper/guy_213b_266a/guy_213b_266a.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_370A
|
||||
@@ -65,6 +66,29 @@
|
||||
#include "guy_epaper/lcdDebug/lcdDebug.h"
|
||||
#endif
|
||||
|
||||
#ifdef READGUY_DEV_154C
|
||||
#include "guy_epaper/guy_154C/guy_154C.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_370B
|
||||
#include "guy_epaper/guy_370B/guy_370B.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_426A
|
||||
#include "guy_epaper/guy_426A/guy_426A.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583A
|
||||
#include "guy_epaper/guy_583A/guy_583A.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_583B
|
||||
#include "guy_epaper/guy_583B/guy_583B.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_750A
|
||||
#include "guy_epaper/guy_750A/guy_750A.h"
|
||||
#endif
|
||||
#ifdef READGUY_DEV_1020A
|
||||
#include "guy_epaper/guy_1020A/guy_1020A.h"
|
||||
#endif
|
||||
//添加新屏幕型号 add displays here
|
||||
|
||||
#include "guy_button.h" //改自Button2精简而来
|
||||
#include "guy_version.h"
|
||||
#include "guy_driver_config.h" //config
|
||||
@@ -77,28 +101,28 @@
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266) //for ESP8266
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
#include <EEPROM.h> //ESP32需要NVS才可以读取引脚信息
|
||||
#endif
|
||||
#include <EEPROM.h> //ESP32需要NVS才可以读取引脚信息,
|
||||
#ifdef READGUY_ESP_ENABLE_WIFI
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include "ESP8266HTTPUpdateServer.h"
|
||||
#endif
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
#include <SDFS.h>
|
||||
#endif
|
||||
#include <Ticker.h>
|
||||
#else //for ESP32
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
#include <Preferences.h> //ESP32需要NVS才可以读取引脚信息
|
||||
#endif
|
||||
#ifdef READGUY_ESP_ENABLE_WIFI
|
||||
#include <WiFi.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "HTTPUpdateServer.h"
|
||||
#endif
|
||||
#ifdef READGUY_ENABLE_SD
|
||||
#include <SD.h>
|
||||
#endif
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#endif
|
||||
@@ -132,6 +156,13 @@
|
||||
#define READGUY_buttons (config_data[21]) //按钮个数, 0-3都有可能
|
||||
#endif
|
||||
|
||||
#define READGUY_SLOW 0
|
||||
#define READGUY_FAST 1
|
||||
#define READGUY_SLOW_START 2
|
||||
#define READGUY_FAST_START 3
|
||||
#define READGUY_SLOW_END 4
|
||||
#define READGUY_FAST_END 5
|
||||
|
||||
class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
public:
|
||||
#ifdef READGUY_ESP_ENABLE_WIFI
|
||||
@@ -147,15 +178,19 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
/** @brief 初始化readguy
|
||||
* @param WiFiSet 是否保持AP模式关闭. 0:配网完成自动关WiFi, 1:需要手动调用 WiFi.mode(WIFI_OFF) 关闭WiFi.
|
||||
* 2:自动连接到已存的WiFi, 但不等待连接成功
|
||||
* @param initepd 是否初始化墨水屏. 初始化后的首次刷屏必为慢刷. 如果是不断电复位, 可以不初始化墨水屏直接刷屏
|
||||
* @param initSD 是否初始化文件系统. 选是-初始化SD失败则初始化LittleFs; 选否-不初始化SD也不初始化littlefs.
|
||||
* @return SD卡是否就绪
|
||||
*/
|
||||
uint8_t init(uint8_t WiFiSet = 0);
|
||||
uint8_t init(uint8_t WiFiSet = 0, bool initepd = 1, bool initSD = 1);
|
||||
/// @brief 设置显示亮度
|
||||
void setBright(int d);
|
||||
/// @brief 返回显示亮度
|
||||
int getBright() const { return currentBright; }
|
||||
/// @brief 刷新显示到屏幕上
|
||||
void display(bool part = true);
|
||||
void display(uint8_t part = READGUY_FAST);
|
||||
/// @brief 刷新显示到屏幕上
|
||||
void displayBuffer(const uint8_t *buf, uint8_t part);
|
||||
/** @brief 刷新显示到屏幕上, 可以自定义读取指定位置像素的函数
|
||||
* @param f 自定义的函数. 此函数将在读取像素并输出到墨水屏时被调用.
|
||||
* 每次调用需要返回 "参数对应位置" 的8个像素的颜色信息(凑成一字节). 其中左侧应在高位,右侧应在低位.
|
||||
@@ -170,9 +205,13 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
* @endcode
|
||||
* 该函数会将参数从0开始,每次逐渐增加1的顺序来被调用. 即先调用f(0),再f(1),f(2),f(3)... 以此类推.
|
||||
*/
|
||||
void display(std::function<uint8_t(int)> f, bool part = true);
|
||||
/// @brief 显示图片, 使用抖动算法. 可以用省内存的方法显示
|
||||
void drawImage(LGFX_Sprite &spr,uint16_t x,uint16_t y);
|
||||
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);
|
||||
}
|
||||
/// @brief 显示图片, 将图片(任意颜色格式)显示到一个黑白色的sprite(必须是黑白二值型)上 (未经测试)
|
||||
void drawImage(LGFX_Sprite &base,LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw=0,uint16_t zoomh=0);
|
||||
/// @brief 设置显示对比度(灰度)
|
||||
void setDepth(uint8_t d);
|
||||
/** @brief 返回目标屏幕是否支持16级灰度 返回非0代表支持.
|
||||
@@ -184,12 +223,12 @@ 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);
|
||||
void draw16grey(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw=0,uint16_t zoomh=0);
|
||||
/** @brief 按照自定义分步显示灰度图片,如果支持,否则就不显示灰度图片了. 可以用省内存的方法显示
|
||||
* @param step 步骤代号. 从1开始到15,依次调用此函数来自定义的灰度显示显存内容. 没有0和16.
|
||||
* @note 必须按照 "慢刷全屏->绘图->设置参数1->绘图->设置参数2... 调用15次 来完成一次自定义灰度刷屏
|
||||
* 连续调用多次此函数之间, 可以修改显存内的像素颜色, 但只能从白色改为黑色.
|
||||
* @attention 需要先调用 supportGreyscaling() 来确定是否支持灰度分步刷新.为负数时需要从深到浅刷新
|
||||
* @attention 需要先调用 supportGreyscaling() 来确定是否支持灰度分步刷新.为负数时需要从深到浅刷新. 参见示例.
|
||||
*/
|
||||
void draw16greyStep(int step);
|
||||
/** @brief 分步刷新显示灰度, 详见 display(f,part) 和 draw16grey(spr,x,y) 的注释.
|
||||
@@ -199,13 +238,13 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
void invertDisplay();
|
||||
/// @brief 进入EPD的低功耗模式
|
||||
void sleepEPD(void);
|
||||
#ifdef READGUY_ESP_ENABLE_WIFI
|
||||
/// @brief ap配网设置页面
|
||||
typedef struct {
|
||||
String linkname;
|
||||
String event; //链接名称 事件URI
|
||||
std::function<void(ReadguyWebServer*)> func; //触发时执行的函数
|
||||
} serveFunc;
|
||||
#ifdef READGUY_ESP_ENABLE_WIFI
|
||||
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
|
||||
void ap_setup();
|
||||
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
|
||||
@@ -213,6 +252,12 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
bool server_loop();
|
||||
void server_end();
|
||||
#else
|
||||
/// @brief ap配网设置页面
|
||||
typedef struct {
|
||||
String linkname;
|
||||
String event; //链接名称 事件URI
|
||||
std::function<void(void*)> func; //触发时执行的函数
|
||||
} serveFunc;
|
||||
/// @brief 初始化WiFi AP模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
|
||||
void ap_setup(){}
|
||||
/// @brief 初始化服务器模式, 用于将来的连接WiFi 处于已连接状态下会断开原本的连接
|
||||
@@ -225,7 +270,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
/** @brief 初始化屏幕, 设置驱动代号, 引脚排列顺序. 过程会检验引脚可用性.
|
||||
* @param g_width, g_height 显示区域的宽度和高度. 为0表示直接使用屏幕的宽度和高度
|
||||
* @note 这两个参数转专为指定分辨率的程序画面设计, 其他分辨率的画面会自动拉伸. [1.2新增] */
|
||||
void setEpdDriver(int g_width = 0,int g_height = 0);
|
||||
void setEpdDriver(bool initepd = 1, bool initGFX = 1);
|
||||
/** @brief 初始化SD卡, 设置驱动代号, 引脚排列顺序. 过程会检验引脚可用性.
|
||||
* @return SD卡初始化成功与否 */
|
||||
bool setSDcardDriver();
|
||||
@@ -236,6 +281,8 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
bool SDinside(bool check=true) { return check?setSDcardDriver():READGUY_sd_ok; };
|
||||
/// @brief 检查按钮. 当配置未完成时,按钮不可用, 返回0.
|
||||
uint8_t getBtn() { return (READGUY_cali==127)?getBtn_impl():0; }
|
||||
/// @brief [此函数已弃用 非常不建议使用] 根据按钮ID来检查按钮. 注意这里如果按下返回0, 没按下或者按钮无效返回1
|
||||
//uint8_t getBtn(int btnID){return btnID<getButtonsCount()?(!(btn_rd[btnID].isPressedRaw())):1;}
|
||||
/** @brief 返回可用的文件系统. 当SD卡可用时, 返回SD卡. 否则根据情况返回最近的可用文件系统
|
||||
* @param initSD 2:总是重新初始化SD卡; 1:若SD卡不可用则初始化; 0:SD卡不可用则返回LittleFS. */
|
||||
fs::FS &guyFS(uint8_t initSD = 0);
|
||||
@@ -247,21 +294,21 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
static const char projname[8];
|
||||
static const char tagname[7];
|
||||
//uint8_t config_wifi=0; //是否强行在初始化期间设置WiFi.
|
||||
#ifdef DYNAMIC_PIN_SETTINGS//数据是否已经校准
|
||||
int8_t config_data[22];
|
||||
char randomch[4]; //校验用字符串
|
||||
void nvs_init(); //初始化持久存储器.
|
||||
void nvs_deinit();//保存持久存储器的内容
|
||||
bool nvs_read(); //从持久存储器读取, 返回是否读取成功
|
||||
void nvs_write(); //写入到持久存储器
|
||||
#ifdef DYNAMIC_PIN_SETTINGS//数据是否已经校准
|
||||
int8_t config_data[22];
|
||||
char randomch[4]; //校验用字符串
|
||||
#else
|
||||
static const int8_t config_data[22];
|
||||
int8_t READGUY_sd_ok = 0;
|
||||
int8_t READGUY_cali = 0;
|
||||
int8_t READGUY_buttons = 0; //按钮个数, 0-3都有可能
|
||||
#endif
|
||||
int epd_OK=0; //墨水屏可用
|
||||
int currentBright = -3; //初始亮度
|
||||
int16_t guy_width=0,guy_height=0;
|
||||
|
||||
//LGFX_Sprite gfx; // 图形引擎类指针, 可以用这个指针去操作屏幕缓冲区
|
||||
readguyEpdBase *guy_dev = nullptr;
|
||||
@@ -274,10 +321,8 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
//对于esp8266, 需要注册到ticker
|
||||
Ticker btnTask;
|
||||
#else
|
||||
#ifdef DYNAMIC_PIN_SETTINGS
|
||||
//NVS数据操作函数, 无NVS的使用EEProm的最后几个字节块
|
||||
Preferences nvsData;
|
||||
#endif
|
||||
static SPIClass *sd_spi;
|
||||
static SPIClass *epd_spi;
|
||||
static TaskHandle_t btn_handle;
|
||||
@@ -325,51 +370,67 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
|
||||
static uint8_t rd_btn_f(uint8_t btn);
|
||||
uint8_t getBtn_impl(); //按钮不可用, 返回0.
|
||||
static void in_press(){ //SPI开始传输屏幕数据
|
||||
#ifndef ESP8266
|
||||
#ifdef ESP8266
|
||||
if(!spibz) SPI.beginTransaction(SPISettings(ESP8266_SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
|
||||
#else
|
||||
if(!spibz) epd_spi->beginTransaction(SPISettings(ESP32_DISP_FREQUENCY, MSBFIRST, SPI_MODE0));
|
||||
#endif
|
||||
spibz ++;
|
||||
}
|
||||
static void in_release(){//SPI结束传输屏幕数据
|
||||
spibz --;
|
||||
#ifndef ESP8266
|
||||
#ifdef ESP8266
|
||||
if(!spibz) SPI.endTransaction();
|
||||
#else
|
||||
if(!spibz) epd_spi->endTransaction();
|
||||
#endif
|
||||
}
|
||||
public: //增加了一些返回系统状态变量的函数, 它们是静态的, 而且不会对程序造成任何影响.
|
||||
constexpr int getShareSpi() const { return config_data[1]; }
|
||||
constexpr int getEpdType () const { return config_data[2]; } // 对应的epd驱动程序代号, -1为未指定
|
||||
constexpr int getShareSpi() const { return READGUY_shareSpi; }
|
||||
constexpr int getEpdType () const { return READGUY_epd_type; } // 对应的epd驱动程序代号, -1为未指定
|
||||
//显示驱动部分, 显示默认使用vspi (vspi也是默认SPI库的通道)
|
||||
constexpr int getEpdMosi () const { return config_data[3]; } // 目标显示器的 MOSI 引脚
|
||||
constexpr int getEpdSclk () const { return config_data[4]; } // 目标显示器的 SCLK 引脚
|
||||
constexpr int getEpdCs () const { return config_data[5]; } // 目标显示器的 CS 引脚
|
||||
constexpr int getEpdDc () const { return config_data[6]; } // 目标显示器的 DC 引脚
|
||||
constexpr int getEpdRst () const { return config_data[7]; } // 目标显示器的 RST 引脚
|
||||
constexpr int getEpdBusy () const { return config_data[8]; } // 目标显示器的 BUSY 引脚
|
||||
constexpr int getEpdMosi () const { return READGUY_epd_mosi; } // 目标显示器的 MOSI 引脚
|
||||
constexpr int getEpdSclk () const { return READGUY_epd_sclk; } // 目标显示器的 SCLK 引脚
|
||||
constexpr int getEpdCs () const { return READGUY_epd_cs; } // 目标显示器的 CS 引脚
|
||||
constexpr int getEpdDc () const { return READGUY_epd_dc; } // 目标显示器的 DC 引脚
|
||||
constexpr int getEpdRst () const { return READGUY_epd_rst; } // 目标显示器的 RST 引脚
|
||||
constexpr int getEpdBusy () const { return READGUY_epd_busy; } // 目标显示器的 BUSY 引脚
|
||||
//sd卡驱动部分, 默认使用hspi (sd卡建议用hspi)
|
||||
constexpr int getSdMiso () const { return config_data[9]; } // 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdMosi () const { return config_data[10]; }// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdSclk () const { return config_data[11]; }// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdCs () const { return config_data[12]; }// 目标sd卡的 CS 引脚.
|
||||
constexpr int getI2cSda () const { return config_data[13]; }// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
|
||||
constexpr int getI2cScl () const { return config_data[14]; }// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
|
||||
constexpr int getSdMiso () const { return READGUY_sd_miso; } // 目标sd卡的 MISO 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdMosi () const { return READGUY_sd_mosi; }// 目标sd卡的 MOSI 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdSclk () const { return READGUY_sd_sclk; }// 目标sd卡的 SCLK 引脚, sd_share_spi == 1 时无效
|
||||
constexpr int getSdCs () const { return READGUY_sd_cs; }// 目标sd卡的CS引脚. 对ESP32S3, 返回127代表使用SDMMC
|
||||
constexpr int getI2cSda () const { return READGUY_i2c_sda; }// 目标i2c总线的SDA引脚, 当且仅当启用i2c总线时才生效
|
||||
constexpr int getI2cScl () const { return READGUY_i2c_scl; }// 目标i2c总线的SCL引脚, 当且仅当启用i2c总线时才生效
|
||||
//按键驱动部分, 为负代表高触发, 否则低触发,
|
||||
//注意, 这里的io编号是加1的, 即 1或-1 代表 gpio0 的低触发/高触发
|
||||
constexpr int getBtn1Pin () const { return config_data[15]; }
|
||||
constexpr int getBtn2Pin () const { return config_data[16]; }
|
||||
constexpr int getBtn3Pin () const { return config_data[17]; }
|
||||
constexpr int getBlPin () const { return config_data[18]; } //前置光接口引脚IO
|
||||
constexpr int getRtcType () const { return config_data[19]; } //使用的RTC型号(待定, 还没用上)
|
||||
constexpr int getButtonsCount() const { return config_data[21]; } //按钮个数, 0-3都有可能
|
||||
constexpr int memWidth () const { return guy_width ; } //返回显存宽度(不是画幅宽度),不会随着画布旋转改变
|
||||
constexpr int memHeight () const { return guy_height ; } //返回显存高度(不是画幅高度),不会随着画布旋转改变
|
||||
constexpr int getBtn1Pin () const { return READGUY_btn1; }
|
||||
constexpr int getBtn2Pin () const { return READGUY_btn2; }
|
||||
constexpr int getBtn3Pin () const { return READGUY_btn3; }
|
||||
constexpr int getBlPin () const { return READGUY_bl_pin; } //前置光接口引脚IO
|
||||
constexpr int getRtcType () const { return READGUY_rtc_type; } //使用的RTC型号(待定, 还没用上)
|
||||
constexpr int getButtonsCount() const { return READGUY_buttons; } //按钮个数, 0-3都有可能
|
||||
//constexpr int memWidth () const { return guy_width ; } //返回显存宽度(不是画幅宽度),不会随着画布旋转改变
|
||||
//constexpr int memHeight () const { return guy_height ; } //返回显存高度(不是画幅高度),不会随着画布旋转改变
|
||||
int drvWidth () const { return READGUY_cali==127?guy_dev->drv_width():0; } //返回显示屏硬件宽度(不是画幅宽度)
|
||||
int drvHeight() const { return READGUY_cali==127?guy_dev->drv_height():0; } //返回显示屏硬件高度(不是画幅高度)
|
||||
//int width () const { return (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);
|
||||
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);
|
||||
};
|
||||
#endif /* END OF FILE. ReadGuy project.
|
||||
Copyright (C) 2023 FriendshipEnder. */
|
||||
Reference in New Issue
Block a user