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.
Diff: SDCard.cpp
- Revision:
- 5:d85e20b6b904
- Parent:
- 4:9a5878d316d5
- Child:
- 6:ddf09d859ed7
diff -r 9a5878d316d5 -r d85e20b6b904 SDCard.cpp --- 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 } }