| 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@