update to 1.3.0 version

This commit is contained in:
fsender
2023-11-06 15:39:13 +08:00
parent b5d77bc054
commit a8b2540468
31 changed files with 903 additions and 635 deletions

View File

@@ -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,14 +92,24 @@ 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(!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){ //单色刷新等功能
if(sleeping) Init(lut_slow);
BeginTransfer();
@@ -136,8 +139,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;

View File

@@ -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

View File

@@ -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,21 @@ 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(!epd_PowerOn) part=0; //未上电 无法局刷
if(!part) { iLut=15; greyScaling=0; }
_part=part;
}
void drvSSD168x::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
BeginTransfer();
if(_part && epd_PowerOn){
if(_part){
//Reset();
SetLut();
guy_epdCmd(0x37);
@@ -186,7 +163,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,7 +192,9 @@ 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);
}
@@ -206,8 +204,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) {

View File

@@ -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();
};

View File

@@ -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,12 +106,14 @@ 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(!epd_PowerOn) part=0; //未上电 无法局刷
//if(part==epdFull) return;
if(!part) iLut=15; //恢复默认的灰度模式
epdFull = !part;
@@ -144,21 +146,22 @@ void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
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.

View File

@@ -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[];

View File

@@ -76,13 +76,8 @@ drv_base::drv_base(){
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);
@@ -110,11 +105,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){
@@ -134,17 +129,19 @@ 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(!Power_is_on) part=0;
if(!part) greyLut=15; //恢复默认的灰度模式
part_mode = part;
}
@@ -157,11 +154,11 @@ void drv_base::drv_setDepth(uint8_t i){
}
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);
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写入数据
@@ -169,58 +166,33 @@ void drv_base::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
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++)
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);
}
}
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){

View File

@@ -50,12 +50,11 @@ 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];

View File

@@ -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(sleeping) return;
if(!part) {
greyScaling=15; //恢复默认的灰度模式
BeginTransfer();
@@ -142,8 +146,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){ //设置显示颜色深度, 不支持的话什么都不做

View File

@@ -47,9 +47,9 @@ public:
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);
};

View File

@@ -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,25 @@ 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(epdFull<=1) epdFull = !part; //epdFull==2代表睡眠中, 不能快刷
if(epdFull) GreyScaling=0;
}
void drv::drv_dispWriter(std::function<uint8_t(int)> f){ //单色刷新
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);
@@ -260,13 +257,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.

View File

@@ -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的
};

View File

@@ -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,
@@ -153,6 +161,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++)
@@ -198,15 +207,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);
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(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 +233,8 @@ void drv::drv_sleep() { //开始屏幕睡眠
guy_epdParam(0xA5);
EndTransfer();
}
Power_is_on=0;
part_mode=0;
}
}
#endif /* END OF FILE. ReadGuy project.

View File

@@ -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];
};

View File

@@ -70,9 +70,11 @@ 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;
@@ -157,7 +159,8 @@ void readguyEpdBase::Reset(uint32_t minTime)
}
//void readguyEpdBase::drv_draw16grey(const uint8_t *d16bit){ //不支持的话什么都不做
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o){
void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y,int o,
uint16_t fw, uint16_t fh){
#ifndef FLOYD_STEINBERG_DITHERING
static const uint8_t bayer_tab [64]={
0, 32, 8, 40, 2, 34, 10, 42,
@@ -170,30 +173,32 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
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; }
floyd_tab[0] = new int16_t [fw];
floyd_tab[1] = new int16_t [fw];
for(int j=0;j<fw;j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
#endif
writeBuff = new uint8_t[w];
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);
sprbase.fillRect(x,y,fw,fh,1);
for(int32_t i=y;i<(int32_t)fh+y;i++){
spr.readRect(0,(i-y)*spr.height()/fh,spr.width(),1,readBuff);
#ifdef FLOYD_STEINBERG_DITHERING
uint_fast8_t buff8bit=0;
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]));
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,23 +210,23 @@ 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;
for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
#else
for(int32_t j=0;j<w;j++){
uint_fast8_t buff8bit=0;
for(uint_fast8_t b=0;b<8;b++)
buff8bit |= (bayer_tab[(b<<3)|(i&7)]<(greysc(readBuff[(j<<3)+b])>>2))<<(7-b);
buff8bit |= (bayer_tab[(b<<3)|(i&7)]<(greysc(readBuff[j*spr.width()/fw])>>2))<<(7-b);
writeBuff[j]=buff8bit;
}
#endif
sprbase.drawBitmap(x,i,writeBuff,spr.width(),1,1,0);
sprbase.drawBitmap(x,i,writeBuff,fw,1,1,0);
}
//_display((const uint8_t*)sprbase.getBuffer()); //显示
if(o==0 || o==3){
@@ -234,19 +239,21 @@ void readguyEpdBase::drv_drawImage(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_
}
}
//不支持的话使用单色抖动刷屏
void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16_t x,uint16_t y){
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()];
floyd_tab[0] = new int16_t [fw];
floyd_tab[1] = new int16_t [fw];
#endif
}
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()); //先对区域慢刷白屏确保颜色正确
@@ -254,33 +261,31 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
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; }
if(_quality&2) for(int j=0;j<fw;j++){ floyd_tab[0][j] = 0; floyd_tab[1][j] = 0; }
#endif
for(int i=y;i<spr.height()+y;i++){
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{ cg=greysc(readBuff[j*spr.width()/fw])>>4; }
#else
uint_fast8_t cg=greysc(readBuff[j])>>4;
uint_fast8_t cg=greysc(readBuff[j*spr.width()/fw])>>4;
#endif
if(negativeOrder)
buff8bit |= (cg<k)<<((~j)&7);
@@ -288,17 +293,17 @@ void readguyEpdBase::drv_draw16grey(LGFX_Sprite &sprbase,LGFX_Sprite &spr,uint16
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;
if(_quality&2) for(int floi=0;floi<fw;floi++) floyd_tab[i&1][floi]=0;
#endif
sprbase.drawBitmap(x,i,writeBuff,spr.width(),1,1,0);
sprbase.drawBitmap(x,i,writeBuff,fw,1,1,0);
}
drv_draw16grey_step((const uint8_t*)sprbase.getBuffer(),k); //使用灰度显示函数
}

