#include "SDInterface.h" #include "lang_var.h" #ifdef HAS_C5_SD SDInterface::SDInterface(SPIClass* spi, int cs) : _spi(spi), _cs(cs) {} #endif bool SDInterface::initSD() { #ifdef HAS_SD String display_string = ""; #ifdef KIT pinMode(SD_DET, INPUT); if (digitalRead(SD_DET) == LOW) { Serial.println(F("SD Card Detect Pin Detected")); } else { Serial.println(F("SD Card Detect Pin Not Detected")); this->supported = false; return false; } #endif pinMode(SD_CS, OUTPUT); delay(10); #if (defined(MARAUDER_M5STICKC)) || (defined(HAS_CYD_TOUCH)) || (defined(MARAUDER_CARDPUTER)) /* Set up SPI SD Card using external pin header StickCPlus Header - SPI SD Card Reader 3v3 - 3v3 GND - GND G0 - CLK G36/G25 - MISO G26 - MOSI - CS (jumper to SD Card GND Pin) */ #if defined(MARAUDER_M5STICKC) enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 }; #elif defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER) || defined(HAS_SEPARATE_SD) enum { SPI_SCK = SD_SCK, SPI_MISO = SD_MISO, SPI_MOSI = SD_MOSI }; #else enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 }; #endif #ifndef MARAUDER_CARDPUTER this->spiExt = new SPIClass(); #else this->spiExt = new SPIClass(FSPI); #endif Serial.println("Using external SPI configuration..."); this->spiExt->begin(SPI_SCK, SPI_MISO, SPI_MOSI, SD_CS); if (!SD.begin(SD_CS, *(this->spiExt))) { #elif defined(HAS_C5_SD) Serial.println("Using C5 SD configuration..."); if (!SD.begin(SD_CS, *_spi)) { #else if (!SD.begin(SD_CS)) { #endif Serial.println(F("Failed to mount SD Card")); this->supported = false; return false; } else { this->supported = true; this->cardType = SD.cardType(); this->cardSizeMB = SD.cardSize() / (1024 * 1024); if (this->supported) { const int NUM_DIGITS = log10(this->cardSizeMB) + 1; char sz[NUM_DIGITS + 1]; sz[NUM_DIGITS] = 0; for ( size_t i = NUM_DIGITS; i--; this->cardSizeMB /= 10) { sz[i] = '0' + (this->cardSizeMB % 10); display_string.concat((String)sz[i]); } this->card_sz = sz; } if (!SD.exists("/SCRIPTS")) { Serial.println(F("/SCRIPTS does not exist. Creating...")); SD.mkdir("/SCRIPTS"); Serial.println(F("/SCRIPTS created")); } this->sd_files = new LinkedList(); //this->sd_files->add("Back"); return true; } #else Serial.println(F("SD support disabled, skipping init")); return false; #endif } File SDInterface::getFile(String path) { if (this->supported) { File file = SD.open(path, FILE_READ); //if (file) return file; } } bool SDInterface::removeFile(String file_path) { if (SD.remove(file_path)) return true; else return false; } void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) { if (this->supported) { File dir = SD.open(str_dir); while (true) { File entry = dir.openNextFile(); if (!entry) { break; } if (entry.isDirectory()) continue; String file_name = entry.name(); if (ext != "") { if (file_name.endsWith(ext)) { file_names->add(file_name); } } else file_names->add(file_name); } } } void SDInterface::listDir(String str_dir){ if (this->supported) { File dir = SD.open(str_dir); while (true) { File entry = dir.openNextFile(); if (! entry) { break; } //for (uint8_t i = 0; i < numTabs; i++) //{ // Serial.print('\t'); //} Serial.print(entry.name()); Serial.print("\t"); Serial.println(entry.size()); entry.close(); } } } void SDInterface::runUpdate(String file_name) { if (file_name == "") file_name = "/update.bin"; #ifdef HAS_SCREEN display_obj.tft.setTextWrap(false); display_obj.tft.setFreeFont(NULL); display_obj.tft.setCursor(0, TFT_HEIGHT / 3); display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_WHITE); display_obj.tft.println("Opening " + file_name + "..."); #endif File updateBin = SD.open(file_name); if (updateBin) { if(updateBin.isDirectory()){ #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_RED); display_obj.tft.println(F(text_table2[0])); #endif Serial.println("Error, could not find \"" + file_name + "\""); #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_WHITE); #endif updateBin.close(); return; } size_t updateSize = updateBin.size(); if (updateSize > 0) { #ifdef HAS_SCREEN display_obj.tft.println(F(text_table2[1])); #endif Serial.println(F("Starting update over SD. Please wait...")); this->performUpdate(updateBin, updateSize); } else { #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_RED); display_obj.tft.println(F(text_table2[2])); #endif Serial.println(F("Error, file is empty")); #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_WHITE); #endif return; } updateBin.close(); // whe finished remove the binary from sd card to indicate end of the process #ifdef HAS_SCREEN display_obj.tft.println(F(text_table2[3])); #endif const esp_partition_t *running = esp_ota_get_running_partition(); Serial.printf("Currently running: %s at 0x%X\n", running->label, running->address); const esp_partition_t *next = esp_ota_get_next_update_partition(NULL); Serial.printf("Next OTA partition: %s at 0x%X\n", next->label, next->address); esp_err_t result = esp_ota_set_boot_partition(next); Serial.printf("esp_ota_set_boot_partition result: %s\n", esp_err_to_name(result)); Serial.println(F("rebooting...")); //SD.remove("/update.bin"); delay(1000); ESP.restart(); } else { #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_RED); display_obj.tft.println(F(text_table2[4])); #endif Serial.println(F("Could not load update.bin from sd root")); #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_WHITE); #endif } } void SDInterface::performUpdate(Stream &updateSource, size_t updateSize) { if (Update.begin(updateSize)) { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[5] + String(updateSize)); display_obj.tft.println(F(text_table2[6])); #endif size_t written = Update.writeStream(updateSource); if (written == updateSize) { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[7] + String(written) + text_table2[10]); #endif Serial.println("Written : " + String(written) + " successfully"); } else { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[8] + String(written) + "/" + String(updateSize) + text_table2[9]); #endif Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?"); } if (Update.end()) { Serial.println("OTA done!"); if (Update.isFinished()) { #ifdef HAS_SCREEN display_obj.tft.println(F(text_table2[11])); #endif Serial.println(F("Update successfully completed. Rebooting.")); } else { #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_RED); display_obj.tft.println(text_table2[12]); #endif Serial.println(F("Update not finished? Something went wrong!")); #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_WHITE); #endif } } else { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[13] + String(Update.getError())); #endif Serial.println("Error Occurred. Error #: " + String(Update.getError())); } } else { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[14]); #endif Serial.println(F("Not enough space to begin OTA")); } } bool SDInterface::checkDetectPin() { #ifdef KIT if (digitalRead(SD_DET) == LOW) return true; else return false; #endif return false; } void SDInterface::main() { if (!this->supported) { if (checkDetectPin()) { delay(100); this->initSD(); } } }