#include "SD_Card.h" #include "Display_ST7789.h" #include "HandshakeCapture.h" #include "SPI_Bus_Lock.h" uint16_t SDCard_Size = 0; static bool g_sd_ready = false; static bool s_sd_vfs_was_open = false; static void beginSDOperation() { SPIBus_SetDisplayPaused(true); SPIBus_Lock(); } static void endSDOperation() { SPIBus_Unlock(); SPIBus_SetDisplayPaused(false); } bool SD_IsReady() { return g_sd_ready; } bool SD_Init() { beginSDOperation(); g_sd_ready = false; pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); // Shared SPI with ST7789: ensure display CS idle so SD sees a clean bus. digitalWrite(EXAMPLE_PIN_NUM_LCD_CS, HIGH); if (s_sd_vfs_was_open) { SD.end(); s_sd_vfs_was_open = false; HANDSHAKE_LOGLN("[SD] previous mount closed before re-begin"); } HANDSHAKE_LOGF("[SD] begin(cs=%d)...\n", SD_CS); if (!SD.begin(SD_CS, SPI)) { HANDSHAKE_LOGLN("[SD] FAIL: SD.begin() returned false"); endSDOperation(); return false; } uint8_t ct = (uint8_t)SD.cardType(); HANDSHAKE_LOGF("[SD] cardType=%u (0=NONE)\n", (unsigned)ct); if (SD.cardType() == CARD_NONE) { HANDSHAKE_LOGLN("[SD] FAIL: CARD_NONE after begin"); SD.end(); s_sd_vfs_was_open = false; endSDOperation(); return false; } g_sd_ready = true; s_sd_vfs_was_open = true; SDCard_Size = SD.totalBytes() / (1024 * 1024); HANDSHAKE_LOGF("[SD] OK size=%u MiB ready=%d\n", (unsigned)SDCard_Size, (int)g_sd_ready); endSDOperation(); return true; } bool SD_WriteFileAtomic(const char* path, const uint8_t* data, size_t len) { if (path == nullptr || data == nullptr || len == 0) return false; beginSDOperation(); bool ok = false; File file = SD.open(path, FILE_WRITE); if (file) { ok = (file.write(data, len) == len); file.close(); } endSDOperation(); if (len >= 1024) yield(); return ok; } bool SD_AppendLine(const char* path, const char* line) { if (path == nullptr || line == nullptr) return false; beginSDOperation(); bool ok = false; File f = SD.open(path, FILE_APPEND); if (f) { size_t n = strlen(line); ok = (f.write((const uint8_t*)line, n) == n); f.close(); } endSDOperation(); return ok; } bool SD_ForEachLine(const char* path, SD_LineCallback cb, void* user) { if (path == nullptr || cb == nullptr) return false; beginSDOperation(); if (!SD.exists(path)) { endSDOperation(); return true; } File f = SD.open(path, FILE_READ); if (!f) { endSDOperation(); return false; } char buf[80]; while (f.available()) { int n = f.readBytesUntil('\n', buf, (int)sizeof(buf) - 1); if (n < 0) n = 0; buf[n] = '\0'; while (n > 0 && (buf[n - 1] == '\r' || buf[n - 1] == ' ')) { buf[--n] = '\0'; } if (n > 0) cb(buf, user); } f.close(); endSDOperation(); return true; }