/* xdsp_16_esp32_epaper_47.ino - LILIGO47 e-paper support for Tasmota Copyright (C) 2021 Theo Arends, Gerhard Mutz and LILIGO This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef ESP32 #ifdef USE_DISPLAY #ifdef USE_LILYGO47 #define XDSP_16 16 #define EPD47_BLACK 0 #define EPD47_WHITE 15 #include Epd47 *epd47; bool epd47_init_done = false; extern uint8_t color_type; extern uint16_t fg_color; extern uint16_t bg_color; /*********************************************************************************************/ void EpdInitDriver47(void) { if (PinUsed(GPIO_EPD_DATA)) { Settings->display_model = XDSP_16; if (Settings->display_width != EPD47_WIDTH) { Settings->display_width = EPD47_WIDTH; } if (Settings->display_height != EPD47_HEIGHT) { Settings->display_height = EPD47_HEIGHT; } // init renderer epd47 = new Epd47(Settings->display_width, Settings->display_height); epd47->Init(); renderer = epd47; renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font); renderer->setTextColor(EPD47_BLACK, EPD47_WHITE); #ifdef SHOW_SPLASH // Welcome text renderer->setTextFont(2); renderer->DrawStringAt(50, 50, "LILGO 4.7 E-Paper Display!", EPD47_BLACK, 0); renderer->Updateframe(); #endif fg_color = EPD47_BLACK; bg_color = EPD47_WHITE; color_type = COLOR_COLOR; #ifdef USE_TOUCH_BUTTONS // start digitizer EPD47_Touch_Init(); #endif // USE_TOUCH_BUTTONS epd47_init_done = true; AddLog(LOG_LEVEL_INFO, PSTR("DSP: E-Paper 4.7")); } } /*********************************************************************************************/ #ifdef USE_TOUCH_BUTTONS #define TOUCH_SLAVE_ADDRESS 0x5a class TouchClass { typedef struct { uint8_t id; uint8_t state; uint16_t x; uint16_t y; } TouchData_t; public: bool begin(TwoWire &port = Wire, uint8_t addr = TOUCH_SLAVE_ADDRESS); uint8_t scanPoint(); void getPoint(int16_t &x, int16_t &y, uint8_t index); // void sleep(void); // void wakeup(void); TouchData_t data[5]; private: void clearFlags(void); void readBytes(uint8_t *data, uint8_t nbytes); uint8_t _address; bool initialization = false; TwoWire *_i2cPort; }; void TouchClass::readBytes(uint8_t *data, uint8_t nbytes) { _i2cPort->beginTransmission(_address); // Initialize the Tx buffer _i2cPort->write(data, 2); // Put data in Tx buffer if (0 != _i2cPort->endTransmission()) { Serial.println("readBytes error!"); } uint8_t i = 0; _i2cPort->requestFrom(_address, nbytes); // Read bytes from slave register address while (_i2cPort->available()) { data[i++] = _i2cPort->read(); } } void TouchClass::clearFlags(void) { uint8_t buf[3] = {0xD0, 0X00, 0XAB}; _i2cPort->beginTransmission(_address); _i2cPort->write(buf, 3); _i2cPort->endTransmission(); } bool TouchClass::begin(TwoWire &port, uint8_t addr) { _i2cPort = &port; _address = addr; _i2cPort->beginTransmission(_address); if (0 == _i2cPort->endTransmission()) { // wakeup(); return true; } return false; } uint8_t TouchClass::scanPoint() { uint8_t point = 0; uint8_t buffer[40] = {0}; uint32_t sumL = 0, sumH = 0; buffer[0] = 0xD0; buffer[1] = 0x00; readBytes(buffer, 7); if (buffer[0] == 0xAB) { clearFlags(); return 0; } point = buffer[5] & 0xF; if (point == 1) { buffer[5] = 0xD0; buffer[6] = 0x07; readBytes( &buffer[5], 2); sumL = buffer[5] << 8 | buffer [6]; } else if (point > 1) { buffer[5] = 0xD0; buffer[6] = 0x07; readBytes( &buffer[5], 5 * (point - 1) + 3); sumL = buffer[5 * point + 1] << 8 | buffer[5 * point + 2]; } clearFlags(); for (int i = 0 ; i < 5 * point; ++i) { sumH += buffer[i]; } if (sumH != sumL) { point = 0; } if (point) { uint8_t offset; for (int i = 0; i < point; ++i) { if (i == 0) { offset = 0; } else { offset = 4; } data[i].id = (buffer[i * 5 + offset] >> 4) & 0x0F; data[i].state = buffer[i * 5 + offset] & 0x0F; if (data[i].state == 0x06) { data[i].state = 0x07; } else { data[i].state = 0x06; } data[i].y = (uint16_t)((buffer[i * 5 + 1 + offset] << 4) | ((buffer[i * 5 + 3 + offset] >> 4) & 0x0F)); data[i].x = (uint16_t)((buffer[i * 5 + 2 + offset] << 4) | (buffer[i * 5 + 3 + offset] & 0x0F)); } } else { point = 1; data[0].id = (buffer[0] >> 4) & 0x0F; data[0].state = 0x06; data[0].y = (uint16_t)((buffer[0 * 5 + 1] << 4) | ((buffer[0 * 5 + 3] >> 4) & 0x0F)); data[0].x = (uint16_t)((buffer[0 * 5 + 2] << 4) | (buffer[0 * 5 + 3] & 0x0F)); } // Serial.printf("X:%d Y:%d\n", data[0].x, data[0].y); return point; } void TouchClass::getPoint(int16_t &x, int16_t &y, uint8_t index) { if (index >= 4)return; x = data[index].x; y = data[index].y; } //if (touch.scanPoint()) { // touch.getPoint(x, y, 0); #define EPD47_address 0x5A TouchClass *EPD47_touchp; void EPD47_Touch_Init(void) { FT5206_found = false; EPD47_touchp = new TouchClass(); if (EPD47_touchp->begin(Wire, EPD47_address)) { I2cSetActiveFound(EPD47_address, "EPD47"); FT5206_found = true; } } uint8_t EPD47_ctouch_counter = 0; // no rotation support void EPD47_RotConvert(int16_t *x, int16_t *y) { int16_t temp; if (renderer) { uint8_t rot=renderer->getRotation(); switch (rot) { case 0: break; case 1: temp=*y; *y=renderer->height()-*x; *x=temp; break; case 2: *x=renderer->width()-*x; *y=renderer->height()-*y; break; case 3: temp=*y; *y=*x; *x=renderer->width()-temp; break; } } } // check digitizer hit void EPD47_CheckTouch(void) { EPD47_ctouch_counter++; if (2 == EPD47_ctouch_counter) { // every 100 ms should be enough EPD47_ctouch_counter = 0; touched = EPD47_touchp->scanPoint(); if (touched) { EPD47_touchp->getPoint(touch_xp, touch_yp, 0); EPD47_RotConvert(&touch_xp, &touch_yp); } //Touch_Check(EPD47_RotConvert); } } #endif // USE_TOUCH_BUTTONS /*********************************************************************************************\ * Interface \*********************************************************************************************/ bool Xdsp16(uint8_t function) { bool result = false; if (FUNC_DISPLAY_INIT_DRIVER == function) { EpdInitDriver47(); } else if (epd47_init_done && (XDSP_16 == Settings->display_model)) { switch (function) { case FUNC_DISPLAY_MODEL: result = true; break; #ifdef USE_TOUCH_BUTTONS case FUNC_DISPLAY_EVERY_50_MSECOND: if (FT5206_found) { EPD47_CheckTouch(); } break; #endif // USE_TOUCH_BUTTONS } } return result; } #endif // USE_LILYGO47 #endif // USE_DISPLAY #endif // ESP32