diff --git a/data/src/index.html b/data/src/index.html index a0b4466..0c8b980 100644 --- a/data/src/index.html +++ b/data/src/index.html @@ -63,8 +63,8 @@
{{ memUsage }}%
-
Memory usage
-
{{ memFree }} / {{ memTotal }} kB
+
Memory free
+
{{ memFree }} / {{ memTotal }} KiB

@@ -191,6 +191,13 @@ +
+ +
+ +
A restart is required to apply new hostname prefix.
+
+
diff --git a/data/src/js/script.ts b/data/src/js/script.ts index e370e02..0952e77 100644 --- a/data/src/js/script.ts +++ b/data/src/js/script.ts @@ -1,6 +1,6 @@ import './helpers.js'; -var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown"]; +var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown", "Market Cap"]; toTime = (secs) => { var hours = Math.floor(secs / (60 * 60)); @@ -28,7 +28,7 @@ getBcStatus = () => { var source = document.getElementById("entry-template").innerHTML; var template = Handlebars.compile(source); - var context = { timerRunning: jsonData.timerRunning, memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100), memFree: (jsonData.espFreeHeap / 1000), memTotal: (jsonData.espHeapSize / 1000), uptime: toTime(jsonData.espUptime), currentScreen: jsonData.currentScreen, rendered: jsonData.rendered, data: jsonData.data, screens: screens, ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [] }; + var context = { timerRunning: jsonData.timerRunning, memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100), memFree: (jsonData.espFreeHeap / 1024), memTotal: (jsonData.espHeapSize / 1024), uptime: toTime(jsonData.espUptime), currentScreen: jsonData.currentScreen, rendered: jsonData.rendered, data: jsonData.data, screens: screens, ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [] }; document.getElementById('output').innerHTML = template(context); @@ -76,6 +76,7 @@ fetch('/api/settings', { document.getElementById('fullRefreshMin').value = jsonData.fullRefreshMin; document.getElementById('wpTimeout').value = jsonData.wpTimeout; document.getElementById('mempoolInstance').value = jsonData.mempoolInstance; + document.getElementById('hostnamePrefix').value = jsonData.hostnamePrefix; if (jsonData.gitRev) document.getElementById('gitRev').innerHTML = "Version: " + jsonData.gitRev; diff --git a/doc/Rev.B/IMG_3310.jpeg b/doc/Rev.B/IMG_3310.jpeg new file mode 100644 index 0000000..9cd98b4 Binary files /dev/null and b/doc/Rev.B/IMG_3310.jpeg differ diff --git a/doc/Rev.B/IMG_3313.jpeg b/doc/Rev.B/IMG_3313.jpeg new file mode 100644 index 0000000..1c20403 Binary files /dev/null and b/doc/Rev.B/IMG_3313.jpeg differ diff --git a/doc/Rev.B/IMG_3314.jpeg b/doc/Rev.B/IMG_3314.jpeg new file mode 100644 index 0000000..f26ddf4 Binary files /dev/null and b/doc/Rev.B/IMG_3314.jpeg differ diff --git a/doc/Rev.B/IMG_3317.jpeg b/doc/Rev.B/IMG_3317.jpeg new file mode 100644 index 0000000..777777b Binary files /dev/null and b/doc/Rev.B/IMG_3317.jpeg differ diff --git a/src/lib/epd.cpp b/src/lib/epd.cpp index 3cc5499..b936e00 100644 --- a/src/lib/epd.cpp +++ b/src/lib/epd.cpp @@ -26,7 +26,7 @@ void setFgColor(int color) void showSetupQr(const String &ssid, const String &password) { - char displayIndex = 6; + uint displayIndex = 6; const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;"; diff --git a/src/lib/functions.cpp b/src/lib/functions.cpp index dd2b6d5..78d2d33 100644 --- a/src/lib/functions.cpp +++ b/src/lib/functions.cpp @@ -36,8 +36,8 @@ void setupSoftAP() { byte mac[6]; WiFi.macAddress(mac); - softAP_SSID = String("BTClock" + String(mac[5], 16) + String(mac[1], 16)); - WiFi.setHostname(softAP_SSID.c_str()); + softAP_SSID = getMyHostname().c_str(); + WiFi.setHostname(getMyHostname().c_str()); softAP_password = base64::encode(String(mac[2], 16) + String(mac[4], 16) + String(mac[5], 16) + String(mac[1], 16)).substring(2, 10); } @@ -180,7 +180,9 @@ void setupPreferences() {SCREEN_MSCW_TIME, "Sats per dollar"}, {SCREEN_BTC_TICKER, "Ticker"}, {SCREEN_TIME, "Time"}, - {SCREEN_HALVING_COUNTDOWN, "Halving countdown"}}; + {SCREEN_HALVING_COUNTDOWN, "Halving countdown"}, + {SCREEN_MARKET_CAP, "Market Cap"} + }; #ifdef WITH_RGB_LED pixels.setBrightness(preferences.getUInt("ledBrightness", 128)); @@ -222,28 +224,24 @@ void handleScreenTasks(uint screen) vTaskSuspend(blockNotifyTaskHandle); if (getPriceTaskHandle) vTaskSuspend(getPriceTaskHandle); - if (minuteTaskHandle) - vTaskSuspend(minuteTaskHandle); switch (currentScreen) { case SCREEN_BLOCK_HEIGHT: - if (blockNotifyTaskHandle) - { - vTaskResume(blockNotifyTaskHandle); - } - break; case SCREEN_HALVING_COUNTDOWN: if (blockNotifyTaskHandle) vTaskResume(blockNotifyTaskHandle); break; case SCREEN_BTC_TICKER: - if (getPriceTaskHandle) - vTaskResume(getPriceTaskHandle); - break; case SCREEN_MSCW_TIME: if (getPriceTaskHandle) vTaskResume(getPriceTaskHandle); break; + case SCREEN_MARKET_CAP: + if (getPriceTaskHandle) + vTaskResume(getPriceTaskHandle); + if (blockNotifyTaskHandle) + vTaskResume(blockNotifyTaskHandle); + break; case SCREEN_TIME: if (minuteTaskHandle) { @@ -376,18 +374,21 @@ void showNetworkSettings() String ipAddr = WiFi.localIP().toString(); String subNet = WiFi.subnetMask().toString(); - epdContent[1] = "IP/Subnet"; + epdContent[0] = "IP/Subnet"; int ipAddrPos = 0; int subnetPos = 0; for (int i = 0; i < 4; i++) { - epdContent[2 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) + "/" + subNet.substring(0, subNet.indexOf('.')); + epdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) + "/" + subNet.substring(0, subNet.indexOf('.')); ipAddrPos = ipAddr.indexOf('.') + 1; subnetPos = subNet.indexOf('.') + 1; ipAddr = ipAddr.substring(ipAddrPos); subNet = subNet.substring(subnetPos); } + epdContent[NUM_SCREENS-2] = "RAM/Status"; + + epdContent[NUM_SCREENS-1] = String((int)round(ESP.getFreeHeap()/1024)) + "/" + (int)round(ESP.getHeapSize()/1024); CustomTextScreen::setText(epdContent); diff --git a/src/lib/functions.hpp b/src/lib/functions.hpp index 95177b4..d4d939d 100644 --- a/src/lib/functions.hpp +++ b/src/lib/functions.hpp @@ -5,6 +5,7 @@ //#include #include "config.h" +#include "utils.hpp" #include "shared.hpp" #include "Adafruit_GFX.h" #include "lib/epd.hpp" diff --git a/src/lib/utils.cpp b/src/lib/utils.cpp new file mode 100644 index 0000000..480ca6a --- /dev/null +++ b/src/lib/utils.cpp @@ -0,0 +1,54 @@ +#include "utils.hpp"; + +double getSupplyAtBlock(uint blockNr) { + if (blockNr >= 33 * 210000) { + return 20999999.9769; + } + + const int initialBlockReward = 50; // Initial block reward + const int halvingInterval = 210000; // Number of blocks before halving + + int halvingCount = blockNr / halvingInterval; + double totalBitcoinInCirculation = 0; + + for (int i = 0; i < halvingCount; ++i) { + totalBitcoinInCirculation += halvingInterval * initialBlockReward * std::pow(0.5, i); + } + + totalBitcoinInCirculation += (blockNr % halvingInterval) * initialBlockReward * std::pow(0.5, halvingCount); + + return totalBitcoinInCirculation; +} + +std::string formatNumberWithSuffix(int64_t num) { + const long long quadrillion = 1000000000000000LL; + const long long trillion = 1000000000000LL; + const long long billion = 1000000000; + const long long million = 1000000; + const long long thousand = 1000; + + if (num >= quadrillion) { + return std::to_string(num / quadrillion) + "Q"; + } else if (num >= trillion) { + return std::to_string(num / trillion) + "T"; + } else if (num >= billion) { + return std::to_string(num / billion) + "B"; + } else if (num >= million) { + return std::to_string(num / million) + "M"; + } else if (num >= thousand) { + return std::to_string(num / thousand) + "K"; + } else { + return std::to_string(num); + } +} + +String getMyHostname() { + uint8_t mac[6]; + //WiFi.macAddress(mac); + esp_efuse_mac_get_default(mac); + char hostname[15]; + String hostnamePrefix = preferences.getString("hostnamePrefix", "btclock"); + snprintf(hostname, sizeof(hostname), "%s-%02x%02x%02x", + hostnamePrefix, mac[3], mac[4], mac[5]); + return hostname; +} \ No newline at end of file diff --git a/src/lib/utils.hpp b/src/lib/utils.hpp new file mode 100644 index 0000000..32f2a6d --- /dev/null +++ b/src/lib/utils.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "shared.hpp" + +double getSupplyAtBlock(uint blockNr); +std::string formatNumberWithSuffix(int64_t num); +String getMyHostname(); diff --git a/src/lib/webserver.cpp b/src/lib/webserver.cpp index a9a9d1a..0f96454 100644 --- a/src/lib/webserver.cpp +++ b/src/lib/webserver.cpp @@ -52,7 +52,7 @@ void setupWebserver() // Start server server.begin(); - if (!MDNS.begin(HOSTNAME)) + if (!MDNS.begin(getMyHostname())) { Serial.println(F("Error setting up MDNS responder!")); while (1) @@ -61,13 +61,16 @@ void setupWebserver() } } MDNS.addService("http", "tcp", 80); + MDNS.addServiceTxt("http", "tcp", "model", "BTClock"); + MDNS.addServiceTxt("http", "tcp", "version", "2.0"); + MDNS.addServiceTxt("http", "tcp", "rev", GIT_REV); Serial.println(F("Webserver should be running")); } /** * @Api * @Path("/api/status") -*/ + */ void onApiStatus(AsyncWebServerRequest *request) { AsyncResponseStream *response = request->beginResponseStream("application/json"); @@ -110,7 +113,7 @@ void onApiStatus(AsyncWebServerRequest *request) /** * @Api * @Path("/api/action/pause") -*/ + */ void onApiActionPause(AsyncWebServerRequest *request) { timerRunning = false; @@ -122,7 +125,7 @@ void onApiActionPause(AsyncWebServerRequest *request) /** * @Api * @Path("/api/action/full_refresh") -*/ + */ void onApiFullRefresh(AsyncWebServerRequest *request) { @@ -134,7 +137,7 @@ void onApiFullRefresh(AsyncWebServerRequest *request) /** * @Api * @Path("/api/action/timer_restart") -*/ + */ void onApiActionTimerRestart(AsyncWebServerRequest *request) { // moment = millis(); @@ -148,7 +151,7 @@ void onApiActionTimerRestart(AsyncWebServerRequest *request) * @Api * @Path("/api/action/update") * @Parameter int rate Time in minutes -*/ + */ void onApiActionUpdate(AsyncWebServerRequest *request) { if (request->hasParam("rate")) @@ -167,10 +170,10 @@ void onApiActionUpdate(AsyncWebServerRequest *request) * @Api * @Method GET * @Path("/api/settings") -*/ + */ void onApiSettingsGet(AsyncWebServerRequest *request) { - StaticJsonDocument<768> root; + StaticJsonDocument<1536> root; root["numScreens"] = NUM_SCREENS; root["fgColor"] = getFgColor(); root["bgColor"] = getBgColor(); @@ -184,7 +187,9 @@ void onApiSettingsGet(AsyncWebServerRequest *request) root["rpcUser"] = preferences.getString("rpcUser", BITCOIND_RPC_USER); root["rpcHost"] = preferences.getString("rpcHost", BITCOIND_HOST); root["mempoolInstance"] = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE); - + root["hostnamePrefix"] = preferences.getString("hostnamePrefix", "btclock"); + root["hostname"] = getMyHostname(); + #ifdef IS_BW root["epdColors"] = 2; #else @@ -212,7 +217,7 @@ void onApiSettingsGet(AsyncWebServerRequest *request) AsyncResponseStream *response = request->beginResponseStream("application/json"); serializeJson(root, *response); - + request->send(response); } @@ -290,6 +295,14 @@ void onApiSettingsPost(AsyncWebServerRequest *request) settingsChanged = true; } + if (request->hasParam("hostnamePrefix", true)) + { + AsyncWebParameter *hostnamePrefix = request->getParam("hostnamePrefix", true); + + preferences.putString("hostnamePrefix", hostnamePrefix->value().c_str()); + settingsChanged = true; + } + if (request->hasParam("ledBrightness", true)) { AsyncWebParameter *ledBrightness = request->getParam("ledBrightness", true); diff --git a/src/main.cpp b/src/main.cpp index a21cf8b..5d30115 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include "screens/ticker.hpp" #include "screens/time.hpp" #include "screens/halvingcountdown.hpp" +#include "screens/market_cap.hpp" #include "tasks/ha.hpp" #include "tasks/epd.hpp" @@ -62,6 +63,7 @@ void setup() BlockHeightScreen::init(); HalvingCountdownScreen::init(); TickerScreen::init(); + MarketCapScreen::init(); #ifdef WITH_BUTTONS setupButtonTask(); diff --git a/src/screens/blockheight.cpp b/src/screens/blockheight.cpp index 62d8615..44bfec4 100644 --- a/src/screens/blockheight.cpp +++ b/src/screens/blockheight.cpp @@ -57,4 +57,8 @@ std::array BlockHeightScreen::getEpdContent() // std::copy(std::begin(BlockHeightScreen::epdContent), std::end(BlockHeightScreen::epdContent), std::begin(ret)); return ret; +} + +uint BlockHeightScreen::getBlockNr() { + return blockNr; } \ No newline at end of file diff --git a/src/screens/blockheight.hpp b/src/screens/blockheight.hpp index e44443b..c0a4440 100644 --- a/src/screens/blockheight.hpp +++ b/src/screens/blockheight.hpp @@ -17,4 +17,5 @@ public: static void showScreen(); static void onNewBlock(uint blockNr); static std::array getEpdContent(); + static uint getBlockNr(); }; \ No newline at end of file diff --git a/src/screens/market_cap.cpp b/src/screens/market_cap.cpp new file mode 100644 index 0000000..46db538 --- /dev/null +++ b/src/screens/market_cap.cpp @@ -0,0 +1,30 @@ +#include "market_cap.hpp" + +uint MarketCapScreen::satsPerDollar = 0; +std::array MarketCapScreen::epdContent = {"", "", "", "", "", "", ""}; + +void MarketCapScreen::init() +{ + // Dependent on price and blocks + MarketCapScreen::showScreen(); +} + +void MarketCapScreen::showScreen() +{ + double supply = getSupplyAtBlock(BlockHeightScreen::getBlockNr()); + int64_t marketCap = static_cast(supply * double(TickerScreen::getPrice())); + + std::string priceString = "$" + formatNumberWithSuffix(marketCap); + priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); + + epdContent[0] = "USD/MCAP"; + for (uint i = 1; i < NUM_SCREENS; i++) + { + MarketCapScreen::epdContent[i] = priceString[i]; + } +} + +std::array MarketCapScreen::getEpdContent() +{ + return MarketCapScreen::epdContent; +} \ No newline at end of file diff --git a/src/screens/market_cap.hpp b/src/screens/market_cap.hpp new file mode 100644 index 0000000..e7e0e79 --- /dev/null +++ b/src/screens/market_cap.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "base.hpp" +#include "config.h" +#include "shared.hpp" +#include "lib/utils.hpp" +#include "blockheight.hpp"; +#include "ticker.hpp"; +#include "tasks/epd.hpp" + +class MarketCapScreen { + protected: + static uint satsPerDollar; + static std::array epdContent; + public: + static void init(); + static void showScreen(); + static void onPriceUpdate(uint price); + static std::array getEpdContent(); +}; \ No newline at end of file diff --git a/src/screens/sats_per_dollar.cpp b/src/screens/sats_per_dollar.cpp deleted file mode 100644 index b292b94..0000000 --- a/src/screens/sats_per_dollar.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// #include "sats_per_dollar.hpp" - -// uint SatsPerDollarScreen::satsPerDollar = 0; -// std::array SatsPerDollarScreen::epdContent = { "", "", "", "", "", "", "" }; - -// void SatsPerDollarScreen::init() { -// SatsPerDollarScreen::satsPerDollar = int(round(1 / preferences.getFloat("btcPrice", 12345) * 10e7)); -// setupGetPriceTask(); -// SatsPerDollarScreen::showScreen(); -// } - -// void SatsPerDollarScreen::showScreen() { -// std::string satsPerDollarString = String(SatsPerDollarScreen::satsPerDollar).c_str(); -// satsPerDollarString.insert(satsPerDollarString.begin(), 7 - satsPerDollarString.length(), ' '); -// epdContent[0] = "MSCW/TIME"; -// for (uint i = 1; i < NUM_SCREENS; i++) -// { -// SatsPerDollarScreen::epdContent[i] = satsPerDollarString[i]; -// } -// } - -// void SatsPerDollarScreen::onPriceUpdate(uint price) { -// SatsPerDollarScreen::satsPerDollar = int(round(1 / float(price) * 10e7)); - -// SatsPerDollarScreen::showScreen(); -// } - -// std::array SatsPerDollarScreen::getEpdContent() { -// return SatsPerDollarScreen::epdContent; -// } \ No newline at end of file diff --git a/src/screens/sats_per_dollar.hpp b/src/screens/sats_per_dollar.hpp deleted file mode 100644 index 428b49c..0000000 --- a/src/screens/sats_per_dollar.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// #pragma once - -// #include "base.hpp" -// #include "config.h" -// #include "shared.hpp" -// #include "tasks/epd.hpp" - -// class SatsPerDollarScreen { -// protected: -// static uint satsPerDollar; -// static std::array epdContent; -// public: -// static void init(); -// static void showScreen(); -// static void onPriceUpdate(uint price); -// static std::array getEpdContent(); -// }; \ No newline at end of file diff --git a/src/screens/ticker.cpp b/src/screens/ticker.cpp index da2f7f0..b902477 100644 --- a/src/screens/ticker.cpp +++ b/src/screens/ticker.cpp @@ -48,4 +48,8 @@ std::array TickerScreen::getEpdContentSats() { return epdContentSats; +} + +uint TickerScreen::getPrice() { + return price; } \ No newline at end of file diff --git a/src/screens/ticker.hpp b/src/screens/ticker.hpp index 420e6ed..df9adf8 100644 --- a/src/screens/ticker.hpp +++ b/src/screens/ticker.hpp @@ -18,4 +18,5 @@ public: static void onPriceUpdate(uint price); static std::array getEpdContent(); static std::array getEpdContentSats(); + static uint getPrice(); }; \ No newline at end of file diff --git a/src/shared.hpp b/src/shared.hpp index e3af487..42d038f 100644 --- a/src/shared.hpp +++ b/src/shared.hpp @@ -55,9 +55,11 @@ const PROGMEM int SCREEN_MSCW_TIME = 1; const PROGMEM int SCREEN_BTC_TICKER = 2; const PROGMEM int SCREEN_TIME = 3; const PROGMEM int SCREEN_HALVING_COUNTDOWN = 4; +const PROGMEM int SCREEN_MARKET_CAP = 5; + const PROGMEM int SCREEN_COUNTDOWN = 98; const PROGMEM int SCREEN_CUSTOM = 99; -const PROGMEM int screens[5] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN }; +const PROGMEM int screens[6] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP }; const uint screenCount = sizeof(screens) / sizeof(int); diff --git a/src/tasks/epd.cpp b/src/tasks/epd.cpp index 10fa326..a20739b 100644 --- a/src/tasks/epd.cpp +++ b/src/tasks/epd.cpp @@ -192,6 +192,9 @@ void taskEpd(void *pvParameters) case SCREEN_HALVING_COUNTDOWN: epdContent = HalvingCountdownScreen::getEpdContent(); break; + case SCREEN_MARKET_CAP: + epdContent = MarketCapScreen::getEpdContent(); + break; case SCREEN_COUNTDOWN: epdContent = CountdownScreen::getEpdContent(); break; @@ -325,7 +328,7 @@ extern "C" void updateDisplay(void *pvParameters) noexcept if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0) { - displays[epdIndex].init(0, false, 20); // Little longer reset duration because of MCP + displays[epdIndex].init(0, false); // Little longer reset duration because of MCP #ifndef USE_UNIVERSAL_PIN resetSingleDisplay(epdIndex); #endif diff --git a/src/tasks/epd.hpp b/src/tasks/epd.hpp index 7378c0e..f1a7644 100644 --- a/src/tasks/epd.hpp +++ b/src/tasks/epd.hpp @@ -11,10 +11,12 @@ #include "screens/blockheight.hpp" #include "screens/ticker.hpp" #include "screens/time.hpp" -#include "screens/sats_per_dollar.hpp" +#include "screens/market_cap.hpp" #include "screens/countdown.hpp" #include "screens/custom_text.hpp" #include "screens/halvingcountdown.hpp" + + #ifdef USE_UNIVERSAL_PIN #include #include diff --git a/src/tasks/minute.cpp b/src/tasks/minute.cpp index e62c618..a676803 100644 --- a/src/tasks/minute.cpp +++ b/src/tasks/minute.cpp @@ -1,44 +1,59 @@ #include "minute.hpp" TaskHandle_t minuteTaskHandle = NULL; - // Define a type for the event callback +// Define a type for the event callback std::vector minuteEventCallbacks; // Define a vector to hold multiple event callbacks -bool eventTriggered = false; // Initialize the event triggered flag to false +bool eventTriggered = false; // Initialize the event triggered flag to false +const int usPerMinute = 60 * 1000000; -void minuteTask(void * parameter) { - while(1) { - #ifdef IS_3C // wait 5 minutes in case of a 3 color screen otherwise it keeps refreshing - if(rtc.getMinute() % 5 == 0 && !eventTriggered) { - eventTriggered = true; - for(auto &callback : minuteEventCallbacks) { // Loop through all the event callbacks and call them - callback(); - } +void minuteTask(void *parameter) +{ + + esp_timer_handle_t minuteTimer; + const esp_timer_create_args_t minuteTimerConfig = { + .callback = &minuteTimerISR, + .name = "minute_timer"}; + + esp_timer_create(&minuteTimerConfig, &minuteTimer); + + time_t currentTime; + struct tm timeinfo; + time(¤tTime); + localtime_r(¤tTime, &timeinfo); + uint32_t secondsUntilNextMinute = 60 - timeinfo.tm_sec; + + if (secondsUntilNextMinute > 0) + vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000))); + + esp_timer_start_periodic(minuteTimer, usPerMinute); + + while (1) + { + for (auto &callback : minuteEventCallbacks) + { + callback(); } - if(rtc.getMinute() % 5 != 0 && eventTriggered) { // Reset the event triggered flag if the second is not 0 - eventTriggered = false; - } - vTaskDelay(pdMS_TO_TICKS(1000)); // Sleep for 1000 milliseconds to avoid busy waiting - #else - if(rtc.getSecond() == 0 && !eventTriggered) { - eventTriggered = true; - for(auto &callback : minuteEventCallbacks) { // Loop through all the event callbacks and call them - callback(); - } - } - if(rtc.getSecond() != 0) { // Reset the event triggered flag if the second is not 0 - eventTriggered = false; - } - vTaskDelay(pdMS_TO_TICKS(1000)); // Sleep for 1000 milliseconds to avoid busy waiting - #endif + + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + } +} + +void IRAM_ATTR minuteTimerISR(void *arg) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(minuteTaskHandle, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken == pdTRUE) + { + portYIELD_FROM_ISR(); } } void setupMinuteEvent() { - xTaskCreate(minuteTask, "MinuteTask", 4096, NULL, 1, &minuteTaskHandle); // Create the FreeRTOS task + xTaskCreate(minuteTask, "MinuteTask", 4096, NULL, 1, &minuteTaskHandle); // Create the FreeRTOS task } void registerNewMinuteCallback(const EventCallback cb) { minuteEventCallbacks.push_back(cb); -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/tasks/minute.hpp b/src/tasks/minute.hpp index 6a3a635..811200a 100644 --- a/src/tasks/minute.hpp +++ b/src/tasks/minute.hpp @@ -6,9 +6,13 @@ #include #include #include "shared.hpp" +#include +#include extern TaskHandle_t minuteTaskHandle; void minuteTask(void *pvParameters); void setupMinuteEvent(); +void IRAM_ATTR minuteTimerISR(void* arg); + void registerNewMinuteCallback(const EventCallback cb); \ No newline at end of file