| Remote Access Control |

# radio.c File Reference

## Detailed Description

Source file for the RF receiver support functions.

This file contains the function implementation for the RF receiver support functions. Refer to the radio.h file for more details.

- File: radio.c
- Compiler: IAR EWAVR 4.11B
- Supported devices: ATtiny45/85
- AppNote: AVR411 - Secure Rolling Code Algorithm for Wireless Link

Author:
  Atmel Corporation: http://www.atmel.com
  Support email: avr@atmel.com

Name

Revision
  1193

Date
  2006-10-31 14:21:08 +0100 (ti, 31 okt 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 radio.c.

`#include "radio.h"`
`#include "common.h"`
`#include "config.h"`
`#include <stddef.h>`

Include dependency graph for radio.c:

Go to the source code of this file.

## Defines
#define | DELAY_US(delay) __delay_cycles( (delay) * (CPU_F / 1000000) )
#define | DRIVE_RX_DATA() RX_DATA_DDR_REG |= (1<<RX_DATA_BIT_POS);
#define | PROG_BIT_DELAY() DELAY_US( RX_BASIC_CLK_US * PROG_BIT_PULSE_CYCLES )
#define | PROG_BIT_PULSE_CYCLES 70
#define | PROG_RESET_MARKER_HALF_PERIOD_DELAY() DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 2) )
#define | PROG_RESET_MARKER_PERIOD_CYCLES 4096
#define | PROG_RESET_MARKER_QUARTER_PERIOD_DELAY() DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 4) )
#define | PROG_START_DELAY() DELAY_US( RX_BASIC_CLK_US * PROG_START_PULSE_CYCLES )
#define | PROG_START_PULSE_CYCLES 5000
#define | PROG_START_RESET_DELAY() DELAY_US( RX_BASIC_CLK_US * PROG_START_RESET_PULSE_CYCLES )
#define | PROG_START_RESET_PULSE_CYCLES 8700
#define | PROG_WINDOW_DELAY() DELAY_US( RX_BASIC_CLK_US * PROG_WINDOW_DELAY_CYCLES )
#define | PROG_WINDOW_DELAY_CYCLES 76
#define | RELEASE_RX_DATA() RX_DATA_DDR_REG &= ~(1<<RX_DATA_BIT_POS);
#define | RX_BASIC_CLK_US ( RX_PRESCALE / (RX_XTAL_HZ / 1000000) )
#define | RX_TIMEOUT_VALUE (RX_BASIC_CLK_US * PROG_RESET_MARKER_PERIOD_CYCLES)
#define | WAIT_RX_DATA_EDGE(timeoutCountdownVar)
#define | WAIT_RX_DATA_FALLING(timeoutCountdownVar)
#define | WAIT_RX_DATA_RISING(timeoutCountdownVar)
## Typedefs
typedef unsigned int | rx_timeout_t
## Functions
bool | rx_CheckResetMarker (unsigned char checkCycles)
bool | rx_WriteLIMIT (const rx_LIMIT_t *settings, bool longStartPulse, bool *equivalenceValue)
bool | rx_WriteOFF (bool longStartPulse)
bool | rx_WriteOPMODE (const rx_OPMODE_t *settings, bool longStartPulse, bool *equivalenceValue)
bool | rx_WriteRegister (unsigned int value, bool longStartPulse, bool *equivalenceValue)
bool | rx_WriteVerifySleep (const rx_OPMODE_t *opmode, const rx_LIMIT_t *limit)

## Define Documentation

#define DELAY_US | ( | delay |  | ) | __delay_cycles( (delay) * (CPU_F / 1000000) )

Macro to delay given number of microseconds based on AVR CPU speed.

Definition at line 76 of file radio.c.

#define DRIVE_RX_DATA | ( |  | ) | RX_DATA_DDR_REG |= (1<<RX_DATA_BIT_POS);

Drive the RF receiver data line low from the AVR side.

Definition at line 106 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define PROG_BIT_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * PROG_BIT_PULSE_CYCLES )

Delay for the length of one programming bit pulse.

Definition at line 89 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define PROG_BIT_PULSE_CYCLES 70

Length of programming bit pulse in 'basic clock cycles'.

Definition at line 67 of file radio.c.

#define PROG_RESET_MARKER_HALF_PERIOD_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 2) )

Delay for one half of a reset marker period.

Definition at line 95 of file radio.c.

Referenced by rx_CheckResetMarker().

#define PROG_RESET_MARKER_PERIOD_CYCLES 4096

