From 8ed4bb8aa6c07cce0b55c9c84c3e2ff19d151fd2 Mon Sep 17 00:00:00 2001
From: Djuri Baars <dsbaars@users.noreply.github.com>
Date: Sun, 26 Nov 2023 00:51:54 +0100
Subject: [PATCH] Restart if after 10 minutes no connection

---
 boards/btclock.json        | 57 +++++++++++++++++++++++++++++++++++
 data                       |  2 +-
 partition_16mb.csv         |  7 +++++
 platformio.ini             | 31 ++++++++++++++++---
 src/lib/button_handler.cpp |  6 ++--
 src/lib/config.cpp         | 62 ++++++++++++++++++++++++++++++++------
 src/lib/config.hpp         |  1 +
 src/lib/epd.cpp            | 57 +++++++++++++++++++++++++++++------
 src/lib/shared.hpp         |  5 ++-
 src/main.cpp               | 17 ++++++++++-
 10 files changed, 215 insertions(+), 30 deletions(-)
 create mode 100644 boards/btclock.json
 create mode 100644 partition_16mb.csv

diff --git a/boards/btclock.json b/boards/btclock.json
new file mode 100644
index 0000000..8de370b
--- /dev/null
+++ b/boards/btclock.json
@@ -0,0 +1,57 @@
+{
+  "build": {
+    "arduino":{
+      "ldscript": "esp32s3_out.ld",
+      "partitions": "default_16MB.csv",
+      "memory_type": "qio_opi"
+    },
+    "core": "esp32",
+    "extra_flags": [
+      "-DBOARD_HAS_PSRAM",
+      "-DARDUINO_BTCLOCK",
+      "-DIS_BTCLOCK_S3",
+      "-DARDUINO_USB_MODE=1",
+      "-DARDUINO_RUNNING_CORE=1",
+      "-DARDUINO_EVENT_RUNNING_CORE=1",
+      "-DARDUINO_USB_CDC_ON_BOOT=1"
+    ],
+    "f_cpu": "240000000L",
+    "f_flash": "80000000L",
+    "flash_mode": "qio",
+    "hwids": [
+      [
+        "0x303A",
+        "0x1001"
+      ]
+    ],
+    "mcu": "esp32s3",
+    "variant": "btclock"
+  },
+  "connectivity": [
+    "bluetooth",
+    "wifi"
+  ],
+  "debug": {
+    "default_tool": "esp-builtin",
+    "onboard_tools": [
+      "esp-builtin"
+    ],
+    "openocd_target": "esp32s3.cfg"
+  },
+  "frameworks": [
+    "arduino",
+    "espidf"
+  ],
+  "name": "BTClock",
+  "upload": {
+    "flash_size": "16MB",
+    "maximum_ram_size": 327680,
+    "maximum_size": 16777216,    
+    "use_1200bps_touch": true,
+    "wait_for_upload_port": true,
+    "require_upload_port": true,
+    "speed": 460800
+  },
+  "url": "http://github.com/btclock",
+  "vendor": "BTClock"
+}
diff --git a/data b/data
index fd492c4..51366f2 160000
--- a/data
+++ b/data
@@ -1 +1 @@
-Subproject commit fd492c416ce736726f0fd3f208cd946741ecd918
+Subproject commit 51366f27e815459eae78b2bda71ee90671415e15
diff --git a/partition_16mb.csv b/partition_16mb.csv
new file mode 100644
index 0000000..80df02b
--- /dev/null
+++ b/partition_16mb.csv
@@ -0,0 +1,7 @@
+# Name,   Type, SubType, Offset,  Size, Flags
+nvs,      data, nvs,     36K,     20K,
+otadata,  data, ota,     56K,     8K,
+app0,     app,  ota_0,   64K,     4096K,
+app1,     app,  ota_1,   ,        4096K,
+spiffs,   data, spiffs,  ,        3072K,
+coredump, data, coredump,,        64K,
diff --git a/platformio.ini b/platformio.ini
index 05f9735..7f09b00 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -20,7 +20,6 @@ board_build.filesystem = littlefs
 
 [btclock_base]
 extra_scripts = post:scripts/extra_script.py
-board_build.partitions = partition.csv
 build_flags =
   !python scripts/git_rev.py
   -DLAST_BUILD_TIME=$UNIX_TIME
@@ -44,12 +43,15 @@ lib_deps =
 [env:lolin_s3_mini]
 extends = btclock_base
 board = lolin_s3_mini
