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

Revision:
5:d85e20b6b904
Parent:
4:9a5878d316d5
Child:
6:ddf09d859ed7
--- a/SDCard.cpp	Fri Aug 27 00:59:28 2010 +0000
+++ b/SDCard.cpp	Sat Jan 15 05:58:22 2011 +0000
@@ -5,8 +5,9 @@
 
 #include "SDCard.h"
 
-SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs, const char* DiskName) :
-    FATFileSystem(DiskName), DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1), Timeout(1024)
+SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs,
+    const char* DiskName) : FATFileSystem(DiskName),
+    DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1), Timeout(1024)
 {
     DataLines.frequency(100000);
         //set universal speed
@@ -14,10 +15,10 @@
         //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)
+        //(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)
+        //generate the data crc lookup table;
+        //(polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665)
     Initialize();
         //run card setup operations
 }
@@ -43,11 +44,11 @@
 unsigned char SDCard::disk_read(
     unsigned char* buff, unsigned long sector, unsigned char count)
 { return Read((unsigned int)sector, count, buff); }
-    //read operations must efficiently complete multiple sector transactions
+    //multiple sector read transaction
 unsigned char SDCard::disk_write(
     const unsigned char* buff, unsigned long sector, unsigned char count)
 { return Write((unsigned int)sector, count, (unsigned char*)buff); }
-    //write operations must efficiently complete multiple sector transactions
+    //multiple sector write transaction
 unsigned char SDCard::disk_sync()
 { return 0x00; }
     //all disc functions are synchronous
@@ -56,11 +57,14 @@
     switch (CSD[0] & 0xC0)
     {
         case 0x00:
-            return ((((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1)
-                * (1 << ((((CSD[9] & 0x03) << 1) | ((CSD[10] & 0x80) >> 7)) + 2));
+            return ((((CSD[6] & 0x03) << 10) | (CSD[7] << 2)
+                | ((CSD[8] & 0xC0) >> 6)) + 1)
+                * (1 << ((((CSD[9] & 0x03) << 1)
+                | ((CSD[10] & 0x80) >> 7)) + 2));
                 //calculate sector count as specified for version 1 cards
         case 0x40:
-            return ((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1) * 1024;
+            return ((((CSD[7] & 0x3F) << 16)
+                | (CSD[8] << 8) | CSD[9]) + 1) * 1024;
                 //calculate sector count as specified for version 2 cards
         default:
             return 0;
@@ -79,7 +83,8 @@
                 //calculate erase sector size for version 1 cards
         case 0x40:
             return 1;
-                //erase sector size is given by allocation unit for version 2 cards
+                //erase sector size is given by
+                //allocation unit for version 2 cards
         default:
             return 0;
     }
@@ -94,22 +99,23 @@
         //store last written byte number of current memory block
 
     if (CRCMode)
+        //CRC's are not used in raw data mode
     {
         SelectCRCMode(0);
     }
-        //CRC's are not used in raw data mode
 
     switch (Control)
     {
         case 0x00:
+                //control code 0x00 synchronizes the card
             if (Mode)
             {
                 ChipSelect.write(0);
                 for (; Index < 512; Index++)
+                    //get through left over space, filling with FFh
                 {
                     DataLines.write(0xFF);
                 }
-                    //get through left over space, filling with 0xFF for write blocks
                 DataLines.write(0xFF);
                 DataLines.write(0xFF);
                     //get through CRC
@@ -121,7 +127,8 @@
                     do
                     {
                         t++;
-                    } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout));
+                    } while (((DataLines.write(0xFF) & 0x11) != 0x01)
+                        && (t < Timeout));
                         //get through data response token
                     while (!DataLines.write(0xFF));
                         //get through busy signal
@@ -147,21 +154,24 @@
                     //finish read block
                 Index = 0;
                 Mode = 0x00;
-                    //reset index to start and mode to synced
+                    //reset index to start and mode to synchronized
             }
             return 0xFF;
-                //control code 0 synchronizes the card
 
         case 0x01:
+                //control code 1 writes a byte
             if (Mode != 0x01)
+                //if previous call was not a write operation, synchronize
+                //the card, start a new write block, and set function to
+                //write mode
             {
                 Log(0, 0);
                 Command(25, 0, Workspace);
                 Mode = 0x01;
             }
-                //if previous call was not a write operation, sync the card,
-                //start a new write block, and set function to write mode
             if (Index == 0)
+                //if the index is at the start, send the start block token
+                //before the byte
             {
                 ChipSelect.write(0);
                 DataLines.write(0xFC);
@@ -169,16 +179,17 @@
                 ChipSelect.write(1);
                 Index++;
             }
-                //if the index is at the start, send the start block token before the byte
             else if (Index < 511)
+                //if the index is between the boundaries, write the byte
             {
                 ChipSelect.write(0);
                 DataLines.write(Data);
                 ChipSelect.write(1);
                 Index++;
             }
-                //if the index is between the boundaries, simply write the byte
             else
+                //if the index is at the last address, get through CRC,
+                //Data response token, and busy signal and reset the index
             {
                 ChipSelect.write(0);
                 DataLines.write(Data);
@@ -188,40 +199,43 @@
                 do
                 {
                     t++;
-                } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout));
+                } while (((DataLines.write(0xFF) & 0x11) != 0x01)
+                    && (t < Timeout));
                 while (!DataLines.write(0xFF));
                 ChipSelect.write(1);
                 Index = 0;
             }
