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