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:
Sat Aug 07 18:32:30 2010 +0000
Revision:
1:94c648931f84
Parent:
0:f3870f76a890
Child:
3:210eb67b260c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Blaze513 0:f3870f76a890 1 #include "SDCard.h"
Blaze513 0:f3870f76a890 2
Blaze513 1:94c648931f84 3 SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs, const char* DiskName) :
Blaze513 1:94c648931f84 4 FATFileSystem(DiskName), DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1), Timeout(8192)
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 1:94c648931f84 17 }
Blaze513 1:94c648931f84 18
Blaze513 1:94c648931f84 19 unsigned char SDCard::disk_initialize()
Blaze513 1:94c648931f84 20 { return 0x00; }
Blaze513 1:94c648931f84 21 unsigned char SDCard::disk_status()
Blaze513 1:94c648931f84 22 { return 0x00; }
Blaze513 1:94c648931f84 23 unsigned char SDCard::disk_read(unsigned char* buff, unsigned long sector, unsigned char count)
Blaze513 1:94c648931f84 24 { return Read((unsigned int)sector, count, buff); }
Blaze513 1:94c648931f84 25 unsigned char SDCard::disk_write(const unsigned char* buff, unsigned long sector, unsigned char count)
Blaze513 1:94c648931f84 26 { return Write((unsigned int)sector, count, (unsigned char*)buff); }
Blaze513 1:94c648931f84 27 unsigned char SDCard::disk_sync()
Blaze513 1:94c648931f84 28 { return 0x00; }
Blaze513 1:94c648931f84 29 unsigned long SDCard::disk_sector_count()
Blaze513 1:94c648931f84 30 {
Blaze513 1:94c648931f84 31 switch (CSD[0] & 0xC0)
Blaze513 1:94c648931f84 32 {
Blaze513 1:94c648931f84 33 case 0x00:
Blaze513 1:94c648931f84 34 return ((((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1)
Blaze513 1:94c648931f84 35 * (1 << ((((CSD[9] & 0x03) << 1) | ((CSD[10] & 0x80) >> 7)) + 2));
Blaze513 1:94c648931f84 36 case 0x40:
Blaze513 1:94c648931f84 37 return ((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1) * 1024;
Blaze513 1:94c648931f84 38 default:
Blaze513 1:94c648931f84 39 return 0;
Blaze513 1:94c648931f84 40 }
Blaze513 1:94c648931f84 41 }
Blaze513 1:94c648931f84 42 unsigned short SDCard::disk_sector_size()
Blaze513 1:94c648931f84 43 { return 512; }
Blaze513 1:94c648931f84 44 unsigned long SDCard::disk_block_size()
Blaze513 1:94c648931f84 45 {
Blaze513 1:94c648931f84 46 switch (CSD[0] & 0xC0)
Blaze513 1:94c648931f84 47 {
Blaze513 1:94c648931f84 48 case 0x00:
Blaze513 1:94c648931f84 49 return (CSD[10] << 1) | (CSD[11] >> 7) + 1;
Blaze513 1:94c648931f84 50 case 0x40:
Blaze513 1:94c648931f84 51 return 1;
Blaze513 1:94c648931f84 52 default:
Blaze513 1:94c648931f84 53 return 0;
Blaze513 1:94c648931f84 54 }
Blaze513 0:f3870f76a890 55 }
Blaze513 0:f3870f76a890 56
Blaze513 1:94c648931f84 57 unsigned char SDCard::Log(unsigned char Control, unsigned char Data)
Blaze513 0:f3870f76a890 58 {
Blaze513 1:94c648931f84 59 static unsigned char Mode = 0x00;
Blaze513 1:94c648931f84 60 static unsigned short Index = 0;
Blaze513 1:94c648931f84 61
Blaze513 1:94c648931f84 62 if (CRCMode)
Blaze513 0:f3870f76a890 63 {
Blaze513 1:94c648931f84 64 SelectCRCMode(0);
Blaze513 0:f3870f76a890 65 }
Blaze513 1:94c648931f84 66
Blaze513 1:94c648931f84 67 switch (Control)
Blaze513 0:f3870f76a890 68 {
Blaze513 1:94c648931f84 69 case 0x00:
Blaze513 1:94c648931f84 70 if (Mode)
Blaze513 1:94c648931f84 71 {
Blaze513 1:94c648931f84 72 ChipSelect.write(0);
Blaze513 1:94c648931f84 73 for (; Index < 512; Index++)
Blaze513 1:94c648931f84 74 {
Blaze513 1:94c648931f84 75 DataLines.write(0xFF);
Blaze513 1:94c648931f84 76 }
Blaze513 1:94c648931f84 77 DataLines.write(0xFF);
Blaze513 1:94c648931f84 78 DataLines.write(0xFF);
Blaze513 1:94c648931f84 79 ChipSelect.write(1);
Blaze513 1:94c648931f84 80 if (Mode == 0x01)
Blaze513 1:94c648931f84 81 {
Blaze513 1:94c648931f84 82 ChipSelect.write(0);
Blaze513 1:94c648931f84 83 t = 0;
Blaze513 1:94c648931f84 84 do
Blaze513 1:94c648931f84 85 {
Blaze513 1:94c648931f84 86 t++;
Blaze513 1:94c648931f84 87 } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout));
Blaze513 1:94c648931f84 88 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 89 DataLines.write(0xFD);
Blaze513 1:94c648931f84 90 DataLines.write(0xFF);
Blaze513 1:94c648931f84 91 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 92 ChipSelect.write(1);
Blaze513 1:94c648931f84 93 DataLines.write(0xFF);
Blaze513 1:94c648931f84 94 }
Blaze513 1:94c648931f84 95 else
Blaze513 1:94c648931f84 96 {
Blaze513 1:94c648931f84 97 Command(12, 0, Workspace);
Blaze513 1:94c648931f84 98 ChipSelect.write(0);
Blaze513 1:94c648931f84 99 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 100 ChipSelect.write(1);
Blaze513 1:94c648931f84 101 DataLines.write(0xFF);
Blaze513 1:94c648931f84 102 }
Blaze513 1:94c648931f84 103 Index = 0;
Blaze513 1:94c648931f84 104 Mode = 0x00;
Blaze513 1:94c648931f84 105 }
Blaze513 1:94c648931f84 106 return 0xFF;
Blaze513 1:94c648931f84 107
Blaze513 1:94c648931f84 108 case 0x01:
Blaze513 1:94c648931f84 109 if (Mode != 0x01)
Blaze513 1:94c648931f84 110 {
Blaze513 1:94c648931f84 111 Log(0, 0);
Blaze513 1:94c648931f84 112 Command(25, 0, Workspace);
Blaze513 1:94c648931f84 113 Mode = 0x01;
Blaze513 1:94c648931f84 114 }
Blaze513 1:94c648931f84 115 if (Index == 0)
Blaze513 1:94c648931f84 116 {
Blaze513 1:94c648931f84 117 ChipSelect.write(0);
Blaze513 1:94c648931f84 118 DataLines.write(0xFC);
Blaze513 1:94c648931f84 119 DataLines.write(Data);
Blaze513 1:94c648931f84 120 ChipSelect.write(1);
Blaze513 1:94c648931f84 121 Index++;
Blaze513 1:94c648931f84 122 }
Blaze513 1:94c648931f84 123 else if (Index < 511)
Blaze513 1:94c648931f84 124 {
Blaze513 1:94c648931f84 125 ChipSelect.write(0);
Blaze513 1:94c648931f84 126 DataLines.write(Data);
Blaze513 1:94c648931f84 127 ChipSelect.write(1);
Blaze513 1:94c648931f84 128 Index++;
Blaze513 1:94c648931f84 129 }
Blaze513 1:94c648931f84 130 else
Blaze513 1:94c648931f84 131 {
Blaze513 1:94c648931f84 132 ChipSelect.write(0);
Blaze513 1:94c648931f84 133 DataLines.write(Data);
Blaze513 1:94c648931f84 134 DataLines.write(0xFF);
Blaze513 1:94c648931f84 135 DataLines.write(0xFF);
Blaze513 1:94c648931f84 136 t = 0;
Blaze513 1:94c648931f84 137 do
Blaze513 1:94c648931f84 138 {
Blaze513 1:94c648931f84 139 t++;
Blaze513 1:94c648931f84 140 } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout));
Blaze513 1:94c648931f84 141 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 142 ChipSelect.write(1);
Blaze513 1:94c648931f84 143 Index = 0;
Blaze513 1:94c648931f84 144 }
Blaze513 1:94c648931f84 145 return 0xFF;
Blaze513 1:94c648931f84 146
Blaze513 1:94c648931f84 147 case 0x02:
Blaze513 1:94c648931f84 148 if (Mode != 0x02)
Blaze513 1:94c648931f84 149 {
Blaze513 1:94c648931f84 150 Log(0, 0);
Blaze513 1:94c648931f84 151 Command(18, 0, Workspace);
Blaze513 1:94c648931f84 152 Mode = 0x02;
Blaze513 1:94c648931f84 153 }
Blaze513 1:94c648931f84 154 if (Index == 0)
Blaze513 1:94c648931f84 155 {
Blaze513 1:94c648931f84 156 ChipSelect.write(0);
Blaze513 1:94c648931f84 157 t = 0;
Blaze513 1:94c648931f84 158 do
Blaze513 1:94c648931f84 159 {
Blaze513 1:94c648931f84 160 t++;
Blaze513 1:94c648931f84 161 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
Blaze513 1:94c648931f84 162 Workspace[0] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 163 ChipSelect.write(1);
Blaze513 1:94c648931f84 164 Index++;
Blaze513 1:94c648931f84 165 return Workspace[0];
Blaze513 1:94c648931f84 166 }
Blaze513 1:94c648931f84 167 else if (Index < 511)
Blaze513 1:94c648931f84 168 {
Blaze513 1:94c648931f84 169 ChipSelect.write(0);
Blaze513 1:94c648931f84 170 Workspace[0] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 171 ChipSelect.write(1);
Blaze513 1:94c648931f84 172 Index++;
Blaze513 1:94c648931f84 173 return Workspace[0];
Blaze513 1:94c648931f84 174 }
Blaze513 1:94c648931f84 175 else
Blaze513 1:94c648931f84 176 {
Blaze513 1:94c648931f84 177 ChipSelect.write(0);
Blaze513 1:94c648931f84 178 Workspace[0] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 179 DataLines.write(0xFF);
Blaze513 1:94c648931f84 180 DataLines.write(0xFF);
Blaze513 1:94c648931f84 181 ChipSelect.write(1);
Blaze513 1:94c648931f84 182 Index = 0;
Blaze513 1:94c648931f84 183 return Workspace[0];
Blaze513 1:94c648931f84 184 }
Blaze513 1:94c648931f84 185
Blaze513 1:94c648931f84 186 default:
Blaze513 1:94c648931f84 187 return 0xFF;
Blaze513 0:f3870f76a890 188 }
Blaze513 0:f3870f76a890 189 }
Blaze513 0:f3870f76a890 190
Blaze513 1:94c648931f84 191 unsigned char SDCard::Write(unsigned int Address, unsigned char* Data)
Blaze513 0:f3870f76a890 192 {
Blaze513 1:94c648931f84 193 if (!Capacity)
Blaze513 0:f3870f76a890 194 {
Blaze513 1:94c648931f84 195 Command(24, Address * 512, Workspace);
Blaze513 1:94c648931f84 196 if (Workspace[0])
Blaze513 1:94c648931f84 197 { return 0x04; }
Blaze513 0:f3870f76a890 198 }
Blaze513 0:f3870f76a890 199 else
Blaze513 0:f3870f76a890 200 {
Blaze513 1:94c648931f84 201 Command(24, Address, Workspace);
Blaze513 1:94c648931f84 202 if (Workspace[0])
Blaze513 1:94c648931f84 203 { return 0x04; }
Blaze513 1:94c648931f84 204 }
Blaze513 1:94c648931f84 205 DataCRC(512, Data, Workspace);
Blaze513 1:94c648931f84 206 ChipSelect.write(0);
Blaze513 1:94c648931f84 207 DataLines.write(0xFE);
Blaze513 1:94c648931f84 208 for (unsigned short i = 0; i < 512; i++)
Blaze513 1:94c648931f84 209 {
Blaze513 1:94c648931f84 210 DataLines.write(Data[i]);
Blaze513 1:94c648931f84 211 }
Blaze513 1:94c648931f84 212 DataLines.write(Workspace[0]);
Blaze513 1:94c648931f84 213 DataLines.write(Workspace[1]);
Blaze513 1:94c648931f84 214 t = 0;
Blaze513 1:94c648931f84 215 do
Blaze513 1:94c648931f84 216 {
Blaze513 1:94c648931f84 217 Workspace[0] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 218 t++;
Blaze513 1:94c648931f84 219 } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout));
Blaze513 1:94c648931f84 220 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 221 ChipSelect.write(1);
Blaze513 1:94c648931f84 222 DataLines.write(0xFF);
Blaze513 1:94c648931f84 223 if (((Workspace[0] & 0x1F) != 0x05) || (t == Timeout))
Blaze513 1:94c648931f84 224 { return 0x01; }
Blaze513 1:94c648931f84 225 else
Blaze513 1:94c648931f84 226 { return 0x00; }
Blaze513 1:94c648931f84 227 }
Blaze513 1:94c648931f84 228 unsigned char SDCard::Write(unsigned int Address, unsigned char SectorCount, unsigned char* Data)
Blaze513 1:94c648931f84 229 {
Blaze513 1:94c648931f84 230 static unsigned char CurrentSectorCount = 1;
Blaze513 1:94c648931f84 231 if (SectorCount != CurrentSectorCount)
Blaze513 1:94c648931f84 232 {
Blaze513 1:94c648931f84 233 Command(55, 0, Workspace);
Blaze513 1:94c648931f84 234 Command(23, SectorCount, Workspace);
Blaze513 1:94c648931f84 235 if (Workspace[0])
Blaze513 1:94c648931f84 236 { return 0x04; }
Blaze513 1:94c648931f84 237 CurrentSectorCount = SectorCount;
Blaze513 1:94c648931f84 238 }
Blaze513 1:94c648931f84 239 if (!Capacity)
Blaze513 1:94c648931f84 240 {
Blaze513 1:94c648931f84 241 Command(25, Address * 512, Workspace);
Blaze513 1:94c648931f84 242 if (Workspace[0])
Blaze513 1:94c648931f84 243 { return 0x04; }
Blaze513 1:94c648931f84 244 }
Blaze513 1:94c648931f84 245 else
Blaze513 1:94c648931f84 246 {
Blaze513 1:94c648931f84 247 Command(25, Address, Workspace);
Blaze513 1:94c648931f84 248 if (Workspace[0])
Blaze513 1:94c648931f84 249 { return 0x04; }
Blaze513 1:94c648931f84 250 }
Blaze513 1:94c648931f84 251 Workspace[4] = 0x00;
Blaze513 1:94c648931f84 252 for (unsigned char i = 0; i < SectorCount; i++)
Blaze513 1:94c648931f84 253 {
Blaze513 1:94c648931f84 254 DataCRC(512, &Data[i * 512], Workspace);
Blaze513 1:94c648931f84 255 ChipSelect.write(0);
Blaze513 1:94c648931f84 256 DataLines.write(0xFC);
Blaze513 1:94c648931f84 257 for (unsigned int j = i * 512; j < (i + 1) * 512; j++)
Blaze513 0:f3870f76a890 258 {
Blaze513 1:94c648931f84 259 DataLines.write(Data[j]);
Blaze513 1:94c648931f84 260 }
Blaze513 1:94c648931f84 261 DataLines.write(Workspace[0]);
Blaze513 1:94c648931f84 262 DataLines.write(Workspace[1]);
Blaze513 1:94c648931f84 263 t = 0;
Blaze513 1:94c648931f84 264 do
Blaze513 1:94c648931f84 265 {
Blaze513 1:94c648931f84 266 Workspace[0] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 267 t++;
Blaze513 1:94c648931f84 268 } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout));
Blaze513 1:94c648931f84 269 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 270 ChipSelect.write(1);
Blaze513 1:94c648931f84 271 Workspace[4] |= Workspace[0];
Blaze513 1:94c648931f84 272 if (t == Timeout)
Blaze513 1:94c648931f84 273 {
Blaze513 1:94c648931f84 274 ChipSelect.write(0);
Blaze513 1:94c648931f84 275 DataLines.write(0xFD);
Blaze513 1:94c648931f84 276 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 277 ChipSelect.write(1);
Blaze513 1:94c648931f84 278 DataLines.write(0xFF);
Blaze513 1:94c648931f84 279 return 0x01;
Blaze513 0:f3870f76a890 280 }
Blaze513 0:f3870f76a890 281 }
Blaze513 0:f3870f76a890 282 ChipSelect.write(0);
Blaze513 1:94c648931f84 283 DataLines.write(0xFD);
Blaze513 1:94c648931f84 284 DataLines.write(0xFF);
Blaze513 1:94c648931f84 285 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 286 ChipSelect.write(1);
Blaze513 1:94c648931f84 287 DataLines.write(0xFF);
Blaze513 1:94c648931f84 288 if ((Workspace[4] & 0x1F) != 0x05)
Blaze513 1:94c648931f84 289 { return 0x01; }
Blaze513 1:94c648931f84 290 else
Blaze513 1:94c648931f84 291 { return 0x00; }
Blaze513 1:94c648931f84 292 }
Blaze513 1:94c648931f84 293
Blaze513 1:94c648931f84 294 unsigned char SDCard::Read(unsigned int Address, unsigned char* Data)
Blaze513 1:94c648931f84 295 {
Blaze513 1:94c648931f84 296 if (!Capacity)
Blaze513 0:f3870f76a890 297 {
Blaze513 1:94c648931f84 298 Command(17, Address * 512, Workspace);
Blaze513 1:94c648931f84 299 if (Workspace[0])
Blaze513 1:94c648931f84 300 { return 0x04; }
Blaze513 0:f3870f76a890 301 }
Blaze513 1:94c648931f84 302 else
Blaze513 1:94c648931f84 303 {
Blaze513 1:94c648931f84 304 Command(17, Address, Workspace);
Blaze513 1:94c648931f84 305 if (Workspace[0])
Blaze513 1:94c648931f84 306 { return 0x04; }
Blaze513 1:94c648931f84 307 }
Blaze513 1:94c648931f84 308 ChipSelect.write(0);
Blaze513 1:94c648931f84 309 t = 0;
Blaze513 1:94c648931f84 310 do
Blaze513 0:f3870f76a890 311 {
Blaze513 1:94c648931f84 312 t++;
Blaze513 1:94c648931f84 313 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
Blaze513 1:94c648931f84 314 if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
Blaze513 1:94c648931f84 315 for (unsigned short i = 0; i < 512; i++)
Blaze513 1:94c648931f84 316 {
Blaze513 1:94c648931f84 317 Data[i] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 318 }
Blaze513 1:94c648931f84 319 Workspace[2] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 320 Workspace[3] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 321 ChipSelect.write(1);
Blaze513 0:f3870f76a890 322 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 323 DataCRC(512, Data, Workspace);
Blaze513 1:94c648931f84 324 if (CRCMode && ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])))
Blaze513 1:94c648931f84 325 { return 0x01; }
Blaze513 1:94c648931f84 326 else
Blaze513 1:94c648931f84 327 { return 0x00; }
Blaze513 1:94c648931f84 328 }
Blaze513 1:94c648931f84 329 unsigned char SDCard::Read(unsigned int Address, unsigned char SectorCount, unsigned char* Data)
Blaze513 1:94c648931f84 330 {
Blaze513 1:94c648931f84 331 if (!Capacity)
Blaze513 1:94c648931f84 332 {
Blaze513 1:94c648931f84 333 Command(18, Address * 512, Workspace);
Blaze513 1:94c648931f84 334 if (Workspace[0])
Blaze513 1:94c648931f84 335 { return 0; }
Blaze513 1:94c648931f84 336 }
Blaze513 0:f3870f76a890 337 else
Blaze513 1:94c648931f84 338 {
Blaze513 1:94c648931f84 339 Command(18, Address, Workspace);
Blaze513 1:94c648931f84 340 if (Workspace[0])
Blaze513 1:94c648931f84 341 { return 0; }
Blaze513 1:94c648931f84 342 }
Blaze513 1:94c648931f84 343 Workspace[4] = 0x00;
Blaze513 1:94c648931f84 344 for (unsigned char i = 0; i < SectorCount; i++)
Blaze513 1:94c648931f84 345 {
Blaze513 1:94c648931f84 346 ChipSelect.write(0);
Blaze513 1:94c648931f84 347 t = 0;
Blaze513 1:94c648931f84 348 do
Blaze513 1:94c648931f84 349 {
Blaze513 1:94c648931f84 350 t++;
Blaze513 1:94c648931f84 351 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
Blaze513 1:94c648931f84 352 if (t == Timeout)
Blaze513 1:94c648931f84 353 {
Blaze513 1:94c648931f84 354 ChipSelect.write(1);
Blaze513 1:94c648931f84 355 Command(12, 0, Workspace);
Blaze513 1:94c648931f84 356 ChipSelect.write(0);
Blaze513 1:94c648931f84 357 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 358 ChipSelect.write(1);
Blaze513 1:94c648931f84 359 DataLines.write(0xFF);
Blaze513 1:94c648931f84 360 return 0x01;
Blaze513 1:94c648931f84 361 }
Blaze513 1:94c648931f84 362 for (unsigned int j = i * 512; j < (i + 1) * 512; j++)
Blaze513 1:94c648931f84 363 {
Blaze513 1:94c648931f84 364 Data[j] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 365 }
Blaze513 1:94c648931f84 366 Workspace[2] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 367 Workspace[3] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 368 ChipSelect.write(1);
Blaze513 1:94c648931f84 369 DataCRC(512, &Data[i * 512], Workspace);
Blaze513 1:94c648931f84 370 Workspace[4] |= ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]));
Blaze513 1:94c648931f84 371 }
Blaze513 1:94c648931f84 372 Command(12, 0, Workspace);
Blaze513 1:94c648931f84 373 ChipSelect.write(0);
Blaze513 1:94c648931f84 374 while (!DataLines.write(0xFF));
Blaze513 1:94c648931f84 375 ChipSelect.write(1);
Blaze513 1:94c648931f84 376 if (Workspace[4])
Blaze513 1:94c648931f84 377 { return 0x01; }
Blaze513 1:94c648931f84 378 else
Blaze513 1:94c648931f84 379 { return 0x00; }
Blaze513 0:f3870f76a890 380 }
Blaze513 0:f3870f76a890 381
Blaze513 1:94c648931f84 382 unsigned char SDCard::SelectCRCMode(bool Mode)
Blaze513 0:f3870f76a890 383 {
Blaze513 1:94c648931f84 384 t = 0;
Blaze513 1:94c648931f84 385 do
Blaze513 1:94c648931f84 386 {
Blaze513 1:94c648931f84 387 Command(59, Mode, Workspace);
Blaze513 1:94c648931f84 388 t++;
Blaze513 1:94c648931f84 389 } while (Workspace[0] && (t < Timeout));
Blaze513 1:94c648931f84 390 CRCMode = Mode;
Blaze513 1:94c648931f84 391 if (t == Timeout)
Blaze513 1:94c648931f84 392 { return 0x01; }
Blaze513 1:94c648931f84 393 else
Blaze513 1:94c648931f84 394 { return 0x00; }
Blaze513 1:94c648931f84 395 }
Blaze513 1:94c648931f84 396
Blaze513 1:94c648931f84 397 unsigned char SDCard::Initialize()
Blaze513 1:94c648931f84 398 {
Blaze513 1:94c648931f84 399 for (unsigned char i = 0; i < 16; i++)
Blaze513 0:f3870f76a890 400 {
Blaze513 0:f3870f76a890 401 DataLines.write(0xFF);
Blaze513 1:94c648931f84 402 //clock card at least 74 times to power up
Blaze513 0:f3870f76a890 403 }
Blaze513 1:94c648931f84 404
Blaze513 1:94c648931f84 405 t = 0;
Blaze513 1:94c648931f84 406 do
Blaze513 0:f3870f76a890 407 {
Blaze513 0:f3870f76a890 408 Command(0, 0, Workspace);
Blaze513 0:f3870f76a890 409 //send command 0 to put the card into SPI mode
Blaze513 1:94c648931f84 410 t++;
Blaze513 1:94c648931f84 411 } while ((Workspace[0] != 0x01) && (t < Timeout));
Blaze513 1:94c648931f84 412 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 413
Blaze513 1:94c648931f84 414 t = 0;
Blaze513 1:94c648931f84 415 do
Blaze513 0:f3870f76a890 416 {
Blaze513 0:f3870f76a890 417 Command(59, 1, Workspace);
Blaze513 1:94c648931f84 418 //turn on CRCs
Blaze513 1:94c648931f84 419 t++;
Blaze513 1:94c648931f84 420 } while ((Workspace[0] != 0x01) && (Workspace[0] != 0x05) && (t < Timeout));
Blaze513 1:94c648931f84 421 //command 59 is not valid for all cards in idle state
Blaze513 1:94c648931f84 422 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 423
Blaze513 1:94c648931f84 424 t = 0;
Blaze513 1:94c648931f84 425 do
Blaze513 0:f3870f76a890 426 {
Blaze513 0:f3870f76a890 427 Command(8, 426, Workspace);
Blaze513 0:f3870f76a890 428 //voltage bits are 0x01 for 2.7V - 3.6V,
Blaze513 0:f3870f76a890 429 //check pattern 0xAA, [00,00,01,AA] = 426
Blaze513 1:94c648931f84 430 t++;
Blaze513 1:94c648931f84 431 } while (((Workspace[0] != 0x01) || ((Workspace[3] & 0x0F) != 0x01) ||
Blaze513 1:94c648931f84 432 (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05) && (t < Timeout));
Blaze513 1:94c648931f84 433 //check version, voltage acceptance, and check pattern
Blaze513 1:94c648931f84 434 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 435 Version = Workspace[0] != 0x05;
Blaze513 0:f3870f76a890 436 //store card version
Blaze513 1:94c648931f84 437
Blaze513 1:94c648931f84 438 t = 0;
Blaze513 1:94c648931f84 439 do
Blaze513 0:f3870f76a890 440 {
Blaze513 0:f3870f76a890 441 Command(58, 0, Workspace);
Blaze513 0:f3870f76a890 442 //check the OCR
Blaze513 1:94c648931f84 443 t++;
Blaze513 1:94c648931f84 444 } while (((Workspace[0] != 0x01) ||
Blaze513 1:94c648931f84 445 !((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) && (t < Timeout));
Blaze513 1:94c648931f84 446 //check for correct operating voltage 3.3V
Blaze513 1:94c648931f84 447 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 448
Blaze513 1:94c648931f84 449 t = 0;
Blaze513 1:94c648931f84 450 do
Blaze513 0:f3870f76a890 451 {
Blaze513 0:f3870f76a890 452 Command(55, 0, Workspace);
Blaze513 0:f3870f76a890 453 Command(41, 1073741824, Workspace);
Blaze513 1:94c648931f84 454 //specify host supports high capacity
Blaze513 1:94c648931f84 455 //cards, [40,00,00,00] = 1073741824
Blaze513 1:94c648931f84 456 t++;
Blaze513 1:94c648931f84 457 } while (Workspace[0] && (t < Timeout));
Blaze513 1:94c648931f84 458 //check if card is ready
Blaze513 1:94c648931f84 459 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 460
Blaze513 1:94c648931f84 461 if (SelectCRCMode(1))
Blaze513 1:94c648931f84 462 { return 0x01; }
Blaze513 1:94c648931f84 463 //turn on CRCs for all cards
Blaze513 1:94c648931f84 464
Blaze513 1:94c648931f84 465 t = 0;
Blaze513 1:94c648931f84 466 do
Blaze513 0:f3870f76a890 467 {
Blaze513 0:f3870f76a890 468 Command(58, 0, Workspace);
Blaze513 0:f3870f76a890 469 //check the OCR again
Blaze513 1:94c648931f84 470 t++;
Blaze513 1:94c648931f84 471 } while ((Workspace[0] || !(Workspace[1] & 0x80)) && (t < Timeout));
Blaze513 1:94c648931f84 472 //check power up status
Blaze513 1:94c648931f84 473 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 474 for (unsigned char i = 0; i < 4; i++)
Blaze513 1:94c648931f84 475 {
Blaze513 1:94c648931f84 476 OCR[i] = Workspace[i + 1];
Blaze513 1:94c648931f84 477 //record OCR
Blaze513 0:f3870f76a890 478 }
Blaze513 0:f3870f76a890 479 Capacity = (OCR[0] & 0x40) == 0x40;
Blaze513 0:f3870f76a890 480 //record capacity
Blaze513 1:94c648931f84 481
Blaze513 1:94c648931f84 482 t = 0;
Blaze513 1:94c648931f84 483 do
Blaze513 0:f3870f76a890 484 {
Blaze513 1:94c648931f84 485 do
Blaze513 0:f3870f76a890 486 {
Blaze513 1:94c648931f84 487 Command(9, 0, Workspace);
Blaze513 1:94c648931f84 488 //read the card-specific-data register
Blaze513 1:94c648931f84 489 t++;
Blaze513 1:94c648931f84 490 } while (Workspace[0] && (t < Timeout));
Blaze513 1:94c648931f84 491 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 492 ChipSelect.write(0);
Blaze513 1:94c648931f84 493 do
Blaze513 1:94c648931f84 494 {
Blaze513 1:94c648931f84 495 t++;
Blaze513 1:94c648931f84 496 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
Blaze513 0:f3870f76a890 497 //get to the start-data-block token
Blaze513 1:94c648931f84 498 if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
Blaze513 1:94c648931f84 499 for (unsigned char i = 0; i < 16; i++)
Blaze513 0:f3870f76a890 500 {
Blaze513 1:94c648931f84 501 CSD[i] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 502 //gather CSD
Blaze513 0:f3870f76a890 503 }
Blaze513 1:94c648931f84 504 Workspace[2] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 505 Workspace[3] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 506 //save CSD CRC
Blaze513 0:f3870f76a890 507 ChipSelect.write(1);
Blaze513 0:f3870f76a890 508 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 509 DataCRC(16, CSD, Workspace);
Blaze513 0:f3870f76a890 510 //calculate the CSD data CRC
Blaze513 1:94c648931f84 511 Workspace[4] = 0;
Blaze513 1:94c648931f84 512 for (unsigned char i = 0; i < 15; i++)
Blaze513 0:f3870f76a890 513 {
Blaze513 1:94c648931f84 514 Workspace[4] = CommandCRCTable[Workspace[4]] ^ CSD[i];
Blaze513 0:f3870f76a890 515 }
Blaze513 1:94c648931f84 516 Workspace[4] = CommandCRCTable[Workspace[4]] | 0x01;
Blaze513 1:94c648931f84 517 //calculate the CSD table CRC
Blaze513 1:94c648931f84 518 t++;
Blaze513 1:94c648931f84 519 } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]) ||
Blaze513 1:94c648931f84 520 (Workspace[4] != CSD[15])) && (t < Timeout));
Blaze513 1:94c648931f84 521 //check all CSD CRCs
Blaze513 1:94c648931f84 522 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 523
Blaze513 1:94c648931f84 524 if (((CSD[3] & 0x07) > 0x02) ||
Blaze513 1:94c648931f84 525 (((CSD[3] & 0x78) > 0x30) && ((CSD[3] & 0x07) > 0x01)))
Blaze513 0:f3870f76a890 526 {
Blaze513 0:f3870f76a890 527 DataLines.frequency(25000000);
Blaze513 1:94c648931f84 528 //maximum speed is 25MHz
Blaze513 0:f3870f76a890 529 }
Blaze513 0:f3870f76a890 530 else
Blaze513 0:f3870f76a890 531 {
Blaze513 0:f3870f76a890 532 Workspace[0] = 1;
Blaze513 1:94c648931f84 533 for (unsigned char i = 0; i < (CSD[3] & 0x07); i++)
Blaze513 0:f3870f76a890 534 {
Blaze513 0:f3870f76a890 535 Workspace[0] *= 10;
Blaze513 0:f3870f76a890 536 //the first three bits are a power of ten multiplier for speed
Blaze513 0:f3870f76a890 537 }
Blaze513 0:f3870f76a890 538 switch (CSD[3] & 0x78)
Blaze513 0:f3870f76a890 539 {
Blaze513 0:f3870f76a890 540 case 0x08: DataLines.frequency(Workspace[0] * 100000); break;
Blaze513 0:f3870f76a890 541 case 0x10: DataLines.frequency(Workspace[0] * 120000); break;
Blaze513 0:f3870f76a890 542 case 0x18: DataLines.frequency(Workspace[0] * 140000); break;
Blaze513 0:f3870f76a890 543 case 0x20: DataLines.frequency(Workspace[0] * 150000); break;
Blaze513 0:f3870f76a890 544 case 0x28: DataLines.frequency(Workspace[0] * 200000); break;
Blaze513 0:f3870f76a890 545 case 0x30: DataLines.frequency(Workspace[0] * 250000); break;
Blaze513 0:f3870f76a890 546 case 0x38: DataLines.frequency(Workspace[0] * 300000); break;
Blaze513 0:f3870f76a890 547 case 0x40: DataLines.frequency(Workspace[0] * 350000); break;
Blaze513 0:f3870f76a890 548 case 0x48: DataLines.frequency(Workspace[0] * 400000); break;
Blaze513 0:f3870f76a890 549 case 0x50: DataLines.frequency(Workspace[0] * 450000); break;
Blaze513 0:f3870f76a890 550 case 0x58: DataLines.frequency(Workspace[0] * 500000); break;
Blaze513 0:f3870f76a890 551 case 0x60: DataLines.frequency(Workspace[0] * 550000); break;
Blaze513 0:f3870f76a890 552 case 0x68: DataLines.frequency(Workspace[0] * 600000); break;
Blaze513 0:f3870f76a890 553 case 0x70: DataLines.frequency(Workspace[0] * 700000); break;
Blaze513 0:f3870f76a890 554 case 0x78: DataLines.frequency(Workspace[0] * 800000); break;
Blaze513 0:f3870f76a890 555 default: break;
Blaze513 0:f3870f76a890 556 //read the CSD card speed bits and speed up card operations
Blaze513 0:f3870f76a890 557 }
Blaze513 0:f3870f76a890 558 }
Blaze513 1:94c648931f84 559
Blaze513 1:94c648931f84 560 if (CSD[4] & 0x40)
Blaze513 1:94c648931f84 561 //check for switch command class support
Blaze513 1:94c648931f84 562 {
Blaze513 1:94c648931f84 563 t = 0;
Blaze513 1:94c648931f84 564 do
Blaze513 1:94c648931f84 565 {
Blaze513 1:94c648931f84 566 Command(6, 2147483649, Workspace);
Blaze513 1:94c648931f84 567 //switch to high-speed mode (SDR25, 50MHz)
Blaze513 1:94c648931f84 568 t++;
Blaze513 1:94c648931f84 569 } while (Workspace[0] && (Workspace[0] != 0x04) && (t < Timeout));
Blaze513 1:94c648931f84 570 //some cards that support switch class commands respond with illegal command
Blaze513 1:94c648931f84 571 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 572 if (!Workspace[0])
Blaze513 1:94c648931f84 573 {
Blaze513 1:94c648931f84 574 do
Blaze513 1:94c648931f84 575 {
Blaze513 1:94c648931f84 576 ChipSelect.write(0);
Blaze513 1:94c648931f84 577 do
Blaze513 1:94c648931f84 578 {
Blaze513 1:94c648931f84 579 t++;
Blaze513 1:94c648931f84 580 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout));
Blaze513 1:94c648931f84 581 //get to the start-data-block token
Blaze513 1:94c648931f84 582 if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; }
Blaze513 1:94c648931f84 583 for (unsigned char i = 0; i < 64; i++)
Blaze513 1:94c648931f84 584 {
Blaze513 1:94c648931f84 585 FSR[i] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 586 //gather function-status register
Blaze513 1:94c648931f84 587 }
Blaze513 1:94c648931f84 588 Workspace[2] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 589 Workspace[3] = DataLines.write(0xFF);
Blaze513 1:94c648931f84 590 //record data CRC
Blaze513 1:94c648931f84 591 ChipSelect.write(1);
Blaze513 1:94c648931f84 592 DataLines.write(0xFF);
Blaze513 1:94c648931f84 593 DataCRC(64, FSR, Workspace);
Blaze513 1:94c648931f84 594 //calculate CRC
Blaze513 1:94c648931f84 595 t++;
Blaze513 1:94c648931f84 596 } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])) &&
Blaze513 1:94c648931f84 597 (t < Timeout));
Blaze513 1:94c648931f84 598 //complete CRC
Blaze513 1:94c648931f84 599 if (t == Timeout) { return 0x01; }
Blaze513 1:94c648931f84 600 if ((FSR[13] & 0x02) && ((FSR[16] & 0x0F) == 0x01))
Blaze513 1:94c648931f84 601 {
Blaze513 1:94c648931f84 602 DataLines.frequency(50000000);
Blaze513 1:94c648931f84 603 //increase speed if function switch was successful
Blaze513 1:94c648931f84 604 }
Blaze513 1:94c648931f84 605 }
Blaze513 1:94c648931f84 606 }
Blaze513 1:94c648931f84 607
Blaze513 0:f3870f76a890 608 if (!Version)
Blaze513 0:f3870f76a890 609 {
Blaze513 1:94c648931f84 610 t = 0;
Blaze513 1:94c648931f84 611 do
Blaze513 0:f3870f76a890 612 {
Blaze513 0:f3870f76a890 613 Command(16, 512, Workspace);
Blaze513 0:f3870f76a890 614 //set data-block length to 512 bytes
Blaze513 1:94c648931f84 615 t++;
Blaze513 1:94c648931f84 616 } while (Workspace[0] && (t < Timeout));
Blaze513 1:94c648931f84 617 if (t == Timeout) { return 0x01; }
Blaze513 0:f3870f76a890 618 }
Blaze513 1:94c648931f84 619
Blaze513 1:94c648931f84 620 if (SelectCRCMode(0))
Blaze513 1:94c648931f84 621 { return 0x01; }
Blaze513 1:94c648931f84 622 //turn off CRCs
Blaze513 1:94c648931f84 623
Blaze513 1:94c648931f84 624 return 0x00;
Blaze513 0:f3870f76a890 625 }
Blaze513 0:f3870f76a890 626
Blaze513 0:f3870f76a890 627 void SDCard::Command(unsigned char Index, unsigned int Argument, unsigned char* Response)
Blaze513 0:f3870f76a890 628 {
Blaze513 1:94c648931f84 629 CommandCRC(&Index, &Argument, Workspace);
Blaze513 1:94c648931f84 630 //calculate command CRC
Blaze513 0:f3870f76a890 631 ChipSelect.write(0);
Blaze513 0:f3870f76a890 632 //assert chip select low to synchronize command
Blaze513 0:f3870f76a890 633 DataLines.write(0x40 | Index);
Blaze513 0:f3870f76a890 634 //the index is assumed valid, commands start with "01b"
Blaze513 0:f3870f76a890 635 DataLines.write(((char*)&Argument)[3]);
Blaze513 0:f3870f76a890 636 DataLines.write(((char*)&Argument)[2]);
Blaze513 0:f3870f76a890 637 DataLines.write(((char*)&Argument)[1]);
Blaze513 0:f3870f76a890 638 DataLines.write(((char*)&Argument)[0]);
Blaze513 0:f3870f76a890 639 //send the argument bytes in order from MSB to LSB (mbed is little endian)
Blaze513 1:94c648931f84 640 DataLines.write(Workspace[0]);
Blaze513 0:f3870f76a890 641 //send the command CRC
Blaze513 1:94c648931f84 642 t = 0;
Blaze513 1:94c648931f84 643 do
Blaze513 0:f3870f76a890 644 {
Blaze513 0:f3870f76a890 645 Response[0] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 646 //clock the card high to let it run operations, the first byte will be
Blaze513 0:f3870f76a890 647 //busy (all high), the response will be sent some time later
Blaze513 1:94c648931f84 648 t++;
Blaze513 1:94c648931f84 649 } while ((Response[0] & 0x80) && (t < Timeout));
Blaze513 1:94c648931f84 650 //check for a response by testing if the first bit is low
Blaze513 0:f3870f76a890 651 if ((Index == 8) || (Index == 13) || (Index == 58))
Blaze513 0:f3870f76a890 652 {
Blaze513 1:94c648931f84 653 for (unsigned char i = 1; i < 5; i++)
Blaze513 0:f3870f76a890 654 {
Blaze513 1:94c648931f84 655 Response[i] = DataLines.write(0xFF);
Blaze513 0:f3870f76a890 656 }
Blaze513 0:f3870f76a890 657 //get the rest of the response
Blaze513 0:f3870f76a890 658 }
Blaze513 0:f3870f76a890 659 ChipSelect.write(1);
Blaze513 0:f3870f76a890 660 //assert chip select high to synchronize command
Blaze513 0:f3870f76a890 661 DataLines.write(0xFF);
Blaze513 0:f3870f76a890 662 //clock the deselected card high to complete processing for some cards
Blaze513 0:f3870f76a890 663 }
Blaze513 0:f3870f76a890 664
Blaze513 1:94c648931f84 665 void SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr, unsigned char* Result)
Blaze513 0:f3870f76a890 666 {
Blaze513 1:94c648931f84 667 if (CRCMode)
Blaze513 1:94c648931f84 668 {
Blaze513 1:94c648931f84 669 Result[0] =
Blaze513 0:f3870f76a890 670 CommandCRCTable[
Blaze513 0:f3870f76a890 671 CommandCRCTable[
Blaze513 0:f3870f76a890 672 CommandCRCTable[
Blaze513 0:f3870f76a890 673 CommandCRCTable[
Blaze513 1:94c648931f84 674 CommandCRCTable[
Blaze513 1:94c648931f84 675 *IndexPtr | 0x40
Blaze513 1:94c648931f84 676 ] ^ ((char*)ArgumentPtr)[3]
Blaze513 1:94c648931f84 677 ] ^ ((char*)ArgumentPtr)[2]
Blaze513 1:94c648931f84 678 ] ^ ((char*)ArgumentPtr)[1]
Blaze513 1:94c648931f84 679 ] ^ ((char*)ArgumentPtr)[0]
Blaze513 1:94c648931f84 680 ] | 0x01;
Blaze513 1:94c648931f84 681 }
Blaze513 1:94c648931f84 682 else
Blaze513 1:94c648931f84 683 {
Blaze513 1:94c648931f84 684 Result[0] = 0xFF;
Blaze513 1:94c648931f84 685 }
Blaze513 1:94c648931f84 686 //using a CRC table, the CRC result of a byte is equal to the byte
Blaze513 1:94c648931f84 687 //in the table at the address equal to the input byte, a message CRC
Blaze513 1:94c648931f84 688 //is obtained by successively XORing these with the message bytes
Blaze513 0:f3870f76a890 689 }
Blaze513 0:f3870f76a890 690
Blaze513 0:f3870f76a890 691 void SDCard::DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result)
Blaze513 0:f3870f76a890 692 {
Blaze513 1:94c648931f84 693 if (CRCMode)
Blaze513 0:f3870f76a890 694 {
Blaze513 1:94c648931f84 695 unsigned char Reference;
Blaze513 1:94c648931f84 696 //store the current CRC lookup value
Blaze513 1:94c648931f84 697 Result[0] = 0x00;
Blaze513 1:94c648931f84 698 Result[1] = 0x00;
Blaze513 1:94c648931f84 699 //initialize result carrier
Blaze513 1:94c648931f84 700 for (unsigned short i = 0; i < Length; i++)
Blaze513 1:94c648931f84 701 //step through each byte of the data to be checked
Blaze513 1:94c648931f84 702 {
Blaze513 1:94c648931f84 703 Reference = Result[0];
Blaze513 1:94c648931f84 704 //record current crc lookup for both bytes
Blaze513 1:94c648931f84 705 Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
Blaze513 1:94c648931f84 706 //new fist byte result is XORed with old second byte result
Blaze513 1:94c648931f84 707 Result[1] = DataCRCTable[(2 * Reference) + 1] ^ Data[i];
Blaze513 1:94c648931f84 708 //new second byte result is XORed with new data byte
Blaze513 1:94c648931f84 709 }
Blaze513 1:94c648931f84 710 for (unsigned char i = 0; i < 2; i++)
Blaze513 1:94c648931f84 711 //the final result must be XORed with two 0x00 bytes.
Blaze513 1:94c648931f84 712 {
Blaze513 1:94c648931f84 713 Reference = Result[0];
Blaze513 1:94c648931f84 714 Result[0] = DataCRCTable[2 * Reference] ^ Result[1];
Blaze513 1:94c648931f84 715 Result[1] = DataCRCTable[(2 * Reference) + 1];
Blaze513 1:94c648931f84 716 }
Blaze513 0:f3870f76a890 717 }
Blaze513 1:94c648931f84 718 else
Blaze513 0:f3870f76a890 719 {
Blaze513 1:94c648931f84 720 Result[0] = 0xFF;
Blaze513 1:94c648931f84 721 Result[1] = 0xFF;
Blaze513 0:f3870f76a890 722 }
Blaze513 0:f3870f76a890 723 }
Blaze513 0:f3870f76a890 724
Blaze513 0:f3870f76a890 725 void SDCard::GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table)
Blaze513 0:f3870f76a890 726 {
Blaze513 0:f3870f76a890 727 unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
Blaze513 1:94c648931f84 728 //this will hold information from the generator; the position indicates
Blaze513 1:94c648931f84 729 //the order of the encountered 1, the value indicates its position in
Blaze513 1:94c648931f84 730 //the generator, the 9th entry indicates the number of 1's encountered
Blaze513 1:94c648931f84 731 for (unsigned char i = 0; i < 64; i++)
Blaze513 0:f3870f76a890 732 {
Blaze513 0:f3870f76a890 733 if (((char*)&Generator)[7] & 0x80)
Blaze513 0:f3870f76a890 734 { break; }
Blaze513 0:f3870f76a890 735 Generator = Generator << 1;
Blaze513 0:f3870f76a890 736 //shift generator so that the first bit is high
Blaze513 0:f3870f76a890 737 }
Blaze513 1:94c648931f84 738 for (unsigned char i = 0; i < Size; i++)
Blaze513 0:f3870f76a890 739 {
Blaze513 1:94c648931f84 740 Table[i] = 0x00;
Blaze513 1:94c648931f84 741 //initialize table
Blaze513 0:f3870f76a890 742 }
Blaze513 0:f3870f76a890 743 for (unsigned char i = 0; i < 8; i++)
Blaze513 0:f3870f76a890 744 //increment through each generator bit
Blaze513 0:f3870f76a890 745 {
Blaze513 0:f3870f76a890 746 if ((0x80 >> i) & ((unsigned char*)&Generator)[7])
Blaze513 0:f3870f76a890 747 //if a 1 is encountered in the generator
Blaze513 0:f3870f76a890 748 {
Blaze513 0:f3870f76a890 749 Index[Index[8]] = i;
Blaze513 0:f3870f76a890 750 Index[8]++;
Blaze513 0:f3870f76a890 751 //record its order and location and increment the counter
Blaze513 0:f3870f76a890 752 }
Blaze513 0:f3870f76a890 753 for (unsigned char j = 0; j < (0x01 << i); j++)
Blaze513 0:f3870f76a890 754 //each bit increases the number of xor operations by a power of 2
Blaze513 0:f3870f76a890 755 {
Blaze513 0:f3870f76a890 756 for (unsigned char k = 0; k < Size; k++)
Blaze513 0:f3870f76a890 757 //we need to perform operations for each byte in the CRC result
Blaze513 0:f3870f76a890 758 {
Blaze513 0:f3870f76a890 759 Table[(Size * ((0x01 << i) + j)) + k] = Table[(Size * j) + k];
Blaze513 1:94c648931f84 760 //each new power is equal to all previous entries with an added
Blaze513 1:94c648931f84 761 //xor on the leftmost bit and each succeeding 1 on the generator
Blaze513 0:f3870f76a890 762 for (unsigned char l = 0; l < Index[8]; l++)
Blaze513 0:f3870f76a890 763 //increment through the encountered generator 1s
Blaze513 0:f3870f76a890 764 {
Blaze513 0:f3870f76a890 765 Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[7-k] << (i + 1 - Index[l]));
Blaze513 0:f3870f76a890 766 Table[(Size * ((0x01 << i) + j)) + k] ^= (((unsigned char*)&Generator)[6-k] >> (7 - i + Index[l]));
Blaze513 0:f3870f76a890 767 //xor the new bit and the new generator 1s
Blaze513 0:f3870f76a890 768 }
Blaze513 0:f3870f76a890 769 }
Blaze513 0:f3870f76a890 770 }
Blaze513 0:f3870f76a890 771 }
Blaze513 0:f3870f76a890 772 }