-                //if the index is at the last address, get through CRC,
-                //Data response token, and busy signal and reset the index
             return 0xFF;
-                //return stuff bits; control code 1 writes a byte
 
         case 0x02:
+            //control code 2 reads a byte
             if (Mode != 0x02)
+                //if previous call was not a read operation, synchronise
+                //the card, start a new read block, and set function to
+                //read mode
             {
                 Log(0, 0);
                 Command(18, 0, Workspace);
                 Mode = 0x02;
             }
-                //if previous call was not a read operation, sync the card,
-                //start a new read block, and set function to read mode
             if (Index == 0)
+                //if the index is at the start, get the start block token
+                //and read the first byte
             {
                 ChipSelect.write(0);
                 t = 0;
                 do
                 {
                     t++;
-                } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
+                } while ((DataLines.write(0xFF) != 0xFE)
+                    && (t < Timeout));
                 Workspace[0] = DataLines.write(0xFF);
                 ChipSelect.write(1);
                 Index++;
                 return Workspace[0];
             }
-                //if the index is at the start, get the start block token and read the first byte
             else if (Index < 511)
+                //if the index is between the boundaries, read the byte
             {
                 ChipSelect.write(0);
                 Workspace[0] = DataLines.write(0xFF);
@@ -229,8 +243,9 @@
                 Index++;
                 return Workspace[0];
             }
-                //if the index is between the boundaries, simply read the byte
             else
+                //if the index is at the last address, get through
+                //CRC and reset the index
             {
                 ChipSelect.write(0);
                 Workspace[0] = DataLines.write(0xFF);
@@ -240,12 +255,10 @@
                 Index = 0;
                 return Workspace[0];
             }
-                //if the index is at the last address, get through
-                //CRC and reset the index; control code 2 reads a byte
 
         default:
+            //undefined control codes only return stuff bits
             return 0xFF;
-                //return stuff bits
     }
 }
 
@@ -259,20 +272,20 @@
     {
         Command(24, Address, Workspace);
     }
-        //send single block write command; addressing depends on the card version
+        //send single block write command; addressing depends on version
     if (Workspace[0])
+        //if a command error occurs, return parameter error
     { return 0x04; }
-        //if a command error occurs, return parameter error
     DataCRC(512, Data, Workspace);
         //calculate the data CRC
     ChipSelect.write(0);
     DataLines.write(0xFE);
         //write start block token
     for (unsigned short i = 0; i < 512; i++)
+        //write the data to the addressed card sector
     {
         DataLines.write(Data[i]);
     }
