Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

main.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00060 #include <inavr.h>
00061 
00062 #include <iotiny24.h>   // standard IAR header file with 4.11A and later
00063 #include "main.h"
00064 #include "USI_TWI_Master.h"
00065 #include "LCD.h"
00066 #include "KPD.h"
00067 
00068 __flash unsigned char STRING_WELCOME[] = {"Tiny24 CODE LOCK"};
00069 __flash unsigned char STRING_OPEN[] = {"   LOCK  OPEN   "};
00070 __flash unsigned char STRING_CLOSE[] = {"  LOCK  CLOSED  "};
00071 
00072 __eeprom unsigned char CODE_ACCESS[CODE_ACCESS_LENGTH+1] = {"1234 "};
00073 
00074 unsigned char KeyBuffer[CODE_MAX_LENGTH];
00075 
00076 // Main program
00077 void main(void)
00078 {
00079   unsigned char i;
00080 
00081   Initialise();
00082 
00083   Beep(625);                        // 800 Hz tone at 1 MHz clock
00084   Delay(100);
00085   LCD_ClearDisplay();
00086   ClearInputBuffer();
00087   Beep(0);
00088 
00089   do                                  // main loop
00090   {
00091     for (i=0;i<16;i++)
00092       LCD_PutXY(STRING_WELCOME[i],i,0); // uses less SRAM than LCD_WriteLine
00093 
00094     while (!KPD_KeyPressed);
00095     asm("wdr");                       // we have input; reset watchdog
00096 
00097     for (i=CODE_MAX_LENGTH;i>0;i--)
00098       KeyBuffer[i] = KeyBuffer[i-1];  // scroll input buffer
00099     KeyBuffer[0] = KPD_GetKey();
00100     Beep(625);                        // 800 Hz tone at 1 MHz clock
00101     Delay(100);
00102     Beep(0);
00103 
00104     for (i=0;i<CODE_MAX_LENGTH;i++)
00105       LCD_PutXY(KeyBuffer[i],11-i,1);
00106 
00107     CheckAccess();
00108   }
00109   while(1);
00110 }
00111 
00112 // Master init
00113 void Initialise(void)
00114 {
00115   USI_TWI_Master_Initialise();        // initialise TWI
00116   LCD_Init();                         // initialise LCD
00117   KPD_Init();                         // initialise keypad
00118 
00119   DDRA |= (1 << LOCK_PIN);            // set pin as output (lock control)
00120   PORTA &= ~(1 << LOCK_PIN);          // set pin low (close lock)
00121 
00122   DDRA |= (1 << PINA5);               // set pin A5 as output (buzzer)
00123 
00124   asm("wdr");
00125   MCUSR = 0;                          // clear all reset flags
00126   WDTCSR = (1<<WDIE) | (1<<WDE) | (1<<WDP3);  // enable WD, timeout in 4.0 s
00127 }
00128 
00129 void ClearInputBuffer(void)
00130 {
00131   unsigned char i;
00132 
00133   for (i=0;i<CODE_MAX_LENGTH;i++)
00134     KeyBuffer[i] = 0;
00135 }
00136 
00137 void CheckAccess(void)
00138 {
00139   unsigned char i;
00140 
00141   for (i=0;i<CODE_ACCESS_LENGTH;i++)
00142     if (CODE_ACCESS[CODE_ACCESS_LENGTH-i-1] != KeyBuffer[i])
00143       return;
00144 
00145   // Still here? It was a match, then. Sesame, open.
00146   OpenLock();
00147   for (i=0;i<16;i++)
00148     LCD_PutXY(STRING_CLOSE[i],i,0);   // uses less SRAM than LCD_WriteLine
00149   Delay(1000);
00150   KPD_Init();                         // initialise keypad: clear pending keys
00151 }
00152 
00153 // Activate signal, which opens the lock.
00154 void OpenLock(void)
00155 {
00156   unsigned char i;
00157 
00158   for (i=0;i<16;i++)
00159     LCD_PutXY(STRING_OPEN[i],i,0);    // uses less SRAM than LCD_WriteLine
00160 
00161   Beep(1250);                       // 400 Hz tone at 1 MHz clock
00162 
00163   PORTA |= (1 << LOCK_PIN);           // set pin high (open lock)
00164   DelayBar(3);
00165   PORTA &= ~(1 << LOCK_PIN);          // set pin low (close lock)
00166 
00167   Beep(0);
00168 }
00169 
00170 // Display a progress bar on second row of LCD. Reduce size of bar from right
00171 // to left, one pixel at a time. Maximum time is 20 seconds (set by input).
00172 void DelayBar(unsigned char sec)
00173 {
00174   unsigned char i,j;
00175   unsigned char delay;
00176 
00177   delay = (sec << 2);
00178   delay += (sec << 3);
00179   delay += (sec / 2);
00180 
00181   for (i=0;i<16;i++)
00182     LCD_PutXY_Raw(0x13,i,1);
00183   for (i=0;i<16;i++)
00184   {
00185     for (j=0;j<4;j++)
00186     {
00187       LCD_PutXY_Raw(0x7E-j,15-i,1);
00188       Delay(delay);
00189     }
00190     LCD_PutXY(' ',15-i,1);
00191     Delay(delay);
00192   }
00193 }
00194 
00195 // Sound pietzoelectric buzzer using timer/counter 1. Buzzer frequency is
00196 // inversely proportional to tone input value: Freq = fCLK / (2 x tone).
00197 void Beep(unsigned int tone)
00198 {
00199   if (tone == 0)
00200   {
00201     TCCR1A = (1 << COM1B1);               // clear OC1B on compare match
00202     TCCR1B = (1 << WGM12);                // CTC mode,  no clock
00203     TCCR1C = (1 << FOC1B);                // force output compare for channel B
00204   }
00205   else
00206   {
00207     TCNT1 = 0x0000;                       // clear 16-bit counter
00208     OCR1A = tone;                         // set TOP
00209     OCR1B = tone >> 1;                    // set compare
00210     TCCR1A = (1 << COM1B0);               // toggle OC1B on compare match
00211     TCCR1B = (1 << WGM12) | (1 << CS10);  // CTC mode, 1/CLK
00212   }
00213 }
00214 
00215 // Delay execution for number of milliseconds. Calibrated for 1 MHz clock.
00216 void Delay(unsigned int ms)
00217 {
00218   unsigned char delay;
00219 
00220   do
00221   {
00222     delay = 166;                      // 6 cycles/loop
00223     while(delay--);
00224   }
00225   while (ms--);
00226 }
00227 
00228 // Watchdog timeout.
00229 #pragma vector = WDT_vect
00230 __interrupt void WDT_ISR(void)
00231 {
00232   MCUSR &= ~(1 << WDRF);              // clear WD reset flag
00233   WDTCSR |= (1<<WDIE);                // set WDIE to avoid hardware reset
00234   ClearInputBuffer();                 // erase all keystrokes from buffer
00235   LCD_ClearLine(1);                   // erase all characters on 2nd row
00236 }

Generated on Mon Oct 10 15:25:09 2005 for AVR245: Code Lock with 4x4 Keypad and I2C(TM) LCD by  doxygen 1.4.4