Difference Analysis Generated by HtmlDiff on 10/26/2004 1:34 PM  

Base file: C:\CY4632_RDK_1_21\Firmware\Source Code\RDK Mouse\radio.c

Modified file: C:\CY4632_RDK_1_3\Firmware\Source Code\RDK Mouse\radio.c

//--------------------------------------------------------------------------
//
//  Collection of functions to access the LS Radio
//
//--------------------------------------------------------------------------
// $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK Mouse/radio.c $
// $Modtime: 6/16/04 4:38p10/01/04 1:18p $
// $Revision: 1011 $
//--------------------------------------------------------------------------
//
// Copyright 2003-2004, Cypress Semiconductor Corporation.
//
// This software is owned by Cypress Semiconductor Corporation (Cypress)
// and is protected by and subject to worldwide patent protection (United
// States and foreign), United States copyright laws and international 
// treaty provisions. Cypress hereby grants to licensee a personal, 
// non-exclusive, non-transferable license to copy, use, modify, create 
// derivative works of, and compile the Cypress Source Code and derivative 
// works for the sole purpose of creating custom software in support of 
// licensee product to be used only in conjunction with a Cypress integrated 
// circuit as specified in the applicable agreement. Any reproduction, 
// modification, translation, compilation, or representation of this 
// software except as specified above is prohibited without the express 
// written permission of Cypress.
//
// Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, 
// WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Cypress reserves the right to make changes without further notice to the
// materials described herein. Cypress does not assume any liability arising
// out of the application or use of any product or circuit described herein.
// Cypress does not authorize its products for use as critical components in
// life-support systems where a malfunction or failure may reasonably be
// expected to result in significant injury to the user. The inclusion of
// Cypress’ product in a life-support systems application implies that the
// manufacturer assumes all risk of such use and in doing so indemnifies
// Cypress against all charges.
//
// Use may be limited by and subject to the applicable Cypress software
// license agreement.
//
//--------------------------------------------------------------------------


#include "spim_1.h"
#include "ls_config.h"
#include "radio.h"
#include "protocol.h"
#include "bind.h"

#define RADIO_WAKEUP_TIME        5  3  // wait 53 ms for PLL to lock/stabliaze
#define GOOD_CHANNEL           0x01
#define BAD_CHANNEL            0xff
#define DEADMAN_MAX_COUNT       200

// Macros to support the radio_rx_isr handler.
// These should functionaly match spi.c and are used here to 
// flatten the call tree for the isr due to compiler inefficiency
// by using #pragma interrupt_handler.

#pragma interrupt_handler radio_rx_isr

#if defined (TWO_WAY) || defined (RX_MODE)

#define mSPI_ADDRESS    0x3F
#define bSPI_WRITE      0x80

#define SPI_ISR_RADIO_PUT(address, data)                              \
{                                                                     \
    RADIO_PORT &= ~nSS;                                               \
    SPIM_1_TX_BUFFER_REG = (((address) & mSPI_ADDRESS)| bSPI_WRITE);  \
    while(!(SPIM_1_CONTROL_REG & SPIM_1_SPIM_SPI_COMPLETE));          \
    SPIM_1_TX_BUFFER_REG = (data);                                    \
    while(!(SPIM_1_CONTROL_REG & SPIM_1_SPIM_SPI_COMPLETE));          \
    RADIO_PORT |= nSS;                                                \
}

#define SPI_ISR_RADIO_GET(address, data)                              \
{                                                                     \
    RADIO_PORT &= ~nSS;                                               \
    SPIM_1_TX_BUFFER_REG = ((address) & mSPI_ADDRESS);                \
    while(!(SPIM_1_CONTROL_REG & SPIM_1_SPIM_SPI_COMPLETE));          \
    SPIM_1_TX_BUFFER_REG = 0xff;                                      \
    while(!(SPIM_1_CONTROL_REG & SPIM_1_SPIM_SPI_COMPLETE));          \
    RADIO_PORT |= nSS;                                                \
    data = SPIM_1_RX_BUFFER_REG;                                      \
}

#define SPI_ISR_RADIO_OFF()                                           \
{                                                                     \
    RADIO_ISR_DISABLE();                                              \
    SPI_ISR_RADIO_PUT(REG_CONTROL, 0)                                 \
}

#endif

// These globals are set by radioIsr
UINT8 gChannelBytes = 0;
UINT8 gChannelEof = 0;
UINT8 gOverFlow = 0;