-        //write the data to the addressed card sector
     DataLines.write(Workspace[0]);
     DataLines.write(Workspace[1]);
         //write the data CRC to the card
@@ -288,16 +301,19 @@
     ChipSelect.write(1);
     DataLines.write(0xFF);
     if (((Workspace[0] & 0x1F) != 0x05) || (t == Timeout))
+        //if data response token indicates error, return write error
     { return 0x01; }
     else
     { return 0x00; }
-        //if data response token indicates error, return R/W error
 }
-unsigned char SDCard::Write(unsigned int Address, unsigned char SectorCount, unsigned char* Data)
+unsigned char SDCard::Write(
+    unsigned int Address, unsigned char SectorCount, unsigned char* Data)
 {
     static unsigned char CurrentSectorCount = 1;
         //store the last write sector count
     if (SectorCount != CurrentSectorCount)
+        //set the expected number of write blocks if different from
+        //previous operations
     {
         Command(55, 0, Workspace);
         Command(23, SectorCount, Workspace);
@@ -305,7 +321,6 @@
         { return 0x04; }
         CurrentSectorCount = SectorCount;
     }
-        //set the expected number of write blocks if different from previous operations
     if (!Capacity)
     {
         Command(25, Address * 512, Workspace);
@@ -314,10 +329,14 @@
     {
         Command(25, Address, Workspace);
     }
+        //send multiple block write command; addressing depends on version
     if (Workspace[0])
+        //if a command error occurs, return parameter error
     { return 0x04; }
     Workspace[4] = 0x00;
+        //initialize error detection variable
     for (unsigned char i = 0; i < SectorCount; i++)
+        //write each data sector
     {
         DataCRC(512, &Data[i * 512], Workspace);
             //calculate data crc for each passed write block
@@ -325,41 +344,40 @@
         DataLines.write(0xFC);
             //send multiple write block start token
         for (unsigned int j = i * 512; j < (i + 1) * 512; j++)
+            //write each data block
         {
             DataLines.write(Data[j]);
         }
-            //write each data block
         DataLines.write(Workspace[0]);
         DataLines.write(Workspace[1]);
+            //write the data CRC to the card
         t = 0;
         do
         {
             Workspace[0] = DataLines.write(0xFF);
             t++;
         } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout));
+            //gather the data block response token
         while (!DataLines.write(0xFF));
+            //get through the busy signal
         ChipSelect.write(1);
         Workspace[4] |= Workspace[0];
-            //record if any write errors are detected in the data response tokens
+            //record if any write errors are detected in the data response
+            //tokens
         if (t == Timeout)
-        {
-            ChipSelect.write(0);
-            DataLines.write(0xFD);
-            DataLines.write(0xFF);
-            while (!DataLines.write(0xFF));
-            ChipSelect.write(1);
-            DataLines.write(0xFF);
-            return 0x01;
-        }
-            //if a block write operation gets timed out, make sure the card is synced and exit
+            //if a block write operation gets timed out, stop operations
+        { break; }
     }
     ChipSelect.write(0);
     DataLines.write(0xFD);
     DataLines.write(0xFF);
+        //send stop transmission token
     while (!DataLines.write(0xFF));
+        //get through busy signal
     ChipSelect.write(1);
     DataLines.write(0xFF);
-    if ((Workspace[4] & 0x1F) != 0x05)
+    if (((Workspace[4] & 0x1F) != 0x05) || (t == Timeout))
+        //if a data response token indicated an error, return write error
     { return 0x01; }
     else
     { return 0x00; }
@@ -375,18 +393,19 @@
     {
         Command(17, Address, Workspace);
     }
-        //send single block read command; addressing depends on the card version
+        //send single block read command; addressing depends on version
     if (Workspace[0])
+        //if a command error occurs, return parameter error
     { return 0x04; }
-        //if a command error occurs, return parameter error
     ChipSelect.write(0);
     t = 0;
     do
     {
         t++;
     } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
-    if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
         //get to start block token
+    if (t == Timeout) {
+        ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
     for (unsigned short i = 0; i < 512; i++)
     {
         Data[i] = DataLines.write(0xFF);
@@ -394,18 +413,20 @@
         //read the data from the addressed card sector
     Workspace[2] = DataLines.write(0xFF);
     Workspace[3] = DataLines.write(0xFF);
-        //read the data CRC to the card
+        //read the data CRC from the card
     ChipSelect.write(1);
     DataLines.write(0xFF);
     DataCRC(512, Data, Workspace);
         //calculate the data CRC
-    if (CRCMode && ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])))
+    if (CRCMode && ((Workspace[0] != Workspace[2])
+        || (Workspace[1] != Workspace[3])))
+        //if CRC is invalid, return read error
     { return 0x01; }
     else
     { return 0x00; }
-        //if CRC is invalid, return R/W error
 }
-unsigned char SDCard::Read(unsigned int Address, unsigned char SectorCount, unsigned char* Data)
+unsigned char SDCard::Read(
+    unsigned int Address, unsigned char SectorCount, unsigned char* Data)
 {
     if (!Capacity)
     {
@@ -415,10 +436,14 @@
     {
         Command(18, Address, Workspace);
     }
+        //send multiple block read command; addressing depends on version
     if (Workspace[0])
+        //if a command error occurs, return parameter error
     { return 0; }
     Workspace[4] = 0x00;
+        //initialize error detection variable
     for (unsigned char i = 0; i < SectorCount; i++)
+        //read each data sector
     {
         ChipSelect.write(0);
         t = 0;
@@ -429,15 +454,9 @@
             //get to each data block start token
         if (t == Timeout)
         {
-            ChipSelect.write(1);
-            Command(12, 0, Workspace);
-            ChipSelect.write(0);
-            while (!DataLines.write(0xFF));
-            ChipSelect.write(1);
-            DataLines.write(0xFF);
-            return 0x01;
+            break;
         }
-            //if a block read operation gets timed out, make sure the card is synced and exit
+            //if a block read operation gets timed out, stop operations
         for (unsigned int j = i * 512; j < (i + 1) * 512; j++)
         {
             Data[j] = DataLines.write(0xFF);
@@ -445,17 +464,24 @@
             //read each data block
         Workspace[2] = DataLines.write(0xFF);
         Workspace[3] = DataLines.write(0xFF);
-        ChipSelect.write(1);
+            //read the data CRC from the card
         DataCRC(512, &Data[i * 512], Workspace);
             //calculate data crc for each read data block
-        Workspace[4] |= ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]));
-            //record if any invalid CRCs are detected during the transaction
+        Workspace[4] |= (CRCMode && ((Workspace[0] != Workspace[2])
+            || (Workspace[1] != Workspace[3])));
+            //record if any invalid CRCs are detected during the
+            //transaction
     }
+    ChipSelect.write(1);
     Command(12, 0, Workspace);
+        //send stop transmission command
     ChipSelect.write(0);
     while (!DataLines.write(0xFF));
+        //get through busy signal
     ChipSelect.write(1);
-    if (Workspace[4])
+    DataLines.write(0xFF);
+    if ((Workspace[4]) || (t == Timeout))
+        //if an invalid CRC was detected, return read error
     { return 0x01; }
     else
     { return 0x00; }
@@ -463,33 +489,39 @@
 
 unsigned char SDCard::SelectCRCMode(bool Mode)
 {
-    t = 0;
-    do
+    unsigned char Response;
+    if (CRCMode != Mode)
+        //only send command if CRCMode has been changed
     {
-        Command(59, Mode, Workspace);
-            //command 59 sets card CRC mode
-        t++;
-    } while (Workspace[0] && (t < Timeout));
-    CRCMode = Mode;
+        t = 0;
+        do
+        {
+            Command(59, Mode, &Response);
+                //command 59 sets card CRC mode
+            t++;
+        } while (Response && (t < Timeout));
+        CRCMode = Mode;
+    }
     if (t == Timeout)
+        //if command times out, return error
     { return 0x01; }
     else
     { return 0x00; }
