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:
6:ddf09d859ed7
Parent:
5:d85e20b6b904
--- a/SDCard.cpp	Sat Jan 15 05:58:22 2011 +0000
+++ b/SDCard.cpp	Sun Jan 16 09:20:30 2011 +0000
@@ -6,121 +6,145 @@
 #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)
+    const char* DiskName) :
+    FATFileSystem(DiskName), DataLines(mosi, miso, sck), ChipSelect(cs),
+    t(0), Timeout(1024), CRCMode(1), Capacity(0), Version(0), Status(0x00)
+    //card always starts uninitialized and in CRC mode; version 1 low-capacity
+    //card protocols are backwards-compatible with all other card protocols
 {
     DataLines.frequency(100000);
         //set universal speed
     ChipSelect.write(1);
-        //chip select is active low
+        //deselect the chip
     GenerateCRCTable(1, 137, CommandCRCTable);
-        //generate the command crc lookup table;
-        //(polynomial x^7 + x^3 + 1 converts to decimal 137)
+        //generate the CRC7 lookup table; polynomial x^7 + x^3 + 1 converts to
+        //decimal 137
     GenerateCRCTable(2, 69665, DataCRCTable);
-        //generate the data crc lookup table;
-        //(polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665)
+        //generate the crc16 lookup table; polynomial x^16 + x^12 + x^5 + 1
+        //converts to decimal 69665
     Initialize();
-        //run card setup operations
+        //run setup operations
 }
 
 SDCard::~SDCard()
+    //delete all tables and card data registers
 {
     delete[] CommandCRCTable;
     delete[] DataCRCTable;
     delete[] OCR;
     delete[] CSD;
     delete[] FSR;
-    delete[] Workspace;
-        //delete all card data register copies and workspaces
     delete this;
 }
 
 unsigned char SDCard::disk_initialize()
-{ return 0x00; }
-    //disc is initialized during construction
+    //give the FAT module access to the card setup routine
+{
+    if (Status == 0x01)
+    {
+        return Initialize();
+    }
+    else
+    {
+        return Status;
+    }
+}
 unsigned char SDCard::disk_status()
-{ return 0x00; }
-    //card is always initialized
+    //return card initialization and availability status
+{ return Status; }
 unsigned char SDCard::disk_read(
     unsigned char* buff, unsigned long sector, unsigned char count)
+    //give the FAT module access to the multiple-sector reading function
 { return Read((unsigned int)sector, count, buff); }
-    //multiple sector read transaction
 unsigned char SDCard::disk_write(
     const unsigned char* buff, unsigned long sector, unsigned char count)
+    //give the FAT module access to the multiple-sector writing function
 { return Write((unsigned int)sector, count, (unsigned char*)buff); }
-    //multiple sector write transaction
 unsigned char SDCard::disk_sync()
+    //the disk is always synchronized, so return "disk ready"
 { return 0x00; }
-    //all disc functions are synchronous
 unsigned long SDCard::disk_sector_count()
+    //calculate and return the number of sectors on the card from the CSD
 {
     switch (CSD[0] & 0xC0)
     {
         case 0x00:
+            //calculate sector count as specified for version 1 cards
             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:
+            //calculate sector count as specified for version 2 cards
             return ((((CSD[7] & 0x3F) << 16)
                 | (CSD[8] << 8) | CSD[9]) + 1) * 1024;
-                //calculate sector count as specified for version 2 cards
         default:
             return 0;
     }
 }
-    //return number of sectors on card
 unsigned short SDCard::disk_sector_size()
+    //fix the sector size to 512 bytes for all cards versions
 { return 512; }
-    //fix SD card sector size to 512 for all cards
 unsigned long SDCard::disk_block_size()
+    //calculate and return the number of sectors in an erase block from the CSD
 {
-    switch (CSD[0] & 0xC0)
+    if (Version)
+        //the erase sector size is the allocation unit for version 2 cards
     {
-        case 0x00:
-            return (CSD[10] << 1) | (CSD[11] >> 7) + 1;
-                //calculate erase sector size for version 1 cards
-        case 0x40:
-            return 1;
-                //erase sector size is given by
-                //allocation unit for version 2 cards
-        default:
-            return 0;
+        return 1;
+    }
+    else
+        //calculate the erase sector size for version 1 cards
+    {
+        return (CSD[10] << 1) | (CSD[11] >> 7) + 1;
     }
 }