+board_build.partitions = partition.csv
 build_flags =
     ${btclock_base.build_flags}
     -D MCP_INT_PIN=8
     -D NEOPIXEL_PIN=34
     -D NEOPIXEL_COUNT=4
     -D NUM_SCREENS=7
+    -D I2C_SDA_PIN=35
+    -D I2C_SCK_PIN=36
 build_unflags = 
   ${btclock_base.build_unflags}
 
@@ -59,7 +61,26 @@ build_flags =
     ${env:lolin_s3_mini.build_flags}
     -D USE_QR
 
-[env:lolin_s3_mini_qr_ota]
-extends = env:lolin_s3_mini_qr
-upload_protocol = espota
-upload_port = 192.168.23.30
\ No newline at end of file
+[env:btclock_s3]
+extends = btclock_base
+board = btclock
+board_build.partitions = partition_16mb.csv
+build_flags =
+    ${btclock_base.build_flags}
+    -D MCP_INT_PIN=4
+    -D NEOPIXEL_PIN=5
+    -D NEOPIXEL_COUNT=4
+    -D NUM_SCREENS=8
+    -D SPI_SDA_PIN=11
+    -D SPI_SCK_PIN=12
+    -D I2C_SDA_PIN=1
+    -D I2C_SCK_PIN=2
+    -D MCP_RESET_PIN=21
+    -D MCP1_A0_PIN=6
+    -D MCP1_A1_PIN=7
+    -D MCP1_A2_PIN=8
+    -D MCP2_A0_PIN=9
+    -D MCP2_A1_PIN=10
+    -D MCP2_A2_PIN=14
+build_unflags = 
+  ${btclock_base.build_unflags}
\ No newline at end of file
diff --git a/src/lib/button_handler.cpp b/src/lib/button_handler.cpp
index d4d3f9e..424171d 100644
--- a/src/lib/button_handler.cpp
+++ b/src/lib/button_handler.cpp
@@ -18,7 +18,7 @@ void buttonTask(void *parameter)
 
             if (!digitalRead(MCP_INT_PIN))
             {
-                uint pin = mcp.getLastInterruptPin();
+                uint pin = mcp1.getLastInterruptPin();
 
                 switch (pin)
                 {
@@ -36,7 +36,7 @@ void buttonTask(void *parameter)
                     break;
                 }
             }
-            mcp.clearInterrupts();
+            mcp1.clearInterrupts();
         }
         else
         {
@@ -44,7 +44,7 @@ void buttonTask(void *parameter)
         // Very ugly, but for some reason this is necessary
         while (!digitalRead(MCP_INT_PIN))
         {
-            mcp.clearInterrupts();
+            mcp1.clearInterrupts();
         }
     }
 }
diff --git a/src/lib/config.cpp b/src/lib/config.cpp
index 23649b4..417686c 100644
--- a/src/lib/config.cpp
+++ b/src/lib/config.cpp
@@ -3,7 +3,10 @@
 #define MAX_ATTEMPTS_WIFI_CONNECTION 20
 
 Preferences preferences;
-Adafruit_MCP23X17 mcp;
+Adafruit_MCP23X17 mcp1;
+#ifdef IS_BTCLOCK_S3
+Adafruit_MCP23X17 mcp2;
+#endif
 std::vector<std::string> screenNameMap(SCREEN_COUNT);
 std::mutex mcpMutex;
 
