Remote Access Control


main.c File Reference


Detailed Description

Main application source file.

This file contains the setup and main control code for the Remote Keyless Entry application.

Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Name
Revision
1206
Date
2006-11-08 09:50:32 +0100 (on, 08 nov 2006)

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)


Function Documentation

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:

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