-    //return the number of sectors in an erase sector
+
+unsigned char SDCard::Format(unsigned int AllocationUnit)
+    //call the FAT module formatting function
+{
+    if (format(AllocationUnit))
+    {
+        return 0x01;
+    }
+    else
+    {
+        return 0x00;
+    }
+}
 
 unsigned char SDCard::Log(unsigned char Control, unsigned char Data)
 {
-    static unsigned char Mode = 0x00;
-        //store previous operating mode to determine current behavior
+    static unsigned char Workspace;
+        //work area for card commands and data transactions
     static unsigned short Index = 0;
         //store last written byte number of current memory block
+    static unsigned char Mode = 0x00;
+        //store previous operating mode to determine current behavior
 
-    if (CRCMode)
+    SelectCRCMode(0);
         //CRC's are not used in raw data mode
-    {
-        SelectCRCMode(0);
-    }
 
     switch (Control)
     {
         case 0x00:
-                //control code 0x00 synchronizes the card
+            //control code 0x00 synchronizes the card
             if (Mode)
+                //if the card is in read or write mode, synchronize the card
             {
                 ChipSelect.write(0);
                 for (; Index < 512; Index++)
-                    //get through left over space, filling with FFh
+                    //get through the left over space, filling with 0xFF
                 {
                     DataLines.write(0xFF);
                 }
                 DataLines.write(0xFF);
                 DataLines.write(0xFF);
-                    //get through CRC
+                    //get through the CRC
                 ChipSelect.write(1);
                 if (Mode == 0x01)
+                    //if the card is in write mode, finish the current sector
+                    //and finalize the writing operation
                 {
                     ChipSelect.write(0);
                     t = 0;
@@ -129,44 +153,45 @@
                         t++;
                     } while (((DataLines.write(0xFF) & 0x11) != 0x01)
                         && (t < Timeout));
-                        //get through data response token
+                        //get through the data response token
                     while (!DataLines.write(0xFF));
-                        //get through busy signal
+                        //get through the busy signal
                     DataLines.write(0xFD);
                     DataLines.write(0xFF);
-                        //send stop transmission token
+                        //send the stop transmission token
                     while (!DataLines.write(0xFF));
-                        //get through busy signal
+                        //get through the busy signal
                     ChipSelect.write(1);
                     DataLines.write(0xFF);
                 }
-                    //finish write block
                 else
+                    //if the card is in read mode, finish the current sector
+                    //and finalize the reading operation
                 {
-                    Command(12, 0, Workspace);
-                        //send stop transmission command
+                    Command(12, 0, &Workspace);
+                        //send the stop transmission command
                     ChipSelect.write(0);
                     while (!DataLines.write(0xFF));
-                        //get through busy signal
+                        //get through the busy signal
                     ChipSelect.write(1);
                     DataLines.write(0xFF);
                 }
-                    //finish read block
                 Index = 0;
                 Mode = 0x00;
-                    //reset index to start and mode to synchronized
+                    //reset the index to the start and switch the mode to
+                    //synchronized mode
             }
             return 0xFF;
 
         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
+                //if the previous call was not a write operation, synchronize
+                //the card, start a new write block, and set the function to
                 //write mode
             {
                 Log(0, 0);
-                Command(25, 0, Workspace);
+                Command(25, 0, &Workspace);
                 Mode = 0x01;
             }
             if (Index == 0)
@@ -188,8 +213,8 @@
                 Index++;
             }
             else
-                //if the index is at the last address, get through CRC,
-                //Data response token, and busy signal and reset the index
+                //if the index is at the last address, get through the CRC,
+                //data response token, and busy signal and reset the index
             {
                 ChipSelect.write(0);
                 DataLines.write(Data);
@@ -210,12 +235,12 @@
         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
+                //if the previous call was not a read operation, synchronise
+                //the card, start a new read block, and set the function to
                 //read mode
             {
                 Log(0, 0);
-                Command(18, 0, Workspace);
+                Command(18, 0, &Workspace);
                 Mode = 0x02;
             }
             if (Index == 0)
@@ -229,55 +254,59 @@
                     t++;
                 } while ((DataLines.write(0xFF) != 0xFE)
                     && (t < Timeout));