-        //if command times out, return error
 }
 
 void SDCard::SetTimeout(unsigned int Retries)
 {
     Timeout = Retries;
 }
-    //set c=number of retries for card operations
 
 unsigned char SDCard::Initialize()
 {
+    unsigned char Workspace[5];
+        //allocate space to hold data during initialization operations
     for (unsigned char i = 0; i < 16; i++)
+        //clock card at least 74 times to power up
     {
         DataLines.write(0xFF);
-            //clock card at least 74 times to power up
     }
 
     t = 0;
@@ -499,6 +531,7 @@
             //send command 0 to put the card into SPI mode
         t++;
     } while ((Workspace[0] != 0x01) && (t < Timeout));
+        //check for command acceptance
     if (t == Timeout) { return 0x01; }
 
     t = 0;
@@ -507,7 +540,8 @@
         Command(59, 1, Workspace);
             //turn on CRCs
         t++;
-    } while ((Workspace[0] != 0x01) && (Workspace[0] != 0x05) && (t < Timeout));
+    } while ((Workspace[0] != 0x01) && (Workspace[0] != 0x05)
+        && (t < Timeout));
         //command 59 is not valid for all cards in idle state
     if (t == Timeout) { return 0x01; }
 
@@ -515,16 +549,29 @@
     do
     {
         Command(8, 426, Workspace);
-            //voltage bits are 0x01 for 2.7V - 3.6V,
-            //check pattern 0xAA, [00,00,01,AA] = 426
+            //voltage bits are 01h for 2.7V - 3.6V,
+            //check pattern AAh, 000001AAh = 426d
         t++;
     } while (((Workspace[0] != 0x01) || ((Workspace[3] & 0x0F) != 0x01) ||
-        (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05) && (t < Timeout));
+        (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05)
+        && (t < Timeout));
         //check version, voltage acceptance, and check pattern
     if (t == Timeout) { return 0x01; }
     Version = Workspace[0] != 0x05;
         //store card version
 
+    if (!Version)
+    {
+        t = 0;
+        do
+        {
+            Command(16, 512, Workspace);
+                //set data-block length to 512 bytes
+            t++;
+        } while (Workspace[0] && (t < Timeout));
+        if (t == Timeout) { return 0x01; }
+    }
+
     t = 0;
     do
     {
@@ -532,7 +579,8 @@
             //check the OCR
         t++;
     } while (((Workspace[0] != 0x01) ||
-        !((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) && (t < Timeout));
+        !((Workspace[2] & 0x20) || (Workspace[2] & 0x10)))
+        && (t < Timeout));
         //check for correct operating voltage 3.3V
     if (t == Timeout) { return 0x01; }
 
@@ -540,16 +588,18 @@
     do
     {
         Command(55, 0, Workspace);
+            //command 41 is application-specific
         Command(41, 1073741824, Workspace);
-            //specify host supports high capacity cards, [40,00,00,00] = 1073741824
+            //specify host supports high capacity cards,
+            //40000000h = 1073741824d
         t++;
     } while (Workspace[0] && (t < Timeout));
         //check if card is ready
     if (t == Timeout) { return 0x01; }
 
     if (SelectCRCMode(1))
+        //turn on CRCs for all cards
     { return 0x01; }
-        //turn on CRCs for all cards
 
     t = 0;
     do
@@ -561,9 +611,9 @@
         //check power up status
     if (t == Timeout) { return 0x01; }
     for (unsigned char i = 0; i < 4; i++)
+        //record OCR
     {
         OCR[i] = Workspace[i + 1];
-            //record OCR
     }
     Capacity = (OCR[0] & 0x40) == 0x40;
         //record capacity
@@ -584,11 +634,12 @@
             t++;
         } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
             //get to the start-data-block token
