| Remote Access Control | |||||
This file contains the setup and main control code for the Remote Keyless Entry application.
Copyright (c) 2006, Atmel Corporation All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Definition in file main.c.
#include "common.h"
#include "config.h"
#include "aes.h"
#include "cmac.h"
#include "memory.h"
#include "comms.h"
#include "crc.h"
Include dependency graph for main.c:

Go to the source code of this file.
Functions | |
| void | errorLoop (byte blinkCount) |
| void | handleResetFlags (void) |
| void | main (void) |
| static __interrupt void | pinChangeHandler (void) |
| void | setupPeripherals (void) |
| COMMAND_CODE_TYPE | sleepAndGetCommand (void) |
| void | transmitCommandMessage (COMMAND_CODE_TYPE command) |
| void | transmitTeachMessage (void) |
| void errorLoop | ( | byte | blinkCount | ) |
Loop forever, blinking a LED.
Definition at line 128 of file main.c.
Referenced by handleResetFlags().
00129 { 00130 // Initialize Watchdog Timer. 00131 __watchdog_reset(); 00132 WDTCR = (1<<WDCE) | (1<<WDE); 00133 WDTCR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0); 00134 WDTCR |= (1<<WDTIF) | (1<<WDTIE); 00135 00136 // Enable Power Down Sleep Mode. 00137 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0); 00138 00139 // Start blinking. 00140 __enable_interrupt(); 00141 DDRB = (1<<PB3); 00142 PORTB = (0<<PB3); 00143 for(;;) { 00144 __sleep(); 00145 __watchdog_reset(); 00146 WDTCR |= (1<<WDTIE); 00147 byte blinks; 00148 for( blinks = 0; blinks < blinkCount; ++blinks ) { 00149 PORTB = (1<<PB3); 00150 __delay_cycles( (8000000/1000)*50 ); // 50ms 00151 PORTB = (0<<PB3); 00152 __delay_cycles( (8000000/1000)*50 ); // 50ms 00153 } 00154 } 00155 }
| void handleResetFlags | ( | void | ) |
Read reset flags and act accordingly.
Definition at line 254 of file main.c.
References errorLoop(), and MAX_WATCHDOG_RESETS.
Referenced by main().
00255 { 00256 #ifndef NOWDT 00257 static __no_init byte __eeprom watchdogResetCount; // Will be set to 0 or 0xff on first Power-up. 00258 if( watchdogResetCount == 0xff ) { 00259 watchdogResetCount = 0x00; 00260 } 00261 #endif 00262 00263 // Read and clear reset flags. 00264 byte resetFlags = MCUSR; 00265 MCUSR = 0x00; 00266 00267 // Check for reset sources. 00268 if( resetFlags & ((1<<PORF)|(1<<EXTRF)) ) { // Power-on or External Reset? 00269 #ifndef NOWDT 00270 watchdogResetCount = 0; 00271 #endif 00272 } 00273 #ifndef NOWDT 00274 if( resetFlags & (1<<WDRF) ) { // Watchdog Reset? 00275 if( watchdogResetCount >= MAX_WATCHDOG_RESETS ) { 00276 errorLoop( 2 ); 00277 } else { 00278 ++watchdogResetCount; 00279 } 00280 } 00281 #endif 00282 #ifndef NOBOD 00283 if( resetFlags & (1<<BORF) ) { // Brown Out Reset? 00284 errorLoop( 1 ); 00285 } 00286 #endif 00287 }
Here is the call graph for this function:

| void main | ( | void | ) |
Definition at line 324 of file main.c.
References calcCMACSubkey(), calcKeySchedule(), COMMAND_CODE_TYPE, cryptoBlock, handleResetFlags(), initializeMessage(), setupPeripherals(), sleepAndGetCommand(), TEACH_COMMAND, transmitCommandMessage(), and transmitTeachMessage().
00325 { 00326 handleResetFlags(); 00327 setupPeripherals(); 00328 initializeMessage(); 00329 calcKeySchedule( secretKey ); 00330 calcCMACSubkey( cryptoBlock ); 00331 __enable_interrupt(); 00332 00333 for(;;) { // Loop for ever. 00334 00335 PORTB &= ~(1<<PB4); // Disable transmitter. 00336 DDRB &= ~(1<<PB1); // PB1 back to input for button input. 00337 00338 COMMAND_CODE_TYPE command = sleepAndGetCommand(); 00339 00340 PORTB |= (1<<PB4); // Enable transmitter. 00341 DDRB |= (1<<PB1); // PB1 to output for both ASK and FSK. 00342 00343 // Allow time for transmitter to start up. 00344 __delay_cycles( 8000000 / 1000 * 5 ); // 5ms, given in datasheet. 00345 00346 if( command != TEACH_COMMAND ) { 00347 transmitCommandMessage( command ); 00348 } else { 00349 transmitTeachMessage(); 00350 } 00351 } 00352 }
Here is the call graph for this function:

| static __interrupt void pinChangeHandler | ( | void | ) | [static] |
ISR called when a button is pressed.
Definition at line 60 of file main.c.
References BUTTON_MASK, and COMMAND_CODE_TYPE.
00061 { 00062 COMMAND_CODE_TYPE lastButtonState; 00063 COMMAND_CODE_TYPE newButtonState; 00064 unsigned char equalCount = 0; 00065 00066 lastButtonState = PINB & BUTTON_MASK; 00067 do { 00068 __delay_cycles( 8000 ); // Allow for debounce and human slowness. Empirical value. 00069 newButtonState = PINB & BUTTON_MASK; 00070 if( newButtonState == lastButtonState ) { 00071 ++equalCount; 00072 } else { 00073 equalCount = 0; 00074 lastButtonState = newButtonState; 00075 } 00076 } while( equalCount < 10 ); // 10 is empirical value. 00077 }
| void setupPeripherals | ( | void | ) |
Initial setup of misc. peripherals in the AVR.
Definition at line 292 of file main.c.
References BUTTON_MASK.
Referenced by main().
00293 { 00294 #ifndef NOWDT 00295 // Initialize Watchdog Timer. 00296 __watchdog_reset(); 00297 WDTCR = (1<<WDCE) | (1<<WDE); 00298 WDTCR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0); 00299 WDTCR |= (1<<WDIF) | (1<<WDIE); 00300 #endif 00301 00302 // Setup Pin-change input mask. 00303 PCMSK = BUTTON_MASK; 00304 00305 // Setup IO ports. 00306 PORTB = (0<<PB0) | 00307 (0<<PB1) | 00308 (0<<PB2) | 00309 (0<<PB3) | 00310 (0<<PB4) | 00311 (0<<PB5); 00312 DDRB |= (1<<PB4); // Transmitter Enable signal is output. 00313 00314 // Turn off unused modules to save power/oomph. 00315 ACSR |= (1<<ACD); 00316 PRR = (1<<PRTIM1) | (1<<PRADC); 00317 00318 // Enable Power Down Sleep Mode. 00319 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0); 00320 }
| COMMAND_CODE_TYPE sleepAndGetCommand | ( | void | ) |
Sleep and wait for button to be pressed.
Definition at line 93 of file main.c.
References BUTTON_MASK, and COMMAND_CODE_TYPE.
Referenced by main().
00094 { 00095 COMMAND_CODE_TYPE buttonState; 00096 00097 // Enable Power Down Sleep Mode. 00098 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0); 00099 00100 // Enable Pin Change Interrupt. 00101 __delay_cycles( 100 ); // Wait for RF TX ctrl pins to settle. Empirical value. 00102 GIFR |= (1<<PCIF); 00103 GIMSK |= (1<<PCIE); 00104 00105 do { 00106 #ifndef NOWDT 00107 // Restart watchdog if it timed out. 00108 if( !(WDTCR & (1<<WDIE)) ) { 00109 __watchdog_reset(); 00110 WDTCR |= (1<<WDIE); 00111 } 00112 #endif 00113 __sleep(); // Wait for Pin-Change Interrupt. 00114 00115 // Read pins and mask out unused inputs according pin change mask. 00116 buttonState = PINB & BUTTON_MASK; 00117 } while( !buttonState ); 00118 00119 GIMSK &= ~(1<<PCIE); // Good practice to turn off interrupt. 00120 00121 return buttonState; 00122 }
| void transmitCommandMessage | ( | COMMAND_CODE_TYPE | command | ) |
Construct and transmit and ordinary command message.
Definition at line 160 of file main.c.
References calcCMAC(), continueTransmission(), createMessage(), cryptoBlock, MAC_BYTES, SharedBlock::messagePayload, PREBURST_BYTES, MessagePayload::serialNo, sharedBlock, startCounterUpdate(), startTransmission(), stopTransmission(), waitForCounterUpdate(), and waitForTransmission().
Referenced by main().
00161 { 00162 const byte preburst = 0xff; 00163 byte i; 00164 00165 createMessage( command ); 00166 startTransmission( &preburst, 1 ); 00167 for( i = 0; i < PREBURST_BYTES-1; ++i ) { 00168 waitForTransmission(); 00169 continueTransmission( &preburst, 1 ); 00170 } 00171 waitForTransmission(); 00172 continueTransmission( (const byte *) 00173 &sharedBlock.messagePayload, 00174 sizeof( struct MessagePayload ) ); 00175 calcCMAC( (const byte *) 00176 &sharedBlock.messagePayload.serialNo, 00177 cryptoBlock ); 00178 waitForTransmission(); 00179 00180 // Send MAC bytes and one extra byte to make sure all Manchester edges are recognized 00181 // at the receiver. Actually only one extra edge after the last MAC byte would be enough, 00182 // but it is more convenient to just add another byte in the transmission. 00183 cryptoBlock[ MAC_BYTES ] = 0x00; // Don't reveal more MAC bytes than necessary. 00184 continueTransmission( cryptoBlock, MAC_BYTES + 1 ); 00185 00186 startCounterUpdate(); 00187 waitForTransmission(); 00188 stopTransmission(); 00189 waitForCounterUpdate(); 00190 }
Here is the call graph for this function:

| void transmitTeachMessage | ( | void | ) |
Construct and transmit a message with serial number, encrypted key etc.
Definition at line 195 of file main.c.
References BLOCK_SIZE, calcCRC(), calcKeySchedule(), cipherLookup(), continueTransmission(), copyBytesFromEEPROM(), CRCReg, SharedBlock::cryptoBlock, cryptoBlock, initCRC(), initializeMessage(), KEY_SIZE, SharedBlock::messagePayload, PREBURST_BYTES, SEQ_COUNTER_BYTES, SERIAL_NO_BYTES, MessagePayload::serialNo, sharedBlock, startTransmission(), stopTransmission(), and waitForTransmission().
Referenced by main().
00196 { 00197 const byte preburst = 0xff; 00198 byte i; 00199 00200 calcKeySchedule( sharedKey ); 00201 initCRC(); 00202 startTransmission( &preburst, 1 ); 00203 for( i = 0; i < PREBURST_BYTES-1; ++i ) { 00204 waitForTransmission(); 00205 continueTransmission( &preburst, 1 ); 00206 } 00207 waitForTransmission(); 00208 continueTransmission( (const byte*) 00209 &sharedBlock.messagePayload, 00210 SERIAL_NO_BYTES + SEQ_COUNTER_BYTES + 1 ); 00211 for( i = 0; i < SERIAL_NO_BYTES + SEQ_COUNTER_BYTES; ++i ) { 00212 calcCRC( ((byte *) &sharedBlock.messagePayload.serialNo)[ i ] ); 00213 } 00214 copyBytesFromEEPROM( cryptoBlock, 00215 secretKey, BLOCK_SIZE ); 00216 cipherLookup( cryptoBlock ); 00217 waitForTransmission(); 00218 continueTransmission( cryptoBlock, BLOCK_SIZE ); 00219 for( i = 0; i < BLOCK_SIZE; ++i ) { 00220 calcCRC( cryptoBlock[ i ] ); 00221 } 00222 #if KEY_SIZE > BLOCK_SIZE 00223 copyBytesFromEEPROM( sharedBlock.cryptoBlock, 00224 secretKey + BLOCK_SIZE, 00225 KEY_SIZE - BLOCK_SIZE ); 00226 #if KEY_SIZE < (2*BLOCK_SIZE) 00227 00228 for( i = KEY_SIZE - BLOCK_SIZE; i < BLOCK_SIZE; ++i ) { 00229 sharedBlock.cryptoBlock[ i ] = 0x00; 00230 } 00231 #endif 00232 cipherLookup( sharedBlock.cryptoBlock ); 00233 waitForTransmission(); 00234 continueTransmission( sharedBlock.cryptoBlock, 00235 BLOCK_SIZE ); 00236 for( i = 0; i < BLOCK_SIZE; ++i ) { 00237 calcCRC( sharedBlock.cryptoBlock[ i ] ); 00238 } 00239 #endif 00240 00241 calcCRC( 0x00 ); 00242 calcCRC( 0x00 ); 00243 waitForTransmission(); 00244 continueTransmission( CRCReg, 3 ); // Transmit one extra byte, see comment for MAC transmission in transmitCommandMessage(...). 00245 calcKeySchedule( secretKey ); 00246 initializeMessage(); 00247 waitForTransmission(); 00248 stopTransmission(); 00249 }
Here is the call graph for this function:

Generated on Fri Aug 8 11:03:27 2008 for AVR411 Secure Rolling Code Algorithm (Transmitter) by 1.4.7
|