Browse Source

updated to sdfatlib2010902

Bernhard Kubicek 13 years ago
parent
commit
64f2121ab1

+ 3
- 3
Marlin/Configuration.h View File

4
 
4
 
5
 
5
 
6
 // This determines the communication speed of the printer
6
 // This determines the communication speed of the printer
7
-#define BAUDRATE 250000
8
-//#define BAUDRATE 115200
7
+//#define BAUDRATE 250000
8
+#define BAUDRATE 115200
9
 //#define BAUDRATE 230400
9
 //#define BAUDRATE 230400
10
 
10
 
11
 
11
 
277
 
277
 
278
 #define ULTIPANEL
278
 #define ULTIPANEL
279
 #ifdef ULTIPANEL
279
 #ifdef ULTIPANEL
280
-//  #define NEWPANEL  //enable this if you have a click-encoder panel
280
+  #define NEWPANEL  //enable this if you have a click-encoder panel
281
   #define SDSUPPORT
281
   #define SDSUPPORT
282
   #define ULTRA_LCD
282
   #define ULTRA_LCD
283
   #define LCD_WIDTH 20
283
   #define LCD_WIDTH 20

+ 16
- 4
Marlin/Marlin.pde View File

26
  */
26
  */
27
 
27
 
28
 #include <EEPROM.h>
28
 #include <EEPROM.h>
29
+
29
 #include "EEPROMwrite.h"
30
 #include "EEPROMwrite.h"
30
 #include "fastio.h"
31
 #include "fastio.h"
31
 #include "Configuration.h"
32
 #include "Configuration.h"
391
   while( !card.eof()  && buflen < BUFSIZE) {
392
   while( !card.eof()  && buflen < BUFSIZE) {
392
     int16_t n=card.get();
393
     int16_t n=card.get();
393
     serial_char = (char)n;
394
     serial_char = (char)n;
395
+//     Serial.print((char)serial_char);
396
+//     Serial.print(" ");
397
+//     Serial.println((int)serial_count);
394
     if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) 
398
     if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) 
395
     {
399
     {
396
-     
400
+//       if(serial_char == '\n' || serial_char == '\r' )
401
+//         Serial.println("newline or :");
402
+//       if(serial_count >= (MAX_CMD_SIZE - 1))
403
+//         Serial.println("too long line");
397
       if(card.eof()){
404
       if(card.eof()){
398
         card.sdprinting = false;
405
         card.sdprinting = false;
399
         SERIAL_PROTOCOLLNPGM("Done printing file");
406
         SERIAL_PROTOCOLLNPGM("Done printing file");
409
         LCD_MESSAGE(time);
416
         LCD_MESSAGE(time);
410
         card.checkautostart(true);
417
         card.checkautostart(true);
411
       }
418
       }
412
-      if(!serial_count) 
413
-	return; //if empty line
419
+      if(serial_char=='\n')
420
+         comment_mode = false; //for new command
421
+      if(!serial_count)
422
+      {
423
+// 	Serial.println("empty line");
424
+        return; //if empty line
425
+      }
414
       cmdbuffer[bufindw][serial_count] = 0; //terminate string
426
       cmdbuffer[bufindw][serial_count] = 0; //terminate string
415
       if(!comment_mode){
427
       if(!comment_mode){
416
         fromsd[bufindw] = true;
428
         fromsd[bufindw] = true;
417
         buflen += 1;
429
         buflen += 1;
418
         bufindw = (bufindw + 1)%BUFSIZE;
430
         bufindw = (bufindw + 1)%BUFSIZE;
419
       }
431
       }
420
-      comment_mode = false; //for new command
432
+     
421
       serial_count = 0; //clear buffer
433
       serial_count = 0; //clear buffer
422
     }
434
     }
423
     else
435
     else

+ 217
- 218
Marlin/Sd2Card.cpp View File

17
  * along with the Arduino Sd2Card Library.  If not, see
17
  * along with the Arduino Sd2Card Library.  If not, see
18
  * <http://www.gnu.org/licenses/>.
18
  * <http://www.gnu.org/licenses/>.
19
  */
19
  */
20
+#if ARDUINO < 100
20
 #include <WProgram.h>
21
 #include <WProgram.h>
22
+#else  // ARDUINO
23
+#include <Arduino.h>
24
+#endif  // ARDUINO
21
 #include "Sd2Card.h"
25
 #include "Sd2Card.h"
22
 //------------------------------------------------------------------------------
26
 //------------------------------------------------------------------------------
23
 #ifndef SOFTWARE_SPI
27
 #ifndef SOFTWARE_SPI
24
 // functions for hardware SPI
28
 // functions for hardware SPI
25
-/** Send a byte to the card */
29
+//------------------------------------------------------------------------------
30
+// make sure SPCR rate is in expected bits
31
+#if (SPR0 != 0 || SPR1 != 1)
32
+#error unexpected SPCR bits
33
+#endif
34
+/**
35
+ * Initialize hardware SPI
36
+ * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
37
+ */
38
+static void spiInit(uint8_t spiRate) {
39
+  // See avr processor documentation
40
+  SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1);
41
+  SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X;
42
+}
43
+//------------------------------------------------------------------------------
44
+/** SPI receive a byte */
45
+static uint8_t spiRec() {
46
+  SPDR = 0XFF;
47
+  while (!(SPSR & (1 << SPIF)));
48
+  return SPDR;
49
+}
50
+//------------------------------------------------------------------------------
51
+/** SPI read data - only one call so force inline */
52
+static inline __attribute__((always_inline))
53
+  void spiRead(uint8_t* buf, uint16_t nbyte) {
54
+  if (nbyte-- == 0) return;
55
+  SPDR = 0XFF;
56
+  for (uint16_t i = 0; i < nbyte; i++) {
57
+    while (!(SPSR & (1 << SPIF)));
58
+    buf[i] = SPDR;
59
+    SPDR = 0XFF;
60
+  }
61
+  while (!(SPSR & (1 << SPIF)));
62
+  buf[nbyte] = SPDR;
63
+}
64
+//------------------------------------------------------------------------------
65
+/** SPI send a byte */
26
 static void spiSend(uint8_t b) {
66
 static void spiSend(uint8_t b) {
27
   SPDR = b;
67
   SPDR = b;
28
   while (!(SPSR & (1 << SPIF)));
68
   while (!(SPSR & (1 << SPIF)));
29
 }
69
 }
30
-/** Receive a byte from the card */
31
-static  uint8_t spiRec(void) {
32
-  spiSend(0XFF);
33
-  return SPDR;
70
+//------------------------------------------------------------------------------
71
+/** SPI send block - only one call so force inline */
72
+static inline __attribute__((always_inline))
73
+  void spiSendBlock(uint8_t token, const uint8_t* buf) {
74
+  SPDR = token;
75
+  for (uint16_t i = 0; i < 512; i += 2) {
76
+    while (!(SPSR & (1 << SPIF)));
77
+    SPDR = buf[i];
78
+    while (!(SPSR & (1 << SPIF)));
79
+    SPDR = buf[i + 1];
80
+  }
81
+  while (!(SPSR & (1 << SPIF)));
34
 }
82
 }
83
+//------------------------------------------------------------------------------
35
 #else  // SOFTWARE_SPI
84
 #else  // SOFTWARE_SPI
36
 //------------------------------------------------------------------------------
85
 //------------------------------------------------------------------------------
37
 /** nop to tune soft SPI timing */
86
 /** nop to tune soft SPI timing */
38
 #define nop asm volatile ("nop\n\t")
87
 #define nop asm volatile ("nop\n\t")
39
 //------------------------------------------------------------------------------
88
 //------------------------------------------------------------------------------
40
-/** Soft SPI receive */
41
-uint8_t spiRec(void) {
89
+/** Soft SPI receive byte */
90
+static uint8_t spiRec() {
42
   uint8_t data = 0;
91
   uint8_t data = 0;
43
   // no interrupts during byte receive - about 8 us
92
   // no interrupts during byte receive - about 8 us
44
   cli();
93
   cli();
63
   return data;
112
   return data;
64
 }
113
 }
65
 //------------------------------------------------------------------------------
114
 //------------------------------------------------------------------------------
66
-/** Soft SPI send */
67
-void spiSend(uint8_t data) {
115
+/** Soft SPI read data */
116
+static void spiRead(uint8_t* buf, uint16_t nbyte) {
117
+  for (uint16_t i = 0; i < nbyte; i++) {
118
+    buf[i] = spiRec();
119
+  }
120
+}
121
+//------------------------------------------------------------------------------
122
+/** Soft SPI send byte */
123
+static void spiSend(uint8_t data) {
68
   // no interrupts during byte send - about 8 us
124
   // no interrupts during byte send - about 8 us
69
   cli();
125
   cli();
70
   for (uint8_t i = 0; i < 8; i++) {
126
   for (uint8_t i = 0; i < 8; i++) {
86
   // enable interrupts
142
   // enable interrupts
87
   sei();
143
   sei();
88
 }
144
 }
145
+//------------------------------------------------------------------------------
146
+/** Soft SPI send block */
147
+  void spiSendBlock(uint8_t token, const uint8_t* buf) {
148
+  spiSend(token);
149
+  for (uint16_t i = 0; i < 512; i++) {
150
+    spiSend(buf[i]);
151
+  }
152
+}
89
 #endif  // SOFTWARE_SPI
153
 #endif  // SOFTWARE_SPI
90
 //------------------------------------------------------------------------------
154
 //------------------------------------------------------------------------------
91
 // send command and return error code.  Return zero for OK
155
 // send command and return error code.  Return zero for OK
92
 uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
156
 uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
93
-  // end read if in partialBlockRead mode
94
-  readEnd();
95
-
96
   // select card
157
   // select card
97
   chipSelectLow();
158
   chipSelectLow();
98
 
159
 
111
   if (cmd == CMD8) crc = 0X87;  // correct crc for CMD8 with arg 0X1AA
172
   if (cmd == CMD8) crc = 0X87;  // correct crc for CMD8 with arg 0X1AA
112
   spiSend(crc);
173
   spiSend(crc);
113
 
174
 
175
+  // skip stuff byte for stop read
176
+  if (cmd == CMD12) spiRec();
177
+
114
   // wait for response
178
   // wait for response
115
   for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
179
   for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
116
   return status_;
180
   return status_;
122
  * \return The number of 512 byte data blocks in the card
186
  * \return The number of 512 byte data blocks in the card
123
  *         or zero if an error occurs.
187
  *         or zero if an error occurs.
124
  */
188
  */
125
-uint32_t Sd2Card::cardSize(void) {
189
+uint32_t Sd2Card::cardSize() {
126
   csd_t csd;
190
   csd_t csd;
127
   if (!readCSD(&csd)) return 0;
191
   if (!readCSD(&csd)) return 0;
128
   if (csd.v1.csd_ver == 0) {
192
   if (csd.v1.csd_ver == 0) {
142
   }
206
   }
143
 }
207
 }
144
 //------------------------------------------------------------------------------
208
 //------------------------------------------------------------------------------
145
-void Sd2Card::chipSelectHigh(void) {
209
+void Sd2Card::chipSelectHigh() {
146
   digitalWrite(chipSelectPin_, HIGH);
210
   digitalWrite(chipSelectPin_, HIGH);
147
 }
211
 }
148
 //------------------------------------------------------------------------------
212
 //------------------------------------------------------------------------------
149
-void Sd2Card::chipSelectLow(void) {
213
+void Sd2Card::chipSelectLow() {
214
+#ifndef SOFTWARE_SPI
215
+  spiInit(spiRate_);
216
+#endif  // SOFTWARE_SPI
150
   digitalWrite(chipSelectPin_, LOW);
217
   digitalWrite(chipSelectPin_, LOW);
151
 }
218
 }
152
 //------------------------------------------------------------------------------
219
 //------------------------------------------------------------------------------
163
  * \return The value one, true, is returned for success and
230
  * \return The value one, true, is returned for success and
164
  * the value zero, false, is returned for failure.
231
  * the value zero, false, is returned for failure.
165
  */
232
  */
166
-uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
167
-  if (!eraseSingleBlockEnable()) {
168
-    error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
169
-    goto fail;
233
+bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
234
+  csd_t csd;
235
+  if (!readCSD(&csd)) goto fail;
236
+  // check for single block erase
237
+  if (!csd.v1.erase_blk_en) {
238
+    // erase size mask
239
+    uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
240
+    if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
241
+      // error card can't erase specified area
242
+      error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
243
+      goto fail;
244
+    }
170
   }
245
   }
171
   if (type_ != SD_CARD_TYPE_SDHC) {
246
   if (type_ != SD_CARD_TYPE_SDHC) {
172
     firstBlock <<= 9;
247
     firstBlock <<= 9;
195
  * \return The value one, true, is returned if single block erase is supported.
270
  * \return The value one, true, is returned if single block erase is supported.
196
  * The value zero, false, is returned if single block erase is not supported.
271
  * The value zero, false, is returned if single block erase is not supported.
197
  */
272
  */
198
-uint8_t Sd2Card::eraseSingleBlockEnable(void) {
273
+bool Sd2Card::eraseSingleBlockEnable() {
199
   csd_t csd;
274
   csd_t csd;
200
-  return readCSD(&csd) ? csd.v1.erase_blk_en : 0;
275
+  return readCSD(&csd) ? csd.v1.erase_blk_en : false;
201
 }
276
 }
202
 //------------------------------------------------------------------------------
277
 //------------------------------------------------------------------------------
203
 /**
278
 /**
210
  * the value zero, false, is returned for failure.  The reason for failure
285
  * the value zero, false, is returned for failure.  The reason for failure
211
  * can be determined by calling errorCode() and errorData().
286
  * can be determined by calling errorCode() and errorData().
212
  */
287
  */
213
-uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
214
-  errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
288
+bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
289
+  errorCode_ = type_ = 0;
215
   chipSelectPin_ = chipSelectPin;
290
   chipSelectPin_ = chipSelectPin;
216
   // 16-bit init start time allows over a minute
291
   // 16-bit init start time allows over a minute
217
   uint16_t t0 = (uint16_t)millis();
292
   uint16_t t0 = (uint16_t)millis();
227
 #ifndef SOFTWARE_SPI
302
 #ifndef SOFTWARE_SPI
228
   // SS must be in output mode even it is not chip select
303
   // SS must be in output mode even it is not chip select
229
   pinMode(SS_PIN, OUTPUT);
304
   pinMode(SS_PIN, OUTPUT);
230
-  // Enable SPI, Master, clock rate f_osc/128
231
-  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
232
-  // clear double speed
233
-  SPSR &= ~(1 << SPI2X);
305
+  // set SS high - may be chip select for another SPI device
306
+#if SET_SPI_SS_HIGH
307
+  digitalWrite(SS_PIN, HIGH);
308
+#endif  // SET_SPI_SS_HIGH
309
+  // set SCK rate for initialization commands
310
+  spiRate_ = SPI_SD_INIT_RATE;
311
+  spiInit(spiRate_);
234
 #endif  // SOFTWARE_SPI
312
 #endif  // SOFTWARE_SPI
235
 
313
 
236
   // must supply min of 74 clock cycles with CS high.
314
   // must supply min of 74 clock cycles with CS high.
237
   for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
315
   for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
238
 
316
 
239
-  chipSelectLow();
240
-
241
   // command to go idle in SPI mode
317
   // command to go idle in SPI mode
242
   while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
318
   while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
243
     if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
319
     if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
291
 }
367
 }
292
 //------------------------------------------------------------------------------
368
 //------------------------------------------------------------------------------
293
 /**
369
 /**
294
- * Enable or disable partial block reads.
295
- *
296
- * Enabling partial block reads improves performance by allowing a block
297
- * to be read over the SPI bus as several sub-blocks.  Errors may occur
298
- * if the time between reads is too long since the SD card may timeout.
299
- * The SPI SS line will be held low until the entire block is read or
300
- * readEnd() is called.
370
+ * Read a 512 byte block from an SD card.
301
  *
371
  *
302
- * Use this for applications like the Adafruit Wave Shield.
303
- *
304
- * \param[in] value The value TRUE (non-zero) or FALSE (zero).)
305
- */
306
-void Sd2Card::partialBlockRead(uint8_t value) {
307
-  readEnd();
308
-  partialBlockRead_ = value;
309
-}
310
-//------------------------------------------------------------------------------
311
-/**
312
- * Read a 512 byte block from an SD card device.
313
- *
314
- * \param[in] block Logical block to be read.
372
+ * \param[in] blockNumber Logical block to be read.
315
  * \param[out] dst Pointer to the location that will receive the data.
373
  * \param[out] dst Pointer to the location that will receive the data.
316
 
374
 
317
  * \return The value one, true, is returned for success and
375
  * \return The value one, true, is returned for success and
318
  * the value zero, false, is returned for failure.
376
  * the value zero, false, is returned for failure.
319
  */
377
  */
320
-uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {
321
-  return readData(block, 0, 512, dst);
378
+bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
379
+  // use address if not SDHC card
380
+  if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
381
+  if (cardCommand(CMD17, blockNumber)) {
382
+    error(SD_CARD_ERROR_CMD17);
383
+    goto fail;
384
+  }
385
+  return readData(dst, 512);
386
+
387
+ fail:
388
+  chipSelectHigh();
389
+  return false;
322
 }
390
 }
323
 //------------------------------------------------------------------------------
391
 //------------------------------------------------------------------------------
324
-/**
325
- * Read part of a 512 byte block from an SD card.
392
+/** Read one data block in a multiple block read sequence
393
+ *
394
+ * \param[in] dst Pointer to the location for the data to be read.
326
  *
395
  *
327
- * \param[in] block Logical block to be read.
328
- * \param[in] offset Number of bytes to skip at start of block
329
- * \param[out] dst Pointer to the location that will receive the data.
330
- * \param[in] count Number of bytes to read
331
  * \return The value one, true, is returned for success and
396
  * \return The value one, true, is returned for success and
332
  * the value zero, false, is returned for failure.
397
  * the value zero, false, is returned for failure.
333
  */
398
  */
334
-uint8_t Sd2Card::readData(uint32_t block,
335
-        uint16_t offset, uint16_t count, uint8_t* dst) {
336
-  uint16_t n;
337
-  if (count == 0) return true;
338
-  if ((count + offset) > 512) {
339
-    goto fail;
340
-  }
341
-  if (!inBlock_ || block != block_ || offset < offset_) {
342
-    block_ = block;
343
-    // use address if not SDHC card
344
-    if (type()!= SD_CARD_TYPE_SDHC) block <<= 9;
345
-    if (cardCommand(CMD17, block)) {
346
-      error(SD_CARD_ERROR_CMD17);
347
-      goto fail;
348
-    }
349
-    if (!waitStartBlock()) {
399
+bool Sd2Card::readData(uint8_t *dst) {
400
+  chipSelectLow();
401
+  return readData(dst, 512);
402
+}
403
+//------------------------------------------------------------------------------
404
+bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
405
+  // wait for start block token
406
+  uint16_t t0 = millis();
407
+  while ((status_ = spiRec()) == 0XFF) {
408
+    if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
409
+      error(SD_CARD_ERROR_READ_TIMEOUT);
350
       goto fail;
410
       goto fail;
351
     }
411
     }
352
-    offset_ = 0;
353
-    inBlock_ = 1;
354
-  }
355
-
356
-#ifdef OPTIMIZE_HARDWARE_SPI
357
-  // start first spi transfer
358
-  SPDR = 0XFF;
359
-
360
-  // skip data before offset
361
-  for (;offset_ < offset; offset_++) {
362
-    while (!(SPSR & (1 << SPIF)));
363
-    SPDR = 0XFF;
364
-  }
365
-  // transfer data
366
-  n = count - 1;
367
-  for (uint16_t i = 0; i < n; i++) {
368
-    while (!(SPSR & (1 << SPIF)));
369
-    dst[i] = SPDR;
370
-    SPDR = 0XFF;
371
   }
412
   }
372
-  // wait for last byte
373
-  while (!(SPSR & (1 << SPIF)));
374
-  dst[n] = SPDR;
375
-
376
-#else  // OPTIMIZE_HARDWARE_SPI
377
-
378
-  // skip data before offset
379
-  for (;offset_ < offset; offset_++) {
380
-    spiRec();
413
+  if (status_ != DATA_START_BLOCK) {
414
+    error(SD_CARD_ERROR_READ);
415
+    goto fail;
381
   }
416
   }
382
   // transfer data
417
   // transfer data
383
-  for (uint16_t i = 0; i < count; i++) {
384
-    dst[i] = spiRec();
385
-  }
386
-#endif  // OPTIMIZE_HARDWARE_SPI
418
+  spiRead(dst, count);
387
 
419
 
388
-  offset_ += count;
389
-  if (!partialBlockRead_ || offset_ >= 512) {
390
-    // read rest of data, checksum and set chip select high
391
-    readEnd();
392
-  }
420
+  // discard CRC
421
+  spiRec();
422
+  spiRec();
423
+  chipSelectHigh();
393
   return true;
424
   return true;
394
 
425
 
395
  fail:
426
  fail:
397
   return false;
428
   return false;
398
 }
429
 }
399
 //------------------------------------------------------------------------------
430
 //------------------------------------------------------------------------------
400
-/** Skip remaining data in a block when in partial block read mode. */
401
-void Sd2Card::readEnd(void) {
402
-  if (inBlock_) {
403
-      // skip data and crc
404
-#ifdef OPTIMIZE_HARDWARE_SPI
405
-    // optimize skip for hardware
406
-    SPDR = 0XFF;
407
-    while (offset_++ < 513) {
408
-      while (!(SPSR & (1 << SPIF)));
409
-      SPDR = 0XFF;
410
-    }
411
-    // wait for last crc byte
412
-    while (!(SPSR & (1 << SPIF)));
413
-#else  // OPTIMIZE_HARDWARE_SPI
414
-    while (offset_++ < 514) spiRec();
415
-#endif  // OPTIMIZE_HARDWARE_SPI
416
-    chipSelectHigh();
417
-    inBlock_ = 0;
418
-  }
419
-}
420
-//------------------------------------------------------------------------------
421
 /** read CID or CSR register */
431
 /** read CID or CSR register */
422
-uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
432
+bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
423
   uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
433
   uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
424
   if (cardCommand(cmd, 0)) {
434
   if (cardCommand(cmd, 0)) {
425
     error(SD_CARD_ERROR_READ_REG);
435
     error(SD_CARD_ERROR_READ_REG);
426
     goto fail;
436
     goto fail;
427
   }
437
   }
