Browse Source

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.
bkubicek 11 years ago
parent
commit
ab965376ff
3 changed files with 121 additions and 20 deletions
  1. 34
    9
      Marlin/Marlin_main.cpp
  2. 79
    10
      Marlin/cardreader.cpp
  3. 8
    1
      Marlin/cardreader.h

+ 34
- 9
Marlin/Marlin_main.cpp View File

90
 // M29  - Stop SD write
90
 // M29  - Stop SD write
91
 // M30  - Delete file from SD (M30 filename.g)
91
 // M30  - Delete file from SD (M30 filename.g)
92
 // M31  - Output time since last M109 or SD card start to serial
92
 // M31  - Output time since last M109 or SD card start to serial
93
-// M32  - Select file and start SD print (Can be used when printing from SD card)
93
+// M32  - Select file and start SD print (Can be used _while_ printing from SD card files): 
94
+//        syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"
95
+//        Call gcode file : "M32 P !filename#" and return to caller file after finishing (simiarl to #include).
96
+//        The '#' is necessary when calling from within sd files, as it stops buffer prereading
94
 // 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.
97
 // 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.
95
 // M80  - Turn on Power Supply
98
 // M80  - Turn on Power Supply
96
 // M81  - Turn off Power Supply
99
 // M81  - Turn off Power Supply
1467
         card.removeFile(strchr_pointer + 4);
1470
         card.removeFile(strchr_pointer + 4);
1468
       }
1471
       }
1469
       break;
1472
       break;
1470
-    case 32: //M32 - Select file and start SD print
1473
+    case 32: //M32 - Select file and start SD print 
1474
+    {
1471
       if(card.sdprinting) {
1475
       if(card.sdprinting) {
1472
         st_synchronize();
1476
         st_synchronize();
1473
-        card.closefile();
1474
-        card.sdprinting = false;
1477
+
1475
       }
1478
       }
1476
-      starpos = (strchr(strchr_pointer + 4,'*'));
1479
+      starpos = (strchr(strchr_pointer + 4,'*')); 
1480
+      
1481
+      char* namestartpos = (strchr(strchr_pointer + 4,'!'));   //find ! to indicate filename string start.
1482
+      if(namestartpos==NULL)
1483
+      {
1484
+        namestartpos=strchr_pointer + 4; //default name position, 4 letters after the M
1485
+      }
1486
+      else
1487
+        namestartpos++; //to skip the '!'
1488
+        
1477
       if(starpos!=NULL)
1489
       if(starpos!=NULL)
1478
         *(starpos-1)='\0';
1490
         *(starpos-1)='\0';
1479
-      card.openFile(strchr_pointer + 4,true);
1480
-      card.startFileprint();
1481
-      starttime=millis();
1482
-      break;
1491
+            
1492
+      bool call_procedure=(code_seen('P'));
1493
+      
1494
+      if(strchr_pointer>namestartpos) 
1495
+        call_procedure=false;  //false alert, 'P' found within filename
1496
+      
1497
+      if( card.cardOK ) 
1498
+      {
1499
+        card.openFile(namestartpos,true,!call_procedure);
1500
+        if(code_seen('S'))
1501
+          if(strchr_pointer<namestartpos) //only if "S" is occuring _before_ the filename
1502
+            card.setIndex(code_value_long());
1503
+        card.startFileprint();
1504
+        if(!call_procedure)
1505
+          starttime=millis(); //procedure calls count as normal print time.
1506
+      }
1507
+    } break;
1483
     case 928: //M928 - Start SD write
1508
     case 928: //M928 - Start SD write
1484
       starpos = (strchr(strchr_pointer + 5,'*'));
1509
       starpos = (strchr(strchr_pointer + 5,'*'));
1485
       if(starpos != NULL){
1510
       if(starpos != NULL){

+ 79
- 10
Marlin/cardreader.cpp View File

19
    logging = false;
19
    logging = false;
20
    autostart_atmillis=0;
20
    autostart_atmillis=0;
21
    workDirDepth = 0;
21
    workDirDepth = 0;
22
+   file_subcall_ctr=0;
22
    memset(workDirParents, 0, sizeof(workDirParents));
23
    memset(workDirParents, 0, sizeof(workDirParents));
23
 
24
 
24
    autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
25
    autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
224
   openFile(name, false);
225
   openFile(name, false);
225
 }
226
 }
226
 
227
 