@@ -18,7 +21,7 @@ void setup()
     }
     {
         std::lock_guard<std::mutex> lockMcp(mcpMutex);
-        if (mcp.digitalRead(3) == LOW)
+        if (mcp1.digitalRead(3) == LOW)
         {
             preferences.putBool("wifiConfigured", false);
             preferences.remove("txPower");
@@ -65,7 +68,7 @@ void tryImprovSetup()
         bool buttonPress = false;
         {
             std::lock_guard<std::mutex> lockMcp(mcpMutex);
-            buttonPress = (mcp.digitalRead(2) == LOW);
+            buttonPress = (mcp1.digitalRead(2) == LOW);
         }
         
         {
@@ -230,6 +233,33 @@ std::vector<std::string> getScreenNameMap()
     return screenNameMap;
 }
 
+
+void setupMcp()
+{
+    #ifdef IS_BTCLOCK_S3
+    const int mcp1AddrPins[] = {MCP1_A0_PIN, MCP1_A1_PIN, MCP1_A2_PIN};
+    const int mcp1AddrValues[] = {LOW, LOW, LOW};
+
+    const int mcp2AddrPins[] = {MCP2_A0_PIN, MCP2_A1_PIN, MCP2_A2_PIN};
+    const int mcp2AddrValues[] = {LOW, LOW, HIGH};
+
+    pinMode(MCP_RESET_PIN, OUTPUT);
+    digitalWrite(MCP_RESET_PIN, HIGH);
+
+    for (int i = 0; i < 3; ++i) {
+        pinMode(mcp1AddrPins[i], OUTPUT);
+        digitalWrite(mcp1AddrPins[i], mcp1AddrValues[i]);
+
+        pinMode(mcp2AddrPins[i], OUTPUT);
+        digitalWrite(mcp2AddrPins[i], mcp2AddrValues[i]);
+    }
+
+    digitalWrite(MCP_RESET_PIN, LOW);
+    delay(30);
+    digitalWrite(MCP_RESET_PIN, HIGH);
+    #endif
+}
+
 void setupHardware()
 {
     if (!LittleFS.begin(true))
@@ -250,9 +280,11 @@ void setupHardware()
         Serial.println(F("PSRAM not available"));
     }
 
-    Wire.begin(35, 36, 400000);
+    setupMcp();
 
-    if (!mcp.begin_I2C(0x20))
+    Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
+
+    if (!mcp1.begin_I2C(0x20))
     {
         Serial.println(F("Error MCP23017"));
 
@@ -262,18 +294,30 @@ void setupHardware()
     else
     {
         pinMode(MCP_INT_PIN, INPUT_PULLUP);
-        mcp.setupInterrupts(false, false, LOW);
+        mcp1.setupInterrupts(false, false, LOW);
 
         for (int i = 0; i < 4; i++)
         {
-            mcp.pinMode(i, INPUT_PULLUP);
-            mcp.setupInterruptPin(i, LOW);
+            mcp1.pinMode(i, INPUT_PULLUP);
+            mcp1.setupInterruptPin(i, LOW);
         }
+        #ifndef IS_BTCLOCK_S3
         for (int i = 8; i <= 14; i++)
         {
-            mcp.pinMode(i, OUTPUT);
+            mcp1.pinMode(i, OUTPUT);
         }
+        #endif
     }
+
+    #ifdef IS_BTCLOCK_S3
+    if (!mcp2.begin_I2C(0x21))
+    {
+        Serial.println(F("Error MCP23017"));
+
+        // while (1)
+        //         ;
+    }
+    #endif
 }
 
 void improvGetAvailableWifiNetworks()
diff --git a/src/lib/config.hpp b/src/lib/config.hpp
index 12c9809..56716f3 100644
--- a/src/lib/config.hpp
+++ b/src/lib/config.hpp
@@ -41,6 +41,7 @@ void setupHardware();
 void tryImprovSetup();
 void setupTimers();
 void finishSetup();
+void setupMcp();
 std::vector<std::string> getScreenNameMap();
 
 std::vector<std::string> getLocalUrl();
diff --git a/src/lib/epd.cpp b/src/lib/epd.cpp
index 10e0f6b..d982556 100644
--- a/src/lib/epd.cpp
+++ b/src/lib/epd.cpp
@@ -1,5 +1,6 @@
 #include "epd.hpp"
 
+#ifndef IS_BTCLOCK_S3
 Native_Pin EPD_CS[NUM_SCREENS] = {
     Native_Pin(2),
     Native_Pin(4),
@@ -24,16 +25,53 @@ Native_Pin EPD_BUSY[NUM_SCREENS] = {
     Native_Pin(16),
 };
 MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
-    MCP23X17_Pin(mcp, 8),
-    MCP23X17_Pin(mcp, 9),
-    MCP23X17_Pin(mcp, 10),
-    MCP23X17_Pin(mcp, 11),
-    MCP23X17_Pin(mcp, 12),
-    MCP23X17_Pin(mcp, 13),
-    MCP23X17_Pin(mcp, 14),
+    MCP23X17_Pin(mcp1, 8),
+    MCP23X17_Pin(mcp1, 9),
+    MCP23X17_Pin(mcp1, 10),
+    MCP23X17_Pin(mcp1, 11),
+    MCP23X17_Pin(mcp1, 12),
+    MCP23X17_Pin(mcp1, 13),
+    MCP23X17_Pin(mcp1, 14),
 };
 
 Native_Pin EPD_DC = Native_Pin(14);
+#else
+Native_Pin EPD_DC = Native_Pin(38);
+
+MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
+    MCP23X17_Pin(mcp1, 8),
+    MCP23X17_Pin(mcp1, 9),
+    MCP23X17_Pin(mcp1, 10),
+    MCP23X17_Pin(mcp1, 11),
+    MCP23X17_Pin(mcp1, 12),
+    MCP23X17_Pin(mcp1, 13),
+    MCP23X17_Pin(mcp1, 14),
+    MCP23X17_Pin(mcp1, 4),
+};
+
+MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
+    MCP23X17_Pin(mcp2, 8),
+    MCP23X17_Pin(mcp2, 10),
+    MCP23X17_Pin(mcp2, 12),
+    MCP23X17_Pin(mcp2, 14),
+    MCP23X17_Pin(mcp2, 0),
+    MCP23X17_Pin(mcp2, 2),
+    MCP23X17_Pin(mcp2, 4),
+    MCP23X17_Pin(mcp2, 6)
+};
+
+MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
+    MCP23X17_Pin(mcp2, 9),
+    MCP23X17_Pin(mcp2, 11),
+    MCP23X17_Pin(mcp2, 13),
+    MCP23X17_Pin(mcp2, 15),
+    MCP23X17_Pin(mcp2, 1),
+    MCP23X17_Pin(mcp2, 3),
+    MCP23X17_Pin(mcp2, 5),
+    MCP23X17_Pin(mcp2, 7),
+};
+
+#endif
 
 GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> displays[NUM_SCREENS] = {
     GxEPD2_213_B74(&EPD_CS[0], &EPD_DC, &EPD_RESET_MPD[0], &EPD_BUSY[0]),
@@ -43,9 +81,8 @@ GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> displays[NUM_SCREENS] = {
     GxEPD2_213_B74(&EPD_CS[4], &EPD_DC, &EPD_RESET_MPD[4], &EPD_BUSY[4]),
     GxEPD2_213_B74(&EPD_CS[5], &EPD_DC, &EPD_RESET_MPD[5], &EPD_BUSY[5]),
     GxEPD2_213_B74(&EPD_CS[6], &EPD_DC, &EPD_RESET_MPD[6], &EPD_BUSY[6]),
-#if NUM_SCREENS == 9
-    GxEPD2_213_B74(&EPD8_CS, &EPD_DC, &EPD_RESET_MPD[7], &EPD8_BUSY),
-    GxEPD2_213_B74(&EPD9_CS, &EPD_DC, &EPD_RESET_MPD[8], &EPD9_BUSY),
+#ifdef IS_BTCLOCK_S3
+    GxEPD2_213_B74(&EPD_CS[7], &EPD_DC, &EPD_RESET_MPD[6], &EPD_BUSY[7]),
 #endif
 };
 
diff --git a/src/lib/shared.hpp b/src/lib/shared.hpp
index 85cd95b..71bc0de 100644
--- a/src/lib/shared.hpp
+++ b/src/lib/shared.hpp
@@ -9,7 +9,10 @@
 
 #include "utils.hpp"
 
-extern Adafruit_MCP23X17 mcp;
+extern Adafruit_MCP23X17 mcp1;
+#ifdef IS_BTCLOCK_S3
+extern Adafruit_MCP23X17 mcp2;
+#endif
 extern Preferences preferences;
 extern std::mutex mcpMutex;
 
diff --git a/src/main.cpp b/src/main.cpp
index fc65c36..80c41c8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,10 +4,11 @@
 #include "ESPAsyncWebServer.h" 
 
 #include "lib/config.hpp"
-#define USE_QR
 
 //char ptrTaskList[400];
 
+uint wifiLostConnection;
+
 extern "C" void app_main()
 {
     initArduino();
@@ -27,7 +28,21 @@ extern "C" void app_main()
             xTaskNotifyGive(eventSourceTaskHandle);
 
         if (!WiFi.isConnected()) {
+            if (!wifiLostConnection) {
+                wifiLostConnection = esp_timer_get_time() / 1000000;
+                Serial.println("Lost WiFi connection, trying to reconnect...");
+            }
+
+            if (((esp_timer_get_time() / 1000000) - wifiLostConnection) > 600) {
+                Serial.println("Still no connection after 10 minutes, restarting...");
+                delay(2000);
+                ESP.restart();
+            }
+
             WiFi.begin();
+        } else if (wifiLostConnection) {
+            wifiLostConnection = 0;
+            Serial.println("Connection restored, reset timer.");
         }
 
         vTaskDelay(pdMS_TO_TICKS(5000));