#if defined (TWO_WAY) || defined (RX_MODE)
UINT8 gChannelValid[LS_RX_PACKET_LEN];
#endif

SYS_PARAMETERS sysParams;

static UINT8 gLastChannel = 0xFF;

const UINT8 radio_initData[] =
{
    REG_CONTROL, 0,
    REG_DATA_RATE, RADIO_MODE,
    REG_CONFIG, bIRQ_ACTIVE_HIGH, 
    REG_THOLD_L, THRESHOLD_L,
    REG_THOLD_H, THRESHOLD_H,
    REG_XTAL_ADJ, (bCLOCK_DISABLE),
    REG_PA, (PA_BIAS & mPA_BIAS),
    REG_RX_INT_EN, (bRX_FULL_A | bRX_EOF_A),
    REG_TX_INT_EN, (bTX_EMPTY), 
    REG_SERDES_CTL, (bSERDES_ENABLE | (mEND_OF_FRAME_LEN & EOF_BITS)),
    REG_VALID_TX, 0xFF,
    REG_ANALOG_CTL, (bAGC_DISABLERSSI_CTL | bPACTL_EN),
    REG_AGC_CTL, bAGC_OFF,
    REG_SYN_LOCK_CNT, SYNTH_SETTLE_COUNT, // wait for the synth to settle
    REG_CLOCK_ENABLE, 0x41, // set per datasheet
    REG_CLOCK_MANUAL, 0x41, // set per datasheet
    REG_VCO_CAL, bMINUS5_PLUS5 // use the laser trimmed VCO value
};

const UINT8 pnCodeTable[] = 
{
    0x6A, 0xE7, 0x01, 0xEA, 0x03, 0xFD, 0x13, 0xD2, 
    0xDC, 0xC0, 0x6B, 0xB8, 0x2B, 0x09, 0xBB, 0xB2, 
    0xA3, 0x1E, 0xF2, 0xA4, 0x31, 0x32, 0x7A, 0xB3, 
    0x44, 0x83, 0x3B, 0xDD, 0x14, 0xCF, 0x8E, 0xC9, 
    0x35, 0x35, 0x4E, 0xC5, 0xF3, 0x52, 0x47, 0xB0, 
    0x7C, 0x23, 0x8A, 0xCE, 0x45, 0x5C, 0x54, 0xD7, 
    0x81, 0xAC, 0xFB, 0x83, 0x7A, 0x9A, 0x61, 0xAC, 
    0x3C, 0x12, 0x5F, 0x9C, 0x39, 0x98, 0xF6, 0x8A, 
//    0x99, 0x29, 0xE5, 0x96, 
};