-                Workspace[0] = DataLines.write(0xFF);
+                Workspace = DataLines.write(0xFF);
                 ChipSelect.write(1);
                 Index++;
-                return Workspace[0];
+                return Workspace;
             }
             else if (Index < 511)
                 //if the index is between the boundaries, read the byte
             {
                 ChipSelect.write(0);
-                Workspace[0] = DataLines.write(0xFF);
+                Workspace = DataLines.write(0xFF);
                 ChipSelect.write(1);
                 Index++;
-                return Workspace[0];
+                return Workspace;
             }
             else
-                //if the index is at the last address, get through
-                //CRC and reset the index
+                //if the index is at the last address, get through the CRC and
+                //reset the index
             {
                 ChipSelect.write(0);
-                Workspace[0] = DataLines.write(0xFF);
+                Workspace = DataLines.write(0xFF);
                 DataLines.write(0xFF);
                 DataLines.write(0xFF);
                 ChipSelect.write(1);
                 Index = 0;
-                return Workspace[0];
+                return Workspace;
             }
 
         default:
-            //undefined control codes only return stuff bits
+            //undefined control codes will only return stuff bits
             return 0xFF;
     }
 }
 
 unsigned char SDCard::Write(unsigned int Address, unsigned char* Data)
 {
-    if (!Capacity)
+    unsigned char Workspace[2];
+        //work area for card commands and data transactions
+    
+    if (Capacity)
+        //send the single-block write command addressed for high-capacity cards
+    {
+        Command(24, Address, Workspace);
+    }
+    else
+        //send the single-block write command addressed for low-capacity cards
     {
         Command(24, Address * 512, Workspace);
     }
-    else
-    {
-        Command(24, Address, Workspace);
-    }
-        //send single block write command; addressing depends on version
     if (Workspace[0])
-        //if a command error occurs, return parameter error
+        //if a command error occurs, return "parameter error"
     { return 0x04; }
     DataCRC(512, Data, Workspace);
-        //calculate the data CRC
+        //calculate the CRC16
     ChipSelect.write(0);
     DataLines.write(0xFE);
         //write start block token
@@ -288,7 +317,7 @@
     }
     DataLines.write(Workspace[0]);
     DataLines.write(Workspace[1]);
