diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index c53a5b5830..4bea72b158 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -90,7 +90,10 @@ // M29 - Stop SD write // M30 - Delete file from SD (M30 filename.g) // M31 - Output time since last M109 or SD card start to serial -// M32 - Select file and start SD print (Can be used when printing from SD card) +// M32 - Select file and start SD print (Can be used _while_ printing from SD card files): +// syntax "M32 /path/filename#", or "M32 S !filename#" +// Call gcode file : "M32 P !filename#" and return to caller file after finishing (simiarl to #include). +// The '#' is necessary when calling from within sd files, as it stops buffer prereading // M42 - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used. // M80 - Turn on Power Supply // M81 - Turn off Power Supply @@ -1467,19 +1470,41 @@ void process_commands() card.removeFile(strchr_pointer + 4); } break; - case 32: //M32 - Select file and start SD print + case 32: //M32 - Select file and start SD print + { if(card.sdprinting) { st_synchronize(); - card.closefile(); - card.sdprinting = false; + } - starpos = (strchr(strchr_pointer + 4,'*')); + starpos = (strchr(strchr_pointer + 4,'*')); + + char* namestartpos = (strchr(strchr_pointer + 4,'!')); //find ! to indicate filename string start. + if(namestartpos==NULL) + { + namestartpos=strchr_pointer + 4; //default name position, 4 letters after the M + } + else + namestartpos++; //to skip the '!' + if(starpos!=NULL) *(starpos-1)='\0'; - card.openFile(strchr_pointer + 4,true); - card.startFileprint(); - starttime=millis(); - break; + + bool call_procedure=(code_seen('P')); + + if(strchr_pointer>namestartpos) + call_procedure=false; //false alert, 'P' found within filename + + if( card.cardOK ) + { + card.openFile(namestartpos,true,!call_procedure); + if(code_seen('S')) + if(strchr_pointer(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(); + 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; - + SdFile myDir; curDir=&root; char *fname=name; @@ -547,14 +605,25 @@ void CardReader::updir() void CardReader::printingHasFinished() { st_synchronize(); - quickStop(); - file.close(); - sdprinting = false; - if(SD_FINISHED_STEPPERRELEASE) + if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure. { - //finishAndDisableSteppers(); - enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND)); + file.close(); + file_subcall_ctr--; + openFile(filenames[file_subcall_ctr],true,true); + setIndex(filespos[file_subcall_ctr]); + startFileprint(); + } + else + { + quickStop(); + file.close(); + sdprinting = false; + if(SD_FINISHED_STEPPERRELEASE) + { + //finishAndDisableSteppers(); + enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND)); + } + autotempShutdown(); } - autotempShutdown(); } #endif //SDSUPPORT diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 6e59645295..07c7090ce9 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -18,7 +18,7 @@ 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(char* name,bool read); + void openFile(char* name,bool read,bool replace_current=true); void openLogFile(char* name); void removeFile(char* name); void closefile(); @@ -31,6 +31,8 @@ public: void getfilename(const uint8_t nr); uint16_t getnrfilenames(); + void getAbsFilename(char *t); + void ls(); void chdir(const char * relpath); @@ -60,6 +62,11 @@ private: Sd2Card card; SdVolume volume; SdFile file; + #define SD_PROCEDURE_DEPTH 1 + #define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1) + uint8_t file_subcall_ctr; + uint32_t filespos[SD_PROCEDURE_DEPTH]; + char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH]; uint32_t filesize; //int16_t n; unsigned long autostart_atmillis;