forked from btclock/btclock_v3
Improved screen update tasks and display update mechanism
This commit is contained in:
parent
466aa5be4a
commit
d0eb007c4c
12 changed files with 619 additions and 411 deletions
|
@ -2,21 +2,67 @@
|
||||||
|
|
||||||
char *wsServer;
|
char *wsServer;
|
||||||
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
||||||
unsigned long int currentBlockHeight = 816000;
|
uint currentBlockHeight = 816000;
|
||||||
|
|
||||||
|
// const char *mempoolWsCert = R"(-----BEGIN CERTIFICATE-----
|
||||||
|
// MIIHfTCCBmWgAwIBAgIRANFX3mhqRYDt1NFuENoSyaAwDQYJKoZIhvcNAQELBQAw
|
||||||
|
// gZUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
|
||||||
|
// BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE9MDsGA1UE
|
||||||
|
// AxM0U2VjdGlnbyBSU0EgT3JnYW5pemF0aW9uIFZhbGlkYXRpb24gU2VjdXJlIFNl
|
||||||
|
// cnZlciBDQTAeFw0yMzA3MjQwMDAwMDBaFw0yNDA4MjIyMzU5NTlaMFcxCzAJBgNV
|
||||||
|
// BAYTAkpQMQ4wDAYDVQQIEwVUb2t5bzEgMB4GA1UEChMXTUVNUE9PTCBTUEFDRSBD
|
||||||
|
// Ty4sIExURC4xFjAUBgNVBAMTDW1lbXBvb2wuc3BhY2UwggEiMA0GCSqGSIb3DQEB
|
||||||
|
// AQUAA4IBDwAwggEKAoIBAQCqmiPRWgo58d25R0biQjAksXMq5ciH7z7ZQo2w2AbB
|
||||||
|
// rHxpnlIry74b9S4wRY5UJeYmd6ZwA76NdSioDvxTJc29bLplY+Ftmfc4ET0zYb2k
|
||||||
|
// Fi86z7GOWb6Ezor/qez9uMM9cxd021Bvcs0/2OrL6Sgp66u9keDZv9NyvFPpXfuR
|
||||||
|
// tdV2r4HF57VJqZn105PN4k80kNWgDbae8aw+BuUNvQYKEe71yfB7Bh6zSh9pCSfM
|
||||||
|
// I6pIJdQzoada2uY1dQMoJeIq8qKNKqAPKGsH5McemUT5ZIKU/tjk3nfX0pz/sQa4
|
||||||
|
// CN7tLH6UeUlctei92GFd6Xtn7RbKLhDUbc4Sq02Cc9iXAgMBAAGjggQDMIID/zAf
|
||||||
|
// BgNVHSMEGDAWgBQX2dYlJ2f5McJJQ9kwNkSMbKlP6zAdBgNVHQ4EFgQUXkxoddJ6
|
||||||
|
// rKobsbmDdtuCK1ywXuIwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYD
|
||||||
|
// VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEoGA1UdIARDMEEwNQYMKwYBBAGy
|
||||||
|
// MQECAQMEMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgG
|
||||||
|
// BmeBDAECAjBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLnNlY3RpZ28uY29t
|
||||||
|
// L1NlY3RpZ29SU0FPcmdhbml6YXRpb25WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0Eu
|
||||||
|
// Y3JsMIGKBggrBgEFBQcBAQR+MHwwVQYIKwYBBQUHMAKGSWh0dHA6Ly9jcnQuc2Vj
|
||||||
|
// dGlnby5jb20vU2VjdGlnb1JTQU9yZ2FuaXphdGlvblZhbGlkYXRpb25TZWN1cmVT
|
||||||
|
// ZXJ2ZXJDQS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29t
|
||||||
|
// MIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoAdwB2/4g/Crb7lVHCYcz1h7o0tKTN
|
||||||
|
// uyncaEIKn+ZnTFo6dAAAAYmc9m/gAAAEAwBIMEYCIQD8XOozx411S/bnZambGjTB
|
||||||
|
// yTcr2fCmggUfQLSmqksD5gIhAIjiEMg0o1VSuQW31gWzfzL6idCkIZeSKN104cdp
|
||||||
|
// xa4SAHcA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGJnPZwPwAA
|
||||||
|
// BAMASDBGAiEA2sPTZTzvxewzQ8vk36+BWAKuJS7AvJ5W3clvfwCa8OUCIQC74ekT
|
||||||
|
// Ged2fqQE4sVy74aS6HRA2ihC9VLtNrASJx1YjQB2AO7N0GTV2xrOxVy3nbTNE6Iy
|
||||||
|
// h0Z8vOzew1FIWUZxH7WbAAABiZz2cA8AAAQDAEcwRQIgEklH7wYCFuuJIFUHX5PY
|
||||||
|
// /vZ3bDoxOp+061PT3caa+rICIQC0abgfGlBKiHxp47JZxnW3wcVqWdiYX4ViLm9H
|
||||||
|
// xfx4ljCBxgYDVR0RBIG+MIG7gg1tZW1wb29sLnNwYWNlghMqLmZtdC5tZW1wb29s
|
||||||
|
// LnNwYWNlghMqLmZyYS5tZW1wb29sLnNwYWNlgg8qLm1lbXBvb2wuc3BhY2WCEyou
|
||||||
|
// dGs3Lm1lbXBvb2wuc3BhY2WCEyoudmExLm1lbXBvb2wuc3BhY2WCDGJpc3EubWFy
|
||||||
|
// a2V0c4IKYmlzcS5uaW5qYYIObGlxdWlkLm5ldHdvcmuCDGxpcXVpZC5wbGFjZYIN
|
||||||
|
// bWVtcG9vbC5uaW5qYTANBgkqhkiG9w0BAQsFAAOCAQEAFvOSRnlHDfq9C8acjZEG
|
||||||
|
// 5XIqjNYigyWyjOvx83of6Z3PBKkAZB5D/UHBPp+jBDJiEb/QXC7Z7Y7kpuvnoVib
|
||||||
|
// b4jDc0RjGEsxL+3F7cSw26m3wILJhhHooGZRmFY4GOAeCZtYCOTzJsiZvFpDoQjU
|
||||||
|
// hTBxtaps05z0Ly9/eYvkXnjnBNROZJVR+KYHlq4TIoGNc4q4KvpfHv2I/vhS2M1e
|
||||||
|
// bECNNPEyRxHGKdXXO3huocE7aVKpy+JDR6cWwDu6hpdc1j/SCDqdTDFQ7McHOrqA
|
||||||
|
// fpPh4FcfePMh7Mqxtg2pSs5pXPtiP0ZjLgxd7HbAXct8Y+/jGk+k3sx3SeYXVimr
|
||||||
|
// ew==
|
||||||
|
// -----END CERTIFICATE-----)";
|
||||||
|
|
||||||
void setupBlockNotify()
|
void setupBlockNotify()
|
||||||
{
|
{
|
||||||
currentBlockHeight = preferences.getULong("blockHeight", 816000);
|
//currentBlockHeight = preferences.getUInt("blockHeight", 816000);
|
||||||
|
|
||||||
IPAddress result;
|
IPAddress result;
|
||||||
|
|
||||||
int dnsErr = -1;
|
int dnsErr = -1;
|
||||||
String mempoolInstance = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
String mempoolInstance = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||||
|
|
||||||
while (dnsErr != 1) {
|
while (dnsErr != 1)
|
||||||
|
{
|
||||||
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
||||||
|
|
||||||
if (dnsErr != 1) {
|
if (dnsErr != 1)
|
||||||
|
{
|
||||||
Serial.print(mempoolInstance);
|
Serial.print(mempoolInstance);
|
||||||
Serial.println(F("mempool DNS could not be resolved"));
|
Serial.println(F("mempool DNS could not be resolved"));
|
||||||
WiFi.reconnect();
|
WiFi.reconnect();
|
||||||
|
@ -33,13 +79,20 @@ void setupBlockNotify()
|
||||||
{
|
{
|
||||||
String blockHeightStr = http->getString();
|
String blockHeightStr = http->getString();
|
||||||
currentBlockHeight = blockHeightStr.toInt();
|
currentBlockHeight = blockHeightStr.toInt();
|
||||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
if (workQueue != nullptr)
|
||||||
|
{
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::strcpy(wsServer, String("wss://" + mempoolInstance + "/api/v1/ws").c_str());
|
// std::strcpy(wsServer, String("wss://" + mempoolInstance + "/api/v1/ws").c_str());
|
||||||
|
|
||||||
esp_websocket_client_config_t config = {
|
esp_websocket_client_config_t config = {
|
||||||
.uri = "wss://mempool.space/api/v1/ws",
|
.uri = "wss://mempool.space/api/v1/ws",
|
||||||
|
// .task_stack = (6*1024),
|
||||||
|
// .cert_pem = mempoolWsCert,
|
||||||
.user_agent = USER_AGENT,
|
.user_agent = USER_AGENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,19 +140,25 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
||||||
{
|
{
|
||||||
JsonObject block = doc["block"];
|
JsonObject block = doc["block"];
|
||||||
|
|
||||||
currentBlockHeight = block["height"].as<long>();
|
currentBlockHeight = block["height"].as<uint>();
|
||||||
|
|
||||||
Serial.printf("New block found: %d\r\n", block["height"].as<long>());
|
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
||||||
preferences.putULong("blockHeight", currentBlockHeight);
|
size_t prefWrite = preferences.putUInt("blockHeight", currentBlockHeight);
|
||||||
|
Serial.printf("Wrote %d for block\r\n", prefWrite);
|
||||||
|
|
||||||
if (blockUpdateTaskHandle != nullptr) {
|
if (workQueue != nullptr)
|
||||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
{
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
|
||||||
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT && preferences.getBool("stealFocus", true)) {
|
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT && preferences.getBool("stealFocus", true))
|
||||||
|
{
|
||||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT && preferences.getBool("ledFlashOnUpd", false)) {
|
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT && preferences.getBool("ledFlashOnUpd", false))
|
||||||
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||||
}
|
}
|
||||||
|
@ -109,18 +168,25 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
||||||
doc.clear();
|
doc.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long getBlockHeight()
|
uint getBlockHeight()
|
||||||
{
|
{
|
||||||
return currentBlockHeight;
|
return currentBlockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBlockNotifyConnected() {
|
void setBlockHeight(uint newBlockHeight)
|
||||||
|
{
|
||||||
|
currentBlockHeight = newBlockHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBlockNotifyConnected()
|
||||||
|
{
|
||||||
if (blockNotifyClient == NULL)
|
if (blockNotifyClient == NULL)
|
||||||
return false;
|
return false;
|
||||||
return esp_websocket_client_is_connected(blockNotifyClient);
|
return esp_websocket_client_is_connected(blockNotifyClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopBlockNotify() {
|
void stopBlockNotify()
|
||||||
|
{
|
||||||
esp_websocket_client_stop(blockNotifyClient);
|
esp_websocket_client_stop(blockNotifyClient);
|
||||||
esp_websocket_client_destroy(blockNotifyClient);
|
esp_websocket_client_destroy(blockNotifyClient);
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ void setupBlockNotify();
|
||||||
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
||||||
void onWebsocketMessage(esp_websocket_event_data_t* event_data);
|
void onWebsocketMessage(esp_websocket_event_data_t* event_data);
|
||||||
|
|
||||||
unsigned long getBlockHeight();
|
void setBlockHeight(uint newBlockHeight);
|
||||||
|
uint getBlockHeight();
|
||||||
bool isBlockNotifyConnected();
|
bool isBlockNotifyConnected();
|
||||||
void stopBlockNotify();
|
void stopBlockNotify();
|
|
@ -71,16 +71,13 @@ void tryImprovSetup()
|
||||||
WiFi.softAPIP().toString().c_str(),
|
WiFi.softAPIP().toString().c_str(),
|
||||||
wifiManager->getConfigPortalSSID().c_str(),
|
wifiManager->getConfigPortalSSID().c_str(),
|
||||||
softAP_password.c_str());
|
softAP_password.c_str());
|
||||||
// vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
delay(6000);
|
delay(6000);
|
||||||
|
|
||||||
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() + ";T:WPA;P:" + softAP_password.c_str() + ";;";
|
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() + ";T:WPA;P:" + softAP_password.c_str() + ";;";
|
||||||
const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password;
|
const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password;
|
||||||
std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "", "To setup\r\nscan QR or\r\nconnect\r\nmanually", "", explainText, "", qrText};
|
std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "", "To setup\r\nscan QR or\r\nconnect\r\nmanually", "", explainText, "", qrText};
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
delay(3000);
|
});
|
||||||
Serial.println("xTask");
|
|
||||||
xTaskNotifyGive(epdTaskHandle); });
|
|
||||||
|
|
||||||
wm.setSaveConfigCallback([]()
|
wm.setSaveConfigCallback([]()
|
||||||
{
|
{
|
||||||
|
@ -143,8 +140,6 @@ void setupTime()
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.println(F("Retry set time"));
|
Serial.println(F("Retry set time"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPreferences()
|
void setupPreferences()
|
||||||
|
@ -154,6 +149,8 @@ void setupPreferences()
|
||||||
|
|
||||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||||
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
||||||
|
setBlockHeight(preferences.getUInt("blockHeight", 816000));
|
||||||
|
setPrice(preferences.getUInt("lastPrice", 30000));
|
||||||
|
|
||||||
screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
|
screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
|
||||||
screenNameMap[SCREEN_MSCW_TIME] = "Sats per dollar";
|
screenNameMap[SCREEN_MSCW_TIME] = "Sats per dollar";
|
||||||
|
@ -201,11 +198,7 @@ void setupHardware()
|
||||||
|
|
||||||
WiFi.setHostname(getMyHostname().c_str());
|
WiFi.setHostname(getMyHostname().c_str());
|
||||||
;
|
;
|
||||||
if (psramInit())
|
if (!psramInit())
|
||||||
{
|
|
||||||
Serial.println(F("PSRAM is correctly initialized"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Serial.println(F("PSRAM not available"));
|
Serial.println(F("PSRAM not available"));
|
||||||
}
|
}
|
||||||
|
|
377
src/lib/epd.cpp
377
src/lib/epd.cpp
|
@ -53,7 +53,10 @@ std::array<String, NUM_SCREENS> currentEpdContent;
|
||||||
std::array<String, NUM_SCREENS> epdContent;
|
std::array<String, NUM_SCREENS> epdContent;
|
||||||
uint32_t lastFullRefresh[NUM_SCREENS];
|
uint32_t lastFullRefresh[NUM_SCREENS];
|
||||||
TaskHandle_t tasks[NUM_SCREENS];
|
TaskHandle_t tasks[NUM_SCREENS];
|
||||||
TaskHandle_t epdTaskHandle = NULL;
|
// TaskHandle_t epdTaskHandle = NULL;
|
||||||
|
|
||||||
|
#define UPDATE_QUEUE_SIZE 14
|
||||||
|
QueueHandle_t updateQueue;
|
||||||
|
|
||||||
SemaphoreHandle_t epdUpdateSemaphore[NUM_SCREENS];
|
SemaphoreHandle_t epdUpdateSemaphore[NUM_SCREENS];
|
||||||
|
|
||||||
|
@ -72,6 +75,10 @@ void setupDisplays()
|
||||||
displays[i].init();
|
displays[i].init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateQueue = xQueueCreate(UPDATE_QUEUE_SIZE, sizeof(UpdateDisplayTaskItem));
|
||||||
|
|
||||||
|
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, tskIDLE_PRIORITY, NULL);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
{
|
{
|
||||||
epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
||||||
|
@ -80,11 +87,9 @@ void setupDisplays()
|
||||||
int *taskParam = new int;
|
int *taskParam = new int;
|
||||||
*taskParam = i;
|
*taskParam = i;
|
||||||
|
|
||||||
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 4096, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
|
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 2048, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
|
||||||
}
|
}
|
||||||
|
|
||||||
xTaskCreate(taskEpd, "epd_task", 2048, NULL, tskIDLE_PRIORITY, &epdTaskHandle);
|
|
||||||
|
|
||||||
epdContent = {"B",
|
epdContent = {"B",
|
||||||
"T",
|
"T",
|
||||||
"C",
|
"C",
|
||||||
|
@ -94,99 +99,59 @@ void setupDisplays()
|
||||||
"K"};
|
"K"};
|
||||||
|
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
xTaskNotifyGive(tasks[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskEpd(void *pvParameters)
|
|
||||||
{
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
|
|
||||||
bool updatedThisCycle = false;
|
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
if (epdContent[i].compareTo(currentEpdContent[i]) != 0)
|
|
||||||
{
|
|
||||||
if (!updatedThisCycle)
|
|
||||||
{
|
|
||||||
updatedThisCycle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xSemaphoreTake(epdUpdateSemaphore[i], pdMS_TO_TICKS(5000)) == pdTRUE)
|
|
||||||
{
|
|
||||||
xTaskNotifyGive(tasks[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Couldnt get screen" + String(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent)
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent)
|
||||||
{
|
{
|
||||||
epdContent = newEpdContent;
|
epdContent = newEpdContent;
|
||||||
if (epdTaskHandle != NULL)
|
|
||||||
xTaskNotifyGive(epdTaskHandle);
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
if (epdContent[i].compareTo(currentEpdContent[i]) != 0)
|
||||||
|
{
|
||||||
|
UpdateDisplayTaskItem dispUpdate = {i};
|
||||||
|
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
||||||
|
// if (xSemaphoreTake(epdUpdateSemaphore[i], pdMS_TO_TICKS(5000)) == pdTRUE)
|
||||||
|
// {
|
||||||
|
// xTaskNotifyGive(tasks[i]);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
if (eventSourceTaskHandle != NULL)
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept
|
void prepareDisplayUpdateTask(void *pvParameters)
|
||||||
{
|
{
|
||||||
const int epdIndex = *(int *)pvParameters;
|
UpdateDisplayTaskItem receivedItem;
|
||||||
delete (int *)pvParameters;
|
|
||||||
|
|
||||||
for (;;)
|
while (1)
|
||||||
{
|
{
|
||||||
// Wait for the task notification
|
// Wait for a work item to be available in the queue
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY))
|
||||||
|
{
|
||||||
|
uint epdIndex = receivedItem.dispNum;
|
||||||
if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
|
if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
||||||
uint count = 0;
|
|
||||||
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
|
|
||||||
{
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
if (count >= 9)
|
|
||||||
{
|
|
||||||
displays[epdIndex].init(0, false);
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updatePartial = true;
|
bool updatePartial = true;
|
||||||
|
|
||||||
// Full Refresh every half hour
|
// // Full Refresh every half hour
|
||||||
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", 30) * 60 * 1000))
|
// if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", 30) * 60 * 1000))
|
||||||
{
|
|
||||||
updatePartial = false;
|
|
||||||
lastFullRefresh[epdIndex] = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (updatePartial)
|
|
||||||
// {
|
// {
|
||||||
// displays[epdIndex].setPartialWindow(0, 0, displays[i].width(), display[i].height());
|
// updatePartial = false;
|
||||||
|
// lastFullRefresh[epdIndex] = millis();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
||||||
{
|
{
|
||||||
String top = epdContent[epdIndex].substring(0, epdContent[epdIndex].indexOf("/"));
|
String top = epdContent[epdIndex].substring(0, epdContent[epdIndex].indexOf("/"));
|
||||||
String bottom = epdContent[epdIndex].substring(epdContent[epdIndex].indexOf("/") + 1);
|
String bottom = epdContent[epdIndex].substring(epdContent[epdIndex].indexOf("/") + 1);
|
||||||
#ifdef PAGED_WRITE
|
|
||||||
splitTextPaged(epdIndex, top, bottom, updatePartial);
|
|
||||||
#else
|
|
||||||
splitText(epdIndex, top, bottom, updatePartial);
|
splitText(epdIndex, top, bottom, updatePartial);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (epdContent[epdIndex].startsWith(F("qr")))
|
else if (epdContent[epdIndex].startsWith(F("qr")))
|
||||||
{
|
{
|
||||||
|
@ -199,20 +164,101 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef PAGED_WRITE
|
if (epdContent[epdIndex].length() > 1)
|
||||||
showDigitPaged(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
{
|
||||||
#else
|
|
||||||
if (epdContent[epdIndex].length() > 1) {
|
|
||||||
showChars(epdIndex, epdContent[epdIndex], updatePartial, &Antonio_SemiBold30pt7b);
|
showChars(epdIndex, epdContent[epdIndex], updatePartial, &Antonio_SemiBold30pt7b);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PAGED_WRITE
|
if (xSemaphoreTake(epdUpdateSemaphore[epdIndex], pdMS_TO_TICKS(5000)) == pdTRUE)
|
||||||
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
{
|
||||||
#else
|
xTaskNotifyGive(tasks[epdIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
|
{
|
||||||
|
const int epdIndex = *(int *)pvParameters;
|
||||||
|
delete (int *)pvParameters;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Wait for the task notification
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
// if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
||||||
|
uint count = 0;
|
||||||
|
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
|
||||||
|
{
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
// if (count >= 9)
|
||||||
|
// {
|
||||||
|
// displays[epdIndex].init(0, false);
|
||||||
|
// }
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updatePartial = true;
|
||||||
|
|
||||||
|
// Full Refresh every half hour
|
||||||
|
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", 30) * 60 * 1000))
|
||||||
|
{
|
||||||
|
updatePartial = false;
|
||||||
|
lastFullRefresh[epdIndex] = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
// // if (updatePartial)
|
||||||
|
// // {
|
||||||
|
// // displays[epdIndex].setPartialWindow(0, 0, displays[i].width(), display[i].height());
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
||||||
|
// {
|
||||||
|
// String top = epdContent[epdIndex].substring(0, epdContent[epdIndex].indexOf("/"));
|
||||||
|
// String bottom = epdContent[epdIndex].substring(epdContent[epdIndex].indexOf("/") + 1);
|
||||||
|
// #ifdef PAGED_WRITE
|
||||||
|
// splitTextPaged(epdIndex, top, bottom, updatePartial);
|
||||||
|
// #else
|
||||||
|
// splitText(epdIndex, top, bottom, updatePartial);
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
// else if (epdContent[epdIndex].startsWith(F("qr")))
|
||||||
|
// {
|
||||||
|
// renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
|
// }
|
||||||
|
// else if (epdContent[epdIndex].length() > 5)
|
||||||
|
// {
|
||||||
|
// renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
|
||||||
|
// #ifdef PAGED_WRITE
|
||||||
|
// showDigitPaged(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
||||||
|
// #else
|
||||||
|
// if (epdContent[epdIndex].length() > 1)
|
||||||
|
// {
|
||||||
|
// showChars(epdIndex, epdContent[epdIndex], updatePartial, &Antonio_SemiBold30pt7b);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #ifdef PAGED_WRITE
|
||||||
|
// currentEpdContent[epdIndex] = epdContent[epdIndex];
|
||||||
|
// #else
|
||||||
char tries = 0;
|
char tries = 0;
|
||||||
while (tries < 3)
|
while (tries < 3)
|
||||||
{
|
{
|
||||||
|
@ -227,8 +273,8 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
}
|
}
|
||||||
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
||||||
|
|
||||||
#endif
|
// #endif
|
||||||
}
|
// }
|
||||||
xSemaphoreGive(epdUpdateSemaphore[epdIndex]);
|
xSemaphoreGive(epdUpdateSemaphore[epdIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,54 +319,54 @@ void splitText(const uint dispNum, const String &top, const String &bottom, bool
|
||||||
displays[dispNum].print(bottom);
|
displays[dispNum].print(bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void splitTextPaged(const uint dispNum, String top, String bottom, bool partial)
|
// void splitTextPaged(const uint dispNum, String top, String bottom, bool partial)
|
||||||
{
|
// {
|
||||||
displays[dispNum].setRotation(2);
|
// displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(&FONT_SMALL);
|
// displays[dispNum].setFont(&FONT_SMALL);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
// displays[dispNum].setTextColor(getFgColor());
|
||||||
|
|
||||||
// Top text
|
// // Top text
|
||||||
int16_t ttbx, ttby;
|
// int16_t ttbx, ttby;
|
||||||
uint16_t ttbw, ttbh;
|
// uint16_t ttbw, ttbh;
|
||||||
displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
// displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
||||||
uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
// uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
||||||
uint16_t ty = ((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
// uint16_t ty = ((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
||||||
|
|
||||||
// Bottom text
|
// // Bottom text
|
||||||
int16_t tbbx, tbby;
|
// int16_t tbbx, tbby;
|
||||||
uint16_t tbbw, tbbh;
|
// uint16_t tbbw, tbbh;
|
||||||
displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
// displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
||||||
uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
// uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
||||||
uint16_t by = ((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
// uint16_t by = ((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
||||||
|
|
||||||
// Make separator as wide as the shortest text.
|
// // Make separator as wide as the shortest text.
|
||||||
uint16_t lineWidth, lineX;
|
// uint16_t lineWidth, lineX;
|
||||||
if (tbbw < ttbh)
|
// if (tbbw < ttbh)
|
||||||
lineWidth = tbbw;
|
// lineWidth = tbbw;
|
||||||
else
|
// else
|
||||||
lineWidth = ttbw;
|
// lineWidth = ttbw;
|
||||||
lineX = round((displays[dispNum].width() - lineWidth) / 2);
|
// lineX = round((displays[dispNum].width() - lineWidth) / 2);
|
||||||
|
|
||||||
if (partial)
|
// if (partial)
|
||||||
{
|
// {
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
// displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
displays[dispNum].setFullWindow();
|
// displays[dispNum].setFullWindow();
|
||||||
}
|
// }
|
||||||
displays[dispNum].firstPage();
|
// displays[dispNum].firstPage();
|
||||||
|
|
||||||
do
|
// do
|
||||||
{
|
// {
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
// displays[dispNum].fillScreen(getBgColor());
|
||||||
displays[dispNum].setCursor(tx, ty);
|
// displays[dispNum].setCursor(tx, ty);
|
||||||
displays[dispNum].print(top);
|
// displays[dispNum].print(top);
|
||||||
displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3, lineWidth, 6, 3, getFgColor());
|
// displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3, lineWidth, 6, 3, getFgColor());
|
||||||
displays[dispNum].setCursor(bx, by);
|
// displays[dispNum].setCursor(bx, by);
|
||||||
displays[dispNum].print(bottom);
|
// displays[dispNum].print(bottom);
|
||||||
} while (displays[dispNum].nextPage());
|
// } while (displays[dispNum].nextPage());
|
||||||
}
|
// }
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
||||||
{
|
{
|
||||||
|
@ -339,7 +385,8 @@ void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
||||||
displays[dispNum].print(str);
|
displays[dispNum].print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font) {
|
void showChars(const uint dispNum, const String &chars, bool partial, const GFXfont *font)
|
||||||
|
{
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
displays[dispNum].setFont(font);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
@ -354,35 +401,35 @@ void showChars(const uint dispNum, const String& chars, bool partial, const GFXf
|
||||||
displays[dispNum].print(chars);
|
displays[dispNum].print(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
// void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
||||||
{
|
// {
|
||||||
String str(chr);
|
// String str(chr);
|
||||||
displays[dispNum].setRotation(2);
|
// displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
// displays[dispNum].setFont(font);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
// displays[dispNum].setTextColor(getFgColor());
|
||||||
int16_t tbx, tby;
|
// int16_t tbx, tby;
|
||||||
uint16_t tbw, tbh;
|
// uint16_t tbw, tbh;
|
||||||
displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
// displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
// center the bounding box by transposition of the origin:
|
// // center the bounding box by transposition of the origin:
|
||||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
// uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
// uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
if (partial)
|
// if (partial)
|
||||||
{
|
// {
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
// displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
displays[dispNum].setFullWindow();
|
// displays[dispNum].setFullWindow();
|
||||||
}
|
// }
|
||||||
displays[dispNum].firstPage();
|
// displays[dispNum].firstPage();
|
||||||
|
|
||||||
do
|
// do
|
||||||
{
|
// {
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
// displays[dispNum].fillScreen(getBgColor());
|
||||||
displays[dispNum].setCursor(x, y);
|
// displays[dispNum].setCursor(x, y);
|
||||||
displays[dispNum].print(str);
|
// displays[dispNum].print(str);
|
||||||
} while (displays[dispNum].nextPage());
|
// } while (displays[dispNum].nextPage());
|
||||||
}
|
// }
|
||||||
|
|
||||||
int getBgColor()
|
int getBgColor()
|
||||||
{
|
{
|
||||||
|
@ -406,11 +453,6 @@ void setFgColor(int color)
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> getCurrentEpdContent()
|
std::array<String, NUM_SCREENS> getCurrentEpdContent()
|
||||||
{
|
{
|
||||||
// Serial.println("currentEpdContent");
|
|
||||||
|
|
||||||
// for (int i = 0; i < NUM_SCREENS; i++) {
|
|
||||||
// Serial.printf("%d = %s", i, currentEpdContent[i]);
|
|
||||||
// }
|
|
||||||
return currentEpdContent;
|
return currentEpdContent;
|
||||||
}
|
}
|
||||||
void renderText(const uint dispNum, const String &text, bool partial)
|
void renderText(const uint dispNum, const String &text, bool partial)
|
||||||
|
@ -445,12 +487,12 @@ void renderText(const uint dispNum, const String &text, bool partial)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//displays[dispNum].display(partial);
|
// displays[dispNum].display(partial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
void renderQr(const uint dispNum, const String &text, bool partial)
|
||||||
{
|
{
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
|
|
||||||
uint8_t tempBuffer[800];
|
uint8_t tempBuffer[800];
|
||||||
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||||
|
@ -473,16 +515,19 @@ void renderQr(const uint dispNum, const String &text, bool partial)
|
||||||
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//displays[dispNum].display(partial);
|
// displays[dispNum].display(partial);
|
||||||
|
|
||||||
//free(tempBuffer);
|
// free(tempBuffer);
|
||||||
//free(qrcode);
|
// free(qrcode);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitUntilNoneBusy() {
|
void waitUntilNoneBusy()
|
||||||
for (int i = 0; i < NUM_SCREENS; i++) {
|
{
|
||||||
while (EPD_BUSY[i].digitalRead()) {
|
for (int i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
while (EPD_BUSY[i].digitalRead())
|
||||||
|
{
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,21 +13,27 @@
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
#include "qrcodegen.h"
|
#include "qrcodegen.h"
|
||||||
#endif
|
#endif
|
||||||
extern TaskHandle_t epdTaskHandle;
|
// extern TaskHandle_t epdTaskHandle;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char dispNum;
|
||||||
|
} UpdateDisplayTaskItem;
|
||||||
|
|
||||||
void setupDisplays();
|
void setupDisplays();
|
||||||
void taskEpd(void *pvParameters);
|
// void taskEpd(void *pvParameters);
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String& top, const String& bottom, bool partial);
|
void splitText(const uint dispNum, const String& top, const String& bottom, bool partial);
|
||||||
void splitTextPaged(const uint dispNum, String top, String bottom, bool partial);
|
//void splitTextPaged(const uint dispNum, String top, String bottom, bool partial);
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font);
|
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font);
|
||||||
|
|
||||||
void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
//void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
||||||
void updateDisplayAlt(int epdIndex);
|
void updateDisplayAlt(int epdIndex);
|
||||||
|
void prepareDisplayUpdateTask(void *pvParameters);
|
||||||
|
|
||||||
int getBgColor();
|
int getBgColor();
|
||||||
int getFgColor();
|
int getFgColor();
|
||||||
|
|
|
@ -29,9 +29,9 @@ void onOTAStart()
|
||||||
esp_timer_stop(minuteTimer);
|
esp_timer_stop(minuteTimer);
|
||||||
|
|
||||||
// Stop or suspend all tasks
|
// Stop or suspend all tasks
|
||||||
vTaskSuspend(priceUpdateTaskHandle);
|
// vTaskSuspend(priceUpdateTaskHandle);
|
||||||
vTaskSuspend(blockUpdateTaskHandle);
|
// vTaskSuspend(blockUpdateTaskHandle);
|
||||||
vTaskSuspend(timeUpdateTaskHandle);
|
vTaskSuspend(workerTaskHandle);
|
||||||
vTaskSuspend(taskScreenRotateTaskHandle);
|
vTaskSuspend(taskScreenRotateTaskHandle);
|
||||||
|
|
||||||
vTaskSuspend(ledTaskHandle);
|
vTaskSuspend(ledTaskHandle);
|
||||||
|
@ -49,3 +49,6 @@ void handleOTATask(void *parameter) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(2500));
|
vTaskDelay(pdMS_TO_TICKS(2500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void downloadUpdate() {
|
||||||
|
}
|
|
@ -6,3 +6,4 @@
|
||||||
void setupOTA();
|
void setupOTA();
|
||||||
void onOTAStart();
|
void onOTAStart();
|
||||||
void handleOTATask(void *parameter);
|
void handleOTATask(void *parameter);
|
||||||
|
void downloadUpdate();
|
|
@ -1,16 +1,52 @@
|
||||||
#include "price_notify.hpp"
|
#include "price_notify.hpp"
|
||||||
|
|
||||||
const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
|
const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
|
||||||
|
|
||||||
|
// const char* coinCapWsCert = R"(-----BEGIN CERTIFICATE-----
|
||||||
|
// MIIFMjCCBNmgAwIBAgIQBtgXvFyc28MsvQ1HjCnXJTAKBggqhkjOPQQDAjBKMQsw
|
||||||
|
// CQYDVQQGEwJVUzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEgMB4GA1UEAxMX
|
||||||
|
// Q2xvdWRmbGFyZSBJbmMgRUNDIENBLTMwHhcNMjMwNTEwMDAwMDAwWhcNMjQwNTA5
|
||||||
|
// MjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG
|
||||||
|
// A1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEe
|
||||||
|
// MBwGA1UEAxMVc25pLmNsb3VkZmxhcmVzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZI
|
||||||
|
// zj0DAQcDQgAEpvFIXzQKHuqTo+IE6c6sB4p0PMXK1KsseEGf2UN/CNRhG5hO7lr8
|
||||||
|
// JtXrPZkawWBysZxOsEoetkPrDHMugCLfXKOCA3QwggNwMB8GA1UdIwQYMBaAFKXO
|
||||||
|
// N+rrsHUOlGeItEX62SQQh5YfMB0GA1UdDgQWBBShsZDJohaR1a5E0Qj7yblZjKDC
|
||||||
|
// gDA6BgNVHREEMzAxggwqLmNvaW5jYXAuaW+CCmNvaW5jYXAuaW+CFXNuaS5jbG91
|
||||||
|
// ZGZsYXJlc3NsLmNvbTAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUH
|
||||||
|
// AwEGCCsGAQUFBwMCMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj
|
||||||
|
// ZXJ0LmNvbS9DbG91ZGZsYXJlSW5jRUNDQ0EtMy5jcmwwN6A1oDOGMWh0dHA6Ly9j
|
||||||
|
// cmw0LmRpZ2ljZXJ0LmNvbS9DbG91ZGZsYXJlSW5jRUNDQ0EtMy5jcmwwPgYDVR0g
|
||||||
|
// BDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2Vy
|
||||||
|
// dC5jb20vQ1BTMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29j
|
||||||
|
// c3AuZGlnaWNlcnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdp
|
||||||
|
// Y2VydC5jb20vQ2xvdWRmbGFyZUluY0VDQ0NBLTMuY3J0MAwGA1UdEwEB/wQCMAAw
|
||||||
|
// ggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AO7N0GTV2xrOxVy3nbTNE6Iyh0Z8
|
||||||
|
// vOzew1FIWUZxH7WbAAABiAPnoRAAAAQDAEYwRAIgAP2W09OozuhmKeKKMsaVBcae
|
||||||
|
// o+nPHF1WUWk0i387YYYCIDIM1Wll7/4O3GNx2/Fx9bC6pi69Uya4pLxsCfW3fZMe
|
||||||
|
// AHYASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGIA+eg+QAABAMA
|
||||||
|
// RzBFAiEAuNpSqrbx47gYBgBMz5M6q0CnV/WMJqWQOxYFKrwfwVACIH3nCs4bKToT
|
||||||
|
// e+MiBrqSDaekixk4kPFEQESO9qHCkWY5AHcA2ra/az+1tiKfm8K7XGvocJFxbLtR
|
||||||
|
// hIU0vaQ9MEjX+6sAAAGIA+eg1gAABAMASDBGAiEAolCFl2IfbOHUPAOxoi4BLclS
|
||||||
|
// v9FVXb7LwIvTuCfyrEQCIQDcvehwhV9XGopKGl17F2LYYKI7hvlO3RmpPZQJt1da
|
||||||
|
// MDAKBggqhkjOPQQDAgNHADBEAiAXRWZ/JVMsfpSFFTHQHUSqRnQ/7cCOWx+9svIy
|
||||||
|
// mYnFZQIgHMEG0Cm7O4cn5KUzKOsTwwK+2U15s/jPUQi2n2IDTEM=
|
||||||
|
// -----END CERTIFICATE-----)";
|
||||||
|
|
||||||
// WebsocketsClient client;
|
// WebsocketsClient client;
|
||||||
esp_websocket_client_handle_t clientPrice = NULL;
|
esp_websocket_client_handle_t clientPrice = NULL;
|
||||||
unsigned long int currentPrice = 30000;
|
uint currentPrice = 30000;
|
||||||
unsigned long int lastPriceUpdate;
|
unsigned long int lastPriceUpdate;
|
||||||
|
|
||||||
void setupPriceNotify()
|
void setupPriceNotify()
|
||||||
{
|
{
|
||||||
|
// currentPrice = preferences.get("lastPrice", 30000);
|
||||||
|
|
||||||
esp_websocket_client_config_t config = {
|
esp_websocket_client_config_t config = {
|
||||||
.uri = wsServerPrice,
|
.uri = wsServerPrice,
|
||||||
.user_agent = USER_AGENT,
|
// .task_stack = (7*1024),
|
||||||
|
// .cert_pem = coinCapWsCert,
|
||||||
|
.user_agent = USER_AGENT
|
||||||
};
|
};
|
||||||
|
|
||||||
clientPrice = esp_websocket_client_init(&config);
|
clientPrice = esp_websocket_client_init(&config);
|
||||||
|
@ -53,22 +89,28 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
||||||
|
|
||||||
if (lastPriceUpdate == 0 || (currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
if (lastPriceUpdate == 0 || (currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
||||||
// const unsigned long oldPrice = currentPrice;
|
// const unsigned long oldPrice = currentPrice;
|
||||||
currentPrice = doc["bitcoin"].as<long>();
|
currentPrice = doc["bitcoin"].as<uint>();
|
||||||
|
preferences.putUInt("lastPrice", currentPrice);
|
||||||
lastPriceUpdate = currentTime;
|
lastPriceUpdate = currentTime;
|
||||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||||
if (priceUpdateTaskHandle != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP))
|
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long getPrice() {
|
uint getPrice() {
|
||||||
return currentPrice;
|
return currentPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPrice(uint newPrice) {
|
||||||
|
currentPrice = newPrice;
|
||||||
|
}
|
||||||
|
|
||||||
bool isPriceNotifyConnected() {
|
bool isPriceNotifyConnected() {
|
||||||
if (clientPrice == NULL)
|
if (clientPrice == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -14,6 +14,8 @@ void setupPriceNotify();
|
||||||
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
||||||
void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data);
|
void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data);
|
||||||
|
|
||||||
unsigned long getPrice();
|
uint getPrice();
|
||||||
|
void setPrice(uint newPrice);
|
||||||
|
|
||||||
bool isPriceNotifyConnected();
|
bool isPriceNotifyConnected();
|
||||||
void stopPriceNotify();
|
void stopPriceNotify();
|
|
@ -1,9 +1,10 @@
|
||||||
#include "screen_handler.hpp"
|
#include "screen_handler.hpp"
|
||||||
|
|
||||||
TaskHandle_t priceUpdateTaskHandle;
|
// TaskHandle_t priceUpdateTaskHandle;
|
||||||
TaskHandle_t blockUpdateTaskHandle;
|
// TaskHandle_t blockUpdateTaskHandle;
|
||||||
TaskHandle_t timeUpdateTaskHandle;
|
// TaskHandle_t timeUpdateTaskHandle;
|
||||||
TaskHandle_t taskScreenRotateTaskHandle;
|
TaskHandle_t taskScreenRotateTaskHandle;
|
||||||
|
TaskHandle_t workerTaskHandle;
|
||||||
esp_timer_handle_t screenRotateTimer;
|
esp_timer_handle_t screenRotateTimer;
|
||||||
esp_timer_handle_t minuteTimer;
|
esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
|
@ -11,18 +12,43 @@ std::array<String, NUM_SCREENS> taskEpdContent = {"", "", "", "", "", "", ""};
|
||||||
std::string priceString;
|
std::string priceString;
|
||||||
const int usPerSecond = 1000000;
|
const int usPerSecond = 1000000;
|
||||||
const int usPerMinute = 60 * usPerSecond;
|
const int usPerMinute = 60 * usPerSecond;
|
||||||
int64_t next_callback_time = 0;
|
|
||||||
|
// typedef enum
|
||||||
|
// {
|
||||||
|
// TASK_PRICE_UPDATE,
|
||||||
|
// TASK_BLOCK_UPDATE,
|
||||||
|
// TASK_TIME_UPDATE
|
||||||
|
// } TaskType;
|
||||||
|
|
||||||
|
// typedef struct
|
||||||
|
// {
|
||||||
|
// TaskType type;
|
||||||
|
// unsigned long data;
|
||||||
|
// } WorkItem;
|
||||||
|
|
||||||
|
#define WORK_QUEUE_SIZE 10
|
||||||
|
QueueHandle_t workQueue;
|
||||||
|
|
||||||
uint currentScreen;
|
uint currentScreen;
|
||||||
|
|
||||||
void taskPriceUpdate(void *pvParameters)
|
void workerTask(void *pvParameters)
|
||||||
{
|
{
|
||||||
for (;;)
|
WorkItem receivedItem;
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
|
|
||||||
unsigned long price = getPrice();
|
while (1)
|
||||||
|
{
|
||||||
|
// Wait for a work item to be available in the queue
|
||||||
|
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY))
|
||||||
|
{
|
||||||
uint firstIndex = 0;
|
uint firstIndex = 0;
|
||||||
|
|
||||||
|
// Process the work item based on its type
|
||||||
|
switch (receivedItem.type)
|
||||||
|
{
|
||||||
|
case TASK_PRICE_UPDATE:
|
||||||
|
{
|
||||||
|
firstIndex = 0;
|
||||||
|
uint price = getPrice();
|
||||||
if (getCurrentScreen() == SCREEN_BTC_TICKER)
|
if (getCurrentScreen() == SCREEN_BTC_TICKER)
|
||||||
{
|
{
|
||||||
priceString = ("$" + String(price)).c_str();
|
priceString = ("$" + String(price)).c_str();
|
||||||
|
@ -50,16 +76,17 @@ void taskPriceUpdate(void *pvParameters)
|
||||||
double supply = getSupplyAtBlock(getBlockHeight());
|
double supply = getSupplyAtBlock(getBlockHeight());
|
||||||
int64_t marketCap = static_cast<std::int64_t>(supply * double(price));
|
int64_t marketCap = static_cast<std::int64_t>(supply * double(price));
|
||||||
|
|
||||||
|
|
||||||
taskEpdContent[0] = "USD/MCAP";
|
taskEpdContent[0] = "USD/MCAP";
|
||||||
|
|
||||||
if (preferences.getBool("mcapBigChar", true)) {
|
if (preferences.getBool("mcapBigChar", true))
|
||||||
|
{
|
||||||
firstIndex = 1;
|
firstIndex = 1;
|
||||||
|
|
||||||
priceString = "$" + formatNumberWithSuffix(marketCap);
|
priceString = "$" + formatNumberWithSuffix(marketCap);
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
std::string stringValue = std::to_string(marketCap);
|
std::string stringValue = std::to_string(marketCap);
|
||||||
size_t mcLength = stringValue.length();
|
size_t mcLength = stringValue.length();
|
||||||
size_t leadingSpaces = (3 - mcLength % 3) % 3;
|
size_t leadingSpaces = (3 - mcLength % 3) % 3;
|
||||||
|
@ -67,23 +94,26 @@ void taskPriceUpdate(void *pvParameters)
|
||||||
|
|
||||||
uint groups = (mcLength + leadingSpaces) / 3;
|
uint groups = (mcLength + leadingSpaces) / 3;
|
||||||
|
|
||||||
if (groups < NUM_SCREENS) {
|
if (groups < NUM_SCREENS)
|
||||||
|
{
|
||||||
firstIndex = 1;
|
firstIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = firstIndex; i < NUM_SCREENS-groups-1; i++) {
|
for (int i = firstIndex; i < NUM_SCREENS - groups - 1; i++)
|
||||||
|
{
|
||||||
taskEpdContent[i] = "";
|
taskEpdContent[i] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
taskEpdContent[NUM_SCREENS-groups-1] = " $ ";
|
taskEpdContent[NUM_SCREENS - groups - 1] = " $ ";
|
||||||
for (uint i = 0; i < groups; i ++)
|
for (uint i = 0; i < groups; i++)
|
||||||
{
|
{
|
||||||
taskEpdContent[(NUM_SCREENS-groups+i)] = stringValue.substr(i*3, 3).c_str();
|
taskEpdContent[(NUM_SCREENS - groups + i)] = stringValue.substr(i * 3, 3).c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(getCurrentScreen() == SCREEN_MARKET_CAP && !preferences.getBool("mcapBigChar", true))) {
|
if (!(getCurrentScreen() == SCREEN_MARKET_CAP && !preferences.getBool("mcapBigChar", true)))
|
||||||
|
{
|
||||||
for (uint i = firstIndex; i < NUM_SCREENS; i++)
|
for (uint i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
{
|
{
|
||||||
taskEpdContent[i] = priceString[i];
|
taskEpdContent[i] = priceString[i];
|
||||||
|
@ -91,36 +121,12 @@ void taskPriceUpdate(void *pvParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case TASK_BLOCK_UPDATE:
|
||||||
|
|
||||||
void taskScreenRotate(void *pvParameters)
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
|
|
||||||
int nextScreen = (currentScreen + 1) % 5;
|
|
||||||
String key = "screen" + String(nextScreen) + "Visible";
|
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
|
||||||
{
|
|
||||||
nextScreen = (nextScreen + 1) % 5;
|
|
||||||
key = "screen" + String(nextScreen) + "Visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentScreen(nextScreen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBlockUpdate(void *pvParameters)
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
|
|
||||||
std::string blockNrString = String(getBlockHeight()).c_str();
|
std::string blockNrString = String(getBlockHeight()).c_str();
|
||||||
uint firstIndex = 0;
|
firstIndex = 0;
|
||||||
|
|
||||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN)
|
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN)
|
||||||
{
|
{
|
||||||
|
@ -158,12 +164,9 @@ void taskBlockUpdate(void *pvParameters)
|
||||||
{
|
{
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case TASK_TIME_UPDATE:
|
||||||
|
|
||||||
void taskTimeUpdate(void *pvParameters)
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
if (getCurrentScreen() == SCREEN_TIME)
|
if (getCurrentScreen() == SCREEN_TIME)
|
||||||
{
|
{
|
||||||
|
@ -190,20 +193,44 @@ void taskTimeUpdate(void *pvParameters)
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Add more cases for additional task types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void taskScreenRotate(void *pvParameters)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
int nextScreen = (currentScreen + 1) % 5;
|
||||||
|
String key = "screen" + String(nextScreen) + "Visible";
|
||||||
|
|
||||||
|
while (!preferences.getBool(key.c_str(), true))
|
||||||
|
{
|
||||||
|
nextScreen = (nextScreen + 1) % 5;
|
||||||
|
key = "screen" + String(nextScreen) + "Visible";
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentScreen(nextScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR minuteTimerISR(void *arg)
|
void IRAM_ATTR minuteTimerISR(void *arg)
|
||||||
{
|
{
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
// vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
|
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
if (xHigherPriorityTaskWoken == pdTRUE)
|
||||||
{
|
{
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
int64_t current_time = esp_timer_get_time();
|
|
||||||
next_callback_time = current_time + usPerMinute;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR screenRotateTimerISR(void *arg)
|
void IRAM_ATTR screenRotateTimerISR(void *arg)
|
||||||
|
@ -218,9 +245,13 @@ void IRAM_ATTR screenRotateTimerISR(void *arg)
|
||||||
|
|
||||||
void setupTasks()
|
void setupTasks()
|
||||||
{
|
{
|
||||||
xTaskCreate(taskPriceUpdate, "updatePrice", 3072, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
||||||
xTaskCreate(taskBlockUpdate, "updateBlock", 2048, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
|
||||||
xTaskCreate(taskTimeUpdate, "updateTime", 4096, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
// xTaskCreate(taskPriceUpdate, "updatePrice", 1024, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
||||||
|
// xTaskCreate(taskBlockUpdate, "updateBlock", 1024, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
||||||
|
// xTaskCreate(taskTimeUpdate, "updateTime", 1024, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
||||||
|
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY, &workerTaskHandle);
|
||||||
|
|
||||||
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
||||||
|
|
||||||
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
||||||
|
@ -244,7 +275,10 @@ void setupTimeUpdateTimer(void *pvParameters)
|
||||||
vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000)));
|
vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000)));
|
||||||
|
|
||||||
esp_timer_start_periodic(minuteTimer, usPerMinute);
|
esp_timer_start_periodic(minuteTimer, usPerMinute);
|
||||||
xTaskNotifyGive(timeUpdateTaskHandle);
|
|
||||||
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
@ -316,18 +350,30 @@ void setCurrentScreen(uint newScreen)
|
||||||
switch (currentScreen)
|
switch (currentScreen)
|
||||||
{
|
{
|
||||||
case SCREEN_TIME:
|
case SCREEN_TIME:
|
||||||
xTaskNotifyGive(timeUpdateTaskHandle);
|
{
|
||||||
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SCREEN_HALVING_COUNTDOWN:
|
case SCREEN_HALVING_COUNTDOWN:
|
||||||
case SCREEN_BLOCK_HEIGHT:
|
case SCREEN_BLOCK_HEIGHT:
|
||||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
{
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
//xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SCREEN_MARKET_CAP:
|
case SCREEN_MARKET_CAP:
|
||||||
case SCREEN_MSCW_TIME:
|
case SCREEN_MSCW_TIME:
|
||||||
case SCREEN_BTC_TICKER:
|
case SCREEN_BTC_TICKER:
|
||||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
{
|
||||||
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
|
//xTaskNotifyGive(priceUpdateTaskHandle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
if (eventSourceTaskHandle != NULL)
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
|
|
|
@ -8,15 +8,31 @@
|
||||||
#include "shared.hpp"
|
#include "shared.hpp"
|
||||||
#include "lib/epd.hpp"
|
#include "lib/epd.hpp"
|
||||||
|
|
||||||
extern TaskHandle_t priceUpdateTaskHandle;
|
// extern TaskHandle_t priceUpdateTaskHandle;
|
||||||
extern TaskHandle_t blockUpdateTaskHandle;
|
// extern TaskHandle_t blockUpdateTaskHandle;
|
||||||
extern TaskHandle_t timeUpdateTaskHandle;
|
// extern TaskHandle_t timeUpdateTaskHandle;
|
||||||
|
extern TaskHandle_t workerTaskHandle;
|
||||||
extern TaskHandle_t taskScreenRotateTaskHandle;
|
extern TaskHandle_t taskScreenRotateTaskHandle;
|
||||||
|
|
||||||
extern esp_timer_handle_t screenRotateTimer;
|
extern esp_timer_handle_t screenRotateTimer;
|
||||||
extern esp_timer_handle_t minuteTimer;
|
extern esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
|
extern QueueHandle_t workQueue;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TASK_PRICE_UPDATE,
|
||||||
|
TASK_BLOCK_UPDATE,
|
||||||
|
TASK_TIME_UPDATE
|
||||||
|
} TaskType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
TaskType type;
|
||||||
|
char data;
|
||||||
|
} WorkItem;
|
||||||
|
|
||||||
|
void workerTask(void *pvParameters);
|
||||||
uint getCurrentScreen();
|
uint getCurrentScreen();
|
||||||
void setCurrentScreen(uint newScreen);
|
void setCurrentScreen(uint newScreen);
|
||||||
void nextScreen();
|
void nextScreen();
|
||||||
|
@ -30,9 +46,9 @@ void setupScreenRotateTimer(void *pvParameters);
|
||||||
void IRAM_ATTR minuteTimerISR(void* arg);
|
void IRAM_ATTR minuteTimerISR(void* arg);
|
||||||
void IRAM_ATTR screenRotateTimerISR(void* arg);
|
void IRAM_ATTR screenRotateTimerISR(void* arg);
|
||||||
|
|
||||||
void taskPriceUpdate(void *pvParameters);
|
// void taskPriceUpdate(void *pvParameters);
|
||||||
void taskBlockUpdate(void *pvParameters);
|
// void taskBlockUpdate(void *pvParameters);
|
||||||
void taskTimeUpdate(void *pvParameters);
|
// void taskTimeUpdate(void *pvParameters);
|
||||||
void taskScreenRotate(void *pvParameters);
|
void taskScreenRotate(void *pvParameters);
|
||||||
|
|
||||||
uint getTimerSeconds();
|
uint getTimerSeconds();
|
||||||
|
|
|
@ -13,14 +13,7 @@ void setupWebserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
events.onConnect([](AsyncEventSourceClient *client)
|
events.onConnect([](AsyncEventSourceClient *client)
|
||||||
{
|
{ client->send("welcome", NULL, millis(), 1000); });
|
||||||
if (client->lastId())
|
|
||||||
{
|
|
||||||
Serial.printf("Client reconnected! Last message ID that it gat is: %u\n", client->lastId());
|
|
||||||
}
|
|
||||||
// send event with message "hello!", id current millis
|
|
||||||
// and set reconnect delay to 1 second
|
|
||||||
client->send("welcome",NULL,millis(),1000); });
|
|
||||||
server.addHandler(&events);
|
server.addHandler(&events);
|
||||||
|
|
||||||
server.serveStatic("/css", LittleFS, "/css/");
|
server.serveStatic("/css", LittleFS, "/css/");
|
||||||
|
@ -70,7 +63,8 @@ void setupWebserver()
|
||||||
xTaskCreate(eventSourceTask, "eventSourceTask", 4096, NULL, tskIDLE_PRIORITY, &eventSourceTaskHandle);
|
xTaskCreate(eventSourceTask, "eventSourceTask", 4096, NULL, tskIDLE_PRIORITY, &eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopWebServer() {
|
void stopWebServer()
|
||||||
|
{
|
||||||
server.end();
|
server.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +139,6 @@ void onApiStatus(AsyncWebServerRequest *request)
|
||||||
void onApiActionPause(AsyncWebServerRequest *request)
|
void onApiActionPause(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
setTimerActive(false);
|
setTimerActive(false);
|
||||||
Serial.println(F("Update timer paused"));
|
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -156,10 +148,7 @@ void onApiActionPause(AsyncWebServerRequest *request)
|
||||||
*/
|
*/
|
||||||
void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
// moment = millis();
|
|
||||||
setTimerActive(true);
|
setTimerActive(true);
|
||||||
Serial.println(F("Update timer restarted"));
|
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,13 +279,13 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *ledFlashOnUpdate = request->getParam("ledFlashOnUpd", true);
|
AsyncWebParameter *ledFlashOnUpdate = request->getParam("ledFlashOnUpd", true);
|
||||||
|
|
||||||
preferences.putBool("ledFlashOnUpd", ledFlashOnUpdate->value().toInt());
|
preferences.putBool("ledFlashOnUpd", ledFlashOnUpdate->value().toInt());
|
||||||
Serial.printf("Setting led flash on update to %d\r\n", ledFlashOnUpdate->value().toInt());
|
// Serial.printf("Setting led flash on update to %d\r\n", ledFlashOnUpdate->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
preferences.putBool("ledFlashOnUpd", 0);
|
preferences.putBool("ledFlashOnUpd", 0);
|
||||||
Serial.print("Setting led flash on update to false");
|
// Serial.print("Setting led flash on update to false");
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,13 +294,13 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *stealFocusOnBlock = request->getParam("stealFocusOnBlock", true);
|
AsyncWebParameter *stealFocusOnBlock = request->getParam("stealFocusOnBlock", true);
|
||||||
|
|
||||||
preferences.putBool("stealFocus", stealFocusOnBlock->value().toInt());
|
preferences.putBool("stealFocus", stealFocusOnBlock->value().toInt());
|
||||||
Serial.printf("Setting steal focus on new block to %d\r\n", stealFocusOnBlock->value().toInt());
|
// Serial.printf("Setting steal focus on new block to %d\r\n", stealFocusOnBlock->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
preferences.putBool("stealFocus", 0);
|
preferences.putBool("stealFocus", 0);
|
||||||
Serial.print("Setting steal focus on new block to false");
|
// Serial.print("Setting steal focus on new block to false");
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +315,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
preferences.putBool("mcapBigChar", 0);
|
preferences.putBool("mcapBigChar", 0);
|
||||||
Serial.print("Setting big characters for market cap to false");
|
// Serial.print("Setting big characters for market cap to false");
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +324,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *mempoolInstance = request->getParam("mempoolInstance", true);
|
AsyncWebParameter *mempoolInstance = request->getParam("mempoolInstance", true);
|
||||||
|
|
||||||
preferences.putString("mempoolInstance", mempoolInstance->value().c_str());
|
preferences.putString("mempoolInstance", mempoolInstance->value().c_str());
|
||||||
Serial.printf("Setting mempool instance to %s\r\n", mempoolInstance->value().c_str());
|
// Serial.printf("Setting mempool instance to %s\r\n", mempoolInstance->value().c_str());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +333,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *ledBrightness = request->getParam("ledBrightness", true);
|
AsyncWebParameter *ledBrightness = request->getParam("ledBrightness", true);
|
||||||
|
|
||||||
preferences.putUInt("ledBrightness", ledBrightness->value().toInt());
|
preferences.putUInt("ledBrightness", ledBrightness->value().toInt());
|
||||||
Serial.printf("Setting brightness to %d\r\n", ledBrightness->value().toInt());
|
// Serial.printf("Setting brightness to %d\r\n", ledBrightness->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +342,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *fullRefreshMin = request->getParam("fullRefreshMin", true);
|
AsyncWebParameter *fullRefreshMin = request->getParam("fullRefreshMin", true);
|
||||||
|
|
||||||
preferences.putUInt("fullRefreshMin", fullRefreshMin->value().toInt());
|
preferences.putUInt("fullRefreshMin", fullRefreshMin->value().toInt());
|
||||||
Serial.printf("Set full refresh minutes to %d\r\n", fullRefreshMin->value().toInt());
|
// Serial.printf("Set full refresh minutes to %d\r\n", fullRefreshMin->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +351,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *wpTimeout = request->getParam("wpTimeout", true);
|
AsyncWebParameter *wpTimeout = request->getParam("wpTimeout", true);
|
||||||
|
|
||||||
preferences.putUInt("wpTimeout", wpTimeout->value().toInt());
|
preferences.putUInt("wpTimeout", wpTimeout->value().toInt());
|
||||||
Serial.printf("Set WiFi portal timeout seconds to %d\r\n", wpTimeout->value().toInt());
|
// Serial.printf("Set WiFi portal timeout seconds to %ld\r\n", wpTimeout->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +367,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *screenParam = request->getParam(key, true);
|
AsyncWebParameter *screenParam = request->getParam(key, true);
|
||||||
visible = screenParam->value().toInt();
|
visible = screenParam->value().toInt();
|
||||||
}
|
}
|
||||||
Serial.printf("Setting screen %d to %d\r\n", i, visible);
|
// Serial.printf("Setting screen %d to %d\r\n", i, visible);
|
||||||
|
|
||||||
preferences.putBool(prefKey.c_str(), visible);
|
preferences.putBool(prefKey.c_str(), visible);
|
||||||
}
|
}
|
||||||
|
@ -388,7 +377,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *p = request->getParam("tzOffset", true);
|
AsyncWebParameter *p = request->getParam("tzOffset", true);
|
||||||
int tzOffsetSeconds = p->value().toInt() * 60;
|
int tzOffsetSeconds = p->value().toInt() * 60;
|
||||||
preferences.putInt("gmtOffset", tzOffsetSeconds);
|
preferences.putInt("gmtOffset", tzOffsetSeconds);
|
||||||
Serial.printf("Setting tz offset to %d\r\n", tzOffsetSeconds);
|
// Serial.printf("Setting tz offset to %d\r\n", tzOffsetSeconds);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +386,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
AsyncWebParameter *p = request->getParam("minSecPriceUpd", true);
|
AsyncWebParameter *p = request->getParam("minSecPriceUpd", true);
|
||||||
int minSecPriceUpd = p->value().toInt();
|
int minSecPriceUpd = p->value().toInt();
|
||||||
preferences.putUInt("minSecPriceUpd", minSecPriceUpd);
|
preferences.putUInt("minSecPriceUpd", minSecPriceUpd);
|
||||||
Serial.printf("Setting minSecPriceUpd to %d\r\n", minSecPriceUpd);
|
// Serial.printf("Setting minSecPriceUpd to %d\r\n", minSecPriceUpd);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,8 +430,6 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
if (settingsChanged)
|
if (settingsChanged)
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_FLASH_SUCCESS);
|
queueLedEffect(LED_FLASH_SUCCESS);
|
||||||
|
|
||||||
Serial.println(F("Settings changed"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue