Files
OpenEPaperLink/ESP32_AP-Flasher/src/ips_display.cpp
2025-03-25 10:02:39 -07:00

547 lines
16 KiB
C++

#include <Arduino.h>
#include <FS.h>
#include <WiFi.h>
#include "commstructs.h"
#include "newproto.h"
#include "storage.h"
#include "tag_db.h"
#ifdef HAS_TFT
#include "ips_display.h"
#define YELLOW_SENSE 8 // sense AP hardware
#ifdef HAS_ELECROW_ADV_2_8
#define TFT_BACKLIGHT 38
#else
#define TFT_BACKLIGHT 14
#endif
TFT_eSPI tft2 = TFT_eSPI();
uint8_t YellowSense = 0;
bool tftLogscreen = true;
bool tftOverride = false;
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
#if defined HAS_LILYGO_TPANEL
static const uint8_t st7701_type9_init_operations_lilygo[] = {
BEGIN_WRITE,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
WRITE_C8_D8, 0xEF, 0x08,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
WRITE_C8_D16, 0xC1, 0x0B, 0x02,
WRITE_COMMAND_8, 0xC2,
WRITE_BYTES, 3, 0x30, 0x02, 0x37,
WRITE_C8_D8, 0xCC, 0x10,
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x0F, 0x16, 0x0E,
0x11, 0x07, 0x09, 0x09,
0x08, 0x23, 0x05, 0x11,
0x0F, 0x28, 0x2D, 0x18,
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x0F, 0x16, 0x0E,
0x11, 0x07, 0x09, 0x08,
0x09, 0x23, 0x05, 0x11,
0x0F, 0x28, 0x2D, 0x18,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
WRITE_C8_D8, 0xB0, 0x4D,
WRITE_C8_D8, 0xB1, 0x33,
WRITE_C8_D8, 0xB2, 0x87,
WRITE_C8_D8, 0xB5, 0x4B,
WRITE_C8_D8, 0xB7, 0x8C,
WRITE_C8_D8, 0xB8, 0x20,
WRITE_C8_D8, 0xC1, 0x78,
WRITE_C8_D8, 0xC2, 0x78,
WRITE_C8_D8, 0xD0, 0x88,
WRITE_COMMAND_8, 0xE0,
WRITE_BYTES, 3, 0x00, 0x00, 0x02,
WRITE_COMMAND_8, 0xE1,
WRITE_BYTES, 11,
0x02, 0xF0, 0x00, 0x00,
0x03, 0xF0, 0x00, 0x00,
0x00, 0x44, 0x44,
WRITE_COMMAND_8, 0xE2,
WRITE_BYTES, 12,
0x10, 0x10, 0x40, 0x40,
0xF2, 0xF0, 0x00, 0x00,
0xF2, 0xF0, 0x00, 0x00,
WRITE_COMMAND_8, 0xE3,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE4, 0x44, 0x44,
WRITE_COMMAND_8, 0xE5,
WRITE_BYTES, 16,
0x07, 0xEF, 0xF0, 0xF0,
0x09, 0xF1, 0xF0, 0xF0,
0x03, 0xF3, 0xF0, 0xF0,
0x05, 0xED, 0xF0, 0xF0,
WRITE_COMMAND_8, 0xE6,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE7, 0x44, 0x44,
WRITE_COMMAND_8, 0xE8,
WRITE_BYTES, 16,
0x08, 0xF0, 0xF0, 0xF0,
0x0A, 0xF2, 0xF0, 0xF0,
0x04, 0xF4, 0xF0, 0xF0,
0x06, 0xEE, 0xF0, 0xF0,
WRITE_COMMAND_8, 0xEB,
WRITE_BYTES, 7,
0x00, 0x00, 0xE4, 0xE4,
0x44, 0x88, 0x40,
WRITE_C8_D16, 0xEC, 0x78, 0x00,
WRITE_COMMAND_8, 0xED,
WRITE_BYTES, 16,
0x20, 0xF9, 0x87, 0x76,
0x65, 0x54, 0x4F, 0xFF,
0xFF, 0xF4, 0x45, 0x56,
0x67, 0x78, 0x9F, 0x02,
WRITE_COMMAND_8, 0xEF,
WRITE_BYTES, 6,
0x10, 0x0D, 0x04, 0x08,
0x3F, 0x1F,
// WRITE_C8_D8, 0xCD, 0x05,//Test
WRITE_C8_D8, 0x3A, 0x55,
WRITE_C8_D8, 0x36, 0x08,
WRITE_COMMAND_8, 0x11,
// WRITE_COMMAND_8, 0xFF,//Test
// WRITE_BYTES, 5,
// 0x77, 0x01, 0x00, 0x00,
// 0x12,
// WRITE_C8_D8, 0xD1, 0x81,//Test
// WRITE_C8_D8, 0xD2, 0x08,//Test
WRITE_COMMAND_8, 0x29, // Display On
// WRITE_C8_D8, 0x35, 0x00,//Test
// WRITE_C8_D8, 0xCE, 0x04,//Test
// WRITE_COMMAND_8, 0xF2,//Test
// WRITE_BYTES, 4,
// 0xF0, 0xA3, 0xA3, 0x71,
END_WRITE};
Arduino_DataBus* bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
XL95X5_CS /* XL CS */, XL95X5_SCLK /* XL SCK */, XL95X5_MOSI /* XL MOSI */);
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true /* useBigEndian */,
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
#else
static const uint8_t st7701_4848S040_init[] = {
BEGIN_WRITE,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
WRITE_C8_D16, 0xC1, 0x0D, 0x02,
WRITE_C8_D16, 0xC2, 0x31, 0x05,
WRITE_C8_D8, 0xCD, 0x00, // 0xCD, 0x08 !!
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08,
0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08,
0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18,
// PAGE1
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
WRITE_C8_D8, 0xB0, 0x60, // Vop=4.7375v
WRITE_C8_D8, 0xB1, 0x32, // VCOM=32
WRITE_C8_D8, 0xB2, 0x07, // VGH=15v
WRITE_C8_D8, 0xB3, 0x80,
WRITE_C8_D8, 0xB5, 0x49, // VGL=-10.17v
WRITE_C8_D8, 0xB7, 0x85,
WRITE_C8_D8, 0xB8, 0x21, // AVDD=6.6 & AVCL=-4.6
WRITE_C8_D8, 0xC1, 0x78,
WRITE_C8_D8, 0xC2, 0x78,
WRITE_COMMAND_8, 0xE0,
WRITE_BYTES, 3, 0x00, 0x1B, 0x02,
WRITE_COMMAND_8, 0xE1,
WRITE_BYTES, 11,
0x08, 0xA0, 0x00, 0x00,
0x07, 0xA0, 0x00, 0x00,
0x00, 0x44, 0x44,
WRITE_COMMAND_8, 0xE2,
WRITE_BYTES, 12,
0x11, 0x11, 0x44, 0x44,
0xED, 0xA0, 0x00, 0x00,
0xEC, 0xA0, 0x00, 0x00,
WRITE_COMMAND_8, 0xE3,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE4, 0x44, 0x44,
WRITE_COMMAND_8, 0xE5,
WRITE_BYTES, 16,
0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0,
0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0,
WRITE_COMMAND_8, 0xE6,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE7, 0x44, 0x44,
WRITE_COMMAND_8, 0xE8,
WRITE_BYTES, 16,
0x09, 0xE8, 0xD8, 0xA0,
0x0B, 0xEA, 0xD8, 0xA0,
0x0D, 0xEC, 0xD8, 0xA0,
0x0F, 0xEE, 0xD8, 0xA0,
WRITE_COMMAND_8, 0xEB,
WRITE_BYTES, 7, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40,
WRITE_C8_D16, 0xEC, 0x3C, 0x00,
WRITE_COMMAND_8, 0xED,
WRITE_BYTES, 16,
0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA,
//-----------VAP & VAN---------------
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
WRITE_C8_D8, 0xE5, 0xE4,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x00,
// WRITE_COMMAND_8, 0x21, // 0x20 normal, 0x21 IPS !!
WRITE_C8_D8, 0x3A, 0x50, // 0x70 RGB888, 0x60 RGB666, 0x50 RGB565
WRITE_COMMAND_8, 0x11, // Sleep Out
END_WRITE,
DELAY, 120,
BEGIN_WRITE,
WRITE_COMMAND_8, 0x29, // Display On
END_WRITE};
Arduino_DataBus* bus = new Arduino_SWSPI(
GFX_NOT_DEFINED /* DC */, SPI_LCD_CS /* CS */, SPI_LCD_SCLK /* SCK */, SPI_LCD_MOSI /* MOSI */, GFX_NOT_DEFINED /* MISO */);
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
LCD_DE /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
LCD_R0 /* B0 */, LCD_R1 /* B1 */, LCD_R2 /* B2 */, LCD_R3 /* B3 */, LCD_R4 /* B4 */,
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
LCD_B0 /* R0 */, LCD_B1 /* R1 */, LCD_B2 /* R2 */, LCD_B3 /* R3 */, LCD_B4 /* R4 */,
1 /* hsync_polarity */, 10 /* hsync_front_porch */, 8 /* hsync_pulse_width */, 50 /* hsync_back_porch */,
1 /* vsync_polarity */, 10 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 20 /* vsync_back_porch */,
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true);
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
bus, -1 /* RST */, st7701_4848S040_init, sizeof(st7701_4848S040_init));
#endif
#endif
#if defined HAS_GT911_TOUCH
#include <Wire.h>
#include <Touch_GT911.h>
#define TOUCH_GT911_SCL 45
#define TOUCH_GT911_SDA 19
int touch_last_x = 0, touch_last_y = 0;
uint32_t last_touch_read = 0;
uint8_t is_new_touch_checked = false;
Touch_GT911 ts = Touch_GT911(TOUCH_GT911_SDA, TOUCH_GT911_SCL, max(480, 0), max(480, 0));
void touch_init()
{
ts.begin();
}
void touch_loop()
{
if (millis() - last_touch_read >= 50) {
last_touch_read = millis();
ts.read();
if (ts.isTouched)
{
touch_last_x = map(ts.points[0].x, 480, 0, 0, 480 - 1);
touch_last_y = map(ts.points[0].y, 480, 0, 0, 480 - 1);
Serial.printf("Touch position X: %i Y: %i\r\n", touch_last_x, touch_last_y);
if(is_new_touch_checked == false)
{
is_new_touch_checked = true;
if(touch_last_x <= 240)
sendAvail(WAKEUP_REASON_BUTTON1);
else
sendAvail(WAKEUP_REASON_BUTTON2);
}
}else{
is_new_touch_checked = false;
}
}
}
#else
void touch_init()
{
}
void touch_loop()
{
}
#endif
void TFTLog(String text) {
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
gfx->setTextSize(2);
if (tftLogscreen == false) {
gfx->fillScreen(BLACK);
gfx->setCursor(0, 0);
tftLogscreen = true;
}
if (text.isEmpty()) return;
gfx->setTextColor(WHITE);
gfx->println(text);
#else
if (tftLogscreen == false) {
tft2.fillScreen(TFT_BLACK);
tft2.setCursor(0, 0, (tft2.width() == 160 ? 1 : 2));
tftLogscreen = true;
} else {
if (tft2.width() == 160) tft2.setCursor(0, tft2.getCursorY(), 1);
}
if (text.isEmpty()) return;
tft2.setTextColor(TFT_SILVER);
if (text.startsWith("!")) {
tft2.setTextColor(TFT_RED);
text = text.substring(1);
} else if (text.indexOf("http") != -1) {
int httpIndex = text.indexOf("http");
tft2.print(text.substring(0, httpIndex));
tft2.setTextColor(TFT_YELLOW);
if (tft2.width() == 160) {
tft2.setCursor(0, tft2.getCursorY() + 8, 2);
text = text.substring(httpIndex + 7);
} else {
text = text.substring(httpIndex);
}
} else if (text.indexOf(":") != -1) {
int colonIndex = text.indexOf(":");
tft2.setTextColor(TFT_SILVER);
tft2.print(text.substring(0, colonIndex + 1));
tft2.setTextColor(TFT_WHITE);
if (tft2.width() == 160) tft2.setCursor(0, tft2.getCursorY() + 8, 2);
text = text.substring(colonIndex + 1);
} else if (text.endsWith("!")) {
tft2.setTextColor(TFT_GREEN);
}
tft2.println(text);
#endif
}
int32_t findId(uint8_t mac[8]) {
for (uint32_t c = 0; c < tagDB.size(); c++) {
tagRecord* tag = tagDB.at(c);
if (memcmp(tag->mac, mac, 8) == 0 && tag->version == 0) {
return c;
}
}
return -1;
}
void sendAvail(uint8_t wakeupReason) {
struct espAvailDataReq eadr = {0};
uint8_t mac[6];
WiFi.macAddress(mac);
memcpy(&eadr.src, mac, 6);
eadr.adr.lastPacketRSSI = WiFi.RSSI();
eadr.adr.currentChannel = config.channel;
#ifdef TFT_HW_TYPE
eadr.adr.hwType = TFT_HW_TYPE;
#elif defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
eadr.adr.hwType = 0xE2;
#else
eadr.adr.hwType = (tft2.width() == 160 ? 0xE1 : 0xE0);
#endif
eadr.adr.wakeupReason = wakeupReason;
eadr.adr.capabilities = 0;
eadr.adr.tagSoftwareVersion = 0;
eadr.adr.customMode = 0;
processDataReq(&eadr, true);
}
void yellow_ap_display_init(void) {
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
tftLogscreen = true;
pinMode(LCD_BL, OUTPUT);
digitalWrite(LCD_BL, HIGH);
#if ESP_ARDUINO_VERSION_MAJOR == 2
ledcAttachPin(LCD_BL, 1);
ledcSetup(1, 1000, 8);
ledcWrite(1, config.tft); // brightness
#else
ledcAttachChannel(LCD_BL, 1000, 8, 1);
ledcWriteChannel(1, config.tft);
#endif
#if defined HAS_LILYGO_TPANEL
Wire.begin(IIC_SDA, IIC_SCL);
#endif
gfx->begin();
gfx->fillScreen(BLACK);
#else
#ifdef HAS_ELECROW_C6
YellowSense = 0;
#else
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
vTaskDelay(100 / portTICK_PERIOD_MS);
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
#endif
pinMode(TFT_BACKLIGHT, OUTPUT);
digitalWrite(TFT_BACKLIGHT, LOW);
tft2.init();
#ifdef ST7735_NANO_TLSR
YellowSense = 0;
tft2.setRotation(1);
#else
tft2.setRotation(YellowSense == 1 ? 1 : 3);
#endif
tft2.fillScreen(TFT_BLACK);
tft2.setCursor(12, 0, (tft2.width() == 160 ? 1 : 2));
tft2.setTextColor(TFT_WHITE);
tftLogscreen = true;
#if ESP_ARDUINO_VERSION_MAJOR == 2
ledcSetup(1, 5000, 8);
ledcAttachPin(TFT_BACKLIGHT, 1);
ledcWrite(1, config.tft);
if (tft2.width() == 160) {
GPIO.func_out_sel_cfg[TFT_BACKLIGHT].inv_sel = 1;
}
#else
ledcAttachChannel(TFT_BACKLIGHT, 5000, 8, 1);
ledcWriteChannel(1, config.tft);
if (tft2.width() == 160) ledcOutputInvert(TFT_BACKLIGHT, true);
#endif
#endif
touch_init();
}
void yellow_ap_display_loop(void) {
static bool first_run = 0;
static time_t last_checkin = 0;
static time_t last_update = 0;
if (millis() - last_checkin >= 60000) {
sendAvail(0);
last_checkin = millis();
tftLogscreen = false;
}
if (first_run == 0) {
sendAvail(0xFC);
first_run = 1;
}
if (millis() - last_update >= 3000) {
uint8_t wifimac[8];
WiFi.macAddress(wifimac);
memset(&wifimac[6], 0, 2);
tagRecord* tag = tagRecord::findByMAC(wifimac);
if (tag == nullptr) {
last_update = millis();
return;
}
if (tag->pendingCount > 0 && tftOverride == false) {
String filename = tag->filename;
fs::File file = contentFS->open(filename);
if (!file) {
Serial.print("No current file. Canceling request\r\n");
prepareCancelPending(tag->mac);
return;
}
TFT_eSprite spr = TFT_eSprite(&tft2);
spr.setColorDepth(16);
if (tag->len == tft2.width() * tft2.height()) spr.setColorDepth(8);
spr.createSprite(tft2.width(), tft2.height());
void* spriteData = spr.getPointer();
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
file.close();
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
long dy = spr.height();
long dx = spr.width();
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData));
gfx->draw16bitRGBBitmap(0, 0, (uint16_t*)spriteData, dx, dy);
spr.deleteSprite();
#else
spr.pushSprite(0, 0);
#endif
tftLogscreen = false;
struct espXferComplete xfc = {0};
memcpy(xfc.src, tag->mac, 8);
processXferComplete(&xfc, true);
}
last_update = millis();
}
touch_loop();
}
#endif