Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M20 L updated format and first implementation of timestamp reporting (M20 T) #3113

Merged
merged 8 commits into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Firmware/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3963,6 +3963,8 @@ static void extended_capabilities_report()
#endif //FANCHECK and TACH_0 or TACH_1
// AUTOREPORT_POSITION (M114)
cap_line(PSTR("AUTOREPORT_POSITION"), ENABLED(AUTO_REPORT));
// EXTENDED_M20 (support for L and T parameters)
cap_line(PSTR("EXTENDED_M20"), 1);
//@todo Update RepRap cap
}
#endif //EXTENDED_CAPABILITIES_REPORT
Expand Down Expand Up @@ -5739,16 +5741,17 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
### M20 - SD Card file list <a href="https://reprap.org/wiki/G-code#M20:_List_SD_card">M20: List SD card</a>
#### Usage

M20 [ L ]
M20 [ L | T ]
#### Parameters
- `L` - Reports ling filenames instead of just short filenames. Requires host software parsing.
- `T` - Report timestamps as well. The value is one uint32_t encoded as hex. Requires host software parsing (Cap:EXTENDED_M20).
- `L` - Reports long filenames instead of just short filenames. Requires host software parsing (Cap:EXTENDED_M20).
*/
case 20:
KEEPALIVE_STATE(NOT_BUSY); // do not send busy messages during listing. Inhibits the output of manage_heater()
SERIAL_PROTOCOLLNRPGM(_N("Begin file list"));////MSG_BEGIN_FILE_LIST
card.ls(code_seen('L'));
card.ls(CardReader::ls_param(code_seen('L'), code_seen('T')));
SERIAL_PROTOCOLLNRPGM(_N("End file list"));////MSG_END_FILE_LIST
break;
break;

/*!
### M21 - Init SD card <a href="https://reprap.org/wiki/G-code#M21:_Initialize_SD_card">M21: Initialize SD card</a>
Expand Down
70 changes: 35 additions & 35 deletions Firmware/cardreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,9 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
+* LS_Count - Add +1 to nrFiles for every file within the parent
+* LS_GetFilename - Get the filename of the file indexed by nrFiles
+* LS_SerialPrint - Print the full path and size of each file to serial output
+* LS_SerialPrint_LFN - Print the full path, long filename and size of each file to serial output
+*/