428
-  if (!waitStartBlock()) goto fail;
429
-  // transfer data
430
-  for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
431
-  spiRec();  // get first crc byte
432
-  spiRec();  // get second crc byte
438
+  return readData(dst, 16);
439
+
440
+ fail:
441
+  chipSelectHigh();
442
+  return false;
443
+}
444
+//------------------------------------------------------------------------------
445
+/** Start a read multiple blocks sequence.
446
+ *
447
+ * \param[in] blockNumber Address of first block in sequence.
448
+ *
449
+ * \note This function is used with readData() and readStop() for optimized
450
+ * multiple block reads.  SPI chipSelect must be low for the entire sequence.
451
+ *
452
+ * \return The value one, true, is returned for success and
453
+ * the value zero, false, is returned for failure.
454
+ */
455
+bool Sd2Card::readStart(uint32_t blockNumber) {
456
+  if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
457
+  if (cardCommand(CMD18, blockNumber)) {
458
+    error(SD_CARD_ERROR_CMD18);
459
+    goto fail;
460
+  }
461
+  chipSelectHigh();
462
+  return true;
463
+
464
+ fail:
465
+  chipSelectHigh();
466
+  return false;
467
+}
468
+//------------------------------------------------------------------------------
469
+/** End a read multiple blocks sequence.
470
+ *
471
+* \return The value one, true, is returned for success and
472
+ * the value zero, false, is returned for failure.
473
+ */
474
+bool Sd2Card::readStop() {
475
+  chipSelectLow();
476
+  if (cardCommand(CMD12, 0)) {
477
+    error(SD_CARD_ERROR_CMD12);
478
+    goto fail;
479
+  }
433
   chipSelectHigh();
480
   chipSelectHigh();
434
   return true;
481
   return true;
435
 
482
 
450
  * \return The value one, true, is returned for success and the value zero,
497
  * \return The value one, true, is returned for success and the value zero,
451
  * false, is returned for an invalid value of \a sckRateID.
498
  * false, is returned for an invalid value of \a sckRateID.
452
  */
499
  */
453
-uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
500
+bool Sd2Card::setSckRate(uint8_t sckRateID) {
454
   if (sckRateID > 6) {
501
   if (sckRateID > 6) {
455
     error(SD_CARD_ERROR_SCK_RATE);
502
     error(SD_CARD_ERROR_SCK_RATE);
456
     return false;
503
     return false;
457
   }
504
   }
458
-  // see avr processor datasheet for SPI register bit definitions
459
-  if ((sckRateID & 1) || sckRateID == 6) {
460
-    SPSR &= ~(1 << SPI2X);
461
-  } else {
462
-    SPSR |= (1 << SPI2X);
463
-  }
464
-  SPCR &= ~((1 <<SPR1) | (1 << SPR0));
465
-  SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
466
-    | (sckRateID & 2 ? (1 << SPR0) : 0);
505
+  spiRate_ = sckRateID;
467
   return true;
506
   return true;
468
 }
507
 }
469
 //------------------------------------------------------------------------------
508
 //------------------------------------------------------------------------------
470
 // wait for card to go not busy
509
 // wait for card to go not busy
471
-uint8_t Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
510
+bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
472
   uint16_t t0 = millis();
511
   uint16_t t0 = millis();
473
-  do {
474
-    if (spiRec() == 0XFF) return true;
475
-  }
476
-  while (((uint16_t)millis() - t0) < timeoutMillis);
477
-  return false;
478
-}
479
-//------------------------------------------------------------------------------
480
-/** Wait for start block token */
481
-uint8_t Sd2Card::waitStartBlock(void) {
482
-  uint16_t t0 = millis();
483
-  while ((status_ = spiRec()) == 0XFF) {
484
-    if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
485
-      error(SD_CARD_ERROR_READ_TIMEOUT);
486
-      goto fail;
487
-    }
488
-  }
489
-  if (status_ != DATA_START_BLOCK) {
490
-    error(SD_CARD_ERROR_READ);
491
-    goto fail;
512
+  while (spiRec() != 0XFF) {
513
+    if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
492
   }
514
   }
493
   return true;
515
   return true;
494
 
516
 
495
  fail:
517
  fail:
496
-  chipSelectHigh();
497
   return false;
518
   return false;
498
 }
519
 }
499
 //------------------------------------------------------------------------------
520
 //------------------------------------------------------------------------------
505
  * \return The value one, true, is returned for success and
526
  * \return The value one, true, is returned for success and
506
  * the value zero, false, is returned for failure.
527
  * the value zero, false, is returned for failure.
507
  */
528
  */
508
-uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
509
-#if SD_PROTECT_BLOCK_ZERO
510
-  // don't allow write to first block
511
-  if (blockNumber == 0) {
512
-    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
513
-    goto fail;
514
-  }
515
-#endif  // SD_PROTECT_BLOCK_ZERO
516
-
529
+bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
517
   // use address if not SDHC card
530
   // use address if not SDHC card
518
   if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
531
   if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
519
   if (cardCommand(CMD24, blockNumber)) {
532
   if (cardCommand(CMD24, blockNumber)) {
540
   return false;
553
   return false;
541
 }
554
 }
542
 //------------------------------------------------------------------------------
555
 //------------------------------------------------------------------------------
543
-/** Write one data block in a multiple block write sequence */
544
-uint8_t Sd2Card::writeData(const uint8_t* src) {
556
+/** Write one data block in a multiple block write sequence
557
+ * \param[in] src Pointer to the location of the data to be written.
558
+ * \return The value one, true, is returned for success and
559
+ * the value zero, false, is returned for failure.
560
+ */
561
+bool Sd2Card::writeData(const uint8_t* src) {
562
+  chipSelectLow();
545
   // wait for previous write to finish
563
   // wait for previous write to finish
546
-  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
547
-    error(SD_CARD_ERROR_WRITE_MULTIPLE);
548
-    chipSelectHigh();
549
-    return false;
550
-  }
551
-  return writeData(WRITE_MULTIPLE_TOKEN, src);
564
+  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
565
+  if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
566
+  chipSelectHigh();
567
+  return true;
568
+
569
+ fail:
570
+  error(SD_CARD_ERROR_WRITE_MULTIPLE);
571
+  chipSelectHigh();
572
+  return false;
552
 }
573
 }
553
 //------------------------------------------------------------------------------
574
 //------------------------------------------------------------------------------
554
 // send one block of data for write block or write multiple blocks
575
 // send one block of data for write block or write multiple blocks
555
-uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
556
-#ifdef OPTIMIZE_HARDWARE_SPI
557
-
558
-  // send data - optimized loop
559
-  SPDR = token;
560
-
561
-  // send two byte per iteration
562
-  for (uint16_t i = 0; i < 512; i += 2) {
563
-    while (!(SPSR & (1 << SPIF)));
564
-    SPDR = src[i];
565
-    while (!(SPSR & (1 << SPIF)));
566
-    SPDR = src[i+1];
567
-  }
568
-
569
-  // wait for last data byte
570
-  while (!(SPSR & (1 << SPIF)));
576
+bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
577
+  spiSendBlock(token, src);
571
 
578
 
572
-#else  // OPTIMIZE_HARDWARE_SPI
573
-  spiSend(token);
574
-  for (uint16_t i = 0; i < 512; i++) {
575
-    spiSend(src[i]);
576
-  }
577
-#endif  // OPTIMIZE_HARDWARE_SPI
578
   spiSend(0xff);  // dummy crc
579
   spiSend(0xff);  // dummy crc
579
   spiSend(0xff);  // dummy crc
580
   spiSend(0xff);  // dummy crc
580
 
581
 
581
   status_ = spiRec();
582
   status_ = spiRec();
582
   if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
583
   if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
583
     error(SD_CARD_ERROR_WRITE);
584
     error(SD_CARD_ERROR_WRITE);
584
-    chipSelectHigh();
585
-    return false;
585
+    goto fail;
586
   }
586
   }
587
   return true;
587
   return true;
588
+
589
+ fail:
590
+  chipSelectHigh();
591
+  return false;
588
 }
592
 }
589
 //------------------------------------------------------------------------------
593
 //------------------------------------------------------------------------------
590
 /** Start a write multiple blocks sequence.
594
 /** Start a write multiple blocks sequence.
598
  * \return The value one, true, is returned for success and
602
  * \return The value one, true, is returned for success and
599
  * the value zero, false, is returned for failure.
603
  * the value zero, false, is returned for failure.
600
  */
604
  */
601
-uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
602
-#if SD_PROTECT_BLOCK_ZERO
603
-  // don't allow write to first block
604
-  if (blockNumber == 0) {
605
-    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
606
-    goto fail;
607
-  }
608
-#endif  // SD_PROTECT_BLOCK_ZERO
605
+bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
609
   // send pre-erase count
606
   // send pre-erase count
610
   if (cardAcmd(ACMD23, eraseCount)) {
607
   if (cardAcmd(ACMD23, eraseCount)) {
611
     error(SD_CARD_ERROR_ACMD23);
608
     error(SD_CARD_ERROR_ACMD23);
617
     error(SD_CARD_ERROR_CMD25);
614
     error(SD_CARD_ERROR_CMD25);
618
     goto fail;
615
     goto fail;
619
   }
616
   }
617
+  chipSelectHigh();
620
   return true;
618
   return true;
621
 
619
 
622
  fail:
620
  fail:
629
 * \return The value one, true, is returned for success and
627
 * \return The value one, true, is returned for success and
630
  * the value zero, false, is returned for failure.
628
  * the value zero, false, is returned for failure.
631
  */
629
  */
632
-uint8_t Sd2Card::writeStop(void) {
630
+bool Sd2Card::writeStop() {
631
+  chipSelectLow();
633
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
632
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
634
   spiSend(STOP_TRAN_TOKEN);
633
   spiSend(STOP_TRAN_TOKEN);
635
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
634
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;

+ 127
- 126
Marlin/Sd2Card.h View File

21
 #define Sd2Card_h
21
 #define Sd2Card_h
22
 /**
22
 /**
23
  * \file
23
  * \file
24
- * Sd2Card class
24
+ * \brief Sd2Card class for V2 SD/SDHC cards
25
  */
25
  */
26
+#include "SdFatConfig.h"
26
 #include "Sd2PinMap.h"
27
 #include "Sd2PinMap.h"
27
 #include "SdInfo.h"
28
 #include "SdInfo.h"
29
+//------------------------------------------------------------------------------
30
+// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
28
 /** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */
31
 /** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */
29
 uint8_t const SPI_FULL_SPEED = 0;
32
 uint8_t const SPI_FULL_SPEED = 0;
30
 /** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */
33
 /** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */
31
 uint8_t const SPI_HALF_SPEED = 1;
34
 uint8_t const SPI_HALF_SPEED = 1;
32
-/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */
35
+/** Set SCK rate to F_CPU/8. See Sd2Card::setSckRate(). */
33
 uint8_t const SPI_QUARTER_SPEED = 2;
36
 uint8_t const SPI_QUARTER_SPEED = 2;
34
-/**
35
- * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos.
36
- * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
37
- *
38
- * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
39
- * on Mega Arduinos.  Software SPI works well with GPS Shield V1.1
40
- * but many SD cards will fail with GPS Shield V1.0.
41
- */
42
-#define MEGA_SOFT_SPI 0
43
-//------------------------------------------------------------------------------
44
-#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))
45
-#define SOFTWARE_SPI
46
-#endif  // MEGA_SOFT_SPI
47
-//------------------------------------------------------------------------------
48
-// SPI pin definitions
49
-//
50
-#ifndef SOFTWARE_SPI
51
-// hardware pin defs
52
-/**
53
- * SD Chip Select pin
54
- *
55
- * Warning if this pin is redefined the hardware SS will pin will be enabled
56
- * as an output by init().  An avr processor will not function as an SPI
57
- * master unless SS is set to output mode.
58
- */
59
-/** The default chip select pin for the SD card is SS. */
60
-uint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;
61
-// The following three pins must not be redefined for hardware SPI.
62
-/** SPI Master Out Slave In pin */
63
-uint8_t const  SPI_MOSI_PIN = MOSI_PIN;
64
-/** SPI Master In Slave Out pin */
65
-uint8_t const  SPI_MISO_PIN = MISO_PIN;
66
-/** SPI Clock pin */
67
-uint8_t const  SPI_SCK_PIN = SCK_PIN;
68
-/** optimize loops for hardware SPI */
69
-#define OPTIMIZE_HARDWARE_SPI
70
-
71
-#else  // SOFTWARE_SPI
72
-// define software SPI pins so Mega can use unmodified GPS Shield
73
-/** SPI chip select pin */
74
-uint8_t const SD_CHIP_SELECT_PIN = 10;
75
-/** SPI Master Out Slave In pin */
76
-uint8_t const SPI_MOSI_PIN = 11;
77
-/** SPI Master In Slave Out pin */
78
-uint8_t const SPI_MISO_PIN = 12;
79
-/** SPI Clock pin */
80
-uint8_t const SPI_SCK_PIN = 13;
81
-#endif  // SOFTWARE_SPI
37
+/** Set SCK rate to F_CPU/16. See Sd2Card::setSckRate(). */
38
+uint8_t const SPI_EIGHTH_SPEED = 3;
39
+/** Set SCK rate to F_CPU/32. See Sd2Card::setSckRate(). */
40
+uint8_t const SPI_SIXTEENTH_SPEED = 4;
82
 //------------------------------------------------------------------------------
41
 //------------------------------------------------------------------------------
83
-/** Protect block zero from write if nonzero */
84
-#define SD_PROTECT_BLOCK_ZERO 1
85
 /** init timeout ms */
42
 /** init timeout ms */
86
 uint16_t const SD_INIT_TIMEOUT = 2000;
43
 uint16_t const SD_INIT_TIMEOUT = 2000;
87
 /** erase timeout ms */
44
 /** erase timeout ms */
92
 uint16_t const SD_WRITE_TIMEOUT = 600;
49
 uint16_t const SD_WRITE_TIMEOUT = 600;
93
 //------------------------------------------------------------------------------
50
 //------------------------------------------------------------------------------
94
 // SD card errors
51
 // SD card errors
95
-/** timeout error for command CMD0 */
52
+/** timeout error for command CMD0 (initialize card in SPI mode) */
96
 uint8_t const SD_CARD_ERROR_CMD0 = 0X1;
53
 uint8_t const SD_CARD_ERROR_CMD0 = 0X1;
97
 /** CMD8 was not accepted - not a valid SD card*/
54
 /** CMD8 was not accepted - not a valid SD card*/
98
 uint8_t const SD_CARD_ERROR_CMD8 = 0X2;
55
 uint8_t const SD_CARD_ERROR_CMD8 = 0X2;
56
+/** card returned an error response for CMD12 (write stop) */
57
+uint8_t const SD_CARD_ERROR_CMD12 = 0X3;
99
 /** card returned an error response for CMD17 (read block) */
58
 /** card returned an error response for CMD17 (read block) */
100
-uint8_t const SD_CARD_ERROR_CMD17 = 0X3;
59
+uint8_t const SD_CARD_ERROR_CMD17 = 0X4;
60
+/** card returned an error response for CMD18 (read multiple block) */
61
+uint8_t const SD_CARD_ERROR_CMD18 = 0X5;
101
 /** card returned an error response for CMD24 (write block) */
62
 /** card returned an error response for CMD24 (write block) */
102
-uint8_t const SD_CARD_ERROR_CMD24 = 0X4;
63
+uint8_t const SD_CARD_ERROR_CMD24 = 0X6;
103
 /**  WRITE_MULTIPLE_BLOCKS command failed */
64
 /**  WRITE_MULTIPLE_BLOCKS command failed */
104
-uint8_t const SD_CARD_ERROR_CMD25 = 0X05;
65
+uint8_t const SD_CARD_ERROR_CMD25 = 0X7;
105
 /** card returned an error response for CMD58 (read OCR) */
66
 /** card returned an error response for CMD58 (read OCR) */
106
-uint8_t const SD_CARD_ERROR_CMD58 = 0X06;
67
+uint8_t const SD_CARD_ERROR_CMD58 = 0X8;
107
 /** SET_WR_BLK_ERASE_COUNT failed */
68
 /** SET_WR_BLK_ERASE_COUNT failed */
108
-uint8_t const SD_CARD_ERROR_ACMD23 = 0X07;
109
-/** card's ACMD41 initialization process timeout */
110
-uint8_t const SD_CARD_ERROR_ACMD41 = 0X08;
69
+uint8_t const SD_CARD_ERROR_ACMD23 = 0X9;
70
+/** ACMD41 initialization process timeout */
71
+uint8_t const SD_CARD_ERROR_ACMD41 = 0XA;
111
 /** card returned a bad CSR version field */
72
 /** card returned a bad CSR version field */
112
-uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09;
73
+uint8_t const SD_CARD_ERROR_BAD_CSD = 0XB;
113
 /** erase block group command failed */
74
 /** erase block group command failed */
114
-uint8_t const SD_CARD_ERROR_ERASE = 0X0A;
75
+uint8_t const SD_CARD_ERROR_ERASE = 0XC;
115
 /** card not capable of single block erase */
76
 /** card not capable of single block erase */
116
-uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B;
77
+uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD;
117
 /** Erase sequence timed out */
78
 /** Erase sequence timed out */
118
-uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C;
79
+uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE;
119
 /** card returned an error token instead of read data */
80
 /** card returned an error token instead of read data */
120
-uint8_t const SD_CARD_ERROR_READ = 0X0D;
81
+uint8_t const SD_CARD_ERROR_READ = 0XF;
121
 /** read CID or CSD failed */
82
 /** read CID or CSD failed */
122
-uint8_t const SD_CARD_ERROR_READ_REG = 0X0E;
83
+uint8_t const SD_CARD_ERROR_READ_REG = 0X10;
123
 /** timeout while waiting for start of read data */
84
 /** timeout while waiting for start of read data */
124
-uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F;
85
+uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X11;
125
 /** card did not accept STOP_TRAN_TOKEN */
86
 /** card did not accept STOP_TRAN_TOKEN */
126
-uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10;
87
+uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X12;
127
 /** card returned an error token as a response to a write operation */
88
 /** card returned an error token as a response to a write operation */
128
-uint8_t const SD_CARD_ERROR_WRITE = 0X11;
89
+uint8_t const SD_CARD_ERROR_WRITE = 0X13;
129
 /** attempt to write protected block zero */
90
 /** attempt to write protected block zero */
130
-uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12;
91
+uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14;  // REMOVE - not used
131
 /** card did not go ready for a multiple block write */
92
 /** card did not go ready for a multiple block write */
132
-uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13;
93
+uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15;
133
 /** card returned an error to a CMD13 status check after a write */
94
 /** card returned an error to a CMD13 status check after a write */
134
-uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14;
95
+uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
135
 /** timeout occurred during write programming */
96
 /** timeout occurred during write programming */
136
-uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15;
97
+uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X17;
137
 /** incorrect rate selected */
98
 /** incorrect rate selected */
138
-uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16;
99
+uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18;
100
+/** init() not called */
101
+uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19;
139
 //------------------------------------------------------------------------------
102
 //------------------------------------------------------------------------------
140
 // card types
103
 // card types
141
 /** Standard capacity V1 SD card */
104
 /** Standard capacity V1 SD card */
142
-uint8_t const SD_CARD_TYPE_SD1 = 1;
105
+uint8_t const SD_CARD_TYPE_SD1  = 1;
143
 /** Standard capacity V2 SD card */
106
 /** Standard capacity V2 SD card */
144
-uint8_t const SD_CARD_TYPE_SD2 = 2;
107
+uint8_t const SD_CARD_TYPE_SD2  = 2;
145
 /** High Capacity SD card */
108
 /** High Capacity SD card */
146
 uint8_t const SD_CARD_TYPE_SDHC = 3;
109
 uint8_t const SD_CARD_TYPE_SDHC = 3;
110
+/**
111
+ * define SOFTWARE_SPI to use bit-bang SPI
112
+ */
113
+//------------------------------------------------------------------------------
114
+#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))
115
+#define SOFTWARE_SPI
116
+#elif USE_SOFTWARE_SPI
117
+#define SOFTWARE_SPI
118
+#endif  // MEGA_SOFT_SPI
119
+//------------------------------------------------------------------------------
120
+// SPI pin definitions - do not edit here - change in SdFatConfig.h
121
+//
122
+#ifndef SOFTWARE_SPI
123
+// hardware pin defs
124
+/** The default chip select pin for the SD card is SS. */
125
+uint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;
126
+// The following three pins must not be redefined for hardware SPI.
127
+/** SPI Master Out Slave In pin */
128
+uint8_t const  SPI_MOSI_PIN = MOSI_PIN;
129
+/** SPI Master In Slave Out pin */
130
+uint8_t const  SPI_MISO_PIN = MISO_PIN;
131
+/** SPI Clock pin */
132
+uint8_t const  SPI_SCK_PIN = SCK_PIN;
133
+
134
+#else  // SOFTWARE_SPI
135
+
136
+/** SPI chip select pin */
137
+uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
138
+/** SPI Master Out Slave In pin */
139
+uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
140
+/** SPI Master In Slave Out pin */
141
+uint8_t const SPI_MISO_PIN = SOFT_SPI_MISO_PIN;
142
+/** SPI Clock pin */
143
+uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN;
144
+#endif  // SOFTWARE_SPI
147
 //------------------------------------------------------------------------------
145
 //------------------------------------------------------------------------------
148
 /**
146
 /**
149
  * \class Sd2Card
147
  * \class Sd2Card
152
 class Sd2Card {
150
 class Sd2Card {
153
  public:
151
  public:
154
   /** Construct an instance of Sd2Card. */
152
   /** Construct an instance of Sd2Card. */
155
-  Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {}
156
-  uint32_t cardSize(void);
157
-  uint8_t erase(uint32_t firstBlock, uint32_t lastBlock);
158
-  uint8_t eraseSingleBlockEnable(void);
153
+  Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {}
154
+  uint32_t cardSize();
155
+  bool erase(uint32_t firstBlock, uint32_t lastBlock);
156
+  bool eraseSingleBlockEnable();
157
+  /**
158
+   *  Set SD error code.
159
+   *  \param[in] code value for error code.
160
+   */
161
+  void error(uint8_t code) {errorCode_ = code;}
159
   /**
162
   /**
160
    * \return error code for last error. See Sd2Card.h for a list of error codes.
163
    * \return error code for last error. See Sd2Card.h for a list of error codes.
161
    */
164
    */
162
-  uint8_t errorCode(void) const {return errorCode_;}
165
+  int errorCode() const {return errorCode_;}
163
   /** \return error data for last error. */
166
   /** \return error data for last error. */
164
-  uint8_t errorData(void) const {return status_;}
167
+  int errorData() const {return status_;}
165
   /**
168
   /**
166
    * Initialize an SD flash memory card with default clock rate and chip
169
    * Initialize an SD flash memory card with default clock rate and chip
167
    * select pin.  See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
170
    * select pin.  See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
171
+   *
172
+   * \return true for success or false for failure.
168
    */
173
    */
169
-  uint8_t init(void) {
170
-    return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN);
171
-  }
174
+  bool init(uint8_t sckRateID = SPI_FULL_SPEED,
175
+    uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
176
+  bool readBlock(uint32_t block, uint8_t* dst);
172
   /**
177
   /**
173
-   * Initialize an SD flash memory card with the selected SPI clock rate
174
-   * and the default SD chip select pin.
175
-   * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
176
-   */
177
-  uint8_t init(uint8_t sckRateID) {
178
-    return init(sckRateID, SD_CHIP_SELECT_PIN);
179
-  }
180
-  uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin);
181
-  void partialBlockRead(uint8_t value);
182
-  /** Returns the current value, true or false, for partial block read. */
183
-  uint8_t partialBlockRead(void) const {return partialBlockRead_;}
184
-  uint8_t readBlock(uint32_t block, uint8_t* dst);
185
-  uint8_t readData(uint32_t block,
186
-          uint16_t offset, uint16_t count, uint8_t* dst);
187
-  /**
188
-   * Read a cards CID register. The CID contains card identification
178
+   * Read a card's CID register. The CID contains card identification
189
    * information such as Manufacturer ID, Product name, Product serial
179
    * information such as Manufacturer ID, Product name, Product serial
190
-   * number and Manufacturing date. */
191
-  uint8_t readCID(cid_t* cid) {
180
+   * number and Manufacturing date. 
181
+   *
182
+   * \param[out] cid pointer to area for returned data.
183
+   *
184
+   * \return true for success or false for failure.
185
+   */
186
+  bool readCID(cid_t* cid) {
192
     return readRegister(CMD10, cid);
187
     return readRegister(CMD10, cid);
193
   }
188
   }
194
   /**
189
   /**
195
-   * Read a cards CSD register. The CSD contains Card-Specific Data that
196
-   * provides information regarding access to the card's contents. */
197
-  uint8_t readCSD(csd_t* csd) {
190
+   * Read a card's CSD register. The CSD contains Card-Specific Data that
191
+   * provides information regarding access to the card's contents.
192
+   *
193
+   * \param[out] csd pointer to area for returned data.
194
+   *
195
+   * \return true for success or false for failure.
196
+   */
197
+  bool readCSD(csd_t* csd) {
198
     return readRegister(CMD9, csd);
198
     return readRegister(CMD9, csd);
199
   }
199
   }
200
-  void readEnd(void);
201
-  uint8_t setSckRate(uint8_t sckRateID);
202
-  /** Return the card type: SD V1, SD V2 or SDHC */
203
-  uint8_t type(void) const {return type_;}
204
-  uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src);
205
-  uint8_t writeData(const uint8_t* src);
206
-  uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount);
207
-  uint8_t writeStop(void);
200
+  bool readData(uint8_t *dst);
201
+  bool readStart(uint32_t blockNumber);
202
+  bool readStop();
203
+  bool setSckRate(uint8_t sckRateID);
204
+  /** Return the card type: SD V1, SD V2 or SDHC
205
+   * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
206
+   */
207
+  int type() const {return type_;}
208
+  bool writeBlock(uint32_t blockNumber, const uint8_t* src);
209
+  bool writeData(const uint8_t* src);
210
+  bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
211
+  bool writeStop();
208
  private:
212
  private:
209
-  uint32_t block_;
213
+  //----------------------------------------------------------------------------
210
   uint8_t chipSelectPin_;
214
   uint8_t chipSelectPin_;
211
   uint8_t errorCode_;
215
   uint8_t errorCode_;
212
-  uint8_t inBlock_;
213
-  uint16_t offset_;
214
-  uint8_t partialBlockRead_;
216
+  uint8_t spiRate_;
215
   uint8_t status_;
217
   uint8_t status_;
216
   uint8_t type_;
218
   uint8_t type_;
217
   // private functions
219
   // private functions
220
     return cardCommand(cmd, arg);
222
     return cardCommand(cmd, arg);
221
   }
223
   }
222
   uint8_t cardCommand(uint8_t cmd, uint32_t arg);
224
   uint8_t cardCommand(uint8_t cmd, uint32_t arg);
223
-  void error(uint8_t code) {errorCode_ = code;}
224
-  uint8_t readRegister(uint8_t cmd, void* buf);
225
-  uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount);
226
-  void chipSelectHigh(void);
227
-  void chipSelectLow(void);
225
+
226
+  bool readData(uint8_t* dst, uint16_t count);
227
+  bool readRegister(uint8_t cmd, void* buf);
228
+  void chipSelectHigh();
229
+  void chipSelectLow();
228
   void type(uint8_t value) {type_ = value;}
230
   void type(uint8_t value) {type_ = value;}
229
-  uint8_t waitNotBusy(uint16_t timeoutMillis);
230
-  uint8_t writeData(uint8_t token, const uint8_t* src);
231
-  uint8_t waitStartBlock(void);
231
+  bool waitNotBusy(uint16_t timeoutMillis);
232
+  bool writeData(uint8_t token, const uint8_t* src);
232
 };
233
 };
233
 #endif  // Sd2Card_h
234
 #endif  // Sd2Card_h

+ 45
- 38
Marlin/Sd2PinMap.h View File

21
 #ifndef Sd2PinMap_h
21
 #ifndef Sd2PinMap_h
22
 #define Sd2PinMap_h
22
 #define Sd2PinMap_h
23
 #include <avr/io.h>
23
 #include <avr/io.h>
24
-
25
 //------------------------------------------------------------------------------
24
 //------------------------------------------------------------------------------
26
 /** struct for mapping digital pins */
25
 /** struct for mapping digital pins */
27
 struct pin_map_t {
26
 struct pin_map_t {
31
   uint8_t bit;
30
   uint8_t bit;
32
 };
31
 };
33
 //------------------------------------------------------------------------------
32
 //------------------------------------------------------------------------------
34
-#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
33
+#if defined(__AVR_ATmega1280__)\
34
+|| defined(__AVR_ATmega2560__)
35
 // Mega
35
 // Mega
36
 
36
 
37
 // Two Wire (aka I2C) ports
37
 // Two Wire (aka I2C) ports
38
-uint8_t const SDA_PIN = 20;
39
-uint8_t const SCL_PIN = 21;
38
+uint8_t const SDA_PIN = 20;  // D1
39
+uint8_t const SCL_PIN = 21;  // D0
40
 
40
 
41
 // SPI port
41
 // SPI port
42
-uint8_t const SS_PIN = 53;
43
-uint8_t const MOSI_PIN = 51;
44
-uint8_t const MISO_PIN = 50;
45
-uint8_t const SCK_PIN = 52;
42
+uint8_t const SS_PIN = 53;    // B0
43
+uint8_t const MOSI_PIN = 51;  // B2
44
+uint8_t const MISO_PIN = 50;  // B3
45
+uint8_t const SCK_PIN = 52;   // B1
46
 
46
 
47
 static const pin_map_t digitalPinMap[] = {
47
 static const pin_map_t digitalPinMap[] = {
48
   {&DDRE, &PINE, &PORTE, 0},  // E0  0
48
   {&DDRE, &PINE, &PORTE, 0},  // E0  0
117
   {&DDRK, &PINK, &PORTK, 7}   // K7 69
117
   {&DDRK, &PINK, &PORTK, 7}   // K7 69
118
 };
118
 };
119
 //------------------------------------------------------------------------------
119
 //------------------------------------------------------------------------------
120
-#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
120
+#elif defined(__AVR_ATmega644P__)\
121
+|| defined(__AVR_ATmega644__)\
122
+|| defined(__AVR_ATmega1284P__)
121
 // Sanguino
123
 // Sanguino
122
 
124
 
123
 // Two Wire (aka I2C) ports
125
 // Two Wire (aka I2C) ports
124
-uint8_t const SDA_PIN = 17;
125
-uint8_t const SCL_PIN = 18;
126
+uint8_t const SDA_PIN = 17;  // C1
127
+uint8_t const SCL_PIN = 18;  // C2
126
 
128
 
127
 // SPI port
129
 // SPI port
128
-uint8_t const SS_PIN = 4;
129
-uint8_t const MOSI_PIN = 5;
130
-uint8_t const MISO_PIN = 6;
131
-uint8_t const SCK_PIN = 7;
130
+uint8_t const SS_PIN = 4;    // B4
131
+uint8_t const MOSI_PIN = 5;  // B5
132
+uint8_t const MISO_PIN = 6;  // B6
133
+uint8_t const SCK_PIN = 7;   // B7
132
 
134
 
133
 static const pin_map_t digitalPinMap[] = {
135
 static const pin_map_t digitalPinMap[] = {
134
   {&DDRB, &PINB, &PORTB, 0},  // B0  0
136
   {&DDRB, &PINB, &PORTB, 0},  // B0  0
169
 // Teensy 2.0
171
 // Teensy 2.0
170
 
172
 
171
 // Two Wire (aka I2C) ports
173
 // Two Wire (aka I2C) ports
172
-uint8_t const SDA_PIN = 6;
173
-uint8_t const SCL_PIN = 5;
174
+uint8_t const SDA_PIN = 6;  // D1
175
+uint8_t const SCL_PIN = 5;  // D0
174
 
176
 
175
 // SPI port
177
 // SPI port
176
-uint8_t const SS_PIN = 0;
177
-uint8_t const MOSI_PIN = 2;
178
-uint8_t const MISO_PIN = 3;
179
-uint8_t const SCK_PIN = 1;
178
+uint8_t const SS_PIN = 0;    // B0
179
+uint8_t const MOSI_PIN = 2;  // B2
180
+uint8_t const MISO_PIN = 3;  // B3
181
+uint8_t const SCK_PIN = 1;   // B1
180
 
182
 
181
 static const pin_map_t digitalPinMap[] = {
183
 static const pin_map_t digitalPinMap[] = {
182
   {&DDRB, &PINB, &PORTB, 0},  // B0  0
184
   {&DDRB, &PINB, &PORTB, 0},  // B0  0
206
   {&DDRE, &PINE, &PORTE, 6}   // E6 24
208
   {&DDRE, &PINE, &PORTE, 6}   // E6 24
207
 };
209
 };
208
 //------------------------------------------------------------------------------
210
 //------------------------------------------------------------------------------
209
-#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
211
+#elif defined(__AVR_AT90USB646__)\
212
+|| defined(__AVR_AT90USB1286__)
210
 // Teensy++ 1.0 & 2.0
213
 // Teensy++ 1.0 & 2.0
211
 
214
 
212
 // Two Wire (aka I2C) ports
215
 // Two Wire (aka I2C) ports
213
-uint8_t const SDA_PIN = 1;
214
-uint8_t const SCL_PIN = 0;
216
+uint8_t const SDA_PIN = 1;  // D1
217
+uint8_t const SCL_PIN = 0;  // D0
215
 
218
 
216
 // SPI port
219
 // SPI port
217
-uint8_t const SS_PIN = 20;
218
-uint8_t const MOSI_PIN = 22;
219
-uint8_t const MISO_PIN = 23;
220
-uint8_t const SCK_PIN = 21;
220
+uint8_t const SS_PIN = 20;    // B0
221
+uint8_t const MOSI_PIN = 22;  // B2
222
+uint8_t const MISO_PIN = 23;  // B3
223
+uint8_t const SCK_PIN = 21;   // B1
221
 
224
 
222
 static const pin_map_t digitalPinMap[] = {
225
 static const pin_map_t digitalPinMap[] = {
223
   {&DDRD, &PIND, &PORTD, 0},  // D0  0
226
   {&DDRD, &PIND, &PORTD, 0},  // D0  0
268
   {&DDRF, &PINF, &PORTF, 7}   // F7 45
271
   {&DDRF, &PINF, &PORTF, 7}   // F7 45
269
 };
272
 };
270
 //------------------------------------------------------------------------------
273
 //------------------------------------------------------------------------------
271
-#else  // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
274
+#elif defined(__AVR_ATmega168__)\
275
+||defined(__AVR_ATmega168P__)\
276
+||defined(__AVR_ATmega328P__)
272
 // 168 and 328 Arduinos
277
 // 168 and 328 Arduinos
273
 
278
 
274
 // Two Wire (aka I2C) ports
279
 // Two Wire (aka I2C) ports
275
-uint8_t const SDA_PIN = 18;
276
-uint8_t const SCL_PIN = 19;
280
+uint8_t const SDA_PIN = 18;  // C4
281
+uint8_t const SCL_PIN = 19;  // C5
277
 
282
 
278
 // SPI port
283
 // SPI port
279
-uint8_t const SS_PIN = 10;
280
-uint8_t const MOSI_PIN = 11;
281
-uint8_t const MISO_PIN = 12;
282
-uint8_t const SCK_PIN = 13;
284
+uint8_t const SS_PIN = 10;    // B2
285
+uint8_t const MOSI_PIN = 11;  // B3
286
+uint8_t const MISO_PIN = 12;  // B4
287
+uint8_t const SCK_PIN = 13;   // B5
283
 
288
 
284
 static const pin_map_t digitalPinMap[] = {
289
 static const pin_map_t digitalPinMap[] = {
285
   {&DDRD, &PIND, &PORTD, 0},  // D0  0
290
   {&DDRD, &PIND, &PORTD, 0},  // D0  0
303
   {&DDRC, &PINC, &PORTC, 4},  // C4 18
308
   {&DDRC, &PINC, &PORTC, 4},  // C4 18
304
   {&DDRC, &PINC, &PORTC, 5}   // C5 19
309
   {&DDRC, &PINC, &PORTC, 5}   // C5 19
305
 };
310
 };
306
-#endif  // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
311
+#else  // defined(__AVR_ATmega1280__)
312
+#error unknown chip
313
+#endif  // defined(__AVR_ATmega1280__)
307
 //------------------------------------------------------------------------------
314
 //------------------------------------------------------------------------------
308
 static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
315
 static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
309
 
316
 
311
   __attribute__((error("Pin number is too large or not a constant")));
318
   __attribute__((error("Pin number is too large or not a constant")));
312
 
319
 
313
 static inline __attribute__((always_inline))
320
 static inline __attribute__((always_inline))
314
-  uint8_t getPinMode(uint8_t pin) {
321
+  bool getPinMode(uint8_t pin) {
315
   if (__builtin_constant_p(pin) && pin < digitalPinCount) {
322
   if (__builtin_constant_p(pin) && pin < digitalPinCount) {
316
     return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
323
     return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
317
   } else {
324
   } else {
331
   }
338
   }
332
 }
339
 }
333
 static inline __attribute__((always_inline))
340
 static inline __attribute__((always_inline))
334
-  uint8_t fastDigitalRead(uint8_t pin) {
341
+  bool fastDigitalRead(uint8_t pin) {
335
   if (__builtin_constant_p(pin) && pin < digitalPinCount) {
342
   if (__builtin_constant_p(pin) && pin < digitalPinCount) {
336
     return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
343
     return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
337
   } else {
344
   } else {

+ 1818
- 0
Marlin/SdBaseFile.cpp
File diff suppressed because it is too large
View File


+ 489
- 0
Marlin/SdBaseFile.h View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2009 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+#ifndef SdBaseFile_h
21
+#define SdBaseFile_h
22
+/**
23
+ * \file
24
+ * \brief SdBaseFile class
25
+ */
26
+#include <avr/pgmspace.h>
27
+#if ARDUINO < 100
28
+#include <WProgram.h>
29
+#else  // ARDUINO
30
+#include <Arduino.h>
31
+#endif  // ARDUINO
32
+#include "SdFatConfig.h"
33
+#include "SdVolume.h"
34
+//------------------------------------------------------------------------------
35
+/**
36
+ * \struct fpos_t
37
+ * \brief internal type for istream
38
+ * do not use in user apps
39
+ */
40
+struct fpos_t {
41
+  /** stream position */
42
+  uint32_t position;
43
+  /** cluster for position */
44
+  uint32_t cluster;
45
+  fpos_t() : position(0), cluster(0) {}
46
+};
47
+
48
+// use the gnu style oflag in open()
49
+/** open() oflag for reading */
50
+uint8_t const O_READ = 0X01;
51
+/** open() oflag - same as O_IN */
52
+uint8_t const O_RDONLY = O_READ;
53
+/** open() oflag for write */
54
+uint8_t const O_WRITE = 0X02;
55
+/** open() oflag - same as O_WRITE */
56
+uint8_t const O_WRONLY = O_WRITE;
57
+/** open() oflag for reading and writing */
58
+uint8_t const O_RDWR = (O_READ | O_WRITE);
59
+/** open() oflag mask for access modes */
60
+uint8_t const O_ACCMODE = (O_READ | O_WRITE);
61
+/** The file offset shall be set to the end of the file prior to each write. */
62
+uint8_t const O_APPEND = 0X04;
63
+/** synchronous writes - call sync() after each write */
64
+uint8_t const O_SYNC = 0X08;
65
+/** truncate the file to zero length */
66
+uint8_t const O_TRUNC = 0X10;
67
+/** set the initial position at the end of the file */
68
+uint8_t const O_AT_END = 0X20;
69
+/** create the file if nonexistent */
70
+uint8_t const O_CREAT = 0X40;
71
+/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
72
+uint8_t const O_EXCL = 0X80;
73
+
74
+// SdBaseFile class static and const definitions
75
+// flags for ls()
76
+/** ls() flag to print modify date */
77
+uint8_t const LS_DATE = 1;
78
+/** ls() flag to print file size */
79
+uint8_t const LS_SIZE = 2;
80
+/** ls() flag for recursive list of subdirectories */
81
+uint8_t const LS_R = 4;
82
+
83
+
84
+// flags for timestamp
85
+/** set the file's last access date */
86
+uint8_t const T_ACCESS = 1;
87
+/** set the file's creation date and time */
88
+uint8_t const T_CREATE = 2;
89
+/** Set the file's write date and time */
90
+uint8_t const T_WRITE = 4;
91
+// values for type_
92
+/** This file has not been opened. */
93
+uint8_t const FAT_FILE_TYPE_CLOSED = 0;
94
+/** A normal file */
95
+uint8_t const FAT_FILE_TYPE_NORMAL = 1;
96
+/** A FAT12 or FAT16 root directory */
97
+uint8_t const FAT_FILE_TYPE_ROOT_FIXED = 2;
98
+/** A FAT32 root directory */
99
+uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
100
+/** A subdirectory file*/
101
+uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
102
+/** Test value for directory type */
103
+uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;
104
+
105
+/** date field for FAT directory entry
106
+ * \param[in] year [1980,2107]
107
+ * \param[in] month [1,12]
108
+ * \param[in] day [1,31]
109
+ *
110
+ * \return Packed date for dir_t entry.
111
+ */
112
+static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
113
+  return (year - 1980) << 9 | month << 5 | day;
114
+}
115
+/** year part of FAT directory date field
116
+ * \param[in] fatDate Date in packed dir format.
117
+ *
118
+ * \return Extracted year [1980,2107]
119
+ */
120
+static inline uint16_t FAT_YEAR(uint16_t fatDate) {
121
+  return 1980 + (fatDate >> 9);
122
+}
123
+/** month part of FAT directory date field
124
+ * \param[in] fatDate Date in packed dir format.
125
+ *
126
+ * \return Extracted month [1,12]
127
+ */
128
+static inline uint8_t FAT_MONTH(uint16_t fatDate) {
129
+  return (fatDate >> 5) & 0XF;
130
+}
131
+/** day part of FAT directory date field
132
+ * \param[in] fatDate Date in packed dir format.
133
+ *
134
+ * \return Extracted day [1,31]
135
+ */
136
+static inline uint8_t FAT_DAY(uint16_t fatDate) {
137
+  return fatDate & 0X1F;
138
+}
139
+/** time field for FAT directory entry
140
+ * \param[in] hour [0,23]
141
+ * \param[in] minute [0,59]
142
+ * \param[in] second [0,59]
143
+ *
144
+ * \return Packed time for dir_t entry.
145
+ */
146
+static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
147
+  return hour << 11 | minute << 5 | second >> 1;
148
+}
149
+/** hour part of FAT directory time field
150
+ * \param[in] fatTime Time in packed dir format.
151
+ *
152
+ * \return Extracted hour [0,23]
153
+ */
154
+static inline uint8_t FAT_HOUR(uint16_t fatTime) {
155
+  return fatTime >> 11;
156
+}
157
+/** minute part of FAT directory time field
158
+ * \param[in] fatTime Time in packed dir format.
159
+ *
160
+ * \return Extracted minute [0,59]
161
+ */
162
+static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
163
+  return(fatTime >> 5) & 0X3F;
164
+}
165
+/** second part of FAT directory time field
166
+ * Note second/2 is stored in packed time.
167
+ *
168
+ * \param[in] fatTime Time in packed dir format.
169
+ *
170
+ * \return Extracted second [0,58]
171
+ */
172
+static inline uint8_t FAT_SECOND(uint16_t fatTime) {
173
+  return 2*(fatTime & 0X1F);
174
+}
175
+/** Default date for file timestamps is 1 Jan 2000 */
176
+uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
177
+/** Default time for file timestamp is 1 am */
178
+uint16_t const FAT_DEFAULT_TIME = (1 << 11);
179
+//------------------------------------------------------------------------------
180
+/**
181
+ * \class SdBaseFile
182
+ * \brief Base class for SdFile with Print and C++ streams.
183
+ */
184
+class SdBaseFile {
185
+ public:
186
+  /** Create an instance. */
187
+  SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
188
+  SdBaseFile(const char* path, uint8_t oflag);
189
+  ~SdBaseFile() {if(isOpen()) close();}
190
+  /**
191
+   * writeError is set to true if an error occurs during a write().
192
+   * Set writeError to false before calling print() and/or write() and check
193
+   * for true after calls to print() and/or write().
194
+   */
195
+  bool writeError;
196
+  //----------------------------------------------------------------------------
197
+  // helpers for stream classes
198
+  /** get position for streams
199
+   * \param[out] pos struct to receive position
200
+   */
201
+  void getpos(fpos_t* pos);
202
+  /** set position for streams
203
+   * \param[out] pos struct with value for new position
204
+   */
205
+  void setpos(fpos_t* pos);
206
+  //----------------------------------------------------------------------------
207
+  bool close();
208
+  bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
209
+  bool createContiguous(SdBaseFile* dirFile,
210
+          const char* path, uint32_t size);
211
+  /** \return The current cluster number for a file or directory. */
212
+  uint32_t curCluster() const {return curCluster_;}
213
+  /** \return The current position for a file or directory. */
214
+  uint32_t curPosition() const {return curPosition_;}
215
+  /** \return Current working directory */
216
+  static SdBaseFile* cwd() {return cwd_;}
217
+  /** Set the date/time callback function
218
+   *
219
+   * \param[in] dateTime The user's call back function.  The callback
220
+   * function is of the form:
221
+   *
222
+   * \code
223
+   * void dateTime(uint16_t* date, uint16_t* time) {
224
+   *   uint16_t year;
225
+   *   uint8_t month, day, hour, minute, second;
226
+   *
227
+   *   // User gets date and time from GPS or real-time clock here
228
+   *
229
+   *   // return date using FAT_DATE macro to format fields
230
+   *   *date = FAT_DATE(year, month, day);
231
+   *
232
+   *   // return time using FAT_TIME macro to format fields
233
+   *   *time = FAT_TIME(hour, minute, second);
234
+   * }
235
+   * \endcode
236
+   *
237
+   * Sets the function that is called when a file is created or when
238
+   * a file's directory entry is modified by sync(). All timestamps,
239
+   * access, creation, and modify, are set when a file is created.
240
+   * sync() maintains the last access date and last modify date/time.
241
+   *
242
+   * See the timestamp() function.
243
+   */
244
+  static void dateTimeCallback(
245
+    void (*dateTime)(uint16_t* date, uint16_t* time)) {
246
+    dateTime_ = dateTime;
247
+  }
248
+  /**  Cancel the date/time callback function. */
249
+  static void dateTimeCallbackCancel() {dateTime_ = 0;}
250
+  bool dirEntry(dir_t* dir);
251
+  static void dirName(const dir_t& dir, char* name);
252
+  bool exists(const char* name);
253
+  int16_t fgets(char* str, int16_t num, char* delim = 0);
254
+  /** \return The total number of bytes in a file or directory. */
255
+  uint32_t fileSize() const {return fileSize_;}
256
+  /** \return The first cluster number for a file or directory. */
257
+  uint32_t firstCluster() const {return firstCluster_;}
258
+  bool getFilename(char* name);
259
+  /** \return True if this is a directory else false. */
260
+  bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
261
+  /** \return True if this is a normal file else false. */
262
+  bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;}
263
+  /** \return True if this is an open file/directory else false. */
264
+  bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;}
265
+  /** \return True if this is a subdirectory else false. */
266
+  bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;}
267
+  /** \return True if this is the root directory. */
268
+  bool isRoot() const {
269
+    return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
270
+  }
271
+  void ls(Print* pr, uint8_t flags = 0, uint8_t indent = 0);
272
+  void ls(uint8_t flags = 0);
273
+  bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
274
+  // alias for backward compactability
275
+  bool makeDir(SdBaseFile* dir, const char* path) {
276
+    return mkdir(dir, path, false);
277
+  }
278
+  bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
279
+  bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
280
+  bool open(const char* path, uint8_t oflag = O_READ);
281
+  bool openNext(SdBaseFile* dirFile, uint8_t oflag);
282
+  bool openRoot(SdVolume* vol);
283
+  int peek();
284
+  static void printFatDate(uint16_t fatDate);
285
+  static void printFatDate(Print* pr, uint16_t fatDate);
286
+  static void printFatTime(uint16_t fatTime);
287
+  static void printFatTime(Print* pr, uint16_t fatTime);
288
+  bool printName();
289
+  int16_t read();
290
+  int16_t read(void* buf, uint16_t nbyte);
291
+  int8_t readDir(dir_t* dir);
292
+  static bool remove(SdBaseFile* dirFile, const char* path);
293
+  bool remove();
294
+  /** Set the file's current position to zero. */
295
+  void rewind() {seekSet(0);}
296
+  bool rename(SdBaseFile* dirFile, const char* newPath);
297
+  bool rmdir();
298
+  // for backward compatibility
299
+  bool rmDir() {return rmdir();}
300
+  bool rmRfStar();
301
+  /** Set the files position to current position + \a pos. See seekSet().
302
+   * \param[in] offset The new position in bytes from the current position.
303
+   * \return true for success or false for failure.
304
+   */
305
+  bool seekCur(int32_t offset) {
306
+    return seekSet(curPosition_ + offset);
307
+  }
308
+  /** Set the files position to end-of-file + \a offset. See seekSet().
309
+   * \param[in] offset The new position in bytes from end-of-file.
310
+   * \return true for success or false for failure.
311
+   */
312
+  bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);}
313
+  bool seekSet(uint32_t pos);
314
+  bool sync();
315
+  bool timestamp(SdBaseFile* file);
316
+  bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
317
+          uint8_t hour, uint8_t minute, uint8_t second);
318
+  /** Type of file.  You should use isFile() or isDir() instead of type()
319
+   * if possible.
320
+   *
321
+   * \return The file or directory type.
322
+   */
323
+  uint8_t type() const {return type_;}
324
+  bool truncate(uint32_t size);
325
+  /** \return SdVolume that contains this file. */
326
+  SdVolume* volume() const {return vol_;}
327
+  int16_t write(const void* buf, uint16_t nbyte);
328
+//------------------------------------------------------------------------------
329
+ private:
330
+  // allow SdFat to set cwd_
331
+  friend class SdFat;
332
+  // global pointer to cwd dir
333
+  static SdBaseFile* cwd_;
334
+  // data time callback function
335
+  static void (*dateTime_)(uint16_t* date, uint16_t* time);
336
+  // bits defined in flags_
337
+  // should be 0X0F
338
+  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
339
+  // sync of directory entry required
340
+  static uint8_t const F_FILE_DIR_DIRTY = 0X80;
341
+
342
+  // private data
343
+  uint8_t   flags_;         // See above for definition of flags_ bits
344
+  uint8_t   fstate_;        // error and eof indicator
345
+  uint8_t   type_;          // type of file see above for values
346
+  uint32_t  curCluster_;    // cluster for current file position
347
+  uint32_t  curPosition_;   // current file position in bytes from beginning
348
+  uint32_t  dirBlock_;      // block for this files directory entry
349
+  uint8_t   dirIndex_;      // index of directory entry in dirBlock
350
+  uint32_t  fileSize_;      // file size in bytes
351
+  uint32_t  firstCluster_;  // first cluster of file
352
+  SdVolume* vol_;           // volume where file is located
353
+
354
+  /** experimental don't use */
355
+  bool openParent(SdBaseFile* dir);
356
+  // private functions
357
+  bool addCluster();
358
+  bool addDirCluster();
359
+  dir_t* cacheDirEntry(uint8_t action);
360
+  int8_t lsPrintNext(Print *pr, uint8_t flags, uint8_t indent);
361
+  static bool make83Name(const char* str, uint8_t* name, const char** ptr);
362
+  bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
363
+  bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
364
+  bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
365
+  dir_t* readDirCache();
366
+//------------------------------------------------------------------------------
367
+// to be deleted
368
+  static void printDirName(const dir_t& dir,
369
+    uint8_t width, bool printSlash);
370
+  static void printDirName(Print* pr, const dir_t& dir,
371
+    uint8_t width, bool printSlash);
372
+//------------------------------------------------------------------------------
373
+// Deprecated functions  - suppress cpplint warnings with NOLINT comment
374
+#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
375
+ public:
376
+  /** \deprecated Use:
377
+   * bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
378
+   * \param[out] bgnBlock the first block address for the file.
379
+   * \param[out] endBlock the last  block address for the file.
380
+   * \return true for success or false for failure.
381
+   */
382
+  bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {  // NOLINT
383
+    return contiguousRange(&bgnBlock, &endBlock);
384
+  }
385
+ /** \deprecated Use:
386
+   * bool createContiguous(SdBaseFile* dirFile,
387
+   *   const char* path, uint32_t size)
388
+   * \param[in] dirFile The directory where the file will be created.
389
+   * \param[in] path A path with a valid DOS 8.3 file name.
390
+   * \param[in] size The desired file size.
391
+   * \return true for success or false for failure.
392
+   */
393
+  bool createContiguous(SdBaseFile& dirFile,  // NOLINT
394
+    const char* path, uint32_t size) {
395
+    return createContiguous(&dirFile, path, size);
396
+  }
397
+  /** \deprecated Use:
398
+   * static void dateTimeCallback(
399
+   *   void (*dateTime)(uint16_t* date, uint16_t* time));
400
+   * \param[in] dateTime The user's call back function.
401
+   */
402
+  static void dateTimeCallback(
403
+    void (*dateTime)(uint16_t& date, uint16_t& time)) {  // NOLINT
404
+    oldDateTime_ = dateTime;
405
+    dateTime_ = dateTime ? oldToNew : 0;
406
+  }
407
+  /** \deprecated Use: bool dirEntry(dir_t* dir);
408
+   * \param[out] dir Location for return of the file's directory entry.
409
+   * \return true for success or false for failure.
410
+   */
411
+  bool dirEntry(dir_t& dir) {return dirEntry(&dir);}  // NOLINT
412
+  /** \deprecated Use:
413
+   * bool mkdir(SdBaseFile* dir, const char* path);
414
+   * \param[in] dir An open SdFat instance for the directory that will contain
415
+   * the new directory.
416
+   * \param[in] path A path with a valid 8.3 DOS name for the new directory.
417
+   * \return true for success or false for failure.
418
+   */
419
+  bool mkdir(SdBaseFile& dir, const char* path) {  // NOLINT
420
+    return mkdir(&dir, path);
421
+  }
422
+  /** \deprecated Use:
423
+   * bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
424
+   * \param[in] dirFile An open SdFat instance for the directory containing the
425
+   * file to be opened.
426
+   * \param[in] path A path with a valid 8.3 DOS name for the file.
427
+   * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
428
+   * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
429
+   * \return true for success or false for failure.
430
+   */
431
+  bool open(SdBaseFile& dirFile, // NOLINT
432
+    const char* path, uint8_t oflag) {
433
+    return open(&dirFile, path, oflag);
434
+  }
435
+  /** \deprecated  Do not use in new apps
436
+   * \param[in] dirFile An open SdFat instance for the directory containing the
437
+   * file to be opened.
438
+   * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
439
+   * \return true for success or false for failure.
440
+   */
441
+  bool open(SdBaseFile& dirFile, const char* path) {  // NOLINT
442
+    return open(dirFile, path, O_RDWR);
443
+  }
444
+  /** \deprecated Use:
445
+   * bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
446
+   * \param[in] dirFile An open SdFat instance for the directory.
447
+   * \param[in] index The \a index of the directory entry for the file to be
448
+   * opened.  The value for \a index is (directory file position)/32.
449
+   * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
450
+   * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
451
+   * \return true for success or false for failure.
452
+   */
453
+  bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) {  // NOLINT
454
+    return open(&dirFile, index, oflag);
455
+  }
456
+  /** \deprecated Use: bool openRoot(SdVolume* vol);
457
+   * \param[in] vol The FAT volume containing the root directory to be opened.
458
+   * \return true for success or false for failure.
459
+   */
460
+  bool openRoot(SdVolume& vol) {return openRoot(&vol);}  // NOLINT
461
+  /** \deprecated Use: int8_t readDir(dir_t* dir);
462
+   * \param[out] dir The dir_t struct that will receive the data.
463
+   * \return bytes read for success zero for eof or -1 for failure.
464
+   */
465
+  int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT
466
+  /** \deprecated Use:
467
+   * static uint8_t remove(SdBaseFile* dirFile, const char* path);
468
+   * \param[in] dirFile The directory that contains the file.
469
+   * \param[in] path The name of the file to be removed.
470
+   * \return true for success or false for failure.
471
+   */
472
+  static bool remove(SdBaseFile& dirFile, const char* path) {  // NOLINT
473
+    return remove(&dirFile, path);
474
+  }
475
+//------------------------------------------------------------------------------
476
+// rest are private
477
+ private:
478
+  static void (*oldDateTime_)(uint16_t& date, uint16_t& time);  // NOLINT
479
+  static void oldToNew(uint16_t* date, uint16_t* time) {
480
+    uint16_t d;
481
+    uint16_t t;
482
+    oldDateTime_(d, t);
483
+    *date = d;
484
+    *time = t;
485
+  }
486
+#endif  // ALLOW_DEPRECATED_FUNCTIONS
487
+};
488
+
489
+#endif  // SdBaseFile_h

+ 329
- 0
Marlin/SdFat.cpp View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2009 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+#include "SdFat.h"
21
+#include "SdFatUtil.h"
22
+//------------------------------------------------------------------------------
23
+/** Change a volume's working directory to root
24
+ *
25
+ * Changes the volume's working directory to the SD's root directory.
26
+ * Optionally set the current working directory to the volume's
27
+ * working directory.
28
+ *
29
+ * \param[in] set_cwd Set the current working directory to this volume's
30
+ *  working directory if true.
31
+ *
32
+ * \return The value one, true, is returned for success and
33
+ * the value zero, false, is returned for failure.
34
+ */
35
+bool SdFat::chdir(bool set_cwd) {
36
+  if (set_cwd) SdBaseFile::cwd_ = &vwd_;
37
+  vwd_.close();
38
+  return vwd_.openRoot(&vol_);
39
+}
40
+//------------------------------------------------------------------------------
41
+/** Change a volume's working directory
42
+ *
43
+ * Changes the volume working directory to the \a path subdirectory.
44
+ * Optionally set the current working directory to the volume's
45
+ * working directory.
46
+ *
47
+ * Example: If the volume's working directory is "/DIR", chdir("SUB")
48
+ * will change the volume's working directory from "/DIR" to "/DIR/SUB".
49
+ *
50
+ * If path is "/", the volume's working directory will be changed to the
51
+ * root directory
52
+ *
53
+ * \param[in] path The name of the subdirectory.
54
+ *
55
+ * \param[in] set_cwd Set the current working directory to this volume's
56
+ *  working directory if true.
57
+ *
58
+ * \return The value one, true, is returned for success and
59
+ * the value zero, false, is returned for failure.
60
+ */
61
+bool SdFat::chdir(const char *path, bool set_cwd) {
62
+  SdBaseFile dir;
63
+  if (path[0] == '/' && path[1] == '\0') return chdir(set_cwd);
64
+  if (!dir.open(&vwd_, path, O_READ)) goto fail;
65
+  if (!dir.isDir()) goto fail;
66
+  vwd_ = dir;
67
+  if (set_cwd) SdBaseFile::cwd_ = &vwd_;
68
+  return true;
69
+
70
+ fail:
71
+  return false;
72
+}
73
+//------------------------------------------------------------------------------
74
+/** Set the current working directory to a volume's working directory.
75
+ *
76
+ * This is useful with multiple SD cards.
77
+ *
78
+ * The current working directory is changed to this volume's working directory.
79
+ *
80
+ * This is like the Windows/DOS \<drive letter>: command.
81
+ */
82
+void SdFat::chvol() {
83
+  SdBaseFile::cwd_ = &vwd_;
84
+}
85
+//------------------------------------------------------------------------------
86
+/** %Print any SD error code and halt. */
87
+void SdFat::errorHalt() {
88
+  errorPrint();
89
+  while (1);
90
+}
91
+//------------------------------------------------------------------------------
92
+/** %Print msg, any SD error code, and halt.
93
+ *
94
+ * \param[in] msg Message to print.
95
+ */
96
+void SdFat::errorHalt(char const* msg) {
97
+  errorPrint(msg);
98
+  while (1);
99
+}
100
+//------------------------------------------------------------------------------
101
+/** %Print msg, any SD error code, and halt.
102
+ *
103
+ * \param[in] msg Message in program space (flash memory) to print.
104
+ */
105
+void SdFat::errorHalt_P(PGM_P msg) {
106
+  errorPrint_P(msg);
107
+  while (1);
108
+}
109
+//------------------------------------------------------------------------------
110
+/** %Print any SD error code. */
111
+void SdFat::errorPrint() {
112
+  if (!card_.errorCode()) return;
113
+  PgmPrint("SD errorCode: 0X");
114
+  Serial.println(card_.errorCode(), HEX);
115
+}
116
+//------------------------------------------------------------------------------
117
+/** %Print msg, any SD error code.
118
+ *
119
+ * \param[in] msg Message to print.
120
+ */
121
+void SdFat::errorPrint(char const* msg) {
122
+  PgmPrint("error: ");
123
+  Serial.println(msg);
124
+  errorPrint();
125
+}
126
+//------------------------------------------------------------------------------
127
+/** %Print msg, any SD error code.
128
+ *
129
+ * \param[in] msg Message in program space (flash memory) to print.
130
+ */
131
+void SdFat::errorPrint_P(PGM_P msg) {
132
+  PgmPrint("error: ");
133
+  SerialPrintln_P(msg);
134
+  errorPrint();
135
+}
136
+//------------------------------------------------------------------------------
137
+/**
138
+ * Test for the existence of a file.
139
+ *
140
+ * \param[in] name Name of the file to be tested for.
141
+ *
142
+ * \return true if the file exists else false.
143
+ */
144
+bool SdFat::exists(const char* name) {
145
+  return vwd_.exists(name);
146
+}
147
+//------------------------------------------------------------------------------
148
+/**
149
+ * Initialize an SdFat object.
150
+ *
151
+ * Initializes the SD card, SD volume, and root directory.
152
+ *
153
+ * \param[in] sckRateID value for SPI SCK rate. See Sd2Card::init().
154
+ * \param[in] chipSelectPin SD chip select pin. See Sd2Card::init().
155
+ *
156
+ * \return The value one, true, is returned for success and
157
+ * the value zero, false, is returned for failure.
158
+ */
159
+bool SdFat::init(uint8_t sckRateID, uint8_t chipSelectPin) {
160
+  return card_.init(sckRateID, chipSelectPin) && vol_.init(&card_) && chdir(1);
161
+}
162
+//------------------------------------------------------------------------------
163
+/** %Print error details and halt after SdFat::init() fails. */
164
+void SdFat::initErrorHalt() {
165
+  initErrorPrint();
166
+  while (1);
167
+}
168
+//------------------------------------------------------------------------------
169
+/**Print message, error details, and halt after SdFat::init() fails.
170
+ *
171
+ * \param[in] msg Message to print.
172
+ */
173
+void SdFat::initErrorHalt(char const *msg) {
174
+  Serial.println(msg);
175
+  initErrorHalt();
176
+}
177
+//------------------------------------------------------------------------------
178
+/**Print message, error details, and halt after SdFat::init() fails.
179
+ *
180
+ * \param[in] msg Message in program space (flash memory) to print.
181
+ */
182
+void SdFat::initErrorHalt_P(PGM_P msg) {
183
+  SerialPrintln_P(msg);
184
+  initErrorHalt();
185
+}
186
+//------------------------------------------------------------------------------
187
+/** Print error details after SdFat::init() fails. */
188
+void SdFat::initErrorPrint() {
189
+  if (card_.errorCode()) {
190
+    PgmPrintln("Can't access SD card. Do not reformat.");
191
+    if (card_.errorCode() == SD_CARD_ERROR_CMD0) {
192
+      PgmPrintln("No card, wrong chip select pin, or SPI problem?");
193
+    }
194
+    errorPrint();
195
+  } else if (vol_.fatType() == 0) {
196
+    PgmPrintln("Invalid format, reformat SD.");
197
+  } else if (!vwd_.isOpen()) {
198
+    PgmPrintln("Can't open root directory.");
199
+  } else {
200
+    PgmPrintln("No error found.");
201
+  }
202
+}
203
+//------------------------------------------------------------------------------
204
+/**Print message and error details and halt after SdFat::init() fails.
205
+ *
206
+ * \param[in] msg Message to print.
207
+ */
208
+void SdFat::initErrorPrint(char const *msg) {
209
+  Serial.println(msg);
210
+  initErrorPrint();
211
+}
212
+//------------------------------------------------------------------------------
213
+/**Print message and error details after SdFat::init() fails.
214
+ *
215
+ * \param[in] msg Message in program space (flash memory) to print.
216
+ */
217
+void SdFat::initErrorPrint_P(PGM_P msg) {
218
+  SerialPrintln_P(msg);
219
+  initErrorHalt();
220
+}
221
+//------------------------------------------------------------------------------
222
+/** List the directory contents of the volume working directory to Serial.
223
+ *
224
+ * \param[in] flags The inclusive OR of
225
+ *
226
+ * LS_DATE - %Print file modification date
227
+ *
228
+ * LS_SIZE - %Print file size.
229
+ *
230
+ * LS_R - Recursive list of subdirectories.
231
+ */
232
+void SdFat::ls(uint8_t flags) {
233
+  vwd_.ls(&Serial, flags);
234
+}
235
+//------------------------------------------------------------------------------
236
+/** List the directory contents of the volume working directory to Serial.
237
+ *
238
+ * \param[in] pr Print stream for list.
239
+ *
240
+ * \param[in] flags The inclusive OR of
241
+ *
242
+ * LS_DATE - %Print file modification date
243
+ *
244
+ * LS_SIZE - %Print file size.
245
+ *
246
+ * LS_R - Recursive list of subdirectories.
247
+ */
248
+void SdFat::ls(Print* pr, uint8_t flags) {
249
+  vwd_.ls(pr, flags);
250
+}
251
+//------------------------------------------------------------------------------
252
+/** Make a subdirectory in the volume working directory.
253
+ *
254
+ * \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
255
+ *
256
+ * \param[in] pFlag Create missing parent directories if true.
257
+ *
258
+ * \return The value one, true, is returned for success and
259
+ * the value zero, false, is returned for failure.
260
+ */
261
+bool SdFat::mkdir(const char* path, bool pFlag) {
262
+  SdBaseFile sub;
263
+  return sub.mkdir(&vwd_, path, pFlag);
264
+}
265
+//------------------------------------------------------------------------------
266
+/** Remove a file from the volume working directory.
267
+*
268
+* \param[in] path A path with a valid 8.3 DOS name for the file.
269
+*
270
+* \return The value one, true, is returned for success and
271
+* the value zero, false, is returned for failure.
272
+*/
273
+bool SdFat::remove(const char* path) {
274
+  return SdBaseFile::remove(&vwd_, path);
275
+}
276
+//------------------------------------------------------------------------------
277
+/** Rename a file or subdirectory.
278
+ *
279
+ * \param[in] oldPath Path name to the file or subdirectory to be renamed.
280
+ *
281
+ * \param[in] newPath New path name of the file or subdirectory.
282
+ *
283
+ * The \a newPath object must not exist before the rename call.
284
+ *
285
+ * The file to be renamed must not be open.  The directory entry may be
286
+ * moved and file system corruption could occur if the file is accessed by
287
+ * a file object that was opened before the rename() call.
288
+ *
289
+ * \return The value one, true, is returned for success and
290
+ * the value zero, false, is returned for failure.
291
+ */
292
+bool SdFat::rename(const char *oldPath, const char *newPath) {
293
+  SdBaseFile file;
294
+  if (!file.open(oldPath, O_READ)) return false;
295
+  return file.rename(&vwd_, newPath);
296
+}
297
+//------------------------------------------------------------------------------
298
+/** Remove a subdirectory from the volume's working directory.
299
+ *
300
+ * \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
301
+ *
302
+ * The subdirectory file will be removed only if it is empty.
303
+ *
304
+ * \return The value one, true, is returned for success and
305
+ * the value zero, false, is returned for failure.
306
+ */
307
+bool SdFat::rmdir(const char* path) {
308
+  SdBaseFile sub;
309
+  if (!sub.open(path, O_READ)) return false;
310
+  return sub.rmdir();
311
+}
312
+//------------------------------------------------------------------------------
313
+/** Truncate a file to a specified length.  The current file position
314
+ * will be maintained if it is less than or equal to \a length otherwise
315
+ * it will be set to end of file.
316
+ *
317
+ * \param[in] path A path with a valid 8.3 DOS name for the file.
318
+ * \param[in] length The desired length for the file.
319
+ *
320
+ * \return The value one, true, is returned for success and
321
+ * the value zero, false, is returned for failure.
322
+ * Reasons for failure include file is read only, file is a directory,
323
+ * \a length is greater than the current file size or an I/O error occurs.
324
+ */
325
+bool SdFat::truncate(const char* path, uint32_t length) {
326
+  SdBaseFile file;
327
+  if (!file.open(path, O_WRITE)) return false;
328
+  return file.truncate(length);
329
+}

