From 13c8e67b4c850aad5541dfc71217ce086a81d5b4 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Mon, 30 Dec 2024 00:53:50 +0100 Subject: [PATCH] More efficient handling of multiple fonts, restore data bugfix --- data | 2 +- src/fonts/fonts.hpp | 26 +++++++++ src/lib/epd.cpp | 114 ++++++++++--------------------------- src/lib/epd.hpp | 2 +- src/lib/price_notify.cpp | 31 ++++++++-- src/lib/price_notify.hpp | 3 +- src/lib/screen_handler.cpp | 1 + src/lib/shared.hpp | 10 ++++ src/lib/webserver.cpp | 1 + 9 files changed, 96 insertions(+), 94 deletions(-) diff --git a/data b/data index 48e585d..0041ec3 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 48e585d4ec12bbc441499936d7cbf53d4307b9ec +Subproject commit 0041ec3d9a174955383836bba02caf79f3961072 diff --git a/src/fonts/fonts.hpp b/src/fonts/fonts.hpp index a1f03bd..8f66032 100644 --- a/src/fonts/fonts.hpp +++ b/src/fonts/fonts.hpp @@ -15,9 +15,35 @@ struct FontData { const uint8_t yAdvance; }; +// Font name constants +namespace FontNames { + static const String ANTONIO = "antonio"; + static const String OSWALD = "oswald"; + + static const std::array AVAILABLE_FONTS = { + ANTONIO, + OSWALD + }; + + static const std::array& getAvailableFonts() { + return AVAILABLE_FONTS; + } +} class FontLoader { public: + static GFXfont* loadCompressedFont(const FontData& fontData) { + return loadCompressedFont( + fontData.compressedData, + fontData.glyphs, + fontData.compressedSize, + fontData.originalSize, + fontData.first, + fontData.last, + fontData.yAdvance + ); + } + static GFXfont* loadCompressedFont( const uint8_t* compressedData, const GFXglyph* glyphs, diff --git a/src/lib/epd.cpp b/src/lib/epd.cpp index cca11a7..31fbf86 100644 --- a/src/lib/epd.cpp +++ b/src/lib/epd.cpp @@ -161,73 +161,21 @@ void forceFullRefresh() GFXfont font90; -void setupDisplays() -{ - String fontName = preferences.getString("fontName", DEFAULT_FONT_NAME); // Default to antonio - - if (fontName == "antonio") - { +void loadFonts(const String& fontName) { + if (fontName == FontNames::ANTONIO) { // Load Antonio fonts - antonioFonts.big = FontLoader::loadCompressedFont( - Antonio_SemiBold90pt7b_Properties.compressedData, - Antonio_SemiBold90pt7b_Properties.glyphs, - Antonio_SemiBold90pt7b_Properties.compressedSize, - Antonio_SemiBold90pt7b_Properties.originalSize, - Antonio_SemiBold90pt7b_Properties.first, - Antonio_SemiBold90pt7b_Properties.last, - Antonio_SemiBold90pt7b_Properties.yAdvance); - - antonioFonts.medium = FontLoader::loadCompressedFont( - Antonio_SemiBold40pt7b_Properties.compressedData, - Antonio_SemiBold40pt7b_Properties.glyphs, - Antonio_SemiBold40pt7b_Properties.compressedSize, - Antonio_SemiBold40pt7b_Properties.originalSize, - Antonio_SemiBold40pt7b_Properties.first, - Antonio_SemiBold40pt7b_Properties.last, - Antonio_SemiBold40pt7b_Properties.yAdvance); - - antonioFonts.small = FontLoader::loadCompressedFont( - Antonio_SemiBold20pt7b_Properties.compressedData, - Antonio_SemiBold20pt7b_Properties.glyphs, - Antonio_SemiBold20pt7b_Properties.compressedSize, - Antonio_SemiBold20pt7b_Properties.originalSize, - Antonio_SemiBold20pt7b_Properties.first, - Antonio_SemiBold20pt7b_Properties.last, - Antonio_SemiBold20pt7b_Properties.yAdvance); + antonioFonts.big = FontLoader::loadCompressedFont(Antonio_SemiBold90pt7b_Properties); + antonioFonts.medium = FontLoader::loadCompressedFont(Antonio_SemiBold40pt7b_Properties); + antonioFonts.small = FontLoader::loadCompressedFont(Antonio_SemiBold20pt7b_Properties); FONT_BIG = antonioFonts.big; FONT_MEDIUM = antonioFonts.medium; FONT_SMALL = antonioFonts.small; - } - else if (fontName == "oswald") - { + } else if (fontName == FontNames::OSWALD) { // Load Oswald fonts - oswaldFonts.big = FontLoader::loadCompressedFont( - Oswald_Medium80pt7b_Properties.compressedData, - Oswald_Medium80pt7b_Properties.glyphs, - Oswald_Medium80pt7b_Properties.compressedSize, - Oswald_Medium80pt7b_Properties.originalSize, - Oswald_Medium80pt7b_Properties.first, - Oswald_Medium80pt7b_Properties.last, - Oswald_Medium80pt7b_Properties.yAdvance); - - oswaldFonts.medium = FontLoader::loadCompressedFont( - Oswald_Medium30pt7b_Properties.compressedData, - Oswald_Medium30pt7b_Properties.glyphs, - Oswald_Medium30pt7b_Properties.compressedSize, - Oswald_Medium30pt7b_Properties.originalSize, - Oswald_Medium30pt7b_Properties.first, - Oswald_Medium30pt7b_Properties.last, - Oswald_Medium30pt7b_Properties.yAdvance); - - oswaldFonts.small = FontLoader::loadCompressedFont( - Oswald_Medium20pt7b_Properties.compressedData, - Oswald_Medium20pt7b_Properties.glyphs, - Oswald_Medium20pt7b_Properties.compressedSize, - Oswald_Medium20pt7b_Properties.originalSize, - Oswald_Medium20pt7b_Properties.first, - Oswald_Medium20pt7b_Properties.last, - Oswald_Medium20pt7b_Properties.yAdvance); + oswaldFonts.big = FontLoader::loadCompressedFont(Oswald_Medium80pt7b_Properties); + oswaldFonts.medium = FontLoader::loadCompressedFont(Oswald_Medium30pt7b_Properties); + oswaldFonts.small = FontLoader::loadCompressedFont(Oswald_Medium20pt7b_Properties); FONT_BIG = oswaldFonts.big; FONT_MEDIUM = oswaldFonts.medium; @@ -235,53 +183,49 @@ void setupDisplays() } FONT_SATSYMBOL = &Satoshi_Symbol90pt7b; +} +void setupDisplays() { + // Load fonts based on preference + String fontName = preferences.getString("fontName", DEFAULT_FONT_NAME); + loadFonts(fontName); + + // Initialize displays std::lock_guard lockMcp(mcpMutex); - - for (uint i = 0; i < NUM_SCREENS; i++) - { + for (uint i = 0; i < NUM_SCREENS; i++) { displays[i].init(0, true, 30); } + // Create update queue and task updateQueue = xQueueCreate(UPDATE_QUEUE_SIZE, sizeof(UpdateDisplayTaskItem)); - xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", EPD_TASK_STACK_SIZE * 2, NULL, 11, NULL); - for (uint i = 0; i < NUM_SCREENS; i++) - { + // Create display update tasks + for (uint i = 0; i < NUM_SCREENS; i++) { int *taskParam = new int; *taskParam = i; - - xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), EPD_TASK_STACK_SIZE, taskParam, - 11, &tasks[i]); // create task + xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), EPD_TASK_STACK_SIZE, taskParam, 11, &tasks[i]); } - // Hold lower button to enable "storage mode" (prevents burn-in of ePaper displays) - if (mcp1.read1(0) == LOW) - { + // Check for storage mode (prevents burn-in) + if (mcp1.read1(0) == LOW) { setFgColor(GxEPD_BLACK); setBgColor(GxEPD_WHITE); - epdContent.fill(""); - } - else - { - // Get custom text from preferences or use default "BTCLOCK" + } else { + // Initialize with custom text or default String customText = preferences.getString("displayText", DEFAULT_BOOT_TEXT); - - // Initialize array with spaces std::array newContent; newContent.fill(" "); - // Fill in the custom text, truncating if longer than NUM_SCREENS for (size_t i = 0; i < std::min(customText.length(), (size_t)NUM_SCREENS); i++) { - newContent[i] = String(customText[i]); + newContent[i] = String(customText[i]); } epdContent = newContent; } - setEpdContent(epdContent); + setEpdContent(epdContent); } void setEpdContent(std::array newEpdContent) @@ -527,8 +471,8 @@ void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font) if (chr == '.') { - displays[dispNum].fillRect(x, y, displays[dispNum].width(), - round(displays[dispNum].height() * 0.9), getBgColor()); + displays[dispNum].fillRect(0, 0, displays[dispNum].width(), + round(displays[dispNum].height() * 0.67), getBgColor()); } } diff --git a/src/lib/epd.hpp b/src/lib/epd.hpp index 1825189..4796776 100644 --- a/src/lib/epd.hpp +++ b/src/lib/epd.hpp @@ -31,7 +31,6 @@ #ifdef USE_QR #include "qrcodegen.h" #endif -// extern TaskHandle_t epdTaskHandle; typedef struct { char dispNum; @@ -39,6 +38,7 @@ typedef struct { void forceFullRefresh(); void setupDisplays(); +void loadFonts(const String& fontName); void splitText(const uint dispNum, const String &top, const String &bottom, bool partial); diff --git a/src/lib/price_notify.cpp b/src/lib/price_notify.cpp index 0d56a90..2c6fe94 100644 --- a/src/lib/price_notify.cpp +++ b/src/lib/price_notify.cpp @@ -110,15 +110,17 @@ void processNewPrice(uint newPrice, char currency) if (lastUpdateMap.find(currency) == lastUpdateMap.end() || (currentTime - lastUpdateMap[currency]) > minSecPriceUpd) { - // const unsigned long oldPrice = currentPrice; currencyMap[currency] = newPrice; - if (currency == CURRENCY_USD && ( lastUpdateMap[currency] == 0 || - (currentTime - lastUpdateMap[currency]) > 120)) + + // Store price in preferences if enough time has passed + if (lastUpdateMap[currency] == 0 || (currentTime - lastUpdateMap[currency]) > 120) { - preferences.putUInt("lastPrice", currentPrice); + String prefKey = String("lastPrice_") + getCurrencyCode(currency).c_str(); + preferences.putUInt(prefKey.c_str(), newPrice); } + lastUpdateMap[currency] = currentTime; - // if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) { + if (workQueue != nullptr && (ScreenHandler::getCurrentScreen() == SCREEN_BTC_TICKER || ScreenHandler::getCurrentScreen() == SCREEN_SATS_PER_CURRENCY || ScreenHandler::getCurrentScreen() == SCREEN_MARKET_CAP)) @@ -126,7 +128,24 @@ void processNewPrice(uint newPrice, char currency) WorkItem priceUpdate = {TASK_PRICE_UPDATE, currency}; xQueueSend(workQueue, &priceUpdate, portMAX_DELAY); } - //} + } +} + +void loadStoredPrices() +{ + // Load prices for all supported currencies + std::vector currencies = getAvailableCurrencies(); + + for (const std::string ¤cy : currencies) { + // Get first character as the currency identifier + String prefKey = String("lastPrice_") + currency.c_str(); + uint storedPrice = preferences.getUInt(prefKey.c_str(), 0); + + if (storedPrice > 0) { + currencyMap[getCurrencyChar(currency)] = storedPrice; + // Initialize lastUpdateMap to 0 so next update will store immediately + lastUpdateMap[getCurrencyChar(currency)] = 0; + } } } diff --git a/src/lib/price_notify.hpp b/src/lib/price_notify.hpp index 4aad356..3591d40 100644 --- a/src/lib/price_notify.hpp +++ b/src/lib/price_notify.hpp @@ -27,4 +27,5 @@ void stopPriceNotify(); void restartPriceNotify(); bool getPriceNotifyInit(); -uint getLastPriceUpdate(char currency); \ No newline at end of file +uint getLastPriceUpdate(char currency); +void loadStoredPrices(); \ No newline at end of file diff --git a/src/lib/screen_handler.cpp b/src/lib/screen_handler.cpp index f837e5e..4d8d1b9 100644 --- a/src/lib/screen_handler.cpp +++ b/src/lib/screen_handler.cpp @@ -321,6 +321,7 @@ void taskScreenRotate(void *pvParameters) { void setupTasks() { workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem)); + loadStoredPrices(); xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY, &workerTaskHandle); diff --git a/src/lib/shared.hpp b/src/lib/shared.hpp index adbbe5e..78fb9ea 100644 --- a/src/lib/shared.hpp +++ b/src/lib/shared.hpp @@ -97,6 +97,16 @@ namespace ArduinoJson { array.add(item); } }; + + template + struct Converter> { + static void toJson(const std::array& src, JsonVariant dst) { + JsonArray array = dst.to(); + for (const String& item : src) { + array.add(item); + } + } + }; } class HttpHelper { diff --git a/src/lib/webserver.cpp b/src/lib/webserver.cpp index 539fb17..c2bc86a 100644 --- a/src/lib/webserver.cpp +++ b/src/lib/webserver.cpp @@ -676,6 +676,7 @@ void onApiSettingsGet(AsyncWebServerRequest *request) root["nostrZapPubkey"] = preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY); root["ledFlashOnZap"] = preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP); root["fontName"] = preferences.getString("fontName", DEFAULT_FONT_NAME); + root["availableFonts"] = FontNames::getAvailableFonts(); // Custom endpoint settings (only used for CUSTOM_SOURCE) root["customEndpoint"] = preferences.getString("customEndpoint", DEFAULT_CUSTOM_ENDPOINT); root["customEndpointDisableSSL"] = preferences.getBool("customEndpointDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);