The Smart Card Detective (SCD)
scd_io.c
Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines