/ Repetier / SDCard.cpp
SDCard.cpp
  1  /*
  2      This file is part of Repetier-Firmware.
  3  
  4      Repetier-Firmware is free software: you can redistribute it and/or modify
  5      it under the terms of the GNU General Public License as published by
  6      the Free Software Foundation, either version 3 of the License, or
  7      (at your option) any later version.
  8  
  9      Repetier-Firmware is distributed in the hope that it will be useful,
 10      but WITHOUT ANY WARRANTY; without even the implied warranty of
 11      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12      GNU General Public License for more details.
 13  
 14      You should have received a copy of the GNU General Public License
 15      along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 16  
 17      This firmware is a nearly complete rewrite of the sprinter firmware
 18      by kliment (https://github.com/kliment/Sprinter)
 19      which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
 20  */
 21  
 22  #include "Reptier.h"
 23  #include "ui.h"
 24  
 25  #if SDSUPPORT
 26  
 27  #ifndef SD_ALLOW_LONG_NAMES
 28  #define SD_ALLOW_LONG_NAMES false
 29  #endif
 30  
 31  SDCard sd;
 32  
 33  SDCard::SDCard() {
 34    sdmode = false;
 35    sdactive = false;
 36    savetosd = false;
 37      //power to SD reader
 38  #if SDPOWER > -1
 39    SET_OUTPUT(SDPOWER); 
 40    WRITE(SDPOWER,HIGH);
 41  #endif
 42  #if defined(SDCARDDETECT) && SDCARDDETECT>-1
 43    SET_INPUT(SDCARDDETECT);
 44    WRITE(SDCARDDETECT,HIGH);
 45  #endif
 46  }
 47  void SDCard::automount() {
 48  #if defined(SDCARDDETECT) && SDCARDDETECT>-1
 49    if(READ(SDCARDDETECT) != SDCARDDETECTINVERTED) {
 50      if(sdactive) { // Card removed
 51        sdactive = false;
 52        savetosd = false;
 53        sdmode = false;
 54        UI_STATUS(UI_TEXT_SD_REMOVED);
 55        OUT_P_LN(UI_TEXT_SD_REMOVED);
 56      }
 57    } else {
 58      if(!sdactive) {
 59        UI_STATUS(UI_TEXT_SD_INSERTED);
 60        OUT_P_LN(UI_TEXT_SD_INSERTED);
 61        initsd();
 62      }
 63    }
 64  #endif
 65  }
 66  void SDCard::initsd() {
 67    sdactive = false;
 68    #if SDSS >- 1
 69      /*if(dir[0].isOpen())
 70          dir[0].close();*/
 71      if(!fat.begin(SDSS,SPI_FULL_SPEED)) {
 72          OUT_P_LN("SD init fail");
 73          return;
 74      }
 75      fat.setStdOut(&out);
 76      sdactive = true;
 77    #endif
 78  }
 79    
 80  void SDCard::write_command(GCode *code) {
 81       unsigned int sum1=0,sum2=0; // for fletcher-16 checksum
 82        byte buf[100];
 83        byte p=2;
 84        file.writeError = false;
 85        int params = 128 | (code->params & ~1);
 86        *(int*)buf = params;
 87        if(GCODE_IS_V2(code)) { // Read G,M as 16 bit value
 88          *(int*)&buf[p] = code->params2;p+=2;
 89          if(GCODE_HAS_STRING(code))
 90            buf[p++] = strlen(code->text);
 91          if(code->params & 2) {*(int*)&buf[p] = code->M;p+=2;}
 92          if(code->params & 4) {*(int*)&buf[p]= code->G;p+=2;}
 93        } else {
 94          if(code->params & 2) {buf[p++] = (byte)code->M;}
 95          if(code->params & 4) {buf[p++] = (byte)code->G;}
 96        }
 97        if(code->params & 8) {*(float*)&buf[p] = code->X;p+=4;}
 98        if(code->params & 16) {*(float*)&buf[p] = code->Y;p+=4;}
 99        if(code->params & 32) {*(float*)&buf[p] = code->Z;p+=4;}
100        if(code->params & 64) {*(float*)&buf[p] = code->E;p+=4;}
101        if(code->params & 256) {*(float*)&buf[p] = code->F;p+=4;}
102        if(code->params & 512) {buf[p++] = code->T;}
103        if(code->params & 1024) {*(long int*)&buf[p] = code->S;p+=4;}
104        if(code->params & 2048) {*(long int*)&buf[p] = code->P;p+=4;}
105        if(code->params2 & 1) {*(float*)&buf[p] = code->I;p+=4;}
106        if(code->params2 & 2) {*(float*)&buf[p] = code->J;p+=4;}
107        if(GCODE_HAS_STRING(code)) { // read 16 byte into string
108          char *sp = code->text;
109          if(GCODE_IS_V2(code)) {
110            byte i = strlen(code->text);
111            for(;i;i--) buf[p++] = *sp++;
112          } else {
113            for(byte i=0;i<16;++i) buf[p++] = *sp++;
114          }
115        }
116        byte *ptr = buf;
117        byte len = p;
118        while (len) {
119          byte tlen = len > 21 ? 21 : len;
120          len -= tlen;
121          do {
122            sum1 += *ptr++;
123            if(sum1>=255) sum1-=255;
124            sum2 += sum1;
125            if(sum2>=255) sum2-=255;
126          } while (--tlen);
127        }
128        buf[p++] = sum1;
129        buf[p++] = sum2;
130        file.write(buf,p);
131        if (file.writeError){
132            OUT_P_LN("error writing to file");
133        }
134  }
135  char *SDCard::createFilename(char *buffer,const dir_t &p)
136  {
137    char *pos = buffer,*src = (char*)p.name;
138    for (byte i = 0; i < 11; i++,src++) 
139    {   
140      if (*src == ' ') continue;
141      if (i == 8) 
142        *pos++ = '.';
143      *pos++ = *src;
144    }
145    *pos = 0;
146    return pos;
147  }
148  bool SDCard::showFilename(const uint8_t *name) {
149    if (*name == DIR_NAME_DELETED || *name == '.') return false;
150  #if !SD_ALLOW_LONG_NAMES
151    byte i=11;
152    while(i--) {
153       if(*name=='~') return false;
154       name++;
155    }
156  #endif
157    return true; 
158  }
159  void  SDCard::lsRecursive(SdBaseFile *parent,byte level)
160  {
161    dir_t *p;
162    uint8_t cnt=0;
163    char *oldpathend = pathend;
164    char filename[13];
165    parent->rewind();
166    while ((p= parent->readDirCache()))
167    {
168      if (p->name[0] == DIR_NAME_FREE) break;
169      if (!showFilename(p->name)) continue;
170      if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
171      if( DIR_IS_SUBDIR(p))
172      {
173        if(level>=SD_MAX_FOLDER_DEPTH) continue; // can't go deeper
174        if(level<SD_MAX_FOLDER_DEPTH) {
175          createFilename(filename,*p);
176          if(level) {
177            out.print(fullName);
178            out.print('/');
179          }
180          out.print(filename);
181          out.println('/'); //End with / to mark it as directory entry, so we can see empty directories.
182        }
183        char *tmp = oldpathend;
184        if(level) *tmp++ = '/';
185        char *dirname = tmp;
186        pathend = createFilename(tmp,*p);
187        SdBaseFile next;
188        uint16_t index = parent->curPosition()/32 - 1;
189        if(next.open(parent,dirname, O_READ))
190          lsRecursive(&next,level+1);
191        parent->seekSet(32 * (index + 1));
192        *oldpathend = 0;
193      } else {
194        createFilename(filename,*p);
195        if(level) {
196          out.print(fullName);
197          out.print('/');
198        }
199        out.print(filename);
200  #ifdef SD_EXTENDED_DIR
201        out.write(' ');
202        out.print(p->fileSize);
203  #endif
204        out.println();
205      }
206    }
207  }
208  void SDCard::ls() {
209    OUT_P_LN("Begin file list");
210    *fullName = 0;
211    pathend = fullName;
212    fat.chdir();
213    lsRecursive(fat.vwd(),0);
214    OUT_P_LN("End file list");
215  }
216  
217  void SDCard::selectFile(char *filename) {
218    if(!sdactive) return;
219    sdmode = false;
220    file.close();
221    fat.chdir();
222    if (file.open(fat.vwd(),filename, O_READ)) {
223      OUT_P("File opened:");
224      out.print(filename);
225      OUT_P_L_LN(" Size:",file.fileSize());
226      sdpos = 0;
227      filesize = file.fileSize();
228      OUT_P_LN("File selected");
229    } else {
230      OUT_P_LN("file.open failed");
231    }
232  }
233  void SDCard::printStatus() {
234    if(sdactive){
235      OUT_P_L("SD printing byte ",sdpos);
236      OUT_P_L_LN("/",filesize);
237    } else {
238      OUT_P_LN("Not SD printing");
239    }
240  }
241  void SDCard::startWrite(char *filename) {
242    if(!sdactive) return;
243    file.close();
244    sdmode = false;
245    fat.chdir();
246    if(!file.open(filename, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))  {
247      OUT_P("open failed, File: ");
248      out.print(filename);
249      out.print('.');
250    } else {
251      UI_STATUS(UI_TEXT_UPLOADING);
252      savetosd = true;
253      OUT_P("Writing to file: ");
254      out.println(filename);
255    }
256  }
257  void SDCard::finishWrite() {
258    if(!savetosd) return; // already closed or never opened
259    file.sync();
260    file.close();
261    savetosd = false;
262    OUT_P_LN("Done saving file.");
263    UI_CLEAR_STATUS;
264  }
265  void SDCard::deleteFile(char *filename) {
266    if(!sdactive) return;
267    sdmode = false;
268    file.close();
269    if(fat.remove(filename)) {
270      OUT_P_LN("File deleted");
271    } else {
272      if(fat.rmdir(filename))
273        OUT_P_LN("File deleted");
274      else
275        OUT_P_LN("Deletion failed");
276    }
277  }
278  void SDCard::makeDirectory(char *filename) {
279    if(!sdactive) return;
280    sdmode = false;
281    file.close();
282    if(fat.mkdir(filename)) {
283      OUT_P_LN("Directory created");    
284    } else {
285      OUT_P_LN("Creation failed");
286    }
287  }
288  #endif
289