Difference Analysis Generated by HtmlDiff on 11/10/2004 5:09 PM  

Base file: C:\CY4632_RDK_1_3\Firmware\Source Code\RDK Mouse\bind.c

Modified file: C:\CY4632_RDK_1_31\Firmware\Source Code\RDK Mouse\bind.c

//--------------------------------------------------------------------------
//
//  Collection of the bind functions for basic, sem-auto, and automatic bind.
//
//--------------------------------------------------------------------------
// $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK MouseKeyboard/bind.c $
// $Modtime: 10/01/04 1:18p6/16/04 2:06p $
// $Revision: 101.22 $
//--------------------------------------------------------------------------
//
// 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 "ls_config.h"
#include "bind.h"
#include "protocol.h"
#include "radio.h"


#ifdef BIND_BASIC

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    protocol_bind_init
//
//  Description: Perform the basic bind channel and PN Code setup
//
//  Inputs:      None
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void protocol_bind_init()   // Bind Basic
{
    // load pnCode define in application header file    
    radio_set_pn_code(sysParams.networkId.pnCode);

    RADIO_SLEEP();
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    bind
//
//  Description: 
//
//  Inputs:      channel, pnCode
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////
void protocol_bind(UINT8 channel, UINT8 pnCode)   // Bind Basic
{
    sysParams.networkId.channel = channel;
    sysParams.networkId.pnCode = pnCode;
}

#endif // BIND_BASIC


#ifdef BIND_AUTO

UINT8  gBindMode = 0;

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    get_next_channel
//
//  Description: Perform the channel selection algorithm. Every sixth channel
//               will be used.
//
//  Inputs:      sysParams global for pid and channel variables
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void get_next_channel(void)
{
    sysParams.networkId.channel += (6 * (sysParams.networkId.pin+1));

    if((NUM_CHANNELS) - 1 < sysParams.networkId.channel)
    {
        sysParams.networkId.channel -= NUM_CHANNELS;    
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    init_channel
//
//  Description: Initialize the channel selection algorithm to the top channel
//               in the channel subset
//
//  Inputs:      None
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void init_channel(void)
{
    sysParams.networkId.channel = sysParams.networkId.baseChannel;

    while (sysParams.networkId.channel < NUM_CHANNELS - 6) 
    {
        sysParams.networkId.channel += 6;
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    protocol_bind_init
//
//  Description: Perform the basic bind channel and pnCode setup
//
//  Inputs:      None
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

void protocol_bind_init()    // Bind Auto
{
    init_channel();

    gBindMode = DISCONNECTED_STATE;

    RADIO_SLEEP();
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    protocol_bind
//
//  Description: Perform the automatic bind function, get the bind parameters,
//               bind to a bridge, connect to the bridge, and then return
//
//  Inputs:      None
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

UINT8 protocol_bind()    // Bind Auto
{
    UINT8  chanTimeout;
    UINT8  rLength;
    UINT8  status = LS_STATUS_SUCCESS;
    UINT8  ackTimeout;    
    UINT8  pktReceived;
    UINT8  txTimeout;
    UINT8  pa_setting;
        
    // Bind Operation
    RADIO_WAKEUP();  
         
    gBindMode = DISCONNECTED_STATE;
    
    // format the bind packet
    txPacket.bind.hdr.type    = BIND_REQUEST; 
    txPacket.bind.hdr.devType = DEVICE_TYPE; 
    txPacket.bind.hdr.parity  = protocol_gen_parity(txPacket.first.byte);
    
    #ifndef PROTOCOL_1_1
    // read the radio ID
    SPI_RADIO_PUT( REG_ANALOG_CTL, (bAGC_RSSI_CTL | bPACTL_EN | bMID_READ_EN ));    

    // read the Radio ID registers
    txPacket.bind.mid1 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_1 );  
    txPacket.bind.mid2 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_2 );  
    txPacket.bind.mid3 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_3 );  
    txPacket.bind.mid4 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_4 ); 

    // disable the Radio ID registers
    SPI_RADIO_PUT( REG_ANALOG_CTL, (bAGC_RSSI_CTL | bPACTL_EN ));

    txPacket.bind.checkSum = 
       protocol_calc_ck_sum((UINT8 *)&txPacket.bind, BIND_REQ_LEN-1, BIND_SEED);

    sysParams.networkId.pin     = 0;
    #endif // PROTOCOL_1_1

    // load the bind pnCode index
    radio_set_pn_code(BIND_PNCODE);
     
    // Read PA setting
    pa_setting = (SPI_RADIO_GET(REG_PA) & mPA_BIAS);

    // load Bind PA
    SPI_RADIO_PUT(REG_PA, BIND_PA);

    // seed the channel algorithm with bind parameters 0,0
    sysParams.networkId.channel = 0;
       
    // send a bind request and wait for response, if no response change
    // the channel and try again
    for( chanTimeout = 0; chanTimeout < BIND_TIMEOUT; chanTimeout++)
    {   
        //setup TX loop control variables
        txTimeout = 0;
        pktReceived = NO_PACKET;

        // setup mode
        radio_set_channel(sysParams.networkId.channel);
        radio_transmit_on();
        
        // loop until ACK radio_received or TX retries exhausted
        while( (pktReceived != BIND_RESPONSE) && 
               (++txTimeout <= BIND_MAX_TRANSMITS) )
        {                           
            radio_transmit_on();
            radio_transmit(BIND_REQ_LEN, (UINT8 *)&txPacket);
            radio_receive_on();

            // wait for Bind Response 
            ackTimeout = 0;                        
            pktReceived = protocol_receive(&rLength);

            while( (pktReceived != BIND_RESPONSE) && 
                   (++ackTimeout < BIND_ACK_TIMEOUT)  )
            {
                TIMER_DELAY_50_USEC();
                pktReceived = protocol_receive(&rLength);
            }

            if (pktReceived != BIND_RESPONSE)
            {
//              radio_off();
                RADIO_SLEEP();
                TIMER_DELAY_MSEC(8);
                RADIO_WAKEUP();
            }
        }
       
        // check for Bind timeout
        if(txTimeout >= BIND_MAX_TRANSMITS)
        {
            // Clear Watchdog and Sleep Timer
            M8C_ClearWDTAndSleep;

            //try the next channel in the subset of channels
            get_next_channel();
        }
        else if( (pktReceived == BIND_RESPONSE) && (rLength == BIND_RESP_LEN) ) 
        {  
            // Good Ack
            
            // send an ACK
            txPacket.first.byte = 0;
            txPacket.ack.hdr.type   = ACK_PACKET;                    
            txPacket.ack.hdr.flag   = GOOD_ACK;
            txPacket.ack.hdr.parity = protocol_gen_parity(
                                      (UINT8) txPacket.first.byte);
              
            #ifdef CHECKSUM_ALL_PACKETS
            txPacket.data.appPacket[0] = 
                protocol_calc_ck_sum((UINT8 *)&txPacket, 1, 
                                     rxPacket.bind.checkSumSeed );
            #endif        

            
            // setup radio_transmit mode
            radio_transmit_on();
            
            // send the ACK to the bind response multiple times to
            // ensure delivery
            radio_transmit(ACK_LEN, (UINT8 *)&txPacket);
            
            radio_transmit_on();
            TIMER_DELAY_50_USEC();
            TIMER_DELAY_50_USEC();          
            TIMER_DELAY_50_USEC();
            TIMER_DELAY_50_USEC();          
            radio_transmit(ACK_LEN, (UINT8 *)&txPacket);
            
            radio_transmit_on();
            TIMER_DELAY_50_USEC();
            TIMER_DELAY_50_USEC();          
            TIMER_DELAY_50_USEC();
            TIMER_DELAY_50_USEC();          
            radio_transmit(ACK_LEN, (UINT8 *)&txPacket);

            #ifndef PROTOCOL_1_1
            // extract the bind parameters and store them        
            sysParams.networkId.pin         = rxPacket.bind.hdr.pin;
            sysParams.networkId.baseChannel = rxPacket.bind.channel;
            sysParams.networkId.channel     = rxPacket.bind.channel;
            sysParams.networkId.pnCode      = rxPacket.bind.pnCode;
            sysParams.networkId.seed        = rxPacket.bind.checkSumSeed;
            #else
            // extract Bridge MID from BIND_RESPONSE 
            // calculate baseChannel, pnCode, etc.
            sysParams.bridgeMid.mid1        = rxPacket.bind.mid1;
            sysParams.bridgeMid.mid2        = rxPacket.bind.mid2;
            sysParams.bridgeMid.mid3        = rxPacket.bind.mid3;
            sysParams.bridgeMid.mid4        = rxPacket.bind.mid4;
            rLength                         = rxPacket.bind.mid4;
            // store sysParams
            #endif // PROTOCOL_1_1

            break; // exit the for loop
        }
        else if( pktReceived == BIND_RESPONSE ) 
        {
            //Failed previous test, bad length
            // reset loop control variable
            pktReceived = NO_PACKET;
        }
        
    }  // for()

    // Restore PA setting
    SPI_RADIO_PUT(REG_PA, pa_setting);
    
    SPI_RADIO_OFF();
    
    // check the results of the while loop
    if(BIND_TIMEOUT - 1 < chanTimeout)
    {
        // can't Bind, start over
        protocol_bind_init();
        
        status = LS_STATUS_FAILED;
    }
    else if(pktReceived == BIND_RESPONSE)   // ack sent OK
    {
        // store parameters in NVRAM
        NVRAM_WRITE( &sysParams );
        
        #ifdef PROTOCOL_1_1
        // calculate channel, PN code, etc. from the Bridge MID
        calculate_network_id();
        #endif // PROTOCOL_1_1
        
        // give the dongle time to ping before trying to reconnect
        TIMER_DELAY_MSEC(BRIDGE_PING_TIME);
        
        init_channel();
        
        status = protocol_reconnect();

        #ifdef ENCRYPT_DATA
        if (status == LS_STATUS_SUCCESS) 
        {
            encrypt_request_key();
        }        
        #endif  // ENCRYPT_DATA
    }

    RADIO_SLEEP();  
        
    return status;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Function:    protocol_reconnect
//
//  Description: Perform the reconnect phase of the automatic bind function.
//               bind to a bridge, connect to the bridge, and then return
//
//  Inputs:      None
//
//  Returns:     Void
//
///////////////////////////////////////////////////////////////////////////////

UINT8 protocol_reconnect()
{
    UINT8  timeout;
    UINT8  rLength;
    UINT8  status;
    UINT8  ackTimeout;    
    UINT8  pktReceived;
    #ifdef DYNAMIC_PA_SUPPORT
    UINT8  pa_setting = mPA_BIAS;
    UINT8  channel_count = 0;
    #endif

        
    if (NUM_CHANNELS - 1 < sysParams.networkId.baseChannel) 
    {
        // Turn off the radio
        SPI_RADIO_OFF();
        RADIO_SLEEP();

        return LS_STATUS_FAILED;
    }
    
    // check for radio resetting due to a glitch on the nReset
    // pin. The TX Valids bit should be 0xFF. If not that value the 
    // radio is corrupted.
    if( SPI_RADIO_GET( REG_VALID_TX ) != 0xFF )
    {
       // reset the radio
       radio_init();
       
    }
    
    // select a channel, send a connect request, and
    // wait for a connect response
    // format the bind packet
    txPacket.connect.hdr.type   = CONN_REQUEST; 
    #ifdef DYNAMIC_PA_SUPPORT
    txPacket.connect.hdr.pin    = protocol_device_type;
    #else
    txPacket.connect.hdr.pin    = sysParams.networkId.pin;
    #endif //DYNAMIC_PA_SUPPORT
    txPacket.connect.hdr.parity = 
        protocol_gen_parity((UINT8) txPacket.first.byte);

    #ifndef PROTOCOL_1_1
    txPacket.connect.channel  = sysParams.networkId.baseChannel; 
    txPacket.connect.pnCode   = sysParams.networkId.pnCode; 

    // read the radio ID
    SPI_RADIO_PUT( REG_ANALOG_CTL, (bAGC_RSSI_CTL | bPACTL_EN | bMID_READ_EN ));    

    // read the radio IDs
    txPacket.connect.mid1 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_1 );  
    txPacket.connect.mid2 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_2 );  
    txPacket.connect.mid3 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_3 );  
    txPacket.connect.mid4 =  SPI_RADIO_GET( REG_MFG_ID_1 + RADIO_ID_4 ); 

    // disable the Radio ID registers
    SPI_RADIO_PUT( REG_ANALOG_CTL, (bAGC_RSSI_CTL | bPACTL_EN ));
    
    #else
    // load Bridge MID from sysParams into the txPacket...
    // do I want to keep the bridge MID in sysParams, or should I move 
    // it somewhere else????
    NVRAM_READ( &txPacket.connect.mid1, 4 );
    #endif

    #ifdef DYNAMIC_PA_SUPPORT
    // Set PA field
    txPacket.connect.pa = (SPI_RADIO_GET(REG_PA) & mPA_BIAS);
    #endif //DYNAMIC_PA_SUPPORT
    
    // calculate check sum
    txPacket.connect.checkSum =
        protocol_calc_ck_sum( (UINT8 *)&txPacket.connect, 
                              CONNECT_REQ_LEN-1, sysParams.networkId.seed );

    // load the bind pnCode index
    radio_set_pn_code(sysParams.networkId.pnCode);
            
    // send a bind request and wait for response, if no response change
    // the channel and try again
    for(timeout=0; timeout<CONNECT_TIMEOUT; timeout++)
    {                
        #ifdef DYNAMIC_PA_SUPPORT
        if (SUBSET_CHANNELS - 1 < channel_count)
        {
            // Clear Channel count
            channel_count = 0;

            // Adjust PA (1,3,5, or 7)
            if (pa_setting == mPA_BIAS0x03)
            {
                pa_setting = 0x10x07;
            }
            else
            {
                pa_setting +-= 2;
            }

            // Change PA setting
            SPI_RADIO_PUT(REG_PA, pa_setting);

            // Set PA field
            txPacket.connect.pa = pa_setting;

            // calculate check sum
            txPacket.connect.checkSum =
                protocol_calc_ck_sum( (UINT8 *)&txPacket.connect, 
                                      CONNECT_REQ_LEN-1, 
                                      sysParams.networkId.seed );
        }
        #endif    // DYNAMIC_PA_SUPPORT

        // setup radio_transmit mode
        radio_set_channel(sysParams.networkId.channel);
        radio_transmit_on();
        radio_transmit(CONNECT_REQ_LEN, (UINT8 *)&txPacket);
        radio_receive_on();

        // wait for Connect Response 
        
        pktReceived = protocol_receive(&rLength);

        for(ackTimeout = 0; (pktReceived != CONN_RESPONSE) && 
              (ackTimeout < CONN_ACK_TIMEOUT); ++ackTimeout )            
        {
            TIMER_DELAY_50_USEC();
            
            pktReceived = protocol_receive(&rLength);
        }
       
        if(pktReceived == CONN_RESPONSE)
        {
            if ((rxPacket.connect.hdr.flag == GOOD_ACK ) &&
                (rLength == CONNECT_RESP_LEN))
            {
                // send an ACK for the connect response
                txPacket.first.byte = 0;
                txPacket.ack.hdr.type   = ACK_PACKET;                    
                txPacket.ack.hdr.flag   = GOOD_ACK;
                txPacket.ack.hdr.parity = protocol_gen_parity(
                                             (UINT8) txPacket.first.byte);
              
                #ifdef CHECKSUM_ALL_PACKETS
                txPacket.data.appPacket[0] = 
                    protocol_calc_ck_sum((UINT8 *)&txPacket, 1, 
                                         sysParams.networkId.seed );
                #endif        

                TIMER_DELAY_50_USEC();
                      
                // setup radio_transmit mode
                radio_transmit_on();                
                                
                radio_transmit(ACK_LEN, (UINT8 *)&txPacket); 
            
                radio_receive_on();
                
                break; // exit the loop
            } 
            else
            {
                // bad response, bump channel
                get_next_channel();            
            }
        }
        else if( CONN_ACK_TIMEOUT - 1 < ackTimeout)
        {
            #ifdef APP_CALLBACK_FUNC
            APP_CALLBACK_FUNC();
            #endif

            // Try a few times on the original channel
            if (ORIGINAL_CHAN_RECONNECT_COUNT < timeout)
            {
                // timeout, bump channel
                get_next_channel();
                
                #ifdef DYNAMIC_PA_SUPPORT
                ++channel_count;
                #endif
            }
        }
    }  // end for(timeout = 0; timeout < CONNECT_TIMEOUT; timeout++)

    // check the result of the while loop
    if(pktReceived == CONN_RESPONSE)
    {
        // exit back to main()
        gBindMode = CONNECTED_STATE;
  
        // return a success status...
        status = LS_STATUS_SUCCESS;
    }
    else if(CONNECT_TIMEOUT - 1 < timeout)
    {
        gBindMode = DISCONNECTED_STATE;
        status = LS_STATUS_FAILED;
    }
    else
    {
        status = LS_STATUS_FAILED;
    }

    SPI_RADIO_OFF();
    RADIO_SLEEP();
   
    return status;
}

#endif // BIND_AUTO