Remote Access Control


radio.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00048 #include "radio.h"
00049 #include "common.h"
00050 #include "config.h"
00051 #include <stddef.h>
00052 
00053 
00054 
00055 /* --- Internal definitions for RF recevier programming timing --- */
00056 
00058 #define RX_BASIC_CLK_US ( RX_PRESCALE / (RX_XTAL_HZ / 1000000) )
00059 
00061 #define PROG_START_PULSE_CYCLES 5000 // Approx. 10% less than max. (t1 in datasheet).
00063 #define PROG_START_RESET_PULSE_CYCLES 8700 // Approx. 10% more than min. (t1 in datasheet).
00065 #define PROG_WINDOW_DELAY_CYCLES 76 // Approx. 20% more than min. (t4 in datasheet).
00067 #define PROG_BIT_PULSE_CYCLES 70 // Approx. 10% more than min. (t7 in datasheet).
00069 #define PROG_RESET_MARKER_PERIOD_CYCLES 4096 // Exact value (f_RM in datasheet).
00070 
00071 
00072 
00073 /* --- Delay macros for RF recevier programming timing --- */
00074 
00076 #define DELAY_US( delay ) \
00077         __delay_cycles( (delay) * (CPU_F / 1000000) )
00078 
00080 #define PROG_START_DELAY() \
00081         DELAY_US( RX_BASIC_CLK_US * PROG_START_PULSE_CYCLES )
00083 #define PROG_START_RESET_DELAY() \
00084         DELAY_US( RX_BASIC_CLK_US * PROG_START_RESET_PULSE_CYCLES )
00086 #define PROG_WINDOW_DELAY() \
00087         DELAY_US( RX_BASIC_CLK_US * PROG_WINDOW_DELAY_CYCLES )
00089 #define PROG_BIT_DELAY() \
00090         DELAY_US( RX_BASIC_CLK_US * PROG_BIT_PULSE_CYCLES )
00092 #define PROG_RESET_MARKER_QUARTER_PERIOD_DELAY() \
00093         DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 4) )
00095 #define PROG_RESET_MARKER_HALF_PERIOD_DELAY() \
00096         DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 2) )
00097 
00098 
00099 
00100 /* --- Macros for controlling the RF recevier data line --- */
00101 
00103 #define RELEASE_RX_DATA() \
00104         RX_DATA_DDR_REG &= ~(1<<RX_DATA_BIT_POS);
00106 #define DRIVE_RX_DATA() \
00107         RX_DATA_DDR_REG |= (1<<RX_DATA_BIT_POS);
00109 #define WAIT_RX_DATA_FALLING( timeoutCountdownVar ) \
00110         do {} while( (GET_RX_DATA() == 0) && (--timeoutCountdownVar > 0) ); \
00111         if( timeoutCountdownVar > 0 ) { \
00112                 do {} while( (GET_RX_DATA() != 0) && (--timeoutCountdownVar > 0) ); \
00113         }
00115 #define WAIT_RX_DATA_RISING( timeoutCountdownVar ) \
00116         do {} while( (GET_RX_DATA() != 0) && (--timeoutCountdownVar > 0) ); \
00117         if( timeoutCountdownVar > 0 ) { \
00118                 do {} while( (GET_RX_DATA() == 0) && (--timeoutCountdownVar > 0) ); \
00119         }
00121 #define WAIT_RX_DATA_EDGE( timeoutCountdownVar ) \
00122         { \
00123                 unsigned char tempValue = GET_RX_DATA(); \
00124                 do {} while( (GET_RX_DATA() == tempValue) && (--timeoutCountdownVar > 0) ); \
00125         }
00126 
00127 
00128 
00129 /* --- Functions for programming the RF recevier --- */
00130 
00132 typedef unsigned int rx_timeout_t;
00134 #define RX_TIMEOUT_VALUE (RX_BASIC_CLK_US * PROG_RESET_MARKER_PERIOD_CYCLES)
00135 
00136 
00137 
00152 bool rx_WriteRegister( unsigned int value, bool longStartPulse, bool * equivalenceValue )
00153 {
00154         unsigned char bitCount = 15;
00155         rx_timeout_t timeoutCountdown;
00156 
00157         DRIVE_RX_DATA(); // Begin 'programming start' pulse.
00158         if( longStartPulse == true ) {
00159                 PROG_START_RESET_DELAY();
00160         } else {
00161                 PROG_START_DELAY();
00162         }
00163         RELEASE_RX_DATA(); // End 'programming start' pulse.
00164 
00165         do {
00166                 timeoutCountdown = RX_TIMEOUT_VALUE;
00167                 WAIT_RX_DATA_FALLING( timeoutCountdown ) // Wait for synch. pulse begin edge.
00168                 if( timeoutCountdown == 0 ) return false; // Timed out!
00169                 timeoutCountdown = RX_TIMEOUT_VALUE;
00170                 WAIT_RX_DATA_RISING( timeoutCountdown ) // Wait for synch. pulse end edge.
00171 
00172                 if( timeoutCountdown == 0 ) return false; // Timed out!
00173 
00174                 PROG_WINDOW_DELAY(); // Wait for programming window.
00175                 if( !(value & 0x8000) ) {
00176                         DRIVE_RX_DATA(); // Drive data line low to indicate logic 0.
00177                         PROG_BIT_DELAY(); // Bit pulse duration.
00178                         RELEASE_RX_DATA(); // Release line after bit pulse.
00179                 } else {
00180                         PROG_BIT_DELAY(); // Bit pulse duration for logic 1.
00181                 }
00182 
00183                 value <<= 1; // Move next bit into MSB of word.
00184         } while( --bitCount );
00185 
00186         bool equivalenceBit;
00187         timeoutCountdown = RX_TIMEOUT_VALUE;
00188         WAIT_RX_DATA_FALLING( timeoutCountdown ); // Wait for equivalence pulse begin egde.
00189         if( timeoutCountdown == 0 ) {
00190                 equivalenceBit = false; // Timed out => no pulse.
00191         } else {
00192                 timeoutCountdown = RX_TIMEOUT_VALUE;
00193                 WAIT_RX_DATA_RISING( timeoutCountdown ) // Wait for equivalence pulse end edge.
00194                 if( timeoutCountdown == 0 ) return false; // Timed out!
00195                 equivalenceBit = true; // No timeout => pulse present.
00196         }
00197 
00198         // If pointer is supplied, store equivalence bit.
00199         if( equivalenceValue ) {
00200                 *equivalenceValue = equivalenceBit;
00201         }
00202 
00203         return true; // Success!
00204 }
00205 
00206 
00207 
00208 bool rx_CheckResetMarker( unsigned char checkCycles )
00209 {
00210         rx_timeout_t timeoutCountdown;
00211 
00212         timeoutCountdown = RX_TIMEOUT_VALUE;
00213         WAIT_RX_DATA_EDGE( timeoutCountdown ); // Wait for first edge.
00214         if( timeoutCountdown == 0 ) return false; // Timed out => no reset marker.
00215         PROG_RESET_MARKER_QUARTER_PERIOD_DELAY(); // Wait until the middle of the half-period.
00216 
00217         unsigned char tempValue = GET_RX_DATA();
00218         do {
00219                 PROG_RESET_MARKER_HALF_PERIOD_DELAY(); // Wait until next half of period.
00220 
00221                 if( GET_RX_DATA() == tempValue ) {
00222                         // No change on data line => no reset marker.
00223                         return false;
00224                 } else {
00225                         // Change => Store value and check next half-period.
00226                         tempValue = GET_RX_DATA();
00227                 }
00228         } while( --checkCycles );
00229 
00230         return true; // Yes, we found the reset marker.
00231 }
00232 
00233 
00234 
00245 bool rx_WriteOFF( bool longStartPulse )
00246 {
00247         rx_timeout_t timeoutCountdown;
00248 
00249         DRIVE_RX_DATA(); // Begin 'programming start' pulse.
00250         if( longStartPulse == true ) {
00251                 PROG_START_RESET_DELAY();
00252         } else {
00253                 PROG_START_DELAY();
00254         }
00255         RELEASE_RX_DATA(); // End 'programming start' pulse.
00256 
00257         timeoutCountdown = RX_TIMEOUT_VALUE;
00258         WAIT_RX_DATA_FALLING( timeoutCountdown ); // Wait for synch. pulse begin edge.
00259         if( timeoutCountdown == 0 ) return false; // Timed out!
00260         timeoutCountdown = RX_TIMEOUT_VALUE;
00261         WAIT_RX_DATA_RISING( timeoutCountdown ); // Wait for synch. pulse end edge.
00262         if( timeoutCountdown == 0 ) return false; // Timed out!
00263 
00264         PROG_WINDOW_DELAY(); // Wait for programming window.
00265         PROG_BIT_DELAY(); // Bit pulse duration for logic 1.
00266 
00267         return true; // Success!
00268 }
00269 
00270 
00271 
00286 bool rx_WriteOPMODE( const rx_OPMODE_t * settings, bool longStartPulse, bool * equivalenceValue )
00287 {
00288         if( settings == NULL ) {
00289                 return false; // Invalid input.
00290         }
00291 
00292         // Check that no fields exceed their bitfield's max value.
00293         if( settings->baudRateRange >= (1<<2) ||
00294                         settings->bitCheck >= (1<<2) ||
00295                         settings->amplitudeModulation >= (1<<1) ||
00296                         settings->sleepValue >= (1<<5) ||
00297                         settings->sleepExtension >= (1<<1) ||
00298                         settings->noiseSuppression >= (1<<1) ) {
00299                 return false; // Invalid input.
00300         }
00301 
00302         unsigned int registerValue = 0x4000; // Blank OPMODE frame.
00303         // Place fields correctly in frame.
00304         // Shift amount = register value bits (16) - position from right - field size in bits.
00305         registerValue |= settings->baudRateRange << (16-2-2);
00306         registerValue |= settings->bitCheck << (16-4-2);
00307         registerValue |= settings->amplitudeModulation << (16-6-1);
00308         registerValue |= settings->sleepValue << (16-7-5);
00309         registerValue |= settings->sleepExtension << (16-12-1);
00310         registerValue |= settings->noiseSuppression << (16-13-1);
00311 
00312         return rx_WriteRegister( registerValue, longStartPulse, equivalenceValue );
00313 }
00314 
00315 
00316 
00331 bool rx_WriteLIMIT( const rx_LIMIT_t * settings, bool longStartPulse, bool * equivalenceValue )
00332 {
00333         if( settings == NULL ) {
00334                 return false; // Invalid input.
00335         }
00336 
00337         if( settings->limMin >= (1<<6) || settings->limMax >= (1<<6) ) {
00338                 return false; // Invalid input.
00339         }
00340 
00341         unsigned int registerValue = 0x0000; // Blank LIMIT frame.
00342         // Place fields correctly in frame.
00343         // Shift amount = register value bits (16) - position from right - field size in bits.
00344         registerValue |= settings->limMin << (16-2-6);
00345         registerValue |= settings->limMax << (16-8-6);
00346 
00347         return rx_WriteRegister( registerValue, longStartPulse, equivalenceValue );
00348 }
00349 
00350 
00351 
00352 bool rx_WriteVerifySleep( const rx_OPMODE_t * opmode, const rx_LIMIT_t * limit )
00353 {
00354         bool success;
00355         bool equivalent;
00356 
00357         success = rx_WriteOPMODE( opmode, true, NULL );
00358         if( !success ) {
00359                 // Try again of no success on first try.
00360                 success = rx_WriteOPMODE( opmode, true, NULL );
00361                 if( !success ) return false;
00362         }
00363         success = rx_WriteOPMODE( opmode, false, &equivalent );
00364         if( !success || !equivalent ) {
00365                 // Try again of no success on first try.
00366                 success = rx_WriteOPMODE( opmode, false, &equivalent );
00367                 if( !success || !equivalent ) return false;
00368         }
00369 
00370         success = rx_WriteLIMIT( limit, false, NULL );
00371         if( !success ) {
00372                 // Try again of no success on first try.
00373                 success = rx_WriteLIMIT( limit, false, NULL );
00374                 if( !success ) return false;
00375         }
00376         success = rx_WriteLIMIT( limit, false, &equivalent );
00377         if( !success || !equivalent ) {
00378                 // Try again of no success on first try.
00379                 success = rx_WriteLIMIT( limit, false, &equivalent );
00380                 if( !success || !equivalent ) return false;
00381         }
00382 
00383         success = rx_WriteOFF( false );
00384         if( !success ) {
00385                 // Try again of no success on first try.
00386                 success = rx_WriteOFF( false );
00387                 if( !success ) return false;
00388         }
00389 
00390         return true;
00391 }
00392 
@DOC_TITLE@
Generated on Fri Aug 8 11:03:47 2008 for AVR411 Secure Rolling Code Algorithm (Receiver) by doxygen 1.4.7