Use mutexes to guard the MCP

This commit is contained in:
Djuri Baars 2023-11-13 20:02:58 +01:00
parent a3783ceffa
commit 59f9b29df3
5 changed files with 164 additions and 77 deletions

View file

@ -9,6 +9,8 @@ void buttonTask(void *parameter)
while (1) while (1)
{ {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
std::lock_guard<std::mutex> lock(mcpMutex);
TickType_t currentTime = xTaskGetTickCount(); TickType_t currentTime = xTaskGetTickCount();
if ((currentTime - lastDebounceTime) >= debounceDelay) if ((currentTime - lastDebounceTime) >= debounceDelay)
{ {
@ -35,11 +37,14 @@ void buttonTask(void *parameter)
} }
} }
mcp.clearInterrupts(); mcp.clearInterrupts();
// Very ugly, but for some reason this is necessary }
while (!digitalRead(MCP_INT_PIN)) else
{ {
mcp.clearInterrupts(); }
} // Very ugly, but for some reason this is necessary
while (!digitalRead(MCP_INT_PIN))
{
mcp.clearInterrupts();
} }
} }
} }

View file

@ -5,6 +5,7 @@
Preferences preferences; Preferences preferences;
Adafruit_MCP23X17 mcp; Adafruit_MCP23X17 mcp;
std::vector<std::string> screenNameMap(SCREEN_COUNT); std::vector<std::string> screenNameMap(SCREEN_COUNT);
std::mutex mcpMutex;
void setup() void setup()
{ {
@ -15,12 +16,15 @@ void setup()
{ {
queueLedEffect(LED_POWER_TEST); queueLedEffect(LED_POWER_TEST);
} }
if (mcp.digitalRead(3) == LOW)
{ {
preferences.putBool("wifiConfigured", false); std::lock_guard<std::mutex> lockMcp(mcpMutex);
if (mcp.digitalRead(3) == LOW)
{
preferences.putBool("wifiConfigured", false);
WiFi.eraseAP(); WiFi.eraseAP();
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS); queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
}
} }
tryImprovSetup(); tryImprovSetup();
@ -56,8 +60,13 @@ void tryImprovSetup()
uint8_t x_buffer[16]; uint8_t x_buffer[16];
uint8_t x_position = 0; uint8_t x_position = 0;
bool buttonPress = false;
{
std::lock_guard<std::mutex> lockMcp(mcpMutex);
buttonPress = (mcp.digitalRead(2) == LOW);
}
// Hold second button to start QR code wifi config // Hold second button to start QR code wifi config
if (mcp.digitalRead(2) == LOW) if (buttonPress)
{ {
WiFiManager wm; WiFiManager wm;
@ -81,8 +90,7 @@ void tryImprovSetup()
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); });
});
wm.setSaveConfigCallback([]() wm.setSaveConfigCallback([]()
{ {
@ -133,7 +141,7 @@ void tryImprovSetup()
vTaskDelay(pdMS_TO_TICKS(400)); vTaskDelay(pdMS_TO_TICKS(400));
} }
} }
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS); // queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
} }
void setupTime() void setupTime()
@ -153,7 +161,6 @@ void setupPreferences()
{ {
preferences.begin("btclock", false); preferences.begin("btclock", false);
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)); setBlockHeight(preferences.getUInt("blockHeight", 816000));
@ -171,9 +178,12 @@ void setupWebsocketClients(void *pvParameters)
{ {
setupBlockNotify(); setupBlockNotify();
if (preferences.getBool("fetchEurPrice", false)) { if (preferences.getBool("fetchEurPrice", false))
{
setupPriceFetchTask(); setupPriceFetchTask();
} else { }
else
{
setupPriceNotify(); setupPriceNotify();
} }
@ -211,7 +221,7 @@ void setupHardware()
WiFi.setHostname(getMyHostname().c_str()); WiFi.setHostname(getMyHostname().c_str());
; ;
if (!psramInit()) if (!psramInit())
{ {
Serial.println(F("PSRAM not available")); Serial.println(F("PSRAM not available"));
} }
@ -449,60 +459,63 @@ void WiFiEvent(WiFiEvent_t event)
{ {
Serial.printf("[WiFi-event] event: %d\n", event); Serial.printf("[WiFi-event] event: %d\n", event);
switch (event) { switch (event)
case ARDUINO_EVENT_WIFI_READY: {
Serial.println("WiFi interface ready"); case ARDUINO_EVENT_WIFI_READY:
break; Serial.println("WiFi interface ready");
case ARDUINO_EVENT_WIFI_SCAN_DONE: break;
Serial.println("Completed scan for access points"); case ARDUINO_EVENT_WIFI_SCAN_DONE:
break; Serial.println("Completed scan for access points");
case ARDUINO_EVENT_WIFI_STA_START: break;
Serial.println("WiFi client started"); case ARDUINO_EVENT_WIFI_STA_START:
break; Serial.println("WiFi client started");
case ARDUINO_EVENT_WIFI_STA_STOP: break;
Serial.println("WiFi clients stopped"); case ARDUINO_EVENT_WIFI_STA_STOP:
break; Serial.println("WiFi clients stopped");
case ARDUINO_EVENT_WIFI_STA_CONNECTED: break;
Serial.println("Connected to access point"); case ARDUINO_EVENT_WIFI_STA_CONNECTED:
break; Serial.println("Connected to access point");
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: break;
Serial.println("Disconnected from WiFi access point"); case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR); Serial.println("Disconnected from WiFi access point");
break; queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: break;
Serial.println("Authentication mode of access point has changed"); case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
break; Serial.println("Authentication mode of access point has changed");
case ARDUINO_EVENT_WIFI_STA_GOT_IP: break;
Serial.print("Obtained IP address: "); case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println(WiFi.localIP()); Serial.print("Obtained IP address: ");
break; Serial.println(WiFi.localIP());
case ARDUINO_EVENT_WIFI_STA_LOST_IP: break;
Serial.println("Lost IP address and IP address is reset to 0"); case ARDUINO_EVENT_WIFI_STA_LOST_IP:
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR); Serial.println("Lost IP address and IP address is reset to 0");
break; queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
case ARDUINO_EVENT_WIFI_AP_START: break;
Serial.println("WiFi access point started"); case ARDUINO_EVENT_WIFI_AP_START:
break; Serial.println("WiFi access point started");
case ARDUINO_EVENT_WIFI_AP_STOP: break;
Serial.println("WiFi access point stopped"); case ARDUINO_EVENT_WIFI_AP_STOP:
break; Serial.println("WiFi access point stopped");
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: break;
Serial.println("Client connected"); case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
break; Serial.println("Client connected");
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: break;
Serial.println("Client disconnected"); case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
break; Serial.println("Client disconnected");
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: break;
Serial.println("Assigned IP address to client"); case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
break; Serial.println("Assigned IP address to client");
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: break;
Serial.println("Received probe request"); case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
break; Serial.println("Received probe request");
case ARDUINO_EVENT_WIFI_AP_GOT_IP6: break;
Serial.println("AP IPv6 is preferred"); case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
break; Serial.println("AP IPv6 is preferred");
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: break;
Serial.println("STA IPv6 is preferred"); case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
break; Serial.println("STA IPv6 is preferred");
default: break; break;
}} default:
break;
}
}