-        //write the data CRC to the card
+        //write the data CRC16
     t = 0;
     do
     {
@@ -301,7 +330,7 @@
     ChipSelect.write(1);
     DataLines.write(0xFF);
     if (((Workspace[0] & 0x1F) != 0x05) || (t == Timeout))
-        //if data response token indicates error, return write error
+        //if the data response token indicates error, return write error
     { return 0x01; }
     else
     { return 0x00; }
@@ -309,11 +338,14 @@
 unsigned char SDCard::Write(
     unsigned int Address, unsigned char SectorCount, unsigned char* Data)
 {
+    unsigned char Workspace[5];
+        //work area for card commands and data transactions
     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
+        //set the expected number of write blocks if its different from
+        //previous multiple-block write operations
     {
         Command(55, 0, Workspace);
         Command(23, SectorCount, Workspace);
@@ -321,25 +353,28 @@
         { return 0x04; }
         CurrentSectorCount = SectorCount;
     }
-    if (!Capacity)
+    if (Capacity)
+        //send the multiple-block write command addressed for high-capacity
+        //cards
+    {
+        Command(25, Address, Workspace);
+    }
+    else
+        //send the multiple-block write command addressed for low-capacity
+        //cards
     {
         Command(25, Address * 512, Workspace);
     }
-    else
-    {
-        Command(25, Address, Workspace);
-    }
-        //send multiple block write command; addressing depends on version
     if (Workspace[0])
-        //if a command error occurs, return parameter error
+        //if a command error occurs, return "parameter error"
     { return 0x04; }
     Workspace[4] = 0x00;
-        //initialize error detection variable
+        //initialize the 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
+            //calculate the CRC16
         ChipSelect.write(0);
         DataLines.write(0xFC);
             //send multiple write block start token
@@ -350,7 +385,7 @@
         }
         DataLines.write(Workspace[0]);
         DataLines.write(Workspace[1]);
-            //write the data CRC to the card
+            //write the CRC16
         t = 0;
         do
         {
@@ -362,22 +397,22 @@
             //get through the busy signal
         ChipSelect.write(1);
         Workspace[4] |= Workspace[0];
-            //record if any write errors are detected in the data response
+            //record if any write errors that are detected in the data response
             //tokens
         if (t == Timeout)
-            //if a block write operation gets timed out, stop operations
+            //if a block write operation times out, stop operations
         { break; }
     }
     ChipSelect.write(0);
     DataLines.write(0xFD);
     DataLines.write(0xFF);
-        //send stop transmission token
+        //send the stop transmission token
     while (!DataLines.write(0xFF));
-        //get through busy signal
+        //get through the busy signal
     ChipSelect.write(1);
     DataLines.write(0xFF);
     if (((Workspace[4] & 0x1F) != 0x05) || (t == Timeout))
-        //if a data response token indicated an error, return write error
+        //if a data response token indicated an error, return "write error"
     { return 0x01; }
     else
     { return 0x00; }
@@ -385,17 +420,21 @@
 
 unsigned char SDCard::Read(unsigned int Address, unsigned char* Data)
 {
-    if (!Capacity)
+    unsigned char Workspace[4];
+        //work area for card commands and data transactions
+    
+    if (Capacity)
+        //send the single-block read command addressed for high-capacity cards
+    {
+        Command(17, Address, Workspace);
+    }
+    else
+        //send the single-block read command addressed for low-capacity cards
     {
         Command(17, Address * 512, Workspace);
     }
-    else
-    {
-        Command(17, Address, Workspace);
-    }
-        //send single block read command; addressing depends on version
     if (Workspace[0])
-        //if a command error occurs, return parameter error
+        //if a command error occurs, return "parameter error"
     { return 0x04; }
     ChipSelect.write(0);
     t = 0;
@@ -403,7 +442,7 @@
     {
         t++;
     } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
-        //get to start block token
+        //get to the start block token
     if (t == Timeout) {
         ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
     for (unsigned short i = 0; i < 512; i++)
@@ -413,14 +452,14 @@
         //read the data from the addressed card sector
     Workspace[2] = DataLines.write(0xFF);
     Workspace[3] = DataLines.write(0xFF);
-        //read the data CRC from the card
+        //read the CRC16
     ChipSelect.write(1);
     DataLines.write(0xFF);
     DataCRC(512, Data, Workspace);
-        //calculate the data CRC
+        //calculate the CRC16
     if (CRCMode && ((Workspace[0] != Workspace[2])
         || (Workspace[1] != Workspace[3])))
-        //if CRC is invalid, return read error
+        //if the CRC is invalid, return "read error"
     { return 0x01; }
     else
     { return 0x00; }
@@ -428,17 +467,23 @@
 unsigned char SDCard::Read(
     unsigned int Address, unsigned char SectorCount, unsigned char* Data)
 {
-    if (!Capacity)
+    unsigned char Workspace[5];
+        //work area for card commands and data transactions
+    
+    if (Capacity)
+        //send the multiple-block read command addressed for high-capacity
+        //cards
+    {
+        Command(18, Address, Workspace);
+    }
+    else
+        //send the multiple-block read command addressed for low-capacity
+        //cards
     {
         Command(18, Address * 512, Workspace);
     }
-    else
-    {
-        Command(18, Address, Workspace);
-    }
-        //send multiple block read command; addressing depends on version
     if (Workspace[0])
-        //if a command error occurs, return parameter error
+        //if a command error occurs, return "parameter error"
     { return 0; }
     Workspace[4] = 0x00;
         //initialize error detection variable
@@ -451,37 +496,37 @@
         {
             t++;
         } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
-            //get to each data block start token
+            //get to the data block start token
         if (t == Timeout)
         {
             break;
         }
-            //if a block read operation gets timed out, stop operations
+            //if a block read operation times out, stop operations
         for (unsigned int j = i * 512; j < (i + 1) * 512; j++)
         {
             Data[j] = DataLines.write(0xFF);
         }
-            //read each data block
+            //read the data block
         Workspace[2] = DataLines.write(0xFF);
         Workspace[3] = DataLines.write(0xFF);
             //read the data CRC from the card
+        ChipSelect.write(1);
         DataCRC(512, &Data[i * 512], Workspace);
-            //calculate data crc for each read data block
+            //calculate the CRC16 for each read data block
         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
+        //send the stop transmission command
     ChipSelect.write(0);
     while (!DataLines.write(0xFF));
-        //get through busy signal
+        //get through the busy signal
     ChipSelect.write(1);
     DataLines.write(0xFF);
     if ((Workspace[4]) || (t == Timeout))
-        //if an invalid CRC was detected, return read error
+        //if an invalid CRC was detected, return "read error"
     { return 0x01; }
     else
     { return 0x00; }
@@ -490,6 +535,7 @@
 unsigned char SDCard::SelectCRCMode(bool Mode)
 {
     unsigned char Response;
+    
     if (CRCMode != Mode)
         //only send command if CRCMode has been changed
     {
@@ -497,13 +543,13 @@
         do
         {
             Command(59, Mode, &Response);
-                //command 59 sets card CRC mode
+                //send the set CRC mode command
             t++;
         } while (Response && (t < Timeout));
         CRCMode = Mode;
     }
     if (t == Timeout)
-        //if command times out, return error
+        //if the command times out, return "error"
     { return 0x01; }
     else
     { return 0x00; }
@@ -512,12 +558,14 @@
 void SDCard::SetTimeout(unsigned int Retries)
 {
     Timeout = Retries;
+        //Set the global number of times for operations to be retried
 }
 
 unsigned char SDCard::Initialize()
 {
     unsigned char Workspace[5];
-        //allocate space to hold data during initialization operations
+        //work area for card commands and data transactions
+    
     for (unsigned char i = 0; i < 16; i++)
         //clock card at least 74 times to power up
     {
@@ -528,11 +576,11 @@
     do
     {
         Command(0, 0, Workspace);
-            //send command 0 to put the card into SPI mode
+            //send the reset command to put the card into SPI mode
         t++;
     } while ((Workspace[0] != 0x01) && (t < Timeout));
         //check for command acceptance
-    if (t == Timeout) { return 0x01; }
+    if (t == Timeout) { Status = 0x01; return Status; }
 
     t = 0;
     do
@@ -542,23 +590,22 @@
         t++;
     } 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; }
+        //the set CRC mode command is not valid for all cards in idle state
+    if (t == Timeout) { Status = 0x01; return Status; }
 
     t = 0;
     do
     {
         Command(8, 426, Workspace);
-            //voltage bits are 01h for 2.7V - 3.6V,
-            //check pattern AAh, 000001AAh = 426d
+            //the voltage bits are 0x01 for 2.7V - 3.6V, the check pattern is
+            //0xAA, 0x000001AA converts to decimal 426
         t++;
     } while (((Workspace[0] != 0x01) || ((Workspace[3] & 0x0F) != 0x01) ||
-        (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05)
-        && (t < Timeout));
-        //check version, voltage acceptance, and check pattern
-    if (t == Timeout) { return 0x01; }
+        (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05) && (t < Timeout));
+        //check the version, voltage acceptance, and check pattern
+    if (t == Timeout) { Status = 0x01; return Status; }
     Version = Workspace[0] != 0x05;
-        //store card version
+        //store the card version
 
     if (!Version)
     {
@@ -566,10 +613,10 @@
         do
         {
             Command(16, 512, Workspace);
-                //set data-block length to 512 bytes
+                //set the data-block length to 512 bytes
             t++;
         } while (Workspace[0] && (t < Timeout));
-        if (t == Timeout) { return 0x01; }
+        if (t == Timeout) { Status = 0x01; return Status; }
     }
 
     t = 0;
@@ -579,27 +626,26 @@
             //check the OCR
         t++;
     } while (((Workspace[0] != 0x01) ||
-        !((Workspace[2] & 0x20) || (Workspace[2] & 0x10)))
-        && (t < Timeout));
-        //check for correct operating voltage 3.3V
-    if (t == Timeout) { return 0x01; }
+        !((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) && (t < Timeout));
+        //check for the correct operating voltage, 3.3V
+    if (t == Timeout) { Status = 0x01; return Status; }
 
     t = 0;
     do
     {
         Command(55, 0, Workspace);
-            //command 41 is application-specific
+            //initialize card command is application-specific
         Command(41, 1073741824, Workspace);
-            //specify host supports high capacity cards,
-            //40000000h = 1073741824d
+            //specify host supports high capacity cards, 0x40000000 converts to
+            //decimal 1073741824d
         t++;
     } while (Workspace[0] && (t < Timeout));
-        //check if card is ready
-    if (t == Timeout) { return 0x01; }
+        //check if the card is ready
+    if (t == Timeout) { Status = 0x01; return Status; }
 
     if (SelectCRCMode(1))
         //turn on CRCs for all cards
-    { return 0x01; }
+    { Status = 0x01; return Status; }
 
     t = 0;
     do
@@ -608,15 +654,15 @@
             //check the OCR again
         t++;
     } while ((Workspace[0] || !(Workspace[1] & 0x80)) && (t < Timeout));
-        //check power up status
-    if (t == Timeout) { return 0x01; }
+        //check the power up status
+    if (t == Timeout) { Status = 0x01; return Status; }
     for (unsigned char i = 0; i < 4; i++)
-        //record OCR
+        //record the OCR
     {
         OCR[i] = Workspace[i + 1];
     }
     Capacity = (OCR[0] & 0x40) == 0x40;
-        //record capacity
+        //record the capacity
 
     t = 0;
     do
@@ -624,43 +670,42 @@
         do
         {
             Command(9, 0, Workspace);
-                //read the card-specific-data register
+                //read the CSD
             t++;
         } while (Workspace[0] && (t < Timeout));
-        if (t == Timeout) { return 0x01; }
+        if (t == Timeout) { Status = 0x01; return Status; }
         ChipSelect.write(0);
         do
         {
             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; }
+            //get to the start data block token
+        if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF);
+            Status = 0x01; return Status; }
         for (unsigned char i = 0; i < 16; i++)
-            //gather CSD
+            //record the CSD
         {
             CSD[i] = DataLines.write(0xFF);
         }
         Workspace[2] = DataLines.write(0xFF);
         Workspace[3] = DataLines.write(0xFF);
-            //save CSD CRC
+            //save the CSD CRC16
         ChipSelect.write(1);
         DataLines.write(0xFF);
         DataCRC(16, CSD, Workspace);
-            //calculate the CSD data CRC
+            //calculate the CSD CRC16
         Workspace[4] = 0;
         for (unsigned char i = 0; i < 15; i++)
         {
             Workspace[4] = CommandCRCTable[Workspace[4]] ^ CSD[i];
         }
         Workspace[4] = CommandCRCTable[Workspace[4]] | 0x01;
-            //calculate the CSD table CRC
+            //calculate the CSD CRC7
         t++;
-    } while (((Workspace[0] != Workspace[2])
-        || (Workspace[1] != Workspace[3]) || (Workspace[4] != CSD[15]))
-        && (t < Timeout));
-        //check all CSD CRCs
-    if (t == Timeout) { return 0x01; }
+    } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])
+        || (Workspace[4] != CSD[15])) && (t < Timeout));
+        //perform all CSD CRCs
+    if (t == Timeout) { Status = 0x01; return Status; }
 
     if (((CSD[3] & 0x07) > 0x02) ||
         (((CSD[3] & 0x78) > 0x30) && ((CSD[3] & 0x07) > 0x01)))