+ 44
- 515
Marlin/SdFat.h View File

21
 #define SdFat_h
21
 #define SdFat_h
22
 /**
22
 /**
23
  * \file
23
  * \file
24
- * SdFile and SdVolume classes
24
+ * \brief SdFat class
25
  */
25
  */
26
-#include <avr/pgmspace.h>
27
-#include "Sd2Card.h"
28
-#include "FatStructs.h"
29
-#include "Print.h"
26
+#include "SdFile.h"
27
+//#include <SdStream.h>
28
+//#include <ArduinoStream.h>
30
 //------------------------------------------------------------------------------
29
 //------------------------------------------------------------------------------
31
-/**
32
- * Allow use of deprecated functions if non-zero
33
- */
34
-#define ALLOW_DEPRECATED_FUNCTIONS 1
35
-//------------------------------------------------------------------------------
36
-// forward declaration since SdVolume is used in SdFile
37
-class SdVolume;
38
-//==============================================================================
39
-// SdFile class
40
-
41
-// flags for ls()
42
-/** ls() flag to print modify date */
43
-uint8_t const LS_DATE = 1;
44
-/** ls() flag to print file size */
45
-uint8_t const LS_SIZE = 2;
46
-/** ls() flag for recursive list of subdirectories */
47
-uint8_t const LS_R = 4;
48
-
49
-// use the gnu style oflag in open()
50
-/** open() oflag for reading */
51
-uint8_t const O_READ = 0X01;
52
-/** open() oflag - same as O_READ */
53
-uint8_t const O_RDONLY = O_READ;
54
-/** open() oflag for write */
55
-uint8_t const O_WRITE = 0X02;
56
-/** open() oflag - same as O_WRITE */
57
-uint8_t const O_WRONLY = O_WRITE;
58
-/** open() oflag for reading and writing */
59
-uint8_t const O_RDWR = (O_READ | O_WRITE);
60
-/** open() oflag mask for access modes */
61
-uint8_t const O_ACCMODE = (O_READ | O_WRITE);
62
-/** The file offset shall be set to the end of the file prior to each write. */
63
-uint8_t const O_APPEND = 0X04;
64
-/** synchronous writes - call sync() after each write */
65
-uint8_t const O_SYNC = 0X08;
66
-/** create the file if nonexistent */
67
-uint8_t const O_CREAT = 0X10;
68
-/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
69
-uint8_t const O_EXCL = 0X20;
70
-/** truncate the file to zero length */
71
-uint8_t const O_TRUNC = 0X40;
72
-
73
-// flags for timestamp
74
-/** set the file's last access date */
75
-uint8_t const T_ACCESS = 1;
76
-/** set the file's creation date and time */
77
-uint8_t const T_CREATE = 2;
78
-/** Set the file's write date and time */
79
-uint8_t const T_WRITE = 4;
80
-// values for type_
81
-/** This SdFile has not been opened. */
82
-uint8_t const FAT_FILE_TYPE_CLOSED = 0;
83
-/** SdFile for a file */
84
-uint8_t const FAT_FILE_TYPE_NORMAL = 1;
85
-/** SdFile for a FAT16 root directory */
86
-uint8_t const FAT_FILE_TYPE_ROOT16 = 2;
87
-/** SdFile for a FAT32 root directory */
88
-uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
89
-/** SdFile for a subdirectory */
90
-uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
91
-/** Test value for directory type */
92
-uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16;
93
-
94
-/** date field for FAT directory entry */
95
-static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
96
-  return (year - 1980) << 9 | month << 5 | day;
97
-}
98
-/** year part of FAT directory date field */
99
-static inline uint16_t FAT_YEAR(uint16_t fatDate) {
100
-  return 1980 + (fatDate >> 9);
101
-}
102
-/** month part of FAT directory date field */
103
-static inline uint8_t FAT_MONTH(uint16_t fatDate) {
104
-  return (fatDate >> 5) & 0XF;
105
-}
106
-/** day part of FAT directory date field */
107
-static inline uint8_t FAT_DAY(uint16_t fatDate) {
108
-  return fatDate & 0X1F;
109
-}
110
-/** time field for FAT directory entry */
111
-static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
112
-  return hour << 11 | minute << 5 | second >> 1;
113
-}
114
-/** hour part of FAT directory time field */
115
-static inline uint8_t FAT_HOUR(uint16_t fatTime) {
116
-  return fatTime >> 11;
117
-}
118
-/** minute part of FAT directory time field */
119
-static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
120
-  return(fatTime >> 5) & 0X3F;
121
-}
122
-/** second part of FAT directory time field */
123
-static inline uint8_t FAT_SECOND(uint16_t fatTime) {
124
-  return 2*(fatTime & 0X1F);
125
-}
126
-/** Default date for file timestamps is 1 Jan 2000 */
127
-uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
128
-/** Default time for file timestamp is 1 am */
129
-uint16_t const FAT_DEFAULT_TIME = (1 << 11);
30
+/** SdFat version YYYYMMDD */
31
+#define SD_FAT_VERSION 20110902
130
 //------------------------------------------------------------------------------
32
 //------------------------------------------------------------------------------
131
 /**
33
 /**
132
- * \class SdFile
133
- * \brief Access FAT16 and FAT32 files on SD and SDHC cards.
34
+ * \class SdFat
35
+ * \brief Integration class for the %SdFat library.
134
  */
36
  */
135
-class SdFile : public Print {
37
+class SdFat {
136
  public:
38
  public:
137
-  /** Create an instance of SdFile. */
138
-  SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {}
139
-  /**
140
-   * writeError is set to true if an error occurs during a write().
141
-   * Set writeError to false before calling print() and/or write() and check
142
-   * for true after calls to print() and/or write().
143
-   */
144
-  bool writeError;
145
-  /**
146
-   * Cancel unbuffered reads for this file.
147
-   * See setUnbufferedRead()
148
-   */
149
-  void clearUnbufferedRead(void) {
150
-    flags_ &= ~F_FILE_UNBUFFERED_READ;
151
-  }
152
-  uint8_t close(void);
153
-  uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
154
-  uint8_t createContiguous(SdFile* dirFile,
155
-          const char* fileName, uint32_t size);
156
-  /** \return The current cluster number for a file or directory. */
157
-  uint32_t curCluster(void) const {return curCluster_;}
158
-  /** \return The current position for a file or directory. */
159
-  uint32_t curPosition(void) const {return curPosition_;}
160
-  /**
161
-   * Set the date/time callback function
162
-   *
163
-   * \param[in] dateTime The user's call back function.  The callback
164
-   * function is of the form:
165
-   *
166
-   * \code
167
-   * void dateTime(uint16_t* date, uint16_t* time) {
168
-   *   uint16_t year;
169
-   *   uint8_t month, day, hour, minute, second;
170
-   *
171
-   *   // User gets date and time from GPS or real-time clock here
172
-   *
173
-   *   // return date using FAT_DATE macro to format fields
174
-   *   *date = FAT_DATE(year, month, day);
175
-   *
176
-   *   // return time using FAT_TIME macro to format fields
177
-   *   *time = FAT_TIME(hour, minute, second);
178
-   * }
179
-   * \endcode
180
-   *
181
-   * Sets the function that is called when a file is created or when
182
-   * a file's directory entry is modified by sync(). All timestamps,
183
-   * access, creation, and modify, are set when a file is created.
184
-   * sync() maintains the last access date and last modify date/time.
185
-   *
186
-   * See the timestamp() function.
187
-   */
188
-  static void dateTimeCallback(
189
-    void (*dateTime)(uint16_t* date, uint16_t* time)) {
190
-    dateTime_ = dateTime;
191
-  }
192
-  /**
193
-   * Cancel the date/time callback function.
194
-   */
195
-  static void dateTimeCallbackCancel(void) {
196
-    // use explicit zero since NULL is not defined for Sanguino
197
-    dateTime_ = 0;
198
-  }
199
-  /** \return Address of the block that contains this file's directory. */
200
-  uint32_t dirBlock(void) const {return dirBlock_;}
201
-  uint8_t dirEntry(dir_t* dir);
202
-  /** \return Index of this file's directory in the block dirBlock. */
203
-  uint8_t dirIndex(void) const {return dirIndex_;}
204
-  static void dirName(const dir_t& dir, char* name);
205
-  /** \return The total number of bytes in a file or directory. */
206
-  uint32_t fileSize(void) const {return fileSize_;}
207
-  /** \return The first cluster number for a file or directory. */
208
-  uint32_t firstCluster(void) const {return firstCluster_;}
209
-  /** \return True if this is a SdFile for a directory else false. */
210
-  uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
211
-  /** \return True if this is a SdFile for a file else false. */
212
-  uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;}
213
-  /** \return True if this is a SdFile for an open file/directory else false. */
214
-  uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;}
215
-  /** \return True if this is a SdFile for a subdirectory else false. */
216
-  uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;}
217
-  /** \return True if this is a SdFile for the root directory. */
218
-  uint8_t isRoot(void) const {
219
-    return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32;
220
-  }
221
-  void ls(uint8_t flags = 0, uint8_t indent = 0);
222
-  uint8_t makeDir(SdFile* dir, const char* dirName);
223
-  uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag);
224
-  uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag);
225
-
226
-  uint8_t openRoot(SdVolume* vol);
227
-  static void printDirName(const dir_t& dir, uint8_t width);
228
-  static void printFatDate(uint16_t fatDate);
229
-  static void printFatTime(uint16_t fatTime);
230
-  static void printTwoDigits(uint8_t v);
231
-  /**
232
-   * Read the next byte from a file.
233
-   *
234
-   * \return For success read returns the next byte in the file as an int.
235
-   * If an error occurs or end of file is reached -1 is returned.
236
-   */
237
-  int16_t read(void) {
238
-    uint8_t b;
239
-    return read(&b, 1) == 1 ? b : -1;
240
-  }
241
-  int16_t read(void* buf, uint16_t nbyte);
242
-  int8_t readDir(dir_t* dir);
243
-  static uint8_t remove(SdFile* dirFile, const char* fileName);
244
-  uint8_t remove(void);
245
-  /** Set the file's current position to zero. */
246
-  void rewind(void) {
247
-    curPosition_ = curCluster_ = 0;
248
-  }
249
-  uint8_t rmDir(void);
250
-  uint8_t rmRfStar(void);
251
-  /** Set the files position to current position + \a pos. See seekSet(). */
252
-  uint8_t seekCur(uint32_t pos) {
253
-    return seekSet(curPosition_ + pos);
254
-  }
255
-  /**
256
-   *  Set the files current position to end of file.  Useful to position
257
-   *  a file for append. See seekSet().
258
-   */
259
-  uint8_t seekEnd(void) {return seekSet(fileSize_);}
260
-  uint8_t seekSet(uint32_t pos);
261
-  /**
262
-   * Use unbuffered reads to access this file.  Used with Wave
263
-   * Shield ISR.  Used with Sd2Card::partialBlockRead() in WaveRP.
264
-   *
265
-   * Not recommended for normal applications.
266
-   */
267
-  void setUnbufferedRead(void) {
268
-    if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ;
269
-  }
270
-  uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
271
-          uint8_t hour, uint8_t minute, uint8_t second);
272
-  uint8_t sync(void);
273
-  /** Type of this SdFile.  You should use isFile() or isDir() instead of type()
274
-   * if possible.
275
-   *
276
-   * \return The file or directory type.
277
-   */
278
-  uint8_t type(void) const {return type_;}
279
-  uint8_t truncate(uint32_t size);
280
-  /** \return Unbuffered read flag. */
281
-  uint8_t unbufferedRead(void) const {
282
-    return flags_ & F_FILE_UNBUFFERED_READ;
283
-  }
284
-  /** \return SdVolume that contains this file. */
285
-  SdVolume* volume(void) const {return vol_;}
286
-  void write(uint8_t b);
287
-  int16_t write(const void* buf, uint16_t nbyte);
288
-  void write(const char* str);
289
-  void write_P(PGM_P str);
290
-  void writeln_P(PGM_P str);
291
-//------------------------------------------------------------------------------
292
-#if ALLOW_DEPRECATED_FUNCTIONS
293
-// Deprecated functions  - suppress cpplint warnings with NOLINT comment
294
-  /** \deprecated Use:
295
-   * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
296
-   */
297
-  uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {  // NOLINT
298
-    return contiguousRange(&bgnBlock, &endBlock);
299
-  }
300
- /** \deprecated Use:
301
-   * uint8_t SdFile::createContiguous(SdFile* dirFile,
302
-   *   const char* fileName, uint32_t size)
303
-   */
304
-  uint8_t createContiguous(SdFile& dirFile,  // NOLINT
305
-    const char* fileName, uint32_t size) {
306
-    return createContiguous(&dirFile, fileName, size);
307
-  }
308
-
309
-  /**
310
-   * \deprecated Use:
311
-   * static void SdFile::dateTimeCallback(
312
-   *   void (*dateTime)(uint16_t* date, uint16_t* time));
313
-   */
314
-  static void dateTimeCallback(
315
-    void (*dateTime)(uint16_t& date, uint16_t& time)) {  // NOLINT
316
-    oldDateTime_ = dateTime;
317
-    dateTime_ = dateTime ? oldToNew : 0;
318
-  }
319
-  /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */
320
-  uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);}  // NOLINT
321
-  /** \deprecated Use:
322
-   * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName);
323
-   */
324
-  uint8_t makeDir(SdFile& dir, const char* dirName) {  // NOLINT
325
-    return makeDir(&dir, dirName);
326
-  }
327
-  /** \deprecated Use:
328
-   * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag);
329
-   */
330
-  uint8_t open(SdFile& dirFile, // NOLINT
331
-    const char* fileName, uint8_t oflag) {
332
-    return open(&dirFile, fileName, oflag);
333
-  }
334
-  /** \deprecated  Do not use in new apps */
335
-  uint8_t open(SdFile& dirFile, const char* fileName) {  // NOLINT
336
-    return open(dirFile, fileName, O_RDWR);
337
-  }
338
-  /** \deprecated Use:
339
-   * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag);
340
-   */
341
-  uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) {  // NOLINT
342
-    return open(&dirFile, index, oflag);
343
-  }
344
-  /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */
345
-  uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);}  // NOLINT
346
-
347
-  /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */
348
-  int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT
349
-  /** \deprecated Use:
350
-   * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName);
351
-   */
352
-  static uint8_t remove(SdFile& dirFile, const char* fileName) {  // NOLINT
353
-    return remove(&dirFile, fileName);
354
-  }
355
-//------------------------------------------------------------------------------
356
-// rest are private
357
- private:
358
-  static void (*oldDateTime_)(uint16_t& date, uint16_t& time);  // NOLINT
359
-  static void oldToNew(uint16_t* date, uint16_t* time) {
360
-    uint16_t d;
361
-    uint16_t t;
362
-    oldDateTime_(d, t);
363
-    *date = d;
364
-    *time = t;
365
-  }
366
-#endif  // ALLOW_DEPRECATED_FUNCTIONS
39
+  SdFat() {}
40
+  /** \return a pointer to the Sd2Card object. */
41
+  Sd2Card* card() {return &card_;}
42
+  bool chdir(bool set_cwd = false);
43
+  bool chdir(const char* path, bool set_cwd = false);
44
+  void chvol();
45
+  void errorHalt();
46
+  void errorHalt_P(PGM_P msg);
47
+  void errorHalt(char const *msg);
48
+  void errorPrint();
49
+  void errorPrint_P(PGM_P msg);
50
+  void errorPrint(char const *msg);
51
+  bool exists(const char* name);
52
+  bool init(uint8_t sckRateID = SPI_FULL_SPEED,
53
+    uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
54
+  void initErrorHalt();
55
+  void initErrorHalt(char const *msg);
56
+  void initErrorHalt_P(PGM_P msg);
57
+  void initErrorPrint();
58
+  void initErrorPrint(char const *msg);
59
+  void initErrorPrint_P(PGM_P msg);
60
+  void ls(uint8_t flags = 0);
61
+  void ls(Print* pr, uint8_t flags = 0);
62
+  bool mkdir(const char* path, bool pFlag = true);
63
+  bool remove(const char* path);
64
+  bool rename(const char *oldPath, const char *newPath);
65
+  bool rmdir(const char* path);
66
+  bool truncate(const char* path, uint32_t length);
67
+  /** \return a pointer to the SdVolume object. */
68
+  SdVolume* vol() {return &vol_;}
69
+  /** \return a pointer to the volume working directory. */
70
+  SdBaseFile* vwd() {return &vwd_;}
367
  private:
71
  private:
368
-  // bits defined in flags_
369
-  // should be 0XF
370
-  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
371
-  // available bits
372
-  static uint8_t const F_UNUSED = 0X30;
373
-  // use unbuffered SD read
374
-  static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;
375
-  // sync of directory entry required
376
-  static uint8_t const F_FILE_DIR_DIRTY = 0X80;
377
-
378
-// make sure F_OFLAG is ok
379
-#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
380
-#error flags_ bits conflict
381
-#endif  // flags_ bits
382
-
383
-  // private data
384
-  uint8_t   flags_;         // See above for definition of flags_ bits
385
-  uint8_t   type_;          // type of file see above for values
386
-  uint32_t  curCluster_;    // cluster for current file position
387
-  uint32_t  curPosition_;   // current file position in bytes from beginning
388
-  uint32_t  dirBlock_;      // SD block that contains directory entry for file
389
-  uint8_t   dirIndex_;      // index of entry in dirBlock 0 <= dirIndex_ <= 0XF
390
-  uint32_t  fileSize_;      // file size in bytes
391
-  uint32_t  firstCluster_;  // first cluster of file
392
-  SdVolume* vol_;           // volume where file is located
393
-
394
-  // private functions
395
-  uint8_t addCluster(void);
396
-  uint8_t addDirCluster(void);
397
-  dir_t* cacheDirEntry(uint8_t action);
398
-  static void (*dateTime_)(uint16_t* date, uint16_t* time);
399
-  static uint8_t make83Name(const char* str, uint8_t* name);
400
-  uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
401
-  dir_t* readDirCache(void);
402
-};
403
-//==============================================================================
404
-// SdVolume class
405
-/**
406
- * \brief Cache for an SD data block
407
- */
408
-union cache_t {
409
-           /** Used to access cached file data blocks. */
410
-  uint8_t  data[512];
411
-           /** Used to access cached FAT16 entries. */
412
-  uint16_t fat16[256];
413
-           /** Used to access cached FAT32 entries. */
414
-  uint32_t fat32[128];
415
-           /** Used to access cached directory entries. */
416
-  dir_t    dir[16];
417
-           /** Used to access a cached MasterBoot Record. */
418
-  mbr_t    mbr;
419
-           /** Used to access to a cached FAT boot sector. */
420
-  fbs_t    fbs;
421
-};
422
-//------------------------------------------------------------------------------
423
-/**
424
- * \class SdVolume
425
- * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
426
- */
427
-class SdVolume {
428
- public:
429
-  /** Create an instance of SdVolume */
430
-  SdVolume(void) :allocSearchStart_(2), fatType_(0) {}
431
-  /** Clear the cache and returns a pointer to the cache.  Used by the WaveRP
432
-   *  recorder to do raw write to the SD card.  Not for normal apps.
433
-   */
434
-  static uint8_t* cacheClear(void) {
435
-    cacheFlush();
436
-    cacheBlockNumber_ = 0XFFFFFFFF;
437
-    return cacheBuffer_.data;
438
-  }
439
-  /**
440
-   * Initialize a FAT volume.  Try partition one first then try super
441
-   * floppy format.
442
-   *
443
-   * \param[in] dev The Sd2Card where the volume is located.
444
-   *
445
-   * \return The value one, true, is returned for success and
446
-   * the value zero, false, is returned for failure.  Reasons for
447
-   * failure include not finding a valid partition, not finding a valid
448
-   * FAT file system or an I/O error.
449
-   */
450
-  uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
451
-  uint8_t init(Sd2Card* dev, uint8_t part);
452
-
453
-  // inline functions that return volume info
454
-  /** \return The volume's cluster size in blocks. */
455
-  uint8_t blocksPerCluster(void) const {return blocksPerCluster_;}
456
-  /** \return The number of blocks in one FAT. */
457
-  uint32_t blocksPerFat(void)  const {return blocksPerFat_;}
458
-  /** \return The total number of clusters in the volume. */
459
-  uint32_t clusterCount(void) const {return clusterCount_;}
460
-  /** \return The shift count required to multiply by blocksPerCluster. */
461
-  uint8_t clusterSizeShift(void) const {return clusterSizeShift_;}
462
-  /** \return The logical block number for the start of file data. */
463
-  uint32_t dataStartBlock(void) const {return dataStartBlock_;}
464
-  /** \return The number of FAT structures on the volume. */
465
-  uint8_t fatCount(void) const {return fatCount_;}
466
-  /** \return The logical block number for the start of the first FAT. */
467
-  uint32_t fatStartBlock(void) const {return fatStartBlock_;}
468
-  /** \return The FAT type of the volume. Values are 12, 16 or 32. */
469
-  uint8_t fatType(void) const {return fatType_;}
470
-  /** \return The number of entries in the root directory for FAT16 volumes. */
471
-  uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;}
472
-  /** \return The logical block number for the start of the root directory
473
-       on FAT16 volumes or the first cluster number on FAT32 volumes. */
474
-  uint32_t rootDirStart(void) const {return rootDirStart_;}
475
-  /** return a pointer to the Sd2Card object for this volume */
476
-  static Sd2Card* sdCard(void) {return sdCard_;}
477
-//------------------------------------------------------------------------------
478
-#if ALLOW_DEPRECATED_FUNCTIONS
479
-  // Deprecated functions  - suppress cpplint warnings with NOLINT comment
480
-  /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */
481
-  uint8_t init(Sd2Card& dev) {return init(&dev);}  // NOLINT
482
-
483
-  /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */
484
-  uint8_t init(Sd2Card& dev, uint8_t part) {  // NOLINT
485
-    return init(&dev, part);
486
-  }
487
-#endif  // ALLOW_DEPRECATED_FUNCTIONS
488
-//------------------------------------------------------------------------------
489
-  private:
490
-  // Allow SdFile access to SdVolume private data.
491
-  friend class SdFile;
492
-
493
-  // value for action argument in cacheRawBlock to indicate read from cache
494
-  static uint8_t const CACHE_FOR_READ = 0;
495
-  // value for action argument in cacheRawBlock to indicate cache dirty
496
-  static uint8_t const CACHE_FOR_WRITE = 1;
497
-
498
-  static cache_t cacheBuffer_;        // 512 byte cache for device blocks
499
-  static uint32_t cacheBlockNumber_;  // Logical number of block in the cache
500
-  static Sd2Card* sdCard_;            // Sd2Card object for cache
501
-  static uint8_t cacheDirty_;         // cacheFlush() will write block if true
502
-  static uint32_t cacheMirrorBlock_;  // block number for mirror FAT
503
-//
504
-  uint32_t allocSearchStart_;   // start cluster for alloc search
505
-  uint8_t blocksPerCluster_;    // cluster size in blocks
506
-  uint32_t blocksPerFat_;       // FAT size in blocks
507
-  uint32_t clusterCount_;       // clusters in one FAT
508
-  uint8_t clusterSizeShift_;    // shift to convert cluster count to block count
509
-  uint32_t dataStartBlock_;     // first data block number
510
-  uint8_t fatCount_;            // number of FATs on volume
511
-  uint32_t fatStartBlock_;      // start block for first FAT
512
-  uint8_t fatType_;             // volume type (12, 16, OR 32)
513
-  uint16_t rootDirEntryCount_;  // number of entries in FAT16 root dir
514
-  uint32_t rootDirStart_;       // root start block for FAT16, cluster for FAT32
515
-  //----------------------------------------------------------------------------
516
-  uint8_t allocContiguous(uint32_t count, uint32_t* curCluster);
517
-  uint8_t blockOfCluster(uint32_t position) const {
518
-          return (position >> 9) & (blocksPerCluster_ - 1);}
519
-  uint32_t clusterStartBlock(uint32_t cluster) const {
520
-           return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
521
-  uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
522
-           return clusterStartBlock(cluster) + blockOfCluster(position);}
523
-  static uint8_t cacheFlush(void);
524
-  static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);
525
-  static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;}
526
-  static uint8_t cacheZeroBlock(uint32_t blockNumber);
527
-  uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const;
528
-  uint8_t fatGet(uint32_t cluster, uint32_t* value) const;
529
-  uint8_t fatPut(uint32_t cluster, uint32_t value);
530
-  uint8_t fatPutEOC(uint32_t cluster) {
531
-    return fatPut(cluster, 0x0FFFFFFF);
532
-  }
533
-  uint8_t freeChain(uint32_t cluster);
534
-  uint8_t isEOC(uint32_t cluster) const {
535
-    return  cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
536
-  }
537
-  uint8_t readBlock(uint32_t block, uint8_t* dst) {
538
-    return sdCard_->readBlock(block, dst);}
539
-  uint8_t readData(uint32_t block, uint16_t offset,
540
-    uint16_t count, uint8_t* dst) {
541
-      return sdCard_->readData(block, offset, count, dst);
542
-  }
543
-  uint8_t writeBlock(uint32_t block, const uint8_t* dst) {
544
-    return sdCard_->writeBlock(block, dst);
545
-  }
72
+  Sd2Card card_;
73
+  SdVolume vol_;
74
+  SdBaseFile vwd_;
546
 };
