diff --git a/src/main.cpp b/src/main.cpp index fe40faa..25a329c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,8 @@ /** - * Bitcoin Dashboard for Elecrow 7-inch HMI Display - * Three-column layout with antialiased fonts - */ +* Bitcoin Dashboard for Elecrow 7-inch HMI Display +* Three-column layout with antialiased fonts +* Customization screen for stocks and indices +*/ #include #include @@ -16,12 +17,18 @@ #define SCREEN_WIDTH 800 #define SCREEN_HEIGHT 480 -#define TFT_WHITE 0xFFFF -#define TFT_BLACK 0x0000 -#define TFT_ORANGE 0xFD20 -#define TFT_GOLD 0xFEA0 -#define TFT_SILVER 0xC618 -#define TFT_GREEN 0x07E0 +#define TFT_WHITE 0xFFFF +#define TFT_BLACK 0x0000 +#define TFT_ORANGE 0xFD20 +#define TFT_GOLD 0xFEA0 +#define TFT_SILVER 0xC618 +#define TFT_GREEN 0x07E0 +#define TFT_DARKGRAY 0x2104 +#define TFT_GRAY 0x8410 + +#define MAX_STOCKS 5 +#define MAX_INDICES 5 +#define MAX_TICKER_LEN 8 class LGFX : public lgfx::LGFX_Device { public: @@ -114,12 +121,51 @@ static LGFX lcd; static Preferences preferences; double btcPrice = 0, goldPrice = 0, silverPrice = 0; -double mstrPrice = 0, strtPrice = 0; -double nasdaqPrice = 0, dowPrice = 0, spxPrice = 0; +double stockPrices[MAX_STOCKS] = {0}; +double indexPrices[MAX_INDICES] = {0}; + +char stockTickers[MAX_STOCKS][MAX_TICKER_LEN + 1] = {"MSTR", "STRC", "", "", ""}; +char indexTickers[MAX_INDICES][MAX_TICKER_LEN + 1] = {"^IXIC", "^DJI", "^GSPC", "", ""}; +bool indexSelected[MAX_INDICES] = {true, true, true, false, false}; + +const char* availableIndices[] = { + "^GSPC", "^DJI", "^IXIC", "^RUT", "^VIX", + "^FTSE", "^GDAXI", "^FCHI", "^N225", "^HSI", + "^AXJO", "^KS11", "^TWII", "^STI", "^MXX" +}; +const char* indexNames[] = { + "S&P 500", "Dow Jones", "NASDAQ", "Russell 2000", "VIX", + "FTSE 100", "DAX", "CAC 40", "Nikkei 225", "Hang Seng", + "ASX 200", "KOSPI", "Taiwan Weighted", "Straits Times", "IPC Mexico" +}; +const int numAvailableIndices = 15; + +const char* getIndexFriendlyName(const char* ticker) { + for (int i = 0; i < numAvailableIndices; i++) { + if (strcmp(ticker, availableIndices[i]) == 0) { + return indexNames[i]; + } + } + return ticker; +} unsigned long lastRefresh = 0; const unsigned long REFRESH_INTERVAL = 300000; +enum ScreenState { + SCREEN_DASHBOARD, + SCREEN_CUSTOMIZE_STOCKS, + SCREEN_CUSTOMIZE_INDICES +}; +ScreenState currentScreen = SCREEN_DASHBOARD; + +int selectedStockSlot = -1; +int selectedIndexSlot = -1; +char keyboardBuffer[MAX_TICKER_LEN + 1] = ""; +int keyboardPos = 0; +int indexScrollOffset = 0; +bool needsRefresh = false; + String formatPriceUS(double price, int decimals = 2, bool includeDollar = true) { if (price <= 0) return "..."; @@ -183,16 +229,216 @@ bool fetchPrice(const char* symbol, double* result) { return true; } +void loadConfig() { + preferences.begin("dashboard", true); + + for (int i = 0; i < MAX_STOCKS; i++) { + String key = "stock" + String(i); + String val = preferences.getString(key.c_str(), ""); + if (val.length() > 0 && val.length() <= MAX_TICKER_LEN) { + strcpy(stockTickers[i], val.c_str()); + } + } + + for (int i = 0; i < MAX_INDICES; i++) { + String key = "index" + String(i); + String val = preferences.getString(key.c_str(), ""); + if (val.length() > 0 && val.length() <= MAX_TICKER_LEN) { + strcpy(indexTickers[i], val.c_str()); + indexSelected[i] = true; + } + } + + preferences.end(); +} + +void saveConfig() { + preferences.begin("dashboard", false); + + for (int i = 0; i < MAX_STOCKS; i++) { + String key = "stock" + String(i); + preferences.putString(key.c_str(), stockTickers[i]); + } + + for (int i = 0; i < MAX_INDICES; i++) { + String key = "index" + String(i); + if (indexSelected[i]) { + preferences.putString(key.c_str(), indexTickers[i]); + } else { + preferences.putString(key.c_str(), ""); + } + } + + preferences.end(); +} + void updatePrices() { if (WiFi.status() != WL_CONNECTED) return; fetchPrice("BTC-USD", &btcPrice); fetchPrice("GC=F", &goldPrice); fetchPrice("SI=F", &silverPrice); - fetchPrice("MSTR", &mstrPrice); - fetchPrice("STRC", &strtPrice); - fetchPrice("^IXIC", &nasdaqPrice); - fetchPrice("^DJI", &dowPrice); - fetchPrice("^GSPC", &spxPrice); + + for (int i = 0; i < MAX_STOCKS; i++) { + if (strlen(stockTickers[i]) > 0) { + fetchPrice(stockTickers[i], &stockPrices[i]); + } + } + + for (int i = 0; i < MAX_INDICES; i++) { + if (indexSelected[i] && strlen(indexTickers[i]) > 0) { + fetchPrice(indexTickers[i], &indexPrices[i]); + } + } +} + +void drawKeyboard(int y) { + const char* rows[] = { + "QWERTYUIOP", + "ASDFGHJKL", + "ZXCVBNM", + "1234567890" + }; + const int numRows = 4; + const int keySize = 32; + const int keyGap = 2; + + for (int r = 0; r < numRows; r++) { + int rowLen = strlen(rows[r]); + int rowWidth = rowLen * (keySize + keyGap) - keyGap; + int startX = (SCREEN_WIDTH - rowWidth) / 2; + int keyY = y + r * (keySize + keyGap); + + for (int k = 0; k < rowLen; k++) { + int keyX = startX + k * (keySize + keyGap); + lcd.fillSmoothRoundRect(keyX, keyY, keySize, keySize, 4, TFT_DARKGRAY); + lcd.setTextColor(TFT_WHITE, TFT_DARKGRAY); + lcd.setFont(&fonts::DejaVu12); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawChar(rows[r][k], keyX + keySize/2, keyY + keySize/2); + } + } + + int btnY = y + numRows * (keySize + keyGap) + 4; + int delX = SCREEN_WIDTH / 2 - 125; + int enterX = SCREEN_WIDTH / 2 + 5; + + lcd.fillSmoothRoundRect(delX, btnY, 120, 32, 6, TFT_ORANGE); + lcd.setTextColor(TFT_WHITE, TFT_ORANGE); + lcd.setFont(&fonts::DejaVu18); + lcd.drawString("DEL", delX + 60, btnY + 16); + + lcd.fillSmoothRoundRect(enterX, btnY, 120, 32, 6, TFT_GREEN); + lcd.setTextColor(TFT_WHITE, TFT_GREEN); + lcd.drawString("SAVE", enterX + 60, btnY + 16); +} + +void drawStockCustomizeScreen() { + lcd.fillScreen(TFT_BLACK); + + lcd.fillSmoothRoundRect(0, 0, SCREEN_WIDTH, 50, 8, TFT_ORANGE); + lcd.setTextColor(TFT_WHITE, TFT_ORANGE); + lcd.setFont(&fonts::DejaVu24); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("CUSTOMIZE STOCKS (up to 5)", SCREEN_WIDTH / 2, 25); + + int slotY = 60; + int slotHeight = 36; + + for (int i = 0; i < MAX_STOCKS; i++) { + int y = slotY + i * (slotHeight + 8); + uint16_t bgColor = (selectedStockSlot == i) ? TFT_ORANGE : TFT_DARKGRAY; + + lcd.fillSmoothRoundRect(200, y, 400, slotHeight, 6, bgColor); + lcd.setTextColor(TFT_WHITE, bgColor); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_left); + lcd.drawString(String(i + 1) + ":", 210, y + slotHeight/2); + lcd.setTextDatum(textdatum_t::middle_center); + + String displayText; + if (selectedStockSlot == i) { + displayText = String(keyboardBuffer); + if (displayText.length() == 0) displayText = "_"; + } else { + displayText = strlen(stockTickers[i]) > 0 ? String(stockTickers[i]) : "(tap to edit)"; + } + lcd.drawString(displayText, 400, y + slotHeight/2); + } + + drawKeyboard(slotY + MAX_STOCKS * (slotHeight + 8) + 20); + + lcd.fillSmoothRoundRect(20, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY); + lcd.setTextColor(TFT_WHITE, TFT_GRAY); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("BACK", 95, SCREEN_HEIGHT - 30); + + lcd.fillSmoothRoundRect(SCREEN_WIDTH - 170, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GREEN); + lcd.setTextColor(TFT_WHITE, TFT_GREEN); + lcd.drawString("INDICES >", SCREEN_WIDTH - 95, SCREEN_HEIGHT - 30); +} + +void drawIndexCustomizeScreen() { + lcd.fillScreen(TFT_BLACK); + + lcd.fillSmoothRoundRect(0, 0, SCREEN_WIDTH, 50, 8, TFT_ORANGE); + lcd.setTextColor(TFT_WHITE, TFT_ORANGE); + lcd.setFont(&fonts::DejaVu24); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("CUSTOMIZE INDICES (select up to 5)", SCREEN_WIDTH / 2, 25); + + int listY = 60; + int itemHeight = 40; + int visibleItems = 8; + + for (int i = 0; i < visibleItems; i++) { + int idx = indexScrollOffset + i; + if (idx >= numAvailableIndices) break; + + int y = listY + i * (itemHeight + 4); + bool isSelected = false; + for (int j = 0; j < MAX_INDICES; j++) { + if (indexSelected[j] && strcmp(indexTickers[j], availableIndices[idx]) == 0) { + isSelected = true; + break; + } + } + + uint16_t bgColor = isSelected ? TFT_GREEN : TFT_DARKGRAY; + lcd.fillSmoothRoundRect(150, y, 500, itemHeight, 6, bgColor); + lcd.setTextColor(TFT_WHITE, bgColor); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_left); + lcd.drawString(indexNames[idx], 170, y + itemHeight/2); + + if (isSelected) { + lcd.setTextDatum(textdatum_t::middle_right); + lcd.drawString("SELECTED", 630, y + itemHeight/2); + } + } + + if (indexScrollOffset > 0) { + lcd.fillSmoothRoundRect(380, listY - 30, 40, 24, 4, TFT_GRAY); + lcd.setTextColor(TFT_WHITE, TFT_GRAY); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("^", 400, listY - 18); + } + + if (indexScrollOffset + visibleItems < numAvailableIndices) { + lcd.fillSmoothRoundRect(380, listY + visibleItems * (itemHeight + 4) + 8, 40, 24, 4, TFT_GRAY); + lcd.setTextColor(TFT_WHITE, TFT_GRAY); + lcd.drawString("v", 400, listY + visibleItems * (itemHeight + 4) + 20); + } + + lcd.fillSmoothRoundRect(20, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY); + lcd.setTextColor(TFT_WHITE, TFT_GRAY); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("SAVE", 95, SCREEN_HEIGHT - 30); + + lcd.fillSmoothRoundRect(SCREEN_WIDTH - 170, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY); + lcd.drawString("CANCEL", SCREEN_WIDTH - 95, SCREEN_HEIGHT - 30); } void drawDashboard() { @@ -210,7 +456,7 @@ void drawDashboard() { int col2X = 280; int col3X = 540; int labelY = 60; - int priceY = labelY + 32; + int priceY = labelY + 28; lcd.setTextColor(TFT_ORANGE, TFT_BLACK); lcd.setFont(&fonts::Roboto_Thin_24); @@ -218,37 +464,247 @@ void drawDashboard() { lcd.drawString(formatPriceUS(btcPrice, 0), col1X, priceY); lcd.setTextColor(TFT_GOLD, TFT_BLACK); - lcd.drawString("Gold:", col1X, labelY + 70); - lcd.drawString(formatPriceUS(goldPrice, 2), col1X, priceY + 70); + lcd.drawString("Gold:", col1X, labelY + 65); + lcd.drawString(formatPriceUS(goldPrice, 2), col1X, priceY + 65); lcd.setTextColor(TFT_SILVER, TFT_BLACK); - lcd.drawString("Silver:", col1X, labelY + 140); - lcd.drawString(formatPriceUS(silverPrice, 2), col1X, priceY + 140); + lcd.drawString("Silver:", col1X, labelY + 130); + lcd.drawString(formatPriceUS(silverPrice, 2), col1X, priceY + 130); lcd.setTextColor(TFT_GREEN, TFT_BLACK); - lcd.drawString("MSTR:", col2X, labelY); - lcd.drawString(formatPriceUS(mstrPrice, 2), col2X, priceY); + int stockY = labelY; + for (int i = 0; i < MAX_STOCKS; i++) { + if (strlen(stockTickers[i]) > 0) { + lcd.drawString(String(stockTickers[i]) + ":", col2X, stockY); + lcd.drawString(formatPriceUS(stockPrices[i], 2), col2X, stockY + 28); + stockY += 65; + } + } - lcd.drawString("STRC:", col2X, labelY + 70); - lcd.drawString(formatPriceUS(strtPrice, 2), col2X, priceY + 70); - - lcd.drawString("NASDAQ:", col3X, labelY); - lcd.drawString(formatPriceUS(nasdaqPrice, 2), col3X, priceY); - - lcd.drawString("DOW:", col3X, labelY + 70); - lcd.drawString(formatPriceUS(dowPrice, 2), col3X, priceY + 70); - - lcd.drawString("SPX:", col3X, labelY + 140); - lcd.drawString(formatPriceUS(spxPrice, 2), col3X, priceY + 140); + lcd.setTextColor(TFT_WHITE, TFT_BLACK); + int indexY = labelY; + for (int i = 0; i < MAX_INDICES; i++) { + if (indexSelected[i] && strlen(indexTickers[i]) > 0) { + lcd.drawString(String(getIndexFriendlyName(indexTickers[i])) + ":", col3X, indexY); + lcd.drawString(formatPriceUS(indexPrices[i], 2), col3X, indexY + 28); + indexY += 65; + } + } lcd.fillSmoothRoundRect(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40, 8, TFT_ORANGE); lcd.setTextColor(TFT_WHITE, TFT_ORANGE); lcd.setFont(&fonts::DejaVu18); lcd.setTextDatum(textdatum_t::middle_left); - String wifiStatus = WiFi.status() == WL_CONNECTED ? "Connected" : "DISCONNECTED"; + String wifiStatus = WiFi.status() == WL_CONNECTED ? "OK" : "OFFLINE"; lcd.drawString("WiFi: " + wifiStatus, 20, SCREEN_HEIGHT - 20); + + lcd.fillSmoothRoundRect(SCREEN_WIDTH - 160, SCREEN_HEIGHT - 36, 140, 32, 6, TFT_DARKGRAY); lcd.setTextDatum(textdatum_t::middle_center); - lcd.drawString("TOUCH TO REFRESH", SCREEN_WIDTH / 2, SCREEN_HEIGHT - 20); + lcd.drawString("CUSTOMIZE", SCREEN_WIDTH - 90, SCREEN_HEIGHT - 20); +} + +bool handleKeyboardTouch(int32_t x, int32_t y, int keyboardY) { + const char* rows[] = { + "QWERTYUIOP", + "ASDFGHJKL", + "ZXCVBNM", + "1234567890" + }; + const int numRows = 4; + const int keySize = 32; + const int keyGap = 2; + + for (int r = 0; r < numRows; r++) { + int rowLen = strlen(rows[r]); + int rowWidth = rowLen * (keySize + keyGap) - keyGap; + int startX = (SCREEN_WIDTH - rowWidth) / 2; + int keyY = keyboardY + r * (keySize + keyGap); + + for (int k = 0; k < rowLen; k++) { + int keyX = startX + k * (keySize + keyGap); + if (x >= keyX && x < keyX + keySize && y >= keyY && y < keyY + keySize) { + if (keyboardPos < MAX_TICKER_LEN) { + keyboardBuffer[keyboardPos++] = rows[r][k]; + keyboardBuffer[keyboardPos] = '\0'; + } + return true; + } + } + } + + int btnY = keyboardY + numRows * (keySize + keyGap) + 4; + int delX = SCREEN_WIDTH / 2 - 125; + int enterX = SCREEN_WIDTH / 2 + 5; + + if (x >= delX && x < delX + 120 && y >= btnY && y < btnY + 32) { + if (keyboardPos > 0) { + keyboardPos--; + keyboardBuffer[keyboardPos] = '\0'; + } + return true; + } + + if (x >= enterX && x < enterX + 120 && y >= btnY && y < btnY + 32) { + if (selectedStockSlot >= 0) { + strcpy(stockTickers[selectedStockSlot], keyboardBuffer); + selectedStockSlot = -1; + keyboardPos = 0; + keyboardBuffer[0] = '\0'; + } + return true; + } + + return false; +} + +bool handleStockCustomizeTouch(int32_t x, int32_t y) { + int slotY = 60; + int slotHeight = 36; + + if (x >= 20 && x < 170 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) { + if (selectedStockSlot >= 0 && keyboardPos > 0) { + strcpy(stockTickers[selectedStockSlot], keyboardBuffer); + } + saveConfig(); + currentScreen = SCREEN_DASHBOARD; + needsRefresh = true; + return true; + } + + if (x >= SCREEN_WIDTH - 170 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) { + if (selectedStockSlot >= 0 && keyboardPos > 0) { + strcpy(stockTickers[selectedStockSlot], keyboardBuffer); + } + saveConfig(); + currentScreen = SCREEN_CUSTOMIZE_INDICES; + indexScrollOffset = 0; + return true; + } + + for (int i = 0; i < MAX_STOCKS; i++) { + int sy = slotY + i * (slotHeight + 8); + if (x >= 200 && x < 600 && y >= sy && y < sy + slotHeight) { + if (selectedStockSlot >= 0 && selectedStockSlot != i && keyboardPos > 0) { + strcpy(stockTickers[selectedStockSlot], keyboardBuffer); + } + selectedStockSlot = i; + strcpy(keyboardBuffer, stockTickers[i]); + keyboardPos = strlen(keyboardBuffer); + return true; + } + } + + if (selectedStockSlot >= 0) { + int keyboardY = slotY + MAX_STOCKS * (slotHeight + 8) + 20; + if (handleKeyboardTouch(x, y, keyboardY)) { + return true; + } + } + + return false; +} + +bool handleIndexCustomizeTouch(int32_t x, int32_t y) { + int listY = 60; + int itemHeight = 40; + int visibleItems = 8; + + if (x >= 20 && x < 170 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) { + saveConfig(); + currentScreen = SCREEN_DASHBOARD; + needsRefresh = true; + return true; + } + + if (x >= SCREEN_WIDTH - 170 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) { + currentScreen = SCREEN_DASHBOARD; + loadConfig(); + return true; + } + + if (x >= 380 && x < 420 && y >= listY - 30 && y < listY - 6) { + if (indexScrollOffset > 0) { + indexScrollOffset--; + } + return true; + } + + if (x >= 380 && x < 420 && y >= listY + visibleItems * (itemHeight + 4) + 8 && y < listY + visibleItems * (itemHeight + 4) + 32) { + if (indexScrollOffset + visibleItems < numAvailableIndices) { + indexScrollOffset++; + } + return true; + } + + for (int i = 0; i < visibleItems; i++) { + int idx = indexScrollOffset + i; + if (idx >= numAvailableIndices) break; + + int iy = listY + i * (itemHeight + 4); + if (x >= 150 && x < 650 && y >= iy && y < iy + itemHeight) { + bool alreadySelected = false; + int selectedSlot = -1; + + for (int j = 0; j < MAX_INDICES; j++) { + if (indexSelected[j] && strcmp(indexTickers[j], availableIndices[idx]) == 0) { + alreadySelected = true; + selectedSlot = j; + break; + } + } + + if (alreadySelected) { + indexSelected[selectedSlot] = false; + indexTickers[selectedSlot][0] = '\0'; + } else { + int count = 0; + for (int j = 0; j < MAX_INDICES; j++) { + if (indexSelected[j]) count++; + } + + if (count < MAX_INDICES) { + for (int j = 0; j < MAX_INDICES; j++) { + if (!indexSelected[j]) { + strcpy(indexTickers[j], availableIndices[idx]); + indexSelected[j] = true; + break; + } + } + } + } + return true; + } + } + + return false; +} + +void showRefreshingMessage() { + lcd.fillSmoothRoundRect(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40, 8, TFT_ORANGE); + lcd.setTextColor(TFT_WHITE, TFT_ORANGE); + lcd.setFont(&fonts::DejaVu18); + lcd.setTextDatum(textdatum_t::middle_center); + lcd.drawString("REFRESHING...", SCREEN_WIDTH / 2, SCREEN_HEIGHT - 20); +} + +void refreshDataAndShow() { + drawDashboard(); + showRefreshingMessage(); + updatePrices(); + lastRefresh = millis(); + drawDashboard(); +} + +bool handleDashboardTouch(int32_t x, int32_t y) { + if (x >= SCREEN_WIDTH - 160 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 36 && y < SCREEN_HEIGHT - 4) { + currentScreen = SCREEN_CUSTOMIZE_STOCKS; + selectedStockSlot = -1; + keyboardPos = 0; + keyboardBuffer[0] = '\0'; + return true; + } + + return true; } void setup() { @@ -272,6 +728,8 @@ void setup() { lcd.drawString("Bitcoin Dashboard", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - 40); lcd.setFont(&fonts::DejaVu18); lcd.drawString("Starting...", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); + + loadConfig(); preferences.begin("wifi", true); String ssid = preferences.getString("ssid", ""); @@ -314,21 +772,45 @@ void setup() { void loop() { int32_t x, y; - if (lcd.getTouch(&x, &y)) { - lcd.setTextColor(TFT_WHITE, TFT_BLACK); - lcd.setFont(&fonts::DejaVu24); - lcd.setTextDatum(textdatum_t::middle_center); - lcd.fillRect(0, SCREEN_HEIGHT / 2 - 20, SCREEN_WIDTH, 40, TFT_BLACK); - lcd.drawString("Refreshing...", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); - - updatePrices(); - lastRefresh = millis(); + if (needsRefresh && currentScreen == SCREEN_DASHBOARD) { + needsRefresh = false; drawDashboard(); - - delay(500); + refreshDataAndShow(); } - if (millis() - lastRefresh > REFRESH_INTERVAL) { + if (lcd.getTouch(&x, &y)) { + switch (currentScreen) { + case SCREEN_DASHBOARD: + handleDashboardTouch(x, y); + break; + case SCREEN_CUSTOMIZE_STOCKS: + handleStockCustomizeTouch(x, y); + break; + case SCREEN_CUSTOMIZE_INDICES: + handleIndexCustomizeTouch(x, y); + break; + } + + if (!needsRefresh) { + switch (currentScreen) { + case SCREEN_DASHBOARD: + updatePrices(); + lastRefresh = millis(); + drawDashboard(); + break; + case SCREEN_CUSTOMIZE_STOCKS: + drawStockCustomizeScreen(); + break; + case SCREEN_CUSTOMIZE_INDICES: + drawIndexCustomizeScreen(); + break; + } + } + + delay(300); + } + + if (currentScreen == SCREEN_DASHBOARD && millis() - lastRefresh > REFRESH_INTERVAL) { updatePrices(); lastRefresh = millis(); drawDashboard();