void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/, LsAction lsAction, ls_param lsParams) {
static uint8_t recursionCnt = 0;
// RAII incrementer for the recursionCnt
class _incrementer
Expand All @@ -80,8 +79,12 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
for (position = parent.curPosition(); parent.readDir(p, longFilename) > 0; position = parent.curPosition()) {
if (recursionCnt > MAX_DIR_DEPTH)
return;
else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint

uint8_t pn0 = p.name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
if (longFilename[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
if (DIR_IS_SUBDIR(&p) && lsAction == LS_SerialPrint) { // If the entry is a directory and the action is LS_SerialPrint
// Get the short name for the item, which we know is a folder
char lfilename[FILENAME_LENGTH];
createFilename(lfilename, p);
Expand All @@ -99,47 +102,52 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
// Get a new directory object using the full path
// and dive recursively into it.

if (lsAction == LS_SerialPrint_LFN)
if (lsParams.LFN)
printf_P(PSTR("DIR_ENTER: %s \"%s\"\n"), path, longFilename[0] ? longFilename : lfilename);

SdFile dir;
if (!dir.open(parent, lfilename, O_READ)) {
if (lsAction == LS_SerialPrint || lsAction == LS_SerialPrint_LFN) {
//SERIAL_ECHO_START();
//SERIAL_ECHOPGM(_i("Cannot open subdir"));////MSG_SD_CANT_OPEN_SUBDIR
//SERIAL_ECHOLN(lfilename);
}
//SERIAL_ECHO_START();
//SERIAL_ECHOPGM(_i("Cannot open subdir"));////MSG_SD_CANT_OPEN_SUBDIR
//SERIAL_ECHOLN(lfilename);
}
lsDive(path, dir);
lsDive(path, dir, NULL, lsAction, lsParams);
// close() is done automatically by destructor of SdFile

if (lsAction == LS_SerialPrint_LFN)
if (lsParams.LFN)
puts_P(PSTR("DIR_EXIT"));
}
else {
uint8_t pn0 = p.name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
if (longFilename[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
filenameIsDir = DIR_IS_SUBDIR(&p);
if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
switch (lsAction) {
case LS_Count:
nrFiles++;
break;

case LS_SerialPrint_LFN:
case LS_SerialPrint:
createFilename(filename, p);
SERIAL_PROTOCOL(prepend);
SERIAL_PROTOCOL(filename);

MYSERIAL.write(' ');
SERIAL_PROTOCOL(p.fileSize);

if (lsParams.timestamp)
{
crmodDate = p.lastWriteDate;
crmodTime = p.lastWriteTime;
if( crmodDate < p.creationDate || ( crmodDate == p.creationDate && crmodTime < p.creationTime ) ){
crmodDate = p.creationDate;
crmodTime = p.creationTime;
}
printf_P(PSTR(" %#lx"), ((uint32_t)crmodDate << 16) | crmodTime);
}

if (lsAction == LS_SerialPrint_LFN)
printf_P(PSTR("\"%s\" "), LONGEST_FILENAME);
if (lsParams.LFN)
printf_P(PSTR(" \"%s\""), LONGEST_FILENAME);

SERIAL_PROTOCOLLN(p.fileSize);
SERIAL_PROTOCOLLN();
manage_heater();
break;

Expand Down Expand Up @@ -181,14 +189,10 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
} // while readDir
}

void CardReader::ls(bool printLFN)
void CardReader::ls(ls_param params)
{
lsAction = printLFN ? LS_SerialPrint_LFN : LS_SerialPrint;
//if(lsAction==LS_Count)
//nrFiles=0;

root.rewind();
lsDive("",root);
lsDive("",root, NULL, LS_SerialPrint, params);
}


Expand Down Expand Up @@ -695,38 +699,34 @@ void CardReader::closefile(bool store_location)
void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/)
{
curDir=&workDir;
lsAction=LS_GetFilename;
nrFiles=nr;
curDir->rewind();
lsDive("",*curDir,match);
lsDive("",*curDir,match, LS_GetFilename);

}

void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/)
{
curDir = &workDir;
lsAction = LS_GetFilename;
nrFiles = 0;
curDir->seekSet(position);
lsDive("", *curDir, match);
lsDive("", *curDir, match, LS_GetFilename);
}

void CardReader::getfilename_next(uint32_t position, const char * const match/*=NULL*/)
{
curDir = &workDir;
lsAction = LS_GetFilename;
nrFiles = 1;
curDir->seekSet(position);
lsDive("", *curDir, match);
lsDive("", *curDir, match, LS_GetFilename);
}

uint16_t CardReader::getnrfilenames()
{
curDir=&workDir;
lsAction=LS_Count;
nrFiles=0;
curDir->rewind();
lsDive("",*curDir);
lsDive("",*curDir, NULL, LS_Count);
//SERIAL_ECHOLN(nrFiles);
return nrFiles;
}
Expand Down
20 changes: 16 additions & 4 deletions Firmware/cardreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@
#define MAX_DIR_DEPTH 6

#include "SdFile.h"
enum LsAction {LS_SerialPrint,LS_SerialPrint_LFN,LS_Count,LS_GetFilename};
class CardReader
{
public:
CardReader();

enum LsAction : uint8_t
{
LS_SerialPrint,
LS_Count,
LS_GetFilename,
};
struct ls_param
{
bool LFN : 1;
bool timestamp : 1;
inline ls_param():LFN(0), timestamp(0) { }
inline ls_param(bool LFN, bool timestamp):LFN(LFN), timestamp(timestamp) { }
} __attribute__((packed));

void initsd();
void write_command(char *buf);
void write_command_no_newline(char *buf);
Expand Down Expand Up @@ -43,7 +56,7 @@ class CardReader
uint16_t getWorkDirDepth();


void ls(bool printLFN);
void ls(ls_param params);
bool chdir(const char * relpath, bool doPresort);
void updir();
void setroot(bool doPresort);
Expand Down Expand Up @@ -122,12 +135,11 @@ class CardReader

bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.

LsAction lsAction; //stored for recursion.
int16_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;

bool diveSubfolder (const char *&fileName);
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL, LsAction lsAction = LS_GetFilename, ls_param lsParams = ls_param());
#ifdef SDCARD_SORT_ALPHA
void flush_presort();
#endif
Expand Down