75
 };
547
 #endif  // SdFat_h
76
 #endif  // SdFat_h

+ 108
- 0
Marlin/SdFatConfig.h View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2009 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+/**
21
+ * \file
22
+ * \brief configuration definitions
23
+ */
24
+#ifndef SdFatConfig_h
25
+#define SdFatConfig_h
26
+#include <stdint.h>
27
+//------------------------------------------------------------------------------
28
+/**
29
+ * To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
30
+ *
31
+ * Using multiple cards costs 400 - 500  bytes of flash.
32
+ *
33
+ * Each card requires about 550 bytes of SRAM so use of a Mega is recommended.
34
+ */
35
+#define USE_MULTIPLE_CARDS 0
36
+//------------------------------------------------------------------------------
37
+/**
38
+ * Call flush for endl if ENDL_CALLS_FLUSH is nonzero
39
+ *
40
+ * The standard for iostreams is to call flush.  This is very costly for
41
+ * SdFat.  Each call to flush causes 2048 bytes of I/O to the SD.
42
+ *
43
+ * SdFat has a single 512 byte buffer for SD I/O so it must write the current
44
+ * data block to the SD, read the directory block from the SD, update the
45
+ * directory entry, write the directory block to the SD and read the data
46
+ * block back into the buffer.
47
+ *
48
+ * The SD flash memory controller is not designed for this many rewrites
49
+ * so performance may be reduced by more than a factor of 100.
50
+ *
51
+ * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
52
+ * all data to be written to the SD.
53
+ */
54
+#define ENDL_CALLS_FLUSH 0
55
+//------------------------------------------------------------------------------
56
+/**
57
+ * Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
58
+ */
59
+#define ALLOW_DEPRECATED_FUNCTIONS 1
60
+//------------------------------------------------------------------------------
61
+/**
62
+ * Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
63
+ * FAT12 has not been well tested.
64
+ */
65
+#define FAT12_SUPPORT 0
66
+//------------------------------------------------------------------------------
67
+/**
68
+ * SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
69
+ * or 6 (F_CPU/128).
70
+ */
71
+#define SPI_SD_INIT_RATE 5
72
+//------------------------------------------------------------------------------
73
+/**
74
+ * Set the SS pin high for hardware SPI.  If SS is chip select for another SPI
75
+ * device this will disable that device during the SD init phase.
76
+ */
77
+#define SET_SPI_SS_HIGH 1
78
+//------------------------------------------------------------------------------
79
+/**
80
+ * Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
81
+ * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
82
+ *
83
+ * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
84
+ * on Mega Arduinos.  Software SPI works well with GPS Shield V1.1
85
+ * but many SD cards will fail with GPS Shield V1.0.
86
+ */
87
+#define MEGA_SOFT_SPI 0
88
+//------------------------------------------------------------------------------
89
+/**
90
+ * Set USE_SOFTWARE_SPI nonzero to always use software SPI.
91
+ */
92
+#define USE_SOFTWARE_SPI 0
93
+// define software SPI pins so Mega can use unmodified 168/328 shields
94
+/** Software SPI chip select pin for the SD */
95
+uint8_t const SOFT_SPI_CS_PIN = 10;
96
+/** Software SPI Master Out Slave In pin */
97
+uint8_t const SOFT_SPI_MOSI_PIN = 11;
98
+/** Software SPI Master In Slave Out pin */
99
+uint8_t const SOFT_SPI_MISO_PIN = 12;
100
+/** Software SPI Clock pin */
101
+uint8_t const SOFT_SPI_SCK_PIN = 13;
102
+//------------------------------------------------------------------------------
103
+/**
104
+ * The __cxa_pure_virtual function is an error handler that is invoked when
105
+ * a pure virtual function is called.
106
+ */
107
+#define USE_CXA_PURE_VIRTUAL 1
108
+#endif  // SdFatConfig_h

Marlin/SdFatStructs.h
File diff suppressed because it is too large
View File


+ 74
- 0
Marlin/SdFatUtil.cpp View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2008 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+#include "SdFatUtil.h"
21
+//------------------------------------------------------------------------------
22
+/** Amount of free RAM
23
+ * \return The number of free bytes.
24
+ */
25
+int SdFatUtil::FreeRam() {
26
+  extern int  __bss_end;
27
+  extern int* __brkval;
28
+  int free_memory;
29
+  if (reinterpret_cast<int>(__brkval) == 0) {
30
+    // if no heap use from end of bss section
31
+    free_memory = reinterpret_cast<int>(&free_memory)
32
+                  - reinterpret_cast<int>(&__bss_end);
33
+  } else {
34
+    // use from top of stack to heap
35
+    free_memory = reinterpret_cast<int>(&free_memory)
36
+                  - reinterpret_cast<int>(__brkval);
37
+  }
38
+  return free_memory;
39
+}
40
+//------------------------------------------------------------------------------
41
+/** %Print a string in flash memory.
42
+ *
43
+ * \param[in] pr Print object for output.
44
+ * \param[in] str Pointer to string stored in flash memory.
45
+ */
46
+void SdFatUtil::print_P(Print* pr, PGM_P str) {
47
+  for (uint8_t c; (c = pgm_read_byte(str)); str++) pr->write(c);
48
+}
49
+//------------------------------------------------------------------------------
50
+/** %Print a string in flash memory followed by a CR/LF.
51
+ *
52
+ * \param[in] pr Print object for output.
53
+ * \param[in] str Pointer to string stored in flash memory.
54
+ */
55
+void SdFatUtil::println_P(Print* pr, PGM_P str) {
56
+  print_P(pr, str);
57
+  pr->println();
58
+}
59
+//------------------------------------------------------------------------------
60
+/** %Print a string in flash memory to Serial.
61
+ *
62
+ * \param[in] str Pointer to string stored in flash memory.
63
+ */
64
+void SdFatUtil::SerialPrint_P(PGM_P str) {
65
+  print_P(&Serial, str);
66
+}
67
+//------------------------------------------------------------------------------
68
+/** %Print a string in flash memory to Serial followed by a CR/LF.
69
+ *
70
+ * \param[in] str Pointer to string stored in flash memory.
71
+ */
72
+void SdFatUtil::SerialPrintln_P(PGM_P str) {
73
+  println_P(&Serial, str);
74
+}

+ 15
- 39
Marlin/SdFatUtil.h View File

21
 #define SdFatUtil_h
21
 #define SdFatUtil_h
22
 /**
22
 /**
23
  * \file
23
  * \file
24
- * Useful utility functions.
24
+ * \brief Useful utility functions.
25
  */
25
  */
26
-#include <WProgram.h>
27
 #include <avr/pgmspace.h>
26
 #include <avr/pgmspace.h>
27
+#if ARDUINO < 100
28
+#include <WProgram.h>
29
+#else  // ARDUINO
30
+#include <Arduino.h>
31
+#endif  // ARDUINO
28
 /** Store and print a string in flash memory.*/
32
 /** Store and print a string in flash memory.*/
29
 #define PgmPrint(x) SerialPrint_P(PSTR(x))
33
 #define PgmPrint(x) SerialPrint_P(PSTR(x))
30
 /** Store and print a string in flash memory followed by a CR/LF.*/
34
 /** Store and print a string in flash memory followed by a CR/LF.*/
31
 #define PgmPrintln(x) SerialPrintln_P(PSTR(x))
35
 #define PgmPrintln(x) SerialPrintln_P(PSTR(x))
32
-/** Defined so doxygen works for function definitions. */
33
-#define NOINLINE __attribute__((noinline))
34
-//------------------------------------------------------------------------------
35
-/** Return the number of bytes currently free in RAM. */
36
-static int FreeRam(void) {
37
-  extern int  __bss_end;
38
-  extern int* __brkval;
39
-  int free_memory;
40
-  if (reinterpret_cast<int>(__brkval) == 0) {
41
-    // if no heap use from end of bss section
42
-    free_memory = reinterpret_cast<int>(&free_memory)
43
-                  - reinterpret_cast<int>(&__bss_end);
44
-  } else {
45
-    // use from top of stack to heap
46
-    free_memory = reinterpret_cast<int>(&free_memory)
47
-                  - reinterpret_cast<int>(__brkval);
48
-  }
49
-  return free_memory;
50
-}
51
-//------------------------------------------------------------------------------
52
-/**
53
- * %Print a string in flash memory to the serial port.
54
- *
55
- * \param[in] str Pointer to string stored in flash memory.
56
- */
57
-static NOINLINE void SerialPrint_P(PGM_P str) {
58
-  for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c);
59
-}
60
-//------------------------------------------------------------------------------
61
-/**
62
- * %Print a string in flash memory followed by a CR/LF.
63
- *
64
- * \param[in] str Pointer to string stored in flash memory.
65
- */
66
-static NOINLINE void SerialPrintln_P(PGM_P str) {
67
-  SerialPrint_P(str);
68
-  Serial.println();
36
+
37
+namespace SdFatUtil {
38
+  int FreeRam();
39
+  void print_P(Print* pr, PGM_P str);
40
+  void println_P(Print* pr, PGM_P str);
41
+  void SerialPrint_P(PGM_P str);
42
+  void SerialPrintln_P(PGM_P str);
69
 }
43
 }
44
+
45
+using namespace SdFatUtil;  // NOLINT
70
 #endif  // #define SdFatUtil_h
46
 #endif  // #define SdFatUtil_h

+ 0
- 202
Marlin/SdFatmainpage.h View File

1
-/* Arduino SdFat Library
2
- * Copyright (C) 2009 by William Greiman
3
- *  
4
- * This file is part of the Arduino SdFat Library
5
- *  
6
- * This Library is free software: you can redistribute it and/or modify 
7
- * it under the terms of the GNU General Public License as published by 
8
- * the Free Software Foundation, either version 3 of the License, or
9
- * (at your option) any later version.
10
- * 
11
- * This Library is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with the Arduino SdFat Library.  If not, see
18
- * <http://www.gnu.org/licenses/>.
19
- */
20
-
21
-/**
22
-\mainpage Arduino SdFat Library
23
-<CENTER>Copyright &copy; 2009 by William Greiman
24
-</CENTER>
25
-
26
-\section Intro Introduction
27
-The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32
28
-file systems on SD flash memory cards.  Standard SD and high capacity
29
-SDHC cards are supported.
30
-
31
-The SdFat only supports short 8.3 names.
32
-
33
-The main classes in SdFat are Sd2Card, SdVolume, and SdFile.
34
-
35
-The Sd2Card class supports access to standard SD cards and SDHC cards.  Most
36
-applications will only need to call the Sd2Card::init() member function.
37
-
38
-The SdVolume class supports FAT16 and FAT32 partitions.  Most applications
39
-will only need to call the SdVolume::init() member function.
40
-
41
-The SdFile class provides file access functions such as open(), read(),
42
-remove(), write(), close() and sync(). This class supports access to the root
43
-directory and subdirectories.
44
-
45
-A number of example are provided in the SdFat/examples folder.  These were
46
-developed to test SdFat and illustrate its use.
47
-
48
-SdFat was developed for high speed data recording.  SdFat was used to implement
49
-an audio record/play class, WaveRP, for the Adafruit Wave Shield.  This
50
-application uses special Sd2Card calls to write to contiguous files in raw mode.
51
-These functions reduce write latency so that audio can be recorded with the
52
-small amount of RAM in the Arduino.
53
-
54
-\section SDcard SD\SDHC Cards
55
-
56
-Arduinos access SD cards using the cards SPI protocol.  PCs, Macs, and
57
-most consumer devices use the 4-bit parallel SD protocol.  A card that
58
-functions well on A PC or Mac may not work well on the Arduino.
59
-
60
-Most cards have good SPI read performance but cards vary widely in SPI
61
-write performance.  Write performance is limited by how efficiently the
62
-card manages internal erase/remapping operations.  The Arduino cannot
63
-optimize writes to reduce erase operations because of its limit RAM.
64
-
65
-SanDisk cards generally have good write performance.  They seem to have
66
-more internal RAM buffering than other cards and therefore can limit
67
-the number of flash erase operations that the Arduino forces due to its
68
-limited RAM.
69
-
70
-\section Hardware Hardware Configuration
71
-
72
-SdFat was developed using an
73
-<A HREF = "http://www.adafruit.com/"> Adafruit Industries</A> 
74
-<A HREF = "http://www.ladyada.net/make/waveshield/"> Wave Shield</A>.
75
-
76
-The hardware interface to the SD card should not use a resistor based level
77
-shifter.  SdFat sets the SPI bus frequency to 8 MHz which results in signal
78
-rise times that are too slow for the edge detectors in many newer SD card
79
-controllers when resistor voltage dividers are used.
80
-
81
-The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the
82
-74HC4050N based circuit shown in the file SdLevel.png.  The Adafruit Wave Shield
83
-uses a 74AHC125N.  Gravitech sells SD and MicroSD Card Adapters based on the
84
-74LCX245.
85
-
86
-If you are using a resistor based level shifter and are having problems try
87
-setting the SPI bus frequency to 4 MHz.  This can be done by using 
88
-card.init(SPI_HALF_SPEED) to initialize the SD card.
89
-
90
-\section comment Bugs and Comments
91
-
92
-If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net.
93
-
94
-\section SdFatClass SdFat Usage
95
-
96
-SdFat uses a slightly restricted form of short names.
97
-Only printable ASCII characters are supported. No characters with code point
98
-values greater than 127 are allowed.  Space is not allowed even though space
99
-was allowed in the API of early versions of DOS.
100
-
101
-Short names are limited to 8 characters followed by an optional period (.)
102
-and extension of up to 3 characters.  The characters may be any combination
103
-of letters and digits.  The following special characters are also allowed:
104
-
105
-$ % ' - _ @ ~ ` ! ( ) { } ^ # &
106
-
107
-Short names are always converted to upper case and their original case
108
-value is lost.
109
-
110
-\note
111
-  The Arduino Print class uses character
112
-at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink
113
-function to control when data is written to the SD card.
114
-
115
-\par
116
-An application which writes to a file using \link Print::print() print()\endlink,
117
-\link Print::println() println() \endlink
118
-or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink
119
-at the appropriate time to force data and directory information to be written
120
-to the SD Card.  Data and directory information are also written to the SD card
121
-when \link SdFile::close() close() \endlink is called.
122
-
123
-\par
124
-Applications must use care calling \link SdFile::sync() sync() \endlink
125
-since 2048 bytes of I/O is required to update file and
126
-directory information.  This includes writing the current data block, reading
127
-the block that contains the directory entry for update, writing the directory
128
-block back and reading back the current data block.
129
-
130
-It is possible to open a file with two or more instances of SdFile.  A file may
131
-be corrupted if data is written to the file by more than one instance of SdFile.
132
-
133
-\section HowTo How to format SD Cards as FAT Volumes
134
-
135
-You should use a freshly formatted SD card for best performance.  FAT
136
-file systems become slower if many files have been created and deleted.
137
-This is because the directory entry for a deleted file is marked as deleted,
138
-but is not deleted.  When a new file is created, these entries must be scanned
139
-before creating the file, a flaw in the FAT design.  Also files can become
140
-fragmented which causes reads and writes to be slower.
141
-
142
-Microsoft operating systems support removable media formatted with a
143
-Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector
144
-in block zero.
145
-
146
-Microsoft operating systems expect MBR formatted removable media
147
-to have only one partition. The first partition should be used.
148
-
149
-Microsoft operating systems do not support partitioning SD flash cards.
150
-If you erase an SD card with a program like KillDisk, Most versions of
151
-Windows will format the card as a super floppy.
152
-
153
-The best way to restore an SD card's format is to use SDFormatter
154
-which can be downloaded from:
155
-
156
-http://www.sdcard.org/consumers/formatter/
157
-
158
-SDFormatter aligns flash erase boundaries with file
159
-system structures which reduces write latency and file system overhead.
160
-
161
-SDFormatter does not have an option for FAT type so it may format
162
-small cards as FAT12.
163
-
164
-After the MBR is restored by SDFormatter you may need to reformat small
165
-cards that have been formatted FAT12 to force the volume type to be FAT16.
166
-
167
-If you reformat the SD card with an OS utility, choose a cluster size that
168
-will result in:
169
-
170
-4084 < CountOfClusters && CountOfClusters < 65525
171
-
172
-The volume will then be FAT16.
173
-
174
-If you are formatting an SD card on OS X or Linux, be sure to use the first
175
-partition. Format this partition with a cluster count in above range.
176
-
177
-\section  References References
178
-
179
-Adafruit Industries:
180
-
181
-http://www.adafruit.com/
182
-
183
-http://www.ladyada.net/make/waveshield/
184
-
185
-The Arduino site:
186
-
187
-http://www.arduino.cc/
188
-
189
-For more information about FAT file systems see:
190
-
191
-http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
192
-
193
-For information about using SD cards as SPI devices see:
194
-
195
-http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
196
-
197
-The ATmega328 datasheet:
198
-
199
-http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
200
- 
201
-
202
- */  

+ 22
- 1193
Marlin/SdFile.cpp
File diff suppressed because it is too large
View File


+ 42
- 0
Marlin/SdFile.h View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2009 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+/**
21
+ * \file
22
+ * \brief SdFile class
23
+ */
24
+#include "SdBaseFile.h"
25
+#ifndef SdFile_h
26
+#define SdFile_h
27
+//------------------------------------------------------------------------------
28
+/**
29
+ * \class SdFile
30
+ * \brief SdBaseFile with Print.
31
+ */
32
+class SdFile : public SdBaseFile, public Print {
33
+ public:
34
+  SdFile() {}
35
+  SdFile(const char* name, uint8_t oflag);
36
+  void write(uint8_t b);
37
+  int16_t write(const void* buf, uint16_t nbyte);
38
+  void write(const char* str);
39
+  void write_P(PGM_P str);
40
+  void writeln_P(PGM_P str);
41
+};
42
+#endif  // SdFile_h

+ 140
- 97
Marlin/SdInfo.h View File

26
 // Part 1
26
 // Part 1
27
 // Physical Layer
27
 // Physical Layer
28
 // Simplified Specification
28
 // Simplified Specification
29
-// Version 2.00
30
-// September 25, 2006
29
+// Version 3.01
30
+// May 18, 2010
31
 //
31
 //
32
-// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
32
+// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs
33
 //------------------------------------------------------------------------------
33
 //------------------------------------------------------------------------------
34
 // SD card commands
34
 // SD card commands
35
 /** GO_IDLE_STATE - init card in spi mode if CS low */
35
 /** GO_IDLE_STATE - init card in spi mode if CS low */
40
 uint8_t const CMD9 = 0X09;
40
 uint8_t const CMD9 = 0X09;
41
 /** SEND_CID - read the card identification information (CID register) */
41
 /** SEND_CID - read the card identification information (CID register) */
42
 uint8_t const CMD10 = 0X0A;
42
 uint8_t const CMD10 = 0X0A;
43
+/** STOP_TRANSMISSION - end multiple block read sequence */
44
+uint8_t const CMD12 = 0X0C;
43
 /** SEND_STATUS - read the card status register */
45
 /** SEND_STATUS - read the card status register */
44
 uint8_t const CMD13 = 0X0D;
46
 uint8_t const CMD13 = 0X0D;
45
-/** READ_BLOCK - read a single data block from the card */
47
+/** READ_SINGLE_BLOCK - read a single data block from the card */
46
 uint8_t const CMD17 = 0X11;
48
 uint8_t const CMD17 = 0X11;
49
+/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
50
+uint8_t const CMD18 = 0X12;
47
 /** WRITE_BLOCK - write a single data block to the card */
51
 /** WRITE_BLOCK - write a single data block to the card */
48
 uint8_t const CMD24 = 0X18;
52
 uint8_t const CMD24 = 0X18;
49
 /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
53
 /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
83
 /** write data accepted token */
87
 /** write data accepted token */