@@ -675,7 +720,7 @@
         for (unsigned char i = 0; i < (CSD[3] & 0x07); i++)
         {
             Workspace[0] *= 10;
-                //first three bits are a power of ten multiplier for speed
+                //the first three bits are a power of ten multiplier for speed
         }
         switch (CSD[3] & 0x78)
         {
@@ -709,8 +754,8 @@
             t++;
         } while (Workspace[0] && (Workspace[0] != 0x04) && (t < Timeout));
             //some cards that support switch class commands respond with
-            //illegal command
-        if (t == Timeout) { return 0x01; }
+            //"illegal command"
+        if (t == Timeout) { Status = 0x01; return Status; }
         if (!Workspace[0])
         {
             do
@@ -720,57 +765,58 @@
                 {
                     t++;
                 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
-                    //get to the start-data-block token
+                    //get to the start data block token
                 if (t == Timeout) { ChipSelect.write(1);
-                    DataLines.write(0xFF); return 0x01; }
+                    DataLines.write(0xFF); Status = 0x01; return Status; }
                 for (unsigned char i = 0; i < 64; i++)
-                    //gather function-status register
+                    //gather the function status register
                 {
                     FSR[i] = DataLines.write(0xFF);
                 }
                 Workspace[2] = DataLines.write(0xFF);
                 Workspace[3] = DataLines.write(0xFF);
-                    //record data CRC
+                    //record the CRC16
                 ChipSelect.write(1);
                 DataLines.write(0xFF);
                 DataCRC(64, FSR, Workspace);
-                    //calculate CRC
+                    //calculate the CRC16
                 t++;
             } while (((Workspace[0] != Workspace[2])
                 || (Workspace[1] != Workspace[3])) && (t < Timeout));