///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_init
//
//  Description: Reset and initialize the LS radio
//
//  Inputs:      Void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_init()
{
    UINT8 i;
    UINT8 temp;

    SPI_RADIO_ON();

    // load the configuration data
    for(i = 0; i < sizeof(radio_initData); i+=2)
    {
        temp = radio_initData[i];
        SPI_        SPI_RADIO_PUT(radio_initData[i]temp , radio_initData[i+1]);
    }
    
    // use the laser trimmed VCO value 
    SPI_RADIO_PUT( REG_VCO_CAL, bMINUS5_PLUS5 );
    
    gChannelBytes = 0;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_receive_on
//
//  Description: Set up the radio to receive
//
//  Inputs:      Void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_receive_on(UINT8 channel)
{
    RADIO_ISR_DISABLE();
    
    // clear the Radio control register
    if (channel != gLastChannel)
    {
        gLastChannel = channel;
        SPI_RADIO_PUT(REG_CHANNEL, (mCHANNEL & (channel + CHANNEL_OFFSET)));
    }

    SPI_RADIO_GET(REG_DATA_RX_A);

    gChannelBytes = 0;
    gOverFlow     = 0;
    gChannelEof   = 0;  

#if defined (TWO_WAY) || defined (RX_MODE)
    gChannelValid[0]    = 0; 
    rxPacket.first.byte = 0xff0xFF;
#endif

    SPI_RADIO_PUT(REG_CONTROL, (bRX_ENABLE | bAUTO_SYNTH_COUNT));

    RADIO_ISR_ENABLE();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_switch_rxtransmit_on
//
//  Description: Switch Set up the radio to receivetransmit
//
//  Inputs:      Void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_switch_rx(voidtransmit_on()
{ 
    RADIO_ISR_DISABLE();
    
    SPI_RADIO_GET(REG_DATA_RX_A);

    gChannelBytes = 0;
    gOverFlow     = 0;
    gChannelEof   = 0;  

#if defined (TWO_WAY) || defined (RX_MODE)
    gChannelValid[0]    = 0;                    
    rxPacket.first.byte = 0xff;
#endif

    SPI_RADIO_PUT(REG_CONTROL, (bRX_ENABLE | bAUTO_SYNTH_COUNT));   
    
    RADIO_ISR_ENABLE();
    SPI_RADIO_PUT(REG_CONTROL, (bTX_ENABLE | bAUTO_SYNTH_COUNT));    
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_transmit_onset_channel
//
//  Description: Set up the radio to transmitchannel
//
//  Inputs:      Voidchannel
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_transmit_onset_channel(UINT8 channel)
{
    RADIO_ISR_DISABLE();
    
    // clear the radio control bits
    if (channel != gLastChannel)
    {
        gLastChannel = channel;
        SPI_RADIO_PUT(REG_CHANNEL, (mCHANNEL & (channel + CHANNEL_OFFSET)));
    }

    SPI_RADIO_PUT(REG_CONTROL, (bTX_ENABLE | bAUTO_SYNTH_COUNT));   
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_switch_tx
//
//  Description: Switch the radio to transmit
//
//  Inputs:      Void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_switch_tx()
{
    RADIO_ISR_DISABLE();
       
    SPI_RADIO_PUT(REG_CONTROL, (bTX_ENABLE | bAUTO_SYNTH_COUNT));   
}
    
///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_off
//
//  Description: Turn off the radio Transmitter
//
//  Inputs:      Void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////
    
void radio_off()
{
    RADIO_ISR_DISABLE();
    
    // turn off tx and rx
    SPI_RADIO_PUT(REG_CONTROL, (0));
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_set_pn_code
//
//  Description: Load the Channel Access Code based on the PN Code index,
//               By convention, the index must be an even number.
//
//  Inputs:      pnCodeIndex - index into the PN Code table, must be an even number
//                             even number
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////
void radio_set_pn_code(int pnCodeIndex)
{
    UINT8 i;

    if( pnCodeIndex > NUM_PNCODES - 1 )
#ifdef DEBUG
    if( pnCodeIndex >= NUM_PNCODES)
    {
        pnCodeIndex = NUM_PNCODES - 1;
    }       
#endif //DEBUG

    for(i = 0; i < 8; i++)
    for(i = 0; 7 >= i; i++)
    {
        SPI_RADIO_PUT(REG_PN_CODE+i, pnCodeTable[(pnCodeIndex*8)+i]);
    }
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_transmit
//
//  Description: Send a packet to the radio
//
//  Inputs:      len     - length of packet
//              *data    - pointer to the packet
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_transmit(UINT8 len, UINT8 *data)
{
    UINT8 i;
    UINT8 counter;

    SPI_RADIO_PUT(REG_TX_INT_EN, bTX_EMPTY);

    // send the packet
    for(i = 0; i < len; ++i, ++data) 
    {
        counter = 0;
        while(!LS_IRQ_ASSERTED)
        {
            if( counter++ > 120 ) break;  // dead man timeout, normal count 27-30        
        }
        for (counter = 0; (counter < DEADMAN_MAX_COUNT) && (!LS_IRQ_ASSERTED); 
             counter++); //dead man timeout

        SPI_RADIO_PUT(REG_DATA_TX, *data);
    }

    // enable the EOF interrupt and disable the EMPTY interrupt
    SPI_RADIO_PUT(REG_TX_INT_EN, bTX_EOF);

    counter = 0;
    
    TIMER_DELAY_50_USEC();
    TIMER_DELAY_50_USEC();
    
    while(!LS_IRQ_ASSERTED)
    {
        if( counter++ > 120 ) 
        {
     for (counter = 0; (counter < DEADMAN_MAX_COUNT) && (!LS_IRQ_ASSERTED); 
            break;  // counter++); //dead man timeout   
        }    
    }

    SPI_RADIO_PUT(REG_CONTROL, (0));
    SPI_RADIO_GET(REG_TX_INT_STAT);
}

#ifdef SLEEP_ENABLED

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_wakeup
//
//  Description: Turn off the LS radio to conserve power
//
//  Inputs:      void
//
//  Returns:     nothing
//            
//
///////////////////////////////////////////////////////////////////////////////
void radio_wakeup(void)
{   
    // Turn high-z back on for MISO
    PRT1DM1 = PORT_1_DRIVE_1;

    // Power up radio
    RADIO_PORT |= nPD;

    TIMER_DELAY_MSEC( 3RADIO_WAKEUP_TIME );  
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_sleep
//
//  Description: Turn off the LS radio to conserve power
//
//  Inputs:      void
//
//  Returns:     nothing
//            
//
///////////////////////////////////////////////////////////////////////////////
void radio_sleep(void)
{
    // Power down radio
    RADIO_PORT &= ~nPD;

    // Turn on pull up for MISO to reduce current
    PRT1DM1 = PORT_1_DRIVE_1 & ~MISO_MASK;
}

#endif // SLEEP_ENABLED

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_rx_isr
//
//  Description: Process the radio interrupt
//
//  Inputs:      void
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void radio_rx_isr()
{
#if defined (TWO_WAY) || defined (RX_MODE)

    UINT8 irqSource, data, valid;
    
    // poll for a Radio Module interrupt, interrupts are self clearing
    // when the appropiate status register is read 
    while(LS_IRQ_ASSERTED)
    while( LS_IRQ_ASSERTED )
    {   
        // read the Radio Rx Interrupt register
        irqSource = SPI_RADIO_GET(REG_RX_INT_STAT);
        SPI_ISR_RADIO_GET(REG_RX_INT_STAT, irqSource);
        
        if ((irqSource & 0x0f) 0x0F) == 0) 
        {
            break;
        }

        if(irqSource & bRX_FULL_A)
        {
            data  = SPI_RADIO_GET(REG_DATA_RX_A);
            SPI_ISR_RADIO_GET(REG_DATA_RX_A, data);
            
            // don't read the valid register if it is all valid
            if( irqSource & bRX_VALID_A )
            {
                valid = 0xFF;
            }
            else
            {
                valid = SPI_RADIO_GET(REG_VALID_RX_A);
                SPI_ISR_RADIO_GET(REG_VALID_RX_A, valid);
            }
        
            // filter out bad bytes and don't overwrite the globals
            if( (0x0F < valid > 0x0f) && (gChannelEof != 1) )
            {
                #ifdef QUICK_RADIO_OFF        // Power Savings Initiative
                if (((data & 0xF0) == 0x50) && (gChannelBytes == (ACK_LEN-1))) {
                {
                    gChannelEof = 1;    
                    SPI_ISR_RADIO_ISR_DISABLEOFF();
                    SPI_RADIO_PUT(REG_CONTROL, (0));
                }
                #endif

                if (gChannelBytes < LS_RX_PACKET_LEN)
                {
                    *((UINT8 *) (&rxPacket.first.byte) + gChannelBytes) = data;
                    gChannelValid[gChannelBytes]  = valid;                    
                    gChannelBytes++;
                }
                else
                {
                    gOverFlow = 1;
                }
            }
        }
        
        if(irqSource & bRX_EOF_A)
        {               

            if( gOverFlow == 0 )
            {
                // only handle good packets
                if (gChannelBytes != 0) 
                {
                    gChannelEof = 1;    
                    #ifndef SPI_ISR_RADIO_DEFAULT_ON        // Power Savings InitiativeOFF();
                    RADIO_ISR_DISABLE(); 
                    #endif
                    #ifndef RADIO_DEFAULT_ON        // Power Savings Initiative
                    SPI_RADIO_PUT(REG_CONTROL, (0));
                    #endif
                }   
            }
            else // overflow packet, dump it
            {
                gOverFlow = 0;
                gChannelBytes = 0;
            }
        }   
    }   //    }    // while(LS_IRQ_ASSERTED)

#endif // TWO_WAY
}       


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    radio_get_id
//
//  Description: Read the radio ID registers
//
//  Inputs:      id byte number
//
//  Returns:     register value
//            
//
//////////////////////////////////////////////////////////////////////////////
UINT8 radio_get_id( UINT8 id )
{
    UINT8 mid;
    
    // enable the Radio ID registers
    SPI_RADIO_PUT( REG_ANALOG_CTL, bAGC_DISABLE | bPACTL_EN | bMFG_ID_EN );
    
    // read the selected Radio ID register
    mid = SPI_RADIO_GET( REG_MFG_ID_1 + id );
    
    // disable the Radio ID registers
    SPI_RADIO_PUT( REG_ANALOG_CTL, bAGC_DISABLE | bPACTL_EN );

    return (mid);
}