Length of whole reset marker period in 'basic clock cycles'.

Definition at line 69 of file radio.c.

#define PROG_RESET_MARKER_QUARTER_PERIOD_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * (PROG_RESET_MARKER_PERIOD_CYCLES / 4) )

Delay for one quarter of a reset marker period.

Definition at line 92 of file radio.c.

Referenced by rx_CheckResetMarker().

#define PROG_START_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * PROG_START_PULSE_CYCLES )

Delay for the length of one programming start pulse.

Definition at line 80 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define PROG_START_PULSE_CYCLES 5000

Length of programming start pulse in 'basic clock cycles'.

Definition at line 61 of file radio.c.

#define PROG_START_RESET_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * PROG_START_RESET_PULSE_CYCLES )

Delay for the length of one long start pulse.

Definition at line 83 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define PROG_START_RESET_PULSE_CYCLES 8700

Length of long start pulse in 'basic clock cycles'.

Definition at line 63 of file radio.c.

#define PROG_WINDOW_DELAY | ( |  | ) | DELAY_US( RX_BASIC_CLK_US * PROG_WINDOW_DELAY_CYCLES )

Delay for the length of one programming window delay.

Definition at line 86 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define PROG_WINDOW_DELAY_CYCLES 76

Length of programming window delay in 'basic clock cycles'.

Definition at line 65 of file radio.c.

#define RELEASE_RX_DATA | ( |  | ) | RX_DATA_DDR_REG &= ~(1<<RX_DATA_BIT_POS);

Release the RF receiver data line from the AVR side.

Definition at line 103 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define RX_BASIC_CLK_US ( RX_PRESCALE / (RX_XTAL_HZ / 1000000) )

Internal RF basic clock cycle period in microseconds (equals RF freq. / 14).

Definition at line 58 of file radio.c.

#define RX_TIMEOUT_VALUE (RX_BASIC_CLK_US * PROG_RESET_MARKER_PERIOD_CYCLES)

Timeout value guaranteed to a least exceed a valid reset marker period.

Definition at line 134 of file radio.c.

Referenced by rx_CheckResetMarker(), rx_WriteOFF(), and rx_WriteRegister().

#define WAIT_RX_DATA_EDGE | ( | timeoutCountdownVar |  | ) |

Value:

    { \
                    unsigned char tempValue = GET_RX_DATA(); \
                    do {} while( (GET_RX_DATA() == tempValue) && (--timeoutCountdownVar > 0) ); \
            }

Wait for any edge on the RF receiver data line while decrementing the timeout value.

Definition at line 121 of file radio.c.

Referenced by rx_CheckResetMarker().

#define WAIT_RX_DATA_FALLING | ( | timeoutCountdownVar |  | ) |

Value:

    do {} while( (GET_RX_DATA() == 0) && (--timeoutCountdownVar > 0) ); \
            if( timeoutCountdownVar > 0 ) { \
                    do {} while( (GET_RX_DATA() != 0) && (--timeoutCountdownVar > 0) ); \
            }

Wait for falling edge on the RF receiver data line while decrementing the timeout value.

Definition at line 109 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

#define WAIT_RX_DATA_RISING | ( | timeoutCountdownVar |  | ) |

Value:

    do {} while( (GET_RX_DATA() != 0) && (--timeoutCountdownVar > 0) ); \
            if( timeoutCountdownVar > 0 ) { \
                    do {} while( (GET_RX_DATA() == 0) && (--timeoutCountdownVar > 0) ); \
            }

Wait for rising edge on the RF receiver data line while decrementing the timeout value.

Definition at line 115 of file radio.c.

Referenced by rx_WriteOFF(), and rx_WriteRegister().

## Typedef Documentation

typedef unsigned int rx_timeout_t

Data type to use for the timeout countdown value while waiting for edges on the data line.

Definition at line 132 of file radio.c.

## Function Documentation

bool rx_CheckResetMarker | ( | unsigned char | checkCycles | ) |

Check if the reset marker (square wave) is present for 'checkCycles' cycles in the data line.

Definition at line 208 of file radio.c.

References GET_RX_DATA, PROG_RESET_MARKER_HALF_PERIOD_DELAY, PROG_RESET_MARKER_QUARTER_PERIOD_DELAY, RX_TIMEOUT_VALUE, and WAIT_RX_DATA_EDGE.

    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 }

bool rx_WriteLIMIT | ( | const rx_LIMIT_t * | settings,
|  | bool | longStartPulse,
|  | bool * | equivalenceValue |
| ) |  |  |

