Keep "astyled" elements in SD-related files
This commit is contained in:
@@ -23,131 +23,129 @@
|
||||
#include "Sd2Card.h"
|
||||
//------------------------------------------------------------------------------
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
// functions for hardware SPI
|
||||
//------------------------------------------------------------------------------
|
||||
// make sure SPCR rate is in expected bits
|
||||
#if (SPR0 != 0 || SPR1 != 1)
|
||||
#error unexpected SPCR bits
|
||||
#endif
|
||||
/**
|
||||
* Initialize hardware SPI
|
||||
* Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
|
||||
*/
|
||||
static void spiInit(uint8_t spiRate) {
|
||||
// See avr processor documentation
|
||||
SPCR = BIT(SPE) | BIT(MSTR) | (spiRate >> 1);
|
||||
SPSR = spiRate & 1 || spiRate == 6 ? 0 : BIT(SPI2X);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive a byte */
|
||||
static uint8_t spiRec() {
|
||||
SPDR = 0XFF;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
return SPDR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI read data - only one call so force inline */
|
||||
static inline __attribute__((always_inline))
|
||||
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
if (nbyte-- == 0) return;
|
||||
SPDR = 0XFF;
|
||||
for (uint16_t i = 0; i < nbyte; i++) {
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[i] = SPDR;
|
||||
// functions for hardware SPI
|
||||
//------------------------------------------------------------------------------
|
||||
// make sure SPCR rate is in expected bits
|
||||
#if (SPR0 != 0 || SPR1 != 1)
|
||||
#error unexpected SPCR bits
|
||||
#endif
|
||||
/**
|
||||
* Initialize hardware SPI
|
||||
* Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
|
||||
*/
|
||||
static void spiInit(uint8_t spiRate) {
|
||||
// See avr processor documentation
|
||||
SPCR = BIT(SPE) | BIT(MSTR) | (spiRate >> 1);
|
||||
SPSR = spiRate & 1 || spiRate == 6 ? 0 : BIT(SPI2X);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive a byte */
|
||||
static uint8_t spiRec() {
|
||||
SPDR = 0XFF;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
return SPDR;
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[nbyte] = SPDR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send a byte */
|
||||
static void spiSend(uint8_t b) {
|
||||
SPDR = b;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send block - only one call so force inline */
|
||||
static inline __attribute__((always_inline))
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI read data - only one call so force inline */
|
||||
static inline __attribute__((always_inline))
|
||||
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
if (nbyte-- == 0) return;
|
||||
SPDR = 0XFF;
|
||||
for (uint16_t i = 0; i < nbyte; i++) {
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[i] = SPDR;
|
||||
SPDR = 0XFF;
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[nbyte] = SPDR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send a byte */
|
||||
static void spiSend(uint8_t b) {
|
||||
SPDR = b;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send block - only one call so force inline */
|
||||
static inline __attribute__((always_inline))
|
||||
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
||||
SPDR = token;
|
||||
for (uint16_t i = 0; i < 512; i += 2) {
|
||||
SPDR = token;
|
||||
for (uint16_t i = 0; i < 512; i += 2) {
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i];
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i + 1];
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i];
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i + 1];
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
#else // SOFTWARE_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
/** nop to tune soft SPI timing */
|
||||
#define nop asm volatile ("nop\n\t")
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI receive byte */
|
||||
static uint8_t spiRec() {
|
||||
uint8_t data = 0;
|
||||
// no interrupts during byte receive - about 8 us
|
||||
cli();
|
||||
// output pin high - like sending 0XFF
|
||||
fastDigitalWrite(SPI_MOSI_PIN, HIGH);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
fastDigitalWrite(SPI_SCK_PIN, HIGH);
|
||||
|
||||
// adjust so SCK is nice
|
||||
//------------------------------------------------------------------------------
|
||||
/** nop to tune soft SPI timing */
|
||||
#define nop asm volatile ("nop\n\t")
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI receive byte */
|
||||
static uint8_t spiRec() {
|
||||
uint8_t data = 0;
|
||||
// no interrupts during byte receive - about 8 us
|
||||
cli();
|
||||
// output pin high - like sending 0XFF
|
||||
fastDigitalWrite(SPI_MOSI_PIN, HIGH);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
fastDigitalWrite(SPI_SCK_PIN, HIGH);
|
||||
|
||||
// adjust so SCK is nice
|
||||
nop;
|
||||
nop;
|
||||
|
||||
data <<= 1;
|
||||
|
||||
if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
|
||||
|
||||
fastDigitalWrite(SPI_SCK_PIN, LOW);
|
||||
}
|
||||
// enable interrupts
|
||||
sei();
|
||||
return data;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI read data */
|
||||
static void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
for (uint16_t i = 0; i < nbyte; i++)
|
||||
buf[i] = spiRec();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI send byte */
|
||||
static void spiSend(uint8_t data) {
|
||||
// no interrupts during byte send - about 8 us
|
||||
cli();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
fastDigitalWrite(SPI_SCK_PIN, LOW);
|
||||
|
||||
fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
|
||||
|
||||
data <<= 1;
|
||||
|
||||
fastDigitalWrite(SPI_SCK_PIN, HIGH);
|
||||
}
|
||||
// hold SCK high for a few ns
|
||||
nop;
|
||||
nop;
|
||||
|
||||
data <<= 1;
|
||||
|
||||
if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
|
||||
|
||||
nop;
|
||||
nop;
|
||||
|
||||
fastDigitalWrite(SPI_SCK_PIN, LOW);
|
||||
// enable interrupts
|
||||
sei();
|
||||
}
|
||||
// enable interrupts
|
||||
sei();
|
||||
return data;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI read data */
|
||||
static void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
for (uint16_t i = 0; i < nbyte; i++) {
|
||||
buf[i] = spiRec();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI send byte */
|
||||
static void spiSend(uint8_t data) {
|
||||
// no interrupts during byte send - about 8 us
|
||||
cli();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
fastDigitalWrite(SPI_SCK_PIN, LOW);
|
||||
|
||||
fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
|
||||
|
||||
data <<= 1;
|
||||
|
||||
fastDigitalWrite(SPI_SCK_PIN, HIGH);
|
||||
}
|
||||
// hold SCK high for a few ns
|
||||
nop;
|
||||
nop;
|
||||
nop;
|
||||
nop;
|
||||
|
||||
fastDigitalWrite(SPI_SCK_PIN, LOW);
|
||||
// enable interrupts
|
||||
sei();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI send block */
|
||||
//------------------------------------------------------------------------------
|
||||
/** Soft SPI send block */
|
||||
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
||||
spiSend(token);
|
||||
for (uint16_t i = 0; i < 512; i++) {
|
||||
spiSend(buf[i]);
|
||||
spiSend(token);
|
||||
for (uint16_t i = 0; i < 512; i++)
|
||||
spiSend(buf[i]);
|
||||
}
|
||||
}
|
||||
#endif // SOFTWARE_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
// send command and return error code. Return zero for OK
|
||||
@@ -209,9 +207,9 @@ void Sd2Card::chipSelectHigh() {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Sd2Card::chipSelectLow() {
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
digitalWrite(chipSelectPin_, LOW);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -246,10 +244,10 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
lastBlock <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD32, firstBlock)
|
||||
|| cardCommand(CMD33, lastBlock)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
|| cardCommand(CMD33, lastBlock)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
}
|
||||
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
@@ -257,8 +255,7 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
}
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -297,17 +294,17 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
||||
pinMode(SPI_MOSI_PIN, OUTPUT);
|
||||
pinMode(SPI_SCK_PIN, OUTPUT);
|
||||
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
// SS must be in output mode even it is not chip select
|
||||
pinMode(SS_PIN, OUTPUT);
|
||||
// set SS high - may be chip select for another SPI device
|
||||
#if SET_SPI_SS_HIGH
|
||||
digitalWrite(SS_PIN, HIGH);
|
||||
#endif // SET_SPI_SS_HIGH
|
||||
// set SCK rate for initialization commands
|
||||
spiRate_ = SPI_SD_INIT_RATE;
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
// SS must be in output mode even it is not chip select
|
||||
pinMode(SS_PIN, OUTPUT);
|
||||
// set SS high - may be chip select for another SPI device
|
||||
#if SET_SPI_SS_HIGH
|
||||
digitalWrite(SS_PIN, HIGH);
|
||||
#endif // SET_SPI_SS_HIGH
|
||||
// set SCK rate for initialization commands
|
||||
spiRate_ = SPI_SD_INIT_RATE;
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
|
||||
// must supply min of 74 clock cycles with CS high.
|
||||
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
|
||||
@@ -322,7 +319,8 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
||||
// check SD version
|
||||
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// only need last byte of r7 response
|
||||
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
|
||||
if (status_ != 0XAA) {
|
||||
@@ -353,13 +351,13 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
||||
}
|
||||
chipSelectHigh();
|
||||
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
return setSckRate(sckRateID);
|
||||
#else // SOFTWARE_SPI
|
||||
return true;
|
||||
#endif // SOFTWARE_SPI
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
return setSckRate(sckRateID);
|
||||
#else // SOFTWARE_SPI
|
||||
return true;
|
||||
#endif // SOFTWARE_SPI
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -376,28 +374,27 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
uint8_t retryCnt = 3;
|
||||
// use address if not SDHC card
|
||||
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
retry2:
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
retry2:
|
||||
retryCnt --;
|
||||
if (cardCommand(CMD17, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD17);
|
||||
if (retryCnt > 0) goto retry;
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 512))
|
||||
{
|
||||
if (!readData(dst, 512)) {
|
||||
if (retryCnt > 0) goto retry;
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
retry:
|
||||
chipSelectHigh();
|
||||
cardCommand(CMD12, 0);//Try sending a stop command, but ignore the result.
|
||||
errorCode_ = 0;
|
||||
goto retry2;
|
||||
retry:
|
||||
chipSelectHigh();
|
||||
cardCommand(CMD12, 0);//Try sending a stop command, but ignore the result.
|
||||
errorCode_ = 0;
|
||||
goto retry2;
|
||||
#else
|
||||
// use address if not SDHC card
|
||||
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (cardCommand(CMD17, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD17);
|
||||
goto fail;
|
||||
@@ -405,7 +402,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
|
||||
return readData(dst, 512);
|
||||
#endif
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -417,7 +414,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool Sd2Card::readData(uint8_t *dst) {
|
||||
bool Sd2Card::readData(uint8_t* dst) {
|
||||
chipSelectLow();
|
||||
return readData(dst, 512);
|
||||
}
|
||||
@@ -488,10 +485,9 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
||||
uint16_t calcCrc = CRC_CCITT(dst, count);
|
||||
uint16_t recvCrc = spiRec() << 8;
|
||||
recvCrc |= spiRec();
|
||||
if (calcCrc != recvCrc)
|
||||
{
|
||||
error(SD_CARD_ERROR_CRC);
|
||||
goto fail;
|
||||
if (calcCrc != recvCrc) {
|
||||
error(SD_CARD_ERROR_CRC);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -501,8 +497,7 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
||||
#endif
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -515,8 +510,7 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
||||
goto fail;
|
||||
}
|
||||
return readData(dst, 16);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -532,15 +526,14 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool Sd2Card::readStart(uint32_t blockNumber) {
|
||||
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (cardCommand(CMD18, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD18);
|
||||
goto fail;
|
||||
}
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -558,8 +551,7 @@ bool Sd2Card::readStop() {
|
||||
}
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -592,8 +584,7 @@ bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
|
||||
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -626,8 +617,7 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
||||
}
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -644,8 +634,7 @@ bool Sd2Card::writeData(const uint8_t* src) {
|
||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
error(SD_CARD_ERROR_WRITE_MULTIPLE);
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
@@ -664,8 +653,7 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -695,8 +683,7 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
|
||||
}
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
}
|
||||
@@ -713,8 +700,7 @@ bool Sd2Card::writeStop() {
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
|
||||
chipSelectHigh();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
chipSelectHigh();
|
||||
return false;
|
||||
|
@@ -118,35 +118,35 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))
|
||||
#define SOFTWARE_SPI
|
||||
#define SOFTWARE_SPI
|
||||
#elif USE_SOFTWARE_SPI
|
||||
#define SOFTWARE_SPI
|
||||
#define SOFTWARE_SPI
|
||||
#endif // MEGA_SOFT_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
// SPI pin definitions - do not edit here - change in SdFatConfig.h
|
||||
//
|
||||
#if DISABLED(SOFTWARE_SPI)
|
||||
// hardware pin defs
|
||||
/** The default chip select pin for the SD card is SS. */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SS_PIN;
|
||||
// The following three pins must not be redefined for hardware SPI.
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
uint8_t const SPI_MISO_PIN = MISO_PIN;
|
||||
/** SPI Clock pin */
|
||||
uint8_t const SPI_SCK_PIN = SCK_PIN;
|
||||
// hardware pin defs
|
||||
/** The default chip select pin for the SD card is SS. */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SS_PIN;
|
||||
// The following three pins must not be redefined for hardware SPI.
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
uint8_t const SPI_MISO_PIN = MISO_PIN;
|
||||
/** SPI Clock pin */
|
||||
uint8_t const SPI_SCK_PIN = SCK_PIN;
|
||||
|
||||
#else // SOFTWARE_SPI
|
||||
|
||||
/** SPI chip select pin */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
uint8_t const SPI_MISO_PIN = SOFT_SPI_MISO_PIN;
|
||||
/** SPI Clock pin */
|
||||
uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN;
|
||||
/** SPI chip select pin */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
uint8_t const SPI_MISO_PIN = SOFT_SPI_MISO_PIN;
|
||||
/** SPI Clock pin */
|
||||
uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN;
|
||||
#endif // SOFTWARE_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
@@ -178,12 +178,12 @@ class Sd2Card {
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
|
||||
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
|
||||
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
|
||||
bool readBlock(uint32_t block, uint8_t* dst);
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
* number and Manufacturing date.
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
@@ -203,7 +203,7 @@ class Sd2Card {
|
||||
bool readCSD(csd_t* csd) {
|
||||
return readRegister(CMD9, csd);
|
||||
}
|
||||
bool readData(uint8_t *dst);
|
||||
bool readData(uint8_t* dst);
|
||||
bool readStart(uint32_t blockNumber);
|
||||
bool readStop();
|
||||
bool setSckRate(uint8_t sckRateID);
|
||||
|
@@ -316,12 +316,12 @@ static const pin_map_t digitalPinMap[] = {
|
||||
};
|
||||
#elif defined(__AVR_ATmega1281__)
|
||||
// Waspmote
|
||||
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 41;
|
||||
uint8_t const SCL_PIN = 40;
|
||||
|
||||
|
||||
|
||||
|
||||
#undef MOSI_PIN
|
||||
#undef MISO_PIN
|
||||
// SPI port
|
||||
@@ -329,59 +329,59 @@ uint8_t const SS_PIN = 16; // B0
|
||||
uint8_t const MOSI_PIN = 11; // B2
|
||||
uint8_t const MISO_PIN = 12; // B3
|
||||
uint8_t const SCK_PIN = 10; // B1
|
||||
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||
{&DDRE, &PINE, &PORTE, 3}, // E3 2
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 3
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 4
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 5
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 6
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 7
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 8
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 9
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 10
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 11
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 12
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 13
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 14
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 15
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 16
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 17
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 19
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 20
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 22
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 23
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 24
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||
{&DDRE, &PINE, &PORTE, 2}, // E2 26
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 28
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 29
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 30
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 31
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 32
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 33
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 34
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 35
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 36
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 37
|
||||
{&DDRE, &PINE, &PORTE, 6}, // E6 38
|
||||
{&DDRE, &PINE, &PORTE, 7}, // E7 39
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 40
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 41
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 42
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 43
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 44
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 45
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 46
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 47
|
||||
{&DDRG, &PING, &PORTG, 2}, // G2 48
|
||||
{&DDRG, &PING, &PORTG, 1}, // G1 49
|
||||
{&DDRG, &PING, &PORTG, 0}, // G0 50
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||
{&DDRE, &PINE, &PORTE, 3}, // E3 2
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 3
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 4
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 5
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 6
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 7
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 8
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 9
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 10
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 11
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 12
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 13
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 14
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 15
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 16
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 17
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 19
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 20
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 22
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 23
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 24
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||
{&DDRE, &PINE, &PORTE, 2}, // E2 26
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 28
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 29
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 30
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 31
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 32
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 33
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 34
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 35
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 36
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 37
|
||||
{&DDRE, &PINE, &PORTE, 6}, // E6 38
|
||||
{&DDRE, &PINE, &PORTE, 7}, // E7 39
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 40
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 41
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 42
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 43
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 44
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 45
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 46
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 47
|
||||
{&DDRG, &PING, &PORTG, 2}, // G2 48
|
||||
{&DDRG, &PING, &PORTG, 1}, // G1 49
|
||||
{&DDRG, &PING, &PORTG, 0}, // G0 50
|
||||
};
|
||||
#else // defined(__AVR_ATmega1280__)
|
||||
#error unknown chip
|
||||
|
@@ -48,7 +48,7 @@ bool SdBaseFile::addCluster() {
|
||||
bool SdBaseFile::addDirCluster() {
|
||||
uint32_t block;
|
||||
// max folder size
|
||||
if (fileSize_/sizeof(dir_t) >= 0XFFFF) goto fail;
|
||||
if (fileSize_ / sizeof(dir_t) >= 0XFFFF) goto fail;
|
||||
|
||||
if (!addCluster()) goto fail;
|
||||
if (!vol_->cacheFlush()) goto fail;
|
||||
@@ -68,8 +68,7 @@ bool SdBaseFile::addDirCluster() {
|
||||
// Increase directory file size by cluster size
|
||||
fileSize_ += 512UL << vol_->clusterSizeShift_;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -78,8 +77,7 @@ bool SdBaseFile::addDirCluster() {
|
||||
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
|
||||
if (!vol_->cacheRawBlock(dirBlock_, action)) goto fail;
|
||||
return vol_->cache()->dir + dirIndex_;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -125,7 +123,7 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -147,7 +145,7 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
|
||||
*
|
||||
*/
|
||||
bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
|
||||
const char* path, uint32_t size) {
|
||||
const char* path, uint32_t size) {
|
||||
uint32_t count;
|
||||
// don't allow zero length file
|
||||
if (size == 0) goto fail;
|
||||
@@ -167,8 +165,7 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
|
||||
flags_ |= F_FILE_DIR_DIRTY;
|
||||
|
||||
return sync();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -191,8 +188,7 @@ bool SdBaseFile::dirEntry(dir_t* dir) {
|
||||
// copy to caller's struct
|
||||
memcpy(dir, p, sizeof(dir_t));
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -258,7 +254,8 @@ int16_t SdBaseFile::fgets(char* str, int16_t num, char* delim) {
|
||||
str[n++] = ch;
|
||||
if (!delim) {
|
||||
if (ch == '\n') break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (strchr(delim, ch)) break;
|
||||
}
|
||||
}
|
||||
@@ -318,11 +315,11 @@ void SdBaseFile::getpos(fpos_t* pos) {
|
||||
void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
|
||||
rewind();
|
||||
int8_t status;
|
||||
while ((status = lsPrintNext( flags, indent))) {
|
||||
while ((status = lsPrintNext(flags, indent))) {
|
||||
if (status > 1 && (flags & LS_R)) {
|
||||
uint16_t index = curPosition()/32 - 1;
|
||||
uint16_t index = curPosition() / 32 - 1;
|
||||
SdBaseFile s;
|
||||
if (s.open(this, index, O_READ)) s.ls( flags, indent + 2);
|
||||
if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
|
||||
seekSet(32 * (index + 1));
|
||||
}
|
||||
}
|
||||
@@ -330,7 +327,7 @@ void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
|
||||
//------------------------------------------------------------------------------
|
||||
// saves 32 bytes on stack for ls recursion
|
||||
// return 0 - EOF, 1 - normal file, or 2 - directory
|
||||
int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) {
|
||||
int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
|
||||
dir_t dir;
|
||||
uint8_t w = 0;
|
||||
|
||||
@@ -340,7 +337,7 @@ int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) {
|
||||
|
||||
// skip deleted entry and entries for . and ..
|
||||
if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
|
||||
&& DIR_IS_FILE_OR_SUBDIR(&dir)) break;
|
||||
&& DIR_IS_FILE_OR_SUBDIR(&dir)) break;
|
||||
}
|
||||
// indent for dir level
|
||||
for (uint8_t i = 0; i < indent; i++) MYSERIAL.write(' ');
|
||||
@@ -365,9 +362,9 @@ int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) {
|
||||
// print modify date/time if requested
|
||||
if (flags & LS_DATE) {
|
||||
MYSERIAL.write(' ');
|
||||
printFatDate( dir.lastWriteDate);
|
||||
printFatDate(dir.lastWriteDate);
|
||||
MYSERIAL.write(' ');
|
||||
printFatTime( dir.lastWriteTime);
|
||||
printFatTime(dir.lastWriteTime);
|
||||
}
|
||||
// print size if requested
|
||||
if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
|
||||
@@ -392,7 +389,8 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
|
||||
if (n == 10) goto fail; // only one dot allowed
|
||||
n = 10; // max index for full 8.3 name
|
||||
i = 8; // place for extension
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// illegal FAT characters
|
||||
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
|
||||
uint8_t b;
|
||||
@@ -400,14 +398,13 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
|
||||
// check size and only allow ASCII printable characters
|
||||
if (i > n || c < 0X21 || c > 0X7E)goto fail;
|
||||
// only upper case allowed in 8.3 names - convert lower to upper
|
||||
name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
|
||||
name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
|
||||
}
|
||||
}
|
||||
*ptr = str;
|
||||
// must have a file name, extension is optional
|
||||
return name[0] != ' ';
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -454,8 +451,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
|
||||
sub = parent != &dir1 ? &dir1 : &dir2;
|
||||
}
|
||||
return mkdir(parent, dname);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -503,7 +499,8 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
||||
if (parent->isRoot()) {
|
||||
d.firstClusterLow = 0;
|
||||
d.firstClusterHigh = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
d.firstClusterLow = parent->firstCluster_ & 0XFFFF;
|
||||
d.firstClusterHigh = parent->firstCluster_ >> 16;
|
||||
}
|
||||
@@ -512,24 +509,23 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
||||
|
||||
// write first block
|
||||
return vol_->cacheFlush();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Open a file in the current working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||
* OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::open(const char* path, uint8_t oflag) {
|
||||
return open(cwd_, path, oflag);
|
||||
}
|
||||
/** Open a file in the current working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||
* OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::open(const char* path, uint8_t oflag) {
|
||||
return open(cwd_, path, oflag);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Open a file or directory by name.
|
||||
*
|
||||
@@ -584,8 +580,8 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
||||
bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
|
||||
uint8_t dname[11];
|
||||
SdBaseFile dir1, dir2;
|
||||
SdBaseFile *parent = dirFile;
|
||||
SdBaseFile *sub = &dir1;
|
||||
SdBaseFile* parent = dirFile;
|
||||
SdBaseFile* sub = &dir1;
|
||||
|
||||
if (!dirFile) goto fail;
|
||||
|
||||
@@ -609,14 +605,13 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
|
||||
sub = parent != &dir1 ? &dir1 : &dir2;
|
||||
}
|
||||
return open(parent, dname, oflag);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// open with filename in dname
|
||||
bool SdBaseFile::open(SdBaseFile* dirFile,
|
||||
const uint8_t dname[11], uint8_t oflag) {
|
||||
const uint8_t dname[11], uint8_t oflag) {
|
||||
bool emptyFound = false;
|
||||
bool fileFound = false;
|
||||
uint8_t index;
|
||||
@@ -641,7 +636,8 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
||||
}
|
||||
// done if no entries follow
|
||||
if (p->name[0] == DIR_NAME_FREE) break;
|
||||
} else if (!memcmp(dname, p->name, 11)) {
|
||||
}
|
||||
else if (!memcmp(dname, p->name, 11)) {
|
||||
fileFound = true;
|
||||
break;
|
||||
}
|
||||
@@ -649,14 +645,16 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
||||
if (fileFound) {
|
||||
// don't open existing file if O_EXCL
|
||||
if (oflag & O_EXCL) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// don't create unless O_CREAT and O_WRITE
|
||||
if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) goto fail;
|
||||
if (emptyFound) {
|
||||
index = dirIndex_;
|
||||
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||
if (!p) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto fail;
|
||||
|
||||
// add and zero cluster for dirFile - first cluster is in cache for write
|
||||
@@ -674,7 +672,8 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
||||
if (dateTime_) {
|
||||
// call user date/time function
|
||||
dateTime_(&p->creationDate, &p->creationTime);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// use default date/time
|
||||
p->creationDate = FAT_DEFAULT_DATE;
|
||||
p->creationTime = FAT_DEFAULT_TIME;
|
||||
@@ -688,8 +687,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
|
||||
}
|
||||
// open entry in cache
|
||||
return openCachedEntry(index, oflag);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -731,8 +729,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
|
||||
}
|
||||
// open cached entry
|
||||
return openCachedEntry(index & 0XF, oflag);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -757,10 +754,12 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
||||
if (DIR_IS_FILE(p)) {
|
||||
fileSize_ = p->fileSize;
|
||||
type_ = FAT_FILE_TYPE_NORMAL;
|
||||
} else if (DIR_IS_SUBDIR(p)) {
|
||||
}
|
||||
else if (DIR_IS_SUBDIR(p)) {
|
||||
if (!vol_->chainSize(firstCluster_, &fileSize_)) goto fail;
|
||||
type_ = FAT_FILE_TYPE_SUBDIR;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
// save open flags for read/write
|
||||
@@ -771,8 +770,7 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
||||
curPosition_ = 0;
|
||||
if ((oflag & O_TRUNC) && !truncate(0)) return false;
|
||||
return oflag & O_AT_END ? seekEnd(0) : true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
type_ = FAT_FILE_TYPE_CLOSED;
|
||||
return false;
|
||||
}
|
||||
@@ -818,8 +816,7 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
||||
return openCachedEntry(index, oflag);
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -862,8 +859,9 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
||||
// '..' is pointer to first cluster of parent. open '../..' to find parent
|
||||
if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) {
|
||||
if (!file.openRoot(dir->volume())) goto fail;
|
||||
} else {
|
||||
if (!file.openCachedEntry(1, O_READ)) goto fail;
|
||||
}
|
||||
else if (!file.openCachedEntry(1, O_READ)) {
|
||||
goto fail;
|
||||
}
|
||||
// search for parent in '../..'
|
||||
do {
|
||||
@@ -872,9 +870,8 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
||||
c |= (uint32_t)entry.firstClusterHigh << 16;
|
||||
} while (c != cluster);
|
||||
// open parent
|
||||
return open(&file, file.curPosition()/32 - 1, O_READ);
|
||||
|
||||
fail:
|
||||
return open(&file, file.curPosition() / 32 - 1, O_READ);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -895,11 +892,13 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
|
||||
type_ = FAT_FILE_TYPE_ROOT_FIXED;
|
||||
firstCluster_ = 0;
|
||||
fileSize_ = 32 * vol->rootDirEntryCount();
|
||||
} else if (vol->fatType() == 32) {
|
||||
}
|
||||
else if (vol->fatType() == 32) {
|
||||
type_ = FAT_FILE_TYPE_ROOT32;
|
||||
firstCluster_ = vol->rootDirStart();
|
||||
if (!vol->chainSize(firstCluster_, &fileSize_)) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// volume is not initialized, invalid, or FAT12 without support
|
||||
return false;
|
||||
}
|
||||
@@ -915,8 +914,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
|
||||
dirBlock_ = 0;
|
||||
dirIndex_ = 0;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -940,7 +938,7 @@ int SdBaseFile::peek() {
|
||||
* \param[in] printSlash Print '/' after directory names if true.
|
||||
*/
|
||||
void SdBaseFile::printDirName(const dir_t& dir,
|
||||
uint8_t width, bool printSlash) {
|
||||
uint8_t width, bool printSlash) {
|
||||
uint8_t w = 0;
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
if (dir.name[i] == ' ')continue;
|
||||
@@ -962,7 +960,7 @@ void SdBaseFile::printDirName(const dir_t& dir,
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// print uint8_t with width 2
|
||||
static void print2u( uint8_t v) {
|
||||
static void print2u(uint8_t v) {
|
||||
if (v < 10) MYSERIAL.write('0');
|
||||
MYSERIAL.print(v, DEC);
|
||||
}
|
||||
@@ -985,9 +983,9 @@ static void print2u( uint8_t v) {
|
||||
void SdBaseFile::printFatDate(uint16_t fatDate) {
|
||||
MYSERIAL.print(FAT_YEAR(fatDate));
|
||||
MYSERIAL.write('-');
|
||||
print2u( FAT_MONTH(fatDate));
|
||||
print2u(FAT_MONTH(fatDate));
|
||||
MYSERIAL.write('-');
|
||||
print2u( FAT_DAY(fatDate));
|
||||
print2u(FAT_DAY(fatDate));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -998,12 +996,12 @@ void SdBaseFile::printFatDate(uint16_t fatDate) {
|
||||
* \param[in] pr Print stream for output.
|
||||
* \param[in] fatTime The time field from a directory entry.
|
||||
*/
|
||||
void SdBaseFile::printFatTime( uint16_t fatTime) {
|
||||
print2u( FAT_HOUR(fatTime));
|
||||
void SdBaseFile::printFatTime(uint16_t fatTime) {
|
||||
print2u(FAT_HOUR(fatTime));
|
||||
MYSERIAL.write(':');
|
||||
print2u( FAT_MINUTE(fatTime));
|
||||
print2u(FAT_MINUTE(fatTime));
|
||||
MYSERIAL.write(':');
|
||||
print2u( FAT_SECOND(fatTime));
|
||||
print2u(FAT_SECOND(fatTime));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Print a file's name to Serial
|
||||
@@ -1060,14 +1058,16 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
||||
offset = curPosition_ & 0X1FF; // offset in block
|
||||
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
||||
block = vol_->rootDirStart() + (curPosition_ >> 9);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
|
||||
if (offset == 0 && blockOfCluster == 0) {
|
||||
// start of new cluster
|
||||
if (curPosition_ == 0) {
|
||||
// use first cluster in file
|
||||
curCluster_ = firstCluster_;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// get next cluster from FAT
|
||||
if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail;
|
||||
}
|
||||
@@ -1082,7 +1082,8 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
||||
// no buffering needed if n == 512
|
||||
if (n == 512 && block != vol_->cacheBlockNumber()) {
|
||||
if (!vol_->readBlock(block, dst)) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// read block to cache and copy data to caller
|
||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto fail;
|
||||
uint8_t* src = vol_->cache()->data + offset;
|
||||
@@ -1093,8 +1094,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
||||
toRead -= n;
|
||||
}
|
||||
return nbyte;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1131,15 +1131,15 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
|
||||
// Fill the long filename if we have a long filename entry.
|
||||
// Long filename entries are stored before the short filename.
|
||||
if (longFilename != NULL && DIR_IS_LONG_NAME(dir)) {
|
||||
vfat_t *VFAT = (vfat_t*)dir;
|
||||
vfat_t* VFAT = (vfat_t*)dir;
|
||||
// Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
|
||||
if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES) {
|
||||
// TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table.
|
||||
n = ((VFAT->sequenceNumber & 0x1F) - 1) * FILENAME_LENGTH;
|
||||
for (uint8_t i=0; i<FILENAME_LENGTH; i++)
|
||||
longFilename[n+i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i-5] : VFAT->name3[i-11];
|
||||
for (uint8_t i = 0; i < FILENAME_LENGTH; i++)
|
||||
longFilename[n + i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i - 5] : VFAT->name3[i - 11];
|
||||
// If this VFAT entry is the last one, add a NUL terminator at the end of the string
|
||||
if (VFAT->sequenceNumber & 0x40) longFilename[n+FILENAME_LENGTH] = '\0';
|
||||
if (VFAT->sequenceNumber & 0x40) longFilename[n + FILENAME_LENGTH] = '\0';
|
||||
}
|
||||
}
|
||||
// Return if normal file or subdirectory
|
||||
@@ -1166,8 +1166,7 @@ dir_t* SdBaseFile::readDirCache() {
|
||||
|
||||
// return pointer to entry
|
||||
return vol_->cache()->dir + i;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1202,8 +1201,7 @@ bool SdBaseFile::remove() {
|
||||
// write entry to SD
|
||||
return vol_->cacheFlush();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1228,8 +1226,7 @@ bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
|
||||
SdBaseFile file;
|
||||
if (!file.open(dirFile, path, O_WRITE)) goto fail;
|
||||
return file.remove();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
// can't set iostate - static function
|
||||
return false;
|
||||
}
|
||||
@@ -1272,7 +1269,8 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
|
||||
if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) {
|
||||
goto restore;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// don't create missing path prefix components
|
||||
if (!file.mkdir(dirFile, newPath, false)) {
|
||||
goto restore;
|
||||
@@ -1311,14 +1309,14 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
|
||||
}
|
||||
return vol_->cacheFlush();
|
||||
|
||||
restore:
|
||||
restore:
|
||||
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
||||
if (!d) goto fail;
|
||||
// restore entry
|
||||
d->name[0] = entry.name[0];
|
||||
vol_->cacheFlush();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1358,8 +1356,7 @@ bool SdBaseFile::rmdir() {
|
||||
type_ = FAT_FILE_TYPE_NORMAL;
|
||||
flags_ |= O_WRITE;
|
||||
return remove();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1384,7 +1381,7 @@ bool SdBaseFile::rmRfStar() {
|
||||
rewind();
|
||||
while (curPosition_ < fileSize_) {
|
||||
// remember position
|
||||
index = curPosition_/32;
|
||||
index = curPosition_ / 32;
|
||||
|
||||
dir_t* p = readDirCache();
|
||||
if (!p) goto fail;
|
||||
@@ -1402,14 +1399,15 @@ bool SdBaseFile::rmRfStar() {
|
||||
if (f.isSubDir()) {
|
||||
// recursively delete
|
||||
if (!f.rmRfStar()) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// ignore read-only
|
||||
f.flags_ |= O_WRITE;
|
||||
if (!f.remove()) goto fail;
|
||||
}
|
||||
// position to next entry if required
|
||||
if (curPosition_ != (32*(index + 1))) {
|
||||
if (!seekSet(32*(index + 1))) goto fail;
|
||||
if (curPosition_ != (32 * (index + 1))) {
|
||||
if (!seekSet(32 * (index + 1))) goto fail;
|
||||
}
|
||||
}
|
||||
// don't try to delete root
|
||||
@@ -1417,8 +1415,7 @@ bool SdBaseFile::rmRfStar() {
|
||||
if (!rmdir()) goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1465,7 +1462,8 @@ bool SdBaseFile::seekSet(uint32_t pos) {
|
||||
if (nNew < nCur || curPosition_ == 0) {
|
||||
// must follow chain from first cluster
|
||||
curCluster_ = firstCluster_;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// advance from curPosition
|
||||
nNew -= nCur;
|
||||
}
|
||||
@@ -1474,10 +1472,10 @@ bool SdBaseFile::seekSet(uint32_t pos) {
|
||||
}
|
||||
curPosition_ = pos;
|
||||
|
||||
done:
|
||||
done:
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1520,7 +1518,7 @@ bool SdBaseFile::sync() {
|
||||
}
|
||||
return vol_->cacheFlush();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
writeError = true;
|
||||
return false;
|
||||
}
|
||||
@@ -1560,7 +1558,7 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
|
||||
// write back entry
|
||||
return vol_->cacheFlush();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1598,22 +1596,22 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
||||
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
uint16_t dirDate;
|
||||
uint16_t dirTime;
|
||||
dir_t* d;
|
||||
|
||||
if (!isOpen()
|
||||
|| year < 1980
|
||||
|| year > 2107
|
||||
|| month < 1
|
||||
|| month > 12
|
||||
|| day < 1
|
||||
|| day > 31
|
||||
|| hour > 23
|
||||
|| minute > 59
|
||||
|| second > 59) {
|
||||
goto fail;
|
||||
|| year < 1980
|
||||
|| year > 2107
|
||||
|| month < 1
|
||||
|| month > 12
|
||||
|| day < 1
|
||||
|| day > 31
|
||||
|| hour > 23
|
||||
|| minute > 59
|
||||
|| second > 59) {
|
||||
goto fail;
|
||||
}
|
||||
// update directory entry
|
||||
if (!sync()) goto fail;
|
||||
@@ -1637,8 +1635,7 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
||||
d->lastWriteTime = dirTime;
|
||||
}
|
||||
return vol_->cacheFlush();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1674,7 +1671,8 @@ bool SdBaseFile::truncate(uint32_t length) {
|
||||
// free all clusters
|
||||
if (!vol_->freeChain(firstCluster_)) goto fail;
|
||||
firstCluster_ = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint32_t toFree;
|
||||
if (!vol_->fatGet(curCluster_, &toFree)) goto fail;
|
||||
|
||||
@@ -1696,7 +1694,7 @@ bool SdBaseFile::truncate(uint32_t length) {
|
||||
// set file to correct position
|
||||
return seekSet(newPos);
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1739,16 +1737,19 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
if (firstCluster_ == 0) {
|
||||
// allocate first cluster of file
|
||||
if (!addCluster()) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
curCluster_ = firstCluster_;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint32_t next;
|
||||
if (!vol_->fatGet(curCluster_, &next)) goto fail;
|
||||
if (vol_->isEOC(next)) {
|
||||
// add cluster if at end of chain
|
||||
if (!addCluster()) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
curCluster_ = next;
|
||||
}
|
||||
}
|
||||
@@ -1768,13 +1769,15 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
vol_->cacheSetBlockNumber(0XFFFFFFFF, false);
|
||||
}
|
||||
if (!vol_->writeBlock(block, src)) goto fail;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (blockOffset == 0 && curPosition_ >= fileSize_) {
|
||||
// start of new block don't need to read into cache
|
||||
if (!vol_->cacheFlush()) goto fail;
|
||||
// set cache dirty and SD address of block
|
||||
vol_->cacheSetBlockNumber(block, true);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// rewrite part of block
|
||||
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail;
|
||||
}
|
||||
@@ -1789,7 +1792,8 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
// update fileSize and insure sync will update dir entry
|
||||
fileSize_ = curPosition_;
|
||||
flags_ |= F_FILE_DIR_DIRTY;
|
||||
} else if (dateTime_ && nbyte) {
|
||||
}
|
||||
else if (dateTime_ && nbyte) {
|
||||
// insure sync will update modified date and time
|
||||
flags_ |= F_FILE_DIR_DIRTY;
|
||||
}
|
||||
@@ -1799,7 +1803,7 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
}
|
||||
return nbyte;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
// return for write error
|
||||
writeError = true;
|
||||
return -1;
|
||||
@@ -1807,7 +1811,7 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
//------------------------------------------------------------------------------
|
||||
// suppress cpplint warnings with NOLINT comment
|
||||
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
||||
void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
|
||||
void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
|
||||
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
||||
|
||||
|
||||
|
@@ -158,7 +158,7 @@ static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
||||
* \return Extracted minute [0,59]
|
||||
*/
|
||||
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||
return(fatTime >> 5) & 0X3F;
|
||||
return (fatTime >> 5) & 0X3F;
|
||||
}
|
||||
/** second part of FAT directory time field
|
||||
* Note second/2 is stored in packed time.
|
||||
@@ -168,7 +168,7 @@ static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||
* \return Extracted second [0,58]
|
||||
*/
|
||||
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
||||
return 2*(fatTime & 0X1F);
|
||||
return 2 * (fatTime & 0X1F);
|
||||
}
|
||||
/** Default date for file timestamps is 1 Jan 2000 */
|
||||
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
||||
@@ -184,7 +184,7 @@ class SdBaseFile {
|
||||
/** Create an instance. */
|
||||
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
|
||||
SdBaseFile(const char* path, uint8_t oflag);
|
||||
~SdBaseFile() {if(isOpen()) close();}
|
||||
~SdBaseFile() {if (isOpen()) close();}
|
||||
/**
|
||||
* writeError is set to true if an error occurs during a write().
|
||||
* Set writeError to false before calling print() and/or write() and check
|
||||
@@ -205,7 +205,7 @@ class SdBaseFile {
|
||||
bool close();
|
||||
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
||||
bool createContiguous(SdBaseFile* dirFile,
|
||||
const char* path, uint32_t size);
|
||||
const char* path, uint32_t size);
|
||||
/** \return The current cluster number for a file or directory. */
|
||||
uint32_t curCluster() const {return curCluster_;}
|
||||
/** \return The current position for a file or directory. */
|
||||
@@ -266,7 +266,7 @@ class SdBaseFile {
|
||||
bool isRoot() const {
|
||||
return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
|
||||
}
|
||||
void ls( uint8_t flags = 0, uint8_t indent = 0);
|
||||
void ls(uint8_t flags = 0, uint8_t indent = 0);
|
||||
bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
|
||||
// alias for backward compactability
|
||||
bool makeDir(SdBaseFile* dir, const char* path) {
|
||||
@@ -279,7 +279,7 @@ class SdBaseFile {
|
||||
bool openRoot(SdVolume* vol);
|
||||
int peek();
|
||||
static void printFatDate(uint16_t fatDate);
|
||||
static void printFatTime( uint16_t fatTime);
|
||||
static void printFatTime(uint16_t fatTime);
|
||||
bool printName();
|
||||
int16_t read();
|
||||
int16_t read(void* buf, uint16_t nbyte);
|
||||
@@ -309,7 +309,7 @@ class SdBaseFile {
|
||||
bool sync();
|
||||
bool timestamp(SdBaseFile* file);
|
||||
bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
|
||||
uint8_t hour, uint8_t minute, uint8_t second);
|
||||
uint8_t hour, uint8_t minute, uint8_t second);
|
||||
/** Type of file. You should use isFile() or isDir() instead of type()
|
||||
* if possible.
|
||||
*
|
||||
@@ -320,7 +320,7 @@ class SdBaseFile {
|
||||
/** \return SdVolume that contains this file. */
|
||||
SdVolume* volume() const {return vol_;}
|
||||
int16_t write(const void* buf, uint16_t nbyte);
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
// allow SdFat to set cwd_
|
||||
friend class SdFat;
|
||||
@@ -352,18 +352,18 @@ class SdBaseFile {
|
||||
bool addCluster();
|
||||
bool addDirCluster();
|
||||
dir_t* cacheDirEntry(uint8_t action);
|
||||
int8_t lsPrintNext( uint8_t flags, uint8_t indent);
|
||||
int8_t lsPrintNext(uint8_t flags, uint8_t indent);
|
||||
static bool make83Name(const char* str, uint8_t* name, const char** ptr);
|
||||
bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
|
||||
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
|
||||
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
|
||||
dir_t* readDirCache();
|
||||
//------------------------------------------------------------------------------
|
||||
// to be deleted
|
||||
static void printDirName( const dir_t& dir,
|
||||
uint8_t width, bool printSlash);
|
||||
//------------------------------------------------------------------------------
|
||||
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
||||
//------------------------------------------------------------------------------
|
||||
// to be deleted
|
||||
static void printDirName(const dir_t& dir,
|
||||
uint8_t width, bool printSlash);
|
||||
//------------------------------------------------------------------------------
|
||||
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
||||
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
||||
public:
|
||||
/** \deprecated Use:
|
||||
@@ -375,16 +375,16 @@ class SdBaseFile {
|
||||
bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
|
||||
return contiguousRange(&bgnBlock, &endBlock);
|
||||
}
|
||||
/** \deprecated Use:
|
||||
* bool createContiguous(SdBaseFile* dirFile,
|
||||
* const char* path, uint32_t size)
|
||||
* \param[in] dirFile The directory where the file will be created.
|
||||
* \param[in] path A path with a valid DOS 8.3 file name.
|
||||
* \param[in] size The desired file size.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
/** \deprecated Use:
|
||||
* bool createContiguous(SdBaseFile* dirFile,
|
||||
* const char* path, uint32_t size)
|
||||
* \param[in] dirFile The directory where the file will be created.
|
||||
* \param[in] path A path with a valid DOS 8.3 file name.
|
||||
* \param[in] size The desired file size.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool createContiguous(SdBaseFile& dirFile, // NOLINT
|
||||
const char* path, uint32_t size) {
|
||||
const char* path, uint32_t size) {
|
||||
return createContiguous(&dirFile, path, size);
|
||||
}
|
||||
/** \deprecated Use:
|
||||
@@ -422,7 +422,7 @@ class SdBaseFile {
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool open(SdBaseFile& dirFile, // NOLINT
|
||||
const char* path, uint8_t oflag) {
|
||||
const char* path, uint8_t oflag) {
|
||||
return open(&dirFile, path, oflag);
|
||||
}
|
||||
/** \deprecated Do not use in new apps
|
||||
@@ -465,8 +465,8 @@ class SdBaseFile {
|
||||
static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
|
||||
return remove(&dirFile, path);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// rest are private
|
||||
//------------------------------------------------------------------------------
|
||||
// rest are private
|
||||
private:
|
||||
static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
|
||||
static void oldToNew(uint16_t* date, uint16_t* time) {
|
||||
|
@@ -25,100 +25,100 @@
|
||||
#if ENABLED(SDSUPPORT)
|
||||
|
||||
#ifndef SdFatConfig_h
|
||||
#define SdFatConfig_h
|
||||
#include <stdint.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
|
||||
*
|
||||
* Using multiple cards costs 400 - 500 bytes of flash.
|
||||
*
|
||||
* Each card requires about 550 bytes of SRAM so use of a Mega is recommended.
|
||||
*/
|
||||
#define USE_MULTIPLE_CARDS 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Call flush for endl if ENDL_CALLS_FLUSH is nonzero
|
||||
*
|
||||
* The standard for iostreams is to call flush. This is very costly for
|
||||
* SdFat. Each call to flush causes 2048 bytes of I/O to the SD.
|
||||
*
|
||||
* SdFat has a single 512 byte buffer for SD I/O so it must write the current
|
||||
* data block to the SD, read the directory block from the SD, update the
|
||||
* directory entry, write the directory block to the SD and read the data
|
||||
* block back into the buffer.
|
||||
*
|
||||
* The SD flash memory controller is not designed for this many rewrites
|
||||
* so performance may be reduced by more than a factor of 100.
|
||||
*
|
||||
* If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
|
||||
* all data to be written to the SD.
|
||||
*/
|
||||
#define ENDL_CALLS_FLUSH 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
|
||||
*/
|
||||
#define ALLOW_DEPRECATED_FUNCTIONS 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
|
||||
* FAT12 has not been well tested.
|
||||
*/
|
||||
#define FAT12_SUPPORT 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
|
||||
* or 6 (F_CPU/128).
|
||||
*/
|
||||
#define SPI_SD_INIT_RATE 5
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set the SS pin high for hardware SPI. If SS is chip select for another SPI
|
||||
* device this will disable that device during the SD init phase.
|
||||
*/
|
||||
#define SET_SPI_SS_HIGH 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
|
||||
* Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
|
||||
*
|
||||
* MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
|
||||
* on Mega Arduinos. Software SPI works well with GPS Shield V1.1
|
||||
* but many SD cards will fail with GPS Shield V1.0.
|
||||
*/
|
||||
#define MEGA_SOFT_SPI 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_SOFTWARE_SPI nonzero to always use software SPI.
|
||||
*/
|
||||
#define USE_SOFTWARE_SPI 0
|
||||
// define software SPI pins so Mega can use unmodified 168/328 shields
|
||||
/** Software SPI chip select pin for the SD */
|
||||
uint8_t const SOFT_SPI_CS_PIN = 10;
|
||||
/** Software SPI Master Out Slave In pin */
|
||||
uint8_t const SOFT_SPI_MOSI_PIN = 11;
|
||||
/** Software SPI Master In Slave Out pin */
|
||||
uint8_t const SOFT_SPI_MISO_PIN = 12;
|
||||
/** Software SPI Clock pin */
|
||||
uint8_t const SOFT_SPI_SCK_PIN = 13;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* The __cxa_pure_virtual function is an error handler that is invoked when
|
||||
* a pure virtual function is called.
|
||||
*/
|
||||
#define USE_CXA_PURE_VIRTUAL 1
|
||||
#define SdFatConfig_h
|
||||
#include <stdint.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
|
||||
*
|
||||
* Using multiple cards costs 400 - 500 bytes of flash.
|
||||
*
|
||||
* Each card requires about 550 bytes of SRAM so use of a Mega is recommended.
|
||||
*/
|
||||
#define USE_MULTIPLE_CARDS 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Call flush for endl if ENDL_CALLS_FLUSH is nonzero
|
||||
*
|
||||
* The standard for iostreams is to call flush. This is very costly for
|
||||
* SdFat. Each call to flush causes 2048 bytes of I/O to the SD.
|
||||
*
|
||||
* SdFat has a single 512 byte buffer for SD I/O so it must write the current
|
||||
* data block to the SD, read the directory block from the SD, update the
|
||||
* directory entry, write the directory block to the SD and read the data
|
||||
* block back into the buffer.
|
||||
*
|
||||
* The SD flash memory controller is not designed for this many rewrites
|
||||
* so performance may be reduced by more than a factor of 100.
|
||||
*
|
||||
* If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
|
||||
* all data to be written to the SD.
|
||||
*/
|
||||
#define ENDL_CALLS_FLUSH 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
|
||||
*/
|
||||
#define ALLOW_DEPRECATED_FUNCTIONS 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
|
||||
* FAT12 has not been well tested.
|
||||
*/
|
||||
#define FAT12_SUPPORT 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
|
||||
* or 6 (F_CPU/128).
|
||||
*/
|
||||
#define SPI_SD_INIT_RATE 5
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set the SS pin high for hardware SPI. If SS is chip select for another SPI
|
||||
* device this will disable that device during the SD init phase.
|
||||
*/
|
||||
#define SET_SPI_SS_HIGH 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
|
||||
* Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
|
||||
*
|
||||
* MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
|
||||
* on Mega Arduinos. Software SPI works well with GPS Shield V1.1
|
||||
* but many SD cards will fail with GPS Shield V1.0.
|
||||
*/
|
||||
#define MEGA_SOFT_SPI 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_SOFTWARE_SPI nonzero to always use software SPI.
|
||||
*/
|
||||
#define USE_SOFTWARE_SPI 0
|
||||
// define software SPI pins so Mega can use unmodified 168/328 shields
|
||||
/** Software SPI chip select pin for the SD */
|
||||
uint8_t const SOFT_SPI_CS_PIN = 10;
|
||||
/** Software SPI Master Out Slave In pin */
|
||||
uint8_t const SOFT_SPI_MOSI_PIN = 11;
|
||||
/** Software SPI Master In Slave Out pin */
|
||||
uint8_t const SOFT_SPI_MISO_PIN = 12;
|
||||
/** Software SPI Clock pin */
|
||||
uint8_t const SOFT_SPI_SCK_PIN = 13;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* The __cxa_pure_virtual function is an error handler that is invoked when
|
||||
* a pure virtual function is called.
|
||||
*/
|
||||
#define USE_CXA_PURE_VIRTUAL 1
|
||||
|
||||
/** Number of UTF-16 characters per entry */
|
||||
#define FILENAME_LENGTH 13
|
||||
/** Number of UTF-16 characters per entry */
|
||||
#define FILENAME_LENGTH 13
|
||||
|
||||
/**
|
||||
* Defines for long (vfat) filenames
|
||||
*/
|
||||
/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
|
||||
#define MAX_VFAT_ENTRIES (2)
|
||||
/** Total size of the buffer used to store the long filenames */
|
||||
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH*MAX_VFAT_ENTRIES+1)
|
||||
/**
|
||||
* Defines for long (vfat) filenames
|
||||
*/
|
||||
/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
|
||||
#define MAX_VFAT_ENTRIES (2)
|
||||
/** Total size of the buffer used to store the long filenames */
|
||||
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH*MAX_VFAT_ENTRIES+1)
|
||||
#endif // SdFatConfig_h
|
||||
|
||||
|
||||
|
@@ -55,9 +55,9 @@ struct partitionTable {
|
||||
*/
|
||||
uint8_t boot;
|
||||
/**
|
||||
* Head part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
* Head part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t beginHead;
|
||||
/**
|
||||
* Sector part of Cylinder-head-sector address of the first block in
|
||||
@@ -337,10 +337,10 @@ struct fat32_boot {
|
||||
* Bits 0-3 -- Zero-based number of active FAT.
|
||||
* Only valid if mirroring is disabled.
|
||||
* Bits 4-6 -- Reserved.
|
||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
||||
* -- 1 means only one FAT is active; it is the one referenced
|
||||
* in bits 0-3.
|
||||
* Bits 8-15 -- Reserved.
|
||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
||||
* -- 1 means only one FAT is active; it is the one referenced
|
||||
* in bits 0-3.
|
||||
* Bits 8-15 -- Reserved.
|
||||
*/
|
||||
uint16_t fat32Flags;
|
||||
/**
|
||||
@@ -468,29 +468,29 @@ uint32_t const FAT32MASK = 0X0FFFFFFF;
|
||||
* \brief FAT short directory entry
|
||||
*
|
||||
* Short means short 8.3 name, not the entry size.
|
||||
*
|
||||
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
|
||||
*
|
||||
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
|
||||
* basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
|
||||
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
|
||||
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
|
||||
* 16-bit word):
|
||||
*
|
||||
* Bits 9-15: Count of years from 1980, valid value range 0-127
|
||||
*
|
||||
* Bits 9-15: Count of years from 1980, valid value range 0-127
|
||||
* inclusive (1980-2107).
|
||||
*
|
||||
*
|
||||
* Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
|
||||
*
|
||||
* Bits 0-4: Day of month, valid value range 1-31 inclusive.
|
||||
*
|
||||
* Time Format. A FAT directory entry time stamp is a 16-bit field that has
|
||||
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
|
||||
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
|
||||
* 16-bit word, bit 15 is the MSB of the 16-bit word).
|
||||
*
|
||||
*
|
||||
* Bits 11-15: Hours, valid value range 0-23 inclusive.
|
||||
*
|
||||
*
|
||||
* Bits 5-10: Minutes, valid value range 0-59 inclusive.
|
||||
*
|
||||
*
|
||||
* Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
|
||||
*
|
||||
*
|
||||
* The valid time range is from Midnight 00:00:00 to 23:59:58.
|
||||
*/
|
||||
struct directoryEntry {
|
||||
@@ -548,7 +548,7 @@ struct directoryEntry {
|
||||
*
|
||||
* directoryVFATEntries are found in the same list as normal directoryEntry.
|
||||
* But have the attribute field set to DIR_ATT_LONG_NAME.
|
||||
*
|
||||
*
|
||||
* Long filenames are saved in multiple directoryVFATEntries.
|
||||
* Each entry containing 13 UTF-16 characters.
|
||||
*/
|
||||
|
@@ -33,7 +33,7 @@ int SdFatUtil::FreeRam() {
|
||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||
}
|
||||
#else // __arm__
|
||||
extern char *__brkval;
|
||||
extern char* __brkval;
|
||||
extern char __bss_end;
|
||||
/** Amount of free RAM
|
||||
* \return The number of free bytes.
|
||||
@@ -50,7 +50,7 @@ int SdFatUtil::FreeRam() {
|
||||
* \param[in] pr Print object for output.
|
||||
* \param[in] str Pointer to string stored in flash memory.
|
||||
*/
|
||||
void SdFatUtil::print_P( PGM_P str) {
|
||||
void SdFatUtil::print_P(PGM_P str) {
|
||||
for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -59,8 +59,8 @@ void SdFatUtil::print_P( PGM_P str) {
|
||||
* \param[in] pr Print object for output.
|
||||
* \param[in] str Pointer to string stored in flash memory.
|
||||
*/
|
||||
void SdFatUtil::println_P( PGM_P str) {
|
||||
print_P( str);
|
||||
void SdFatUtil::println_P(PGM_P str) {
|
||||
print_P(str);
|
||||
MYSERIAL.println();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -77,6 +77,6 @@ void SdFatUtil::SerialPrint_P(PGM_P str) {
|
||||
* \param[in] str Pointer to string stored in flash memory.
|
||||
*/
|
||||
void SdFatUtil::SerialPrintln_P(PGM_P str) {
|
||||
println_P( str);
|
||||
println_P(str);
|
||||
}
|
||||
#endif
|
||||
|
@@ -35,8 +35,8 @@
|
||||
|
||||
namespace SdFatUtil {
|
||||
int FreeRam();
|
||||
void print_P( PGM_P str);
|
||||
void println_P( PGM_P str);
|
||||
void print_P(PGM_P str);
|
||||
void println_P(PGM_P str);
|
||||
void SerialPrint_P(PGM_P str);
|
||||
void SerialPrintln_P(PGM_P str);
|
||||
}
|
||||
|
@@ -55,15 +55,13 @@ int16_t SdFile::write(const void* buf, uint16_t nbyte) {
|
||||
* Use writeError to check for errors.
|
||||
*/
|
||||
#if ARDUINO >= 100
|
||||
size_t SdFile::write(uint8_t b)
|
||||
{
|
||||
size_t SdFile::write(uint8_t b) {
|
||||
return SdBaseFile::write(&b, 1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void SdFile::write(uint8_t b)
|
||||
{
|
||||
void SdFile::write(uint8_t b) {
|
||||
SdBaseFile::write(&b, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
/** Write a string to a file. Used by the Arduino Print class.
|
||||
|
@@ -38,7 +38,7 @@ class SdFile : public SdBaseFile, public Print {
|
||||
SdFile() {}
|
||||
SdFile(const char* name, uint8_t oflag);
|
||||
#if ARDUINO >= 100
|
||||
size_t write(uint8_t b);
|
||||
size_t write(uint8_t b);
|
||||
#else
|
||||
void write(uint8_t b);
|
||||
#endif
|
||||
|
@@ -118,13 +118,13 @@ typedef struct CID {
|
||||
/** Manufacturing date month */
|
||||
unsigned char mdt_month : 4;
|
||||
/** Manufacturing date year low digit */
|
||||
unsigned char mdt_year_low :4;
|
||||
unsigned char mdt_year_low : 4;
|
||||
// byte 15
|
||||
/** not used always 1 */
|
||||
unsigned char always1 : 1;
|
||||
/** CRC7 checksum */
|
||||
unsigned char crc : 7;
|
||||
}cid_t;
|
||||
} cid_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/** CSD for version 1.00 cards */
|
||||
typedef struct CSDV1 {
|
||||
@@ -146,7 +146,7 @@ typedef struct CSDV1 {
|
||||
unsigned char c_size_high : 2;
|
||||
unsigned char reserved2 : 2;
|
||||
unsigned char dsr_imp : 1;
|
||||
unsigned char read_blk_misalign :1;
|
||||
unsigned char read_blk_misalign : 1;
|
||||
unsigned char write_blk_misalign : 1;
|
||||
unsigned char read_bl_partial : 1;
|
||||
// byte 7
|
||||
@@ -154,7 +154,7 @@ typedef struct CSDV1 {
|
||||
// byte 8
|
||||
unsigned char vdd_r_curr_max : 3;
|
||||
unsigned char vdd_r_curr_min : 3;
|
||||
unsigned char c_size_low :2;
|
||||
unsigned char c_size_low : 2;
|
||||
// byte 9
|
||||
unsigned char c_size_mult_high : 2;
|
||||
unsigned char vdd_w_cur_max : 3;
|
||||
@@ -186,7 +186,7 @@ typedef struct CSDV1 {
|
||||
// byte 15
|
||||
unsigned char always1 : 1;
|
||||
unsigned char crc : 7;
|
||||
}csd1_t;
|
||||
} csd1_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/** CSD for version 2.00 cards */
|
||||
typedef struct CSDV2 {
|
||||
@@ -212,7 +212,7 @@ typedef struct CSDV2 {
|
||||
unsigned char reserved2 : 4;
|
||||
unsigned char dsr_imp : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char read_blk_misalign :1;
|
||||
unsigned char read_blk_misalign : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char write_blk_misalign : 1;
|
||||
/** fixed to 0 - no partial read */
|
||||
@@ -268,7 +268,7 @@ typedef struct CSDV2 {
|
||||
unsigned char always1 : 1;
|
||||
/** checksum */
|
||||
unsigned char crc : 7;
|
||||
}csd2_t;
|
||||
} csd2_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/** union of old and new style CSD register */
|
||||
union csd_t {
|
||||
|
@@ -23,12 +23,12 @@
|
||||
#include "SdVolume.h"
|
||||
//------------------------------------------------------------------------------
|
||||
#if !USE_MULTIPLE_CARDS
|
||||
// raw block cache
|
||||
uint32_t SdVolume::cacheBlockNumber_; // current block number
|
||||
cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card
|
||||
Sd2Card* SdVolume::sdCard_; // pointer to SD card object
|
||||
bool SdVolume::cacheDirty_; // cacheFlush() will write block if true
|
||||
uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT
|
||||
// raw block cache
|
||||
uint32_t SdVolume::cacheBlockNumber_; // current block number
|
||||
cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card
|
||||
Sd2Card* SdVolume::sdCard_; // pointer to SD card object
|
||||
bool SdVolume::cacheDirty_; // cacheFlush() will write block if true
|
||||
uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT
|
||||
#endif // USE_MULTIPLE_CARDS
|
||||
//------------------------------------------------------------------------------
|
||||
// find a contiguous group of clusters
|
||||
@@ -50,7 +50,8 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
||||
|
||||
// don't save new start location
|
||||
setStart = false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// start at likely place for free cluster
|
||||
bgnCluster = allocSearchStart_;
|
||||
|
||||
@@ -75,7 +76,8 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
||||
if (f != 0) {
|
||||
// cluster in use try next cluster as bgnCluster
|
||||
bgnCluster = endCluster + 1;
|
||||
} else if ((endCluster - bgnCluster + 1) == count) {
|
||||
}
|
||||
else if ((endCluster - bgnCluster + 1) == count) {
|
||||
// done - found space
|
||||
break;
|
||||
}
|
||||
@@ -99,8 +101,7 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
||||
if (setStart) allocSearchStart_ = bgnCluster + 1;
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -119,8 +120,7 @@ bool SdVolume::cacheFlush() {
|
||||
cacheDirty_ = 0;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -132,8 +132,7 @@ bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
|
||||
}
|
||||
if (dirty) cacheDirty_ = true;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -146,8 +145,7 @@ bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
|
||||
} while (!isEOC(cluster));
|
||||
*size = s;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -173,9 +171,11 @@ bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
||||
}
|
||||
if (fatType_ == 16) {
|
||||
lba = fatStartBlock_ + (cluster >> 8);
|
||||
} else if (fatType_ == 32) {
|
||||
}
|
||||
else if (fatType_ == 32) {
|
||||
lba = fatStartBlock_ + (cluster >> 7);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
if (lba != cacheBlockNumber_) {
|
||||
@@ -183,12 +183,12 @@ bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
||||
}
|
||||
if (fatType_ == 16) {
|
||||
*value = cacheBuffer_.fat16[cluster & 0XFF];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -231,23 +231,25 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
||||
}
|
||||
if (fatType_ == 16) {
|
||||
lba = fatStartBlock_ + (cluster >> 8);
|
||||
} else if (fatType_ == 32) {
|
||||
}
|
||||
else if (fatType_ == 32) {
|
||||
lba = fatStartBlock_ + (cluster >> 7);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
||||
// store entry
|
||||
if (fatType_ == 16) {
|
||||
cacheBuffer_.fat16[cluster & 0XFF] = value;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
cacheBuffer_.fat32[cluster & 0X7F] = value;
|
||||
}
|
||||
// mirror second FAT
|
||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -268,8 +270,7 @@ bool SdVolume::freeChain(uint32_t cluster) {
|
||||
} while (!isEOC(cluster));
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -284,9 +285,11 @@ int32_t SdVolume::freeClusterCount() {
|
||||
|
||||
if (fatType_ == 16) {
|
||||
n = 256;
|
||||
} else if (fatType_ == 32) {
|
||||
}
|
||||
else if (fatType_ == 32) {
|
||||
n = 128;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// put FAT12 here
|
||||
return -1;
|
||||
}
|
||||
@@ -298,7 +301,8 @@ int32_t SdVolume::freeClusterCount() {
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (cacheBuffer_.fat16[i] == 0) free++;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (cacheBuffer_.fat32[i] == 0) free++;
|
||||
}
|
||||
@@ -338,10 +342,10 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||
if (part) {
|
||||
if (part > 4)goto fail;
|
||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
||||
part_t* p = &cacheBuffer_.mbr.part[part-1];
|
||||
if ((p->boot & 0X7F) !=0 ||
|
||||
p->totalSectors < 100 ||
|
||||
p->firstSector == 0) {
|
||||
part_t* p = &cacheBuffer_.mbr.part[part - 1];
|
||||
if ((p->boot & 0X7F) != 0 ||
|
||||
p->totalSectors < 100 ||
|
||||
p->firstSector == 0) {
|
||||
// not a valid partition
|
||||
goto fail;
|
||||
}
|
||||
@@ -350,11 +354,11 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
||||
fbs = &cacheBuffer_.fbs32;
|
||||
if (fbs->bytesPerSector != 512 ||
|
||||
fbs->fatCount == 0 ||
|
||||
fbs->reservedSectorCount == 0 ||
|
||||
fbs->sectorsPerCluster == 0) {
|
||||
// not valid FAT volume
|
||||
goto fail;
|
||||
fbs->fatCount == 0 ||
|
||||
fbs->reservedSectorCount == 0 ||
|
||||
fbs->sectorsPerCluster == 0) {
|
||||
// not valid FAT volume
|
||||
goto fail;
|
||||
}
|
||||
fatCount_ = fbs->fatCount;
|
||||
blocksPerCluster_ = fbs->sectorsPerCluster;
|
||||
@@ -365,7 +369,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||
if (clusterSizeShift_++ > 7) goto fail;
|
||||
}
|
||||
blocksPerFat_ = fbs->sectorsPerFat16 ?
|
||||
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
||||
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
||||
|
||||
fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
|
||||
|
||||
@@ -376,11 +380,12 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||
rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
|
||||
|
||||
// data start for FAT16 and FAT32
|
||||
dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511)/512);
|
||||
dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511) / 512);
|
||||
|
||||
// total blocks for FAT16 or FAT32
|
||||
totalBlocks = fbs->totalSectors16 ?
|
||||
fbs->totalSectors16 : fbs->totalSectors32;
|
||||
fbs->totalSectors16 : fbs->totalSectors32;
|
||||
|
||||
// total data blocks
|
||||
clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
|
||||
|
||||
@@ -391,15 +396,16 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||
if (clusterCount_ < 4085) {
|
||||
fatType_ = 12;
|
||||
if (!FAT12_SUPPORT) goto fail;
|
||||
} else if (clusterCount_ < 65525) {
|
||||
}
|
||||
else if (clusterCount_ < 65525) {
|
||||
fatType_ = 16;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
rootDirStart_ = fbs->fat32RootCluster;
|
||||
fatType_ = 32;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
#endif
|
@@ -117,7 +117,7 @@ class SdVolume {
|
||||
* \return true for success or false for failure
|
||||
*/
|
||||
bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
// Allow SdBaseFile access to SdVolume private data.
|
||||
friend class SdBaseFile;
|
||||
@@ -154,12 +154,15 @@ class SdVolume {
|
||||
//----------------------------------------------------------------------------
|
||||
bool allocContiguous(uint32_t count, uint32_t* curCluster);
|
||||
uint8_t blockOfCluster(uint32_t position) const {
|
||||
return (position >> 9) & (blocksPerCluster_ - 1);}
|
||||
return (position >> 9) & (blocksPerCluster_ - 1);
|
||||
}
|
||||
uint32_t clusterStartBlock(uint32_t cluster) const {
|
||||
return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
|
||||
return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);
|
||||
}
|
||||
uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
|
||||
return clusterStartBlock(cluster) + blockOfCluster(position);}
|
||||
cache_t *cache() {return &cacheBuffer_;}
|
||||
return clusterStartBlock(cluster) + blockOfCluster(position);
|
||||
}
|
||||
cache_t* cache() {return &cacheBuffer_;}
|
||||
uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
|
||||
#if USE_MULTIPLE_CARDS
|
||||
bool cacheFlush();
|
||||
@@ -187,11 +190,12 @@ class SdVolume {
|
||||
return cluster >= FAT32EOC_MIN;
|
||||
}
|
||||
bool readBlock(uint32_t block, uint8_t* dst) {
|
||||
return sdCard_->readBlock(block, dst);}
|
||||
return sdCard_->readBlock(block, dst);
|
||||
}
|
||||
bool writeBlock(uint32_t block, const uint8_t* dst) {
|
||||
return sdCard_->writeBlock(block, dst);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
||||
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
||||
public:
|
||||
|
Reference in New Issue
Block a user