View File

@@ -97,8 +97,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);
}
@@ -113,6 +115,8 @@ public:
#ifdef MEPD_DEBUG_DISPLAY
friend class LGFX;
#endif
private:
int16_t guy_width=0,guy_height=0;
};
#endif /* END OF FILE. ReadGuy project.

View File

@@ -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 0
#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.0"
#ifdef ESP8266
#define _READGUY_PLATFORM "ESP8266"

View File

@@ -126,7 +126,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 &notify, const serveFunc *serveFuncs, int funcs){
//启动WiFi服务器端, 这样就可以进行配网工作
@@ -163,7 +163,7 @@ void ReadguyDriver::server_setup(const String &notify, 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());
}
@@ -218,7 +218,7 @@ 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)
@@ -280,7 +280,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,12 +304,13 @@ 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..."));
Serial.println(F("[Guy] Init details..."));
setTextSize(1);
drawCenterString(setSDcardDriver()?"SD Init OK!":"SD Init failed!",width()>>1,(height()>>1)+20);
setButtonDriver(); //初始化按钮..
//} //尝试初始化按键, 调用后, 若SD卡初始化成功, READGUY_sd_ok的值会变成1
@@ -321,7 +322,7 @@ void ReadguyDriver::handleInitPost(){
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(){
@@ -592,7 +593,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();

View File

@@ -48,8 +48,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/* ,int g_width,int g_height */){
if(READGUY_cali==127) //已经初始化过了一次了, 为了防止里面一些volatile的东西出现问题....还是退出吧
return 0;
#ifdef DYNAMIC_PIN_SETTINGS
@@ -77,7 +77,7 @@ 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();
setButtonDriver();
@@ -85,12 +85,12 @@ uint8_t ReadguyDriver::init(uint8_t WiFiSet){ //WiFiSet: 是否保持AP服务器
#endif
nvs_deinit();
#else
if(checkEpdDriver()!=127) setEpdDriver(); //初始化屏幕
if(checkEpdDriver()!=127) setEpdDriver(initepd/* ,g_width,g_height */); //初始化屏幕
else for(;;); //此处可能添加程序rollback等功能操作(比如返回加载上一个程序)
setSDcardDriver();
setButtonDriver();
#endif
Serial.println(F("init done."));
Serial.println(F("[Guy init] init done."));
READGUY_cali=127;
return READGUY_sd_ok;
}
@@ -101,7 +101,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++)
@@ -149,7 +149,7 @@ uint8_t ReadguyDriver::checkEpdDriver(){
case READGUY_DEV_270B: guy_dev = new guydev_154B_270B_290B ::dev270B; break;
#endif
default:
Serial.println(F("[ERR] EPD DRIVER IC NOT SUPPORTED!\n"));
Serial.println(F("[GUY ERR] EPD DRIVER IC NOT SUPPORTED!\n"));
return 127;
}
#if (defined(ESP8266))
@@ -169,26 +169,27 @@ 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/* ,int g_width,int g_height */){
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();
Serial.println(F("[Guy EPD] EPD init OK"));
//以下依赖于你的图形驱动
setColorDepth(1); //单色模式
createPalette(); //初始化颜色系统
Serial.printf_P(PSTR("mono set: w: %d, h: %d\n"),guy_width,guy_height);
Serial.printf_P(PSTR("[Guy EPD] mono set: w: %d, h: %d\n"),guy_dev->drv_width(),guy_dev->drv_height());
//创建画布. 根据LovyanGFX的特性, 如果以前有画布会自动重新生成新画布
//此外, 即使画布宽度不是8的倍数(如2.13寸单色),也支持自动补全8的倍数 ( 250x122 => 250x128 )
//为了保证图片显示功能的正常使用, 高度也必须是8的倍数.
createSprite(guy_width,(guy_height+7)&0x7ffffff8);
createSprite(guy_dev->drv_width(),(guy_dev->drv_height()+7)&0x7ffffff8);
//这里发现如果用自定义的内存分配方式会更好一些. 不会导致返回的height不对. 但是因为LovyanGFX库未更新 暂时不能这么用.
//setRotation(1); //旋转之后操作更方便
setRotation(0);
setFont(&fonts::Font0);
@@ -226,6 +227,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();
@@ -387,21 +389,22 @@ void ReadguyDriver::display(std::function<uint8_t(int)> f, bool part){
//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::drawImage(LGFX_Sprite &base, LGFX_Sprite &spr,uint16_t x,uint16_t y,uint16_t zoomw, uint16_t zoomh) {
if(READGUY_cali==127) guy_dev->drv_drawImage(base, spr, x, y, 0, zoomw, zoomh);
}
void ReadguyDriver::drawImageStage(LGFX_Sprite &spr,uint16_t x,uint16_t y,uint8_t stage,uint8_t totalstage) {
void ReadguyDriver::drawImageStage(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)));
guy_dev->drv_drawImage(*this, 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 +420,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]));
}
@@ -452,7 +455,7 @@ bool ReadguyDriver::nvs_read(){
if(i>=8) config_data[i-8] = rd;
else s[i]=(char)rd;
}
Serial.printf("Get NVS...%d\n", config_data[0]);
Serial.printf("[Guy NVS] Get NVS...%d\n", config_data[0]);
return !(strcmp_P(s,projname));
}
void ReadguyDriver::nvs_write(){

View File

@@ -149,7 +149,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
* 2:自动连接到已存的WiFi, 但不等待连接成功
* @return SD卡是否就绪
*/
uint8_t init(uint8_t WiFiSet = 0);
uint8_t init(uint8_t WiFiSet = 0,bool initepd = 1/* ,int g_width = 0,int g_height = 0 */);
/// @brief 设置显示亮度
void setBright(int d);
/// @brief 返回显示亮度
@@ -171,8 +171,12 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
* 该函数会将参数从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);
/// @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 +188,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) 的注释.
@@ -225,7 +229,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/* ,int g_width = 0,int g_height = 0 */);
/** @brief 初始化SD卡, 设置驱动代号, 引脚排列顺序. 过程会检验引脚可用性.
* @return SD卡初始化成功与否 */
bool setSDcardDriver();
@@ -261,7 +265,6 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
#endif
int epd_OK=0; //墨水屏可用
int currentBright = -3; //初始亮度
int16_t guy_width=0,guy_height=0;
//LGFX_Sprite gfx; // 图形引擎类指针, 可以用这个指针去操作屏幕缓冲区
readguyEpdBase *guy_dev = nullptr;
@@ -361,15 +364,18 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
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 memWidth () const { return guy_width ; } //返回显存宽度(不是画幅宽度),不会随着画布旋转改变
//constexpr int memHeight () const { return guy_height ; } //返回显存高度(不是画幅高度),不会随着画布旋转改变
int drvWidth () const { return READGUY_cali==127?guy_dev->drv_width():0; } //返回显示屏硬件宽度(不是画幅宽度)
int drvHeight() const { return READGUY_cali==127?guy_dev->drv_height():0; } //返回显示屏硬件高度(不是画幅高度)
int width () const { return READGUY_cali==127?((getRotation()&1)?drvHeight():drvWidth()):0; }
int height() const { return READGUY_cali==127?((getRotation()&1)?drvWidth():drvHeight()):0; }
// 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);
};
#endif /* END OF FILE. ReadGuy project.
Copyright (C) 2023 FriendshipEnder. */