v1.0.2; change file structure

This commit is contained in:
fsender
2023-09-24 16:59:01 +08:00
parent 5f91e9a9a5
commit 765c433e53
59 changed files with 9077 additions and 632 deletions

View File

@@ -0,0 +1,171 @@
/******************** 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_154a_290a.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸和2.9英寸墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_154a_290a.h"
#if (defined(READGUY_DEV_154A) || defined(READGUY_DEV_290A))
namespace guydev_154A_290A{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
int drvBase::Init(const unsigned char* lut) {
// * EPD hardware init start /
this->lut = lut;
if(sleeping) {
Reset();
sleeping=0;
}
BeginTransfer();
guy_epdCmd(0x01);
guy_epdParam((epdHeight - 1) & 0xFF);
guy_epdParam(((epdHeight - 1) >> 8) & 0xFF);
guy_epdParam(0x00); // GD = 0; SM = 0; TB = 0;
guy_epdCmd(0x0c);
guy_epdParam(0xD7);
guy_epdParam(0xD6);
guy_epdParam(0x9D);
guy_epdCmd(0x2c);
guy_epdParam(0x9B); // VCOM 7C
guy_epdCmd(0x3a);
guy_epdParam(0x1A); // 4 dummy lines per gate
guy_epdCmd(0x3b);
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)));
}
else
guy_epdParam(pgm_read_byte(this->lut+i));
}
}
void drvBase::SetFrameWriter(std::function<uint8_t(int)> f,uint8_t _extra) {
guy_epdCmd(0x44);
guy_epdParam((0 >> 3) & 0xFF);
guy_epdParam(((epdWidth-1) >> 3) & 0xFF);
guy_epdCmd(0x45);
guy_epdParam(0 & 0xFF);
guy_epdParam((0 >> 8) & 0xFF);
guy_epdParam((epdHeight-1) & 0xFF);
guy_epdParam(((epdHeight-1) >> 8) & 0xFF);
guy_epdCmd(0x4e);
guy_epdParam((0 >> 3) & 0xFF);
guy_epdCmd(0x4f);
guy_epdParam(0 & 0xFF);
guy_epdParam((0 >> 8) & 0xFF);
guy_epdCmd(_extra);
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
guy_epdParam(f(i));
}
const PROGMEM unsigned char lut_slow[] =
{
/* 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22,
0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88,
0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51,
0x35, 0x51, 0x51, 0x19, 0x01, 0x00*/
0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const PROGMEM unsigned char lut_fast[] =
{
0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, //0x13,0x14,0x44,0x12
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const PROGMEM unsigned char lut_grey_update[]={ //从上到下是依次加深
0x10, 0x00, 0x10, 0x00, 0x10, 0x01, 0x10, 0x01,
0x10, 0x02, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04,
0x10, 0x14, 0x10, 0x24, 0x10, 0x34, 0x11, 0x44,
0x12, 0x44, 0x13, 0x44
};
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){ //单色刷新等功能
if(sleeping) Init(lut_slow);
BeginTransfer();
SetMemory(); // bit set = white, bit reset = black
guy_epdBusy(100);
guy_epdCmd(0x24); /* will send the color data */
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
guy_epdParam(f(i));
guy_epdCmd(0x22);
guy_epdParam(0xC4);
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++)
guy_epdParam(f(i));
EndTransfer();
}
void drvBase::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0) { //未定义RST_PIN时无法唤醒
BeginTransfer();
guy_epdCmd(0x10);
EndTransfer();
guy_epdBusy(150);
DigitalWrite(RST_PIN, LOW);
sleeping=1;
}
}
void drvBase::drv_setDepth(uint8_t i){
iLut = i?(i>15?15:i):15;
Init(lut_fast);
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,84 @@
/******************** 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_154a_290a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸和2.9英寸墨水屏 驱动库函数头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD154A290A_H_FILE)) && \
(defined(READGUY_DEV_154A) || defined(READGUY_DEV_290A)))
#define _GUY_EPD154A290A_H_FILE
namespace guydev_154A_290A{
extern const unsigned char lut_slow[];
extern const unsigned char lut_fast[];
extern const unsigned char lut_grey_update[];
class drvBase : public readguyEpdBase {
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
protected:
int epdWidth;
int epdHeight;
int idleSlowRf;
int idleFastRf;
private:
int Init(const unsigned char* lut);
void SetFrameWriter(std::function<uint8_t(int)> f,uint8_t _extra);
const unsigned char* lut;
uint8_t iLut = 15;
uint8_t sleeping=1;
void SetLut(const unsigned char* lut);
};
#ifdef READGUY_DEV_154A
class dev154A : public drvBase {
public:
dev154A(){ epdWidth=200; epdHeight=200; idleSlowRf=1300; idleFastRf=350; }
int drv_ID() const { return READGUY_DEV_154A; }
};
#endif
#ifdef READGUY_DEV_290A
class dev290A : public drvBase {
public:
dev290A(){ epdWidth=128; epdHeight=296; idleSlowRf=1800; idleFastRf=550; }
int drv_ID() const { return READGUY_DEV_290A; }
};
#endif
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,239 @@
/******************** 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_154b_270b_290b.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸B型 2.7英寸B型和2.9英寸B型墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_154b_270b_290b.h"
#if (defined(READGUY_DEV_154B) || defined(READGUY_DEV_270B) || defined(READGUY_DEV_290B))
namespace guydev_154B_270B_290B{
/*const unsigned char drvSSD168x::_WF_PARTIAL_2IN9[48] ={
0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0xff,0x00,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
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,0xB0,0x32,0x28
};*/
const unsigned char drvSSD168x::WS_20_30[48] =
{ /*
0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0,
0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0,
0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x14, 0x8, 0x0, 0x0, 0x0, 0x0, 0x1,
0xA, 0xA, 0x0, 0xA, 0xA, 0x0, 0x1,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x14, 0x8, 0x0, 0x1, 0x0, 0x0, 0x1,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0,
0x22, 0x17, 0x41, 0x0, 0x32, 0x36
*/
0x80, 0x48, 0x40, /*0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,*/
0x40, 0x48, 0x80, /*0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,*/
0x80, 0x48, 0x40, /*0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,*/
0x40, 0x48, 0x80, /*0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,*/
0x0, 0x0, 0x0, /*0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,*/
0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xf, 0x1, 0x0, 0xf, 0x1, 0x0, 0x1,
0xA, 0x0, 0x0, 0x0, /*0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
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};
//以下代码均为我 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::SetFrameWriter(std::function<uint8_t(int)> f) {
if(_part && epd_PowerOn){
//Reset();
SetLut();
guy_epdCmd(0x37);
for(int i=0;i<10;i++) guy_epdParam(i==5?0x40:0x00);
guy_epdCmd(0x3C); //BorderWavefrom
guy_epdParam(0x80);
guy_epdCmd(0x22);
guy_epdParam(0xC0);
guy_epdCmd(0x20);
guy_epdBusy(140);
}
else epd_init();
SetMemory();
guy_epdCmd(0x24);
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
guy_epdParam(f(i));
if(!_part){
guy_epdCmd(0x26);
for (int i = 0; i < epdHeight*epdWidth / 8; i++)
guy_epdParam(f(i));
}
}
void drvSSD168x::DisplayFrame(void) {
guy_epdCmd(0x22);
guy_epdParam(_part?0x0f:0xc7);
guy_epdCmd(0x20);
}
void drvSSD168x::SetLut() {
unsigned char i;
guy_epdCmd(0x32);
if(_part){
for(i=0;i<5;i++){
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);
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);
}
else{
//for(i=0; i<153; i++) guy_epdParam(lut[i]==0xff?iLut:lut[i]);
for(i=0;i<5;i++){
guy_epdParam(pgm_read_byte(WS_20_30+i*3));
guy_epdParam(pgm_read_byte(WS_20_30+i*3+1));
guy_epdParam(pgm_read_byte(WS_20_30+i*3+2));
for(int j=0;j<9;j++) guy_epdParam(0);
}
for(i=0;i<18;i++) guy_epdParam(pgm_read_byte(WS_20_30+i+15));
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);
}
void drvSSD168x::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(!part) { iLut=15; greyScaling=0; }
_part=part;
}
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
BeginTransfer();
SetFrameWriter(f);
DisplayFrame();
EndTransfer();
guy_epdBusy(_part?600:2300);
}
void drvSSD168x::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //无法唤醒
BeginTransfer();
guy_epdCmd(0x10);
guy_epdParam(0x01);
EndTransfer();
epd_PowerOn=0;
}
}
void drvSSD168x::drv_setDepth(uint8_t i){ //设置显示颜色深度, 不支持的话什么都不做
if(i>0 && i<16) {
iLut = i;
drv_fullpart(1);
}
else iLut=15;
}
void drvSSD168x::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality) return readguyEpdBase::drv_draw16grey_step(f,step);
if(step==1){
drv_fullpart(1);
greyScaling=1;
}
iLut=step-1;
drv_dispWriter(f);
if(step==15){
iLut=15;
drv_dispWriter(f);
greyScaling=0;
}
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,93 @@
/******************** 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_154b_270b_290b.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 1.54英寸B型 2.7英寸B型和2.9英寸B型墨水屏 驱动库函数头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD154B270B290B_H_FILE)) && (defined(READGUY_DEV_154B)\
|| defined(READGUY_DEV_270B) || defined(READGUY_DEV_290B)))
#define _GUY_EPD154B270B290B_H_FILE
namespace guydev_154B_270B_290B{
// Display resolution
class drvSSD168x : public readguyEpdBase {
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度
int drv_supportGreyscaling() const { return _quality?16:-16; }
void drv_setDepth(uint8_t i); //设置显示颜色深度, 不支持的话什么都不做
void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
protected:
// Display resolution
int epdWidth;
int epdHeight;
private:
uint8_t _part;
uint8_t epd_PowerOn = 0;
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 VSH_table[32];
void epd_init();
void SetFrameWriter(std::function<uint8_t(int)> f);
void DisplayFrame(void);
void SetLut();
//void SetLut_by_host(const unsigned char *lut);
};
#ifdef READGUY_DEV_154B
class dev154B : public drvSSD168x {
public:
dev154B(){ epdWidth=200; epdHeight=200; }
int drv_ID() const { return READGUY_DEV_154B; }
};
#endif
#ifdef READGUY_DEV_270B
class dev270B : public drvSSD168x {
public:
dev270B(){ epdWidth=176; epdHeight=264; }
int drv_ID() const { return READGUY_DEV_270B; }
};
#endif
#ifdef READGUY_DEV_290B
class dev290B : public drvSSD168x {
public:
dev290B(){ epdWidth=128; epdHeight=296; }
int drv_ID() const { return READGUY_DEV_290B; }
};
#endif
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,167 @@
/******************** 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_213a.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 2.13英寸墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_213a.h"
#ifdef READGUY_DEV_213A
namespace guydev_213A{
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
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 };
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,
0x00, 0x0e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void drv::epd_Init(void){
if(!epd_PowerOn) Reset(); //存疑的选项
//BeginTransfer();
guy_epdCmd(0x01); // Panel configuration, Gate selection
guy_epdParam((GUY_D_HEIGHT - 1) % 256);
guy_epdParam((GUY_D_HEIGHT - 1) / 256);
guy_epdParam(0x00);
guy_epdCmd(0x03); // Set Gate driving voltage
guy_epdParam(0x15);
guy_epdParam(0x0e);
guy_epdCmd(0x04); // Set Source output voltage.
guy_epdParam(0x1d);
guy_epdCmd(0x0c); // softstart
guy_epdParam(0xd7);
guy_epdParam(0xd6);
guy_epdParam(0x9d);
guy_epdCmd(0x2c); // VCOM setting
guy_epdParam(0x55); // * different
guy_epdCmd(0x3a); // DummyLine
guy_epdParam(0x1a); // 4 dummy line per gate
guy_epdCmd(0x3b); // Gatetime
guy_epdParam(0x08); // 2us per line
//设置内部显示内存
guy_epdCmd(0x11); // set ram entry mode
guy_epdParam(0x03); // x increase, y increase : normal mode
guy_epdCmd(0x44); //此处的指令参数已经是确定好的了, 不适合用那个放到epdBase里的setMemory
guy_epdParam(0);
guy_epdParam(15);
guy_epdCmd(0x45);
guy_epdParam(0);
guy_epdParam(255);
guy_epdParam(249);
guy_epdParam(255);
guy_epdCmd(0x4e);
guy_epdParam(0);
guy_epdCmd(0x4f);
guy_epdParam(0);
guy_epdParam(255);
//guy_epdParam((GUY_D_HEIGHT-1)&255);
//guy_epdParam((GUY_D_HEIGHT-1)>>8);
guy_epdCmd(0x32); //发送lut
DigitalWrite(DC_PIN, HIGH); //切换到data
if(/* epd_PowerOn && */!epdFull) {
for(uint32_t i=0;i<sizeof(_ed_lut_part);i++){
if(i==16) SpiTransfer(iLut);
else SpiTransfer(pgm_read_byte(_ed_lut_part+i));
}
}
else {
for(uint32_t i=0;i<sizeof(_ed_lut_full);i++){
SpiTransfer(pgm_read_byte(_ed_lut_full+i));
}
}
DigitalWrite(DC_PIN, LOW); //切换到data
//if(!epd_PowerOn){
epd_PowerOn = 1;
guy_epdCmd(0x22);
guy_epdParam(0xc0);
guy_epdCmd(0x20);
guy_epdBusy(100);
//}
}
void drv::drv_init(){ //初始化屏幕
epdFull = 1;
BeginTransfer();
epd_Init();
EndTransfer();
drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
//if(part==epdFull) return;
if(!part) iLut=15; //恢复默认的灰度模式
epdFull = !part;
//epd_Init();
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
BeginTransfer();
if(epdFull) { //当刷新模式从快刷切换为慢刷时, 需要发送一次init
epdFull=0;
epd_Init(); //初始状态的慢刷也是要发送一次init
epdFull=1;
guy_epdCmd(0x26);
//for (int j = GUY_D_HEIGHT-1; j >= 0; j--)
// for (int k = 0; k < GUY_D_WIDTH/8; k++)
// guy_epdParam(f(j*(GUY_D_WIDTH/8)+k)); //按照给定的RAM写入数据
for (int i = 0; i < GUY_D_WIDTH/8*GUY_D_HEIGHT; i++)
guy_epdParam(f(i));
}
guy_epdCmd(0x24);
//for (int j = GUY_D_HEIGHT-1; j >= 0; j--)
// for (int k = 0; k < GUY_D_WIDTH/8; k++)
// guy_epdParam(f(j*(GUY_D_WIDTH/8)+k)); //按照给定的RAM写入数据
for (int i = 0; i < GUY_D_WIDTH/8*GUY_D_HEIGHT; i++)
guy_epdParam(f(i));
epd_Init();
guy_epdCmd(0x22);
guy_epdParam(epdFull?0xc4:0x04);
guy_epdCmd(0x20);
EndTransfer();
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; //强制设置为慢刷新模式
}
guy_epdCmd(0x10); //enter deep sleep
guy_epdParam(0x01);
EndTransfer();
DelayMs(200);
DigitalWrite(RST_PIN, LOW);
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View 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_213a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 2.13英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD213A_H_FILE) && (defined(READGUY_DEV_213A)))
#define _GUY_EPD213A_H_FILE
namespace guydev_213A{
// Display resolution
/* the resolution is 122x250 in fact */
/* however, the logical resolution is 128x250 */
constexpr int GUY_D_WIDTH =128;
constexpr int EPD_REAL_WIDTH =122; //适用于很多场景的实际宽度
constexpr int GUY_D_HEIGHT =250;
// EPD2IN13 commands
extern const unsigned char lut_slow[];
extern const unsigned char lut_fast[];
class drv : public readguyEpdBase {
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return EPD_REAL_WIDTH; }; //返回显示区域宽度
//int drv_panelwidth() const { return GUY_D_WIDTH; }; //返回缓存的数据宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i){ epdFull=0; iLut = i?(i>15?15:i):15; } //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
void epd_Init(void);
uint8_t epdFull; //是partical模式/快速刷新模式 0快刷, 1慢刷
uint8_t epd_PowerOn = 0; //是否上电
uint8_t iLut = 15; //颜色深度(灰度模式用)
// uint8_t dc_d = 0; //dc引脚状态 0 command, 1 data
static const PROGMEM uint8_t _ed_lut_full[];
static const PROGMEM uint8_t _ed_lut_part[];
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,244 @@
/******************** 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_213b_266a.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 2.13英寸B型墨水屏和 2.66英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_213b_266a.h"
// #define MEPD_DEBUG_WAVE
#ifdef READGUY_DEV_266A
namespace guydev_213B_266A{
static const PROGMEM unsigned char lutSlow_vcom0[] ={
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
0x00, 0x10, 0x00, 0x00, 0x00, 0x01,
0x00, 0x1a, 0x1a, 0x00, 0x00, 0x01
};
static const PROGMEM unsigned char lutSlow_w_w[] ={
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x10, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x1a, 0x1a, 0x00, 0x00, 0x01
};
static const PROGMEM unsigned char lutSlow_b_w[] ={
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x10, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x1a, 0x1a, 0x00, 0x00, 0x01
};
static const PROGMEM unsigned char lutSlow_w_b[] ={
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x10, 0x00, 0x00, 0x00, 0x01,
0x50, 0x1a, 0x1a, 0x00, 0x00, 0x01
};
static const PROGMEM unsigned char lutSlow_b_b[] ={
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x10, 0x00, 0x00, 0x00, 0x01,
0x50, 0x1a, 0x1a, 0x00, 0x00, 0x01
};
// partial update waveform
//参考灰度数据与屏幕相关. 测试用屏来自 vusion 黑白双色价签.
////以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
static const PROGMEM unsigned char lutFast_[]={
0x00,0x18,0x5a,0xa5,0x24
};
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();
guy_epdCmd(0x01);
guy_epdParam(0x03);
guy_epdParam(0x00);
guy_epdParam(0x2b);
guy_epdParam(0x2b);
guy_epdParam(0x03);
guy_epdCmd(0x06);
guy_epdParam(0x17);
guy_epdParam(0x17);
guy_epdParam(0x17);
guy_epdCmd(0x00);
guy_epdParam(0xbf);
guy_epdParam(0x0d);
guy_epdCmd(0x30);
guy_epdParam(0x29); //0x3a:100Hz, 0x29:150Hz
guy_epdCmd(0x61);
guy_epdParam(0x98);
guy_epdParam(0x01);
guy_epdParam(0x28);
guy_epdCmd(0x82);
guy_epdParam(0x17);
guy_epdCmd(0x50);
guy_epdParam(0x17);
}
void drv_base::send_zoneInfo(){
guy_epdCmd(0x90);
guy_epdParam(0x00);
guy_epdParam(0x97);
guy_epdParam(0x00);
guy_epdParam(0x00);
guy_epdParam(0x01);
guy_epdParam(0x27);
guy_epdParam(0x00);
}
void drv_base::SendLuts(bool part_lut){
if(!Power_is_on) part_lut=false; //形参嘛
for(uint8_t i=0;i<5;i++){
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)));
else if(j==5) guy_epdParam(1);
else guy_epdParam(0x0);
}
else {
guy_epdParam(j<24?pgm_read_byte(guy_lutArray[i]+j):0x00);
}
}
}
if(!Power_is_on){
guy_epdCmd(0x04);
guy_epdBusy(-60);
Power_is_on = 1;
}
}
void drv_base::drv_init(){
part_mode=0;
drv_color(0xff);
}
void drv_base::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(!part) greyLut=15; //恢复默认的灰度模式
part_mode = part;
}
void drv_base::drv_setDepth(uint8_t i){
part_mode=1;
greyLut = i?(i>15?15:i):15;
BeginTransfer();
SendLuts(1);
EndTransfer();
}
void drv_base::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
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);
for (int i = 0; i < epdHeight*epdWidth/8; i++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
guy_epdCmd(0x92);
if(part_mode){
guy_epdCmd(0x30);
guy_epdParam(0x3a); //0x3a:100Hz, 0x29:150Hz
//[EPDrg_BW<>] refresh fx
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++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
guy_epdCmd(0x92);
EndTransfer();
//[EPDrg_BW<>] powerOff fx
//guy_epdCmd(0x02);
//[EPDrg_EPD] wait_until_idle fx: 20
//guy_epdBusy(-20);
}
}
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;
}
}
void drv_base::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality) return readguyEpdBase::drv_draw16grey_step(f,step);
if(step==1){
greyHQ=3;
drv_setDepth(3);
drv_fullpart(1); //开始局刷
}
if(step==3) drv_setDepth(2);
if(step==5) drv_setDepth(1);
drv_dispWriter(f);
if(step==15){
greyHQ=4;
drv_setDepth(15);
}
} //据说可以设置灰度渲染方式. 好像是调用setGreyQuality函数就行来着
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,79 @@
/******************** 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_213b_266a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 2.13英寸B型墨水屏和 2.66英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD213B_266A_H_FILE) && \
(defined(READGUY_DEV_266A) || defined(READGUY_DEV_213B)))
#define _GUY_EPD213B_266A_H_FILE
namespace guydev_213B_266A{
class drv_base : public readguyEpdBase {
public:
drv_base();
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return epdWidth; }; //返回显示区域宽度
int drv_height() const{ return epdHeight; }; //返回显示区域高度
void drv_setDepth(uint8_t i); //设置显示颜色深度
int drv_supportGreyscaling() const { return _quality?16:-16; }
void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
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 greyLut=15;
uint8_t greyHQ=4; // greyHQ==3 时 为高品质刷新灰度 否则为常规方式刷新灰度
const uint8_t *guy_lutArray[6];
};
#ifdef READGUY_DEV_213B
class dev213B : public drv_base {
public:
dev213B(){ epdWidth=104; epdHeight=212; }
int drv_ID() const { return READGUY_DEV_213B; }
};
#endif
#ifdef READGUY_DEV_266A
class dev266A : public drv_base {
public:
dev266A(){ epdWidth=152; epdHeight=296; }
int drv_ID() const { return READGUY_DEV_266A; }
};
#endif
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,171 @@
/******************** 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_370a.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 3.7英寸墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_370a.h"
#ifdef READGUY_DEV_370A
namespace guydev_370A{
static const PROGMEM unsigned char lut_1Gray_GC[] ={
0x2A,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//1
0x05,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//2
0x2A,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//3
0x05,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//4
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//5
0x00,0x02,0x03,0x0A,0x00,0x02,0x06,0x0A,0x05,0x00
};
static const PROGMEM unsigned char lut_1Gray_A2[] ={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //1
0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //2
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //3
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //4
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //5
0x00,0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00
};
int drv::Init(void) {
if(sleeping) {
Reset();
sleeping=false;
part_mode=false;
}
BeginTransfer();
guy_epdCmd(0x12); DelayMs(300); //Power on display
guy_epdCmd(0x46); guy_epdParam(0xF7); guy_epdBusy(20);
guy_epdCmd(0x47); guy_epdParam(0xF7); guy_epdBusy(20);
guy_epdCmd(0x01); guy_epdParam(0xDF); guy_epdParam(0x01); guy_epdParam(0x00); // setting gaet number
guy_epdCmd(0x03); guy_epdParam(0x00); // set gate voltage
guy_epdCmd(0x04); guy_epdParam(0x41); guy_epdParam(0xA8); guy_epdParam(0x32); // set source voltage
guy_epdCmd(0x11); guy_epdParam(0x03); // set data entry sequence
guy_epdCmd(0x3C); guy_epdParam(0x01); // set border
guy_epdCmd(0x0C); // set booster strength
guy_epdParam(0xAE); guy_epdParam(0xC7); guy_epdParam(0xC3); guy_epdParam(0xC0); guy_epdParam(0xC0);
guy_epdCmd(0x18); guy_epdParam(0x80); // set internal sensor on
guy_epdCmd(0x2C); guy_epdParam(0x44); // set vcom value
guy_epdCmd(0x37); // set display option, these setting turn on previous function
guy_epdParam(0x00);
for(int i=0;i<4;i++) guy_epdParam(0xff);
guy_epdParam(0x4f);
for(int i=0;i<4;i++) guy_epdParam(0xff);
guy_epdCmd(0x44); // setting X direction start/end position of RAM
guy_epdParam(0x00); guy_epdParam(0x00); guy_epdParam(0x17); guy_epdParam(0x01);
guy_epdCmd(0x45); // setting Y direction start/end position of RAM
guy_epdParam(0x00); guy_epdParam(0x00); guy_epdParam(0xDF); guy_epdParam(0x01);
guy_epdCmd(0x22); guy_epdParam(0xCF); // Display Update Control 2
EndTransfer();
return 0;
}
//以下代码均为我 FriendshipEnder 原创, 呵呵哒~~
void drv::Load_LUT(unsigned char mode) {
unsigned int i;
guy_epdCmd(0x32);
for (i = 0; i < 60; i++) {
if(mode == 1)
guy_epdParam(pgm_read_byte(lut_1Gray_GC+i));
else if(mode == 0){
if(20==i && greyScaling<8) guy_epdParam(0x03);
else if(53==i && greyScaling<3) guy_epdParam(greyScaling);
else if(53==i && greyScaling==15) guy_epdParam(5);
else guy_epdParam(pgm_read_byte(lut_1Gray_A2+i));
}
}
for (i = 0; i < 45; i++) {
if(i<40) guy_epdParam(0x00);
else guy_epdParam(0x22);
}
}
void drv::drv_init(){ //初始化屏幕
Init();
drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(!part) {
greyScaling=15; //恢复默认的灰度模式
BeginTransfer();
guy_epdCmd(0x04); // set source voltage
guy_epdParam(0x41); guy_epdParam(0xA8); guy_epdParam(0x32);
EndTransfer();
}
part_mode=part;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
if(sleeping) Init();
BeginTransfer();
guy_epdCmd(0x4E); guy_epdParam(0x00); guy_epdParam(0x00);
guy_epdCmd(0x4F); guy_epdParam(0x00); guy_epdParam(0x00);
guy_epdCmd(0x24);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
if(!part_mode) {
guy_epdCmd(0x26);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
}
Load_LUT(!part_mode);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(part_mode?500:1300);
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){
BeginTransfer();
guy_epdCmd(0X10); //deep sleep
guy_epdParam(0x03);
EndTransfer();
sleeping = true;
}
}
void drv::drv_setDepth(uint8_t i){ //设置显示颜色深度, 不支持的话什么都不做
if(i<=0 || i>15) i=15; //形参 无所谓随便更改!
greyScaling=i;
if(i>7) i-=7;
// Depth: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 >=15
//VSH(V): 2.4 3.6 4.7 5.6 6.4 7.3 8.1 9.0 9.8 10.7 11.6 12.4 13.3 14.1 15.0
//HEX : 0x8E,0x9A,0xA5,0xAE,0xB6,0xBF,0xC7,0x23,0x27,0x2C,0x30,0x34,0x38,0x3D,0x41
static const uint8_t dep[]={0x8E,0x9A,0xA5,0xAE,0xB6,0xBF,0xC7,0x23,0x27,0x2C,0x30,0x34,0x38,0x3D};
BeginTransfer();
guy_epdCmd(0x04); // set source voltage
if(greyScaling==15){ guy_epdParam(0x41); guy_epdParam(0xA8); }
else{
guy_epdParam(dep[i+6]); // VSH1,default is 0x41 (15.0V)
guy_epdParam(dep[i-1]); // VSH2,default is 0xA8 (5.0V)
}
guy_epdParam(0x32);
EndTransfer();
part_mode=1;
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,58 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file guy_370a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 3.7英寸墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD370A_H_FILE) && (defined(READGUY_DEV_370A)))
#define _GUY_EPD370A_H_FILE
namespace guydev_370A{
constexpr int GUY_D_WIDTH =280;
constexpr int GUY_D_HEIGHT =480;
class drv : public readguyEpdBase {
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_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 greyScaling = 15;
uint8_t sleeping = true;
int Init(void);
void Load_LUT(unsigned char mode);
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,273 @@
/******************** 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_420a.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 4.2英寸Hink墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_420a.h"
#ifdef READGUY_DEV_420A
namespace guydev_420A{
//////////// @brief 以下的部分代码来自半糖(HalfSweet)的程序
//////////// github.com/HalfSweetStudio/EPaperDrive
//////////// @copyright HalfSweet
const PROGMEM unsigned char drv::epd42_lut_full[]={
0x08,0x00,0x48,0x40,0x00,0x00,0x00,//L0 B low-high-low-high
0x20,0x00,0x12,0x20,0x00,0x00,0x00,//L1 W low-high-low
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,//L4 VCOM
0x05,0x20,0x20,0x05,0x00,
0x0f,0x00,0x00,0x00,0x00,
0x20,0x40,0x20,0x20,0x00,
0x20,0x00,0x00,0x00,0x00,
0x05,0x00,0x00,0x00,0x01,
0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,
};
const PROGMEM unsigned char drv::lut_213_B72_Full[]={
0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, //LUT0: BB: VS 0 ~7
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, //LUT1: BW: VS 0 ~7
0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, //LUT2: WB: VS 0 ~7
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, //LUT3: WW: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT4: VCOM: VS 0 ~7
0x03, 0x03, 0x00, 0x00, 0x02, // TP0 A~D RP0
0x09, 0x09, 0x00, 0x00, 0x02, // TP1 A~D RP1
0x03, 0x03, 0x00, 0x00, 0x02, // TP2 A~D RP2
0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
};
const PROGMEM unsigned char drv::lut_213_B72[]={
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT0: BB: VS 0 ~7
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT1: BW: VS 0 ~7
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT2: WB: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT3: WW: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //LUT4: VCOM: VS 0 ~7
0x0f, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0
0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1
0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2
0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
};
const PROGMEM unsigned char drv::lut_213_B72_16grey[]={
//0x05,0x00,0x10,0x10,0x10,0x00,0x01,//L0 BB R0 B/W 0
//0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L1 BW R0 B/W 1
//0x05,0x00,0x05,0x10,0x10,0x00,0x01, //L2 WB R1 B/W 0
//0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L3 WW R0 W/W 0
//0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L4 VCOM
0x01,0x00,0x00,0x00,0x00,0x00,0x00, //L4 bb
0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L4 bw
0x01,0x00,0x00,0x00,0x00,0x00,0x00, //L4 wb
0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L4 ww
0x00,0x00,0x00,0x00,0x00,0x00,0x00, //L4 VCOM
0x00,0x00,0x00,0x01,0x01,
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,0x00,0x00,0x00,
};
void drv::epd_Init(void){
const uint16_t GreyDrvFrameFreq[]={
0x1108, /* 75Hz */
0x180c, /* 35Hz */
0x2c0a, /* 50Hz */
0x0709, /* 65Hz */
0x2f07, /* 80Hz */
0x0807, /* 90Hz */
0x2106, /* 100Hz */
0x0306, /* 110Hz */
0x1405, /* 120Hz */
0x0705, /* 125Hz */
0x3104, /* ~130Hz */
0x2404, /* 135Hz */
0x1804, /* 140Hz */
0x0d04, /* 145Hz */
0x0304, /* 150Hz */
//0x0304, /* 150Hz */
};
//_InitDisplay fx
if(epdFull==2) {
Reset();
epdFull--;
}
//guy_epdCmd(0x12); //wake from deepsleep?
guy_epdCmd(0x74);
guy_epdParam(0x54);
guy_epdCmd(0x7e);
guy_epdParam(0x3b);
guy_epdCmd(0x01);
guy_epdParam(0x2b); //300 columns, will send 299.
guy_epdParam(0x01);
guy_epdParam(0x00);
/*guy_epdCmd(0x0c); //Booster Enable with Phase 1, Phase 2
//and Phase 3 for soft start current and duration setting.
guy_epdParam(0x8b);
guy_epdParam(0x9c);
guy_epdParam(0xd6);
guy_epdParam(0x0f);
guy_epdCmd(0x3a); //set to 100 Hz(0x3a--0x21, 0x3b--0x06)
guy_epdParam(0x21);
guy_epdCmd(0x3b);
guy_epdParam(0x06);*/
guy_epdCmd(0x3c);
guy_epdParam(0x03);
guy_epdCmd(0x2c); //vcom
guy_epdParam(0x70); //-1.6v
guy_epdCmd(0x03);
guy_epdParam(0x15);
guy_epdCmd(0x04); //set src volt (SEE DOC)
guy_epdParam(0x41);
guy_epdParam(0xa8);
guy_epdParam(0x32);
guy_epdCmd(0x3a); //Now trying 100Hz
guy_epdParam((GreyDrvFrameFreq[GreyScalingHighQuality]>>8)&0xff); //raw 30
guy_epdCmd(0x3b);
guy_epdParam(GreyDrvFrameFreq[GreyScalingHighQuality]&0xff); //raw 0a
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();
guy_epdCmd(0x22);
guy_epdParam(0xc3);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(210);
}
void drv::SetLut(const unsigned char* lut){
guy_epdCmd(0x32);
for(int i=0;i<70;i++){
if(!epdFull && GreyScaling && !GreyScalingHighQuality && i==35) guy_epdParam(GreyScaling);
else guy_epdParam(pgm_read_byte(lut+i));
}
}
void drv::drv_init(){ //初始化屏幕
epdFull = 2;
drv_color(0xff);
}
void drv::drv_fullpart(bool part){ //初始化慢刷功能
if(!part) GreyScaling=0;
if(epdFull<=1) epdFull = !part; //epdFull==2代表睡眠中, 不能快刷
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
BeginTransfer();
epd_Init();
SetMemory();
power_up();
SetMemory();
if(epdFull){ //慢刷
guy_epdCmd(0x26);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
}
guy_epdCmd(0x24);
for (int i = 0; i < GUY_D_HEIGHT*GUY_D_WIDTH/8; i++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
if(epdFull){ //慢刷
epd_Init();
SetMemory();
SetLut(lut_213_B72_Full);
guy_epdCmd(0x22);
guy_epdParam(0xc4);
guy_epdCmd(0x20);
EndTransfer();
guy_epdBusy(1600); //等待刷完
}
else{ //快刷
guy_epdCmd(0x2c); //may a mistake? 此处不需要设置vcom
guy_epdParam(0x20);
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++)
guy_epdParam(f(i)); //按照给定的RAM写入数据
EndTransfer();
if(epdFull) power_down();
}
void drv::drv_draw16grey_step(std::function<uint8_t(int)> f, int step){
if(_quality) return readguyEpdBase::drv_draw16grey_step(f,step);
if(step==1) drv_fullpart(1);//初始阶段,完成准备工作 //设置为快刷模式
GreyScalingHighQuality=step; //开启高品质灰度模式
drv_dispWriter(f);
//DelayMs(10); //未知原因()
if(step==15) GreyScalingHighQuality=0;//初始阶段,完成准备工作 //设置为快刷模式
}
/*void drv::drv_draw16grey(uint8_t *d16bit){ //绘制16阶段灰度示例图片, 注意这需要4倍的内存
(void) d16bit;
//drv_color(0xffu); 建议在开始前调用
drv_fullpart(1); //设置为快刷模式
for(int i=0;i<16;i++){
GreyScalingHighQuality=i; //开启高品质灰度模式
for(int j=0;j<15000;j++){ //从最深色开始发送, 逐步淡化, 重复15次(白色就不用刷了)
//if(j%50<5) guy_epdParam(0xff);
//guy_p[j] = (j%50-5<i*3?0:0xff); //For test only
}
//drv_display(guy_p);
}
GreyScalingHighQuality=0; //关闭灰度模式
}*/
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();
}
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View 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_420a.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 4.2英寸Hink墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD420A_H_FILE) && (defined(READGUY_DEV_420A)))
#define _GUY_EPD420A_H_FILE
namespace guydev_420A{
constexpr int GUY_D_WIDTH =400;
constexpr int GUY_D_HEIGHT =300;
class drv : public readguyEpdBase {
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i) { epdFull=0; GreyScaling = i>15?15:i; if(!i) GreyScaling=15;}
void drv_draw16grey_step(std::function<uint8_t(int)> f, int step);
int drv_supportGreyscaling() const { return _quality?16:-16; }
private:
//void Lut(unsigned char* lut);
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 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的
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,233 @@
/******************** 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_420b.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 4.2英寸WF丝印墨水屏 驱动库函数
* @version 1.0
* @date 2023-09-21
* @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_420b.h"
#ifdef READGUY_DEV_420B
namespace guydev_420B{
drv::drv(){
guy_lutArray[0] = lut_vcom0;
guy_lutArray[1] = lut_ww;
guy_lutArray[2] = lut_bw;
guy_lutArray[3] = lut_wb;
guy_lutArray[4] = lut_bb;
guy_lutArray[5] = lutFast_vc0;
guy_lutArray[6] = lutFast_w_w;
guy_lutArray[7] = lutFast_b_w;
guy_lutArray[8] = lutFast_w_b;
guy_lutArray[9] = lutFast_b_b;
customLut=CUSTOM_LUT_DISABLE;
customGreyscale=0;
}
void drv::Init(uint8_t pt) {
Reset();
guy_epdCmd(0x00); //Software reset
guy_epdParam(0x00);
guy_epdCmd(0x00);
guy_epdParam(0x1f);
guy_epdParam(0x0d);
guy_epdCmd(0x50);
guy_epdParam(0x97);
guy_epdCmd(0x01);
guy_epdParam(0x03);
guy_epdParam(0x00);
guy_epdParam(0x2b);
guy_epdParam(0x2b);
guy_epdCmd(0x06);
guy_epdParam(0x17);
guy_epdParam(0x17);
guy_epdParam(0x17);
guy_epdCmd(0x00);
guy_epdParam(0x3f);
guy_epdCmd(0x30);
guy_epdParam(0x3a);
guy_epdCmd(0x61);
guy_epdParam(0x01);
guy_epdParam(0x90);
guy_epdParam(0x01);
guy_epdParam(0x2c);
guy_epdCmd(0x82); //vcom setting: 0x00:-0.1V, 0x3a: -3.0V
guy_epdParam(0x1a);
guy_epdCmd(0x50);
guy_epdParam(0xd7);
SendLuts(pt?1:0); //不知为何, 此处需要快刷lut
if(pt!=2) guy_epdCmd(0x04);
}
void drv::sendArea(){
guy_epdCmd(0x91);
sendAreaRaw();
}
void drv::sendAreaRaw(){
guy_epdCmd(0x90);
guy_epdParam(0x00);
guy_epdParam(0x00);
guy_epdParam(0x01);
guy_epdParam(0x8f);
guy_epdParam(0x00);
guy_epdParam(0x00);
guy_epdParam(0x01);
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,
0x00, 0x08, 0x08, 0x00, 0x00, 0x02
};
const PROGMEM unsigned char drv::lut_ww[] ={
0x50, 0x08, 0x08, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,
0xA0, 0x08, 0x08, 0x00, 0x00, 0x02
};
const PROGMEM unsigned char drv::lut_bw[] ={
0x50, 0x08, 0x08, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,
0xA0, 0x08, 0x08, 0x00, 0x00, 0x02
};
const PROGMEM unsigned char drv::lut_bb[] ={
0x20, 0x08, 0x08, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,
0x10, 0x08, 0x08, 0x00, 0x00, 0x02
};
const PROGMEM unsigned char drv::lut_wb[] ={
0xA0, 0x08, 0x08, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,
0x50, 0x08, 0x08, 0x00, 0x00, 0x02
};
const PROGMEM unsigned char drv::lutFast_vc0[] ={ 0x00,2,0,48,0,1 };
const PROGMEM unsigned char drv::lutFast_w_w[] ={ 0x02,2,0,48,0,1 };
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(){
BeginTransfer();
Init(part_mode);
if(part_mode){
sendArea();
guy_epdCmd(0x13);
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){
send(i); //guy_epdParam(d[i]);
}
//data
guy_epdCmd(0x92);
sendAreaRaw();
//[EPDrg_BW<>] refresh fx
}
else{
guy_epdCmd(0x10);
//刷新数据
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){
send(i); //guy_epdParam(d[i]);
}
guy_epdCmd(0x13);
//刷新数据
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){
send(i); //guy_epdParam(d[i]);
}
guy_epdCmd(0x92);
//[EPDrg_BW<>] refresh fx
guy_epdCmd(0x00);
guy_epdParam(0x1f);
guy_epdParam(0x0d);
guy_epdCmd(0x50);
guy_epdParam(0x97);
//[EPDrg_EPD] wait_until_idle fx: 5000
}
guy_epdCmd(0x12);
EndTransfer();
guy_epdBusy(part_mode?-800:-3600);
BeginTransfer();
if(part_mode){
sendArea();
guy_epdCmd(0x13);
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){
send(i); //guy_epdParam(d[i]);
}
guy_epdCmd(0x92);
EndTransfer();
}
else{
Init(2);
sendArea();
guy_epdCmd(0x13);
for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/8;i++){
send(i); //guy_epdParam(d[i]);
}
guy_epdCmd(0x92);
guy_epdCmd(0x02);
EndTransfer();
guy_epdBusy(-20);
}
}
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);
}
void drv::drv_fullpart(bool part){ //切换慢刷/快刷功能
if(!part) customLut = CUSTOM_LUT_DISABLE;
part_mode = part;
//Init(part);
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
send = [&](int i){ guy_epdParam(f(i)); };
epd_display();
}
void drv::drv_sleep() { //开始屏幕睡眠
if(RST_PIN>=0){ //未定义RST_PIN时无法唤醒
BeginTransfer();
guy_epdCmd(0x02); //power off
EndTransfer();
guy_epdBusy(-30);
BeginTransfer();
guy_epdCmd(0x07); //deep sleep
guy_epdParam(0xA5);
EndTransfer();
}
}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,89 @@
/******************** 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_420b.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 4.2英寸WF丝印墨水屏 驱动库函数 头文件
* @version 1.0
* @date 2023-09-21
* @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_EPD420B_H_FILE) && (defined(READGUY_DEV_420B)))
#define _GUY_EPD420B_H_FILE
namespace guydev_420B{
// Display resolution
constexpr int GUY_D_WIDTH =400;
constexpr int GUY_D_HEIGHT =300;
constexpr int CUSTOM_LUT_DISABLE =48;
class drv : public readguyEpdBase {
public:
drv();
int drv_ID() const { return READGUY_DEV_420B; }
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return GUY_D_WIDTH; }; //返回显示区域宽度
int drv_height() const{ return GUY_D_HEIGHT; }; //返回显示区域高度
void drv_setDepth(uint8_t i) {
part_mode=1;
if(i) customLut = i>15?45:i*3;
else customLut = CUSTOM_LUT_DISABLE;
} //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
uint8_t part_mode = 0;
//uint8_t Power_is_on = 0; //初始为未上电
static const PROGMEM unsigned char lut_vcom0[];
static const PROGMEM unsigned char lut_ww[];
static const PROGMEM unsigned char lut_bw[];
static const PROGMEM unsigned char lut_bb[];
static const PROGMEM unsigned char lut_wb[];
// experimental partial screen update LUTs with balanced charge
// LUTs are filled with zeroes
static const PROGMEM unsigned char lutFast_vc0[];
static const PROGMEM unsigned char lutFast_w_w[];
static const PROGMEM unsigned char lutFast_b_w[];
static const PROGMEM unsigned char lutFast_w_b[];
static const PROGMEM unsigned char lutFast_b_b[];
const unsigned char *guy_lutArray[16];
void Init(uint8_t pt);
void sendArea();
void sendAreaRaw();
void SendLuts(uint8_t lutOption); //0:慢刷, 1:快刷, 2:四阶灰度
uint8_t customLut, customGreyscale; //customLut 是灰度刷新时的自定义lut
void epd_display();
//void (*send)(int);
std::function<void(int)> send; //此处不能用 void (*send)(int); 是因为lambda函数是std的
static const PROGMEM uint8_t greyTable[16];
};
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,55 @@
/******************** 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_epaper_config.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief EPD驱动基础配置文件. 用户可以根据自己对库的编译需求来修改此文件.
* @version 1.0
* @date 2023-09-21
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GUY_E_PAPER_CONFIG_H_FILE
#define _GUY_E_PAPER_CONFIG_H_FILE
//#define MEPD_DEBUG_WAVE 16 //取消此行注释来监视SPI的通信数据 (用于debug), 可以查看主控和屏幕的通信数据
//#define MEPD_DEBUG_WAITTIME //显示墨水屏的刷新时间, 单位是毫秒
#define FLOYD_STEINBERG_DITHERING //默认使用性能更好的floyd steinberg抖动算法, 取消注释则使用bayer图案抖动算法
// ***********************************************************************
//设备设置: 取消对应设备就可以直接禁用掉对应设备
//如果程序不想支持此型号(为了节省flash),请注释掉这一行, 实测根本不会节省多少空间
#define READGUY_DEV_154A 0
#define READGUY_DEV_154B 1
#define READGUY_DEV_213A 2
#define READGUY_DEV_213B 3
#define READGUY_DEV_266A 4
#define READGUY_DEV_270B 5
#define READGUY_DEV_290A 6
#define READGUY_DEV_290B 7
#define READGUY_DEV_370A 8
#define READGUY_DEV_420A 9
#define READGUY_DEV_420B 10
#define MEPD_DEBUG_DISPLAY 11 //使用LCD显示屏幕来debug
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,278 @@
/******************** 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_epdbase.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief readguy EPD 驱动程序 公共基类. 所有驱动都要依赖此文件.
* @version 1.0
* @date 2023-09-21
* @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"
#include <spi.h>
readguyEpdBase::readguyEpdBase() {
};
readguyEpdBase::~readguyEpdBase() {
};
void readguyEpdBase::DigitalWrite(int pin, int value) {
if(pin>=0) digitalWrite(pin, value);
}
int readguyEpdBase::DigitalRead(int pin) {
return (pin>=0)?digitalRead(pin):1;
}
void readguyEpdBase::DelayMs(unsigned int delaytime) {
delay(delaytime);
}
void readguyEpdBase::BeginTransfer(){
if(!in_trans && CS_PIN>=0) {
digitalWrite(CS_PIN, LOW);
if(spi_tr_press!=nullptr) spi_tr_press();
}
in_trans++;
}
void readguyEpdBase::EndTransfer(){
if(in_trans) in_trans--;
if(!in_trans && CS_PIN>=0) {
digitalWrite(CS_PIN, HIGH);
if(spi_tr_release!=nullptr) spi_tr_release();
}
}
void readguyEpdBase::SpiTransfer(unsigned char data) {
if(in_trans) {
_spi->transfer(data);
return;
}
if(CS_PIN>=0) digitalWrite(CS_PIN, LOW);
_spi->transfer(data);
if(CS_PIN>=0) digitalWrite(CS_PIN, HIGH);
}
int readguyEpdBase::IfInit(SPIClass &c,int8_t cs,int8_t dc,int8_t rst,int8_t busy) {
//static uint8_t IfHadInit=0;
//if(IfHadInit) return;
CS_PIN = cs;
DC_PIN = dc;
RST_PIN = rst;
BUSY_PIN = busy;
if(CS_PIN>=0) pinMode(CS_PIN , OUTPUT);
if(RST_PIN>=0) pinMode(RST_PIN , OUTPUT);
DigitalWrite(RST_PIN,HIGH);
if(DC_PIN>=0) pinMode(DC_PIN , OUTPUT);
if(BUSY_PIN>=0) pinMode(BUSY_PIN, INPUT);
_spi = &c;
//_spi->begin();
//_spi->beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
//IfHadInit = 1;
return 0;
}
void readguyEpdBase::guy_epdCmd(unsigned char command)
{
#ifdef MEPD_DEBUG_WAVE
if(dat_combo) {
if(dat_combo>MEPD_DEBUG_WAVE) Serial.printf("\nTotal %d data written.",dat_combo);
Serial.write('\n');
}
dat_combo=0;
Serial.printf("Cmd %02x: ", command);
#endif
DigitalWrite(DC_PIN, LOW);
SpiTransfer(command);
DigitalWrite(DC_PIN, HIGH);
}
void readguyEpdBase::guy_epdParam(unsigned char data)
{
#ifdef MEPD_DEBUG_WAVE
if(dat_combo==MEPD_DEBUG_WAVE){
Serial.print("...");
}
else if(dat_combo<MEPD_DEBUG_WAVE){
Serial.printf("%02x ",data);
}
dat_combo++;
#endif
SpiTransfer(data);
}
void readguyEpdBase::guy_epdBusy(int32_t maxt) {
#if (defined(MEPD_DEBUG_WAVE) || defined(MEPD_DEBUG_WAITTIME))
Serial.printf("\nWaitUntilIdle: max %d ms.\n",maxt);
#endif
//if(spi_tr_release!=nullptr) spi_tr_release();
uint32_t mls = millis();
if(maxt<0){ //HIGH: idle, LOW: busy
while((BUSY_PIN<0 || !DigitalRead(BUSY_PIN)) && millis()-mls<=uint32_t(-maxt))
DelayMs(1);
}
else{ //LOW: idle, HIGH: busy
while(DigitalRead(BUSY_PIN) && millis()-mls<=uint32_t(maxt))
DelayMs(1);
}
#if (defined(MEPD_DEBUG_WAVE) || defined(MEPD_DEBUG_WAITTIME))
Serial.printf("Wait %lu ms.\n",millis()-mls);
#endif
//if(spi_tr_press!=nullptr) spi_tr_press();
}
void readguyEpdBase::SetMemory() {
guy_epdCmd(0x44);
/* x point must be the multiple of 8 or the last 3 bits will be ignored */
guy_epdParam(0);
guy_epdParam(((drv_width()-1) >> 3) & 0xFF);
guy_epdCmd(0x45);
guy_epdParam(0);
guy_epdParam(0);
guy_epdParam((drv_height()-1) & 0xFF);
guy_epdParam(((drv_height()-1) >> 8) & 0xFF);
guy_epdCmd(0x4E);
/* x point must be the multiple of 8 or the last 3 bits will be ignored */
guy_epdParam(0);
guy_epdCmd(0x4F);
guy_epdParam(0);
guy_epdParam(0);
}
void readguyEpdBase::Reset(uint32_t minTime)
{
if(RST_PIN<0) return;
//DigitalWrite(RST_PIN, HIGH);
//DelayMs(minTime);
DigitalWrite(RST_PIN, LOW); //module reset
DelayMs(minTime);
DigitalWrite(RST_PIN, HIGH);
DelayMs(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){
#ifndef FLOYD_STEINBERG_DITHERING
static const 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,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
#endif
const uint_fast16_t w = (spr.width()+7)>>3;
if((!w) || (!spr.height())) return;
uint16_t *readBuff = new uint16_t[spr.width()];
uint8_t *writeBuff = new uint8_t[w];
#ifdef FLOYD_STEINBERG_DITHERING
int16_t *floyd_tab[2];
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
sprbase.fillRect(x,y,spr.width(),spr.height(),1);
for(int_fast16_t i=0;i<(int_fast16_t)spr.height();i++){
spr.readRect(0,i,spr.width(),1,readBuff);
#ifdef FLOYD_STEINBERG_DITHERING
uint_fast8_t buff8bit=0;
for(int_fast16_t j=0;j<(int_fast16_t)spr.width();j++){
int_fast16_t flodelta = floyd_tab[i&1][j]+(int_fast16_t)(greysc(readBuff[j])<<4);
if(flodelta>=2048) {
//spr.drawPixel(j,i,1);
buff8bit |= 1<<((~j)&7);
flodelta -= 4095;
}
if((j&7)==7 || j==((int_fast16_t)spr.width()-1)){
writeBuff[j>>3]=buff8bit;
buff8bit=0;
}
//计算出读取到的颜色, 然后与128比较, 如果小于128, 显示黑色,否则显示白色
//else { spr.drawPixel(j,i,0); }
/*if(j!=(int_fast16_t)spr.width()-1) {
floyd_tab[ i&1 ][j+1] += (flodelta*7)>>4;
floyd_tab[!(i&1)][j+1] += (flodelta )>>4;
}
if(j) { floyd_tab[!(i&1)][j-1] += (flodelta*3)>>4; }
{ floyd_tab[!(i&1)][j ] += (flodelta*5)>>4; }*/
if(j!=(int_fast16_t)spr.width()-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!=(int_fast16_t)spr.width()-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(int_fast16_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;
}
#endif
sprbase.drawBitmap(x,y+i,writeBuff,spr.width(),1,1,0);
}
_display((const uint8_t*)sprbase.getBuffer());
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){
//Serial.println("drv_draw16grey fx");
const uint_fast16_t w = (spr.width()+7)>>3;
if((!w) || (!spr.height())) return;
uint16_t *readBuff = new uint16_t[spr.width()];
uint8_t *writeBuff = new uint8_t[w];
sprbase.fillRect(x,y,spr.width(),spr.height(),1);
bool negativeOrder=(drv_supportGreyscaling()==-16);
drv_fullpart(0);
_display((const uint8_t*)sprbase.getBuffer()); //先对区域慢刷白屏确保颜色正确
drv_fullpart(1);
for(uint_fast8_t k=1;k<16;k++){ //亮度为15的不用绘制,因为本来就是白色
for(int i=0;i<spr.height();i++){
spr.readRect(0,i,spr.width(),1,readBuff);
for(uint_fast16_t j=0;j<w;j++){
uint_fast8_t buff8bit=0;
for(uint_fast8_t b=0;b<8;b++){
//uint_fast8_t cg=greysc(readBuff[j*8+b])/16
uint_fast8_t cg=greysc(readBuff[(j<<3)+b])>>4;
if(negativeOrder)
buff8bit |= (cg<k)<<((~b)&7);
else{
if(cg==15) continue; //白色不考虑
buff8bit |= (cg>=((~k)&15))<<((~b)&7);
}
}
//sprbase.drawPixel(x+j,y+i,(greysc(readBuff[j])/16)==(15-k));
writeBuff[j]=buff8bit^0xff;
}
sprbase.drawBitmap(x,y+i,writeBuff,spr.width(),1,1,0);
}
drv_draw16grey_step((const uint8_t*)sprbase.getBuffer(),k); //使用灰度显示函数
}
delete []readBuff;
delete []writeBuff;
} /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,108 @@
/******************** 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_epdbase.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief readguy EPD 驱动程序 公共基类 头文件. 所有驱动都要依赖此文件.
* @version 1.0
* @date 2023-09-21
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _READGUY_EPDBASE_H_FILE
#define _READGUY_EPDBASE_H_FILE
#include <Arduino.h>
#include <SPI.h>
#include <FS.h>
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include "guy_epaper_config.h"
#define EPD_DRIVERS_NUM_MAX 12 //此选项请不要取消注释掉
class readguyEpdBase {
protected:
SPIClass *_spi;
// Pin definition
int8_t RST_PIN ;
int8_t DC_PIN ;
int8_t CS_PIN ;
int8_t BUSY_PIN;
uint8_t in_trans=0;
uint8_t _quality=0; //灰度显示品质 0(默认)-高品质 1-低品质 部分屏幕支持高品质的连续刷灰度.
#ifdef MEPD_DEBUG_WAVE
uint16_t dat_combo = 0; //dc引脚状态 0 command, 1 data
#endif
public:
readguyEpdBase(void);
virtual ~readguyEpdBase(void);
int IfInit(SPIClass &c,int8_t cs,int8_t dc,int8_t rst,int8_t busy);
void DigitalWrite(int pin, int value);
int DigitalRead(int pin);
void DelayMs(unsigned int delaytime);
void BeginTransfer();
void EndTransfer();
void SpiTransfer(unsigned char data);
//basic I/O operation
void guy_epdCmd(unsigned char command);
void guy_epdParam(unsigned char data);
void guy_epdBusy(int32_t maxt);
void Reset(uint32_t minTime = 20);
void SetMemory(); //集成了0x44 0x45 0x4e 0x4f指令的函数. 此函数用于设置墨水屏内存写入方式
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;}); } //单色刷新
virtual void drv_sleep() =0; //开始屏幕睡眠
virtual int drv_width() const=0; //返回显示区域宽度, 即使旋转了也不能影响此函数输出
virtual int drv_height()const=0; //返回显示区域高度, 即使旋转了也不能影响此函数输出
virtual int drv_supportGreyscaling() const { return 0; }
virtual void drv_setDepth(uint8_t i){} //设置显示颜色深度, 不支持的话什么都不做
/** @brief 获取某一像素颜色, 并转化为256阶灰度
* @param x, y 坐标
* @param gamma_on 是否对灰度值进行gamma校正(速度慢)
* @return uint32_t 颜色的灰度值
*/
static int greysc(int got){ return (int)((got&0xf8)*299+(((got>>11)&0x1c)|((got<<5)&0xe0))*587+((got&0x1f00)>>5)*114)/978; }
void drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y); //分步完成灰度刷新
void drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y);//省内存方式
void drv_draw16grey_step(const uint8_t *buf, int step){ //分步完成灰度刷新
drv_draw16grey_step([&](int n)->uint8_t{return buf[n];},step);
}
virtual void drv_draw16grey_step(std::function<uint8_t(int)> f, int step){ //分步完成灰度刷新
drv_setDepth(step);
drv_dispWriter(f);
}
void setGreyQuality(bool q) { _quality=!q; } //设置灰度的渲染画质. 高画质模式在某些屏幕某些情况下可能表现不好.
void (*spi_tr_release)(void);
void (*spi_tr_press)(void);
#ifdef MEPD_DEBUG_DISPLAY
friend class LGFX;
#endif
};
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,311 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
*
* @file ctg_stack_c_defines.h
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 调试用墨水屏模拟器 驱动库函数 可使用LCD屏幕仿真墨水屏使用或测试
* @version 1.0
* @date 2023-09-21
* @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.
*/
/********** FRIENDSHIPENDER **********
* @note THIS FILE IS FOR ESP8266 OR ESP32-C3-12F ONLY
* @file ctg_stack_c_defines.cpp
* @author FriendshipEnder (Q:3253342798)
* @brief driver for SC3EEN Project
* @version 1.0
* @date V1.1 2022-06-17
* V1.0 2021-11-21
*
* @copyright FriendshipEnder (c) 2022
*
*/
#ifndef _CTG_STACK_C_DEFINES_H
#define _CTG_STACK_C_DEFINES_H
//选择需要的屏幕驱动程序
//墨水屏暂时还不支持使用本库文件驱动(但是可以使用其他的库文件)
//#define DISPLAY_no_CS //屏幕无CS引脚, 请选择此项, 引脚顺序为 GND VCC SCK MOSI RST DC BLK
//#define DISPLAY_TYPE_ST7789_240320 //2.0寸的ST7789 IPS TFT模块
//#define DISPLAY_TYPE_ST7789_240240 //1.3寸或者1.54寸的ST7789 IPS TFT模块
//#define DISPLAY_TYPE_ST7789_135240 //1.14寸的ST7789 模块
//#define DISPLAY_TYPE_ST7735_128160 //1.8寸的ST7735 彩色显示模块
//#define DISPLAY_TYPE_ST7735_128128 //1.44寸的ST7735 彩色显示模块
//#define DISPLAY_TYPE_ST7735_080160 //0.96寸的ST7735 彩色显示模块
//#define DISPLAY_TYPE_SSD1306_MONO_128064 //0.96寸的SSD1306 OLED12864 SPI接口显示模块
//#define DISPLAY_TYPE_SSD1327_128128 //适用于隔壁老王的 1.5寸 16灰阶的 SSD1327 OLED SPI接口
//#define DISPLAY_TYPE_ILI9486_320480 //适用于中景园电子的 3.5寸 ILI9486 8pin LCD SPI接口
//#define DISPLAY_TYPE_ILI9342_320240 //适用于M5Stack
//以下模块 引脚顺序不兼容SC3EEN硬件
//#define DISPLAY_TYPE_SSD1351_128128 //适用于绝版的Adafruit 彩色OLED显示模块
//#define DISPLAY_TYPE_SSD1351_128096 //适用于绝版的Adafruit 彩色OLED显示模块 引脚顺序不兼容SC3EEN硬件
#include <Arduino.h>
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
//#define _DEFINA_SD_CS_PIN 0
// * for NodeMcu ctg stack LCF board
#ifdef ESP8266
#define DISPLAY_TYPE_ST7789_240320 //2.0寸的ST7789 IPS TFT模块
#define _DEFINA_IPS_CS_PIN 15
#define _DEFINA_IPS_DC_PIN 5
#define _DEFINA_IPS_RST_PIN -1
#define _DEFINA_IPS_MOSI_PIN -1
#define _DEFINA_IPS_MISO_PIN -1
#define _DEFINA_IPS_SCLK_PIN -1
#else
//for M5Stack Core ESP32
#define DISPLAY_TYPE_ILI9342_320240
#define _DEFINA_IPS_CS_PIN 14
#define _DEFINA_IPS_DC_PIN 27
#define _DEFINA_IPS_RST_PIN 33
#define _DEFINA_IPS_MOSI_PIN 23
#define _DEFINA_IPS_MISO_PIN 19
#define _DEFINA_IPS_SCLK_PIN 18
#endif
//#define _DEFINA_IPS_BL_PIN 4
class LGFX : public lgfx::LGFX_Device
{
#if (defined(DISPLAY_TYPE_ST7789_240320) || defined(DISPLAY_TYPE_ST7789_240240) || defined(DISPLAY_TYPE_ST7789_135240))
lgfx::Panel_ST7789 _panel_instance;
#elif (defined(DISPLAY_TYPE_ST7735_128160) || defined(DISPLAY_TYPE_ST7735_080160) || defined(DISPLAY_TYPE_ST7735_128128))
lgfx::Panel_ST7735S _panel_instance;
#elif (defined(DISPLAY_TYPE_SSD1351_128128) || defined(DISPLAY_TYPE_SSD1351_128096))
lgfx::Panel_SSD1351 _panel_instance;
#elif (defined(DISPLAY_TYPE_SSD1306_MONO_128064))
lgfx::Panel_SSD1306 _panel_instance;
#elif (defined (DISPLAY_TYPE_ILI9486_320480))
lgfx::Panel_ILI9486 _panel_instance;
#elif (defined (DISPLAY_TYPE_SSD1327_128128))
lgfx::Panel_SSD1327 _panel_instance;
#else //用户可以自己添加屏幕型号操作
lgfx::Panel_ILI9342 _panel_instance; //用户可以自己添加屏幕型号操作
#endif
lgfx::Bus_SPI _bus_instance;
//lgfx::Light_PWM _light_instance;
public:
LGFX(void){}
void configLGFX(void){
{ // 设置总线控制。- SPI, I2C, I2S, FSMC, etc.
auto cfg = _bus_instance.config(); // 获取总线配置的结构。
#ifndef ESP8266
#ifdef CONFIG_IDF_TARGET_ESP32
cfg.spi_host = SPI3_HOST; // 选择要使用的 SPI (VSPI_HOST or HSPI_HOST)
#else
cfg.spi_host = SPI1_HOST; // 选择要使用的 SPI (VSPI_HOST or HSPI_HOST)
#endif
cfg.use_lock = true; // 使用锁时设置为 True
cfg.dma_channel = SPI_DMA_CH_AUTO; // Set the DMA channel (1 or 2. 0=disable) 设置要打开的 DMA 通道 (0=DMA关闭)
#endif
cfg.spi_mode = 0; // SPI设置通讯模式 (0 ~ 3)
#if (defined(DISPLAY_TYPE_ST7789_240320) || defined(DISPLAY_TYPE_ST7789_240240) || defined(DISPLAY_TYPE_ST7789_135240))
cfg.freq_write = 40000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 8000000; // 接收时的SPI时钟
#elif (defined(DISPLAY_TYPE_ST7735_128160) || defined(DISPLAY_TYPE_ST7735_080160) || defined(DISPLAY_TYPE_ST7735_128128))
cfg.freq_write = 27000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 4000000; // 接收时的SPI时钟
#elif (defined(DISPLAY_TYPE_SSD1306_MONO_128064))
cfg.freq_write = 20000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 2000000; // 接收时的SPI时钟
#elif (defined (DISPLAY_TYPE_SSD1327_128128))
cfg.freq_write = 20000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 2000000; // 接收时的SPI时钟
#elif (defined (DISPLAY_TYPE_ILI9486_320480))
cfg.freq_write = 40000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 0; // 接收时的SPI时钟
#elif (defined(DISPLAY_TYPE_SSD1351_128128) || defined(DISPLAY_TYPE_SSD1351_128096))
cfg.freq_write = 16000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 0; // 接收时的SPI时钟
#else //用户可以自己添加屏幕型号操作
cfg.freq_write = 40000000; // 传输时的SPI时钟最高80MHz四舍五入为80MHz除以整数得到的值
cfg.freq_read = 8000000; // 接收时的SPI时钟
#endif
cfg.spi_3wire = true; // 使用 MOSI 引脚接收时设置为 True
cfg.pin_sclk = _DEFINA_IPS_SCLK_PIN; // 设置 SCLK 引脚号
cfg.pin_mosi = _DEFINA_IPS_MOSI_PIN; // 设置 MOSI 引脚号
cfg.pin_miso = _DEFINA_IPS_MISO_PIN; // 设置 MISO 引脚号 (-1 = 禁用)
cfg.pin_dc = _DEFINA_IPS_DC_PIN; // 设置 DC 引脚号 (-1 = 禁用)
_bus_instance.config(cfg); // 设定值反映在总线上。
_panel_instance.setBus(&_bus_instance); // 在面板上设置总线。
}
{ // 设置显示面板控件。- 显示宽度/高度, 颜色格式, 读写像素规则, etc.
auto cfg = _panel_instance.config(); // 获取显示面板设置的结构。
#if (defined(DISPLAY_no_CS))
cfg.pin_cs = -1; // 设置 CS 引脚号 (-1 = 禁用)
#undef _DEFINA_IPS_BL_PIN
#define _DEFINA_IPS_BL_PIN _DEFINA_IPS_CS_PIN
#undef _DEFINA_IPS_CS_PIN
#else
cfg.pin_cs = _DEFINA_IPS_CS_PIN; // 设置 CS 引脚号 (-1 = 禁用)
#endif
cfg.pin_rst = _DEFINA_IPS_RST_PIN; // 设置 RST 引脚号 (-1 = 禁用)
cfg.pin_busy = -1; // 设置 BUSY 引脚号 (-1 = 禁用)
#if defined(DISPLAY_TYPE_ST7789_135240)
cfg.offset_x = 52; // 面板的 X 方向偏移量
#elif (defined(DISPLAY_TYPE_ST7735_128160) || defined(DISPLAY_TYPE_ST7735_128128))
cfg.offset_x = 2; // 面板的 X 方向偏移量
#elif defined(DISPLAY_TYPE_ST7735_080160)
cfg.offset_x = 24; // 面板的 X 方向偏移量
#else
cfg.offset_x = 0; // 面板的 X 方向偏移量
#endif
#if defined(DISPLAY_TYPE_ST7789_135240)
cfg.offset_y = 40; // 面板的 Y 方向偏移量
#elif (defined(DISPLAY_TYPE_ST7735_128160) || defined(DISPLAY_TYPE_ST7735_128128))
cfg.offset_y = 1; // 面板的 Y 方向偏移量
//#elif defined(DISPLAY_TYPE_SSD1351_128096)
// cfg.offset_y = 0; // 面板的 Y 方向偏移量
#else
cfg.offset_y = 0; // 面板的 Y 方向偏移量
#endif
#if defined(DISPLAY_TYPE_ST7789_240320)
#define HW_SCREEN_WIDTH 240 // 实际显示宽度
#define HW_SCREEN_HEIGHT 320 // 实际显示高度
#elif defined(DISPLAY_TYPE_ST7789_240240)
#define HW_SCREEN_WIDTH 240 // 实际显示宽度
#define HW_SCREEN_HEIGHT 240 // 实际显示高度
#elif defined(DISPLAY_TYPE_ST7789_135240)
#define HW_SCREEN_WIDTH 135 // 实际显示宽度
#define HW_SCREEN_HEIGHT 240 // 实际显示高度
#elif defined(DISPLAY_TYPE_ST7735_128160)
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 160 // 实际显示高度
cfg.memory_width = 132; // 驱动IC支持的最大宽度
cfg.memory_height = 162; // 驱动IC支持的最大高度
#elif defined(DISPLAY_TYPE_ST7735_128128)
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 128 // 实际显示高度
cfg.memory_width = 132; // 驱动IC支持的最大宽度
cfg.memory_height = 132; // 驱动IC支持的最大高度
#elif defined(DISPLAY_TYPE_ST7735_080160)
#define HW_SCREEN_WIDTH 80 // 实际显示宽度
#define HW_SCREEN_HEIGHT 160 // 实际显示高度
cfg.memory_width = 128; // 驱动IC支持的最大宽度
cfg.memory_height = 160; // 驱动IC支持的最大高度
#elif defined(DISPLAY_TYPE_SSD1351_128128)
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 128 // 实际显示高度
#elif defined(DISPLAY_TYPE_SSD1351_128096)
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 96 // 实际显示高度
#elif (defined(DISPLAY_TYPE_SSD1306_MONO_128064))
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 64 // 实际显示高度
cfg.memory_width = 128; // 驱动IC支持的最大宽度
cfg.memory_height = 64; // 驱动IC支持的最大高度
#elif (defined(DISPLAY_TYPE_SSD1327_128128))
#define HW_SCREEN_WIDTH 128 // 实际显示宽度
#define HW_SCREEN_HEIGHT 128 // 实际显示高度
cfg.memory_width = 128; // 驱动IC支持的最大宽度
cfg.memory_height = 128; // 驱动IC支持的最大高度
#elif (defined (DISPLAY_TYPE_ILI9486_320480))
#define HW_SCREEN_WIDTH 320 // 实际显示宽度
#define HW_SCREEN_HEIGHT 480 // 实际显示高度
cfg.memory_width = 320; // 驱动IC支持的最大宽度
cfg.memory_height = 480; // 驱动IC支持的最大高度
#elif (defined(DISPLAY_TYPE_ILI9342_320240))
#define HW_SCREEN_WIDTH 320 // 实际显示宽度
#define HW_SCREEN_HEIGHT 240 // 实际显示高度
cfg.memory_width = 320; // 驱动IC支持的最大宽度
cfg.memory_height = 240; // 驱动IC支持的最大高度
#else //用户可以自己添加屏幕型号操作
#define HW_SCREEN_WIDTH 240 // 实际显示宽度
#define HW_SCREEN_HEIGHT 320 // 实际显示高度
cfg.memory_width = 240; // 驱动IC支持的最大宽度
cfg.memory_height = 320; // 驱动IC支持的最大高度
#endif
//cfg.memory_width = cfg.memory_width; // 驱动IC支持的最大宽度
//cfg.memory_height = cfg.memory_height; // 驱动IC支持的最大高度
#if (defined(DISPLAY_TYPE_ST7789_240320) || defined(DISPLAY_TYPE_ST7789_240240) || defined(DISPLAY_TYPE_ST7789_135240))
cfg.memory_width = 240; // 驱动IC支持的最大宽度
cfg.memory_height = 320; // 驱动IC支持的最大高度
#elif (defined(DISPLAY_TYPE_SSD1351_128128) || defined(DISPLAY_TYPE_SSD1351_128096))
cfg.memory_width = 128; // 驱动IC支持的最大宽度
cfg.memory_height = 128; // 驱动IC支持的最大高度
#endif
cfg.panel_width = HW_SCREEN_WIDTH;
cfg.panel_height = HW_SCREEN_HEIGHT;
#if (defined(DISPLAY_TYPE_SSD1351_128128) || defined(DISPLAY_TYPE_SSD1351_128096))
cfg.offset_rotation = 4; // 设置旋转方向的偏移, 可用的值介于0~7之间4~7是镜像的
#elif (defined(DISPLAY_TYPE_SSD1306_MONO_128064))
cfg.offset_rotation = 2; // 设置旋转方向的偏移, 可用的值介于0~7之间4~7是镜像的
#else
cfg.offset_rotation = 0; // 设置旋转方向的偏移, 可用的值介于0~7之间4~7是镜像的
#endif
//cfg.dummy_read_pixel = 0; // 在读取像素之前读取的虚拟位数
//cfg.dummy_read_bits = 0; // 读取像素以外的数据之前的虚拟读取位数
#if (defined(DISPLAY_TYPE_SSD1351_128128) || defined(DISPLAY_TYPE_SSD1351_128096) || defined(DISPLAY_no_CS))
cfg.readable = false; // 如果可以读取数据,则设置为 true
#else
cfg.readable = true; // 如果可以读取数据,则设置为 true
#endif
#if (defined(DISPLAY_TYPE_ST7789_240320) || defined(DISPLAY_TYPE_ST7789_240240) || defined(DISPLAY_TYPE_ST7789_135240)\
|| defined(DISPLAY_TYPE_ILI9342_320240))
cfg.invert = true; // 如果面板的明暗反转,则设置为 true
#else
cfg.invert = false; // 如果面板的明暗反转,则设置为 true
#endif
#if defined(DISPLAY_TYPE_ST7735_128160)
cfg.rgb_order = true; // 如果面板的红色和蓝色被交换,则设置为 true
#else
cfg.rgb_order = false; // 如果面板的红色和蓝色被交换,则设置为 true
#endif
cfg.dlen_16bit = false; // 对于以 16 位单位发送数据长度的面板,设置为 true
cfg.bus_shared = true; // 如果总线与 SD 卡共享,则设置为 true使用 drawJpgFile 等执行总线控制)
_panel_instance.config(cfg);
}
/*
{ // 设置背光控制。 (不需要的话删掉)
}
*/
setPanel(&_panel_instance); // 初始化要使用的面板。
}
};
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,87 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file lcdDebug.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 调试用墨水屏模拟器 驱动库函数 可使用LCD屏幕仿真墨水屏使用或测试
* @version 1.0
* @date 2023-09-21
* @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 "lcdDebug.h"
#ifdef MEPD_DEBUG_DISPLAY
namespace EpdLcdDebug{
void drv::drv_init(){
ips.configLGFX();
ips.init();
ips.fillScreen(0xffff);
}
void drv::drv_fullpart(bool part){
partMode=part;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
uint16_t dat[8];
unsigned short xbits=(drv_width()+7)/8;
if(partMode==0){
ips.invertDisplay(1);
DelayMs(250);
ips.invertDisplay(0);
DelayMs(250);
ips.invertDisplay(1);
DelayMs(250);
ips.invertDisplay(0);
}
for(int j=0;j<drv_height();j++){
for(int i=0;i<xbits;i++){
if(f(j*xbits+i) == 0xff && i!=xbits-1)
ips.drawFastHLine(WHITE_GAP+i*8,WHITE_GAP+j,8,0xffff);
else {
int lineOK=0;
ips.readRect(WHITE_GAP+i*8,WHITE_GAP+j,8,1,dat); //注意这里 readrect函数已经自动化实现边界处理了
if(f(j*xbits+i) == 0x00 && i!=xbits-1){
for(int k=0;k<8;k++)
if((dat[k]&0x1f)==0x1f) lineOK++;
if(lineOK==8) {
ips.drawFastHLine(WHITE_GAP+i*8,WHITE_GAP+j,8,0x1082*(15-depth));
continue;
}
}
for(int k=0;k<8;k++){
if(i==xbits-1 && i*8+k>=drv_width()) break;
if((f(j*xbits+i)&(0x80>>k)))
ips.drawPixel(WHITE_GAP+i*8+k,WHITE_GAP+j,0xffff);
else if((dat[k]&0x1f)==0x1f)
ips.drawPixel(WHITE_GAP+i*8+k,WHITE_GAP+j,0x1082*(15-depth));
}
}
}
yield();
}
//ips.readPixel(i,j);
DelayMs(150);
}
void drv::drv_sleep() {}
}
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */

View File

@@ -0,0 +1,59 @@
/******************** F r i e n d s h i p E n d e r ********************
* 本程序隶属于 Readguy 开源项目, 请尊重开源开发者, 也就是我FriendshipEnder.
* 如果有条件请到 extra/artset/reward 中扫描打赏,否则请在 Bilibili 上支持我.
* 项目交流QQ群: 926824162 (萌新可以进来问问题的哟)
* 郑重声明: 未经授权还请不要商用本开源项目编译出的程序.
* @file lcdDebug.cpp
* @author FriendshipEnder (f_ender@163.com), Bilibili: FriendshipEnder
* @brief 调试用墨水屏模拟器 驱动头文件 可使用LCD屏幕仿真墨水屏使用或测试
* @version 1.0
* @date 2023-09-21
* @attention
* Copyright (c) 2022-2023 FriendshipEnder
*
* Apache License, Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _LCD_DEBUG_H_FILE
#define _LCD_DEBUG_H_FILE
#include "../guy_epdbase.h"
#ifdef MEPD_DEBUG_DISPLAY
#include "ctg_stack_c_defines.h"
#define WHITE_GAP 4
namespace EpdLcdDebug{
class drv : public readguyEpdBase {
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_sleep() ; //开始屏幕睡眠
int drv_width() const { return ips.width()-2*WHITE_GAP; } //返回显示区域宽度
int drv_height() const{ return ips.height()-2*WHITE_GAP; } //返回显示区域高度
void drv_setDepth(uint8_t i) { if(i<=15) depth=i; if(!i) depth=15;} //设置显示颜色深度
int drv_supportGreyscaling() const { return 16; }
private:
LGFX ips;
int16_t depth=15;
int16_t partMode =0;
};
}
#endif
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */