diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp
index 2b275db67..3eac5cf33 100755
--- a/Firmware/Marlin_main.cpp
+++ b/Firmware/Marlin_main.cpp
@@ -4002,9 +4002,9 @@ void process_commands()
}else if (code_seen_P("fv")) { // PRUSA fv
// get file version
#ifdef SDSUPPORT
- card.openFile(strchr_pointer + 3,true);
+ card.openFileReadFilteredGcode(strchr_pointer + 3,true);
while (true) {
- uint16_t readByte = card.get();
+ uint16_t readByte = card.getFilteredGcodeChar();
MYSERIAL.write(readByte);
if (readByte=='\n') {
break;
@@ -4017,7 +4017,7 @@ void process_commands()
} else if (code_seen_P(PSTR("M28"))) { // PRUSA M28
trace();
prusa_sd_card_upload = true;
- card.openFile(strchr_pointer+4,false);
+ card.openFileWrite(strchr_pointer+4);
} else if (code_seen_P(PSTR("SN"))) { // PRUSA SN
char SN[20];
@@ -5786,7 +5786,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
starpos = (strchr(strchr_pointer + 4,'*'));
if(starpos!=NULL)
*(starpos)='\0';
- card.openFile(strchr_pointer + 4,true);
+ card.openFileReadFilteredGcode(strchr_pointer + 4);
break;
/*!
@@ -5856,7 +5856,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
strchr_pointer = strchr(npos,' ') + 1;
*(starpos) = '\0';
}
- card.openFile(strchr_pointer+4,false);
+ card.openFileWrite(strchr_pointer+4);
break;
/*! ### M29 - Stop SD write M29: Stop writing to SD card
@@ -5917,7 +5917,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
if( card.cardOK )
{
- card.openFile(namestartpos,true,!call_procedure);
+ card.openFileReadFilteredGcode(namestartpos,!call_procedure);
if(code_seen('S'))
if(strchr_pointercache()->data; // this is constant for the whole time, so it should be fast and sleek
+}
+
+void SdFile::gfReset(){
+ // reset cache read ptr to its begin
+ gfReadPtr = gfBlockBuffBegin() + gfOffset;
+}
+
+// think twice before allowing this to inline - manipulating 4B longs is costly
+// moreover - this function has its parameters in registers only, so no heavy stack usage besides the call/ret
+void __attribute__((noinline)) SdFile::gfUpdateCurrentPosition(uint16_t inc){
+ curPosition_ += inc;
+}
+
+#define find_endl(resultP, startP) \
+__asm__ __volatile__ ( \
+"cycle: \n" \
+"ld r22, Z+ \n" \
+"cpi r22, 0x0A \n" \
+"brne cycle \n" \
+: "=z" (resultP) /* result of the ASM code - in our case the Z register (R30:R31) */ \
+: "z" (startP) /* input of the ASM code - in our case the Z register as well (R30:R31) */ \
+: "r22" /* modifying register R22 - so that the compiler knows */ \
+)
+
+// avoid calling the default heavy-weight read() for just one byte
+int16_t SdFile::readFilteredGcode(){
+ if( ! gfEnsureBlock() ){
+ goto eof_or_fail; // this is unfortunate :( ... other calls are using the cache and we can loose the data block of our gcode file
+ }
+ // assume, we have the 512B block cache filled and terminated with a '\n'
+ {
+ const uint8_t *start = gfReadPtr;
+
+ // It may seem unreasonable to copy the variable into a local one and copy it back at the end of this method,
+ // but there is an important point of view: the compiler is unsure whether it can optimize the reads/writes
+ // to gfReadPtr within this method, because it is a class member variable.
+ // The compiler cannot see, if omitting read/write won't have any incorrect side-effects to the rest of the whole FW.
+ // So this trick explicitly states, that rdPtr is a local variable limited to the scope of this method,
+ // therefore the compiler can omit read/write to it (keep it in registers!) as it sees fit.
+ // And it does! Codesize dropped by 68B!
+ const uint8_t *rdPtr = gfReadPtr;
+
+ // the same applies to gfXBegin, codesize dropped another 100B!
+ const uint8_t *blockBuffBegin = gfBlockBuffBegin();
+
+ uint8_t consecutiveCommentLines = 0;
+ while( *rdPtr == ';' ){
+ for(;;){
+
+ //while( *(++gfReadPtr) != '\n' ); // skip until a newline is found - suboptimal code!
+ // Wondering, why this "nice while cycle" is done in such a weird way using a separate find_endl() function?
+ // Have a look at the ASM code GCC produced!
+
+ // At first - a separate find_endl() makes the compiler understand,
+ // that I don't need to store gfReadPtr every time, I'm only interested in the final address where the '\n' was found
+ // - the cycle can run on CPU registers only without touching memory besides reading the character being compared.
+ // Not only makes the code run considerably faster, but is also 40B shorter!
+ // This was the generated code:
+ //FORCE_INLINE const uint8_t * find_endl(const uint8_t *p){
+ // while( *(++p) != '\n' ); // skip until a newline is found
+ // return p; }
+ // 11c5e: movw r30, r18
+ // 11c60: subi r18, 0xFF ; 255
+ // 11c62: sbci r19, 0xFF ; 255
+ // 11c64: ld r22, Z
+ // 11c66: cpi r22, 0x0A ; 10
+ // 11c68: brne .-12 ; 0x11c5e
+
+ // Still, even that was suboptimal as the compiler seems not to understand the usage of ld r22, Z+ (the plus is important)
+ // aka automatic increment of the Z register (R30:R31 pair)
+ // There is no other way than pure ASM!
+ find_endl(rdPtr, rdPtr);
+
+ // found a newline, prepare the next block if block cache end reached
+ if( rdPtr - blockBuffBegin > 512 ){
+ // at the end of block cache, fill new data in
+ gfUpdateCurrentPosition( rdPtr - start - 1 );
+ if( ! gfComputeNextFileBlock() )goto eof_or_fail;
+ if( ! gfEnsureBlock() )goto eof_or_fail; // fetch it into RAM
+ rdPtr = start = blockBuffBegin;
+ } else {
+ if(consecutiveCommentLines >= 250){
+ --rdPtr; // unget the already consumed newline
+ goto emit_char;
+ }
+ // peek the next byte - we are inside the block at least at 511th index - still safe
+ if( *rdPtr == ';' ){
+ // consecutive comment
+ ++consecutiveCommentLines;
+ } else {
+ --rdPtr; // unget the already consumed newline
+ goto emit_char;
+ }
+ break; // found the real end of the line even across many blocks
+ }
+ }
+ }
+emit_char:
+ {
+ gfUpdateCurrentPosition( rdPtr - start + 1 );
+ int16_t rv = *rdPtr++;
+
+ if( curPosition_ >= fileSize_ ){
+ // past the end of file
+ goto eof_or_fail;
+ } else if( rdPtr - blockBuffBegin >= 512 ){
+ // past the end of current bufferred block - prepare the next one...
+ if( ! gfComputeNextFileBlock() )goto eof_or_fail;
+ // don't need to force fetch the block here, it will get loaded on the next call
+ rdPtr = blockBuffBegin;
+ }
+
+ // save the current read ptr for the next run
+ gfReadPtr = rdPtr;
+ return rv;
+ }
+
+}
+
+eof_or_fail:
+ // make the rdptr point to a safe location - end of file
+ gfReadPtr = gfBlockBuffBegin() + 512;
+ return -1;
+}
+
+bool SdFile::gfEnsureBlock(){
+ if ( vol_->cacheRawBlock(gfBlock, SdVolume::CACHE_FOR_READ)){
+ // terminate with a '\n'
+ const uint16_t terminateOfs = fileSize_ - gfOffset;
+ vol_->cache()->data[ terminateOfs < 512 ? terminateOfs : 512 ] = '\n';
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SdFile::gfComputeNextFileBlock() {
+ // error if not open or write only
+ if (!isOpen() || !(flags_ & O_READ)) return false;
+
+ gfOffset = curPosition_ & 0X1FF; // offset in block
+ if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
+ // SHR by 9 means skip the last byte and shift just 3 bytes by 1
+ // -> should be 8 instructions... and not the horrible loop shifting 4 bytes at once
+ // still need to get some work on this
+ gfBlock = vol_->rootDirStart() + (curPosition_ >> 9);
+ } else {
+ uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
+ if (gfOffset == 0 && blockOfCluster == 0) {
+ // start of new cluster
+ if (curPosition_ == 0) {
+ // use first cluster in file
+ curCluster_ = firstCluster_;
+ } else {
+ // get next cluster from FAT
+ if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
+ }
+ }
+ gfBlock = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
+ }
+ return true;
+}
+
//------------------------------------------------------------------------------
/** Write data to an open file.
*
diff --git a/Firmware/SdFile.h b/Firmware/SdFile.h
index 60e2f5deb..465224623 100644
--- a/Firmware/SdFile.h
+++ b/Firmware/SdFile.h
@@ -34,7 +34,24 @@
* \brief SdBaseFile with Print.
*/
class SdFile : public SdBaseFile/*, public Print*/ {
- public:
+ // GCode filtering vars and methods - due to optimization reasons not wrapped in a separate class
+
+ // beware - this read ptr is manipulated inside just 2 methods - readFilteredGcode and gfReset
+ // If you even want to call gfReset from readFilteredGcode, you must make sure
+ // to update gfReadPtr inside readFilteredGcode from a local copy (see explanation of this trick in readFilteredGcode)
+ const uint8_t *gfReadPtr;
+
+ uint32_t gfBlock; // remember the current file block to be kept in cache - due to reuse of the memory, the block may fall out a must be read back
+ uint16_t gfOffset;
+
+ const uint8_t *gfBlockBuffBegin()const;
+
+ void gfReset();
+
+ bool gfEnsureBlock();
+ bool gfComputeNextFileBlock();
+ void gfUpdateCurrentPosition(uint16_t inc);
+public:
SdFile() {}
SdFile(const char* name, uint8_t oflag);
#if ARDUINO >= 100
@@ -43,6 +60,9 @@ class SdFile : public SdBaseFile/*, public Print*/ {
void write(uint8_t b);
#endif
+ bool openFilteredGcode(SdBaseFile* dirFile, const char* path);
+ int16_t readFilteredGcode();
+ bool seekSetFilteredGcode(uint32_t pos);
int16_t write(const void* buf, uint16_t nbyte);
void write(const char* str);
void write_P(PGM_P str);
@@ -51,4 +71,4 @@ class SdFile : public SdBaseFile/*, public Print*/ {
#endif // SdFile_h
-#endif
\ No newline at end of file
+#endif
diff --git a/Firmware/SdVolume.h b/Firmware/SdVolume.h
index 2ff2b6eb9..17699190e 100644
--- a/Firmware/SdVolume.h
+++ b/Firmware/SdVolume.h
@@ -36,7 +36,7 @@
*/
union cache_t {
/** Used to access cached file data blocks. */
- uint8_t data[512];
+ uint8_t data[512 + 1]; // abuse the last byte for saving '\n' - ugly optimization of read_filtered's inner skipping loop
/** Used to access cached FAT16 entries. */
uint16_t fat16[256];
/** Used to access cached FAT32 entries. */
@@ -119,6 +119,7 @@ class SdVolume {
bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
//------------------------------------------------------------------------------
private:
+ friend class SdFile;
// Allow SdBaseFile access to SdVolume private data.
friend class SdBaseFile;
@@ -211,4 +212,4 @@ class SdVolume {
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
#endif // SdVolume
-#endif
\ No newline at end of file
+#endif
diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp
index 6f8456664..717f58696 100644
--- a/Firmware/cardreader.cpp
+++ b/Firmware/cardreader.cpp
@@ -284,7 +284,7 @@ void CardReader::startFileprint()
void CardReader::openLogFile(const char* name)
{
logging = true;
- openFile(name, false);
+ openFileWrite(name);
}
void CardReader::getDirName(char* name, uint8_t level)
@@ -383,98 +383,144 @@ bool CardReader::diveSubfolder (const char *&fileName)
return 1;
}
-void CardReader::openFile(const char* name,bool read, bool replace_current/*=true*/)
-{
- if(!cardOK)
- return;
- if(file.isOpen()) //replacing current file by new file, or subfile call
- {
- if(!replace_current)
- {
- if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
- {
- // SERIAL_ERROR_START;
- // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
- // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
- kill(_n("trying to call sub-gcode files with too many levels."), 1);
- return;
- }
-
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
- SERIAL_ECHO(name);
- SERIAL_ECHOPGM("\" parent:\"");
-
- //store current filename and position
- getAbsFilename(filenames[file_subcall_ctr]);
-
- SERIAL_ECHO(filenames[file_subcall_ctr]);
- SERIAL_ECHOPGM("\" pos");
- SERIAL_ECHOLN(sdpos);
- filespos[file_subcall_ctr]=sdpos;
- file_subcall_ctr++;
- }
- else
- {
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("Now doing file: ");
- SERIAL_ECHOLN(name);
- }
- file.close();
- }
- else //opening fresh file
- {
- file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("Now fresh file: ");
- SERIAL_ECHOLN(name);
- }
- sdprinting = false;
+static const char ofKill[] PROGMEM = "trying to call sub-gcode files with too many levels.";
+static const char ofSubroutineCallTgt[] PROGMEM = "SUBROUTINE CALL target:\"";
+static const char ofParent[] PROGMEM = "\" parent:\"";
+static const char ofPos[] PROGMEM = "\" pos";
+static const char ofNowDoingFile[] PROGMEM = "Now doing file: ";
+static const char ofNowFreshFile[] PROGMEM = "Now fresh file: ";
+static const char ofFileOpened[] PROGMEM = "File opened: ";
+static const char ofSize[] PROGMEM = " Size: ";
+static const char ofFileSelected[] PROGMEM = "File selected";
+static const char ofSDPrinting[] PROGMEM = "SD-PRINTING";
+static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
- const char *fname=name;
- if (!diveSubfolder(fname))
- return;
-
- if(read)
- {
- if (file.open(curDir, fname, O_READ))
- {
- getfilename(0, fname);
- filesize = file.fileSize();
- SERIAL_PROTOCOLRPGM(_N("File opened: "));////MSG_SD_FILE_OPENED
- printAbsFilenameFast();
- SERIAL_PROTOCOLRPGM(_n(" Size: "));////MSG_SD_SIZE
- SERIAL_PROTOCOLLN(filesize);
- sdpos = 0;
-
- SERIAL_PROTOCOLLNRPGM(MSG_FILE_SELECTED);
- lcd_setstatuspgm(MSG_FILE_SELECTED);
- scrollstuff = 0;
+void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
+ if(!cardOK)
+ return;
+
+ if(file.isOpen()){ //replacing current file by new file, or subfile call
+ if(!replace_current){
+ if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1){
+ // SERIAL_ERROR_START;
+ // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+ // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+ kill(ofKill, 1);
+ return;
+ }
+
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofSubroutineCallTgt);
+ SERIAL_ECHO(name);
+ SERIAL_ECHORPGM(ofParent);
+
+ //store current filename and position
+ getAbsFilename(filenames[file_subcall_ctr]);
+
+ SERIAL_ECHO(filenames[file_subcall_ctr]);
+ SERIAL_ECHORPGM(ofPos);
+ SERIAL_ECHOLN(sdpos);
+ filespos[file_subcall_ctr]=sdpos;
+ file_subcall_ctr++;
+ } else {
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowDoingFile);
+ SERIAL_ECHOLN(name);
+ }
+ file.close();
+ } else { //opening fresh file
+ file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowFreshFile);
+ SERIAL_ECHOLN(name);
}
- else
- {
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
- SERIAL_PROTOCOL(fname);
- SERIAL_PROTOCOLLN('.');
- }
- }
- else
- { //write
- if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
- {
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
- SERIAL_PROTOCOL(fname);
- SERIAL_PROTOCOLLN('.');
- }
- else
- {
- saving = true;
- SERIAL_PROTOCOLRPGM(_N("Writing to file: "));////MSG_SD_WRITE_TO_FILE
- SERIAL_PROTOCOLLN(name);
- lcd_setstatus(fname);
- }
- }
+ sdprinting = false;
+ const char *fname=name;
+ if (!diveSubfolder(fname))
+ return;
+
+ if (file.openFilteredGcode(curDir, fname)) {
+ getfilename(0, fname);
+ filesize = file.fileSize();
+ SERIAL_PROTOCOLRPGM(ofFileOpened);////MSG_SD_FILE_OPENED
+ printAbsFilenameFast();
+ SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
+ SERIAL_PROTOCOLLN(filesize);
+ sdpos = 0;
+
+ SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
+ lcd_setstatuspgm(ofFileSelected);
+ scrollstuff = 0;
+ } else {
+ SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
+ SERIAL_PROTOCOL(fname);
+ SERIAL_PROTOCOLLN('.');
+ }
+}
+
+void CardReader::openFileWrite(const char* name)
+{
+ if(!cardOK)
+ return;
+ if(file.isOpen()){ //replacing current file by new file, or subfile call
+#if 0
+ // I doubt chained files support is necessary for file saving:
+ // Intentionally disabled because it takes a lot of code size while being not used
+
+ if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1){
+ // SERIAL_ERROR_START;
+ // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+ // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+ kill(ofKill, 1);
+ return;
+ }
+
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofSubroutineCallTgt);
+ SERIAL_ECHO(name);
+ SERIAL_ECHORPGM(ofParent);
+
+ //store current filename and position
+ getAbsFilename(filenames[file_subcall_ctr]);
+
+ SERIAL_ECHO(filenames[file_subcall_ctr]);
+ SERIAL_ECHORPGM(ofPos);
+ SERIAL_ECHOLN(sdpos);
+ filespos[file_subcall_ctr]=sdpos;
+ file_subcall_ctr++;
+ file.close();
+#else
+ SERIAL_ECHOLNPGM("File already opened");
+#endif
+ } else { //opening fresh file
+ file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowFreshFile);
+ SERIAL_ECHOLN(name);
+ }
+ sdprinting = false;
+
+ const char *fname=name;
+ if (!diveSubfolder(fname))
+ return;
+
+ //write
+ if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)){
+ SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
+ SERIAL_PROTOCOL(fname);
+ SERIAL_PROTOCOLLN('.');
+ } else {
+ saving = true;
+ getfilename(0, fname);
+ SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
+ printAbsFilenameFast();
+ SERIAL_PROTOCOLLN();
+
+ SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
+ lcd_setstatuspgm(ofFileSelected);
+ scrollstuff = 0;
+ }
}
void CardReader::removeFile(const char* name)
@@ -1003,7 +1049,7 @@ void CardReader::printingHasFinished()
{
file.close();
file_subcall_ctr--;
- openFile(filenames[file_subcall_ctr],true,true);
+ openFileReadFilteredGcode(filenames[file_subcall_ctr],true);
setIndex(filespos[file_subcall_ctr]);
startFileprint();
}
diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h
index 84462f6a8..0819d3bb8 100644
--- a/Firmware/cardreader.h
+++ b/Firmware/cardreader.h
@@ -1,6 +1,8 @@
#ifndef CARDREADER_H
#define CARDREADER_H
+#define SDSUPPORT
+
#ifdef SDSUPPORT
#define MAX_DIR_DEPTH 6
@@ -19,7 +21,8 @@ public:
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
void checkautostart(bool x);
- void openFile(const char* name,bool read,bool replace_current=true);
+ void openFileWrite(const char* name);
+ void openFileReadFilteredGcode(const char* name, bool replace_current = false);
void openLogFile(const char* name);
void removeFile(const char* name);
void closefile(bool store_location=false);
@@ -55,9 +58,11 @@ public:
#endif
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
- FORCE_INLINE bool eof() { return sdpos>=filesize ;};
- FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();};
- FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
+ bool eof() { return sdpos>=filesize; }
+ // There may be a potential performance problem - when the comment reading fails, sdpos points to the last correctly read character.
+ // However, repeated reading (e.g. after power panic) the comment will be read again - it should survive correctly, it will just take a few moments to skip
+ FORCE_INLINE int16_t getFilteredGcodeChar() { sdpos = file.curPosition();return (int16_t)file.readFilteredGcode();};
+ void setIndex(long index) {sdpos = index;file.seekSetFilteredGcode(index);};
FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); };
diff --git a/Firmware/cmdqueue.cpp b/Firmware/cmdqueue.cpp
index afdddfba2..9c822dab5 100755
--- a/Firmware/cmdqueue.cpp
+++ b/Firmware/cmdqueue.cpp
@@ -584,13 +584,14 @@ void get_command()
sd_count.value = 0;
// Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
while( !card.eof() && !stop_buffering) {
- int16_t n=card.get();
+ int16_t n=card.getFilteredGcodeChar();
char serial_char = (char)n;
- if(serial_char == '\n' ||
- serial_char == '\r' ||
- ((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
- serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
- {
+ if( serial_char == '\n'
+ || serial_char == '\r'
+ || ((serial_char == '#' || serial_char == ':') )
+ || serial_count >= (MAX_CMD_SIZE - 1)
+ || n==-1
+ ){
if(serial_char=='#')
stop_buffering=true;
@@ -601,8 +602,7 @@ void get_command()
// read from the sdcard into sd_count,
// so that the lenght of the already read empty lines and comments will be added
// to the following non-empty line.
- comment_mode = false;
- continue; //if empty line
+ return; // prevent cycling indefinitely - let manage_heaters do their job
}
// The new command buffer could be updated non-atomically, because it is not yet considered
// to be inside the active queue.
@@ -618,10 +618,10 @@ void get_command()
// MYSERIAL.print(sd_count.value, DEC);
// SERIAL_ECHOPGM(") ");
// SERIAL_ECHOLN(cmdbuffer+bufindw+CMDHDRSIZE);
-// SERIAL_ECHOPGM("cmdbuffer:");
-// MYSERIAL.print(cmdbuffer);
-// SERIAL_ECHOPGM("buflen:");
-// MYSERIAL.print(buflen+1);
+// SERIAL_ECHOPGM("cmdbuffer:");
+// MYSERIAL.print(cmdbuffer);
+// SERIAL_ECHOPGM("buflen:");
+// MYSERIAL.print(buflen+1);
sd_count.value = 0;
cli();
@@ -640,15 +640,15 @@ void get_command()
serial_count = 0; //clear buffer
if(card.eof()) break;
-
+
// The following line will reserve buffer space if available.
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
return;
}
else
{
- if(serial_char == ';') comment_mode = true;
- else if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
+ // there are no comments coming from the filtered file
+ cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
}
}
if(card.eof())
diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp
index a0efc3aae..fb79022ff 100644
--- a/Firmware/mesh_bed_calibration.cpp
+++ b/Firmware/mesh_bed_calibration.cpp
@@ -944,7 +944,7 @@ static inline void update_current_position_z()
// At the current position, find the Z stop.
-inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
+bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
#ifdef SUPPORT_VERBOSITY
verbosity_level
#endif //SUPPORT_VERBOSITY
@@ -1065,7 +1065,7 @@ error:
}
#ifdef NEW_XYZCAL
-extern bool xyzcal_find_bed_induction_sensor_point_xy();
+bool xyzcal_find_bed_induction_sensor_point_xy();
#endif //NEW_XYZCAL
// Search around the current_position[X,Y],
// look for the induction sensor response.
@@ -1081,7 +1081,7 @@ extern bool xyzcal_find_bed_induction_sensor_point_xy();
#endif //HEATBED_V2
#ifdef HEATBED_V2
-inline bool find_bed_induction_sensor_point_xy(int
+bool find_bed_induction_sensor_point_xy(int
#if !defined (NEW_XYZCAL) && defined (SUPPORT_VERBOSITY)
verbosity_level
#endif
@@ -1335,7 +1335,7 @@ inline bool find_bed_induction_sensor_point_xy(int
#endif //NEW_XYZCAL
}
#else //HEATBED_V2
-inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
+bool find_bed_induction_sensor_point_xy(int verbosity_level)
{
#ifdef NEW_XYZCAL
return xyzcal_find_bed_induction_sensor_point_xy();
diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h
index 8adc1c119..7ca93c953 100644
--- a/Firmware/mesh_bed_calibration.h
+++ b/Firmware/mesh_bed_calibration.h
@@ -146,9 +146,9 @@ inline bool world2machine_clamp(float &x, float &y)
return clamped;
}
-extern bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
-extern bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
-extern void go_home_with_z_lift();
+bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
+bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
+void go_home_with_z_lift();
/**
* @brief Bed skew and offest detection result
diff --git a/Firmware/messages.c b/Firmware/messages.c
index 58e131d68..97cae85d7 100644
--- a/Firmware/messages.c
+++ b/Firmware/messages.c
@@ -197,4 +197,3 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
-const char MSG_FILE_SELECTED[] PROGMEM_N1 = "File selected"; ////c=20
diff --git a/Firmware/messages.h b/Firmware/messages.h
index a5b672fa2..0a05c58f5 100644
--- a/Firmware/messages.h
+++ b/Firmware/messages.h
@@ -197,7 +197,6 @@ extern const char MSG_M112_KILL[];
extern const char MSG_ADVANCE_K[];
extern const char MSG_POWERPANIC_DETECTED[];
extern const char MSG_LCD_STATUS_CHANGED[];
-extern const char MSG_FILE_SELECTED[];
#if defined(__cplusplus)
}
diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp
index 0326da88a..c2d83572c 100755
--- a/Firmware/ultralcd.cpp
+++ b/Firmware/ultralcd.cpp
@@ -8398,7 +8398,7 @@ static void lcd_selftest_screen_step(int _row, int _col, int _state, const char
static bool check_file(const char* filename) {
if (farm_mode) return true;
- card.openFile((char*)filename, true);
+ card.openFileReadFilteredGcode(filename, true);
bool result = false;
const uint32_t filesize = card.getFileSize();
uint32_t startPos = 0;