-        if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
+        if (t == Timeout) {
+            ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
         for (unsigned char i = 0; i < 16; i++)
+            //gather CSD
         {
             CSD[i] = DataLines.write(0xFF);
-                //gather CSD
         }
         Workspace[2] = DataLines.write(0xFF);
         Workspace[3] = DataLines.write(0xFF);
@@ -605,24 +656,26 @@
         Workspace[4] = CommandCRCTable[Workspace[4]] | 0x01;
             //calculate the CSD table CRC
         t++;
-    } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]) ||
-        (Workspace[4] != CSD[15])) && (t < Timeout));
+    } while (((Workspace[0] != Workspace[2])
+        || (Workspace[1] != Workspace[3]) || (Workspace[4] != CSD[15]))
+        && (t < Timeout));
         //check all CSD CRCs
     if (t == Timeout) { return 0x01; }
 
     if (((CSD[3] & 0x07) > 0x02) ||
         (((CSD[3] & 0x78) > 0x30) && ((CSD[3] & 0x07) > 0x01)))
+        //read the CSD card speed bits and speed up card operations
     {
         DataLines.frequency(25000000);
-            //maximum speed is 25MHz
+            //maximum frequency is 25MHz
     }
     else
     {
-       Workspace[0] = 1;
+        Workspace[0] = 1;
         for (unsigned char i = 0; i < (CSD[3] & 0x07); i++)
         {
             Workspace[0] *= 10;
-                //the first three bits are a power of ten multiplier for speed
+                //first three bits are a power of ten multiplier for speed
         }
         switch (CSD[3] & 0x78)
         {
@@ -642,7 +695,6 @@
             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
         }
     }
 
@@ -656,7 +708,8 @@
                 //switch to high-speed mode (SDR25, 50MHz)
             t++;
         } while (Workspace[0] && (Workspace[0] != 0x04) && (t < Timeout));
-            //some cards that support switch class commands respond with illegal command
+            //some cards that support switch class commands respond with
+            //illegal command
         if (t == Timeout) { return 0x01; }
         if (!Workspace[0])
         {
@@ -668,11 +721,12 @@
                     t++;
                 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
                     //get to the start-data-block token
-                if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
+                if (t == Timeout) { ChipSelect.write(1);
+                    DataLines.write(0xFF); return 0x01; }
                 for (unsigned char i = 0; i < 64; i++)
+                    //gather function-status register
                 {
                     FSR[i] = DataLines.write(0xFF);
-                        //gather function-status register
                 }
                 Workspace[2] = DataLines.write(0xFF);
                 Workspace[3] = DataLines.write(0xFF);
@@ -682,8 +736,8 @@
                 DataCRC(64, FSR, Workspace);
                     //calculate CRC
                 t++;
-            } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])) &&
-                (t < Timeout));
+            } while (((Workspace[0] != Workspace[2])
+                || (Workspace[1] != Workspace[3])) && (t < Timeout));
                 //complete CRC
             if (t == Timeout) { return 0x01; }
             if ((FSR[13] & 0x02) && ((FSR[16] & 0x0F) == 0x01))
@@ -694,18 +748,6 @@
         }
     }
 
-    if (!Version)
-    {
-        t = 0;
-        do
-        {
-            Command(16, 512, Workspace);
-                //set data-block length to 512 bytes
-            t++;
-        } while (Workspace[0] && (t < Timeout));
-        if (t == Timeout) { return 0x01; }
-    }
-
     if (SelectCRCMode(0))
     { return 0x01; }
         //turn off CRCs
@@ -713,9 +755,10 @@
     return 0x00;
 }
 
-void SDCard::Command(unsigned char Index, unsigned int Argument, unsigned char* Response)
+void SDCard::Command(unsigned char Index,
+    unsigned int Argument, unsigned char* Response)
 {
-    CommandCRC(&Index, &Argument, Workspace);
+    CommandCRC(&Index, &Argument, Response);
         //calculate command CRC
     ChipSelect.write(0);
         //assert chip select low to synchronize command
@@ -725,25 +768,25 @@
     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)
