Fri, 17 Nov 2017 10:13:31 +0100
proper configuration, homing and planner optimization
#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