From 66580f32c2f4d39a82b77e4b6982e7ea6dde0766 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 16 Nov 2018 22:39:16 -0600 Subject: [PATCH] Make CardReader class static (#12451) * Make CardReader a static class * Make CardReader flags into bitfields --- Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp | 10 +- Marlin/src/HAL/HAL_LPC1768/main.cpp | 2 +- .../HAL_STM32F1/persistent_store_sdcard.cpp | 4 +- Marlin/src/Marlin.cpp | 2 +- Marlin/src/feature/power_loss_recovery.cpp | 4 +- Marlin/src/feature/power_loss_recovery.h | 2 +- Marlin/src/gcode/queue.cpp | 12 +- .../sdcard/M20-M30_M32-M34_M524_M928.cpp | 12 +- Marlin/src/lcd/extensible_ui/ui_api.cpp | 12 +- Marlin/src/lcd/malyanlcd.cpp | 6 +- Marlin/src/lcd/menu/menu_main.cpp | 4 +- Marlin/src/lcd/menu/menu_sdcard.cpp | 2 +- Marlin/src/sd/SdFatConfig.h | 4 +- Marlin/src/sd/cardreader.cpp | 212 ++++++++++++------ Marlin/src/sd/cardreader.h | 183 ++++++++------- 15 files changed, 281 insertions(+), 190 deletions(-) diff --git a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp index 1054f5ab34..cdb81b2489 100644 --- a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp +++ b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp @@ -19,7 +19,7 @@ void sd_mmc_spi_mem_init(void) { } Ctrl_status sd_mmc_spi_test_unit_ready(void) { - if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK) + if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK) return CTRL_NO_PRESENT; return CTRL_GOOD; } @@ -27,7 +27,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready(void) { // NOTE: This function is defined as returning the address of the last block // in the card, which is cardSize() - 1 Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) { - if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK) + if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK) return CTRL_NO_PRESENT; *nb_sector = card.getSd2Card().cardSize() - 1; return CTRL_GOOD; @@ -42,7 +42,7 @@ bool sd_mmc_spi_wr_protect(void) { } bool sd_mmc_spi_removal(void) { - if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK) + if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK) return true; return false; } @@ -61,7 +61,7 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE]; // #define DEBUG_MMC Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) { - if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK) + if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK) return CTRL_NO_PRESENT; #ifdef DEBUG_MMC @@ -95,7 +95,7 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) { } Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) { - if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK) + if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK) return CTRL_NO_PRESENT; #ifdef DEBUG_MMC diff --git a/Marlin/src/HAL/HAL_LPC1768/main.cpp b/Marlin/src/HAL/HAL_LPC1768/main.cpp index 02207c6109..c4aea39660 100644 --- a/Marlin/src/HAL/HAL_LPC1768/main.cpp +++ b/Marlin/src/HAL/HAL_LPC1768/main.cpp @@ -106,7 +106,7 @@ void HAL_idletask(void) { // the disk if Marlin has it mounted. Unfortuately there is currently no way // to unmount the disk from the LCD menu. // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN()) - if (card.cardOK) + if (card.flag.cardOK) MSC_Aquire_Lock(); else MSC_Release_Lock(); diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp index 349abba246..757d62fd59 100644 --- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp +++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp @@ -41,7 +41,7 @@ char HAL_STM32F1_eeprom_content[HAL_STM32F1_EEPROM_SIZE]; char eeprom_filename[] = "eeprom.dat"; bool PersistentStore::access_start() { - if (!card.cardOK) return false; + if (!card.flag.cardOK) return false; int16_t bytes_read = 0; constexpr char eeprom_zero = 0xFF; card.openFile(eeprom_filename, true); @@ -54,7 +54,7 @@ bool PersistentStore::access_start() { } bool PersistentStore::access_finish() { - if (!card.cardOK) return false; + if (!card.flag.cardOK) return false; card.openFile(eeprom_filename, true); int16_t bytes_written = card.write(HAL_STM32F1_eeprom_content, HAL_STM32F1_EEPROM_SIZE); card.closefile(); diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp index f2522f2ee9..50957517b5 100644 --- a/Marlin/src/Marlin.cpp +++ b/Marlin/src/Marlin.cpp @@ -967,7 +967,7 @@ void loop() { #if ENABLED(SDSUPPORT) card.checkautostart(); - if (card.abort_sd_printing) { + if (card.flag.abort_sd_printing) { card.stopSDPrint( #if SD_RESORT true diff --git a/Marlin/src/feature/power_loss_recovery.cpp b/Marlin/src/feature/power_loss_recovery.cpp index 3661f55512..1971dde898 100644 --- a/Marlin/src/feature/power_loss_recovery.cpp +++ b/Marlin/src/feature/power_loss_recovery.cpp @@ -84,8 +84,8 @@ void PrintJobRecovery::changed() { */ void PrintJobRecovery::check() { if (enabled) { - if (!card.cardOK) card.initsd(); - if (card.cardOK) { + if (!card.flag.cardOK) card.initsd(); + if (card.flag.cardOK) { load(); if (!valid()) return purge(); enqueue_and_echo_commands_P(PSTR("M1000 S")); diff --git a/Marlin/src/feature/power_loss_recovery.h b/Marlin/src/feature/power_loss_recovery.h index 0de0457c00..356ff13f21 100644 --- a/Marlin/src/feature/power_loss_recovery.h +++ b/Marlin/src/feature/power_loss_recovery.h @@ -68,7 +68,7 @@ typedef struct { char command_queue[BUFSIZE][MAX_CMD_SIZE]; // SD Filename and position - char sd_filename[MAXPATHNAMELENGTH]; + char sd_filename[MAXPATHNAMELENGTH + 1]; uint32_t sdpos; // Job elapsed time diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp index 4cf508dca4..0b6bb4ba77 100644 --- a/Marlin/src/gcode/queue.cpp +++ b/Marlin/src/gcode/queue.cpp @@ -503,7 +503,7 @@ static int read_serial(const uint8_t index) { break; case StreamState::STREAM_COMPLETE: stream_state = StreamState::STREAM_RESET; - card.binary_mode = false; + card.flag.binary_mode = false; card.closefile(); CARD_ECHO_P("echo: "); CARD_ECHO_P(card.filename); @@ -514,7 +514,7 @@ static int read_serial(const uint8_t index) { return; case StreamState::STREAM_FAILED: stream_state = StreamState::STREAM_RESET; - card.binary_mode = false; + card.flag.binary_mode = false; card.closefile(); card.removeFile(card.filename); CARD_ECHOLN_P("echo: File transfer failed"); @@ -549,7 +549,7 @@ inline void get_serial_commands() { ; #if ENABLED(FAST_FILE_TRANSFER) - if (card.saving && card.binary_mode) { + if (card.flag.saving && card.flag.binary_mode) { /** * For binary stream file transfer, use serial_line_buffer as the working * receive buffer (which limits the packet size to MAX_CMD_SIZE). @@ -630,7 +630,7 @@ inline void get_serial_commands() { gcode_LastN = gcode_N; } #if ENABLED(SDSUPPORT) - else if (card.saving && strcmp(command, "M29") != 0) // No line number with M29 in Pronterface + else if (card.flag.saving && strcmp(command, "M29") != 0) // No line number with M29 in Pronterface return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i); #endif @@ -838,7 +838,7 @@ void advance_command_queue() { #if ENABLED(SDSUPPORT) - if (card.saving) { + if (card.flag.saving) { char* command = command_queue[cmd_queue_index_r]; if (strstr_P(command, PSTR("M29"))) { // M29 closes the file @@ -860,7 +860,7 @@ void advance_command_queue() { else { // Write the string from the read buffer to SD card.write_command(command); - if (card.logging) + if (card.flag.logging) gcode.process_next_command(); // The card is saving because it's logging else ok_to_send(); diff --git a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp index a8de7f44b7..379c4e054b 100644 --- a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp +++ b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp @@ -118,7 +118,7 @@ void GcodeSuite::M25() { * M26: Set SD Card file index */ void GcodeSuite::M26() { - if (card.cardOK && parser.seenval('S')) + if (card.flag.cardOK && parser.seenval('S')) card.setIndex(parser.value_long()); } @@ -178,7 +178,7 @@ void GcodeSuite::M28() { } // Binary transfer mode - if ((card.binary_mode = binary_mode)) { + if ((card.flag.binary_mode = binary_mode)) { SERIAL_ECHO_START_P(port); SERIAL_ECHO_P(port, " preparing to receive: "); SERIAL_ECHOLN_P(port, p); @@ -202,14 +202,14 @@ void GcodeSuite::M28() { * Processed in write to file routine */ void GcodeSuite::M29() { - // card.saving = false; + // card.flag.saving = false; } /** * M30 : Delete SD Card file */ void GcodeSuite::M30() { - if (card.cardOK) { + if (card.flag.cardOK) { card.closefile(); card.removeFile(parser.string_arg); } @@ -228,7 +228,7 @@ void GcodeSuite::M30() { void GcodeSuite::M32() { if (IS_SD_PRINTING()) planner.synchronize(); - if (card.cardOK) { + if (card.flag.cardOK) { const bool call_procedure = parser.boolval('P'); card.openFile(parser.string_arg, true, call_procedure); @@ -286,7 +286,7 @@ void GcodeSuite::M32() { * M524: Abort the current SD print job (started with M24) */ void GcodeSuite::M524() { - if (IS_SD_PRINTING()) card.abort_sd_printing = true; + if (IS_SD_PRINTING()) card.flag.abort_sd_printing = true; } /** diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp index 932a276af4..390b081174 100644 --- a/Marlin/src/lcd/extensible_ui/ui_api.cpp +++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp @@ -575,7 +575,7 @@ namespace ExtUI { } bool isPrintingFromMedia() { - return IFSD(card.cardOK && card.isFileOpen(), false); + return IFSD(card.flag.cardOK && card.isFileOpen(), false); } bool isPrinting() { @@ -583,7 +583,7 @@ namespace ExtUI { } bool isMediaInserted() { - return IFSD(IS_SD_INSERTED() && card.cardOK, false); + return IFSD(IS_SD_INSERTED() && card.flag.cardOK, false); } void pausePrint() { @@ -612,7 +612,7 @@ namespace ExtUI { void stopPrint() { #if ENABLED(SDSUPPORT) wait_for_heatup = wait_for_user = false; - card.abort_sd_printing = true; + card.flag.abort_sd_printing = true; ExtUI::onStatusChanged(PSTR(MSG_PRINT_ABORTED)); #endif } @@ -648,7 +648,7 @@ namespace ExtUI { } bool FileList::isDir() { - return IFSD(card.filenameIsDir, false); + return IFSD(card.flag.filenameIsDir, false); } uint16_t FileList::count() { @@ -697,13 +697,13 @@ void MarlinUI::update() { last_sd_status = sd_status; if (sd_status) { card.initsd(); - if (card.cardOK) + if (card.flag.cardOK) ExtUI::onMediaInserted(); else ExtUI::onMediaError(); } else { - const bool ok = card.cardOK; + const bool ok = card.flag.cardOK; card.release(); if (ok) ExtUI::onMediaRemoved(); } diff --git a/Marlin/src/lcd/malyanlcd.cpp b/Marlin/src/lcd/malyanlcd.cpp index 3e57cb1b3d..5380497ee8 100644 --- a/Marlin/src/lcd/malyanlcd.cpp +++ b/Marlin/src/lcd/malyanlcd.cpp @@ -278,7 +278,7 @@ void process_lcd_p_command(const char* command) { // There may be a difference in how V1 and V2 LCDs handle subdirectory // prints. Investigate more. This matches the V1 motion controller actions // but the V2 LCD switches to "print" mode on {SYS:DIR} response. - if (card.filenameIsDir) { + if (card.flag.filenameIsDir) { card.chdir(card.filename); write_to_lcd_P(PSTR("{SYS:DIR}")); } @@ -330,7 +330,7 @@ void process_lcd_s_command(const char* command) { case 'L': { #if ENABLED(SDSUPPORT) - if (!card.cardOK) card.initsd(); + if (!card.flag.cardOK) card.initsd(); // A more efficient way to do this would be to // implement a callback in the ls_SerialPrint code, but @@ -342,7 +342,7 @@ void process_lcd_s_command(const char* command) { uint16_t file_count = card.get_num_Files(); for (uint16_t i = 0; i < file_count; i++) { card.getfilename(i); - sprintf_P(message_buffer, card.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename()); + sprintf_P(message_buffer, card.flag.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename()); write_to_lcd(message_buffer); } diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp index fdddc95b14..0287036f70 100644 --- a/Marlin/src/lcd/menu/menu_main.cpp +++ b/Marlin/src/lcd/menu/menu_main.cpp @@ -58,7 +58,7 @@ void lcd_sdcard_stop() { wait_for_heatup = wait_for_user = false; - card.abort_sd_printing = true; + card.flag.abort_sd_printing = true; ui.setstatusPGM(PSTR(MSG_PRINT_ABORTED), -1); ui.return_to_status(); } @@ -86,7 +86,7 @@ void menu_main() { MENU_BACK(MSG_WATCH); #if ENABLED(SDSUPPORT) - if (card.cardOK) { + if (card.flag.cardOK) { if (card.isFileOpen()) { if (IS_SD_PRINTING()) MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause); diff --git a/Marlin/src/lcd/menu/menu_sdcard.cpp b/Marlin/src/lcd/menu/menu_sdcard.cpp index 7f40530030..1ea3379926 100644 --- a/Marlin/src/lcd/menu/menu_sdcard.cpp +++ b/Marlin/src/lcd/menu/menu_sdcard.cpp @@ -125,7 +125,7 @@ void menu_sdcard() { card.getfilename_sorted(nr); - if (card.filenameIsDir) + if (card.flag.filenameIsDir) MENU_ITEM(sdfolder, MSG_CARD_MENU, card); else MENU_ITEM(sdfile, MSG_CARD_MENU, card); diff --git a/Marlin/src/sd/SdFatConfig.h b/Marlin/src/sd/SdFatConfig.h index d203aa38ae..5f90b0102e 100644 --- a/Marlin/src/sd/SdFatConfig.h +++ b/Marlin/src/sd/SdFatConfig.h @@ -106,7 +106,7 @@ * Defines for 8.3 and long (vfat) filenames */ -#define FILENAME_LENGTH 13 // Number of UTF-16 characters per entry +#define FILENAME_LENGTH 12 // Number of UTF-16 characters per entry // Total bytes needed to store a single long filename -#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1) +#define LONG_FILENAME_LENGTH ((FILENAME_LENGTH) * (MAX_VFAT_ENTRIES)) diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 1610f2ff45..949c530a06 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -45,7 +45,83 @@ #include "../feature/pause.h" #endif -#include +// public: + +card_flags_t CardReader::flag; +char CardReader::filename[FILENAME_LENGTH + 1], CardReader::longFilename[LONG_FILENAME_LENGTH + 1]; +int8_t CardReader::autostart_index; + +#if ENABLED(FAST_FILE_TRANSFER) + #if NUM_SERIAL > 1 + uint8_t CardReader::transfer_port; + #endif +#endif + +// private: + +SdFile CardReader::root, CardReader::workDir, CardReader::workDirParents[MAX_DIR_DEPTH]; +uint8_t CardReader::workDirDepth; + +#if ENABLED(SDCARD_SORT_ALPHA) + uint16_t CardReader::sort_count; + #if ENABLED(SDSORT_GCODE) + bool CardReader::sort_alpha; + int CardReader::sort_folders; + //bool CardReader::sort_reverse; + #endif + + #if ENABLED(SDSORT_DYNAMIC_RAM) + uint8_t *CardReader::sort_order; + #else + uint8_t CardReader::sort_order[SDSORT_LIMIT]; + #endif + + #if ENABLED(SDSORT_USES_RAM) + + #if ENABLED(SDSORT_CACHE_NAMES) + #if ENABLED(SDSORT_DYNAMIC_RAM) + char **CardReader::sortshort, **CardReader::sortnames; + #else + char CardReader::sortshort[SDSORT_LIMIT][FILENAME_LENGTH + 1]; + char CardReader::sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1]; + #endif + #elif DISABLED(SDSORT_USES_STACK) + char CardReader::sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1]; + #endif + + #if HAS_FOLDER_SORTING + #if ENABLED(SDSORT_DYNAMIC_RAM) + uint8_t *CardReader::isDir; + #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK) + uint8_t CardReader::isDir[(SDSORT_LIMIT+7)>>3]; + #endif + #endif + + #endif // SDSORT_USES_RAM + +#endif // SDCARD_SORT_ALPHA + +Sd2Card CardReader::sd2card; +SdVolume CardReader::volume; +SdFile CardReader::file; + +uint8_t CardReader::file_subcall_ctr; +uint32_t CardReader::filespos[SD_PROCEDURE_DEPTH]; +char CardReader::proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH + 1]; + +uint32_t CardReader::filesize, CardReader::sdpos; + +LsAction CardReader::lsAction; //stored for recursion. +uint16_t CardReader::nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. +char *CardReader::diveDirName; + +#if ENABLED(AUTO_REPORT_SD_STATUS) + uint8_t CardReader::auto_report_sd_interval; + millis_t CardReader::next_sd_report_ms; + #if NUM_SERIAL > 1 + int8_t CardReader::serialport; + #endif +#endif CardReader::CardReader() { #if ENABLED(SDCARD_SORT_ALPHA) @@ -56,9 +132,8 @@ CardReader::CardReader() { //sort_reverse = false; #endif #endif - sdprinting = cardOK = saving = logging = false; - filesize = 0; - sdpos = 0; + flag.sdprinting = flag.cardOK = flag.saving = flag.logging = false; + filesize = sdpos = 0; file_subcall_ctr = 0; workDirDepth = 0; @@ -73,7 +148,7 @@ CardReader::CardReader() { #endif } -char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters +char *createFilename(char *buffer, const dir_t &p) { char *pos = buffer; for (uint8_t i = 0; i < 11; i++) { if (p.name[i] == ' ') continue; @@ -108,7 +183,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // Get the short name for the item, which we know is a folder - char dosFilename[FILENAME_LENGTH]; + char dosFilename[FILENAME_LENGTH + 1]; createFilename(dosFilename, p); // Allocate enough stack space for the full path to a folder, trailing slash, and nul @@ -120,8 +195,8 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m // It contains the full path to the "parent" argument. // We now have the full path to the item in this folder. strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty - strcat(path, dosFilename); // FILENAME_LENGTH-1 characters maximum - strcat(path, "/"); // 1 character + strcat(path, dosFilename); // FILENAME_LENGTH characters maximum + strcat(path, "/"); // 1 character // Serial.print(path); @@ -150,9 +225,9 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue; - filenameIsDir = DIR_IS_SUBDIR(&p); + flag.filenameIsDir = DIR_IS_SUBDIR(&p); - if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue; + if (!flag.filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue; switch (lsAction) { // 1 based file count case LS_Count: @@ -242,7 +317,7 @@ void CardReader::ls( SERIAL_PROTOCOL_P(port, longFilename[0] ? longFilename : "???"); // If the filename was printed then that's it - if (!filenameIsDir) break; + if (!flag.filenameIsDir) break; // SERIAL_ECHOPGM_P(port, "Opening dir: "); SERIAL_ECHOLN_P(port, segment); @@ -275,7 +350,7 @@ void CardReader::printFilename( #endif ) { if (file.isOpen()) { - char dosFilename[FILENAME_LENGTH]; + char dosFilename[FILENAME_LENGTH + 1]; file.getFilename(dosFilename); SERIAL_ECHO_P(port, dosFilename); #if ENABLED(LONG_FILENAME_HOST_SUPPORT) @@ -293,7 +368,7 @@ void CardReader::printFilename( } void CardReader::initsd() { - cardOK = false; + flag.cardOK = false; if (root.isOpen()) root.close(); #ifndef SPI_SPEED @@ -318,7 +393,7 @@ void CardReader::initsd() { SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL); } else { - cardOK = true; + flag.cardOK = true; SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(MSG_SD_CARD_OK); } @@ -327,7 +402,7 @@ void CardReader::initsd() { void CardReader::release() { stopSDPrint(); - cardOK = false; + flag.cardOK = false; } void CardReader::openAndPrintFile(const char *name) { @@ -339,8 +414,8 @@ void CardReader::openAndPrintFile(const char *name) { } void CardReader::startFileprint() { - if (cardOK) { - sdprinting = true; + if (flag.cardOK) { + flag.sdprinting = true; #if SD_RESORT flush_presort(); #endif @@ -355,7 +430,7 @@ void CardReader::stopSDPrint( #if ENABLED(ADVANCED_PAUSE_FEATURE) did_pause_print = 0; #endif - sdprinting = abort_sd_printing = false; + flag.sdprinting = flag.abort_sd_printing = false; if (isFileOpen()) file.close(); #if SD_RESORT if (re_sort) presort(); @@ -363,7 +438,7 @@ void CardReader::stopSDPrint( } void CardReader::openLogFile(char * const path) { - logging = true; + flag.logging = true; openFile(path, false); } @@ -380,7 +455,7 @@ void CardReader::getAbsFilename(char *t) { for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir appendAtom(workDirParents[i], t, cnt); - if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) { + if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH) - 1) { // Leave room for filename and nul appendAtom(file, t, cnt); --t; } @@ -389,7 +464,7 @@ void CardReader::getAbsFilename(char *t) { void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) { - if (!cardOK) return; + if (!flag.cardOK) return; uint8_t doing = 0; if (isFileOpen()) { // Replacing current file or doing a subroutine @@ -464,7 +539,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall SERIAL_EOL(); } else { - saving = true; + flag.saving = true; getfilename(0, fname); #if ENABLED(EMERGENCY_PARSER) emergency_parser.disable(); @@ -476,7 +551,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall } void CardReader::removeFile(const char * const name) { - if (!cardOK) return; + if (!flag.cardOK) return; //stopSDPrint(); @@ -504,7 +579,7 @@ void CardReader::getStatus( const int8_t port/*= -1*/ #endif ) { - if (cardOK && sdprinting) { + if (flag.cardOK && flag.sdprinting) { SERIAL_PROTOCOLPGM_P(port, MSG_SD_PRINTING_BYTE); SERIAL_PROTOCOL_P(port, sdpos); SERIAL_PROTOCOLCHAR_P(port, '/'); @@ -543,11 +618,11 @@ void CardReader::write_command(char *buf) { void CardReader::checkautostart() { - if (autostart_index < 0 || sdprinting) return; + if (autostart_index < 0 || flag.sdprinting) return; - if (!cardOK) initsd(); + if (!flag.cardOK) initsd(); - if (cardOK + if (flag.cardOK #if ENABLED(POWER_LOSS_RECOVERY) && !recovery.valid() // Don't run auto#.g when a resume file exists #endif @@ -576,7 +651,7 @@ void CardReader::beginautostart() { void CardReader::closefile(const bool store_location) { file.sync(); file.close(); - saving = logging = false; + flag.saving = flag.logging = false; sdpos = 0; #if ENABLED(EMERGENCY_PARSER) emergency_parser.enable(); @@ -603,7 +678,7 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) { if (nr < sort_count) { strcpy(filename, sortshort[nr]); strcpy(longFilename, sortnames[nr]); - filenameIsDir = TEST(isDir[nr>>3], nr & 0x07); + flag.filenameIsDir = TEST(isDir[nr>>3], nr & 0x07); return; } #endif // SDSORT_CACHE_NAMES @@ -712,6 +787,33 @@ void CardReader::setroot() { ); } + #if ENABLED(SDSORT_USES_RAM) + #if ENABLED(SDSORT_DYNAMIC_RAM) + // Use dynamic method to copy long filename + #define SET_SORTNAME(I) (sortnames[I] = strdup(longest_filename())) + #if ENABLED(SDSORT_CACHE_NAMES) + // When caching also store the short name, since + // we're replacing the getfilename() behavior. + #define SET_SORTSHORT(I) (sortshort[I] = strdup(filename)) + #else + #define SET_SORTSHORT(I) NOOP + #endif + #else + // Copy filenames into the static array + #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH + #define SET_SORTNAME(I) do{ strncpy(sortnames[I], longest_filename(), SORTED_LONGNAME_MAXLEN); \ + sortnames[I][SORTED_LONGNAME_MAXLEN] = '\0'; }while(0) + #else + #define SET_SORTNAME(I) strncpy(sortnames[I], longest_filename(), SORTED_LONGNAME_MAXLEN) + #endif + #if ENABLED(SDSORT_CACHE_NAMES) + #define SET_SORTSHORT(I) strcpy(sortshort[I], filename) + #else + #define SET_SORTSHORT(I) NOOP + #endif + #endif + #endif + /** * Read all the files and produce a sort key * @@ -754,7 +856,7 @@ void CardReader::setroot() { sortnames = new char*[fileCnt]; #endif #elif ENABLED(SDSORT_USES_STACK) - char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN]; + char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN + 1]; #endif // Folder sorting needs 1 bit per entry for flags. @@ -783,33 +885,15 @@ void CardReader::setroot() { // If using RAM then read all filenames now. #if ENABLED(SDSORT_USES_RAM) getfilename(i); - #if ENABLED(SDSORT_DYNAMIC_RAM) - // Use dynamic method to copy long filename - sortnames[i] = strdup(longest_filename()); - #if ENABLED(SDSORT_CACHE_NAMES) - // When caching also store the short name, since - // we're replacing the getfilename() behavior. - sortshort[i] = strdup(filename); - #endif - #else - // Copy filenames into the static array - #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH - strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN); - sortnames[i][SORTED_LONGNAME_MAXLEN - 1] = '\0'; - #else - strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN); - #endif - #if ENABLED(SDSORT_CACHE_NAMES) - strcpy(sortshort[i], filename); - #endif - #endif + SET_SORTNAME(i); + SET_SORTSHORT(i); // char out[30]; - // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]); + // sprintf_P(out, PSTR("---- %i %s %s"), i, flag.filenameIsDir ? "D" : " ", sortnames[i]); // SERIAL_ECHOLN(out); #if HAS_FOLDER_SORTING const uint16_t bit = i & 0x07, ind = i >> 3; if (bit == 0) isDir[ind] = 0x00; - if (filenameIsDir) isDir[ind] |= _BV(bit); + if (flag.filenameIsDir) isDir[ind] |= _BV(bit); #endif #endif } @@ -837,7 +921,7 @@ void CardReader::setroot() { ? _SORT_CMP_NODIR() \ : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0) #else - #define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1)) + #define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1)) #endif #endif @@ -847,7 +931,7 @@ void CardReader::setroot() { getfilename(o1); strcpy(name1, longest_filename()); // save (or getfilename below will trounce it) #if HAS_FOLDER_SORTING - bool dir1 = filenameIsDir; + bool dir1 = flag.filenameIsDir; #endif getfilename(o2); char *name2 = longest_filename(); // use the string in-place @@ -885,27 +969,17 @@ void CardReader::setroot() { else { sort_order[0] = 0; #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES) - getfilename(0); #if ENABLED(SDSORT_DYNAMIC_RAM) sortnames = new char*[1]; - sortnames[0] = strdup(longest_filename()); // malloc #if ENABLED(SDSORT_CACHE_NAMES) sortshort = new char*[1]; - sortshort[0] = strdup(filename); // malloc #endif isDir = new uint8_t[1]; - #else - #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH - strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN); - sortnames[0][SORTED_LONGNAME_MAXLEN - 1] = '\0'; - #else - strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN); - #endif - #if ENABLED(SDSORT_CACHE_NAMES) - strcpy(sortshort[0], filename); - #endif #endif - isDir[0] = filenameIsDir ? 0x01 : 0x00; + getfilename(0); + SET_SORTNAME(0); + SET_SORTSHORT(0); + isDir[0] = flag.filenameIsDir ? 0x01 : 0x00; #endif } @@ -1007,7 +1081,7 @@ void CardReader::printingHasFinished() { } void CardReader::openJobRecoveryFile(const bool read) { - if (!cardOK) return; + if (!flag.cardOK) return; if (recovery.file.isOpen()) return; if (!recovery.file.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) { SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name); diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index c8f114822e..57e4376300 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -27,106 +27,121 @@ #define SD_RESORT ENABLED(SDCARD_SORT_ALPHA) && ENABLED(SDSORT_DYNAMIC_RAM) -#define MAX_DIR_DEPTH 10 // Maximum folder depth +#define MAX_DIR_DEPTH 10 // Maximum folder depth +#define MAXDIRNAMELENGTH 8 // DOS folder name size +#define MAXPATHNAMELENGTH (1 + (MAXDIRNAMELENGTH + 1) * (MAX_DIR_DEPTH) + 1 + FILENAME_LENGTH) // "/" + N * ("ADIRNAME/") + "filename.ext" #include "SdFile.h" enum LsAction : uint8_t { LS_SerialPrint, LS_Count, LS_GetFilename }; +typedef struct { + bool saving:1, + logging:1, + sdprinting:1, + cardOK:1, + filenameIsDir:1, + abort_sd_printing:1 + #if ENABLED(FAST_FILE_TRANSFER) + , binary_mode:1 + #endif + ; +} card_flags_t; + class CardReader { public: CardReader(); - void initsd(); - void write_command(char *buf); + static void initsd(); + static void write_command(char *buf); - void beginautostart(); - void checkautostart(); + static void beginautostart(); + static void checkautostart(); - void openFile(char * const path, const bool read, const bool subcall=false); - void openLogFile(char * const path); - void removeFile(const char * const name); - void closefile(const bool store_location=false); - void release(); - void openAndPrintFile(const char *name); - void startFileprint(); - void stopSDPrint( + static void openFile(char * const path, const bool read, const bool subcall=false); + static void openLogFile(char * const path); + static void removeFile(const char * const name); + static void closefile(const bool store_location=false); + static void release(); + static void openAndPrintFile(const char *name); + static void startFileprint(); + static void stopSDPrint( #if SD_RESORT const bool re_sort=false #endif ); - void getStatus( + static void getStatus( #if NUM_SERIAL > 1 const int8_t port = -1 #endif ); - void printingHasFinished(); - void printFilename( + static void printingHasFinished(); + static void printFilename( #if NUM_SERIAL > 1 const int8_t port = -1 #endif ); #if ENABLED(LONG_FILENAME_HOST_SUPPORT) - void printLongPath(char *path + static void printLongPath(char *path #if NUM_SERIAL > 1 , const int8_t port = -1 #endif ); #endif - void getfilename(uint16_t nr, const char* const match=NULL); - uint16_t getnrfilenames(); + static void getfilename(uint16_t nr, const char* const match=NULL); + static uint16_t getnrfilenames(); - void getAbsFilename(char *t); + static void getAbsFilename(char *t); - void ls( + static void ls( #if NUM_SERIAL > 1 const int8_t port = -1 #endif ); - void chdir(const char *relpath); - int8_t updir(); - void setroot(); + static void chdir(const char *relpath); + static int8_t updir(); + static void setroot(); - const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo); + static const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo); - uint16_t get_num_Files(); + static uint16_t get_num_Files(); #if ENABLED(SDCARD_SORT_ALPHA) - void presort(); - void getfilename_sorted(const uint16_t nr); + static void presort(); + static void getfilename_sorted(const uint16_t nr); #if ENABLED(SDSORT_GCODE) - FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); } - FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); } - //FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; } + FORCE_INLINE static void setSortOn(bool b) { sort_alpha = b; presort(); } + FORCE_INLINE static void setSortFolders(int i) { sort_folders = i; presort(); } + //FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; } #endif #else - FORCE_INLINE void getfilename_sorted(const uint16_t nr) { getfilename(nr); } + FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { getfilename(nr); } #endif #if ENABLED(POWER_LOSS_RECOVERY) - bool jobRecoverFileExists(); - void openJobRecoveryFile(const bool read); - void removeJobRecoveryFile(); + static bool jobRecoverFileExists(); + static void openJobRecoveryFile(const bool read); + static void removeJobRecoveryFile(); #endif - inline void pauseSDPrint() { sdprinting = false; } - inline bool isFileOpen() { return file.isOpen(); } - inline bool eof() { return sdpos >= filesize; } - inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); } - inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); } - inline uint32_t getIndex() { return sdpos; } - inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; } - inline char* getWorkDirName() { workDir.getFilename(filename); return filename; } - inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; } - inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; } + static inline void pauseSDPrint() { flag.sdprinting = false; } + static inline bool isFileOpen() { return file.isOpen(); } + static inline bool eof() { return sdpos >= filesize; } + static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); } + static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); } + static inline uint32_t getIndex() { return sdpos; } + static inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; } + static inline char* getWorkDirName() { workDir.getFilename(filename); return filename; } + static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; } + static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; } - Sd2Card& getSd2Card() { return sd2card; } + static Sd2Card& getSd2Card() { return sd2card; } #if ENABLED(AUTO_REPORT_SD_STATUS) - void auto_report_sd_status(void); - inline void set_auto_report_interval(uint8_t v + static void auto_report_sd_status(void); + static inline void set_auto_report_interval(uint8_t v #if NUM_SERIAL > 1 , int8_t port #endif @@ -140,40 +155,39 @@ public: } #endif - inline char* longest_filename() { return longFilename[0] ? longFilename : filename; } + static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; } public: - bool saving, logging, sdprinting, cardOK, filenameIsDir, abort_sd_printing; - char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH]; - int8_t autostart_index; + static card_flags_t flag; + static char filename[FILENAME_LENGTH + 1], longFilename[LONG_FILENAME_LENGTH + 1]; + static int8_t autostart_index; #if ENABLED(FAST_FILE_TRANSFER) - bool binary_mode; #if NUM_SERIAL > 1 - uint8_t transfer_port; + static uint8_t transfer_port; #else static constexpr uint8_t transfer_port = 0; #endif #endif private: - SdFile root, workDir, workDirParents[MAX_DIR_DEPTH]; - uint8_t workDirDepth; + static SdFile root, workDir, workDirParents[MAX_DIR_DEPTH]; + static uint8_t workDirDepth; // Sort files and folders alphabetically. #if ENABLED(SDCARD_SORT_ALPHA) - uint16_t sort_count; // Count of sorted items in the current directory + static uint16_t sort_count; // Count of sorted items in the current directory #if ENABLED(SDSORT_GCODE) - bool sort_alpha; // Flag to enable / disable the feature - int sort_folders; // Flag to enable / disable folder sorting - //bool sort_reverse; // Flag to enable / disable reverse sorting + static bool sort_alpha; // Flag to enable / disable the feature + static int sort_folders; // Folder sorting before/none/after + //static bool sort_reverse; // Flag to enable / disable reverse sorting #endif // By default the sort index is static #if ENABLED(SDSORT_DYNAMIC_RAM) - uint8_t *sort_order; + static uint8_t *sort_order; #else - uint8_t sort_order[SDSORT_LIMIT]; + static uint8_t sort_order[SDSORT_LIMIT]; #endif #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM) @@ -188,21 +202,21 @@ private: // If using dynamic ram for names, allocate on the heap. #if ENABLED(SDSORT_CACHE_NAMES) #if ENABLED(SDSORT_DYNAMIC_RAM) - char **sortshort, **sortnames; + static char **sortshort, **sortnames; #else - char sortshort[SDSORT_LIMIT][FILENAME_LENGTH]; - char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN]; + static char sortshort[SDSORT_LIMIT][FILENAME_LENGTH + 1]; + static char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1]; #endif #elif DISABLED(SDSORT_USES_STACK) - char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN]; + static char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1]; #endif // Folder sorting uses an isDir array when caching items. #if HAS_FOLDER_SORTING #if ENABLED(SDSORT_DYNAMIC_RAM) - uint8_t *isDir; + static uint8_t *isDir; #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK) - uint8_t isDir[(SDSORT_LIMIT+7)>>3]; + static uint8_t isDir[(SDSORT_LIMIT+7)>>3]; #endif #endif @@ -210,28 +224,31 @@ private: #endif // SDCARD_SORT_ALPHA - Sd2Card sd2card; - SdVolume volume; - SdFile file; + static Sd2Card sd2card; + static SdVolume volume; + static SdFile file; - #define SD_PROCEDURE_DEPTH 1 - #define MAXPATHNAMELENGTH (FILENAME_LENGTH*MAX_DIR_DEPTH + MAX_DIR_DEPTH + 1) - uint8_t file_subcall_ctr; - uint32_t filespos[SD_PROCEDURE_DEPTH]; - char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH]; - uint32_t filesize, sdpos; + #ifndef SD_PROCEDURE_DEPTH + #define SD_PROCEDURE_DEPTH 1 + #endif - LsAction lsAction; //stored for recursion. - uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. - char* diveDirName; - void lsDive(const char *prepend, SdFile parent, const char * const match=NULL + static uint8_t file_subcall_ctr; + static uint32_t filespos[SD_PROCEDURE_DEPTH]; + static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH + 1]; + + static uint32_t filesize, sdpos; + + static LsAction lsAction; //stored for recursion. + static uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. + static char *diveDirName; + static void lsDive(const char *prepend, SdFile parent, const char * const match=NULL #if NUM_SERIAL > 1 , const int8_t port = -1 #endif ); #if ENABLED(SDCARD_SORT_ALPHA) - void flush_presort(); + static void flush_presort(); #endif #if ENABLED(AUTO_REPORT_SD_STATUS) @@ -256,7 +273,7 @@ private: #define IS_SD_INSERTED() true #endif -#define IS_SD_PRINTING() card.sdprinting +#define IS_SD_PRINTING() card.flag.sdprinting #define IS_SD_FILE_OPEN() card.isFileOpen() extern CardReader card;