-    DataLines.write(Workspace[0]);
+        //send the argument bytes in order from MSB to LSB
+    DataLines.write(*Response);
         //send the command CRC
     t = 0;
     do
     {
         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
+            //clock the card high to let it run operations, the first byte
+            //will be busy (all high), the response will be sent later
         t++;
     } while ((Response[0] & 0x80) && (t < Timeout));
         //check for a response by testing if the first bit is low
     if ((Index == 8) || (Index == 13) || (Index == 58))
+        //if the command returns a larger response, get the rest of it
     {
         for (unsigned char i = 1; i < 5; i++)
         {
             Response[i] = DataLines.write(0xFF);
         }
-            //get the rest of the response
     }
     ChipSelect.write(1);
         //assert chip select high to synchronize command
@@ -751,9 +794,11 @@
         //clock the deselected card high to complete processing for some cards
 }
 
-void SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr, unsigned char* Result)
+void SDCard::CommandCRC(unsigned char* IndexPtr,
+    unsigned int* ArgumentPtr, unsigned char* Result)
 {
     if (CRCMode)
+        //only calculate if data-checks are desired
     {
         Result[0] =
             CommandCRCTable[
@@ -767,19 +812,20 @@
                     ] ^ ((char*)ArgumentPtr)[1]
                 ] ^ ((char*)ArgumentPtr)[0]
             ] | 0x01;
+            //calculate CRC, SD card protocol requires last bit to be 1
     }
     else
+        //record stuff bits if no data-checking is desired
     {
         Result[0] = 0xFF;
     }
-        //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)
+void SDCard::DataCRC(
+    unsigned short Length, unsigned char* Data, unsigned char* Result)
 {
     if (CRCMode)
+        //only calculate if data-checks are desired
     {
         unsigned char Reference;
             //store the current CRC lookup value
@@ -792,12 +838,12 @@
             Reference = Result[0];
                 //record current crc lookup for both bytes
             Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
-                //new fist byte result is XORed with old second byte result
+                //fist byte result is exclusive ored with old second byte
             Result[1] = DataCRCTable[(2 * Reference) + 1] ^ Data[i];
-                //new second byte result is XORed with new data byte
+                //second byte result is exclusive ored with new data byte
         }
         for (unsigned char i = 0; i < 2; i++)
-            //the final result must be XORed with two 0x00 bytes.
+            //the final result must be exclusive ored with two 0x00 bytes
         {
             Reference = Result[0];
             Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
@@ -805,29 +851,32 @@
         }
     }
     else
+        //record stuff bits if no data-checking is desired
     {
         Result[0] = 0xFF;
         Result[1] = 0xFF;
     }
 }
 
-void SDCard::GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table)
+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
+        //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 (unsigned char i = 0; i < 64; i++)
+        //shift generator left until the first bit is high
     {
         if (((char*)&Generator)[7] & 0x80)
         { break; }
         Generator = Generator << 1;
-            //shift generator so that the first bit is high
     }
     for (unsigned char i = 0; i < Size; i++)
+        //initialize table
     {
         Table[i] = 0x00;
-            //initialize table
     }
     for (unsigned char i = 0; i < 8; i++)
         //increment through each generator bit
@@ -840,21 +889,25 @@
                 //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
+            //each bit doubles the number of exclusive or operations
         {
             for (unsigned char k = 0; k < Size; k++)
-                //we need to perform operations for each byte in the CRC result
+                //we need to precalculate each byte in the CRC table
             {
-                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
+                Table[(Size * ((0x01 << i) + j)) + k]
+                    = Table[(Size * j) + k];
+                    //each power of two is equal to all previous entries
+                    //with an added exclusive or on the leftmost bit and
+                    //on each succeeding 1 in 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]));
+                        (((unsigned char*)&Generator)[7-k]
+                        << (i + 1 - Index[l]));
                     Table[(Size * ((0x01 << i) + j)) + k] ^=
-                        (((unsigned char*)&Generator)[6-k] >> (7 - i + Index[l]));
+                        (((unsigned char*)&Generator)[6-k]
+                        >> (7 - i + Index[l]));
                         //xor the new bit and the new generator 1s
                 }
             }