Set the RF receiver's LIMIT register.

The contents of the rx_LIMIT_t struct is programmed into the LIMIT register.

If 'longStartPulse' is true, the programming is initiated with a long start pulse cancelling any reset marker and initializing all registers.

If an equivalence bit is returned from the RF recevier, ie. the programmed values were already present in the LIMIT register, the 'bool' pointed to by 'equivalenceValue' is set to true. If not, it is set to false.

If the programming sessions fails or times out, nothing is changed and the function returns false. It return true if everything succeeds, regardless of the equivalence bit returned from the RF receiver.

Definition at line 331 of file radio.c.

References rx_LIMIT_t::limMax, rx_LIMIT_t::limMin, and rx_WriteRegister().

Referenced by rx_WriteVerifySleep().

    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 }

Here is the call graph for this function:

bool rx_WriteOFF | ( | bool | longStartPulse | ) |

Write an OFF command to the RF recevier.

An OFF command is sent to the RF receiver.

If 'longStartPulse' is true, the programming is initiated with a long start pulse cancelling any reset marker and initializing all registers.

If the programming sessions fails or times out, nothing is changed and the function returns false. It return true if everything succeeds, regardless of the equivalence bit returned from the RF receiver.

Definition at line 245 of file radio.c.

References DRIVE_RX_DATA, PROG_BIT_DELAY, PROG_START_DELAY, PROG_START_RESET_DELAY, PROG_WINDOW_DELAY, RELEASE_RX_DATA, RX_TIMEOUT_VALUE, WAIT_RX_DATA_FALLING, and WAIT_RX_DATA_RISING.

Referenced by main(), receiverTimedOut(), rx_WriteVerifySleep(), and rxClockLineHandler().

    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 }

bool rx_WriteOPMODE | ( | const rx_OPMODE_t * | settings,
|  | bool | longStartPulse,
|  | bool * | equivalenceValue |
| ) |  |  |

Set the RF recevier's OPMODE register.

The contents of the rx_OPMODE_t struct is programmed into the OPMODE register.

If 'longStartPulse' is true, the programming is initiated with a long start pulse cancelling any reset marker and initializing all registers.

If an equivalence bit is returned from the RF recevier, ie. the programmed values were already present in the OPMODE register, the 'bool' pointed to by 'equivalenceValue' is set to true. If not, it is set to false.

If the programming sessions fails or times out, nothing is changed and the function returns false. It return true if everything succeeds, regardless of the equivalence bit returned from the RF receiver.

Definition at line 286 of file radio.c.

References rx_OPMODE_t::amplitudeModulation, rx_OPMODE_t::baudRateRange, rx_OPMODE_t::bitCheck, rx_OPMODE_t::noiseSuppression, rx_WriteRegister(), rx_OPMODE_t::sleepExtension, and rx_OPMODE_t::sleepValue.

Referenced by rx_WriteVerifySleep().

    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 }

Here is the call graph for this function:

bool rx_WriteRegister | ( | unsigned int | value,
|  | bool | longStartPulse,
|  | bool * | equivalenceValue |
| ) |  |  |

The upper 15 bits of 'value' is programmed into the RF recevier.

If 'longStartPulse' is true, the programming is initiated with a long start pulse cancelling any reset marker and initializing all registers.

If an equivalence bit is returned from the RF recevier, ie. the programmed values were already present in the register in question, the 'bool' pointed to by 'equivalenceValue' is set to true. If not, it is set to false.

If the programming sessions fails or times out, nothing is changed and the function returns false. It return true if everything succeeds, regardless of the equivalence bit returned from the RF receiver.

Definition at line 152 of file radio.c.

References DRIVE_RX_DATA, PROG_BIT_DELAY, PROG_START_DELAY, PROG_START_RESET_DELAY, PROG_WINDOW_DELAY, RELEASE_RX_DATA, RX_TIMEOUT_VALUE, WAIT_RX_DATA_FALLING, and WAIT_RX_DATA_RISING.

Referenced by rx_WriteLIMIT(), and rx_WriteOPMODE().

    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 }

bool rx_WriteVerifySleep | ( | const rx_OPMODE_t * | opmode,
|  | const rx_LIMIT_t * | limit |
| ) |  |  |

Write both registers, verify settings and finish with an OFF command for the RF receiver.

Definition at line 352 of file radio.c.

References rx_WriteLIMIT(), rx_WriteOFF(), and rx_WriteOPMODE().

Referenced by initReceiver().

    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 }

Here is the call graph for this function:

@DOC_TITLE@