From 8906bbee10ae42372449f7fc69ac1161b73d1e52 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Sun, 5 Jan 2025 22:43:02 +0100 Subject: [PATCH] EPD single instance test --- src/lib/epd.cpp | 188 ++++++++++++++++++++++++------------------------ src/lib/epd.hpp | 6 +- 2 files changed, 96 insertions(+), 98 deletions(-) diff --git a/src/lib/epd.cpp b/src/lib/epd.cpp index fa389c6..a585afd 100644 --- a/src/lib/epd.cpp +++ b/src/lib/epd.cpp @@ -69,26 +69,7 @@ EPDManager::EPDManager() , fontSatsymbol{nullptr} , bgColor{GxEPD_BLACK} , fgColor{GxEPD_WHITE} - , displays{ - #ifdef IS_BTCLOCK_V8 - EPD_CLASS(&EPD_CS[0], &EPD_DC, &EPD_RESET[0], &EPD_BUSY[0]), - EPD_CLASS(&EPD_CS[1], &EPD_DC, &EPD_RESET[1], &EPD_BUSY[1]), - EPD_CLASS(&EPD_CS[2], &EPD_DC, &EPD_RESET[2], &EPD_BUSY[2]), - EPD_CLASS(&EPD_CS[3], &EPD_DC, &EPD_RESET[3], &EPD_BUSY[3]), - EPD_CLASS(&EPD_CS[4], &EPD_DC, &EPD_RESET[4], &EPD_BUSY[4]), - EPD_CLASS(&EPD_CS[5], &EPD_DC, &EPD_RESET[5], &EPD_BUSY[5]), - EPD_CLASS(&EPD_CS[6], &EPD_DC, &EPD_RESET[6], &EPD_BUSY[6]), - EPD_CLASS(&EPD_CS[7], &EPD_DC, &EPD_RESET[7], &EPD_BUSY[7]) - #else - EPD_CLASS(&EPD_CS[0], &EPD_DC, &EPD_RESET[0], &EPD_BUSY[0]), - EPD_CLASS(&EPD_CS[1], &EPD_DC, &EPD_RESET[1], &EPD_BUSY[1]), - EPD_CLASS(&EPD_CS[2], &EPD_DC, &EPD_RESET[2], &EPD_BUSY[2]), - EPD_CLASS(&EPD_CS[3], &EPD_DC, &EPD_RESET[3], &EPD_BUSY[3]), - EPD_CLASS(&EPD_CS[4], &EPD_DC, &EPD_RESET[4], &EPD_BUSY[4]), - EPD_CLASS(&EPD_CS[5], &EPD_DC, &EPD_RESET[5], &EPD_BUSY[5]), - EPD_CLASS(&EPD_CS[6], &EPD_DC, &EPD_RESET[6], &EPD_BUSY[6]) - #endif - } + , display{EPD_CLASS(&EPD_CS[0], &EPD_DC, &EPD_RESET[0], &EPD_BUSY[0])} { } @@ -119,11 +100,10 @@ void EPDManager::initialize() { String fontName = preferences.getString("fontName", DEFAULT_FONT_NAME); loadFonts(fontName); - // Initialize displays + // Initialize first display + switchToDisplay(0); std::lock_guard lockMcp(mcpMutex); - for (auto& display : displays) { - display.init(0, true, 30); - } + display.init(0, true, 30); // Create update queue and task updateQueue = xQueueCreate(UPDATE_QUEUE_SIZE, sizeof(UpdateDisplayTaskItem)); @@ -228,46 +208,48 @@ void EPDManager::waitUntilNoneBusy() { } void EPDManager::setupDisplay(uint dispNum, const GFXfont* font) { - displays[dispNum].setRotation(2); - displays[dispNum].setFont(font); - displays[dispNum].setTextColor(fgColor); - displays[dispNum].fillScreen(bgColor); + switchToDisplay(dispNum); + display.setRotation(2); + display.setFont(font); + display.setTextColor(fgColor); + display.fillScreen(bgColor); } void EPDManager::splitText(uint dispNum, const String& top, const String& bottom, bool partial) { + switchToDisplay(dispNum); if (preferences.getBool("verticalDesc", DEFAULT_VERTICAL_DESC) && dispNum == 0) { - displays[dispNum].setRotation(1); + display.setRotation(1); } else { - displays[dispNum].setRotation(2); + display.setRotation(2); } - displays[dispNum].setFont(fontSmall); - displays[dispNum].setTextColor(fgColor); + display.setFont(fontSmall); + display.setTextColor(fgColor); // Top text int16_t ttbx, ttby; uint16_t ttbw, ttbh; - displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh); - uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx; - uint16_t ty = ((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12; + display.getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh); + uint16_t tx = ((display.width() - ttbw) / 2) - ttbx; + uint16_t ty = ((display.height() - ttbh) / 2) - ttby - ttbh / 2 - 12; // Bottom text int16_t tbbx, tbby; uint16_t tbbw, tbbh; - displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh); - uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx; - uint16_t by = ((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12; + display.getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh); + uint16_t bx = ((display.width() - tbbw) / 2) - tbbx; + uint16_t by = ((display.height() - tbbh) / 2) - tbby + tbbh / 2 + 12; // Make separator as wide as the shortest text uint16_t lineWidth = (tbbw < ttbh) ? tbbw : ttbw; - uint16_t lineX = round((displays[dispNum].width() - lineWidth) / 2); + uint16_t lineX = round((display.width() - lineWidth) / 2); - displays[dispNum].fillScreen(bgColor); - displays[dispNum].setCursor(tx, ty); - displays[dispNum].print(top); - displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3, - lineWidth, 6, 3, fgColor); - displays[dispNum].setCursor(bx, by); - displays[dispNum].print(bottom); + display.fillScreen(bgColor); + display.setCursor(tx, ty); + display.print(top); + display.fillRoundRect(lineX, display.height() / 2 - 3, + lineWidth, 6, 3, fgColor); + display.setCursor(bx, by); + display.print(bottom); } void EPDManager::showDigit(uint dispNum, char chr, bool partial, const GFXfont* font) { @@ -280,17 +262,17 @@ void EPDManager::showDigit(uint dispNum, char chr, bool partial, const GFXfont* int16_t tbx, tby; uint16_t tbw, tbh; - displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh); + display.getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh); - uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx; - uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby; + uint16_t x = ((display.width() - tbw) / 2) - tbx; + uint16_t y = ((display.height() - tbh) / 2) - tby; - displays[dispNum].setCursor(x, y); - displays[dispNum].print(str); + display.setCursor(x, y); + display.print(str); if (chr == '.') { - displays[dispNum].fillRect(0, 0, displays[dispNum].width(), - round(displays[dispNum].height() * 0.67), bgColor); + display.fillRect(0, 0, display.width(), + round(display.height() * 0.67), bgColor); } } @@ -299,11 +281,11 @@ void EPDManager::showChars(uint dispNum, const String& chars, bool partial, cons int16_t tbx, tby; uint16_t tbw, tbh; - displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh); + display.getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh); // Center the bounding box by transposition of the origin - uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx; - uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby; + uint16_t x = ((display.width() - tbw) / 2) - tbx; + uint16_t y = ((display.height() - tbh) / 2) - tby; for (size_t i = 0; i < chars.length(); i++) { char c = chars[i]; @@ -313,12 +295,12 @@ void EPDManager::showChars(uint dispNum, const String& chars, bool partial, cons int16_t dotDescent = dotGlyph->yOffset; // Draw the dot with adjusted y-position - displays[dispNum].setCursor(x, y + dotDescent + dotGlyph->height + 8); - displays[dispNum].print(c); + display.setCursor(x, y + dotDescent + dotGlyph->height + 8); + display.print(c); } else { // For other characters, use the original y-position - displays[dispNum].setCursor(x, y); - displays[dispNum].print(c); + display.setCursor(x, y); + display.print(c); } // Move x-position for the next character @@ -327,11 +309,12 @@ void EPDManager::showChars(uint dispNum, const String& chars, bool partial, cons } bool EPDManager::renderIcon(uint dispNum, const String& text, bool partial) { - displays[dispNum].setRotation(2); - displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), - displays[dispNum].height()); - displays[dispNum].fillScreen(bgColor); - displays[dispNum].setTextColor(fgColor); + switchToDisplay(dispNum); + display.setRotation(2); + display.setPartialWindow(0, 0, display.width(), + display.height()); + display.fillScreen(bgColor); + display.setTextColor(fgColor); uint iconIndex = 0; uint width = 122; @@ -352,27 +335,28 @@ bool EPDManager::renderIcon(uint dispNum, const String& text, bool partial) { return false; } - int x_offset = (displays[dispNum].width() - logo.width) / 2; - int y_offset = (displays[dispNum].height() - logo.height) / 2; - displays[dispNum].drawInvertedBitmap(x_offset, y_offset, logo.data, - logo.width, logo.height, fgColor); + int x_offset = (display.width() - logo.width) / 2; + int y_offset = (display.height() - logo.height) / 2; + display.drawInvertedBitmap(x_offset, y_offset, logo.data, + logo.width, logo.height, fgColor); return true; } - int x_offset = (displays[dispNum].width() - width) / 2; - int y_offset = (displays[dispNum].height() - height) / 2; - displays[dispNum].drawInvertedBitmap(x_offset, y_offset, epd_icons_allArray[iconIndex], - width, height, fgColor); + int x_offset = (display.width() - width) / 2; + int y_offset = (display.height() - height) / 2; + display.drawInvertedBitmap(x_offset, y_offset, epd_icons_allArray[iconIndex], + width, height, fgColor); return true; } void EPDManager::renderText(uint dispNum, const String& text, bool partial) { - displays[dispNum].setRotation(2); - displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), - displays[dispNum].height()); - displays[dispNum].fillScreen(GxEPD_WHITE); - displays[dispNum].setTextColor(GxEPD_BLACK); - displays[dispNum].setCursor(0, 50); + switchToDisplay(dispNum); + display.setRotation(2); + display.setPartialWindow(0, 0, display.width(), + display.height()); + display.fillScreen(GxEPD_WHITE); + display.setTextColor(GxEPD_BLACK); + display.setCursor(0, 50); std::stringstream ss; ss.str(text.c_str()); @@ -381,16 +365,17 @@ void EPDManager::renderText(uint dispNum, const String& text, bool partial) { while (std::getline(ss, line, '\n')) { if (line.rfind("*", 0) == 0) { line.erase(std::remove(line.begin(), line.end(), '*'), line.end()); - displays[dispNum].setFont(&FreeSansBold9pt7b); + display.setFont(&FreeSansBold9pt7b); } else { - displays[dispNum].setFont(&FreeSans9pt7b); + display.setFont(&FreeSans9pt7b); } - displays[dispNum].println(line.c_str()); + display.println(line.c_str()); } } void EPDManager::renderQr(uint dispNum, const String& text, bool partial) { #ifdef USE_QR + switchToDisplay(dispNum); // Dynamically allocate QR buffer uint8_t* qrcode = (uint8_t*)malloc(qrcodegen_BUFFER_LEN_MAX); if (!qrcode) { @@ -405,17 +390,17 @@ void EPDManager::renderQr(uint dispNum, const String& text, bool partial) { if (ok) { const int size = qrcodegen_getSize(qrcode); - const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2); - const int paddingY = floor(float(displays[dispNum].height() - (size * 4)) / 2); + const int padding = floor(float(display.width() - (size * 4)) / 2); + const int paddingY = floor(float(display.height() - (size * 4)) / 2); - displays[dispNum].setRotation(2); - displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), - displays[dispNum].height()); - displays[dispNum].fillScreen(GxEPD_WHITE); + display.setRotation(2); + display.setPartialWindow(0, 0, display.width(), + display.height()); + display.fillScreen(GxEPD_WHITE); for (int y = 0; y < size * 4; y++) { for (int x = 0; x < size * 4; x++) { - displays[dispNum].drawPixel( + display.drawPixel( padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK @@ -449,10 +434,10 @@ void EPDManager::updateDisplayTask(void* pvParameters) noexcept { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); std::lock_guard lock(instance.displayMutexes[epdIndex]); - { - std::lock_guard lockMcp(mcpMutex); - instance.displays[epdIndex].init(0, false, 40); - } + + std::lock_guard lockMcp(mcpMutex); + instance.initializeDisplay(epdIndex); + uint32_t count = 0; while (instance.EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) { @@ -469,8 +454,8 @@ void EPDManager::updateDisplayTask(void* pvParameters) noexcept { char tries = 0; while (tries < 3) { - if (instance.displays[epdIndex].displayWithReturn(updatePartial)) { - instance.displays[epdIndex].powerOff(); + if (instance.display.displayWithReturn(updatePartial)) { + instance.display.powerOff(); instance.currentContent[epdIndex] = instance.content[epdIndex]; if (!updatePartial) { instance.lastFullRefresh[epdIndex] = millis(); @@ -534,4 +519,15 @@ void EPDManager::prepareDisplayUpdateTask(void* pvParameters) { xTaskNotifyGive(instance.tasks[epdIndex]); } } -} \ No newline at end of file +} + +void EPDManager::switchToDisplay(uint dispNum) { + display.setCSPin(&EPD_CS[dispNum]); + display.setRSTPin(&EPD_RESET[dispNum]); + display.setBusyPin(&EPD_BUSY[dispNum]); +} + +void EPDManager::initializeDisplay(uint dispNum) { + switchToDisplay(dispNum); + display.init(0, false, 40); +} diff --git a/src/lib/epd.hpp b/src/lib/epd.hpp index 80bed83..1022cd2 100644 --- a/src/lib/epd.hpp +++ b/src/lib/epd.hpp @@ -80,6 +80,8 @@ private: static void updateDisplayTask(void* pvParameters) noexcept; static void prepareDisplayUpdateTask(void* pvParameters); + void switchToDisplay(uint dispNum); + void initializeDisplay(uint dispNum); // Member variables std::array currentContent; @@ -119,8 +121,8 @@ private: static std::array EPD_RESET; #endif - // Display array - std::array, NUM_SCREENS> displays; + // Single display instance + GxEPD2_BW display; static constexpr size_t UPDATE_QUEUE_SIZE = 14; static constexpr uint32_t BUSY_TIMEOUT_COUNT = 200;