diff --git a/sd.c b/sd.c new file mode 100644 index 0000000..b4fd92d --- /dev/null +++ b/sd.c @@ -0,0 +1,278 @@ +/* +ganked from http://www.arduino.cc/playground/Code/SDCARD +*/ +/* +Basic instructions for recording data in an SD Card in native mode +The SD card (3.3 V) must be properly interfaced to Arduino (5 V) + +The typical procedure is: +Initialize SPI +Initialize SD Card +START +-Blank vector of data (vBlock) +-Record data in vector of data +-Copy data from vector to CSD card +GOTO START + +At your convenience: +-Copy data from CSD card to vector of data +-Read data from vector + +Starting from there, you will have to build your own file system... + +Useful links +http://elm-chan.org/docs/mmc/mmc_e.html +http://www.retroleum.co.uk/mmc_cards.html +http://www.maxim-ic.com/appnotes.cfm/an_pk/3969 + +No warranty, no claims, just fun + +Didier Longueville invenit et fecit February 2010 +*/ + +#ifdef SD + +// Ports +int PIN_CS = PINB2; // chip select +int PIN_MOSI = PINB3; // master out slave in +int PIN_MISO = PINB4; // master in slave out +int PIN_CLOCK = PINB5; // clock + +/********************** SPI SECTION BELOW **********************/ + +// SPI Variables +byte clr; // dummy variable used to clear some of the SPI registers +byte spi_err; // SPI timeout flag, must be cleared manually + +// send an SPI command, includes time out management +// returns spi_err: "0" is "no error" +byte spi_cmd(volatile char data) { + spi_err = 0; // reset spi error + SPDR = data; // start the transmission by loading the output byte into the spi data register + int i = 0; + while (!(SPSR & (1<= 0xFF) { + spi_err = 1; + return(0x00); + } + } + // returned value + return(SPDR); +} + +// initialize SPI port +void spi_initialize(void) { + SPCR = (1<=0; i--) { + spi_cmd(arg>>(i*8)); // send argument in little endian form (MSB first) + } + spi_cmd(0x95); // checksum valid for GO_IDLE_STATE, not needed thereafter, so we can hardcode this value + spi_cmd(0xFF); // dummy byte gives card time to process + byte res = spi_cmd(0xFF); + return (res); // query return value from card +} + +// initialize SD card +// retuns 1 if successful +byte sdc_initialize(void) { + // set slow clock: 1/128 base frequency (125Khz in this case) + SPCR |= (1<= 0xFF) { + return(NULL); // timed out! + } + delay(5); + } + // at this stage, the card is in idle mode and ready for start up + retries = 0; + sdc_cmd(APP_CMD, 0); // startup sequence for SD cards 55/41 + while (sdc_cmd(SEND_OP_COND, 0) != 0x00) { + retries++; + if (retries >= 0xFF) { + return(NULL); // timed out! + } + sdc_cmd(APP_CMD, 0); + } + // set fast clock, 1/4 CPU clock frequency (4Mhz in this case) + SPCR &= ~((1<> 6) | ((vBuffer[0x07] & 0xFF) << 2) | ((vBuffer[0x06] & 0x03) << 10); + long C_Mult = ((vBuffer[0x08] & 0x80) >> 7) | ((vBuffer[0x08] & 0x03) << 2); + return ((C_Size+1) << (C_Mult+2)); +} + +// read SD card register content and store it in vBuffer +void sdc_readRegister(byte sentCommand) { + byte retries=0x00; + byte res=sdc_cmd(sentCommand, 0); + while(res != 0x00) { + delay(1); + retries++; + if (retries >= 0xFF) return; // timed out! + res=spi_cmd(0xFF); // retry + } + // wait for data token + while (spi_cmd(0xFF) != 0xFE); + // read data + for (int i=0; i<16; i++) { + vBuffer[i] = spi_cmd(0xFF); + } + // read CRC (lost results in blue sky) + spi_cmd(0xFF); // LSB + spi_cmd(0xFF); // MSB +} + +// write block on SD card +// addr is the address in bytes (multiples of block size) +void sdc_writeBlock(long blockIndex) { + byte retries=0; + while(sdc_cmd(WRITE_BLOCK, blockIndex * blockSize) != 0x00) { + delay(1); + retries++; + if (retries >= 0xFF) return; // timed out! + } + spi_cmd(0xFF); // dummy byte (at least one) + // send data packet (includes data token, data block and CRC) + // data token + spi_cmd(0xFE); + // copy block data + for (int i=0; i= 0xFF) return; // timed out! + res=spi_cmd(0xFF); // retry + } + // read data packet (includes data token, data block and CRC) + // read data token + while (spi_cmd(0xFF) != 0xFE); + // read data block + for (int i=0; i