84
 uint8_t const DATA_RES_ACCEPTED = 0X05;
88
 uint8_t const DATA_RES_ACCEPTED = 0X05;
85
 //------------------------------------------------------------------------------
89
 //------------------------------------------------------------------------------
90
+/** Card IDentification (CID) register */
86
 typedef struct CID {
91
 typedef struct CID {
87
   // byte 0
92
   // byte 0
88
-  uint8_t mid;  // Manufacturer ID
93
+  /** Manufacturer ID */
94
+  unsigned char mid;
89
   // byte 1-2
95
   // byte 1-2
90
-  char oid[2];  // OEM/Application ID
96
+  /** OEM/Application ID */
97
+  char oid[2];
91
   // byte 3-7
98
   // byte 3-7
92
-  char pnm[5];  // Product name
99
+  /** Product name */
100
+  char pnm[5];
93
   // byte 8
101
   // byte 8
94
-  unsigned prv_m : 4;  // Product revision n.m
95
-  unsigned prv_n : 4;
102
+  /** Product revision least significant digit */
103
+  unsigned char prv_m : 4;
104
+  /** Product revision most significant digit */
105
+  unsigned char prv_n : 4;
96
   // byte 9-12
106
   // byte 9-12
97
-  uint32_t psn;  // Product serial number
107
+  /** Product serial number */
108
+  uint32_t psn;
98
   // byte 13
109
   // byte 13
99
-  unsigned mdt_year_high : 4;  // Manufacturing date
100
-  unsigned reserved : 4;
110
+  /** Manufacturing date year low digit */
111
+  unsigned char mdt_year_high : 4;
112
+  /** not used */
113
+  unsigned char reserved : 4;
101
   // byte 14
114
   // byte 14
102
-  unsigned mdt_month : 4;
103
-  unsigned mdt_year_low :4;
115
+  /** Manufacturing date month */
116
+  unsigned char mdt_month : 4;
117
+  /** Manufacturing date year low digit */
118
+  unsigned char mdt_year_low :4;
104
   // byte 15
119
   // byte 15
105
-  unsigned always1 : 1;
106
-  unsigned crc : 7;
120
+  /** not used always 1 */
121
+  unsigned char always1 : 1;
122
+  /** CRC7 checksum */
123
+  unsigned char crc : 7;
107
 }cid_t;
124
 }cid_t;
108
 //------------------------------------------------------------------------------
125
 //------------------------------------------------------------------------------
109
-// CSD for version 1.00 cards
126
+/** CSD for version 1.00 cards */
110
 typedef struct CSDV1 {
127
 typedef struct CSDV1 {
111
   // byte 0
128
   // byte 0
112
-  unsigned reserved1 : 6;
113
-  unsigned csd_ver : 2;
129
+  unsigned char reserved1 : 6;
130
+  unsigned char csd_ver : 2;
114
   // byte 1
131
   // byte 1
115
-  uint8_t taac;
132
+  unsigned char taac;
116
   // byte 2
133
   // byte 2
117
-  uint8_t nsac;
134
+  unsigned char nsac;
118
   // byte 3
135
   // byte 3
119
-  uint8_t tran_speed;
136
+  unsigned char tran_speed;
120
   // byte 4
137
   // byte 4
121
-  uint8_t ccc_high;
138
+  unsigned char ccc_high;
122
   // byte 5
139
   // byte 5
123
-  unsigned read_bl_len : 4;
124
-  unsigned ccc_low : 4;
140
+  unsigned char read_bl_len : 4;
141
+  unsigned char ccc_low : 4;
125
   // byte 6
142
   // byte 6
126
-  unsigned c_size_high : 2;
127
-  unsigned reserved2 : 2;
128
-  unsigned dsr_imp : 1;
129
-  unsigned read_blk_misalign :1;
130
-  unsigned write_blk_misalign : 1;
131
-  unsigned read_bl_partial : 1;
143
+  unsigned char c_size_high : 2;
144
+  unsigned char reserved2 : 2;
145
+  unsigned char dsr_imp : 1;
146
+  unsigned char read_blk_misalign :1;
147
+  unsigned char write_blk_misalign : 1;
148
+  unsigned char read_bl_partial : 1;
132
   // byte 7
149
   // byte 7
133
-  uint8_t c_size_mid;
150
+  unsigned char c_size_mid;
134
   // byte 8
151
   // byte 8
135
-  unsigned vdd_r_curr_max : 3;
136
-  unsigned vdd_r_curr_min : 3;
137
-  unsigned c_size_low :2;
152
+  unsigned char vdd_r_curr_max : 3;
153
+  unsigned char vdd_r_curr_min : 3;
154
+  unsigned char c_size_low :2;
138
   // byte 9
155
   // byte 9
139
-  unsigned c_size_mult_high : 2;
140
-  unsigned vdd_w_cur_max : 3;
141
-  unsigned vdd_w_curr_min : 3;
156
+  unsigned char c_size_mult_high : 2;
157
+  unsigned char vdd_w_cur_max : 3;
158
+  unsigned char vdd_w_curr_min : 3;
142
   // byte 10
159
   // byte 10
143
-  unsigned sector_size_high : 6;
144
-  unsigned erase_blk_en : 1;
145
-  unsigned c_size_mult_low : 1;
160
+  unsigned char sector_size_high : 6;
161
+  unsigned char erase_blk_en : 1;
162
+  unsigned char c_size_mult_low : 1;
146
   // byte 11
163
   // byte 11
147
-  unsigned wp_grp_size : 7;
148
-  unsigned sector_size_low : 1;
164
+  unsigned char wp_grp_size : 7;
165
+  unsigned char sector_size_low : 1;
149
   // byte 12
166
   // byte 12
150
-  unsigned write_bl_len_high : 2;
151
-  unsigned r2w_factor : 3;
152
-  unsigned reserved3 : 2;
153
-  unsigned wp_grp_enable : 1;
167
+  unsigned char write_bl_len_high : 2;
168
+  unsigned char r2w_factor : 3;
169
+  unsigned char reserved3 : 2;
170
+  unsigned char wp_grp_enable : 1;
154
   // byte 13
171
   // byte 13
155
-  unsigned reserved4 : 5;
156
-  unsigned write_partial : 1;
157
-  unsigned write_bl_len_low : 2;
172
+  unsigned char reserved4 : 5;
173
+  unsigned char write_partial : 1;
174
+  unsigned char write_bl_len_low : 2;
158
   // byte 14
175
   // byte 14
159
-  unsigned reserved5: 2;
160
-  unsigned file_format : 2;
161
-  unsigned tmp_write_protect : 1;
162
-  unsigned perm_write_protect : 1;
163
-  unsigned copy : 1;
164
-  unsigned file_format_grp : 1;
176
+  unsigned char reserved5: 2;
177
+  unsigned char file_format : 2;
178
+  unsigned char tmp_write_protect : 1;
179
+  unsigned char perm_write_protect : 1;
180
+  unsigned char copy : 1;
181
+  /** Indicates the file format on the card */
182
+  unsigned char file_format_grp : 1;
165
   // byte 15
183
   // byte 15
166
-  unsigned always1 : 1;
167
-  unsigned crc : 7;
184
+  unsigned char always1 : 1;
185
+  unsigned char crc : 7;
168
 }csd1_t;
186
 }csd1_t;
169
 //------------------------------------------------------------------------------
187
 //------------------------------------------------------------------------------
170
-// CSD for version 2.00 cards
188
+/** CSD for version 2.00 cards */
171
 typedef struct CSDV2 {
189
 typedef struct CSDV2 {
172
   // byte 0
190
   // byte 0
173
-  unsigned reserved1 : 6;
174
-  unsigned csd_ver : 2;
191
+  unsigned char reserved1 : 6;
192
+  unsigned char csd_ver : 2;
175
   // byte 1
193
   // byte 1
176
-  uint8_t taac;
194
+  /** fixed to 0X0E */
195
+  unsigned char taac;
177
   // byte 2
196
   // byte 2
178
-  uint8_t nsac;
197
+  /** fixed to 0 */
198
+  unsigned char nsac;
179
   // byte 3
199
   // byte 3
180
-  uint8_t tran_speed;
200
+  unsigned char tran_speed;
181
   // byte 4
201
   // byte 4
182
-  uint8_t ccc_high;
202
+  unsigned char ccc_high;
183
   // byte 5
203
   // byte 5
184
-  unsigned read_bl_len : 4;
185
-  unsigned ccc_low : 4;
204
+  /** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
205
+  unsigned char read_bl_len : 4;
206
+  unsigned char ccc_low : 4;
186
   // byte 6
207
   // byte 6
187
-  unsigned reserved2 : 4;
188
-  unsigned dsr_imp : 1;
189
-  unsigned read_blk_misalign :1;
190
-  unsigned write_blk_misalign : 1;
191
-  unsigned read_bl_partial : 1;
208
+  /** not used */
209
+  unsigned char reserved2 : 4;
210
+  unsigned char dsr_imp : 1;
211
+  /** fixed to 0 */
212
+  unsigned char read_blk_misalign :1;
213
+  /** fixed to 0 */
214
+  unsigned char write_blk_misalign : 1;
215
+  /** fixed to 0 - no partial read */
216
+  unsigned char read_bl_partial : 1;
192
   // byte 7
217
   // byte 7
193
-  unsigned reserved3 : 2;
194
-  unsigned c_size_high : 6;
218
+  /** not used */
219
+  unsigned char reserved3 : 2;
220
+  /** high part of card size */
221
+  unsigned char c_size_high : 6;
195
   // byte 8
222
   // byte 8
196
-  uint8_t c_size_mid;
223
+  /** middle part of card size */
224
+  unsigned char c_size_mid;
197
   // byte 9
225
   // byte 9
198
-  uint8_t c_size_low;
226
+  /** low part of card size */
227
+  unsigned char c_size_low;
199
   // byte 10
228
   // byte 10
200
-  unsigned sector_size_high : 6;
201
-  unsigned erase_blk_en : 1;
202
-  unsigned reserved4 : 1;
229
+  /** sector size is fixed at 64 KB */
230
+  unsigned char sector_size_high : 6;
231
+  /** fixed to 1 - erase single is supported */
232
+  unsigned char erase_blk_en : 1;
233
+  /** not used */
234
+  unsigned char reserved4 : 1;
203
   // byte 11
235
   // byte 11
204
-  unsigned wp_grp_size : 7;
205
-  unsigned sector_size_low : 1;
236
+  unsigned char wp_grp_size : 7;
237
+  /** sector size is fixed at 64 KB */
238
+  unsigned char sector_size_low : 1;
206
   // byte 12
239
   // byte 12
207
-  unsigned write_bl_len_high : 2;
208
-  unsigned r2w_factor : 3;
209
-  unsigned reserved5 : 2;
210
-  unsigned wp_grp_enable : 1;
240
+  /** write_bl_len fixed for 512 byte blocks */
241
+  unsigned char write_bl_len_high : 2;
242
+  /** fixed value of 2 */
243
+  unsigned char r2w_factor : 3;
244
+  /** not used */
245
+  unsigned char reserved5 : 2;
246
+  /** fixed value of 0 - no write protect groups */
247
+  unsigned char wp_grp_enable : 1;
211
   // byte 13
248
   // byte 13
212
-  unsigned reserved6 : 5;
213
-  unsigned write_partial : 1;
214
-  unsigned write_bl_len_low : 2;
249
+  unsigned char reserved6 : 5;
250
+  /** always zero - no partial block read*/
251
+  unsigned char write_partial : 1;
252
+  /** write_bl_len fixed for 512 byte blocks */
253
+  unsigned char write_bl_len_low : 2;
215
   // byte 14
254
   // byte 14
216
-  unsigned reserved7: 2;
217
-  unsigned file_format : 2;
218
-  unsigned tmp_write_protect : 1;
219
-  unsigned perm_write_protect : 1;
220
-  unsigned copy : 1;
221
-  unsigned file_format_grp : 1;
255
+  unsigned char reserved7: 2;
256
+  /** Do not use always 0 */
257
+  unsigned char file_format : 2;
258
+  unsigned char tmp_write_protect : 1;
259
+  unsigned char perm_write_protect : 1;
260
+  unsigned char copy : 1;
261
+  /** Do not use always 0 */
262
+  unsigned char file_format_grp : 1;
222
   // byte 15
263
   // byte 15
223
-  unsigned always1 : 1;
224
-  unsigned crc : 7;
264
+  /** not used always 1 */
265
+  unsigned char always1 : 1;
266
+  /** checksum */
267
+  unsigned char crc : 7;
225
 }csd2_t;
268
 }csd2_t;
226
 //------------------------------------------------------------------------------
269
 //------------------------------------------------------------------------------
227
-// union of old and new style CSD register
270
+/** union of old and new style CSD register */
228
 union csd_t {
271
 union csd_t {
229
   csd1_t v1;
272
   csd1_t v1;
230
   csd2_t v2;
273
   csd2_t v2;

+ 192
- 86
Marlin/SdVolume.cpp View File

17
  * along with the Arduino SdFat Library.  If not, see
17
  * along with the Arduino SdFat Library.  If not, see
18
  * <http://www.gnu.org/licenses/>.
18
  * <http://www.gnu.org/licenses/>.
19
  */
19
  */
20
-#include "SdFat.h"
20
+#include "SdVolume.h"
21
 //------------------------------------------------------------------------------
21
 //------------------------------------------------------------------------------
22
+#if !USE_MULTIPLE_CARDS
22
 // raw block cache
23
 // raw block cache
23
-// init cacheBlockNumber_to invalid SD block number
24
-uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
25
-cache_t  SdVolume::cacheBuffer_;     // 512 byte cache for Sd2Card
26
-Sd2Card* SdVolume::sdCard_;          // pointer to SD card object
27
-uint8_t  SdVolume::cacheDirty_ = 0;  // cacheFlush() will write block if true
28
-uint32_t SdVolume::cacheMirrorBlock_ = 0;  // mirror  block for second FAT
24
+uint32_t SdVolume::cacheBlockNumber_;  // current block number
25
+cache_t  SdVolume::cacheBuffer_;       // 512 byte cache for Sd2Card
26
+Sd2Card* SdVolume::sdCard_;            // pointer to SD card object
27
+bool     SdVolume::cacheDirty_;        // cacheFlush() will write block if true
28
+uint32_t SdVolume::cacheMirrorBlock_;  // mirror  block for second FAT
29
+#endif  // USE_MULTIPLE_CARDS
29
 //------------------------------------------------------------------------------
30
 //------------------------------------------------------------------------------
30
 // find a contiguous group of clusters
31
 // find a contiguous group of clusters
31
-uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
32
+bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
32
   // start of group
33
   // start of group
33
   uint32_t bgnCluster;
34
   uint32_t bgnCluster;
35
+  // end of group
36
+  uint32_t endCluster;
37
+  // last cluster of FAT
38
+  uint32_t fatEnd = clusterCount_ + 1;
34
 
39
 
35
   // flag to save place to start next search
40
   // flag to save place to start next search
36
-  uint8_t setStart;
41
+  bool setStart;
37
 
42
 
38
   // set search start cluster
43
   // set search start cluster
39
   if (*curCluster) {
44
   if (*curCluster) {
47
     bgnCluster = allocSearchStart_;
52
     bgnCluster = allocSearchStart_;
48
 
53
 
49
     // save next search start if one cluster
54
     // save next search start if one cluster
50
-    setStart = 1 == count;
55
+    setStart = count == 1;
51
   }
56
   }
52
   // end of group
57
   // end of group
53
-  uint32_t endCluster = bgnCluster;
54
-
55
-  // last cluster of FAT
56
-  uint32_t fatEnd = clusterCount_ + 1;
58
+  endCluster = bgnCluster;
57
 
59
 
58
   // search the FAT for free clusters
60
   // search the FAT for free clusters
59
   for (uint32_t n = 0;; n++, endCluster++) {
61
   for (uint32_t n = 0;; n++, endCluster++) {
60
     // can't find space checked all clusters
62
     // can't find space checked all clusters
61
-    if (n >= clusterCount_) return false;
63
+    if (n >= clusterCount_) goto fail;
62
 
64
 
63
     // past end - start from beginning of FAT
65
     // past end - start from beginning of FAT
64
     if (endCluster > fatEnd) {
66
     if (endCluster > fatEnd) {
65
       bgnCluster = endCluster = 2;
67
       bgnCluster = endCluster = 2;
66
     }
68
     }
67
     uint32_t f;
69
     uint32_t f;
68
-    if (!fatGet(endCluster, &f)) return false;
70
+    if (!fatGet(endCluster, &f)) goto fail;
69
 
71
 
70
     if (f != 0) {
72
     if (f != 0) {
71
       // cluster in use try next cluster as bgnCluster
73
       // cluster in use try next cluster as bgnCluster
76
     }
78
     }
77
   }
79
   }
78
   // mark end of chain
80
   // mark end of chain
79
-  if (!fatPutEOC(endCluster)) return false;
81
+  if (!fatPutEOC(endCluster)) goto fail;
80
 
82
 
81
   // link clusters
83
   // link clusters
82
   while (endCluster > bgnCluster) {
84
   while (endCluster > bgnCluster) {
83
-    if (!fatPut(endCluster - 1, endCluster)) return false;
85
+    if (!fatPut(endCluster - 1, endCluster)) goto fail;
84
     endCluster--;
86
     endCluster--;
85
   }
87
   }
86
   if (*curCluster != 0) {
88
   if (*curCluster != 0) {
87
     // connect chains
89
     // connect chains
88
-    if (!fatPut(*curCluster, bgnCluster)) return false;
90
+    if (!fatPut(*curCluster, bgnCluster)) goto fail;
89
   }
91
   }
90
   // return first cluster number to caller
92
   // return first cluster number to caller
91
   *curCluster = bgnCluster;
93
   *curCluster = bgnCluster;
94
   if (setStart) allocSearchStart_ = bgnCluster + 1;
96
   if (setStart) allocSearchStart_ = bgnCluster + 1;
95
 
97
 
96
   return true;
98
   return true;
99
+
100
+ fail:
101
+  return false;
97
 }
102
 }
98
 //------------------------------------------------------------------------------
103
 //------------------------------------------------------------------------------
99
-uint8_t SdVolume::cacheFlush(void) {
104
+bool SdVolume::cacheFlush() {
100
   if (cacheDirty_) {
105
   if (cacheDirty_) {
101
     if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
106
     if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
102
-      return false;
107
+      goto fail;
103
     }
108
     }
104
     // mirror FAT tables
109
     // mirror FAT tables
105
     if (cacheMirrorBlock_) {
110
     if (cacheMirrorBlock_) {
106
       if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
111
       if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
107
-        return false;
112
+        goto fail;
108
       }
113
       }
109
       cacheMirrorBlock_ = 0;
114
       cacheMirrorBlock_ = 0;
110
     }
115
     }
111
     cacheDirty_ = 0;
116
     cacheDirty_ = 0;
112
   }
117
   }
113
   return true;
118
   return true;
119
+
120
+ fail:
121
+  return false;
114
 }
122
 }
115
 //------------------------------------------------------------------------------
123
 //------------------------------------------------------------------------------
116
-uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) {
124
+bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
117
   if (cacheBlockNumber_ != blockNumber) {
125
   if (cacheBlockNumber_ != blockNumber) {
118
-    if (!cacheFlush()) return false;
119
-    if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
126
+    if (!cacheFlush()) goto fail;
127
+    if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail;
120
     cacheBlockNumber_ = blockNumber;
128
     cacheBlockNumber_ = blockNumber;
121
   }
129
   }
122
-  cacheDirty_ |= action;
130
+  if (dirty) cacheDirty_ = true;
123
   return true;
131
   return true;
124
-}
125
-//------------------------------------------------------------------------------
126
-// cache a zero block for blockNumber
127
-uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) {
128
-  if (!cacheFlush()) return false;
129
 
132
 
130
-  // loop take less flash than memset(cacheBuffer_.data, 0, 512);
131
-  for (uint16_t i = 0; i < 512; i++) {
132
-    cacheBuffer_.data[i] = 0;
133
-  }
134
-  cacheBlockNumber_ = blockNumber;
135
-  cacheSetDirty();
136
-  return true;
133
+ fail:
134
+  return false;
137
 }
135
 }
138
 //------------------------------------------------------------------------------
136
 //------------------------------------------------------------------------------
139
 // return the size in bytes of a cluster chain
137
 // return the size in bytes of a cluster chain
140
-uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const {
138
+bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
141
   uint32_t s = 0;
139
   uint32_t s = 0;
142
   do {
140
   do {
143
-    if (!fatGet(cluster, &cluster)) return false;
141
+    if (!fatGet(cluster, &cluster)) goto fail;
144
     s += 512UL << clusterSizeShift_;
142
     s += 512UL << clusterSizeShift_;
145
   } while (!isEOC(cluster));
143
   } while (!isEOC(cluster));
146
   *size = s;
144
   *size = s;
147
   return true;
145
   return true;
146
+
147
+ fail:
148
+  return false;
148
 }
149
 }
149
 //------------------------------------------------------------------------------
150
 //------------------------------------------------------------------------------
150
 // Fetch a FAT entry
151
 // Fetch a FAT entry
151
-uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const {
152
-  if (cluster > (clusterCount_ + 1)) return false;
153
-  uint32_t lba = fatStartBlock_;
154
-  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
152
+bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
153
+  uint32_t lba;
154
+  if (cluster > (clusterCount_ + 1)) goto fail;
155
+  if (FAT12_SUPPORT && fatType_ == 12) {
156
+    uint16_t index = cluster;
157
+    index += index >> 1;
158
+    lba = fatStartBlock_ + (index >> 9);
159
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
160
+    index &= 0X1FF;
161
+    uint16_t tmp = cacheBuffer_.data[index];
162
+    index++;
163
+    if (index == 512) {
164
+      if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail;
165
+      index = 0;
166
+    }
167
+    tmp |= cacheBuffer_.data[index] << 8;
168
+    *value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
169
+    return true;
170
+  }
171
+  if (fatType_ == 16) {
172
+    lba = fatStartBlock_ + (cluster >> 8);
173
+  } else if (fatType_ == 32) {
174
+    lba = fatStartBlock_ + (cluster >> 7);
175
+  } else {
176
+    goto fail;
177
+  }
155
   if (lba != cacheBlockNumber_) {
178
   if (lba != cacheBlockNumber_) {
156
-    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
179
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
157
   }
180
   }
158
   if (fatType_ == 16) {
181
   if (fatType_ == 16) {
159
     *value = cacheBuffer_.fat16[cluster & 0XFF];
182
     *value = cacheBuffer_.fat16[cluster & 0XFF];
161
     *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
184
     *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
162
   }
185
   }
163
   return true;
186
   return true;
187
+
188
+ fail:
189
+  return false;
164
 }
190
 }
165
 //------------------------------------------------------------------------------
191
 //------------------------------------------------------------------------------
166
 // Store a FAT entry
