SD Card Interface class. Log raw data bytes to memory addresses of your choice, or format the card and use the FAT file system to write files.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Blaze513
Date:
Sun Jul 18 21:26:24 2010 +0000
Child:
1:94c648931f84
Commit message:

Changed in this revision

SDCard.cpp Show annotated file Show diff for this revision Revisions of this file
SDCard.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDCard.cpp	Sun Jul 18 21:26:24 2010 +0000
@@ -0,0 +1,422 @@
+#include "SDCard.h"
+
+SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs)
+    : DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1)
+{
+    DataLines.frequency(100000);
+        //set universal speed
+    ChipSelect.write(1);
+        //chip select is active low
+    GenerateCRCTable(1, 137, CommandCRCTable);
+        //generate the command crc lookup table
+        //(generator polynomial x^7 + x^3 + 1 converts to decimal 137)
+    GenerateCRCTable(2, 69665, DataCRCTable);
+        //generate the command crc lookup table
+        //(generator polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665)
+    Initialize();
+        //send card initialization sequence
+}
+
+bool SDCard::Write(unsigned int Address, unsigned char* Data)
+{
+    if (Capacity)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(24, Address, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(24, Address * 512, Workspace);///////////implement block length
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    ChipSelect.write(0);
+    DataLines.write(0xFE);
+        //start data block token
+    for (unsigned short j = 0; j < 512; j++)
+    {
+        DataLines.write(Data[j]);
+            //write the data
+    }
+    DataCRC(512, Data, Workspace);
+    DataLines.write(Workspace[1]);
+    DataLines.write(Workspace[2]);
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Workspace[0] = DataLines.write(0xFF);
+        if ((Workspace[0] & 0x1F) == 0x05)
+        { break; }
+    }
+    while (!DataLines.write(0xFF));
+    ChipSelect.write(1);
+    DataLines.write(0xFF);
+    if ((Workspace[0] & 0x1F) == 0x05)
+    { return 1; }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(13, 0, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+        }
+        return 0;
+    }
+}
+
+bool SDCard::Read(unsigned int Address, unsigned char* Data)
+{
+    if (Capacity)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(17, Address, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(17, Address * 512, Workspace);///////////implement block length
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    ChipSelect.write(0);
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        if (DataLines.write(0xFF) == 0xFE)
+        { break; }
+    }
+    for (unsigned short j = 0; j < 512; j++)
+    {
+        Data[j] = DataLines.write(0xFF);
+    }
+    Workspace[3] = DataLines.write(0xFF);
+    Workspace[4] = DataLines.write(0xFF);
+    ChipSelect.write(1);
+    DataLines.write(0xFF);
+    DataCRC(512, Data, Workspace);
+    if ((Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
+    { return 1; }
+    else
+    { return 0; }
+}
+
+bool SDCard::Initialize()
+{
+    for (unsigned char j = 0; j < 16; j++)
+    {
+        DataLines.write(0xFF);
+    }
+        //perform specified power up sequence
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(0, 0, Workspace);
+            //send command 0 to put the card into SPI mode
+        if (Workspace[0] == 0x01)
+            //check for idle mode
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(59, 1, Workspace);
+            //send command 59 to turn on CRCs
+        if (Workspace[0] == 0x01)
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(8, 426, Workspace);
+            //voltage bits are 0x01 for 2.7V - 3.6V,
+            //check pattern 0xAA, [00,00,01,AA] = 426
+        if ((Workspace[0] == 0x05) || ((Workspace[0] == 0x01) &&
+            ((Workspace[3] & 0x0F) == 0x01) && (Workspace[4] == 0xAA)))
+            //check version, voltage acceptance, and check pattern
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Version = Workspace[0] == 0x01;
+        //store card version
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(58, 0, Workspace);
+            //check the OCR
+        if ((Workspace[0] == 0x01) && ((Workspace[2] & 0x20) || (Workspace[2] & 0x10)))
+            //check for correct operating voltage 3.3V
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(55, 0, Workspace);
+            //specify application-specific command
+        Command(41, 1073741824, Workspace);
+            //specify host supports high capacity cards
+            //[40,00,00,00] = 1073741824
+        if (Workspace[0] == 0x00)
+            //check if card is ready
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(58, 0, Workspace);
+            //check the OCR again
+        if ((Workspace[0] == 0x00) && (Workspace[1] & 0x80))
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    for (unsigned char j = 0; j < 4; j++)
+    {
+        OCR[j] = Workspace[j + 1];
+    }
+        //record OCR
+    Capacity = (OCR[0] & 0x40) == 0x40;
+        //record capacity
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(9, 0, Workspace);
+            //read the card-specific data register
+        ChipSelect.write(0);
+        for (unsigned int k = 0; k < 8192; k++)
+        {
+            if (DataLines.write(0xFF) == 0xFE)
+            { break; }
+        }
+            //get to the start-data-block token
+        for (unsigned char k = 0; k < 16; k++)
+        {
+            CSD[k] = DataLines.write(0xFF);
+        }
+        Workspace[3] = DataLines.write(0xFF);
+        Workspace[4] = DataLines.write(0xFF);
+        ChipSelect.write(1);
+        DataLines.write(0xFF);
+        DataCRC(16, CSD, Workspace);
+            //calculate the CSD data CRC
+        Workspace[0] = 0;
+        for (unsigned char k = 0; k < 15; k++)
+        {
+            Workspace[0] = CommandCRCTable[Workspace[0]] ^ CSD[k];
+        }
+        Workspace[0] = CommandCRCTable[Workspace[0]] | 0x01;
+        if ((Workspace[0] == CSD[15]) && (Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    
+    if (((CSD[3] & 0x07) > 2) || ((CSD[3] & 0x7F) > 0x32))
+    {
+        DataLines.frequency(25000000);
+            //maximum speed is given at 25MHz
+    }
+    else
+    {
+       Workspace[0] = 1;
+        for (unsigned char j = 0; j < (CSD[3] & 0x07); j++)
+        {
+            Workspace[0] *= 10;
+                //the first three bits are a power of ten multiplier for speed
+        }
+        switch (CSD[3] & 0x78)
+        {
+            case 0x08: DataLines.frequency(Workspace[0] * 100000); break;
+            case 0x10: DataLines.frequency(Workspace[0] * 120000); break;
+            case 0x18: DataLines.frequency(Workspace[0] * 140000); break;
+            case 0x20: DataLines.frequency(Workspace[0] * 150000); break;
+            case 0x28: DataLines.frequency(Workspace[0] * 200000); break;
+            case 0x30: DataLines.frequency(Workspace[0] * 250000); break;
+            case 0x38: DataLines.frequency(Workspace[0] * 300000); break;
+            case 0x40: DataLines.frequency(Workspace[0] * 350000); break;
+            case 0x48: DataLines.frequency(Workspace[0] * 400000); break;
+            case 0x50: DataLines.frequency(Workspace[0] * 450000); break;
+            case 0x58: DataLines.frequency(Workspace[0] * 500000); break;
+            case 0x60: DataLines.frequency(Workspace[0] * 550000); break;
+            case 0x68: DataLines.frequency(Workspace[0] * 600000); break;
+            case 0x70: DataLines.frequency(Workspace[0] * 700000); break;
+            case 0x78: DataLines.frequency(Workspace[0] * 800000); break;
+            default: break;
+                //read the CSD card speed bits and speed up card operations
+        }
+    }
+    
+    if (!Version)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(16, 512, Workspace);
+                //set data-block length to 512 bytes
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+        ////////////////////////////////////////////implement data block sizing later
+    return 1;
+}
+
+void SDCard::Command(unsigned char Index, unsigned int Argument, unsigned char* Response)
+{
+    ChipSelect.write(0);
+        //assert chip select low to synchronize command
+    DataLines.write(0x40 | Index);
+        //the index is assumed valid, commands start with "01b"
+    DataLines.write(((char*)&Argument)[3]);
+    DataLines.write(((char*)&Argument)[2]);
+    DataLines.write(((char*)&Argument)[1]);
+    DataLines.write(((char*)&Argument)[0]);
+        //send the argument bytes in order from MSB to LSB (mbed is little endian)
+    if (CRCMode)
+    { DataLines.write(CommandCRC(&Index, &Argument)); }
+    else
+    { DataLines.write(0x00); }
+        //send the command CRC
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Response[0] = DataLines.write(0xFF);
+            //clock the card high to let it run operations, the first byte will be
+            //busy (all high), the response will be sent some time later
+        if (!(Response[0] & 0x80))
+            //check for a response by testing if the first bit is low
+        { break; }
+    }
+    if ((Index == 8) || (Index == 13) || (Index == 58))
+    {
+        for (unsigned char j = 1; j < 5; j++)
+        {
+            Response[j] = DataLines.write(0xFF);
+        }
+            //get the rest of the response
+    }
+    ChipSelect.write(1);
+        //assert chip select high to synchronize command
+    DataLines.write(0xFF);
+        //clock the deselected card high to complete processing for some cards
+}
+
+char SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr)
+{
+    return
+        CommandCRCTable[
+            CommandCRCTable[
+                CommandCRCTable[
+                    CommandCRCTable[
+                        CommandCRCTable[
+                            *IndexPtr | 0x40
+                        ] ^ ((char*)ArgumentPtr)[3]
+                    ] ^ ((char*)ArgumentPtr)[2]
+                ] ^ ((char*)ArgumentPtr)[1]
+            ] ^ ((char*)ArgumentPtr)[0]
+        ] | 0x01;
+        //using a CRC table, the CRC result of a byte is equal to the byte in the table at the
+        //address equal to the input byte, a message CRC is obtained by successively XORing these
+        //with the message bytes
+}
+
+void SDCard::DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result)
+{
+    Result[1] = 0x00;
+    Result[2] = 0x00;
+        //initialize result carrier
+    for (int i = 0; i < Length; i++)
+        //step through each byte of the data to be checked
+    {
+        Result[0] = Result[1];
+            //record current crc lookup for both bytes
+        Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
+            //new fist byte result is XORed with old second byte result
+        Result[2] = DataCRCTable[(2 * Result[0]) + 1] ^ Data[i];
+            //new second byte result is XORed with new data byte
+    }
+    for (int i = 0; i < 2; i++)
+        //the final result must be XORed with two 0x00 bytes.
+    {
+        Result[0] = Result[1];
+        Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
+        Result[2] = DataCRCTable[(2 * Result[0]) + 1];
+    }
+}
+
+void SDCard::GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table)
+{
+    unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+        //this will hold information from the generator; the position indicates the
+        //order of the encountered 1, the value indicates its position in the
+        //generator, the 9th entry indicates the number of 1's encountered
+    for (int i = 0; i < 64; i++)
+    {
+        if (((char*)&Generator)[7] & 0x80)
+        { break; }
+        Generator = Generator << 1;
+            //shift generator so that the first bit is high
+    }
+    for (unsigned char k = 0; k < Size; k++)
+    {
+        Table[k] = 0x00;
+            //initialize the first CRC bytes
+    }
+    for (unsigned char i = 0; i < 8; i++)
+        //increment through each generator bit
+    {
+        if ((0x80 >> i) & ((unsigned char*)&Generator)[7])
+            //if a 1 is encountered in the generator
+        {
+            Index[Index[8]] = i;
+            Index[8]++;
+                //record its order and location and increment the counter
+        }
+        for (unsigned char j = 0; j < (0x01 << i); j++)
+            //each bit increases the number of xor operations by a power of 2
+        {
+            for (unsigned char k = 0; k < Size; k++)
+                //we need to perform operations for each byte in the CRC result
+            {
+                Table[(Size * ((0x01 << i) + j)) + k] = Table[(Size * j) + k];
+                    //each new power is equal to all previous entries with an added xor
+                    //on the leftmost bit and each succeeding 1 on the generator
+                for (unsigned char l = 0; l < Index[8]; l++)
+                    //increment through the encountered generator 1s
+                {
+                    Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[7-k] << (i + 1 - Index[l]));
+                    Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[6-k] >> (7 - i + Index[l]));
+                        //xor the new bit and the new generator 1s
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDCard.h	Sun Jul 18 21:26:24 2010 +0000
@@ -0,0 +1,47 @@
+#ifndef SDCardLibrary
+#define SDCardLibrary
+
+#include "stdint.h"
+#include "mbed.h"
+
+class SDCard
+{
+    private:
+        SPI DataLines;
+        DigitalOut ChipSelect;
+        unsigned char CommandCRCTable[256];
+            //CRC7 lookup table
+        unsigned char DataCRCTable[512];
+            //CRC CCITT lookup table
+        unsigned char OCR[4];
+            //operating condition register
+        unsigned char CSD[16];
+            //card-specific data register
+        bool Version;
+            //card version, low for 1, high for 2
+        bool Capacity;
+            //low for low-capacity, high for high-capacity
+        bool CRCMode;
+            //low to disable CRCs, high to enable CRCs
+        unsigned char Workspace[5];
+            //generic information holder
+
+        bool Initialize();
+            //complete all initialization operations, returns 1 if operation successful
+        void Command(unsigned char Index, unsigned int Argument, unsigned char* Response);
+            //sends command to the SD card
+        char CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr);
+        void DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result);
+            //calculates the CRC result of the input with a lookup table
+        void GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table);
+            //pre-calculates CRC results for efficient checking
+
+    public:
+        SDCard(PinName mosi, PinName miso, PinName sck, PinName cs);
+        bool Write(unsigned int Address, unsigned char* Data);
+            //write data to the card
+        bool Read(unsigned int Address, unsigned char* Data);
+            //read data from the card
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jul 18 21:26:24 2010 +0000
@@ -0,0 +1,547 @@
+#include "mbed.h"
+#include "stdint.h"
+
+SPI Card(p5, p6, p7);
+    //mosi, miso, sck
+DigitalOut cs(p8);
+    //chip select
+
+unsigned char OCR[4];
+    //operating condition register
+unsigned char CSD[16];
+    //card-specific data register
+bool Version;
+    //card version, low for 1, high for 2
+bool Capacity;
+    //low for low-capacity, high for high-capacity
+bool CRCMode;
+    //low to disable CRCs, high to enable CRCs
+unsigned char CommandCRCTable[256];
+    //CRC7 lookup table
+unsigned char DataCRCTable[512];
+    //CRC CCITT lookup table
+unsigned char Workspace[5];
+    //generic information holder
+
+//////////////////////////////
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+Serial Computer(USBTX, USBRX);
+    //for testing
+//////////////////////////////
+
+bool Initialize();
+bool Write(unsigned int Address, unsigned char* Data);
+bool Read(unsigned int Address, unsigned char* Data);
+void Command(unsigned char Index, unsigned int Argument, unsigned char* Response);
+char CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr);
+void DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result);
+void GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table);
+
+int main()
+{
+/////////////////////
+    led1 = 0;
+    led2 = 0;
+    led3 = 0;
+    led4 = 0;
+    Computer.baud(9600);
+        //for testing
+    unsigned char wdata[512];
+    unsigned char rdata[512];
+    int testaddress = 9;
+/////////////////////
+    
+    //Initialize();
+    
+    /*for(unsigned short j = 0; j < 512; j++)
+    {
+        wdata[j] = 0x00;
+    }
+    Write(testaddress, wdata);
+    Read(testaddress, rdata);
+    for(unsigned short j = 0; j < 512; j++)
+    {
+        Computer.putc(rdata[j]);
+    }
+    for(unsigned short j = 0; j < 512; j++)
+    {
+        wdata[j] = 0x00 + j;
+    }
+    Write(testaddress, wdata);
+    Read(testaddress, rdata);
+    for(unsigned short j = 0; j < 512; j++)
+    {
+        Computer.putc(rdata[j]);
+    }*/
+
+/////////////////////
+    if (Initialize())
+    {
+        while(1)
+        {
+            led1 = !led1;
+            wait_ms(250);
+            led2 = !led2;
+            wait_ms(250);
+            led3 = !led3;
+            wait_ms(250);
+            led4 = !led4;
+            wait_ms(250);
+        }
+    }//victory dance
+    else
+    {
+        while(1)
+        {
+            
+            led1 = !led1;
+            led2 = !led2;
+            led3 = !led3;
+            led4 = !led4;
+            wait_ms(250);
+        }
+    }//failure
+        //for testing
+/////////////////////
+}
+
+bool Initialize()
+{
+    Card.frequency(100000);
+        //set universal speed
+    cs = 1;
+        //chip select is active low
+    CRCMode = 1;
+        //turn cyclic redundancy checks on
+
+    GenerateCRCTable(1, 137, CommandCRCTable);
+        //generate the command crc lookup table
+        //(generator polynomial x^7 + x^3 + 1 converts to decimal 137)
+    GenerateCRCTable(2, 69665, DataCRCTable);
+        //generate the command crc lookup table
+        //(generator polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665)
+            
+    for (unsigned char j = 0; j < 16; j++)
+    {
+        Card.write(0xFF);
+    }
+        //perform specified power up sequence
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(0, 0, Workspace);
+            //send command 0 to put the card into SPI mode
+        if (Workspace[0] == 0x01)
+            //check for idle mode
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Computer.putc(0x1F);
+    Computer.putc(Workspace[0]);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(8, 426, Workspace);
+            //voltage bits are 0x01 for 2.7V - 3.6V,
+            //check pattern 0xAA, [00,00,01,AA] = 426
+        if ((Workspace[0] == 0x05) || ((Workspace[0] == 0x01) &&
+            ((Workspace[3] & 0x0F) == 0x01) && (Workspace[4] == 0xAA)))
+            //check version, voltage acceptance, and check pattern
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Version = Workspace[0] == 0x01;
+        //store card version
+    Computer.putc(0x3F);
+    Computer.putc(Workspace[0]);
+    Computer.putc(Version);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(58, 0, Workspace);
+            //check the OCR
+        if ((Workspace[0] == 0x01) && ((Workspace[2] & 0x20) || (Workspace[2] & 0x10)))
+            //check for correct operating voltage 3.3V
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Computer.putc(0x4F);
+    Computer.putc(Workspace[0]);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(59, 1, Workspace);
+            //send command 59 to turn on CRCs
+    Computer.putc(Workspace[0]);
+        if (Workspace[0] == 0x01)
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Computer.putc(0x2F);
+    Computer.putc(Workspace[0]);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(55, 0, Workspace);
+            //specify application-specific command
+        Command(41, 1073741824, Workspace);
+            //specify host supports high capacity cards
+            //[40,00,00,00] = 1073741824
+        if (Workspace[0] == 0x00)
+            //check if card is ready
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Computer.putc(0x5F);
+    Computer.putc(Workspace[0]);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(58, 0, Workspace);
+            //check the OCR again
+        if ((Workspace[0] == 0x00) && (Workspace[1] & 0x80))
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    for (unsigned char j = 0; j < 4; j++)
+    {
+        OCR[j] = Workspace[j + 1];
+    }
+        //record OCR
+    Capacity = (OCR[0] & 0x40) == 0x40;
+        //record capacity
+    Computer.putc(0x6F);
+    Computer.putc(Workspace[0]);
+    Computer.putc(Capacity);
+    
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Command(9, 0, Workspace);
+            //read the card-specific data register
+        cs = 0;
+        for (unsigned int k = 0; k < 8192; k++)
+        {
+            if (Card.write(0xFF) == 0xFE)
+            { break; }
+        }
+            //get to the start-data-block token
+        for (unsigned char k = 0; k < 16; k++)
+        {
+            CSD[k] = Card.write(0xFF);
+        }
+        Workspace[3] = Card.write(0xFF);
+        Workspace[4] = Card.write(0xFF);
+        cs = 1;
+        Card.write(0xFF);
+        DataCRC(16, CSD, Workspace);
+            //calculate the CSD data CRC
+        Workspace[0] = 0;
+        for (unsigned char k = 0; k < 15; k++)
+        {
+            Workspace[0] = CommandCRCTable[Workspace[0]] ^ CSD[k];
+        }
+        Workspace[0] = CommandCRCTable[Workspace[0]] | 0x01;
+        if ((Workspace[0] == CSD[15]) && (Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
+        { break; }
+        if (j == 8191)
+        { return 0; }
+    }
+    Computer.putc(0x7F);
+    Computer.putc(Workspace[0]);
+    Computer.putc(CSD[3] & 0x7F);
+    
+    if (((CSD[3] & 0x07) > 2) || ((CSD[3] & 0x7F) > 0x32))
+    {
+        Card.frequency(25000000);
+            //maximum speed is given at 25MHz
+    }
+    else
+    {
+       Workspace[0] = 1;
+        for (unsigned char j = 0; j < (CSD[3] & 0x07); j++)
+        {
+            Workspace[0] *= 10;
+                //the first three bits are a power of ten multiplier for speed
+        }
+        switch (CSD[3] & 0x78)
+        {
+            case 0x08: Card.frequency(Workspace[0] * 100000); break;
+            case 0x10: Card.frequency(Workspace[0] * 120000); break;
+            case 0x18: Card.frequency(Workspace[0] * 140000); break;
+            case 0x20: Card.frequency(Workspace[0] * 150000); break;
+            case 0x28: Card.frequency(Workspace[0] * 200000); break;
+            case 0x30: Card.frequency(Workspace[0] * 250000); break;
+            case 0x38: Card.frequency(Workspace[0] * 300000); break;
+            case 0x40: Card.frequency(Workspace[0] * 350000); break;
+            case 0x48: Card.frequency(Workspace[0] * 400000); break;
+            case 0x50: Card.frequency(Workspace[0] * 450000); break;
+            case 0x58: Card.frequency(Workspace[0] * 500000); break;
+            case 0x60: Card.frequency(Workspace[0] * 550000); break;
+            case 0x68: Card.frequency(Workspace[0] * 600000); break;
+            case 0x70: Card.frequency(Workspace[0] * 700000); break;
+            case 0x78: Card.frequency(Workspace[0] * 800000); break;
+            default: break;
+                //read the csd card speed bits and speed up card operations
+        }
+    }
+    
+    if (!Version)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(16, 512, Workspace);
+                //set data-block length to 512 bytes
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    Computer.putc(0x8F);
+    Computer.putc(Workspace[0]);
+        ////////////////////////////////////////////implement data block sizing later
+    return 1;
+}
+
+bool Write(unsigned int Address, unsigned char* Data)
+{
+    if (Capacity)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(24, Address, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(24, Address * 512, Workspace);///////////implement block length
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    cs = 0;
+    Card.write(0xFE);
+        //start data block token
+    for (unsigned short j = 0; j < 512; j++)
+    {
+        Card.write(Data[j]);
+            //write the data
+    }
+    DataCRC(512, Data, Workspace);
+    Card.write(Workspace[1]);
+    Card.write(Workspace[2]);
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Workspace[0] = Card.write(0xFF);
+        if ((Workspace[0] & 0x1F) == 0x05)
+        { break; }
+    }
+    while (!Card.write(0xFF));
+    cs = 1;
+    Card.write(0xFF);
+    if ((Workspace[0] & 0x1F) == 0x05)
+    { return 1; }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(13, 0, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+        }
+        return 0;
+    }
+}
+
+bool Read(unsigned int Address, unsigned char* Data)
+{
+    if (Capacity)
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(17, Address, Workspace);
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    else
+    {
+        for (unsigned int j = 0; j < 8192; j++)
+        {
+            Command(17, Address * 512, Workspace);///////////implement block length
+            if (Workspace[0] == 0x00)
+            { break; }
+            if (j == 8191)
+            { return 0; }
+        }
+    }
+    cs = 0;
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        if (Card.write(0xFF) == 0xFE)
+        { break; }
+    }
+    for (unsigned short j = 0; j < 512; j++)
+    {
+        Data[j] = Card.write(0xFF);
+    }
+    Workspace[3] = Card.write(0xFF);
+    Workspace[4] = Card.write(0xFF);
+    cs = 1;
+    Card.write(0xFF);
+    DataCRC(512, Data, Workspace);
+    if ((Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
+    { return 1; }
+    else
+    { return 0; }
+}
+
+void Command(unsigned char Index, unsigned int Argument, unsigned char* Response)
+{
+    cs = 0;
+        //assert chip select low to synchronize command
+    Card.write(0x40 | Index);
+        //the index is assumed valid, commands start with "01b"
+    Card.write(((char*)&Argument)[3]);
+    Card.write(((char*)&Argument)[2]);
+    Card.write(((char*)&Argument)[1]);
+    Card.write(((char*)&Argument)[0]);
+        //send the argument bytes in order from MSB to LSB (mbed is little endian)
+    if (CRCMode)
+    { Card.write(CommandCRC(&Index, &Argument)); }
+    else
+    { Card.write(0x00); }
+        //send the command CRC
+    for (unsigned int j = 0; j < 8192; j++)
+    {
+        Response[0] = Card.write(0xFF);
+            //clock the card high to let it run operations, the first byte will be
+            //busy (all high), the response will be sent some time later
+        if (!(Response[0] & 0x80))
+            //check for a response by testing if the first bit is low
+        { break; }
+    }
+    if ((Index == 8) || (Index == 13) || (Index == 58))
+    {
+        for (unsigned char j = 1; j < 5; j++)
+        {
+            Response[j] = Card.write(0xFF);
+        }
+            //get the rest of the response
+    }
+    cs = 1;
+        //assert chip select high to synchronize command
+    Card.write(0xFF);
+        //clock the deselected card high to complete processing for some cards
+}
+    
+char CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr)
+{
+    return
+        CommandCRCTable[
+            CommandCRCTable[
+                CommandCRCTable[
+                    CommandCRCTable[
+                        CommandCRCTable[
+                            *IndexPtr | 0x40
+                        ] ^ ((char*)ArgumentPtr)[3]
+                    ] ^ ((char*)ArgumentPtr)[2]
+                ] ^ ((char*)ArgumentPtr)[1]
+            ] ^ ((char*)ArgumentPtr)[0]
+        ] | 0x01;
+        //using a CRC table, the CRC result of a byte is equal to the byte in the table at the
+        //address equal to the input byte, a message CRC is obtained by successively XORing these
+        //with the message bytes
+}
+
+void DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result)
+{
+    Result[1] = 0x00;
+    Result[2] = 0x00;
+        //initialize result carrier
+    for (int i = 0; i < Length; i++)
+        //step through each byte of the data to be checked
+    {
+        Result[0] = Result[1];
+            //record current crc lookup for both bytes
+        Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
+            //new fist byte result is XORed with old second byte result
+        Result[2] = DataCRCTable[(2 * Result[0]) + 1] ^ Data[i];
+            //new second byte result is XORed with new data byte
+    }
+    for (int i = 0; i < 2; i++)
+        //the final result must be XORed with two 0x00 bytes.
+    {
+        Result[0] = Result[1];
+        Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
+        Result[2] = DataCRCTable[(2 * Result[0]) + 1];
+    }
+}
+
+void GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table)
+{
+    unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+        //this will hold information from the generator; the position indicates the
+        //order of the encountered 1, the value indicates its position in the
+        //generator, the 9th entry indicates the number of 1's encountered
+    for (int i = 0; i < 64; i++)
+    {
+        if (((char*)&Generator)[7] & 0x80)
+        { break; }
+        Generator = Generator << 1;
+            //shift generator so that the first bit is high
+    }
+    for (unsigned char k = 0; k < Size; k++)
+    {
+        Table[k] = 0x00;
+            //initialize the first CRC bytes
+    }
+    for (unsigned char i = 0; i < 8; i++)
+        //increment through each generator bit
+    {
+        if ((0x80 >> i) & ((unsigned char*)&Generator)[7])
+            //if a 1 is encountered in the generator
+        {
+            Index[Index[8]] = i;
+            Index[8]++;
+                //record its order and location and increment the counter
+        }
+        for (unsigned char j = 0; j < (0x01 << i); j++)
+            //each bit increases the number of xor operations by a power of 2
+        {
+            for (unsigned char k = 0; k < Size; k++)
+                //we need to perform operations for each byte in the CRC result
+            {
+                Table[(Size * ((0x01 << i) + j)) + k] = Table[(Size * j) + k];
+                    //each new power is equal to all previous entries with an added xor
+                    //on the leftmost bit and each succeeding 1 on the generator
+                for (unsigned char l = 0; l < Index[8]; l++)
+                    //increment through the encountered generator 1s
+                {
+                    Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[7-k] << (i + 1 - Index[l]));
+                    Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[6-k] >> (7 - i + Index[l]));
+                        //xor the new bit and the new generator 1s
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Jul 18 21:26:24 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/3944f1e2fa4f