227
-void CardReader::openFile(char* name,bool read)
228
+void CardReader::getAbsFilename(char *t)
229
+{
230
+  uint8_t cnt=0;
231
+  *t='/';t++;cnt++;
232
+  for(uint8_t i=0;i<workDirDepth;i++)
233
+  {
234
+    workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
235
+    while(*t!=0 && cnt< MAXPATHNAMELENGTH) 
236
+    {t++;cnt++;}  //crawl counter forward.
237
+  }
238
+  if(cnt<MAXPATHNAMELENGTH-13)
239
+    file.getFilename(t);
240
+  else
241
+    t[0]=0;
242
+}
243
+
244
+void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
228
 {
245
 {
229
   if(!cardOK)
246
   if(!cardOK)
230
     return;
247
     return;
231
-  file.close();
248
+  if(file.isOpen())  //replaceing current file by new file, or subfile call
249
+  {
250
+    if(!replace_current)
251
+    {
252
+     if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
253
+     {
254
+       SERIAL_ERROR_START;
255
+       SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
256
+       SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
257
+       kill();
258
+       return;
259
+     }
260
+     
261
+     SERIAL_ECHO_START;
262
+     SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
263
+     SERIAL_ECHO(name);
264
+     SERIAL_ECHOPGM("\" parent:\"");
265
+     
266
+     //store current filename and position
267
+     getAbsFilename(filenames[file_subcall_ctr]);
268
+     
269
+     SERIAL_ECHO(filenames[file_subcall_ctr]);
270
+     SERIAL_ECHOPGM("\" pos");
271
+     SERIAL_ECHOLN(sdpos);
272
+     filespos[file_subcall_ctr]=sdpos;
273
+     file_subcall_ctr++;
274
+    }
275
+    else
276
+    {
277
+     SERIAL_ECHO_START;
278
+     SERIAL_ECHOPGM("Now doing file: ");
279
+     SERIAL_ECHOLN(name);
280
+    }
281
+    file.close();
282
+  }
283
+  else //opening fresh file
284
+  {
285
+    file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
286
+    SERIAL_ECHO_START;
287
+    SERIAL_ECHOPGM("Now fresh file: ");
288
+    SERIAL_ECHOLN(name);
289
+  }
232
   sdprinting = false;
290
   sdprinting = false;
233
   
291
   
234
-  
292
+ 
235
   SdFile myDir;
293
   SdFile myDir;
236
   curDir=&root;
294
   curDir=&root;
237
   char *fname=name;
295
   char *fname=name;
547
 void CardReader::printingHasFinished()
605
 void CardReader::printingHasFinished()
548
 {
606
 {
549
     st_synchronize();
607
     st_synchronize();
550
-    quickStop();
551
-    file.close();
552
-    sdprinting = false;
553
-    if(SD_FINISHED_STEPPERRELEASE)
608
+    if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure.
609
+    {
610
+      file.close();
611
+      file_subcall_ctr--;
612
+      openFile(filenames[file_subcall_ctr],true,true);
613
+      setIndex(filespos[file_subcall_ctr]);
614
+      startFileprint();
615
+    }
616
+    else
554
     {
617
     {
555
-        //finishAndDisableSteppers();
556
-        enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND));
618
+      quickStop();
619
+      file.close();
620
+      sdprinting = false;
621
+      if(SD_FINISHED_STEPPERRELEASE)
622
+      {
623
+          //finishAndDisableSteppers();
624
+          enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND));
625
+      }
626
+      autotempShutdown();
557
     }
627
     }
558
-    autotempShutdown();
559
 }
628
 }
560
 #endif //SDSUPPORT
629
 #endif //SDSUPPORT

+ 8
- 1
Marlin/cardreader.h View File

18
   //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
18
   //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
19
 
19
 
20
   void checkautostart(bool x); 
20
   void checkautostart(bool x); 
21
-  void openFile(char* name,bool read);
21
+  void openFile(char* name,bool read,bool replace_current=true);
22
   void openLogFile(char* name);
22
   void openLogFile(char* name);
23
   void removeFile(char* name);
23
   void removeFile(char* name);
24
   void closefile();
24
   void closefile();
31
   void getfilename(const uint8_t nr);
31
   void getfilename(const uint8_t nr);
32
   uint16_t getnrfilenames();
32
   uint16_t getnrfilenames();
33
   
33
   
34
+  void getAbsFilename(char *t);
35
+  
34
 
36
 
35
   void ls();
37
   void ls();
36
   void chdir(const char * relpath);
38
   void chdir(const char * relpath);
60
   Sd2Card card;
62
   Sd2Card card;
61
   SdVolume volume;
63
   SdVolume volume;
62
   SdFile file;
64
   SdFile file;
65
+  #define SD_PROCEDURE_DEPTH 1
66
+  #define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1)
67
+  uint8_t file_subcall_ctr;
68
+  uint32_t filespos[SD_PROCEDURE_DEPTH];
69
+  char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
63
   uint32_t filesize;
70
   uint32_t filesize;
64
   //int16_t n;
71
   //int16_t n;
65
   unsigned long autostart_atmillis;
72
   unsigned long autostart_atmillis;

Loading…
Cancel
Save