192
 // Store a FAT entry
167
-uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) {
193
+bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
194
+  uint32_t lba;
168
   // error if reserved cluster
195
   // error if reserved cluster
169
-  if (cluster < 2) return false;
196
+  if (cluster < 2) goto fail;
170
 
197
 
171
   // error if not in FAT
198
   // error if not in FAT
172
-  if (cluster > (clusterCount_ + 1)) return false;
199
+  if (cluster > (clusterCount_ + 1)) goto fail;
173
 
200
 
174
-  // calculate block address for entry
175
-  uint32_t lba = fatStartBlock_;
176
-  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
177
-
178
-  if (lba != cacheBlockNumber_) {
179
-    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
201
+  if (FAT12_SUPPORT && fatType_ == 12) {
202
+    uint16_t index = cluster;
203
+    index += index >> 1;
204
+    lba = fatStartBlock_ + (index >> 9);
205
+    if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
206
+    // mirror second FAT
207
+    if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
208
+    index &= 0X1FF;
209
+    uint8_t tmp = value;
210
+    if (cluster & 1) {
211
+      tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
212
+    }
213
+    cacheBuffer_.data[index] = tmp;
214
+    index++;
215
+    if (index == 512) {
216
+      lba++;
217
+      index = 0;
218
+      if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
219
+      // mirror second FAT
220
+      if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
221
+    }
222
+    tmp = value >> 4;
223
+    if (!(cluster & 1)) {
224
+      tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4;
225
+    }
226
+    cacheBuffer_.data[index] = tmp;
227
+    return true;
180
   }
228
   }
229
+  if (fatType_ == 16) {
230
+    lba = fatStartBlock_ + (cluster >> 8);
231
+  } else if (fatType_ == 32) {
232
+    lba = fatStartBlock_ + (cluster >> 7);
233
+  } else {
234
+    goto fail;
235
+  }
236
+  if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
181
   // store entry
237
   // store entry
182
   if (fatType_ == 16) {
238
   if (fatType_ == 16) {
183
     cacheBuffer_.fat16[cluster & 0XFF] = value;
239
     cacheBuffer_.fat16[cluster & 0XFF] = value;
184
   } else {
240
   } else {
185
     cacheBuffer_.fat32[cluster & 0X7F] = value;
241
     cacheBuffer_.fat32[cluster & 0X7F] = value;
186
   }
242
   }
187
-  cacheSetDirty();
188
-
189
   // mirror second FAT
243
   // mirror second FAT
190
   if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
244
   if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
191
   return true;
245
   return true;
246
+
247
+ fail:
248
+  return false;
192
 }
249
 }
193
 //------------------------------------------------------------------------------
250
 //------------------------------------------------------------------------------
194
 // free a cluster chain
251
 // free a cluster chain
195
-uint8_t SdVolume::freeChain(uint32_t cluster) {
252
+bool SdVolume::freeChain(uint32_t cluster) {
253
+  uint32_t next;
254
+
196
   // clear free cluster location
255
   // clear free cluster location
197
   allocSearchStart_ = 2;
256
   allocSearchStart_ = 2;
198
 
257
 
199
   do {
258
   do {
200
-    uint32_t next;
201
-    if (!fatGet(cluster, &next)) return false;
259
+    if (!fatGet(cluster, &next)) goto fail;
202
 
260
 
203
     // free cluster
261
     // free cluster
204
-    if (!fatPut(cluster, 0)) return false;
262
+    if (!fatPut(cluster, 0)) goto fail;
205
 
263
 
206
     cluster = next;
264
     cluster = next;
207
   } while (!isEOC(cluster));
265
   } while (!isEOC(cluster));
208
 
266
 
209
   return true;
267
   return true;
268
+
269
+ fail:
270
+  return false;
271
+}
272
+//------------------------------------------------------------------------------
273
+/** Volume free space in clusters.
274
+ *
275
+ * \return Count of free clusters for success or -1 if an error occurs.
276
+ */
277
+int32_t SdVolume::freeClusterCount() {
278
+  uint32_t free = 0;
279
+  uint16_t n;
280
+  uint32_t todo = clusterCount_ + 2;
281
+
282
+  if (fatType_ == 16) {
283
+    n = 256;
284
+  } else if (fatType_ == 32) {
285
+    n = 128;
286
+  } else {
287
+    // put FAT12 here
288
+    return -1;
289
+  }
290
+
291
+  for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
292
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
293
+    if (todo < n) n = todo;
294
+    if (fatType_ == 16) {
295
+      for (uint16_t i = 0; i < n; i++) {
296
+        if (cacheBuffer_.fat16[i] == 0) free++;
297
+      }
298
+    } else {
299
+      for (uint16_t i = 0; i < n; i++) {
300
+        if (cacheBuffer_.fat32[i] == 0) free++;
301
+      }
302
+    }
303
+  }
304
+  return free;
210
 }
305
 }
211
 //------------------------------------------------------------------------------
306
 //------------------------------------------------------------------------------
212
-/**
213
- * Initialize a FAT volume.
307
+/** Initialize a FAT volume.
214
  *
308
  *
215
  * \param[in] dev The SD card where the volume is located.
309
  * \param[in] dev The SD card where the volume is located.
216
  *
310
  *
224
  * failure include not finding a valid partition, not finding a valid
318
  * failure include not finding a valid partition, not finding a valid
225
  * FAT file system in the specified partition or an I/O error.
319
  * FAT file system in the specified partition or an I/O error.
226
  */
320
  */
227
-uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) {
321
+bool SdVolume::init(Sd2Card* dev, uint8_t part) {
322
+  uint32_t totalBlocks;
228
   uint32_t volumeStartBlock = 0;
323
   uint32_t volumeStartBlock = 0;
324
+  fat32_boot_t* fbs;
325
+
229
   sdCard_ = dev;
326
   sdCard_ = dev;
327
+  fatType_ = 0;
328
+  allocSearchStart_ = 2;
329
+  cacheDirty_ = 0;  // cacheFlush() will write block if true
330
+  cacheMirrorBlock_ = 0;
331
+  cacheBlockNumber_ = 0XFFFFFFFF;
332
+
230
   // if part == 0 assume super floppy with FAT boot sector in block zero
333
   // if part == 0 assume super floppy with FAT boot sector in block zero
231
   // if part > 0 assume mbr volume with partition table
334
   // if part > 0 assume mbr volume with partition table
232
   if (part) {
335
   if (part) {
233
-    if (part > 4)return false;
234
-    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
336
+    if (part > 4)goto fail;
337
+    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
235
     part_t* p = &cacheBuffer_.mbr.part[part-1];
338
     part_t* p = &cacheBuffer_.mbr.part[part-1];
236
     if ((p->boot & 0X7F) !=0  ||
339
     if ((p->boot & 0X7F) !=0  ||
237
       p->totalSectors < 100 ||
340
       p->totalSectors < 100 ||
238
       p->firstSector == 0) {
341
       p->firstSector == 0) {
239
       // not a valid partition
342
       // not a valid partition
240
-      return false;
343
+      goto fail;
241
     }
344
     }
242
     volumeStartBlock = p->firstSector;
345
     volumeStartBlock = p->firstSector;
243
   }
346
   }
244
-  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
245
-  bpb_t* bpb = &cacheBuffer_.fbs.bpb;
246
-  if (bpb->bytesPerSector != 512 ||
247
-    bpb->fatCount == 0 ||
248
-    bpb->reservedSectorCount == 0 ||
249
-    bpb->sectorsPerCluster == 0) {
347
+  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
348
+  fbs = &cacheBuffer_.fbs32;
349
+  if (fbs->bytesPerSector != 512 ||
350
+    fbs->fatCount == 0 ||
351
+    fbs->reservedSectorCount == 0 ||
352
+    fbs->sectorsPerCluster == 0) {
250
        // not valid FAT volume
353
        // not valid FAT volume
251
-      return false;
354
+      goto fail;
252
   }
355
   }
253
-  fatCount_ = bpb->fatCount;
254
-  blocksPerCluster_ = bpb->sectorsPerCluster;
255
-
356
+  fatCount_ = fbs->fatCount;
357
+  blocksPerCluster_ = fbs->sectorsPerCluster;
256
   // determine shift that is same as multiply by blocksPerCluster_
358
   // determine shift that is same as multiply by blocksPerCluster_
257
   clusterSizeShift_ = 0;
359
   clusterSizeShift_ = 0;
258
   while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
360
   while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
259
     // error if not power of 2
361
     // error if not power of 2
260
-    if (clusterSizeShift_++ > 7) return false;
362
+    if (clusterSizeShift_++ > 7) goto fail;
261
   }
363
   }
262
-  blocksPerFat_ = bpb->sectorsPerFat16 ?
263
-                    bpb->sectorsPerFat16 : bpb->sectorsPerFat32;
364
+  blocksPerFat_ = fbs->sectorsPerFat16 ?
365
+                    fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
264
 
366
 
265
-  fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;
367
+  fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
266
 
368
 
267
   // count for FAT16 zero for FAT32
369
   // count for FAT16 zero for FAT32
268
-  rootDirEntryCount_ = bpb->rootDirEntryCount;
370
+  rootDirEntryCount_ = fbs->rootDirEntryCount;
269
 
371
 
270
   // directory start for FAT16 dataStart for FAT32
372
   // directory start for FAT16 dataStart for FAT32
271
-  rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;
373
+  rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
272
 
374
 
273
   // data start for FAT16 and FAT32
375
   // data start for FAT16 and FAT32
274
-  dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512);
376
+  dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511)/512);
275
 
377
 
276
   // total blocks for FAT16 or FAT32
378
   // total blocks for FAT16 or FAT32
277
-  uint32_t totalBlocks = bpb->totalSectors16 ?
278
-                           bpb->totalSectors16 : bpb->totalSectors32;
379
+  totalBlocks = fbs->totalSectors16 ?
380
+                           fbs->totalSectors16 : fbs->totalSectors32;
279
   // total data blocks
381
   // total data blocks
280
   clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
382
   clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
281
 
383
 
285
   // FAT type is determined by cluster count
387
   // FAT type is determined by cluster count
286
   if (clusterCount_ < 4085) {
388
   if (clusterCount_ < 4085) {
287
     fatType_ = 12;
389
     fatType_ = 12;
390
+    if (!FAT12_SUPPORT) goto fail;
288
   } else if (clusterCount_ < 65525) {
391
   } else if (clusterCount_ < 65525) {
289
     fatType_ = 16;
392
     fatType_ = 16;
290
   } else {
393
   } else {
291
-    rootDirStart_ = bpb->fat32RootCluster;
394
+    rootDirStart_ = fbs->fat32RootCluster;
292
     fatType_ = 32;
395
     fatType_ = 32;
293
   }
396
   }
294
   return true;
397
   return true;
398
+
399
+ fail:
400
+  return false;
295
 }
401
 }

+ 211
- 0
Marlin/SdVolume.h View File

1
+/* Arduino SdFat Library
2
+ * Copyright (C) 2009 by William Greiman
3
+ *
4
+ * This file is part of the Arduino SdFat Library
5
+ *
6
+ * This Library is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This Library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with the Arduino SdFat Library.  If not, see
18
+ * <http://www.gnu.org/licenses/>.
19
+ */
20
+#ifndef SdVolume_h
21
+#define SdVolume_h
22
+/**
23
+ * \file
24
+ * \brief SdVolume class
25
+ */
26
+#include "SdFatConfig.h"
27
+#include "Sd2Card.h"
28
+#include "SdFatStructs.h"
29
+
30
+//==============================================================================
31
+// SdVolume class
32
+/**
33
+ * \brief Cache for an SD data block
34
+ */
35
+union cache_t {
36
+           /** Used to access cached file data blocks. */
37
+  uint8_t  data[512];
38
+           /** Used to access cached FAT16 entries. */
39
+  uint16_t fat16[256];
40
+           /** Used to access cached FAT32 entries. */
41
+  uint32_t fat32[128];
42
+           /** Used to access cached directory entries. */
43
+  dir_t    dir[16];
44
+           /** Used to access a cached Master Boot Record. */
45
+  mbr_t    mbr;
46
+           /** Used to access to a cached FAT boot sector. */
47
+  fat_boot_t fbs;
48
+           /** Used to access to a cached FAT32 boot sector. */
49
+  fat32_boot_t fbs32;
50
+           /** Used to access to a cached FAT32 FSINFO sector. */
51
+  fat32_fsinfo_t fsinfo;
52
+};
53
+//------------------------------------------------------------------------------
54
+/**
55
+ * \class SdVolume
56
+ * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
57
+ */
58
+class SdVolume {
59
+ public:
60
+  /** Create an instance of SdVolume */
61
+  SdVolume() : fatType_(0) {}
62
+  /** Clear the cache and returns a pointer to the cache.  Used by the WaveRP
63
+   * recorder to do raw write to the SD card.  Not for normal apps.
64
+   * \return A pointer to the cache buffer or zero if an error occurs.
65
+   */
66
+  cache_t* cacheClear() {
67
+    if (!cacheFlush()) return 0;
68
+    cacheBlockNumber_ = 0XFFFFFFFF;
69
+    return &cacheBuffer_;
70
+  }
71
+  /** Initialize a FAT volume.  Try partition one first then try super
72
+   * floppy format.
73
+   *
74
+   * \param[in] dev The Sd2Card where the volume is located.
75
+   *
76
+   * \return The value one, true, is returned for success and
77
+   * the value zero, false, is returned for failure.  Reasons for
78
+   * failure include not finding a valid partition, not finding a valid
79
+   * FAT file system or an I/O error.
80
+   */
81
+  bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
82
+  bool init(Sd2Card* dev, uint8_t part);
83
+
84
+  // inline functions that return volume info
85
+  /** \return The volume's cluster size in blocks. */
86
+  uint8_t blocksPerCluster() const {return blocksPerCluster_;}
87
+  /** \return The number of blocks in one FAT. */
88
+  uint32_t blocksPerFat()  const {return blocksPerFat_;}
89
+  /** \return The total number of clusters in the volume. */
90
+  uint32_t clusterCount() const {return clusterCount_;}
91
+  /** \return The shift count required to multiply by blocksPerCluster. */
92
+  uint8_t clusterSizeShift() const {return clusterSizeShift_;}
93
+  /** \return The logical block number for the start of file data. */
94
+  uint32_t dataStartBlock() const {return dataStartBlock_;}
95
+  /** \return The number of FAT structures on the volume. */
96
+  uint8_t fatCount() const {return fatCount_;}
97
+  /** \return The logical block number for the start of the first FAT. */
98
+  uint32_t fatStartBlock() const {return fatStartBlock_;}
99
+  /** \return The FAT type of the volume. Values are 12, 16 or 32. */
100
+  uint8_t fatType() const {return fatType_;}
101
+  int32_t freeClusterCount();
102
+  /** \return The number of entries in the root directory for FAT16 volumes. */
103
+  uint32_t rootDirEntryCount() const {return rootDirEntryCount_;}
104
+  /** \return The logical block number for the start of the root directory
105
+       on FAT16 volumes or the first cluster number on FAT32 volumes. */
106
+  uint32_t rootDirStart() const {return rootDirStart_;}
107
+  /** Sd2Card object for this volume
108
+   * \return pointer to Sd2Card object.
109
+   */
110
+  Sd2Card* sdCard() {return sdCard_;}
111
+  /** Debug access to FAT table
112
+   *
113
+   * \param[in] n cluster number.
114
+   * \param[out] v value of entry
115
+   * \return true for success or false for failure
116
+   */
117
+  bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
118
+//------------------------------------------------------------------------------
119
+ private:
120
+  // Allow SdBaseFile access to SdVolume private data.
121
+  friend class SdBaseFile;
122
+
123
+  // value for dirty argument in cacheRawBlock to indicate read from cache
124
+  static bool const CACHE_FOR_READ = false;
125
+  // value for dirty argument in cacheRawBlock to indicate write to cache
126
+  static bool const CACHE_FOR_WRITE = true;
127
+
128
+#if USE_MULTIPLE_CARDS
129
+  cache_t cacheBuffer_;        // 512 byte cache for device blocks
130
+  uint32_t cacheBlockNumber_;  // Logical number of block in the cache
131
+  Sd2Card* sdCard_;            // Sd2Card object for cache
132
+  bool cacheDirty_;            // cacheFlush() will write block if true
133
+  uint32_t cacheMirrorBlock_;  // block number for mirror FAT
134
+#else  // USE_MULTIPLE_CARDS
135
+  static cache_t cacheBuffer_;        // 512 byte cache for device blocks
136
+  static uint32_t cacheBlockNumber_;  // Logical number of block in the cache
137
+  static Sd2Card* sdCard_;            // Sd2Card object for cache
138
+  static bool cacheDirty_;            // cacheFlush() will write block if true
139
+  static uint32_t cacheMirrorBlock_;  // block number for mirror FAT
140
+#endif  // USE_MULTIPLE_CARDS
141
+  uint32_t allocSearchStart_;   // start cluster for alloc search
142
+  uint8_t blocksPerCluster_;    // cluster size in blocks
143
+  uint32_t blocksPerFat_;       // FAT size in blocks
144
+  uint32_t clusterCount_;       // clusters in one FAT
145
+  uint8_t clusterSizeShift_;    // shift to convert cluster count to block count
146
+  uint32_t dataStartBlock_;     // first data block number
147
+  uint8_t fatCount_;            // number of FATs on volume
148
+  uint32_t fatStartBlock_;      // start block for first FAT
149
+  uint8_t fatType_;             // volume type (12, 16, OR 32)
150
+  uint16_t rootDirEntryCount_;  // number of entries in FAT16 root dir
151
+  uint32_t rootDirStart_;       // root start block for FAT16, cluster for FAT32
152
+  //----------------------------------------------------------------------------
153
+  bool allocContiguous(uint32_t count, uint32_t* curCluster);
154
+  uint8_t blockOfCluster(uint32_t position) const {
155
+          return (position >> 9) & (blocksPerCluster_ - 1);}
156
+  uint32_t clusterStartBlock(uint32_t cluster) const {
157
+           return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
158
+  uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
159
+           return clusterStartBlock(cluster) + blockOfCluster(position);}
160
+  cache_t *cache() {return &cacheBuffer_;}
161
+  uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
162
+#if USE_MULTIPLE_CARDS
163
+  bool cacheFlush();
164
+  bool cacheRawBlock(uint32_t blockNumber, bool dirty);
165
+#else  // USE_MULTIPLE_CARDS
166
+  static bool cacheFlush();
167
+  static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
168
+#endif  // USE_MULTIPLE_CARDS
169
+  // used by SdBaseFile write to assign cache to SD location
170
+  void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
171
+    cacheDirty_ = dirty;
172
+    cacheBlockNumber_  = blockNumber;
173
+  }
174
+  void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;}
175
+  bool chainSize(uint32_t beginCluster, uint32_t* size);
176
+  bool fatGet(uint32_t cluster, uint32_t* value);
177
+  bool fatPut(uint32_t cluster, uint32_t value);
178
+  bool fatPutEOC(uint32_t cluster) {
179
+    return fatPut(cluster, 0x0FFFFFFF);
180
+  }
181
+  bool freeChain(uint32_t cluster);
182
+  bool isEOC(uint32_t cluster) const {
183
+    if (FAT12_SUPPORT && fatType_ == 12) return  cluster >= FAT12EOC_MIN;
184
+    if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
185
+    return  cluster >= FAT32EOC_MIN;
186
+  }
187
+  bool readBlock(uint32_t block, uint8_t* dst) {
188
+    return sdCard_->readBlock(block, dst);}
189
+  bool writeBlock(uint32_t block, const uint8_t* dst) {
190
+    return sdCard_->writeBlock(block, dst);
191
+  }
192
+//------------------------------------------------------------------------------
193
+  // Deprecated functions  - suppress cpplint warnings with NOLINT comment
194
+#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
195
+ public:
196
+  /** \deprecated Use: bool SdVolume::init(Sd2Card* dev);
197
+   * \param[in] dev The SD card where the volume is located.
198
+   * \return true for success or false for failure.
199
+   */
200
+  bool init(Sd2Card& dev) {return init(&dev);}  // NOLINT
201
+  /** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
202
+   * \param[in] dev The SD card where the volume is located.
203
+   * \param[in] part The partition to be used.
204
+   * \return true for success or false for failure.
205
+   */
206
+  bool init(Sd2Card& dev, uint8_t part) {  // NOLINT
207
+    return init(&dev, part);
208
+  }
209
+#endif  // ALLOW_DEPRECATED_FUNCTIONS
210
+};
211
+#endif  // SdVolume

+ 1
- 0
Marlin/cardreader.h View File

3
 
3
 
4
 #ifdef SDSUPPORT
4
 #ifdef SDSUPPORT
5
  
5
  
6
+
6
 #include "SdFat.h"
7
 #include "SdFat.h"
7
 
8
 
8
 class CardReader
9
 class CardReader

+ 0
- 58
merging still needs.txt View File

1
-files to compare manually:
2
-planner.cpp
3
-stepper.cpp
4
-temperature.cpp
5
-
6
----
7
-things that changed:
8
-* planner.cpp
9
-estimate_acc_distance now works with floats.
10
-in calculate_trapezoid:for_block
11
- long acceleration_rate=(long)((float)acceleration*8.388608) is gone
12
- so is block_>acceleration_rate
13
-void planner_reverse_pass:
14
- some stuff I don't understand right now changed
15
-in planner_forward_pass:
16
- done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere.
17
-no more inline in void plan_discard_current_block()
18
-no more inline in plan_get_current_block()
19
-in plan_buffer_line(...)
20
- the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting.
21
-around if(feed_rate<minimumfeedrate) this only should be done if it is not a pure extrusion. I think there is a bug right now.
22
-~line 447 blockcount= 
23
- not sure if this also works if the difference is negative, as it would happen if the ringbuffer runs over the end and start at 0.
24
-~line 507 tmp_aceleration. not sure whats going on, but a lot changed.
25
-
26
-
27
-* stepper.cpp
28
-~214: if (busy) should be a echoln, maybe
29
-~331: great, The Z_M_PIN checks are in :)
30
-
31
-*temperature.cpp
32
-done: enum for heater, bed,
33
-manage_heater() is seriously different.
34
-  done: if tem_meas_ready ==true->!true+return?
35
-done #define K1 0.95 maybe in the configuration.h?
36
-semi-done: PID-C checking needed. Untested but added.
37
-----
38
-
39
-still needed to finish the merge, before testin!
40
-
41
- manage_heater
42
- ISR
43
- movement planner
44
-
45
-TODO:
46
-
47
-remove traveling at maxpseed
48
-remove Simplelcd
49
-
50
-remove DEBUG_STEPS?
51
-
52
-block_t
53
-pid_dt ->0.1  whats the changes to the PID, checking needed
54
-
55
-
56
-----
57
-second merge saturday morning:
58
-done: PID_dt->0.1

Loading…
Cancel
Save