make it compile with arduino 1.0 ; function is still untested.

master
Bernhard 13 years ago
parent b0c3871750
commit 0bc9daa4f7

@ -5,7 +5,12 @@
// Licence: GPL // Licence: GPL
#define HardwareSerial_h // trick to disable the standard HWserial #define HardwareSerial_h // trick to disable the standard HWserial
#include <math.h> #include <math.h>
#include <WProgram.h> #if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "fastio.h" #include "fastio.h"
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "Configuration.h" #include "Configuration.h"

@ -25,7 +25,11 @@
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <math.h> #include <math.h>
#include "wiring.h" #if ARDUINO >= 100
#include "Arduino.h"
#else
#include "wiring.h"
#endif
#include "wiring_private.h" #include "wiring_private.h"
// this next line disables the entire HardwareSerial.cpp, // this next line disables the entire HardwareSerial.cpp,

@ -1,643 +1,643 @@
/* Arduino Sd2Card Library /* Arduino Sd2Card Library
* Copyright (C) 2009 by William Greiman * Copyright (C) 2009 by William Greiman
* *
* This file is part of the Arduino Sd2Card Library * This file is part of the Arduino Sd2Card Library
* *
* This Library is free software: you can redistribute it and/or modify * This Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This Library is distributed in the hope that it will be useful, * This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with the Arduino Sd2Card Library. If not, see * along with the Arduino Sd2Card Library. If not, see
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#if ARDUINO < 100 #define HardwareSerial_h // trick to disable the standard HWserial
#define HardwareSerial_h // trick to disable the standard HWserial #if ARDUINO < 100
#include <WProgram.h> #include <WProgram.h>
#else // ARDUINO #else // ARDUINO
#include <Arduino.h> #include <Arduino.h>
#endif // ARDUINO #endif // ARDUINO
#include "Sd2Card.h" #include "Sd2Card.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
// functions for hardware SPI // functions for hardware SPI
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// make sure SPCR rate is in expected bits // make sure SPCR rate is in expected bits
#if (SPR0 != 0 || SPR1 != 1) #if (SPR0 != 0 || SPR1 != 1)
#error unexpected SPCR bits #error unexpected SPCR bits
#endif #endif
/** /**
* Initialize hardware SPI * Initialize hardware SPI
* Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
*/ */
static void spiInit(uint8_t spiRate) { static void spiInit(uint8_t spiRate) {
// See avr processor documentation // See avr processor documentation
SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** SPI receive a byte */ /** SPI receive a byte */
static uint8_t spiRec() { static uint8_t spiRec() {
SPDR = 0XFF; SPDR = 0XFF;
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
return SPDR; return SPDR;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** SPI read data - only one call so force inline */ /** SPI read data - only one call so force inline */
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
void spiRead(uint8_t* buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
if (nbyte-- == 0) return; if (nbyte-- == 0) return;
SPDR = 0XFF; SPDR = 0XFF;
for (uint16_t i = 0; i < nbyte; i++) { for (uint16_t i = 0; i < nbyte; i++) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
buf[i] = SPDR; buf[i] = SPDR;
SPDR = 0XFF; SPDR = 0XFF;
} }
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
buf[nbyte] = SPDR; buf[nbyte] = SPDR;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** SPI send a byte */ /** SPI send a byte */
static void spiSend(uint8_t b) { static void spiSend(uint8_t b) {
SPDR = b; SPDR = b;
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** SPI send block - only one call so force inline */ /** SPI send block - only one call so force inline */
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
void spiSendBlock(uint8_t token, const uint8_t* buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
SPDR = token; SPDR = token;
for (uint16_t i = 0; i < 512; i += 2) { for (uint16_t i = 0; i < 512; i += 2) {
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
SPDR = buf[i]; SPDR = buf[i];
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
SPDR = buf[i + 1]; SPDR = buf[i + 1];
} }
while (!(SPSR & (1 << SPIF))); while (!(SPSR & (1 << SPIF)));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#else // SOFTWARE_SPI #else // SOFTWARE_SPI
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** nop to tune soft SPI timing */ /** nop to tune soft SPI timing */
#define nop asm volatile ("nop\n\t") #define nop asm volatile ("nop\n\t")
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Soft SPI receive byte */ /** Soft SPI receive byte */
static uint8_t spiRec() { static uint8_t spiRec() {
uint8_t data = 0; uint8_t data = 0;
// no interrupts during byte receive - about 8 us // no interrupts during byte receive - about 8 us
cli(); cli();
// output pin high - like sending 0XFF // output pin high - like sending 0XFF
fastDigitalWrite(SPI_MOSI_PIN, HIGH); fastDigitalWrite(SPI_MOSI_PIN, HIGH);
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
fastDigitalWrite(SPI_SCK_PIN, HIGH); fastDigitalWrite(SPI_SCK_PIN, HIGH);
// adjust so SCK is nice // adjust so SCK is nice
nop; nop;
nop; nop;
data <<= 1; data <<= 1;
if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
fastDigitalWrite(SPI_SCK_PIN, LOW); fastDigitalWrite(SPI_SCK_PIN, LOW);
} }
// enable interrupts // enable interrupts
sei(); sei();
return data; return data;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Soft SPI read data */ /** Soft SPI read data */
static void spiRead(uint8_t* buf, uint16_t nbyte) { static void spiRead(uint8_t* buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) { for (uint16_t i = 0; i < nbyte; i++) {
buf[i] = spiRec(); buf[i] = spiRec();
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Soft SPI send byte */ /** Soft SPI send byte */
static void spiSend(uint8_t data) { static void spiSend(uint8_t data) {
// no interrupts during byte send - about 8 us // no interrupts during byte send - about 8 us
cli(); cli();
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
fastDigitalWrite(SPI_SCK_PIN, LOW); fastDigitalWrite(SPI_SCK_PIN, LOW);
fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
data <<= 1; data <<= 1;
fastDigitalWrite(SPI_SCK_PIN, HIGH); fastDigitalWrite(SPI_SCK_PIN, HIGH);
} }
// hold SCK high for a few ns // hold SCK high for a few ns
nop; nop;
nop; nop;
nop; nop;
nop; nop;
fastDigitalWrite(SPI_SCK_PIN, LOW); fastDigitalWrite(SPI_SCK_PIN, LOW);
// enable interrupts // enable interrupts
sei(); sei();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Soft SPI send block */ /** Soft SPI send block */
void spiSendBlock(uint8_t token, const uint8_t* buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
spiSend(token); spiSend(token);
for (uint16_t i = 0; i < 512; i++) { for (uint16_t i = 0; i < 512; i++) {
spiSend(buf[i]); spiSend(buf[i]);
} }
} }
#endif // SOFTWARE_SPI #endif // SOFTWARE_SPI
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// send command and return error code. Return zero for OK // send command and return error code. Return zero for OK
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// select card // select card
chipSelectLow(); chipSelectLow();
// wait up to 300 ms if busy // wait up to 300 ms if busy
waitNotBusy(300); waitNotBusy(300);
// send command // send command
spiSend(cmd | 0x40); spiSend(cmd | 0x40);
// send argument // send argument
for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
// send CRC // send CRC
uint8_t crc = 0XFF; uint8_t crc = 0XFF;
if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
spiSend(crc); spiSend(crc);
// skip stuff byte for stop read // skip stuff byte for stop read
if (cmd == CMD12) spiRec(); if (cmd == CMD12) spiRec();
// wait for response // wait for response
for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
return status_; return status_;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Determine the size of an SD flash memory card. * Determine the size of an SD flash memory card.
* *
* \return The number of 512 byte data blocks in the card * \return The number of 512 byte data blocks in the card
* or zero if an error occurs. * or zero if an error occurs.
*/ */
uint32_t Sd2Card::cardSize() { uint32_t Sd2Card::cardSize() {
csd_t csd; csd_t csd;
if (!readCSD(&csd)) return 0; if (!readCSD(&csd)) return 0;
if (csd.v1.csd_ver == 0) { if (csd.v1.csd_ver == 0) {
uint8_t read_bl_len = csd.v1.read_bl_len; uint8_t read_bl_len = csd.v1.read_bl_len;
uint16_t c_size = (csd.v1.c_size_high << 10) uint16_t c_size = (csd.v1.c_size_high << 10)
| (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
| csd.v1.c_size_mult_low; | csd.v1.c_size_mult_low;
return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
} else if (csd.v2.csd_ver == 1) { } else if (csd.v2.csd_ver == 1) {
uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
| (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
return (c_size + 1) << 10; return (c_size + 1) << 10;
} else { } else {
error(SD_CARD_ERROR_BAD_CSD); error(SD_CARD_ERROR_BAD_CSD);
return 0; return 0;
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh() { void Sd2Card::chipSelectHigh() {
digitalWrite(chipSelectPin_, HIGH); digitalWrite(chipSelectPin_, HIGH);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Sd2Card::chipSelectLow() { void Sd2Card::chipSelectLow() {
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
spiInit(spiRate_); spiInit(spiRate_);
#endif // SOFTWARE_SPI #endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW); digitalWrite(chipSelectPin_, LOW);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Erase a range of blocks. /** Erase a range of blocks.
* *
* \param[in] firstBlock The address of the first block in the range. * \param[in] firstBlock The address of the first block in the range.
* \param[in] lastBlock The address of the last block in the range. * \param[in] lastBlock The address of the last block in the range.
* *
* \note This function requests the SD card to do a flash erase for a * \note This function requests the SD card to do a flash erase for a
* range of blocks. The data on the card after an erase operation is * range of blocks. The data on the card after an erase operation is
* either 0 or 1, depends on the card vendor. The card must support * either 0 or 1, depends on the card vendor. The card must support
* single block erase. * single block erase.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
csd_t csd; csd_t csd;
if (!readCSD(&csd)) goto fail; if (!readCSD(&csd)) goto fail;
// check for single block erase // check for single block erase
if (!csd.v1.erase_blk_en) { if (!csd.v1.erase_blk_en) {
// erase size mask // erase size mask
uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
// error card can't erase specified area // error card can't erase specified area
error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
goto fail; goto fail;
} }
} }
if (type_ != SD_CARD_TYPE_SDHC) { if (type_ != SD_CARD_TYPE_SDHC) {
firstBlock <<= 9; firstBlock <<= 9;
lastBlock <<= 9; lastBlock <<= 9;
} }
if (cardCommand(CMD32, firstBlock) if (cardCommand(CMD32, firstBlock)
|| cardCommand(CMD33, lastBlock) || cardCommand(CMD33, lastBlock)
|| cardCommand(CMD38, 0)) { || cardCommand(CMD38, 0)) {
error(SD_CARD_ERROR_ERASE); error(SD_CARD_ERROR_ERASE);
goto fail; goto fail;
} }
if (!waitNotBusy(SD_ERASE_TIMEOUT)) { if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
error(SD_CARD_ERROR_ERASE_TIMEOUT); error(SD_CARD_ERROR_ERASE_TIMEOUT);
goto fail; goto fail;
} }
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Determine if card supports single block erase. /** Determine if card supports single block erase.
* *
* \return The value one, true, is returned if single block erase is supported. * \return The value one, true, is returned if single block erase is supported.
* The value zero, false, is returned if single block erase is not supported. * The value zero, false, is returned if single block erase is not supported.
*/ */
bool Sd2Card::eraseSingleBlockEnable() { bool Sd2Card::eraseSingleBlockEnable() {
csd_t csd; csd_t csd;
return readCSD(&csd) ? csd.v1.erase_blk_en : false; return readCSD(&csd) ? csd.v1.erase_blk_en : false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Initialize an SD flash memory card. * Initialize an SD flash memory card.
* *
* \param[in] sckRateID SPI clock rate selector. See setSckRate(). * \param[in] sckRateID SPI clock rate selector. See setSckRate().
* \param[in] chipSelectPin SD chip select pin number. * \param[in] chipSelectPin SD chip select pin number.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. The reason for failure * the value zero, false, is returned for failure. The reason for failure
* can be determined by calling errorCode() and errorData(). * can be determined by calling errorCode() and errorData().
*/ */
bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
errorCode_ = type_ = 0; errorCode_ = type_ = 0;
chipSelectPin_ = chipSelectPin; chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute // 16-bit init start time allows over a minute
uint16_t t0 = (uint16_t)millis(); uint16_t t0 = (uint16_t)millis();
uint32_t arg; uint32_t arg;
// set pin modes // set pin modes
pinMode(chipSelectPin_, OUTPUT); pinMode(chipSelectPin_, OUTPUT);
chipSelectHigh(); chipSelectHigh();
pinMode(SPI_MISO_PIN, INPUT); pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, OUTPUT); pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT); pinMode(SPI_SCK_PIN, OUTPUT);
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
// SS must be in output mode even it is not chip select // SS must be in output mode even it is not chip select
pinMode(SS_PIN, OUTPUT); pinMode(SS_PIN, OUTPUT);
// set SS high - may be chip select for another SPI device // set SS high - may be chip select for another SPI device
#if SET_SPI_SS_HIGH #if SET_SPI_SS_HIGH
digitalWrite(SS_PIN, HIGH); digitalWrite(SS_PIN, HIGH);
#endif // SET_SPI_SS_HIGH #endif // SET_SPI_SS_HIGH
// set SCK rate for initialization commands // set SCK rate for initialization commands
spiRate_ = SPI_SD_INIT_RATE; spiRate_ = SPI_SD_INIT_RATE;
spiInit(spiRate_); spiInit(spiRate_);
#endif // SOFTWARE_SPI #endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high. // must supply min of 74 clock cycles with CS high.
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
// command to go idle in SPI mode // command to go idle in SPI mode
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0); error(SD_CARD_ERROR_CMD0);
goto fail; goto fail;
} }
} }
// check SD version // check SD version
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
type(SD_CARD_TYPE_SD1); type(SD_CARD_TYPE_SD1);
} else { } else {
// only need last byte of r7 response // only need last byte of r7 response
for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
if (status_ != 0XAA) { if (status_ != 0XAA) {
error(SD_CARD_ERROR_CMD8); error(SD_CARD_ERROR_CMD8);
goto fail; goto fail;
} }
type(SD_CARD_TYPE_SD2); type(SD_CARD_TYPE_SD2);
} }
// initialize card and send host supports SDHC if SD2 // initialize card and send host supports SDHC if SD2
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout // check for timeout
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41); error(SD_CARD_ERROR_ACMD41);
goto fail; goto fail;
} }
} }
// if SD2 read OCR register to check for SDHC card // if SD2 read OCR register to check for SDHC card
if (type() == SD_CARD_TYPE_SD2) { if (type() == SD_CARD_TYPE_SD2) {
if (cardCommand(CMD58, 0)) { if (cardCommand(CMD58, 0)) {
error(SD_CARD_ERROR_CMD58); error(SD_CARD_ERROR_CMD58);
goto fail; goto fail;
} }
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
// discard rest of ocr - contains allowed voltage range // discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec(); for (uint8_t i = 0; i < 3; i++) spiRec();
} }
chipSelectHigh(); chipSelectHigh();
#ifndef SOFTWARE_SPI #ifndef SOFTWARE_SPI
return setSckRate(sckRateID); return setSckRate(sckRateID);
#else // SOFTWARE_SPI #else // SOFTWARE_SPI
return true; return true;
#endif // SOFTWARE_SPI #endif // SOFTWARE_SPI
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Read a 512 byte block from an SD card. * Read a 512 byte block from an SD card.
* *
* \param[in] blockNumber Logical block to be read. * \param[in] blockNumber Logical block to be read.
* \param[out] dst Pointer to the location that will receive the data. * \param[out] dst Pointer to the location that will receive the data.
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
// use address if not SDHC card // 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)) { if (cardCommand(CMD17, blockNumber)) {
error(SD_CARD_ERROR_CMD17); error(SD_CARD_ERROR_CMD17);
goto fail; goto fail;
} }
return readData(dst, 512); return readData(dst, 512);
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Read one data block in a multiple block read sequence /** Read one data block in a multiple block read sequence
* *
* \param[in] dst Pointer to the location for the data to be read. * \param[in] dst Pointer to the location for the data to be read.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::readData(uint8_t *dst) { bool Sd2Card::readData(uint8_t *dst) {
chipSelectLow(); chipSelectLow();
return readData(dst, 512); return readData(dst, 512);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool Sd2Card::readData(uint8_t* dst, uint16_t count) { bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
// wait for start block token // wait for start block token
uint16_t t0 = millis(); uint16_t t0 = millis();
while ((status_ = spiRec()) == 0XFF) { while ((status_ = spiRec()) == 0XFF) {
if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
error(SD_CARD_ERROR_READ_TIMEOUT); error(SD_CARD_ERROR_READ_TIMEOUT);
goto fail; goto fail;
} }
} }
if (status_ != DATA_START_BLOCK) { if (status_ != DATA_START_BLOCK) {
error(SD_CARD_ERROR_READ); error(SD_CARD_ERROR_READ);
goto fail; goto fail;
} }
// transfer data // transfer data
spiRead(dst, count); spiRead(dst, count);
// discard CRC // discard CRC
spiRec(); spiRec();
spiRec(); spiRec();
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** read CID or CSR register */ /** read CID or CSR register */
bool Sd2Card::readRegister(uint8_t cmd, void* buf) { bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf); uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
if (cardCommand(cmd, 0)) { if (cardCommand(cmd, 0)) {
error(SD_CARD_ERROR_READ_REG); error(SD_CARD_ERROR_READ_REG);
goto fail; goto fail;
} }
return readData(dst, 16); return readData(dst, 16);
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Start a read multiple blocks sequence. /** Start a read multiple blocks sequence.
* *
* \param[in] blockNumber Address of first block in sequence. * \param[in] blockNumber Address of first block in sequence.
* *
* \note This function is used with readData() and readStop() for optimized * \note This function is used with readData() and readStop() for optimized
* multiple block reads. SPI chipSelect must be low for the entire sequence. * multiple block reads. SPI chipSelect must be low for the entire sequence.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::readStart(uint32_t blockNumber) { 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)) { if (cardCommand(CMD18, blockNumber)) {
error(SD_CARD_ERROR_CMD18); error(SD_CARD_ERROR_CMD18);
goto fail; goto fail;
} }
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** End a read multiple blocks sequence. /** End a read multiple blocks sequence.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::readStop() { bool Sd2Card::readStop() {
chipSelectLow(); chipSelectLow();
if (cardCommand(CMD12, 0)) { if (cardCommand(CMD12, 0)) {
error(SD_CARD_ERROR_CMD12); error(SD_CARD_ERROR_CMD12);
goto fail; goto fail;
} }
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Set the SPI clock rate. * Set the SPI clock rate.
* *
* \param[in] sckRateID A value in the range [0, 6]. * \param[in] sckRateID A value in the range [0, 6].
* *
* The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum
* SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128
* for \a scsRateID = 6. * for \a scsRateID = 6.
* *
* \return The value one, true, is returned for success and the value zero, * \return The value one, true, is returned for success and the value zero,
* false, is returned for an invalid value of \a sckRateID. * false, is returned for an invalid value of \a sckRateID.
*/ */
bool Sd2Card::setSckRate(uint8_t sckRateID) { bool Sd2Card::setSckRate(uint8_t sckRateID) {
if (sckRateID > 6) { if (sckRateID > 6) {
error(SD_CARD_ERROR_SCK_RATE); error(SD_CARD_ERROR_SCK_RATE);
return false; return false;
} }
spiRate_ = sckRateID; spiRate_ = sckRateID;
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// wait for card to go not busy // wait for card to go not busy
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) { bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
uint16_t t0 = millis(); uint16_t t0 = millis();
while (spiRec() != 0XFF) { while (spiRec() != 0XFF) {
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
} }
return true; return true;
fail: fail:
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* Writes a 512 byte block to an SD card. * Writes a 512 byte block to an SD card.
* *
* \param[in] blockNumber Logical block to be written. * \param[in] blockNumber Logical block to be written.
* \param[in] src Pointer to the location of the data to be written. * \param[in] src Pointer to the location of the data to be written.
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
// use address if not SDHC card // use address if not SDHC card
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD24, blockNumber)) { if (cardCommand(CMD24, blockNumber)) {
error(SD_CARD_ERROR_CMD24); error(SD_CARD_ERROR_CMD24);
goto fail; goto fail;
} }
if (!writeData(DATA_START_BLOCK, src)) goto fail; if (!writeData(DATA_START_BLOCK, src)) goto fail;
// wait for flash programming to complete // wait for flash programming to complete
if (!waitNotBusy(SD_WRITE_TIMEOUT)) { if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
error(SD_CARD_ERROR_WRITE_TIMEOUT); error(SD_CARD_ERROR_WRITE_TIMEOUT);
goto fail; goto fail;
} }
// response is r2 so get and check two bytes for nonzero // response is r2 so get and check two bytes for nonzero
if (cardCommand(CMD13, 0) || spiRec()) { if (cardCommand(CMD13, 0) || spiRec()) {
error(SD_CARD_ERROR_WRITE_PROGRAMMING); error(SD_CARD_ERROR_WRITE_PROGRAMMING);
goto fail; goto fail;
} }
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Write one data block in a multiple block write sequence /** Write one data block in a multiple block write sequence
* \param[in] src Pointer to the location of the data to be written. * \param[in] src Pointer to the location of the data to be written.
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::writeData(const uint8_t* src) { bool Sd2Card::writeData(const uint8_t* src) {
chipSelectLow(); chipSelectLow();
// wait for previous write to finish // wait for previous write to finish
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
error(SD_CARD_ERROR_WRITE_MULTIPLE); error(SD_CARD_ERROR_WRITE_MULTIPLE);
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// send one block of data for write block or write multiple blocks // send one block of data for write block or write multiple blocks
bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
spiSendBlock(token, src); spiSendBlock(token, src);
spiSend(0xff); // dummy crc spiSend(0xff); // dummy crc
spiSend(0xff); // dummy crc spiSend(0xff); // dummy crc
status_ = spiRec(); status_ = spiRec();
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
error(SD_CARD_ERROR_WRITE); error(SD_CARD_ERROR_WRITE);
goto fail; goto fail;
} }
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Start a write multiple blocks sequence. /** Start a write multiple blocks sequence.
* *
* \param[in] blockNumber Address of first block in sequence. * \param[in] blockNumber Address of first block in sequence.
* \param[in] eraseCount The number of blocks to be pre-erased. * \param[in] eraseCount The number of blocks to be pre-erased.
* *
* \note This function is used with writeData() and writeStop() * \note This function is used with writeData() and writeStop()
* for optimized multiple block writes. * for optimized multiple block writes.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
// send pre-erase count // send pre-erase count
if (cardAcmd(ACMD23, eraseCount)) { if (cardAcmd(ACMD23, eraseCount)) {
error(SD_CARD_ERROR_ACMD23); error(SD_CARD_ERROR_ACMD23);
goto fail; goto fail;
} }
// use address if not SDHC card // use address if not SDHC card
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD25, blockNumber)) { if (cardCommand(CMD25, blockNumber)) {
error(SD_CARD_ERROR_CMD25); error(SD_CARD_ERROR_CMD25);
goto fail; goto fail;
} }
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** End a write multiple blocks sequence. /** End a write multiple blocks sequence.
* *
* \return The value one, true, is returned for success and * \return The value one, true, is returned for success and
* the value zero, false, is returned for failure. * the value zero, false, is returned for failure.
*/ */
bool Sd2Card::writeStop() { bool Sd2Card::writeStop() {
chipSelectLow(); chipSelectLow();
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
spiSend(STOP_TRAN_TOKEN); spiSend(STOP_TRAN_TOKEN);
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
chipSelectHigh(); chipSelectHigh();
return true; return true;
fail: fail:
error(SD_CARD_ERROR_STOP_TRAN); error(SD_CARD_ERROR_STOP_TRAN);
chipSelectHigh(); chipSelectHigh();
return false; return false;
} }

@ -24,13 +24,13 @@
* \brief SdBaseFile class * \brief SdBaseFile class
*/ */
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#if ARDUINO < 100
#define HardwareSerial_h // trick to disable the standard HWserial #define HardwareSerial_h // trick to disable the standard HWserial
#if ARDUINO < 100
#include <WProgram.h> #include <WProgram.h>
#include "MarlinSerial.h"
#else // ARDUINO #else // ARDUINO
#include <Arduino.h> #include <Arduino.h>
#endif // ARDUINO #endif // ARDUINO
#include "MarlinSerial.h"
#include "SdFatConfig.h" #include "SdFatConfig.h"
#include "SdVolume.h" #include "SdVolume.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

@ -24,13 +24,14 @@
* \brief Useful utility functions. * \brief Useful utility functions.
*/ */
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#if ARDUINO < 100
#define HardwareSerial_h // trick to disable the standard HWserial #define HardwareSerial_h // trick to disable the standard HWserial
#if ARDUINO < 100
#include <WProgram.h> #include <WProgram.h>
#include "MarlinSerial.h"
#else // ARDUINO #else // ARDUINO
#include <Arduino.h> #include <Arduino.h>
#endif // ARDUINO #endif // ARDUINO
#include "MarlinSerial.h"
/** Store and print a string in flash memory.*/ /** Store and print a string in flash memory.*/
#define PgmPrint(x) SerialPrint_P(PSTR(x)) #define PgmPrint(x) SerialPrint_P(PSTR(x))
/** Store and print a string in flash memory followed by a CR/LF.*/ /** Store and print a string in flash memory followed by a CR/LF.*/

@ -51,7 +51,12 @@ int16_t SdFile::write(const void* buf, uint16_t nbyte) {
* \param[in] b the byte to be written. * \param[in] b the byte to be written.
* Use writeError to check for errors. * Use writeError to check for errors.
*/ */
void SdFile::write(uint8_t b) { #if ARDUINO >= 100
size_t SdFile::write(uint8_t b)
#else
void SdFile::write(uint8_t b)
#endif
{
SdBaseFile::write(&b, 1); SdBaseFile::write(&b, 1);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

@ -34,7 +34,12 @@ class SdFile : public SdBaseFile, public Print {
public: public:
SdFile() {} SdFile() {}
SdFile(const char* name, uint8_t oflag); SdFile(const char* name, uint8_t oflag);
void write(uint8_t b); #if ARDUINO >= 100
size_t write(uint8_t b);
#else
void write(uint8_t b);
#endif
int16_t write(const void* buf, uint16_t nbyte); int16_t write(const void* buf, uint16_t nbyte);
void write(const char* str); void write(const char* str);
void write_P(PGM_P str); void write_P(PGM_P str);

@ -101,7 +101,11 @@ extern uint8_t active_extruder;
/////semi-private stuff /////semi-private stuff
#include <WProgram.h> #if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions
extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed

Loading…
Cancel
Save