Sub-file calls.
by overloading M32 it is now possible to execute gcode files from other gcode files, with a fixed recursion level. This can be used e.g. for having a real start.g and end.g somewhere on the sd card, which are then called from the normal print file. Another usecase would be to have macro-files for nozzle-change and layerchange. I have not tested the speedwise performance. The testing was done with pronterface. syntax: normal call from sd card will open the new file and continue executing there. M32 !/path/filename# this however will call the new file and return to the caller file. M32 P !/path/filename# with the optional "S<position>" the file starting position can be set. this is for continuing prints from a previous location.
This commit is contained in:
parent
b2cc27e5ea
commit
ab965376ff
@ -90,7 +90,10 @@
|
|||||||
// M29 - Stop SD write
|
// M29 - Stop SD write
|
||||||
// M30 - Delete file from SD (M30 filename.g)
|
// M30 - Delete file from SD (M30 filename.g)
|
||||||
// M31 - Output time since last M109 or SD card start to serial
|
// 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<startpos bytes> !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.
|
// 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
|
// M80 - Turn on Power Supply
|
||||||
// M81 - Turn off Power Supply
|
// M81 - Turn off Power Supply
|
||||||
@ -1467,19 +1470,41 @@ void process_commands()
|
|||||||
card.removeFile(strchr_pointer + 4);
|
card.removeFile(strchr_pointer + 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32: //M32 - Select file and start SD print
|
case 32: //M32 - Select file and start SD print
|
||||||
|
{
|
||||||
if(card.sdprinting) {
|
if(card.sdprinting) {
|
||||||
st_synchronize();
|
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)
|
if(starpos!=NULL)
|
||||||
*(starpos-1)='\0';
|
*(starpos-1)='\0';
|
||||||
card.openFile(strchr_pointer + 4,true);
|
|
||||||
card.startFileprint();
|
bool call_procedure=(code_seen('P'));
|
||||||
starttime=millis();
|
|
||||||
break;
|
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<namestartpos) //only if "S" is occuring _before_ the filename
|
||||||
|
card.setIndex(code_value_long());
|
||||||
|
card.startFileprint();
|
||||||
|
if(!call_procedure)
|
||||||
|
starttime=millis(); //procedure calls count as normal print time.
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 928: //M928 - Start SD write
|
case 928: //M928 - Start SD write
|
||||||
starpos = (strchr(strchr_pointer + 5,'*'));
|
starpos = (strchr(strchr_pointer + 5,'*'));
|
||||||
if(starpos != NULL){
|
if(starpos != NULL){
|
||||||
|
@ -19,6 +19,7 @@ CardReader::CardReader()
|
|||||||
logging = false;
|
logging = false;
|
||||||
autostart_atmillis=0;
|
autostart_atmillis=0;
|
||||||
workDirDepth = 0;
|
workDirDepth = 0;
|
||||||
|
file_subcall_ctr=0;
|
||||||
memset(workDirParents, 0, sizeof(workDirParents));
|
memset(workDirParents, 0, sizeof(workDirParents));
|
||||||
|
|
||||||
autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
|
autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
|
||||||
@ -224,14 +225,71 @@ void CardReader::openLogFile(char* name)
|
|||||||
openFile(name, false);
|
openFile(name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::openFile(char* name,bool read)
|
void CardReader::getAbsFilename(char *t)
|
||||||
|
{
|
||||||
|
uint8_t cnt=0;
|
||||||
|
*t='/';t++;cnt++;
|
||||||
|
for(uint8_t i=0;i<workDirDepth;i++)
|
||||||
|
{
|
||||||
|
workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
|
||||||
|
while(*t!=0 && cnt< MAXPATHNAMELENGTH)
|
||||||
|
{t++;cnt++;} //crawl counter forward.
|
||||||
|
}
|
||||||
|
if(cnt<MAXPATHNAMELENGTH-13)
|
||||||
|
file.getFilename(t);
|
||||||
|
else
|
||||||
|
t[0]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
|
||||||
{
|
{
|
||||||
if(!cardOK)
|
if(!cardOK)
|
||||||
return;
|
return;
|
||||||
file.close();
|
if(file.isOpen()) //replaceing 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();
|
||||||
|
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;
|
sdprinting = false;
|
||||||
|
|
||||||
|
|
||||||
SdFile myDir;
|
SdFile myDir;
|
||||||
curDir=&root;
|
curDir=&root;
|
||||||
char *fname=name;
|
char *fname=name;
|
||||||
@ -547,14 +605,25 @@ void CardReader::updir()
|
|||||||
void CardReader::printingHasFinished()
|
void CardReader::printingHasFinished()
|
||||||
{
|
{
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
quickStop();
|
if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure.
|
||||||
file.close();
|
|
||||||
sdprinting = false;
|
|
||||||
if(SD_FINISHED_STEPPERRELEASE)
|
|
||||||
{
|
{
|
||||||
//finishAndDisableSteppers();
|
file.close();
|
||||||
enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND));
|
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
|
#endif //SDSUPPORT
|
||||||
|
@ -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
|
//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 checkautostart(bool x);
|
||||||
void openFile(char* name,bool read);
|
void openFile(char* name,bool read,bool replace_current=true);
|
||||||
void openLogFile(char* name);
|
void openLogFile(char* name);
|
||||||
void removeFile(char* name);
|
void removeFile(char* name);
|
||||||
void closefile();
|
void closefile();
|
||||||
@ -31,6 +31,8 @@ public:
|
|||||||
void getfilename(const uint8_t nr);
|
void getfilename(const uint8_t nr);
|
||||||
uint16_t getnrfilenames();
|
uint16_t getnrfilenames();
|
||||||
|
|
||||||
|
void getAbsFilename(char *t);
|
||||||
|
|
||||||
|
|
||||||
void ls();
|
void ls();
|
||||||
void chdir(const char * relpath);
|
void chdir(const char * relpath);
|
||||||
@ -60,6 +62,11 @@ private:
|
|||||||
Sd2Card card;
|
Sd2Card card;
|
||||||
SdVolume volume;
|
SdVolume volume;
|
||||||
SdFile file;
|
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;
|
uint32_t filesize;
|
||||||
//int16_t n;
|
//int16_t n;
|
||||||
unsigned long autostart_atmillis;
|
unsigned long autostart_atmillis;
|
||||||
|
Loading…
Reference in New Issue
Block a user