View file

@ -98,6 +98,8 @@ void refreshFromMemory()
void setupDisplays() void setupDisplays()
{ {
std::lock_guard<std::mutex> lockMcp(mcpMutex);
for (uint i = 0; i < NUM_SCREENS; i++) for (uint i = 0; i < NUM_SCREENS; i++)
{ {
displays[i].init(0, true, 30); displays[i].init(0, true, 30);
@ -209,7 +211,12 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]); std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
displays[epdIndex].init(0, false, 40);
{
std::lock_guard<std::mutex> lockMcp(mcpMutex);
displays[epdIndex].init(0, false, 40);
}
uint count = 0; uint count = 0;
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
{ {

View file

@ -16,6 +16,7 @@ void setupOTA()
ArduinoOTA.setMdnsEnabled(false); ArduinoOTA.setMdnsEnabled(false);
ArduinoOTA.setRebootOnSuccess(false); ArduinoOTA.setRebootOnSuccess(false);
ArduinoOTA.begin(); ArduinoOTA.begin();
//downloadUpdate();
xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY, &taskOtaHandle); xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY, &taskOtaHandle);
} }
@ -78,14 +79,72 @@ void handleOTATask(void *parameter)
void downloadUpdate() void downloadUpdate()
{ {
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
http.setUserAgent(USER_AGENT);
// Send HTTP request to CoinGecko API
http.useHTTP10(true);
http.begin(client, "https://api.github.com/repos/btclock/btclock_v3/releases/latest");
int httpCode = http.GET();
if (httpCode == 200)
{
// WiFiClient * stream = http->getStreamPtr();
StaticJsonDocument<64> filter;
JsonObject filter_assets_0 = filter["assets"].createNestedObject();
filter_assets_0["name"] = true;
filter_assets_0["browser_download_url"] = true;
SpiRamJsonDocument doc(1536);
DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter));
if (error)
{
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
String downloadUrl;
for (JsonObject asset : doc["assets"].as<JsonArray>())
{
if (asset["name"].as<String>().compareTo("firmware.bin") == 0) {
downloadUrl = asset["browser_download_url"].as<String>();
break;
}
}
Serial.printf("Download update from %s", downloadUrl);
// esp_http_client_config_t config = {
// .url = CONFIG_FIRMWARE_UPGRADE_URL,
// };
// esp_https_ota_config_t ota_config = {
// .http_config = &config,
// };
// esp_err_t ret = esp_https_ota(&ota_config);
// if (ret == ESP_OK)
// {
// esp_restart();
// }
}
} }
void onOTAError(ota_error_t error) { void onOTAError(ota_error_t error)
{
Serial.println("\nOTA update error, restarting"); Serial.println("\nOTA update error, restarting");
Wire.end(); Wire.end();
SPI.end(); SPI.end();
delay(1000); delay(1000);
ESP.restart(); ESP.restart();
} }
void onOTAComplete() void onOTAComplete()

View file

@ -5,10 +5,13 @@
#include <Adafruit_MCP23X17.h> #include <Adafruit_MCP23X17.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <Preferences.h> #include <Preferences.h>
#include <mutex>
#include "utils.hpp" #include "utils.hpp"
extern Adafruit_MCP23X17 mcp; extern Adafruit_MCP23X17 mcp;
extern Preferences preferences; extern Preferences preferences;
extern std::mutex mcpMutex;
const PROGMEM int SCREEN_BLOCK_HEIGHT = 0; const PROGMEM int SCREEN_BLOCK_HEIGHT = 0;
const PROGMEM int SCREEN_MSCW_TIME = 1; const PROGMEM int SCREEN_MSCW_TIME = 1;