Prusa MINI Firmware overview
cardreader.h
Go to the documentation of this file.
1 /**
2  * Marlin 3D Printer Firmware
3  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4  *
5  * Based on Sprinter and grbl.
6  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 #pragma once
23 
24 #include "../inc/MarlinConfig.h"
25 
26 #if ENABLED(SDSUPPORT)
27 
28 #define SD_RESORT BOTH(SDCARD_SORT_ALPHA, SDSORT_DYNAMIC_RAM)
29 
30 #define MAX_DIR_DEPTH 10 // Maximum folder depth
31 #define MAXDIRNAMELENGTH 8 // DOS folder name size
32 #define MAXPATHNAMELENGTH (1 + (MAXDIRNAMELENGTH + 1) * (MAX_DIR_DEPTH) + 1 + FILENAME_LENGTH) // "/" + N * ("ADIRNAME/") + "filename.ext"
33 
34 #include "SdFile.h"
35 
36 typedef struct {
37  bool saving:1,
38  logging:1,
39  sdprinting:1,
40  mounted:1,
41  filenameIsDir:1,
42  workDirIsRoot:1,
43  abort_sd_printing:1
44  #if ENABLED(BINARY_FILE_TRANSFER)
45  , binary_mode:1
46  #endif
47  ;
48 } card_flags_t;
49 
50 class CardReader {
51 public:
52  static card_flags_t flag; // Flags (above)
53  static char filename[FILENAME_LENGTH], // DOS 8.3 filename of the selected item
54  longFilename[LONG_FILENAME_LENGTH]; // Long name of the selected item
55 
56  // Fast! binary file transfer
57  #if ENABLED(BINARY_FILE_TRANSFER)
58  #if NUM_SERIAL > 1
59  static int8_t transfer_port_index;
60  #else
61  static constexpr int8_t transfer_port_index = 0;
62  #endif
63  #endif
64 
65  // // // Methods // // //
66 
67  CardReader();
68 
69  static SdFile getroot() { return root; }
70 
71  static void mount();
72  static void release();
73  static inline bool isMounted() { return flag.mounted; }
74  static void ls();
75 
76  // SD Card Logging
77  static void openLogFile(char * const path);
78  static void write_command(char * const buf);
79 
80  // Auto-Start files
81  static int8_t autostart_index; // Index of autoX.g files
82  static void beginautostart();
83  static void checkautostart();
84 
85  // Basic file ops
86  static void openFile(char * const path, const bool read, const bool subcall=false);
87  static void closefile(const bool store_location=false);
88  static void removeFile(const char * const name);
89 
90  static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }
91  #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
92  static void printLongPath(char * const path); // Used by M33
93  #endif
94 
95  // Working Directory for SD card menu
96  static void cdroot();
97  static void cd(const char *relpath);
98  static int8_t cdup();
99  static uint16_t countFilesInWorkDir();
100  static uint16_t get_num_Files();
101 
102  // Select a file
103  static void selectFileByIndex(const uint16_t nr);
104  static void selectFileByName(const char* const match);
105 
106  // Print job
107  static void openAndPrintFile(const char *name); // (working directory)
108  static void printingHasFinished();
109  static void getAbsFilename(char *dst);
110  static void startFileprint();
111  static void printFilename();
112  static void stopSDPrint(
113  #if SD_RESORT
114  const bool re_sort=false
115  #endif
116  );
117  static void report_status();
118  static inline void pauseSDPrint() { flag.sdprinting = false; }
119  static inline bool isPaused() { return isFileOpen() && !flag.sdprinting; }
120  static inline bool isPrinting() { return flag.sdprinting; }
121  #if HAS_PRINT_PROGRESS_PERMYRIAD
122  static inline uint16_t permyriadDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 9999) / 10000) : 0; }
123  #endif
124  static inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
125 
126  // Helper for open and remove
127  static const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo=false);
128 
129  #if ENABLED(SDCARD_SORT_ALPHA)
130  static void presort();
131  static void getfilename_sorted(const uint16_t nr);
132  #if ENABLED(SDSORT_GCODE)
133  FORCE_INLINE static void setSortOn(bool b) { sort_alpha = b; presort(); }
134  FORCE_INLINE static void setSortFolders(int i) { sort_folders = i; presort(); }
135  //FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; }
136  #endif
137  #else
138  FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
139  #endif
140 
141  #if ENABLED(POWER_LOSS_RECOVERY)
142  static bool jobRecoverFileExists();
143  static void openJobRecoveryFile(const bool read);
144  static void removeJobRecoveryFile();
145  #endif
146 
147  static inline bool isFileOpen() { return isMounted() && file.isOpen(); }
148  static inline uint32_t getIndex() { return sdpos; }
149  static inline bool eof() { return sdpos >= filesize; }
150  static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
151  static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
152  static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
153  static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
154  static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
155 
156  static Sd2Card& getSd2Card() { return sd2card; }
157 
158  #if ENABLED(AUTO_REPORT_SD_STATUS)
159  static void auto_report_sd_status();
160  static inline void set_auto_report_interval(uint8_t v) {
161  #if NUM_SERIAL > 1
162  auto_report_port = serial_port_index;
163  #endif
164  NOMORE(v, 60);
165  auto_report_sd_interval = v;
166  next_sd_report_ms = millis() + 1000UL * v;
167  }
168  #endif
169 
170 private:
171  //
172  // Working directory and parents
173  //
174  static SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
175  static uint8_t workDirDepth;
176 
177  //
178  // Alphabetical file and folder sorting
179  //
180  #if ENABLED(SDCARD_SORT_ALPHA)
181  static uint16_t sort_count; // Count of sorted items in the current directory
182  #if ENABLED(SDSORT_GCODE)
183  static bool sort_alpha; // Flag to enable / disable the feature
184  static int sort_folders; // Folder sorting before/none/after
185  //static bool sort_reverse; // Flag to enable / disable reverse sorting
186  #endif
187 
188  // By default the sort index is static
189  #if ENABLED(SDSORT_DYNAMIC_RAM)
190  static uint8_t *sort_order;
191  #else
192  static uint8_t sort_order[SDSORT_LIMIT];
193  #endif
194 
195  #if BOTH(SDSORT_USES_RAM, SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)
196  #define SORTED_LONGNAME_MAXLEN (SDSORT_CACHE_VFATS) * (FILENAME_LENGTH)
197  #define SORTED_LONGNAME_STORAGE (SORTED_LONGNAME_MAXLEN + 1)
198  #else
199  #define SORTED_LONGNAME_MAXLEN LONG_FILENAME_LENGTH
200  #define SORTED_LONGNAME_STORAGE SORTED_LONGNAME_MAXLEN
201  #endif
202 
203  // Cache filenames to speed up SD menus.
204  #if ENABLED(SDSORT_USES_RAM)
205 
206  // If using dynamic ram for names, allocate on the heap.
207  #if ENABLED(SDSORT_CACHE_NAMES)
208  static uint16_t nrFiles; // Cache the total count
209  #if ENABLED(SDSORT_DYNAMIC_RAM)
210  static char **sortshort, **sortnames;
211  #else
212  static char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
213  #endif
214  #endif
215 
216  #if (ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)) || NONE(SDSORT_CACHE_NAMES, SDSORT_USES_STACK)
217  static char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_STORAGE];
218  #endif
219 
220  // Folder sorting uses an isDir array when caching items.
221  #if HAS_FOLDER_SORTING
222  #if ENABLED(SDSORT_DYNAMIC_RAM)
223  static uint8_t *isDir;
224  #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
225  static uint8_t isDir[(SDSORT_LIMIT+7)>>3];
226  #endif
227  #endif
228 
229  #endif // SDSORT_USES_RAM
230 
231  #endif // SDCARD_SORT_ALPHA
232 
233  static Sd2Card sd2card;
234  static SdVolume volume;
235  static SdFile file;
236 
237  static uint32_t filesize, sdpos;
238 
239  //
240  // Procedure calls to other files
241  //
242  #ifndef SD_PROCEDURE_DEPTH
243  #define SD_PROCEDURE_DEPTH 1
244  #endif
245  static uint8_t file_subcall_ctr;
246  static uint32_t filespos[SD_PROCEDURE_DEPTH];
247  static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
248 
249  //
250  // SD Auto Reporting
251  //
252  #if ENABLED(AUTO_REPORT_SD_STATUS)
253  static uint8_t auto_report_sd_interval;
254  static millis_t next_sd_report_ms;
255  #if NUM_SERIAL > 1
256  static int8_t auto_report_port;
257  #endif
258  #endif
259 
260  //
261  // Directory items
262  //
263  static bool is_dir_or_gcode(const dir_t &p);
264  static int countItems(SdFile dir);
265  static void selectByIndex(SdFile dir, const uint8_t index);
266  static void selectByName(SdFile dir, const char * const match);
267  static void printListing(SdFile parent, const char * const prepend=nullptr);
268 
269  #if ENABLED(SDCARD_SORT_ALPHA)
270  static void flush_presort();
271  #endif
272 };
273 
274 #if ENABLED(USB_FLASH_DRIVE_SUPPORT)
275  #define IS_SD_INSERTED() Sd2Card::isInserted()
276 #elif PIN_EXISTS(SD_DETECT)
277  #if ENABLED(SD_DETECT_INVERTED)
278  #define IS_SD_INSERTED() READ(SD_DETECT_PIN)
279  #else
280  #define IS_SD_INSERTED() !READ(SD_DETECT_PIN)
281  #endif
282 #else
283  // No card detect line? Assume the card is inserted.
284  #define IS_SD_INSERTED() true
285 #endif
286 
287 #define IS_SD_PRINTING() card.flag.sdprinting
288 #define IS_SD_PAUSED() card.isPaused()
289 #define IS_SD_FILE_OPEN() card.isFileOpen()
290 
291 extern CardReader card;
292 
293 #else // !SDSUPPORT
294 
295 #define IS_SD_PRINTING() false
296 #define IS_SD_PAUSED() false
297 #define IS_SD_FILE_OPEN() false
298 
299 #define LONG_FILENAME_LENGTH 0
300 
301 #endif // !SDSUPPORT
SdBaseFile::readDir
int8_t readDir(dir_t *dir, char *longFilename)
Definition: Marlin_CardReader.cpp:459
SERIAL_CHAR
#define SERIAL_CHAR(x)
Definition: serial.h:69
O_APPEND
const uint8_t O_APPEND
Definition: SdBaseFile.h:59
PORT_REDIRECT
#define PORT_REDIRECT(p)
Definition: serial.h:66
Planner::synchronize
static void synchronize()
Definition: planner.cpp:1556
DIR_ATT_HIDDEN
const uint8_t DIR_ATT_HIDDEN
Definition: SdFatStructs.h:564
SERIAL_ECHO
#define SERIAL_ECHO(x)
Definition: serial.h:70
OUT_WRITE
#define OUT_WRITE(IO, V)
Definition: fastio.h:108
GCodeQueue::enqueue_now_P
static void enqueue_now_P(PGM_P const cmd)
Definition: queue.cpp:218
SdVolume
Access FAT16 and FAT32 volumes on SD and SDHC cards.
Definition: SdVolume.h:71
queue
GCodeQueue queue
Definition: queue.cpp:28
settings
MarlinSettings settings
Definition: configuration_store.cpp:344
MarlinSettings::first_load
static FORCE_INLINE void first_load()
Definition: configuration_store.h:81
MSG_SD_OPENROOT_FAIL
#define MSG_SD_OPENROOT_FAIL
Definition: language.h:226
newDir2
static SdFile newDir2
Definition: Marlin_CardReader.cpp:27
print_job_timer
Stopwatch print_job_timer
Definition: printcounter.cpp:63
SDPOWER_PIN
#define SDPOWER_PIN
Definition: pins.h:789
SERIAL_ECHOPAIR
#define SERIAL_ECHOPAIR(V...)
Definition: serial.h:114
MSG_SD_NOT_PRINTING
#define MSG_SD_NOT_PRINTING
Definition: language.h:235
LONG_FILENAME_LENGTH
#define LONG_FILENAME_LENGTH
Definition: cardreader.h:299
SdBaseFile::close
bool close()
Definition: Marlin_CardReader.cpp:535
DIR_NAME_DELETED
const uint8_t DIR_NAME_DELETED
Definition: SdFatStructs.h:561
i
uint8_t i
Definition: screen_test_graph.c:72
STRINGIFY
#define STRINGIFY(M)
Definition: macros.h:73
SPI_SPEED
#define SPI_SPEED
Definition: Conditionals_LCD.h:572
kill
void kill(PGM_P const lcd_error, PGM_P const lcd_component, const bool steppers_off)
Definition: Marlin.cpp:718
millis
uint32_t millis(void)
Definition: wiring_time.c:29
LCD_SDSS
#define LCD_SDSS
Definition: pins_AZSMZ_MINI.h:89
PrintJobRecovery::file
static SdFile file
Definition: power_loss_recovery.h:110
FILENAME_LENGTH
#define FILENAME_LENGTH
Definition: SdFatConfig.h:103
O_WRITE
const uint8_t O_WRITE
Definition: SdBaseFile.h:55
SdBaseFile::isOpen
bool isOpen() const
Definition: SdBaseFile.h:277
recovery
PrintJobRecovery recovery
SERIAL_ECHO_START
#define SERIAL_ECHO_START()
Definition: serial.h:179
Stopwatch::stop
static bool stop()
Stop the stopwatch.
Definition: stopwatch.cpp:36
SERIAL_ECHOLN
#define SERIAL_ECHOLN(x)
Definition: serial.h:72
sprintf_P
#define sprintf_P(s,...)
Definition: pgmspace.h:72
MAX_DIR_DEPTH
#define MAX_DIR_DEPTH
Definition: window_file_list.h:35
SdBaseFile::rewind
void rewind()
Definition: SdBaseFile.h:311
PrintJobRecovery::filename
static const char filename[5]
Definition: power_loss_recovery.h:108
emergency_parser
EmergencyParser emergency_parser
NOMORE
#define NOMORE(v, n)
Definition: macros.h:133
createSpeedLookupTable.end
end
Definition: createSpeedLookupTable.py:33
MSG_SD_VOL_INIT_FAIL
#define MSG_SD_VOL_INIT_FAIL
Definition: language.h:225
ZERO
#define ZERO(a)
Definition: macros.h:201
PrintJobRecovery::valid
static bool valid()
Definition: power_loss_recovery.h:167
FORCE_INLINE
#define FORCE_INLINE
Definition: macros.h:40
Planner::finish_and_disable
static void finish_and_disable()
Definition: planner.cpp:1517
SERIAL_ECHO_MSG
#define SERIAL_ECHO_MSG(S)
Definition: serial.h:183
PSTR
#define PSTR(str)
Definition: pgmspace.h:31
MSG_SD_CANT_ENTER_SUBDIR
#define MSG_SD_CANT_ENTER_SUBDIR
Definition: language.h:238
newDir1
static SdFile newDir1
Definition: Marlin_CardReader.cpp:27
EmergencyParser::enable
static FORCE_INLINE void enable()
Definition: emergency_parser.h:73
Stopwatch::duration
static millis_t duration()
Get the running time.
Definition: stopwatch.cpp:108
directoryEntry::name
uint8_t name[11]
Definition: SdFatStructs.h:486
EmergencyParser::disable
static FORCE_INLINE void disable()
Definition: emergency_parser.h:75
SDSORT_LIMIT
#define SDSORT_LIMIT
Definition: window_file_list.h:27
MSG_SD_PRINTING_BYTE
#define MSG_SD_PRINTING_BYTE
Definition: language.h:234
MSG_SD_CANT_OPEN_SUBDIR
#define MSG_SD_CANT_OPEN_SUBDIR
Definition: language.h:223
SERIAL_ECHOPGM
#define SERIAL_ECHOPGM(S)
Definition: serial.h:173
MSG_SD_OPEN_FILE_FAIL
#define MSG_SD_OPEN_FILE_FAIL
Definition: language.h:229
SdFile
SdBaseFile with Print.
Definition: SdFile.h:45
O_TRUNC
const uint8_t O_TRUNC
Definition: SdBaseFile.h:61
SERIAL_ECHOLNPAIR
#define SERIAL_ECHOLNPAIR(V...)
Definition: serial.h:144
SDSS
#define SDSS
Definition: spi_pins.h:53
directoryEntry::attributes
uint8_t attributes
Definition: SdFatStructs.h:494
FOLDER_SORTING
#define FOLDER_SORTING
Definition: window_file_list.h:31
ELAPSED
#define ELAPSED(NOW, SOON)
Definition: millis_t.h:29
MSG_SD_FILE_SELECTED
#define MSG_SD_FILE_SELECTED
Definition: language.h:232
uint8_t
const uint8_t[]
Definition: 404_html.c:3
ui
MarlinUI ui
GCodeQueue::enqueue_one_now
static void enqueue_one_now(const char *cmd)
Definition: queue.cpp:212
Sd2Card
Raw access to SD and SDHC flash memory cards.
Definition: Sd2Card.h:93
_BV
#define _BV(bit)
Definition: wiring_constants.h:99
SERIAL_ERROR_MSG
#define SERIAL_ERROR_MSG(S)
Definition: serial.h:184
DIR_IS_FILE_OR_SUBDIR
static uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t *dir)
Definition: SdFatStructs.h:612
read
static int read(struct _reent *_r, void *pv, char *pc, int n)
Definition: gcode_file.cpp:9
MSG_SD_ERR_WRITE_TO_FILE
#define MSG_SD_ERR_WRITE_TO_FILE
Definition: language.h:236
MAXPATHNAMELENGTH
#define MAXPATHNAMELENGTH
Definition: screen_filebrowser.cpp:26
createFilename
static char * createFilename(char *const buffer, const dir_t &p)
Get a DOS 8.3 filename in its useful form.
Definition: Marlin_CardReader.cpp:92
HIGH
#define HIGH
Definition: wiring_constants.h:71
SERIAL_EOL
#define SERIAL_EOL()
Definition: serial.h:181
SdFile.h
SdFile class.
directoryEntry::fileSize
uint32_t fileSize
Definition: SdFatStructs.h:525
cardreader.h
MSG_SD_WRITE_TO_FILE
#define MSG_SD_WRITE_TO_FILE
Definition: language.h:233
SdBaseFile::open
bool open(SdBaseFile *dirFile, uint16_t index, uint8_t oflag)
directoryEntry
FAT short directory entry.
Definition: SdFatStructs.h:479
DIR_IS_SUBDIR
static uint8_t DIR_IS_SUBDIR(const dir_t *dir)
Definition: SdFatStructs.h:602
serialprintPGM
void serialprintPGM(PGM_P str)
Definition: serial.cpp:35
MSG_SD_FILE_OPENED
#define MSG_SD_FILE_OPENED
Definition: language.h:230
SERIAL_ECHOLNPGM
#define SERIAL_ECHOLNPGM(S)
Definition: serial.h:174
MSG_SD_SIZE
#define MSG_SD_SIZE
Definition: language.h:231
O_READ
const uint8_t O_READ
Definition: SdBaseFile.h:53
createSpeedLookupTable.b
list b
Definition: createSpeedLookupTable.py:30
MSG_SD_INIT_FAIL
#define MSG_SD_INIT_FAIL
Definition: language.h:224
MSG_SD_CARD_OK
#define MSG_SD_CARD_OK
Definition: language.h:227
O_SYNC
const uint8_t O_SYNC
Definition: SdBaseFile.h:60
DIR_NAME_FREE
const uint8_t DIR_NAME_FREE
Definition: SdFatStructs.h:562
write
static int write(struct _reent *_r, void *pv, const char *pc, int n)
Definition: gcode_file.cpp:17
millis_t
uint32_t millis_t
Definition: millis_t.h:26
ENABLED
#define ENABLED(V...)
Definition: macros.h:177
planner
Planner planner
Definition: planner.cpp:111
PrintJobRecovery::init
static void init()
bit
#define bit(b)
Definition: wiring_constants.h:96
O_CREAT
const uint8_t O_CREAT
Definition: SdBaseFile.h:63