Components and supplies
SD Socket
Resistor 2.21k ohm
Single Turn Potentiometer- 10k ohms
Arduino UNO
RGB Backlight LCD - 16x2
Pushbutton switch 12mm
Resistor 1k ohm
Speaker: 0.25W, 8 ohms
Capacitor 22 µF
General Purpose Transistor NPN
General Purpose Transistor PNP
Resistor 47.5k ohm
Project description
Code
Talking Clock
c_cpp
1/* 2 * sd_bell.ino 3 * 4 * Created: 5/06/2017 23:34:47 5 * Author: moty22.co.uk 6 */ 7 8#include <LiquidCrystal.h> 9 10 // initialize the library with the numbers of the interface pins 11LiquidCrystal lcd(7, 8, A0, A1, A2, A3); 12 13const int CS = 10; // SD CS connected to digital pin PD4 14const int mosi = 11; 15const int clk = 13; 16const int ampON = 9; // led connected to digital pin PB0 17const int audio = 6; //output D6 18const int oc2b = 3; //1000Hz 19const int t1 = 5; //1000Hz 20const int talk = 2; //talk pushbutton 21const int minutes = A4; //minutes advance pushbutton 22const int hours = A5; //hours pushbutton 23int talkPB=1; // talk pushbutton status 24int minutesPB=1; // minutes pushbutton status 25int hoursPB=1; // hours pushbutton status 26 27unsigned long loc,BootSector, RootDir, SectorsPerFat, RootDirCluster, DataSector, FileCluster, FileSize; // 28unsigned int BytesPerSector, ReservedSectors, card; 29unsigned char fn=1, sdhc=0, SectorsPerCluster, Fats; 30unsigned char minute=0, hour=0; 31 32void setup() { 33 // put your setup code here, to run once: 34pinMode(CS, OUTPUT); 35pinMode(mosi, OUTPUT); 36pinMode(clk, OUTPUT); 37pinMode(ampON, OUTPUT); 38pinMode(talk, INPUT_PULLUP); 39pinMode(minutes, INPUT_PULLUP); 40pinMode(hours, INPUT_PULLUP); 41 42lcd.begin(16, 2); // set up the LCD's number of columns and rows: 43 44 //spi init 45SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0) | _BV(SPR1); // Enable spi, Master, set clock rate fck/64 46SPSR = _BV(SPI2X); //set clock rate fck/64 = 250KHz 47 48 //PWM Timer0 49OCR0A = 0; 50TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in phase, fast PWM mode 51TCCR0B = _BV(CS00); // 16MHz/256 = 62.5KHz 52pinMode(audio, OUTPUT); 53 54 //1000 Hz - timer2 55OCR2A =249; 56OCR2B = 125; 57TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM21) | _BV(WGM20); //output B in phase, fast PWM mode 58TCCR2B = _BV(WGM22) | _BV(CS22); // set prescaler to 64 and start the timer 59pinMode(oc2b, OUTPUT); 60 61 //60 sec - timer1 62// OCR1A = 0xEA5F; 63TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A0); // 64TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11) | _BV(CS12); // input T1, PWM mode 65 66digitalWrite(CS, HIGH); 67//digitalWrite(ampON, LOW); 68 69 70 InitSD(); 71 if(sdhc){card = 1;}else{card=512;} //SD or SDHC 72 fat(); 73 if(BytesPerSector!=512){error();} 74 75} 76 77 78void loop() 79{ 80 81 talkPB=digitalRead(talk); 82 if(talkPB==LOW) 83 { 84 //read hours 85 if(hour < 21) {fn=hour; play();} 86 else if(hour == 20) {fn=20; play();} 87 else if(hour > 20) {fn=20; play(); fn=hour-20; play();} 88 fn=24; play(); //read "hours" 89 90 //read minutes 91 if(minute < 21) {fn=minute; play();} 92 else if(minute == 20) {fn=20; play();} 93 else if(minute > 20 && minute < 30) {fn=20; play(); fn=minute-20; play();} 94 else if(minute == 30) {fn=21; play();} 95 else if(minute > 30 && minute < 40) {fn=21; play(); fn=minute-30; play();} 96 else if(minute == 40) {fn=22; play();} 97 else if(minute > 40 && minute < 50) {fn=22; play(); fn=minute-40; play();} 98 else if(minute == 50) {fn=23; play();} 99 else if(minute > 50 && minute < 60) {fn=23; play(); fn=minute-50; play();} 100 fn=25; play(); //read "minutes" 101 fn=26; play(); //read message 102 OCR0A=0; //audio off 103 104 } 105 106 minutesPB=digitalRead(minutes); 107 if(minutesPB==LOW) 108 { 109 minute++; 110 if(minute>59) {minute=0;} 111 display(); 112 wait(); 113 } 114 115 hoursPB=digitalRead(hours); 116 if(hoursPB==LOW) 117 { 118 hour++; 119 if(hour>23) {hour=0;} 120 display(); 121 wait(); 122 } 123 124 if(TIFR1 & _BV(OCF1A)) //1 minute elapsed 125 { 126 OCR1A = 0xEA5F; //59999 counts = 1 minute 127 TIFR1 = _BV(OCF1A); //TMR1 interrupt reset 128 129 minute++; 130 if(minute>59) {minute=0; hour++;} 131 if(hour>23) hour=0; 132 display(); 133 134 } 135} 136 137 //find the file and play it 138 void play(void) 139 { 140 if(!sdhc){fn += 1;} //if not SDHC first file = 1 141 if(fn > 15) 142 { 143 fn -=16; file(fn*32+20,1); //32 bytes per file descriptor at offset of 20 144 } 145 else 146 { 147 file(fn*32+20,0); //32 bytes per file descriptor at offset of 20 148 } 149 loc=(1 + (DataSector) + (unsigned long)(FileCluster-2) * SectorsPerCluster) * card ; 150 ReadSD(); 151 } 152 153 //LCD update 154 void display(void) 155 { 156 lcd.setCursor(5, 0); // top left 157 if(hour<10)lcd.print(" "); 158 lcd.print(hour); 159 lcd.print(":"); 160 if(minute<10)lcd.print("0"); 161 lcd.print(minute); 162 } 163 164 //SD error display 165 void error(void) 166 { 167 lcd.setCursor(0, 1); // bottom left 168 lcd.print("SD ERROR"); 169 lcd.setCursor(0, 0); // top left 170 } 171 172 //1 sec delay 173 void wait(void) 174 { 175 unsigned long i; //,j 176 for(i=0;i<100000;i++) 177 { 178 digitalWrite(ampON, LOW); 179 } 180 } 181 182 void ReadSD(void) 183 { 184 unsigned int i,r; 185 unsigned char read_data; 186 digitalWrite(CS, LOW); 187 r = Command(18,loc,0xFF); //read multi-sector 188 if(r != 0) error(); //if command failed error(); 189 190 while(FileSize--) 191 { 192 while(spi(0xFF) != 0xFE); // wait for first byte 193 for(i=0;i<512;i++){ 194 // 3 rounds of timer 0 = total of time to get 22 khz 195 while (!(TIFR0 & _BV(OCF0A))){} 196 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 197 while (!(TIFR0 & _BV(OCF0A))){} 198 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 199 while (!(TIFR0 & _BV(OCF0A))){} 200 201 OCR0A=spi(0xFF); //write byte to PWM 202 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 203 } 204 spi(0xFF); //discard of CRC 205 spi(0xFF); 206 } 207 208 Command(12,0x00,0xFF); //stop transmit 209 spi(0xFF); 210 spi(0xFF); 211 digitalWrite(CS, HIGH); 212 spi(0xFF); 213 } 214 215void file(unsigned int offset, unsigned char sect) //find files 216{ 217 unsigned int r,i; 218 unsigned char fc[4], fs[4]; // 219 220 digitalWrite(CS, LOW); 221 r = Command(17,(RootDir+sect)*card,0xFF); //read boot-sector for info from file entry 222 if(r != 0) error(); //if command failed 223 224 while(spi(0xFF) != 0xFe); // wait for first byte 225 for(i=0;i<512;i++){ 226 if(i==offset){fc[2]=spi(0xFF);} 227 else if(i==offset+1){fc[3]=spi(0xFF);} 228 else if(i==offset+6){fc[0]=spi(0xFF);} 229 else if(i==offset+7){fc[1]=spi(0xFF);} 230 231 else if(i==offset+8){fs[0]=spi(0xFF);} 232 else if(i==offset+9){fs[1]=spi(0xFF);} 233 else if(i==offset+10){fs[2]=spi(0xFF);} 234 else if(i==offset+11){fs[3]=spi(0xFF);} 235 else{spi(0xFF);} 236 237 } 238 spi(0xFF); //discard of CRC 239 spi(0xFF); 240 digitalWrite(CS, HIGH); 241 spi(0xFF); 242 FileCluster = fc[0] | ( (unsigned long)fc[1] << 8 ) | ( (unsigned long)fc[2] << 16 ) | ( (unsigned long)fc[3] << 24 ); 243 FileSize = fs[0] | ( (unsigned long)fs[1] << 8 ) | ( (unsigned long)fs[2] << 16 ) | ( (unsigned long)fs[3] << 24 ); 244 FileSize = FileSize/512-1; //file size in sectors 245} 246 247void fat (void) 248{ 249 unsigned int r,i; 250 unsigned char pfs[4],bps1,bps2,rs1,rs2,spf[4],rdc[4]; //pfs=partition first sector ,de1,de2,spf1,d[7] 251 252 digitalWrite(CS, LOW); 253 r = Command(17,0,0xFF); //read MBR-sector 254 if(r != 0) error(); //if command failed 255 256 while(spi(0xFF) != 0xFe); // wait for first byte 257 for(i=0;i<512;i++){ 258 if(i==454){pfs[0]=spi(0xFF);} //pfs=partition first sector 259 else if(i==455){pfs[1]=spi(0xFF);} 260 else if(i==456){pfs[2]=spi(0xFF);} 261 else if(i==457){pfs[3]=spi(0xFF);} 262 else{spi(0xFF);} 263 264 } 265 spi(0xFF); //discard of CRC 266 spi(0xFF); 267 digitalWrite(CS, HIGH); 268 spi(0xFF); 269 //convert 4 bytes to long int 270 BootSector = pfs[0] | ( (unsigned long)pfs[1] << 8 ) | ( (unsigned long)pfs[2] << 16 ) | ( (unsigned long)pfs[3] << 24 ); 271 272 digitalWrite(CS, LOW); 273 r = Command(17,BootSector*card,0xFF); //read boot-sector 274 if(r != 0) error(); //if command failed 275 276 while(spi(0xFF) != 0xFe); // wait for first byte 277 for(i=0;i<512;i++){ 278 279 if(i==11){bps1=spi(0xFF);} //bytes per sector 280 else if(i==12){bps2=spi(0xFF);} 281 else if(i==13){SectorsPerCluster=spi(0xFF);} 282 else if(i==14){rs1=spi(0xFF);} 283 else if(i==15){rs2=spi(0xFF);} 284 else if(i==16){Fats=spi(0xFF);} //number of FATs 285 else if(i==36){spf[0]=spi(0xFF);} 286 else if(i==37){spf[1]=spi(0xFF);} 287 else if(i==38){spf[2]=spi(0xFF);} 288 else if(i==39){spf[3]=spi(0xFF);} 289 else if(i==44){rdc[0]=spi(0xFF);} 290 else if(i==45){rdc[1]=spi(0xFF);} 291 else if(i==46){rdc[2]=spi(0xFF);} 292 else if(i==47){rdc[3]=spi(0xFF);} 293 else{spi(0xFF);} 294 295 } 296 spi(0xFF); //discard of CRC 297 spi(0xFF); 298 digitalWrite(CS, HIGH); 299 spi(0xFF); 300 301 BytesPerSector = bps1 | ( (unsigned int)bps2 << 8 ); 302 ReservedSectors = rs1 | ( (unsigned int)rs2 << 8 ); //from partition start to first FAT 303 RootDirCluster = rdc[0] | ( (unsigned long)rdc[1] << 8 ) | ( (unsigned long)rdc[2] << 16 ) | ( (unsigned long)rdc[3] << 24 ); 304 SectorsPerFat = spf[0] | ( (unsigned long)spf[1] << 8 ) | ( (unsigned long)spf[2] << 16 ) | ( (unsigned long)spf[3] << 24 ); 305 DataSector = BootSector + (unsigned long)Fats * (unsigned long)SectorsPerFat + (unsigned long)ReservedSectors; // + 1 306 RootDir = (RootDirCluster -2) * (unsigned long)SectorsPerCluster + DataSector; 307} 308 309unsigned char spi(unsigned char data) // send character over spi 310{ 311 SPDR = data; // Start transmission 312 while(!(SPSR & _BV(SPIF))); // Wait for transmission to complete 313 return SPDR; // received byte 314 315} 316 //assemble a 32 bits command 317char Command(unsigned char frame1, unsigned long adrs, unsigned char frame2 ) 318{ 319 unsigned char i, res; 320 spi(0xFF); 321 spi((frame1 | 0x40) & 0x7F); //first 2 bits are 01 322 spi((adrs & 0xFF000000) >> 24); //first of the 4 bytes address 323 spi((adrs & 0x00FF0000) >> 16); 324 spi((adrs & 0x0000FF00) >> 8); 325 spi(adrs & 0x000000FF); 326 spi(frame2 | 1); //CRC and last bit 1 327 328 for(i=0;i<10;i++) // wait for received character 329 { 330 res = spi(0xFF); 331 if(res != 0xFF)break; 332 } 333 return res; 334} 335 336void InitSD(void) 337{ 338 unsigned char i,r[4]; 339 340 digitalWrite(CS, HIGH); 341 for(i=0; i < 10; i++)spi(0xFF); // min 74 clocks 342 digitalWrite(CS, LOW); // Enabled for spi mode 343 344 i=100; //try idle state for up to 100 times 345 while(Command(0x00,0,0x95) !=1 && i!=0) 346 { 347 digitalWrite(CS, HIGH); 348 spi(0xFF); 349 digitalWrite(CS, LOW); 350 i--; 351 } 352 if(i==0) error(); //idle failed 353 354 if (Command(8,0x01AA,0x87)==1){ //check card is 3.3V 355 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of R7 356 if ( r[2] == 0x01 && r[3] == 0xAA ){ //Vdd OK (3.3V) 357 358 //Command(59,0,0xFF); //CRC off 359 Command(55,0,0xFF); 360 while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);} //ACMD41 with HCS bit 361 } 362 }else{error();} 363 364 if (Command(58,0,0xFF)==0){ //read CCS in the OCR - SD or SDHC 365 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of R3 366 sdhc=r[0] & 0x40; 367 //if(r[0] & 0x40)sdLED=1; 368 } 369 SPCR &= ~(_BV(SPR1)); // set clock rate fck/8 = 2MHz 370 digitalWrite(CS, HIGH); 371} 372 373
Talking Clock
c_cpp
1/* 2 * sd_bell.ino 3 * 4 * Created: 5/06/2017 23:34:47 5 * Author: 6 moty22.co.uk 7 */ 8 9#include <LiquidCrystal.h> 10 11 // initialize 12 the library with the numbers of the interface pins 13LiquidCrystal lcd(7, 8, A0, 14 A1, A2, A3); 15 16const int CS = 10; // SD CS connected to digital pin 17 PD4 18const int mosi = 11; 19const int clk = 13; 20const int ampON = 9; // 21 led connected to digital pin PB0 22const int audio = 6; //output D6 23const 24 int oc2b = 3; //1000Hz 25const int t1 = 5; //1000Hz 26const int talk = 27 2; //talk pushbutton 28const int minutes = A4; //minutes advance pushbutton 29const 30 int hours = A5; //hours pushbutton 31int talkPB=1; // talk pushbutton 32 status 33int minutesPB=1; // minutes pushbutton status 34int hoursPB=1; 35 // hours pushbutton status 36 37unsigned long loc,BootSector, RootDir, 38 SectorsPerFat, RootDirCluster, DataSector, FileCluster, FileSize; // 39unsigned 40 int BytesPerSector, ReservedSectors, card; 41unsigned char fn=1, sdhc=0, SectorsPerCluster, 42 Fats; 43unsigned char minute=0, hour=0; 44 45void setup() { 46 // put your 47 setup code here, to run once: 48pinMode(CS, OUTPUT); 49pinMode(mosi, OUTPUT); 50pinMode(clk, 51 OUTPUT); 52pinMode(ampON, OUTPUT); 53pinMode(talk, INPUT_PULLUP); 54pinMode(minutes, 55 INPUT_PULLUP); 56pinMode(hours, INPUT_PULLUP); 57 58lcd.begin(16, 2); // set 59 up the LCD's number of columns and rows: 60 61 //spi init 62SPCR = _BV(SPE) 63 | _BV(MSTR) | _BV(SPR0) | _BV(SPR1); // Enable spi, Master, set clock rate fck/64 64SPSR 65 = _BV(SPI2X); //set clock rate fck/64 = 250KHz 66 67 //PWM Timer0 68OCR0A 69 = 0; 70TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in phase, fast 71 PWM mode 72TCCR0B = _BV(CS00); // 16MHz/256 = 62.5KHz 73pinMode(audio, OUTPUT); 74 75 76 //1000 Hz - timer2 77OCR2A =249; 78OCR2B = 125; 79TCCR2A = _BV(COM2B1) | 80 _BV(COM2B0) | _BV(WGM21) | _BV(WGM20); //output B in phase, fast PWM mode 81TCCR2B 82 = _BV(WGM22) | _BV(CS22); // set prescaler to 64 and start the timer 83pinMode(oc2b, 84 OUTPUT); 85 86 //60 sec - timer1 87// OCR1A = 0xEA5F; 88TCCR1A = _BV(WGM10) 89 | _BV(WGM11) | _BV(COM1A0); // 90TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11) 91 | _BV(CS12); // input T1, PWM mode 92 93digitalWrite(CS, HIGH); 94//digitalWrite(ampON, 95 LOW); 96 97 98 InitSD(); 99 if(sdhc){card = 1;}else{card=512;} //SD or SDHC 100 101 fat(); 102 if(BytesPerSector!=512){error();} 103 104} 105 106 107void loop() 108{ 109 110 111 talkPB=digitalRead(talk); 112 if(talkPB==LOW) 113 { 114 //read 115 hours 116 if(hour < 21) {fn=hour; play();} 117 else if(hour == 20) 118 {fn=20; play();} 119 else if(hour > 20) {fn=20; play(); fn=hour-20; play();} 120 121 fn=24; play(); //read "hours" 122 123 //read minutes 124 125 if(minute < 21) {fn=minute; play();} 126 else if(minute == 20) {fn=20; 127 play();} 128 else if(minute > 20 && minute < 30) {fn=20; play(); fn=minute-20; 129 play();} 130 else if(minute == 30) {fn=21; play();} 131 else if(minute 132 > 30 && minute < 40) {fn=21; play(); fn=minute-30; play();} 133 else if(minute 134 == 40) {fn=22; play();} 135 else if(minute > 40 && minute < 50) {fn=22; play(); 136 fn=minute-40; play();} 137 else if(minute == 50) {fn=23; play();} 138 else 139 if(minute > 50 && minute < 60) {fn=23; play(); fn=minute-50; play();} 140 fn=25; 141 play(); //read "minutes" 142 fn=26; play(); //read message 143 OCR0A=0; 144 //audio off 145 146 } 147 148 minutesPB=digitalRead(minutes); 149 150 if(minutesPB==LOW) 151 { 152 minute++; 153 if(minute>59) {minute=0;} 154 155 display(); 156 wait(); 157 } 158 159 hoursPB=digitalRead(hours); 160 161 if(hoursPB==LOW) 162 { 163 hour++; 164 if(hour>23) {hour=0;} 165 166 display(); 167 wait(); 168 } 169 170 if(TIFR1 & _BV(OCF1A)) //1 171 minute elapsed 172 { 173 OCR1A = 0xEA5F; //59999 counts = 1 minute 174 175 TIFR1 = _BV(OCF1A); //TMR1 interrupt reset 176 177 minute++; 178 if(minute>59) 179 {minute=0; hour++;} 180 if(hour>23) hour=0; 181 display(); 182 183 } 184} 185 186 187 //find the file and play it 188 void play(void) 189 { 190 if(!sdhc){fn += 191 1;} //if not SDHC first file = 1 192 if(fn > 15) 193 { 194 fn -=16; 195 file(fn*32+20,1); //32 bytes per file descriptor at offset of 20 196 } 197 198 else 199 { 200 file(fn*32+20,0); //32 bytes per file descriptor at 201 offset of 20 202 } 203 loc=(1 + (DataSector) + (unsigned long)(FileCluster-2) 204 * SectorsPerCluster) * card ; 205 ReadSD(); 206 } 207 208 //LCD update 209 210 void display(void) 211 { 212 lcd.setCursor(5, 0); // top left 213 if(hour<10)lcd.print(" 214 "); 215 lcd.print(hour); 216 lcd.print(":"); 217 if(minute<10)lcd.print("0"); 218 219 lcd.print(minute); 220 } 221 222 //SD error display 223 void error(void) 224 225 { 226 lcd.setCursor(0, 1); // bottom left 227 lcd.print("SD ERROR"); 228 229 lcd.setCursor(0, 0); // top left 230 } 231 232 //1 sec delay 233 void 234 wait(void) 235 { 236 unsigned long i; //,j 237 for(i=0;i<100000;i++) 238 239 { 240 digitalWrite(ampON, LOW); 241 } 242 } 243 244 void ReadSD(void) 245 246 { 247 unsigned int i,r; 248 unsigned char read_data; 249 digitalWrite(CS, 250 LOW); 251 r = Command(18,loc,0xFF); //read multi-sector 252 if(r != 0) error(); 253 //if command failed error(); 254 255 while(FileSize--) 256 { 257 258 while(spi(0xFF) != 0xFE); // wait for first byte 259 for(i=0;i<512;i++){ 260 261 // 3 rounds of timer 0 = total of time to get 22 khz 262 while 263 (!(TIFR0 & _BV(OCF0A))){} 264 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 265 266 while (!(TIFR0 & _BV(OCF0A))){} 267 TIFR0 = _BV(OCF0A); //TMR0 268 interrupt reset 269 while (!(TIFR0 & _BV(OCF0A))){} 270 271 OCR0A=spi(0xFF); 272 //write byte to PWM 273 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 274 275 } 276 spi(0xFF); //discard of CRC 277 spi(0xFF); 278 } 279 280 281 Command(12,0x00,0xFF); //stop transmit 282 spi(0xFF); 283 spi(0xFF); 284 285 digitalWrite(CS, HIGH); 286 spi(0xFF); 287 } 288 289void file(unsigned int 290 offset, unsigned char sect) //find files 291{ 292 unsigned int r,i; 293 unsigned 294 char fc[4], fs[4]; // 295 296 digitalWrite(CS, LOW); 297 r = Command(17,(RootDir+sect)*card,0xFF); 298 //read boot-sector for info from file entry 299 if(r != 0) error(); //if 300 command failed 301 302 while(spi(0xFF) != 0xFe); // wait for first byte 303 for(i=0;i<512;i++){ 304 305 if(i==offset){fc[2]=spi(0xFF);} 306 else if(i==offset+1){fc[3]=spi(0xFF);} 307 308 else if(i==offset+6){fc[0]=spi(0xFF);} 309 else if(i==offset+7){fc[1]=spi(0xFF);} 310 311 312 else if(i==offset+8){fs[0]=spi(0xFF);} 313 else if(i==offset+9){fs[1]=spi(0xFF);} 314 315 else if(i==offset+10){fs[2]=spi(0xFF);} 316 else if(i==offset+11){fs[3]=spi(0xFF);} 317 318 else{spi(0xFF);} 319 320 } 321 spi(0xFF); //discard of CRC 322 spi(0xFF); 323 324 digitalWrite(CS, HIGH); 325 spi(0xFF); 326 FileCluster = fc[0] | ( (unsigned 327 long)fc[1] << 8 ) | ( (unsigned long)fc[2] << 16 ) | ( (unsigned long)fc[3] << 24 328 ); 329 FileSize = fs[0] | ( (unsigned long)fs[1] << 8 ) | ( (unsigned long)fs[2] 330 << 16 ) | ( (unsigned long)fs[3] << 24 ); 331 FileSize = FileSize/512-1; //file 332 size in sectors 333} 334 335void fat (void) 336{ 337 unsigned int r,i; 338 unsigned 339 char pfs[4],bps1,bps2,rs1,rs2,spf[4],rdc[4]; //pfs=partition first sector ,de1,de2,spf1,d[7] 340 341 342 digitalWrite(CS, LOW); 343 r = Command(17,0,0xFF); //read MBR-sector 344 345 if(r != 0) error(); //if command failed 346 347 while(spi(0xFF) != 0xFe); 348 // wait for first byte 349 for(i=0;i<512;i++){ 350 if(i==454){pfs[0]=spi(0xFF);} 351 //pfs=partition first sector 352 else if(i==455){pfs[1]=spi(0xFF);} 353 else 354 if(i==456){pfs[2]=spi(0xFF);} 355 else if(i==457){pfs[3]=spi(0xFF);} 356 else{spi(0xFF);} 357 358 359 } 360 spi(0xFF); //discard of CRC 361 spi(0xFF); 362 digitalWrite(CS, 363 HIGH); 364 spi(0xFF); 365 //convert 4 bytes to long int 366 BootSector = pfs[0] 367 | ( (unsigned long)pfs[1] << 8 ) | ( (unsigned long)pfs[2] << 16 ) | ( (unsigned 368 long)pfs[3] << 24 ); 369 370 digitalWrite(CS, LOW); 371 r = Command(17,BootSector*card,0xFF); 372 //read boot-sector 373 if(r != 0) error(); //if command failed 374 375 376 while(spi(0xFF) != 0xFe); // wait for first byte 377 for(i=0;i<512;i++){ 378 379 380 if(i==11){bps1=spi(0xFF);} //bytes per sector 381 else if(i==12){bps2=spi(0xFF);} 382 383 else if(i==13){SectorsPerCluster=spi(0xFF);} 384 else if(i==14){rs1=spi(0xFF);} 385 386 else if(i==15){rs2=spi(0xFF);} 387 else if(i==16){Fats=spi(0xFF);} //number 388 of FATs 389 else if(i==36){spf[0]=spi(0xFF);} 390 else if(i==37){spf[1]=spi(0xFF);} 391 392 else if(i==38){spf[2]=spi(0xFF);} 393 else if(i==39){spf[3]=spi(0xFF);} 394 395 else if(i==44){rdc[0]=spi(0xFF);} 396 else if(i==45){rdc[1]=spi(0xFF);} 397 398 else if(i==46){rdc[2]=spi(0xFF);} 399 else if(i==47){rdc[3]=spi(0xFF);} 400 401 else{spi(0xFF);} 402 403 } 404 spi(0xFF); //discard of CRC 405 spi(0xFF); 406 407 digitalWrite(CS, HIGH); 408 spi(0xFF); 409 410 BytesPerSector = bps1 | 411 ( (unsigned int)bps2 << 8 ); 412 ReservedSectors = rs1 | ( (unsigned int)rs2 << 413 8 ); //from partition start to first FAT 414 RootDirCluster = rdc[0] | ( (unsigned 415 long)rdc[1] << 8 ) | ( (unsigned long)rdc[2] << 16 ) | ( (unsigned long)rdc[3] << 416 24 ); 417 SectorsPerFat = spf[0] | ( (unsigned long)spf[1] << 8 ) | ( (unsigned 418 long)spf[2] << 16 ) | ( (unsigned long)spf[3] << 24 ); 419 DataSector = BootSector 420 + (unsigned long)Fats * (unsigned long)SectorsPerFat + (unsigned long)ReservedSectors; 421 // + 1 422 RootDir = (RootDirCluster -2) * (unsigned long)SectorsPerCluster 423 + DataSector; 424} 425 426unsigned char spi(unsigned char data) // send character 427 over spi 428{ 429 SPDR = data; // Start transmission 430 while(!(SPSR & _BV(SPIF))); 431 // Wait for transmission to complete 432 return SPDR; // received byte 433 434} 435 436 //assemble a 32 bits command 437char Command(unsigned char frame1, unsigned 438 long adrs, unsigned char frame2 ) 439{ 440 unsigned char i, res; 441 spi(0xFF); 442 443 spi((frame1 | 0x40) & 0x7F); //first 2 bits are 01 444 spi((adrs & 0xFF000000) 445 >> 24); //first of the 4 bytes address 446 spi((adrs & 0x00FF0000) >> 16); 447 448 spi((adrs & 0x0000FF00) >> 8); 449 spi(adrs & 0x000000FF); 450 spi(frame2 | 451 1); //CRC and last bit 1 452 453 for(i=0;i<10;i++) // wait for received 454 character 455 { 456 res = spi(0xFF); 457 if(res != 0xFF)break; 458 } 459 460 return res; 461} 462 463void InitSD(void) 464{ 465 unsigned char i,r[4]; 466 467 468 digitalWrite(CS, HIGH); 469 for(i=0; i < 10; i++)spi(0xFF); // min 74 470 clocks 471 digitalWrite(CS, LOW); // Enabled for spi mode 472 473 i=100; 474 //try idle state for up to 100 times 475 while(Command(0x00,0,0x95) !=1 && i!=0) 476 477 { 478 digitalWrite(CS, HIGH); 479 spi(0xFF); 480 digitalWrite(CS, LOW); 481 482 i--; 483 } 484 if(i==0) error(); //idle failed 485 486 if (Command(8,0x01AA,0x87)==1){ 487 //check card is 3.3V 488 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); 489 r[3]=spi(0xFF); //rest of R7 490 if ( r[2] == 0x01 && r[3] == 0xAA ){ //Vdd 491 OK (3.3V) 492 493 //Command(59,0,0xFF); //CRC off 494 Command(55,0,0xFF); 495 496 while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);} //ACMD41 with HCS 497 bit 498 } 499 }else{error();} 500 501 if (Command(58,0,0xFF)==0){ //read 502 CCS in the OCR - SD or SDHC 503 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); 504 r[3]=spi(0xFF); //rest of R3 505 sdhc=r[0] & 0x40; 506 //if(r[0] & 0x40)sdLED=1; 507 508 } 509 SPCR &= ~(_BV(SPR1)); // set clock rate fck/8 = 2MHz 510 digitalWrite(CS, 511 HIGH); 512} 513 514
Downloadable files
arduino clock2
arduino clock2
Comments
Only logged in users can leave comments
moty
0 Followers
•0 Projects
0