Use mutexes to make display writings threadsafe

This commit is contained in:
Djuri Baars 2023-11-13 17:51:10 +01:00
parent 279e156dc1
commit 5987f03e8c
3 changed files with 40 additions and 19 deletions

View file

@ -38,6 +38,9 @@ void setup()
setupButtonTask(); setupButtonTask();
setupOTA(); setupOTA();
waitUntilNoneBusy();
forceFullRefresh();
} }
void tryImprovSetup() void tryImprovSetup()

View file

@ -67,6 +67,7 @@ int bgColor = GxEPD_BLACK;
#define FONT_BIG Antonio_SemiBold90pt7b #define FONT_BIG Antonio_SemiBold90pt7b
std::mutex epdUpdateMutex; std::mutex epdUpdateMutex;
std::mutex epdMutex[NUM_SCREENS];
uint8_t qrcode[800]; uint8_t qrcode[800];
@ -160,7 +161,7 @@ void prepareDisplayUpdateTask(void *pvParameters)
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY)) if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY))
{ {
uint epdIndex = receivedItem.dispNum; uint epdIndex = receivedItem.dispNum;
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
// displays[epdIndex].init(0, false); // Little longer reset duration because of MCP // displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
bool updatePartial = true; bool updatePartial = true;
@ -207,6 +208,8 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
// Wait for the task notification // Wait for the task notification
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
uint count = 0; uint count = 0;
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
{ {
@ -411,6 +414,7 @@ void waitUntilNoneBusy()
} }
else if (count > 205) else if (count > 205)
{ {
Serial.printf("Busy timeout %d", i);
break; break;
} }
} }

View file

@ -11,7 +11,6 @@ esp_timer_handle_t minuteTimer;
std::array<String, NUM_SCREENS> taskEpdContent = {"", "", "", "", "", "", ""}; std::array<String, NUM_SCREENS> taskEpdContent = {"", "", "", "", "", "", ""};
std::string priceString; std::string priceString;
// typedef enum // typedef enum
// { // {
// TASK_PRICE_UPDATE, // TASK_PRICE_UPDATE,
@ -49,20 +48,23 @@ void workerTask(void *pvParameters)
firstIndex = 0; firstIndex = 0;
uint price = getPrice(); uint price = getPrice();
char priceSymbol = '$'; char priceSymbol = '$';
if (preferences.getBool("fetchEurPrice", false))
{
priceSymbol = '[';
}
if (getCurrentScreen() == SCREEN_BTC_TICKER) if (getCurrentScreen() == SCREEN_BTC_TICKER)
{ {
if (preferences.getBool("fetchEurPrice", false)) {
priceSymbol = '[';
}
priceString = (priceSymbol + String(price)).c_str(); priceString = (priceSymbol + String(price)).c_str();
if (priceString.length() < (NUM_SCREENS)) if (priceString.length() < (NUM_SCREENS))
{ {
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
if (preferences.getBool("fetchEurPrice", false)) { if (preferences.getBool("fetchEurPrice", false))
{
taskEpdContent[0] = "BTC/EUR"; taskEpdContent[0] = "BTC/EUR";
} else { }
else
{
taskEpdContent[0] = "BTC/USD"; taskEpdContent[0] = "BTC/USD";
} }
firstIndex = 1; firstIndex = 1;
@ -75,7 +77,12 @@ void workerTask(void *pvParameters)
if (priceString.length() < (NUM_SCREENS)) if (priceString.length() < (NUM_SCREENS))
{ {
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
taskEpdContent[0] = "MSCW/TIME"; if (preferences.getBool("fetchEurPrice", false))
{
taskEpdContent[0] = "SATS/EUR";
} else {
taskEpdContent[0] = "MSCW/TIME";
}
firstIndex = 1; firstIndex = 1;
} }
} }
@ -84,13 +91,20 @@ void workerTask(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"; if (preferences.getBool("fetchEurPrice", false))
{
taskEpdContent[0] = "EUR/MCAP";
}
else
{
taskEpdContent[0] = "USD/MCAP";
}
if (preferences.getBool("mcapBigChar", true)) if (preferences.getBool("mcapBigChar", true))
{ {
firstIndex = 1; firstIndex = 1;
priceString = "$" + formatNumberWithSuffix(marketCap); priceString = priceSymbol + formatNumberWithSuffix(marketCap);
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
} }
else else
@ -209,7 +223,6 @@ void workerTask(void *pvParameters)
} }
} }
void taskScreenRotate(void *pvParameters) void taskScreenRotate(void *pvParameters)
{ {
for (;;) for (;;)
@ -232,10 +245,11 @@ void taskScreenRotate(void *pvParameters)
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}; WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken); xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
if (priceFetchTaskHandle != NULL) { if (priceFetchTaskHandle != NULL)
{
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken); vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
} }
if (xHigherPriorityTaskWoken == pdTRUE) if (xHigherPriorityTaskWoken == pdTRUE)
@ -287,10 +301,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);
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY); xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
// xTaskNotifyGive(timeUpdateTaskHandle); // xTaskNotifyGive(timeUpdateTaskHandle);
vTaskDelete(NULL); vTaskDelete(NULL);
} }
@ -365,7 +379,7 @@ void setCurrentScreen(uint newScreen)
{ {
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY); xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
// xTaskNotifyGive(timeUpdateTaskHandle); // xTaskNotifyGive(timeUpdateTaskHandle);
break; break;
} }
case SCREEN_HALVING_COUNTDOWN: case SCREEN_HALVING_COUNTDOWN:
@ -373,7 +387,7 @@ void setCurrentScreen(uint newScreen)
{ {
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0}; WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY); xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
//xTaskNotifyGive(blockUpdateTaskHandle); // xTaskNotifyGive(blockUpdateTaskHandle);
break; break;
} }
case SCREEN_MARKET_CAP: case SCREEN_MARKET_CAP:
@ -382,7 +396,7 @@ void setCurrentScreen(uint newScreen)
{ {
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0}; WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY); xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
//xTaskNotifyGive(priceUpdateTaskHandle); // xTaskNotifyGive(priceUpdateTaskHandle);
break; break;
} }
} }