--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cardreader.cpp Sat Nov 07 13:23:07 2015 +0100 @@ -0,0 +1,633 @@ +#include "Marlin.h" +#include "cardreader.h" +#include "ultralcd.h" +#include "stepper.h" +#include "temperature.h" +#include "language.h" + +#ifdef SDSUPPORT + + + +CardReader::CardReader() +{ + filesize = 0; + sdpos = 0; + sdprinting = false; + cardOK = false; + saving = false; + autostart_atmillis=0; + + autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + lastnr=0; + //power to SD reader + #if SDPOWER > -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); + #endif //SDPOWER + + autostart_atmillis=millis()+5000; +} + +char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +{ + char *pos=buffer; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ')continue; + if (i == 8) + { + *pos++='.'; + } + *pos++=p.name[i]; + } + *pos++=0; + return buffer; +} + + +void CardReader::lsDive(const char *prepend,SdFile parent) +{ + dir_t p; + uint8_t cnt=0; + + while (parent.readDir(p) > 0) + { + if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint + { + + char path[13*2]; + char lfilename[13]; + createFilename(lfilename,p); + + path[0]=0; + if(strlen(prepend)==0) //avoid leading / if already in prepend + { + strcat(path,"/"); + } + strcat(path,prepend); + strcat(path,lfilename); + strcat(path,"/"); + + //Serial.print(path); + + SdFile dir; + if(!dir.open(parent,lfilename, O_READ)) + { + if(lsAction==LS_SerialPrint) + { + SERIAL_ECHO_START; + SERIAL_ECHOLN(MSG_SD_CANT_OPEN_SUBDIR); + SERIAL_ECHOLN(lfilename); + } + } + lsDive(path,dir); + //close done automatically by destructor of SdFile + + + } + else + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if ( p.name[0] == '.') + { + if ( p.name[1] != '.') + continue; + } + + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + filenameIsDir=DIR_IS_SUBDIR(&p); + + + if(!filenameIsDir) + { + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + } + //if(cnt++!=nr) continue; + createFilename(filename,p); + if(lsAction==LS_SerialPrint) + { + SERIAL_PROTOCOL(prepend); + SERIAL_PROTOCOLLN(filename); + } + else if(lsAction==LS_Count) + { + nrFiles++; + } + else if(lsAction==LS_GetFilename) + { + if(cnt==nrFiles) + return; + cnt++; + + } + } + } +} + +void CardReader::ls() +{ + lsAction=LS_SerialPrint; + if(lsAction==LS_Count) + nrFiles=0; + + root.rewind(); + lsDive("",root); +} + + +void CardReader::initsd() +{ + cardOK = false; + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)) + { + //if (!card.init(SPI_HALF_SPEED,SDSS)) + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL); + } + else if (!volume.init(&card)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL); + } + else if (!root.openRoot(&volume)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL); + } + else + { + cardOK = true; + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(MSG_SD_CARD_OK); + } + workDir=root; + curDir=&root; + /* + if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); + } + */ + +} + +void CardReader::setroot() +{ + /*if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); + }*/ + workDir=root; + + curDir=&workDir; +} +void CardReader::release() +{ + sdprinting = false; + cardOK = false; +} + +void CardReader::startFileprint() +{ + if(cardOK) + { + sdprinting = true; + + } +} + +void CardReader::pauseSDPrint() +{ + if(sdprinting) + { + sdprinting = false; + } +} + + + +void CardReader::openFile(char* name,bool read) +{ + if(!cardOK) + return; + file.close(); + sdprinting = false; + + + SdFile myDir; + curDir=&root; + char *fname=name; + + char *dirname_start,*dirname_end; + if(name[0]=='/') + { + dirname_start=strchr(name,'/')+1; + while(dirname_start>0) + { + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end>0 && dirname_end>dirname_start) + { + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + ;//SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; + } + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + + } + } + else //relative path + { + curDir=&workDir; + } + if(read) + { + if (file.open(curDir, fname, O_READ)) + { + filesize = file.fileSize(); + SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLPGM(MSG_SD_SIZE); + SERIAL_PROTOCOLLN(filesize); + sdpos = 0; + + SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED); + LCD_MESSAGE(fname); + } + else + { + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + } + else + { //write + if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + else + { + saving = true; + SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE); + SERIAL_PROTOCOLLN(name); + LCD_MESSAGE(fname); + } + } + +} + +void CardReader::removeFile(char* name) +{ + if(!cardOK) + return; + file.close(); + sdprinting = false; + + + SdFile myDir; + curDir=&root; + char *fname=name; + + char *dirname_start,*dirname_end; + if(name[0]=='/') + { + dirname_start=strchr(name,'/')+1; + while(dirname_start>0) + { + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end>0 && dirname_end>dirname_start) + { + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + ;//SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; + } + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + + } + } + else //relative path + { + curDir=&workDir; + } + if (file.remove(curDir, fname)) + { + SERIAL_PROTOCOLPGM("File deleted:"); + SERIAL_PROTOCOL(fname); + sdpos = 0; + } + else + { + SERIAL_PROTOCOLPGM("Deletion failed, File: "); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + +} + +void CardReader::getStatus() +{ + if(cardOK){ + SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE); + SERIAL_PROTOCOL(sdpos); + SERIAL_PROTOCOLPGM("/"); + SERIAL_PROTOCOLLN(filesize); + } + else{ + SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING); + } +} +void CardReader::write_command(char *buf) +{ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL) + { + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + file.write(begin); + if (file.writeError) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE); + } +} + + +void CardReader::checkautostart(bool force) +{ + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis<millis()) + return; + } + autostart_stilltocheck=false; + if(!cardOK) + { + initsd(); + if(!cardOK) //fail + return; + } + + char autoname[30]; + sprintf(autoname,"auto%i.g",lastnr); + for(int8_t i=0;i<(int)strlen(autoname);i++) + autoname[i]=tolower(autoname[i]); + dir_t p; + + root.rewind(); + + bool found=false; + while (root.readDir(p) > 0) + { + for(int8_t i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + enquecommand(cmd); + enquecommand("M24"); + found=true; + } + } + if(!found) + lastnr=-1; + else + lastnr++; +} + +void CardReader::closefile() +{ + file.sync(); + file.close(); + saving = false; +} + +void CardReader::getfilename(const uint8_t nr) +{ + curDir=&workDir; + lsAction=LS_GetFilename; + nrFiles=nr; + curDir->rewind(); + lsDive("",*curDir); + +} + +uint16_t CardReader::getnrfilenames() +{ + curDir=&workDir; + lsAction=LS_Count; + nrFiles=0; + curDir->rewind(); + lsDive("",*curDir); + //SERIAL_ECHOLN(nrFiles); + return nrFiles; +} + +void CardReader::chdir(const char * relpath) +{ + SdFile newfile; + SdFile *parent=&root; + + if(workDir.isOpen()) + parent=&workDir; + + if(!newfile.open(*parent,relpath, O_READ)) + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR); + SERIAL_ECHOLN(relpath); + } + else + { + workDirParentParent=workDirParent; + workDirParent=*parent; + + workDir=newfile; + } +} + +void CardReader::updir() +{ + if(!workDir.isRoot()) + { + workDir=workDirParent; + workDirParent=workDirParentParent; + } +} + + +void CardReader::printingHasFinished() +{ + st_synchronize(); + quickStop(); + sdprinting = false; + if(SD_FINISHED_STEPPERRELEASE) + { + //finishAndDisableSteppers(); + enquecommand(SD_FINISHED_RELEASECOMMAND); + } +} +void CardReader::fast_xfer(char* strchr_pointer) + { + char *pstr; + boolean done = false; + + //force heater pins low + if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW); + if(HEATER_BED_PIN > -1) WRITE(HEATER_BED_PIN,LOW); + + lastxferchar = 1; + xferbytes = 0; + + pstr = strstr(strchr_pointer, " "); + //pstr = strchr_pointer; + + if(pstr == NULL) + { + SERIAL_ECHOLN("invalid command"); + return; + } + + *pstr = '\0'; + + //check mode (currently only RAW is supported + if(strcmp(strchr_pointer, "RAW") != 0) + { + SERIAL_ECHOLN("Invalid transfer codec"); + return; + }else{ + SERIAL_ECHOPGM("Selected codec: "); + SERIAL_ECHOLN(strchr_pointer+4); + } + + if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + SERIAL_ECHOPGM("open failed, File: "); + SERIAL_ECHOLN(pstr+1); + SERIAL_ECHOPGM("."); + }else{ + SERIAL_ECHOPGM("Writing to file: "); + SERIAL_ECHOLN(pstr+1); + } + + SERIAL_ECHOLN("ok"); + + //RAW transfer codec + //Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0 + //when host is done, it sends \0\0. + //if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer. + + //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved) + while(!done) + { + while(!MYSERIAL.available()) + { + } + if(MYSERIAL.peek() != 0) + { + //host has failed, this isn't a RAW chunk, it's an actual command + file.sync(); + file.close(); + SERIAL_ECHOLN("Not RAW data"); + return; + } + //clear the initial 0 + MYSERIAL.read(); + for(int i=0;i<SD_FAST_XFER_CHUNK_SIZE+1;i++) + { + while(!MYSERIAL.available()) + { + } + lastxferchar = MYSERIAL.read(); + //buffer the data... + fastxferbuffer[i] = lastxferchar; + + xferbytes++; + + if(lastxferchar == 0) + break; + } + + if(fastxferbuffer[0] != 0) + { + fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE] = 0; + file.write(fastxferbuffer); + SERIAL_ECHOLN("ok"); + }else{ + SERIAL_ECHOPGM("Wrote "); + SERIAL_ECHO(xferbytes); + SERIAL_ECHOLN(" bytes."); + done = true; + } + } + + file.sync(); + file.close(); + } + +#endif //SDSUPPORT