-                //complete CRC
-            if (t == Timeout) { return 0x01; }
+                //perform the CRC
+            if (t == Timeout) { Status = 0x01; return Status; }
             if ((FSR[13] & 0x02) && ((FSR[16] & 0x0F) == 0x01))
             {
                 DataLines.frequency(50000000);
-                    //increase speed if function switch was successful
+                    //increase the speed if the function switch was successful
             }
         }
     }
 
     if (SelectCRCMode(0))
-    { return 0x01; }
+    { Status = 0x01; return Status; }
         //turn off CRCs
 
-    return 0x00;
+    Status = 0x00;
+    return Status;
 }
 
-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, Response);
-        //calculate command CRC
+        //calculate the CRC7
     ChipSelect.write(0);
-        //assert chip select low to synchronize command
+        //assert chip select low to synchronize the command
     DataLines.write(0x40 | Index);
-        //the index is assumed valid, commands start with "01b"
+        //the index is assumed valid, commands start with bits 01
     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
     DataLines.write(*Response);
-        //send the command CRC
+        //send the CRC7
     t = 0;
     do
     {
@@ -794,8 +840,8 @@
         //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
@@ -812,10 +858,10 @@
                     ] ^ ((char*)ArgumentPtr)[1]
                 ] ^ ((char*)ArgumentPtr)[0]
             ] | 0x01;
