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

Committer:
Blaze513
Date:
Sun Jul 18 21:26:24 2010 +0000
Revision:
0:f3870f76a890
Child:
1:94c648931f84

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Blaze513 0:f3870f76a890 1 #include "SDCard.h"
Blaze513 0:f3870f76a890 2
Blaze513 0:f3870f76a890 3 SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs)
Blaze513 0:f3870f76a890 4 : DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1)
Blaze513 0:f3870f76a890 5 {
Blaze513 0:f3870f76a890 6 DataLines.frequency(100000);
Blaze513 0:f3870f76a890 7 //set universal speed
Blaze513 0:f3870f76a890 8 ChipSelect.write(1);
Blaze513 0:f3870f76a890 9 //chip select is active low
Blaze513 0:f3870f76a890 10 GenerateCRCTable(1, 137, CommandCRCTable);
Blaze513 0:f3870f76a890 11 //generate the command crc lookup table
Blaze513 0:f3870f76a890 12 //(generator polynomial x^7 + x^3 + 1 converts to decimal 137)
Blaze513 0:f3870f76a890 13 GenerateCRCTable(2, 69665, DataCRCTable);
Blaze513 0:f3870f76a890 14 //generate the command crc lookup table
Blaze513 0:f3870f76a890 15 //(generator polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665)
Blaze513 0:f3870f76a890 16 Initialize();
Blaze513 0:f3870f76a890 17 //send card initialization sequence
Blaze513 0:f3870f76a890 18 }
Blaze513 0:f3870f76a890 19
Blaze513 0:f3870f76a890 20 bool SDCard::Write(unsigned int Address, unsigned char* Data)
Blaze513 0:f3870f76a890 21 {
Blaze513 0:f3870f76a890 22 if (Capacity)
Blaze513 0:f3870f76a890 23 {
Blaze513 0:f3870f76a890 24 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 25 {
Blaze513 0:f3870f76a890 26 Command(24, Address, Workspace);
Blaze513 0:f3870f76a890 27 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 28 { break; }
Blaze513 0:f3870f76a890 29 if (j == 8191)
Blaze513 0:f3870f76a890 30 { return 0; }
Blaze513 0:f3870f76a890 31 }
Blaze513 0:f3870f76a890 32 }
Blaze513 0:f3870f76a890 33 else
Blaze513 0:f3870f76a890 34 {
Blaze513 0:f3870f76a890 35 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 36 {
Blaze513 0:f3870f76a890 37 Command(24, Address * 512, Workspace);///////////implement block length
Blaze513 0:f3870f76a890 38 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 39 { break; }
Blaze513 0:f3870f76a890 40 if (j == 8191)
Blaze513 0:f3870f76a890 41 { return 0; }
Blaze513 0:f3870f76a890 42 }
Blaze513 0:f3870f76a890 43 }
Blaze513 0:f3870f76a890 44 ChipSelect.write(0);
Blaze513 0:f3870f76a890 45 DataLines.write(0xFE);
Blaze513 0:f3870f76a890 46 //start data block token
Blaze513 0:f3870f76a890 47 for (unsigned short j = 0; j < 512; j++)
Blaze513 0:f3870f76a890 48 {
Blaze513 0:f3870f76a890 49 DataLines.write(Data[j]);
Blaze513 0:f3870f76a890 50 //write the data
Blaze513 0:f3870f76a890 51 }
Blaze513 0:f3870f76a890 52 DataCRC(512, Data, Workspace);
Blaze513 0:f3870f76a890 53 DataLines.write(Workspace[1]);
Blaze513 0:f3870f76a890 54 DataLines.write(Workspace[2]);
Blaze513 0:f3870f76a890 55 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 56 {
Blaze513 0:f3870f76a890 57 Workspace[0] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 58 if ((Workspace[0] & 0x1F) == 0x05)
Blaze513 0:f3870f76a890 59 { break; }
Blaze513 0:f3870f76a890 60 }
Blaze513 0:f3870f76a890 61 while (!DataLines.write(0xFF));
Blaze513 0:f3870f76a890 62 ChipSelect.write(1);
Blaze513 0:f3870f76a890 63 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 64 if ((Workspace[0] & 0x1F) == 0x05)
Blaze513 0:f3870f76a890 65 { return 1; }
Blaze513 0:f3870f76a890 66 else
Blaze513 0:f3870f76a890 67 {
Blaze513 0:f3870f76a890 68 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 69 {
Blaze513 0:f3870f76a890 70 Command(13, 0, Workspace);
Blaze513 0:f3870f76a890 71 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 72 { break; }
Blaze513 0:f3870f76a890 73 }
Blaze513 0:f3870f76a890 74 return 0;
Blaze513 0:f3870f76a890 75 }
Blaze513 0:f3870f76a890 76 }
Blaze513 0:f3870f76a890 77
Blaze513 0:f3870f76a890 78 bool SDCard::Read(unsigned int Address, unsigned char* Data)
Blaze513 0:f3870f76a890 79 {
Blaze513 0:f3870f76a890 80 if (Capacity)
Blaze513 0:f3870f76a890 81 {
Blaze513 0:f3870f76a890 82 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 83 {
Blaze513 0:f3870f76a890 84 Command(17, Address, Workspace);
Blaze513 0:f3870f76a890 85 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 86 { break; }
Blaze513 0:f3870f76a890 87 if (j == 8191)
Blaze513 0:f3870f76a890 88 { return 0; }
Blaze513 0:f3870f76a890 89 }
Blaze513 0:f3870f76a890 90 }
Blaze513 0:f3870f76a890 91 else
Blaze513 0:f3870f76a890 92 {
Blaze513 0:f3870f76a890 93 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 94 {
Blaze513 0:f3870f76a890 95 Command(17, Address * 512, Workspace);///////////implement block length
Blaze513 0:f3870f76a890 96 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 97 { break; }
Blaze513 0:f3870f76a890 98 if (j == 8191)
Blaze513 0:f3870f76a890 99 { return 0; }
Blaze513 0:f3870f76a890 100 }
Blaze513 0:f3870f76a890 101 }
Blaze513 0:f3870f76a890 102 ChipSelect.write(0);
Blaze513 0:f3870f76a890 103 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 104 {
Blaze513 0:f3870f76a890 105 if (DataLines.write(0xFF) == 0xFE)
Blaze513 0:f3870f76a890 106 { break; }
Blaze513 0:f3870f76a890 107 }
Blaze513 0:f3870f76a890 108 for (unsigned short j = 0; j < 512; j++)
Blaze513 0:f3870f76a890 109 {
Blaze513 0:f3870f76a890 110 Data[j] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 111 }
Blaze513 0:f3870f76a890 112 Workspace[3] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 113 Workspace[4] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 114 ChipSelect.write(1);
Blaze513 0:f3870f76a890 115 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 116 DataCRC(512, Data, Workspace);
Blaze513 0:f3870f76a890 117 if ((Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
Blaze513 0:f3870f76a890 118 { return 1; }
Blaze513 0:f3870f76a890 119 else
Blaze513 0:f3870f76a890 120 { return 0; }
Blaze513 0:f3870f76a890 121 }
Blaze513 0:f3870f76a890 122
Blaze513 0:f3870f76a890 123 bool SDCard::Initialize()
Blaze513 0:f3870f76a890 124 {
Blaze513 0:f3870f76a890 125 for (unsigned char j = 0; j < 16; j++)
Blaze513 0:f3870f76a890 126 {
Blaze513 0:f3870f76a890 127 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 128 }
Blaze513 0:f3870f76a890 129 //perform specified power up sequence
Blaze513 0:f3870f76a890 130
Blaze513 0:f3870f76a890 131 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 132 {
Blaze513 0:f3870f76a890 133 Command(0, 0, Workspace);
Blaze513 0:f3870f76a890 134 //send command 0 to put the card into SPI mode
Blaze513 0:f3870f76a890 135 if (Workspace[0] == 0x01)
Blaze513 0:f3870f76a890 136 //check for idle mode
Blaze513 0:f3870f76a890 137 { break; }
Blaze513 0:f3870f76a890 138 if (j == 8191)
Blaze513 0:f3870f76a890 139 { return 0; }
Blaze513 0:f3870f76a890 140 }
Blaze513 0:f3870f76a890 141
Blaze513 0:f3870f76a890 142 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 143 {
Blaze513 0:f3870f76a890 144 Command(59, 1, Workspace);
Blaze513 0:f3870f76a890 145 //send command 59 to turn on CRCs
Blaze513 0:f3870f76a890 146 if (Workspace[0] == 0x01)
Blaze513 0:f3870f76a890 147 { break; }
Blaze513 0:f3870f76a890 148 if (j == 8191)
Blaze513 0:f3870f76a890 149 { return 0; }
Blaze513 0:f3870f76a890 150 }
Blaze513 0:f3870f76a890 151
Blaze513 0:f3870f76a890 152 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 153 {
Blaze513 0:f3870f76a890 154 Command(8, 426, Workspace);
Blaze513 0:f3870f76a890 155 //voltage bits are 0x01 for 2.7V - 3.6V,
Blaze513 0:f3870f76a890 156 //check pattern 0xAA, [00,00,01,AA] = 426
Blaze513 0:f3870f76a890 157 if ((Workspace[0] == 0x05) || ((Workspace[0] == 0x01) &&
Blaze513 0:f3870f76a890 158 ((Workspace[3] & 0x0F) == 0x01) && (Workspace[4] == 0xAA)))
Blaze513 0:f3870f76a890 159 //check version, voltage acceptance, and check pattern
Blaze513 0:f3870f76a890 160 { break; }
Blaze513 0:f3870f76a890 161 if (j == 8191)
Blaze513 0:f3870f76a890 162 { return 0; }
Blaze513 0:f3870f76a890 163 }
Blaze513 0:f3870f76a890 164 Version = Workspace[0] == 0x01;
Blaze513 0:f3870f76a890 165 //store card version
Blaze513 0:f3870f76a890 166
Blaze513 0:f3870f76a890 167 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 168 {
Blaze513 0:f3870f76a890 169 Command(58, 0, Workspace);
Blaze513 0:f3870f76a890 170 //check the OCR
Blaze513 0:f3870f76a890 171 if ((Workspace[0] == 0x01) && ((Workspace[2] & 0x20) || (Workspace[2] & 0x10)))
Blaze513 0:f3870f76a890 172 //check for correct operating voltage 3.3V
Blaze513 0:f3870f76a890 173 { break; }
Blaze513 0:f3870f76a890 174 if (j == 8191)
Blaze513 0:f3870f76a890 175 { return 0; }
Blaze513 0:f3870f76a890 176 }
Blaze513 0:f3870f76a890 177
Blaze513 0:f3870f76a890 178 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 179 {
Blaze513 0:f3870f76a890 180 Command(55, 0, Workspace);
Blaze513 0:f3870f76a890 181 //specify application-specific command
Blaze513 0:f3870f76a890 182 Command(41, 1073741824, Workspace);
Blaze513 0:f3870f76a890 183 //specify host supports high capacity cards
Blaze513 0:f3870f76a890 184 //[40,00,00,00] = 1073741824
Blaze513 0:f3870f76a890 185 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 186 //check if card is ready
Blaze513 0:f3870f76a890 187 { break; }
Blaze513 0:f3870f76a890 188 if (j == 8191)
Blaze513 0:f3870f76a890 189 { return 0; }
Blaze513 0:f3870f76a890 190 }
Blaze513 0:f3870f76a890 191
Blaze513 0:f3870f76a890 192 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 193 {
Blaze513 0:f3870f76a890 194 Command(58, 0, Workspace);
Blaze513 0:f3870f76a890 195 //check the OCR again
Blaze513 0:f3870f76a890 196 if ((Workspace[0] == 0x00) && (Workspace[1] & 0x80))
Blaze513 0:f3870f76a890 197 { break; }
Blaze513 0:f3870f76a890 198 if (j == 8191)
Blaze513 0:f3870f76a890 199 { return 0; }
Blaze513 0:f3870f76a890 200 }
Blaze513 0:f3870f76a890 201 for (unsigned char j = 0; j < 4; j++)
Blaze513 0:f3870f76a890 202 {
Blaze513 0:f3870f76a890 203 OCR[j] = Workspace[j + 1];
Blaze513 0:f3870f76a890 204 }
Blaze513 0:f3870f76a890 205 //record OCR
Blaze513 0:f3870f76a890 206 Capacity = (OCR[0] & 0x40) == 0x40;
Blaze513 0:f3870f76a890 207 //record capacity
Blaze513 0:f3870f76a890 208
Blaze513 0:f3870f76a890 209 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 210 {
Blaze513 0:f3870f76a890 211 Command(9, 0, Workspace);
Blaze513 0:f3870f76a890 212 //read the card-specific data register
Blaze513 0:f3870f76a890 213 ChipSelect.write(0);
Blaze513 0:f3870f76a890 214 for (unsigned int k = 0; k < 8192; k++)
Blaze513 0:f3870f76a890 215 {
Blaze513 0:f3870f76a890 216 if (DataLines.write(0xFF) == 0xFE)
Blaze513 0:f3870f76a890 217 { break; }
Blaze513 0:f3870f76a890 218 }
Blaze513 0:f3870f76a890 219 //get to the start-data-block token
Blaze513 0:f3870f76a890 220 for (unsigned char k = 0; k < 16; k++)
Blaze513 0:f3870f76a890 221 {
Blaze513 0:f3870f76a890 222 CSD[k] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 223 }
Blaze513 0:f3870f76a890 224 Workspace[3] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 225 Workspace[4] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 226 ChipSelect.write(1);
Blaze513 0:f3870f76a890 227 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 228 DataCRC(16, CSD, Workspace);
Blaze513 0:f3870f76a890 229 //calculate the CSD data CRC
Blaze513 0:f3870f76a890 230 Workspace[0] = 0;
Blaze513 0:f3870f76a890 231 for (unsigned char k = 0; k < 15; k++)
Blaze513 0:f3870f76a890 232 {
Blaze513 0:f3870f76a890 233 Workspace[0] = CommandCRCTable[Workspace[0]] ^ CSD[k];
Blaze513 0:f3870f76a890 234 }
Blaze513 0:f3870f76a890 235 Workspace[0] = CommandCRCTable[Workspace[0]] | 0x01;
Blaze513 0:f3870f76a890 236 if ((Workspace[0] == CSD[15]) && (Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4]))
Blaze513 0:f3870f76a890 237 { break; }
Blaze513 0:f3870f76a890 238 if (j == 8191)
Blaze513 0:f3870f76a890 239 { return 0; }
Blaze513 0:f3870f76a890 240 }
Blaze513 0:f3870f76a890 241
Blaze513 0:f3870f76a890 242 if (((CSD[3] & 0x07) > 2) || ((CSD[3] & 0x7F) > 0x32))
Blaze513 0:f3870f76a890 243 {
Blaze513 0:f3870f76a890 244 DataLines.frequency(25000000);
Blaze513 0:f3870f76a890 245 //maximum speed is given at 25MHz
Blaze513 0:f3870f76a890 246 }
Blaze513 0:f3870f76a890 247 else
Blaze513 0:f3870f76a890 248 {
Blaze513 0:f3870f76a890 249 Workspace[0] = 1;
Blaze513 0:f3870f76a890 250 for (unsigned char j = 0; j < (CSD[3] & 0x07); j++)
Blaze513 0:f3870f76a890 251 {
Blaze513 0:f3870f76a890 252 Workspace[0] *= 10;
Blaze513 0:f3870f76a890 253 //the first three bits are a power of ten multiplier for speed
Blaze513 0:f3870f76a890 254 }
Blaze513 0:f3870f76a890 255 switch (CSD[3] & 0x78)
Blaze513 0:f3870f76a890 256 {
Blaze513 0:f3870f76a890 257 case 0x08: DataLines.frequency(Workspace[0] * 100000); break;
Blaze513 0:f3870f76a890 258 case 0x10: DataLines.frequency(Workspace[0] * 120000); break;
Blaze513 0:f3870f76a890 259 case 0x18: DataLines.frequency(Workspace[0] * 140000); break;
Blaze513 0:f3870f76a890 260 case 0x20: DataLines.frequency(Workspace[0] * 150000); break;
Blaze513 0:f3870f76a890 261 case 0x28: DataLines.frequency(Workspace[0] * 200000); break;
Blaze513 0:f3870f76a890 262 case 0x30: DataLines.frequency(Workspace[0] * 250000); break;
Blaze513 0:f3870f76a890 263 case 0x38: DataLines.frequency(Workspace[0] * 300000); break;
Blaze513 0:f3870f76a890 264 case 0x40: DataLines.frequency(Workspace[0] * 350000); break;
Blaze513 0:f3870f76a890 265 case 0x48: DataLines.frequency(Workspace[0] * 400000); break;
Blaze513 0:f3870f76a890 266 case 0x50: DataLines.frequency(Workspace[0] * 450000); break;
Blaze513 0:f3870f76a890 267 case 0x58: DataLines.frequency(Workspace[0] * 500000); break;
Blaze513 0:f3870f76a890 268 case 0x60: DataLines.frequency(Workspace[0] * 550000); break;
Blaze513 0:f3870f76a890 269 case 0x68: DataLines.frequency(Workspace[0] * 600000); break;
Blaze513 0:f3870f76a890 270 case 0x70: DataLines.frequency(Workspace[0] * 700000); break;
Blaze513 0:f3870f76a890 271 case 0x78: DataLines.frequency(Workspace[0] * 800000); break;
Blaze513 0:f3870f76a890 272 default: break;
Blaze513 0:f3870f76a890 273 //read the CSD card speed bits and speed up card operations
Blaze513 0:f3870f76a890 274 }
Blaze513 0:f3870f76a890 275 }
Blaze513 0:f3870f76a890 276
Blaze513 0:f3870f76a890 277 if (!Version)
Blaze513 0:f3870f76a890 278 {
Blaze513 0:f3870f76a890 279 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 280 {
Blaze513 0:f3870f76a890 281 Command(16, 512, Workspace);
Blaze513 0:f3870f76a890 282 //set data-block length to 512 bytes
Blaze513 0:f3870f76a890 283 if (Workspace[0] == 0x00)
Blaze513 0:f3870f76a890 284 { break; }
Blaze513 0:f3870f76a890 285 if (j == 8191)
Blaze513 0:f3870f76a890 286 { return 0; }
Blaze513 0:f3870f76a890 287 }
Blaze513 0:f3870f76a890 288 }
Blaze513 0:f3870f76a890 289 ////////////////////////////////////////////implement data block sizing later
Blaze513 0:f3870f76a890 290 return 1;
Blaze513 0:f3870f76a890 291 }
Blaze513 0:f3870f76a890 292
Blaze513 0:f3870f76a890 293 void SDCard::Command(unsigned char Index, unsigned int Argument, unsigned char* Response)
Blaze513 0:f3870f76a890 294 {
Blaze513 0:f3870f76a890 295 ChipSelect.write(0);
Blaze513 0:f3870f76a890 296 //assert chip select low to synchronize command
Blaze513 0:f3870f76a890 297 DataLines.write(0x40 | Index);
Blaze513 0:f3870f76a890 298 //the index is assumed valid, commands start with "01b"
Blaze513 0:f3870f76a890 299 DataLines.write(((char*)&Argument)[3]);
Blaze513 0:f3870f76a890 300 DataLines.write(((char*)&Argument)[2]);
Blaze513 0:f3870f76a890 301 DataLines.write(((char*)&Argument)[1]);
Blaze513 0:f3870f76a890 302 DataLines.write(((char*)&Argument)[0]);
Blaze513 0:f3870f76a890 303 //send the argument bytes in order from MSB to LSB (mbed is little endian)
Blaze513 0:f3870f76a890 304 if (CRCMode)
Blaze513 0:f3870f76a890 305 { DataLines.write(CommandCRC(&Index, &Argument)); }
Blaze513 0:f3870f76a890 306 else
Blaze513 0:f3870f76a890 307 { DataLines.write(0x00); }
Blaze513 0:f3870f76a890 308 //send the command CRC
Blaze513 0:f3870f76a890 309 for (unsigned int j = 0; j < 8192; j++)
Blaze513 0:f3870f76a890 310 {
Blaze513 0:f3870f76a890 311 Response[0] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 312 //clock the card high to let it run operations, the first byte will be
Blaze513 0:f3870f76a890 313 //busy (all high), the response will be sent some time later
Blaze513 0:f3870f76a890 314 if (!(Response[0] & 0x80))
Blaze513 0:f3870f76a890 315 //check for a response by testing if the first bit is low
Blaze513 0:f3870f76a890 316 { break; }
Blaze513 0:f3870f76a890 317 }
Blaze513 0:f3870f76a890 318 if ((Index == 8) || (Index == 13) || (Index == 58))
Blaze513 0:f3870f76a890 319 {
Blaze513 0:f3870f76a890 320 for (unsigned char j = 1; j < 5; j++)
Blaze513 0:f3870f76a890 321 {
Blaze513 0:f3870f76a890 322 Response[j] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 323 }
Blaze513 0:f3870f76a890 324 //get the rest of the response
Blaze513 0:f3870f76a890 325 }
Blaze513 0:f3870f76a890 326 ChipSelect.write(1);
Blaze513 0:f3870f76a890 327 //assert chip select high to synchronize command
Blaze513 0:f3870f76a890 328 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 329 //clock the deselected card high to complete processing for some cards
Blaze513 0:f3870f76a890 330 }
Blaze513 0:f3870f76a890 331
Blaze513 0:f3870f76a890 332 char SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr)
Blaze513 0:f3870f76a890 333 {
Blaze513 0:f3870f76a890 334 return
Blaze513 0:f3870f76a890 335 CommandCRCTable[
Blaze513 0:f3870f76a890 336 CommandCRCTable[
Blaze513 0:f3870f76a890 337 CommandCRCTable[
Blaze513 0:f3870f76a890 338 CommandCRCTable[
Blaze513 0:f3870f76a890 339 CommandCRCTable[
Blaze513 0:f3870f76a890 340 *IndexPtr | 0x40
Blaze513 0:f3870f76a890 341 ] ^ ((char*)ArgumentPtr)[3]
Blaze513 0:f3870f76a890 342 ] ^ ((char*)ArgumentPtr)[2]
Blaze513 0:f3870f76a890 343 ] ^ ((char*)ArgumentPtr)[1]
Blaze513 0:f3870f76a890 344 ] ^ ((char*)ArgumentPtr)[0]
Blaze513 0:f3870f76a890 345 ] | 0x01;
Blaze513 0:f3870f76a890 346 //using a CRC table, the CRC result of a byte is equal to the byte in the table at the
Blaze513 0:f3870f76a890 347 //address equal to the input byte, a message CRC is obtained by successively XORing these
Blaze513 0:f3870f76a890 348 //with the message bytes
Blaze513 0:f3870f76a890 349 }
Blaze513 0:f3870f76a890 350
Blaze513 0:f3870f76a890 351 void SDCard::DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result)
Blaze513 0:f3870f76a890 352 {
Blaze513 0:f3870f76a890 353 Result[1] = 0x00;
Blaze513 0:f3870f76a890 354 Result[2] = 0x00;
Blaze513 0:f3870f76a890 355 //initialize result carrier
Blaze513 0:f3870f76a890 356 for (int i = 0; i < Length; i++)
Blaze513 0:f3870f76a890 357 //step through each byte of the data to be checked
Blaze513 0:f3870f76a890 358 {
Blaze513 0:f3870f76a890 359 Result[0] = Result[1];
Blaze513 0:f3870f76a890 360 //record current crc lookup for both bytes
Blaze513 0:f3870f76a890 361 Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
Blaze513 0:f3870f76a890 362 //new fist byte result is XORed with old second byte result
Blaze513 0:f3870f76a890 363 Result[2] = DataCRCTable[(2 * Result[0]) + 1] ^ Data[i];
Blaze513 0:f3870f76a890 364 //new second byte result is XORed with new data byte
Blaze513 0:f3870f76a890 365 }
Blaze513 0:f3870f76a890 366 for (int i = 0; i < 2; i++)
Blaze513 0:f3870f76a890 367 //the final result must be XORed with two 0x00 bytes.
Blaze513 0:f3870f76a890 368 {
Blaze513 0:f3870f76a890 369 Result[0] = Result[1];
Blaze513 0:f3870f76a890 370 Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2];
Blaze513 0:f3870f76a890 371 Result[2] = DataCRCTable[(2 * Result[0]) + 1];
Blaze513 0:f3870f76a890 372 }
Blaze513 0:f3870f76a890 373 }
Blaze513 0:f3870f76a890 374
Blaze513 0:f3870f76a890 375 void SDCard::GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table)
Blaze513 0:f3870f76a890 376 {
Blaze513 0:f3870f76a890 377 unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
Blaze513 0:f3870f76a890 378 //this will hold information from the generator; the position indicates the
Blaze513 0:f3870f76a890 379 //order of the encountered 1, the value indicates its position in the
Blaze513 0:f3870f76a890 380 //generator, the 9th entry indicates the number of 1's encountered
Blaze513 0:f3870f76a890 381 for (int i = 0; i < 64; i++)
Blaze513 0:f3870f76a890 382 {
Blaze513 0:f3870f76a890 383 if (((char*)&Generator)[7] & 0x80)
Blaze513 0:f3870f76a890 384 { break; }
Blaze513 0:f3870f76a890 385 Generator = Generator << 1;
Blaze513 0:f3870f76a890 386 //shift generator so that the first bit is high
Blaze513 0:f3870f76a890 387 }
Blaze513 0:f3870f76a890 388 for (unsigned char k = 0; k < Size; k++)
Blaze513 0:f3870f76a890 389 {
Blaze513 0:f3870f76a890 390 Table[k] = 0x00;
Blaze513 0:f3870f76a890 391 //initialize the first CRC bytes
Blaze513 0:f3870f76a890 392 }
Blaze513 0:f3870f76a890 393 for (unsigned char i = 0; i < 8; i++)
Blaze513 0:f3870f76a890 394 //increment through each generator bit
Blaze513 0:f3870f76a890 395 {
Blaze513 0:f3870f76a890 396 if ((0x80 >> i) & ((unsigned char*)&Generator)[7])
Blaze513 0:f3870f76a890 397 //if a 1 is encountered in the generator
Blaze513 0:f3870f76a890 398 {
Blaze513 0:f3870f76a890 399 Index[Index[8]] = i;
Blaze513 0:f3870f76a890 400 Index[8]++;
Blaze513 0:f3870f76a890 401 //record its order and location and increment the counter
Blaze513 0:f3870f76a890 402 }
Blaze513 0:f3870f76a890 403 for (unsigned char j = 0; j < (0x01 << i); j++)
Blaze513 0:f3870f76a890 404 //each bit increases the number of xor operations by a power of 2
Blaze513 0:f3870f76a890 405 {
Blaze513 0:f3870f76a890 406 for (unsigned char k = 0; k < Size; k++)
Blaze513 0:f3870f76a890 407 //we need to perform operations for each byte in the CRC result
Blaze513 0:f3870f76a890 408 {
Blaze513 0:f3870f76a890 409 Table[(Size * ((0x01 << i) + j)) + k] = Table[(Size * j) + k];
Blaze513 0:f3870f76a890 410 //each new power is equal to all previous entries with an added xor
Blaze513 0:f3870f76a890 411 //on the leftmost bit and each succeeding 1 on the generator
Blaze513 0:f3870f76a890 412 for (unsigned char l = 0; l < Index[8]; l++)
Blaze513 0:f3870f76a890 413 //increment through the encountered generator 1s
Blaze513 0:f3870f76a890 414 {
Blaze513 0:f3870f76a890 415 Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[7-k] << (i + 1 - Index[l]));
Blaze513 0:f3870f76a890 416 Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[6-k] >> (7 - i + Index[l]));
Blaze513 0:f3870f76a890 417 //xor the new bit and the new generator 1s
Blaze513 0:f3870f76a890 418 }
Blaze513 0:f3870f76a890 419 }
Blaze513 0:f3870f76a890 420 }
Blaze513 0:f3870f76a890 421 }
Blaze513 0:f3870f76a890 422 }