cardreader.cpp

changeset 0
2c8ba1964db7
equal deleted inserted replaced
-1:000000000000 0:2c8ba1964db7
1 #include "Marlin.h"
2 #include "cardreader.h"
3 #include "ultralcd.h"
4 #include "stepper.h"
5 #include "temperature.h"
6 #include "language.h"
7
8 #ifdef SDSUPPORT
9
10
11
12 CardReader::CardReader()
13 {
14 filesize = 0;
15 sdpos = 0;
16 sdprinting = false;
17 cardOK = false;
18 saving = false;
19 autostart_atmillis=0;
20
21 autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
22 lastnr=0;
23 //power to SD reader
24 #if SDPOWER > -1
25 SET_OUTPUT(SDPOWER);
26 WRITE(SDPOWER,HIGH);
27 #endif //SDPOWER
28
29 autostart_atmillis=millis()+5000;
30 }
31
32 char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
33 {
34 char *pos=buffer;
35 for (uint8_t i = 0; i < 11; i++)
36 {
37 if (p.name[i] == ' ')continue;
38 if (i == 8)
39 {
40 *pos++='.';
41 }
42 *pos++=p.name[i];
43 }
44 *pos++=0;
45 return buffer;
46 }
47
48
49 void CardReader::lsDive(const char *prepend,SdFile parent)
50 {
51 dir_t p;
52 uint8_t cnt=0;
53
54 while (parent.readDir(p) > 0)
55 {
56 if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint
57 {
58
59 char path[13*2];
60 char lfilename[13];
61 createFilename(lfilename,p);
62
63 path[0]=0;
64 if(strlen(prepend)==0) //avoid leading / if already in prepend
65 {
66 strcat(path,"/");
67 }
68 strcat(path,prepend);
69 strcat(path,lfilename);
70 strcat(path,"/");
71
72 //Serial.print(path);
73
74 SdFile dir;
75 if(!dir.open(parent,lfilename, O_READ))
76 {
77 if(lsAction==LS_SerialPrint)
78 {
79 SERIAL_ECHO_START;
80 SERIAL_ECHOLN(MSG_SD_CANT_OPEN_SUBDIR);
81 SERIAL_ECHOLN(lfilename);
82 }
83 }
84 lsDive(path,dir);
85 //close done automatically by destructor of SdFile
86
87
88 }
89 else
90 {
91 if (p.name[0] == DIR_NAME_FREE) break;
92 if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
93 if ( p.name[0] == '.')
94 {
95 if ( p.name[1] != '.')
96 continue;
97 }
98
99 if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
100 filenameIsDir=DIR_IS_SUBDIR(&p);
101
102
103 if(!filenameIsDir)
104 {
105 if(p.name[8]!='G') continue;
106 if(p.name[9]=='~') continue;
107 }
108 //if(cnt++!=nr) continue;
109 createFilename(filename,p);
110 if(lsAction==LS_SerialPrint)
111 {
112 SERIAL_PROTOCOL(prepend);
113 SERIAL_PROTOCOLLN(filename);
114 }
115 else if(lsAction==LS_Count)
116 {
117 nrFiles++;
118 }
119 else if(lsAction==LS_GetFilename)
120 {
121 if(cnt==nrFiles)
122 return;
123 cnt++;
124
125 }
126 }
127 }
128 }
129
130 void CardReader::ls()
131 {
132 lsAction=LS_SerialPrint;
133 if(lsAction==LS_Count)
134 nrFiles=0;
135
136 root.rewind();
137 lsDive("",root);
138 }
139
140
141 void CardReader::initsd()
142 {
143 cardOK = false;
144 if(root.isOpen())
145 root.close();
146 if (!card.init(SPI_FULL_SPEED,SDSS))
147 {
148 //if (!card.init(SPI_HALF_SPEED,SDSS))
149 SERIAL_ECHO_START;
150 SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
151 }
152 else if (!volume.init(&card))
153 {
154 SERIAL_ERROR_START;
155 SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL);
156 }
157 else if (!root.openRoot(&volume))
158 {
159 SERIAL_ERROR_START;
160 SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL);
161 }
162 else
163 {
164 cardOK = true;
165 SERIAL_ECHO_START;
166 SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
167 }
168 workDir=root;
169 curDir=&root;
170 /*
171 if(!workDir.openRoot(&volume))
172 {
173 SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
174 }
175 */
176
177 }
178
179 void CardReader::setroot()
180 {
181 /*if(!workDir.openRoot(&volume))
182 {
183 SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
184 }*/
185 workDir=root;
186
187 curDir=&workDir;
188 }
189 void CardReader::release()
190 {
191 sdprinting = false;
192 cardOK = false;
193 }
194
195 void CardReader::startFileprint()
196 {
197 if(cardOK)
198 {
199 sdprinting = true;
200
201 }
202 }
203
204 void CardReader::pauseSDPrint()
205 {
206 if(sdprinting)
207 {
208 sdprinting = false;
209 }
210 }
211
212
213
214 void CardReader::openFile(char* name,bool read)
215 {
216 if(!cardOK)
217 return;
218 file.close();
219 sdprinting = false;
220
221
222 SdFile myDir;
223 curDir=&root;
224 char *fname=name;
225
226 char *dirname_start,*dirname_end;
227 if(name[0]=='/')
228 {
229 dirname_start=strchr(name,'/')+1;
230 while(dirname_start>0)
231 {
232 dirname_end=strchr(dirname_start,'/');
233 //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
234 //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
235 if(dirname_end>0 && dirname_end>dirname_start)
236 {
237 char subdirname[13];
238 strncpy(subdirname, dirname_start, dirname_end-dirname_start);
239 subdirname[dirname_end-dirname_start]=0;
240 SERIAL_ECHOLN(subdirname);
241 if(!myDir.open(curDir,subdirname,O_READ))
242 {
243 SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
244 SERIAL_PROTOCOL(subdirname);
245 SERIAL_PROTOCOLLNPGM(".");
246 return;
247 }
248 else
249 ;//SERIAL_ECHOLN("dive ok");
250
251 curDir=&myDir;
252 dirname_start=dirname_end+1;
253 }
254 else // the reminder after all /fsa/fdsa/ is the filename
255 {
256 fname=dirname_start;
257 //SERIAL_ECHOLN("remaider");
258 //SERIAL_ECHOLN(fname);
259 break;
260 }
261
262 }
263 }
264 else //relative path
265 {
266 curDir=&workDir;
267 }
268 if(read)
269 {
270 if (file.open(curDir, fname, O_READ))
271 {
272 filesize = file.fileSize();
273 SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED);
274 SERIAL_PROTOCOL(fname);
275 SERIAL_PROTOCOLPGM(MSG_SD_SIZE);
276 SERIAL_PROTOCOLLN(filesize);
277 sdpos = 0;
278
279 SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
280 LCD_MESSAGE(fname);
281 }
282 else
283 {
284 SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
285 SERIAL_PROTOCOL(fname);
286 SERIAL_PROTOCOLLNPGM(".");
287 }
288 }
289 else
290 { //write
291 if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
292 {
293 SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
294 SERIAL_PROTOCOL(fname);
295 SERIAL_PROTOCOLLNPGM(".");
296 }
297 else
298 {
299 saving = true;
300 SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE);
301 SERIAL_PROTOCOLLN(name);
302 LCD_MESSAGE(fname);
303 }
304 }
305
306 }
307
308 void CardReader::removeFile(char* name)
309 {
310 if(!cardOK)
311 return;
312 file.close();
313 sdprinting = false;
314
315
316 SdFile myDir;
317 curDir=&root;
318 char *fname=name;
319
320 char *dirname_start,*dirname_end;
321 if(name[0]=='/')
322 {
323 dirname_start=strchr(name,'/')+1;
324 while(dirname_start>0)
325 {
326 dirname_end=strchr(dirname_start,'/');
327 //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
328 //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
329 if(dirname_end>0 && dirname_end>dirname_start)
330 {
331 char subdirname[13];
332 strncpy(subdirname, dirname_start, dirname_end-dirname_start);
333 subdirname[dirname_end-dirname_start]=0;
334 SERIAL_ECHOLN(subdirname);
335 if(!myDir.open(curDir,subdirname,O_READ))
336 {
337 SERIAL_PROTOCOLPGM("open failed, File: ");
338 SERIAL_PROTOCOL(subdirname);
339 SERIAL_PROTOCOLLNPGM(".");
340 return;
341 }
342 else
343 ;//SERIAL_ECHOLN("dive ok");
344
345 curDir=&myDir;
346 dirname_start=dirname_end+1;
347 }
348 else // the reminder after all /fsa/fdsa/ is the filename
349 {
350 fname=dirname_start;
351 //SERIAL_ECHOLN("remaider");
352 //SERIAL_ECHOLN(fname);
353 break;
354 }
355
356 }
357 }
358 else //relative path
359 {
360 curDir=&workDir;
361 }
362 if (file.remove(curDir, fname))
363 {
364 SERIAL_PROTOCOLPGM("File deleted:");
365 SERIAL_PROTOCOL(fname);
366 sdpos = 0;
367 }
368 else
369 {
370 SERIAL_PROTOCOLPGM("Deletion failed, File: ");
371 SERIAL_PROTOCOL(fname);
372 SERIAL_PROTOCOLLNPGM(".");
373 }
374
375 }
376
377 void CardReader::getStatus()
378 {
379 if(cardOK){
380 SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
381 SERIAL_PROTOCOL(sdpos);
382 SERIAL_PROTOCOLPGM("/");
383 SERIAL_PROTOCOLLN(filesize);
384 }
385 else{
386 SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
387 }
388 }
389 void CardReader::write_command(char *buf)
390 {
391 char* begin = buf;
392 char* npos = 0;
393 char* end = buf + strlen(buf) - 1;
394
395 file.writeError = false;
396 if((npos = strchr(buf, 'N')) != NULL)
397 {
398 begin = strchr(npos, ' ') + 1;
399 end = strchr(npos, '*') - 1;
400 }
401 end[1] = '\r';
402 end[2] = '\n';
403 end[3] = '\0';
404 file.write(begin);
405 if (file.writeError)
406 {
407 SERIAL_ERROR_START;
408 SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE);
409 }
410 }
411
412
413 void CardReader::checkautostart(bool force)
414 {
415 if(!force)
416 {
417 if(!autostart_stilltocheck)
418 return;
419 if(autostart_atmillis<millis())
420 return;
421 }
422 autostart_stilltocheck=false;
423 if(!cardOK)
424 {
425 initsd();
426 if(!cardOK) //fail
427 return;
428 }
429
430 char autoname[30];
431 sprintf(autoname,"auto%i.g",lastnr);
432 for(int8_t i=0;i<(int)strlen(autoname);i++)
433 autoname[i]=tolower(autoname[i]);
434 dir_t p;
435
436 root.rewind();
437
438 bool found=false;
439 while (root.readDir(p) > 0)
440 {
441 for(int8_t i=0;i<(int)strlen((char*)p.name);i++)
442 p.name[i]=tolower(p.name[i]);
443 //Serial.print((char*)p.name);
444 //Serial.print(" ");
445 //Serial.println(autoname);
446 if(p.name[9]!='~') //skip safety copies
447 if(strncmp((char*)p.name,autoname,5)==0)
448 {
449 char cmd[30];
450
451 sprintf(cmd,"M23 %s",autoname);
452 enquecommand(cmd);
453 enquecommand("M24");
454 found=true;
455 }
456 }
457 if(!found)
458 lastnr=-1;
459 else
460 lastnr++;
461 }
462
463 void CardReader::closefile()
464 {
465 file.sync();
466 file.close();
467 saving = false;
468 }
469
470 void CardReader::getfilename(const uint8_t nr)
471 {
472 curDir=&workDir;
473 lsAction=LS_GetFilename;
474 nrFiles=nr;
475 curDir->rewind();
476 lsDive("",*curDir);
477
478 }
479
480 uint16_t CardReader::getnrfilenames()
481 {
482 curDir=&workDir;
483 lsAction=LS_Count;
484 nrFiles=0;
485 curDir->rewind();
486 lsDive("",*curDir);
487 //SERIAL_ECHOLN(nrFiles);
488 return nrFiles;
489 }
490
491 void CardReader::chdir(const char * relpath)
492 {
493 SdFile newfile;
494 SdFile *parent=&root;
495
496 if(workDir.isOpen())
497 parent=&workDir;
498
499 if(!newfile.open(*parent,relpath, O_READ))
500 {
501 SERIAL_ECHO_START;
502 SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
503 SERIAL_ECHOLN(relpath);
504 }
505 else
506 {
507 workDirParentParent=workDirParent;
508 workDirParent=*parent;
509
510 workDir=newfile;
511 }
512 }
513
514 void CardReader::updir()
515 {
516 if(!workDir.isRoot())
517 {
518 workDir=workDirParent;
519 workDirParent=workDirParentParent;
520 }
521 }
522
523
524 void CardReader::printingHasFinished()
525 {
526 st_synchronize();
527 quickStop();
528 sdprinting = false;
529 if(SD_FINISHED_STEPPERRELEASE)
530 {
531 //finishAndDisableSteppers();
532 enquecommand(SD_FINISHED_RELEASECOMMAND);
533 }
534 }
535 void CardReader::fast_xfer(char* strchr_pointer)
536 {
537 char *pstr;
538 boolean done = false;
539
540 //force heater pins low
541 if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW);
542 if(HEATER_BED_PIN > -1) WRITE(HEATER_BED_PIN,LOW);
543
544 lastxferchar = 1;
545 xferbytes = 0;
546
547 pstr = strstr(strchr_pointer, " ");
548 //pstr = strchr_pointer;
549
550 if(pstr == NULL)
551 {
552 SERIAL_ECHOLN("invalid command");
553 return;
554 }
555
556 *pstr = '\0';
557
558 //check mode (currently only RAW is supported
559 if(strcmp(strchr_pointer, "RAW") != 0)
560 {
561 SERIAL_ECHOLN("Invalid transfer codec");
562 return;
563 }else{
564 SERIAL_ECHOPGM("Selected codec: ");
565 SERIAL_ECHOLN(strchr_pointer+4);
566 }
567
568 if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
569 {
570 SERIAL_ECHOPGM("open failed, File: ");
571 SERIAL_ECHOLN(pstr+1);
572 SERIAL_ECHOPGM(".");
573 }else{
574 SERIAL_ECHOPGM("Writing to file: ");
575 SERIAL_ECHOLN(pstr+1);
576 }
577
578 SERIAL_ECHOLN("ok");
579
580 //RAW transfer codec
581 //Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0
582 //when host is done, it sends \0\0.
583 //if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer.
584
585 //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved)
586 while(!done)
587 {
588 while(!MYSERIAL.available())
589 {
590 }
591 if(MYSERIAL.peek() != 0)
592 {
593 //host has failed, this isn't a RAW chunk, it's an actual command
594 file.sync();
595 file.close();
596 SERIAL_ECHOLN("Not RAW data");
597 return;
598 }
599 //clear the initial 0
600 MYSERIAL.read();
601 for(int i=0;i<SD_FAST_XFER_CHUNK_SIZE+1;i++)
602 {
603 while(!MYSERIAL.available())
604 {
605 }
606 lastxferchar = MYSERIAL.read();
607 //buffer the data...
608 fastxferbuffer[i] = lastxferchar;
609
610 xferbytes++;
611
612 if(lastxferchar == 0)
613 break;
614 }
615
616 if(fastxferbuffer[0] != 0)
617 {
618 fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE] = 0;
619 file.write(fastxferbuffer);
620 SERIAL_ECHOLN("ok");
621 }else{
622 SERIAL_ECHOPGM("Wrote ");
623 SERIAL_ECHO(xferbytes);
624 SERIAL_ECHOLN(" bytes.");
625 done = true;
626 }
627 }
628
629 file.sync();
630 file.close();
631 }
632
633 #endif //SDSUPPORT

mercurial