-            //calculate CRC, SD card protocol requires last bit to be 1
+            //calculate the CRC7, SD protocol requires the last bit to be high
     }
     else
-        //record stuff bits if no data-checking is desired
+        //if no data-checking is desired, the return bits are not used
     {
         Result[0] = 0xFF;
     }
@@ -828,22 +874,22 @@
         //only calculate if data-checks are desired
     {
         unsigned char Reference;
-            //store the current CRC lookup value
+            //store the current CRC16 lookup value
         Result[0] = 0x00;
         Result[1] = 0x00;
-            //initialize result carrier
+            //initialize the result carrier
         for (unsigned short i = 0; i < Length; i++)
             //step through each byte of the data to be checked
         {
             Reference = Result[0];
-                //record current crc lookup for both bytes
+                //record the current CRC16 lookup for both bytes
             Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
-                //fist byte result is exclusive ored with old second byte
+                //the first byte result is XORed with the old second byte
             Result[1] = DataCRCTable[(2 * Reference) + 1] ^ Data[i];
-                //second byte result is exclusive ored with new data byte
+                //the second byte result is XORed with the new data byte
         }
         for (unsigned char i = 0; i < 2; i++)
-            //the final result must be exclusive ored with two 0x00 bytes
+            //the final result must be XORed with two 0x00 bytes
         {
             Reference = Result[0];
             Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
@@ -851,7 +897,7 @@
         }
     }
     else
-        //record stuff bits if no data-checking is desired
+        //if no data-checking is desired, the return bits are not used
     {
         Result[0] = 0xFF;
         Result[1] = 0xFF;
@@ -862,10 +908,10 @@
     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
     {
@@ -882,22 +928,22 @@
         //increment through each generator bit
     {
         if ((0x80 >> i) & ((unsigned char*)&Generator)[7])
-            //if a 1 is encountered in the generator
+            //if a 1 is encountered in the generator, record its order and
+            //location and increment the counter
         {
             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 doubles the number of exclusive or operations
+            //each bit doubles the number of XOR operations
         {
             for (unsigned char k = 0; k < Size; k++)
                 //we need to precalculate each byte in the CRC table
             {
                 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
+                    //each power of two is equal to all previous entries with
+                    //an added XOR with the generator 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
@@ -908,7 +954,7 @@
                     Table[(Size * ((0x01 << i) + j)) + k] ^=
                         (((unsigned char*)&Generator)[6-k]
                         >> (7 - i + Index[l]));
-                        //xor the new bit and the new generator 1s
+                        //XOR the new bit and the new generator 1s
                 }
             }
         }