The Smart Card Detective (SCD)
|
00001 00034 00035 #define F_CPU 16000000UL 00036 00037 // this is needed for the delay on the new avr-libc-1.7.0 00038 #ifndef __DELAY_BACKWARD_COMPATIBLE__ 00039 #define __DELAY_BACKWARD_COMPATIBLE__ 00040 #endif 00041 00042 #include <avr/io.h> 00043 #include <string.h> 00044 #include <util/delay.h> 00045 #include <avr/interrupt.h> 00046 #include <stdlib.h> 00047 #include <avr/eeprom.h> 00048 00049 #include "scd_io.h" 00050 00051 // static vars 00052 static uint8_t lcd_count; // used by LCD functions 00053 static uint8_t lcd_state; // 0 if LcdOff, non-zero otherwise 00054 00055 00056 //--------------------------------------------------------------- 00057 00058 /* Led functions */ 00059 00060 void Led1On() 00061 { 00062 DDRE |= _BV(PE7); 00063 PORTE |= _BV(PE7); 00064 } 00065 00066 void Led2On() 00067 { 00068 DDRE |= _BV(PE6); 00069 PORTE |= _BV(PE6); 00070 } 00071 00072 void Led3On() 00073 { 00074 DDRE |= _BV(PE5); 00075 PORTE |= _BV(PE5); 00076 } 00077 00078 void Led4On() 00079 { 00080 DDRE |= _BV(PE4); 00081 PORTE |= _BV(PE4); 00082 } 00083 00084 void Led1Off() 00085 { 00086 //DDRE |= _BV(PE7); 00087 //PORTE &= ~(_BV(PE7)); 00088 00089 DDRE &= ~(_BV(PE7)); 00090 PORTE &= ~(_BV(PE7)); 00091 } 00092 00093 void Led2Off() 00094 { 00095 //DDRE |= _BV(PE6); 00096 //PORTE &= ~(_BV(PE6)); 00097 00098 DDRE &= ~(_BV(PE6)); 00099 PORTE &= ~(_BV(PE6)); 00100 } 00101 00102 void Led3Off() 00103 { 00104 //DDRE |= _BV(PE5); 00105 //PORTE &= ~(_BV(PE5)); 00106 00107 DDRE &= ~(_BV(PE5)); 00108 PORTE &= ~(_BV(PE5)); 00109 } 00110 00111 void Led4Off() 00112 { 00113 //DDRE |= _BV(PE4); 00114 //PORTE &= ~(_BV(PE4)); 00115 00116 DDRE &= ~(_BV(PE4)); 00117 PORTE &= ~(_BV(PE4)); 00118 } 00119 00120 // Ohter signals 00121 00122 void T_C4On() 00123 { 00124 DDRB |= _BV(PB4); 00125 PORTB |= _BV(PB4); 00126 } 00127 00128 void T_C8On() 00129 { 00130 DDRB |= _BV(PB5); 00131 PORTB |= _BV(PB5); 00132 } 00133 00134 void T_C4Off() 00135 { 00136 DDRB &= ~(_BV(PB4)); 00137 PORTB &= ~(_BV(PB4)); 00138 } 00139 00140 void T_C8Off() 00141 { 00142 DDRB &= ~(_BV(PB5)); 00143 PORTB &= ~(_BV(PB5)); 00144 } 00145 00146 void JTAG_P1_High() 00147 { 00148 DDRF |= _BV(PF4); 00149 PORTF |= _BV(PF4); 00150 } 00151 00152 void JTAG_P1_Low() 00153 { 00154 DDRF |= _BV(PF4); 00155 PORTF &= ~(_BV(PF4)); 00156 } 00157 00158 void JTAG_P3_High() 00159 { 00160 DDRF |= _BV(PF6); 00161 PORTF |= _BV(PF6); 00162 } 00163 00164 void JTAG_P3_Low() 00165 { 00166 DDRF |= _BV(PF6); 00167 PORTF &= ~(_BV(PF6)); 00168 } 00169 00170 //--------------------------------------------------------------- 00171 00172 /* Button functions */ 00173 00179 uint8_t GetButtonA() 00180 { 00181 DDRF &= ~(_BV(PF3)); 00182 return bit_is_set(PINF, PF3); 00183 } 00184 00190 uint8_t GetButtonB() 00191 { 00192 DDRF &= ~(_BV(PF2)); 00193 return bit_is_set(PINF, PF2); 00194 } 00195 00196 00202 uint8_t GetButtonC() 00203 { 00204 DDRF &= ~(_BV(PF1)); 00205 return bit_is_set(PINF, PF1); 00206 } 00207 00208 00214 uint8_t GetButtonD() 00215 { 00216 DDRF &= ~(_BV(PF0)); 00217 return bit_is_set(PINF, PF0); 00218 } 00219 00230 uint8_t GetButton() 00231 { 00232 uint8_t result = 0; 00233 00234 if(bit_is_clear(PINF, PF3)) result |= BUTTON_A; 00235 if(bit_is_clear(PINF, PF2)) result |= BUTTON_B; 00236 if(bit_is_clear(PINF, PF1)) result |= BUTTON_C; 00237 if(bit_is_clear(PINF, PF0)) result |= BUTTON_D; 00238 00239 return result; 00240 } 00241 00242 00243 //--------------------------------------------------------------- 00244 00245 /* LCD functions */ 00246 00247 // RS = PC0 00248 // R/W = PC1 00249 // E = PC2 00250 // D0-D7 = PA0-7 00251 00252 // Returns a byte = BF | AC6 ... AC0 containing the busy flag and address counter 00253 uint8_t GetLCDStatus() 00254 { 00255 uint8_t status; 00256 00257 PORTC &= 0xF8; 00258 DDRC |= 0x07; 00259 DDRA = 0; 00260 PORTC |= _BV(PC1); 00261 PORTC |= _BV(PC2); 00262 _delay_us(10); 00263 status = PINA; 00264 PORTC &= ~(_BV(PC2)); 00265 DDRC &= 0xF8; 00266 00267 return status; 00268 } 00269 00273 uint8_t GetLCDState() 00274 { 00275 return lcd_state; 00276 } 00277 00278 /* 00279 * Set the state of the LCD 00280 * Useful when resetting the device 00281 */ 00282 void SetLCDState(uint8_t state) 00283 { 00284 lcd_state = state; 00285 } 00286 00287 // Sends a command with a given delay (if needed) and returns 00288 // the value of the D0-D7 pins 00289 uint8_t SendLCDCommand(uint8_t RS, uint8_t RW, uint8_t data, uint16_t delay_us) 00290 { 00291 uint8_t result, busy; 00292 00293 do{ 00294 result = GetLCDStatus(); 00295 busy = result & 0x80; 00296 }while(busy); 00297 00298 DDRC |= 0x07; 00299 if(RS) PORTC |= _BV(PC0); 00300 else PORTC &= ~(_BV(PC0)); 00301 00302 if(RW) 00303 { 00304 PORTC |= _BV(PC1); 00305 DDRA = 0x00; 00306 } 00307 else 00308 { 00309 PORTC &= ~(_BV(PC1)); 00310 DDRA = 0xFF; 00311 PORTA = data; 00312 } 00313 00314 PORTC |= _BV(PC2); 00315 _delay_us(delay_us); 00316 data = PINA; 00317 PORTC &= ~(_BV(PC2)); 00318 DDRC &= 0xF8; 00319 00320 return data; 00321 } 00322 00323 void FillScreen() 00324 { 00325 uint8_t i; 00326 char *str = "12"; 00327 00328 // clear display 00329 SendLCDCommand(0, 0, 0x01, LCD_COMMAND_DELAY); 00330 00331 // send data for first line 00332 for(i = 0; i < 40; i++) 00333 SendLCDCommand(1, 0, str[0], LCD_COMMAND_DELAY); 00334 00335 // change address to second line 00336 SendLCDCommand(0, 0, 0xc0, 37); 00337 00338 for(i = 0; i < 40; i++) 00339 SendLCDCommand(1, 0, str[1], LCD_COMMAND_DELAY); 00340 } 00341 00348 void WriteStringLCD(char *string, uint8_t len) 00349 { 00350 uint8_t i; 00351 00352 // clear display 00353 SendLCDCommand(0, 0, 0x01, LCD_COMMAND_DELAY); 00354 00355 i = 0; 00356 while(i < len && i < 8) 00357 { 00358 // write byte to DDRAM 00359 SendLCDCommand(1, 0, string[i], LCD_COMMAND_DELAY); 00360 i++; 00361 } 00362 00363 if(len > 8) 00364 { 00365 // change address to second line 00366 SendLCDCommand(0, 0, 0xc0, LCD_COMMAND_DELAY); 00367 00368 while(i < len && i < 16) 00369 { 00370 // write byte to DDRAM 00371 SendLCDCommand(1, 0, string[i], LCD_COMMAND_DELAY); 00372 i++; 00373 } 00374 } 00375 00376 lcd_count = 0; 00377 } 00378 00379 /* 00380 * Send character c to the LCD display. After 8 characters, next 00381 * character is displayed on second line. After a new line ('\n') 00382 * the next char clears the display. 00383 * 00384 * This function is meant to be used with printf/fprintf commands, 00385 * by sending this function as parameter to FDEV_SETUP_STREAM. 00386 * 00387 * @param c character to be sent to LCD 00388 * @param unused unused parameter FILE 00389 * @return 0 if successful, non-zero otherwise 00390 */ 00391 int LcdPutchar(char c, FILE *unused) 00392 { 00393 static uint8_t nl_seen; 00394 00395 if (nl_seen && c != '\n') 00396 { 00397 //First character after newline, clear display and home cursor. 00398 SendLCDCommand(0, 0, 0x01, LCD_COMMAND_DELAY); 00399 nl_seen = 0; 00400 lcd_count = 0; 00401 } 00402 00403 if(c == '\n') 00404 { 00405 nl_seen = 1; 00406 } 00407 else 00408 { 00409 // write character 00410 SendLCDCommand(1, 0, c, LCD_COMMAND_DELAY); 00411 } 00412 00413 lcd_count++; 00414 if(lcd_count == 8) 00415 SendLCDCommand(0, 0, 0xc0, LCD_COMMAND_DELAY); // go to 2nd line 00416 else if(lcd_count == 16) 00417 SendLCDCommand(0, 0, 0x02, LCD_COMMAND_DELAY); // return home 00418 00419 return 0; 00420 } 00421 00422 00427 void InitLCD() 00428 { 00429 // power to V0 (contrast variable resistor output) 00430 DDRC |= _BV(PC5); 00431 PORTC |= _BV(PC5); 00432 00433 // send function set command - 1 line, 8 bits data 00434 //SendLCDCommand(0, 0, 0x30, LCD_COMMAND_DELAY); 00435 00436 // send function set command - 2 lines, 8 bits data 00437 SendLCDCommand(0, 0, 0x38, LCD_COMMAND_DELAY); 00438 00439 // display on, cursor enabled, no blinking 00440 SendLCDCommand(0, 0, 0x0E, LCD_COMMAND_DELAY); 00441 00442 // sets cursor move dir 00443 SendLCDCommand(0, 0, 0x06, LCD_COMMAND_DELAY); 00444 00445 // clear display 00446 SendLCDCommand(0, 0, 0x01, LCD_COMMAND_DELAY); 00447 00448 lcd_state = 1; 00449 00450 // The following shift commands are only needed if a 00451 // display messes with position 00452 00453 // shift to left 00454 //SendLCDCommand(0, 0, 0x18, LCD_COMMAND_DELAY); 00455 00456 // shift to right 00457 //SendLCDCommand(0, 0, 0x1C, LCD_COMMAND_DELAY); 00458 } 00459 00465 uint8_t CheckLCD() 00466 { 00467 // RS = PC0 00468 // R/W = PC1 00469 // E = PC2 00470 // D0-D7 = PA0-7 00471 uint8_t tmp; 00472 00473 // put a random value (i.e. 0xAA) on PORTA. If LCD works, on GetSTATUS 00474 // we should get something different 00475 DDRA = 0xFF; 00476 PORTA = 0xAA; 00477 tmp = GetLCDStatus(); 00478 00479 if(tmp == 0xAA) return 1; 00480 00481 return 0; 00482 } 00483 00487 void LCDOff() 00488 { 00489 SendLCDCommand(0, 0, 0x08, LCD_COMMAND_DELAY); 00490 DDRC &= ~(_BV(PC5)); 00491 PORTC &= ~(_BV(PC5)); 00492 lcd_state = 0; 00493 } 00494 00498 void LCDOn() 00499 { 00500 DDRC |= _BV(PC5); 00501 PORTC |= _BV(PC5); 00502 SendLCDCommand(0, 0, 0x0E, LCD_COMMAND_DELAY); 00503 lcd_state = 1; 00504 } 00505 00506 00507 //--------------------------------------------------------------- 00508 00509 /* EEPROM stuff */ 00510 00523 void WriteSingleByteEEPROM(uint16_t addr, uint8_t data) 00524 { 00525 // wait completion of previous write 00526 while(EECR & _BV(EEPE)); 00527 00528 // set up address and data 00529 EEAR = addr; 00530 EEDR = data; 00531 00532 // make the write 00533 EECR |= _BV(EEMPE); 00534 EECR |= _BV(EEPE); 00535 } 00536 00549 uint8_t ReadSingleByteEEPROM(uint16_t addr) 00550 { 00551 // wait for completion of previous write 00552 while(EECR & _BV(EEPE)); 00553 00554 // set up address and start reading 00555 EEAR = addr; 00556 EECR |= _BV(EERE); 00557 00558 return EEDR; 00559 } 00560 00561 00571 void WriteBytesEEPROM(uint16_t addr, uint8_t *data, uint16_t len) 00572 { 00573 uint8_t i, sreg; 00574 00575 if(data == NULL || len > 4000) return; 00576 00577 sreg = SREG; 00578 cli(); 00579 00580 for(i = 0; i < len; i++) 00581 WriteSingleByteEEPROM(addr++, data[i]); 00582 00583 // wait completion of last write 00584 while(EECR & _BV(EEPE)); 00585 00586 SREG = sreg; 00587 } 00588 00601 uint8_t* ReadBytesEEPROM(uint16_t addr, uint16_t len) 00602 { 00603 uint8_t i, sreg; 00604 uint8_t *data; 00605 00606 if(len > 4000) return NULL; 00607 data = (uint8_t*)malloc(len*sizeof(uint8_t)); 00608 if(data == NULL) return NULL; 00609 00610 sreg = SREG; 00611 cli(); 00612 00613 for(i = 0; i < len; i++) 00614 data[i] = ReadSingleByteEEPROM(addr++); 00615 00616 SREG = sreg; 00617 00618 return data; 00619 } 00620 00621 00629 void InitUSART(uint16_t baudUBRR) 00630 { 00631 uint8_t sreg = SREG; 00632 cli(); 00633 00634 // Set baud 00635 UBRR1H = (uint8_t) (baudUBRR >> 8); 00636 UBRR1L = (uint8_t) (baudUBRR & 0xFF); 00637 00638 // Enable receiver and transmitter 00639 UCSR1B = (1 << RXEN1) || (1 << TXEN1); 00640 00641 // Set frame format: 8 data, 1 stop bit 00642 UCSR1C = (3 << UCSZ10); 00643 SREG = sreg; 00644 } 00645 00646 void DisableUSART() 00647 { 00648 uint8_t sreg = SREG; 00649 cli(); 00650 UCSR1B = 0; 00651 SREG = sreg; 00652 } 00653 00659 void SendCharUSART(char data) 00660 { 00661 // Wait for empty buffer 00662 while(!(UCSR1A & (1 << UDRE1))); 00663 00664 // Put and send the data 00665 UDR1 = data; 00666 } 00667 00668 00672 char GetCharUSART(void) 00673 { 00674 // wait for data to be received 00675 while(!(UCSR1A & (1 << RXC1))); 00676 00677 // return the character 00678 return UDR1; 00679 } 00680 00684 void FlushUSART(void) 00685 { 00686 char dummy; 00687 while(UCSR1A & (1 << RXC1)) dummy = UDR1; 00688 } 00689 00697 char* GetLineUSART() 00698 { 00699 char buf[256]; 00700 uint8_t i = 0; 00701 00702 memset(buf, 0, 256); 00703 00704 while(i < 256) 00705 { 00706 fprintf(stderr, "Getting char\n"); 00707 _delay_ms(200); 00708 buf[i] = GetCharUSART(); 00709 fprintf(stderr, "Char: %c\n", buf[i]); 00710 _delay_ms(200); 00711 00712 if(i == 0 && (buf[i] == '\n' || buf[i] == '\r')) 00713 continue; 00714 else if(buf[i] == '\n') 00715 { 00716 buf[i] = 0; 00717 if(buf[i - 1] == '\r') 00718 buf[i - 1] = 0; 00719 return strdup(buf); 00720 } 00721 00722 i = i + 1; 00723 } 00724 00725 return NULL; 00726 } 00727 00733 void SendLineUSART(const char *data) 00734 { 00735 if(data == NULL) return; 00736 00737 while(data && *data) 00738 SendCharUSART(*data++); 00739 } 00740