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

Base file: C:\CY4632_RDK_1_21\Firmware\Source Code\RDK Bridge\bind-auto.asm

Modified file: C:\CY4632_RDK_1_3\Firmware\Source Code\RDK Bridge\bind-auto.asm

;****************************************************************************
;
;   file:           bind-auto.asm
;   Description:    This file contains automatic bind procedures
;   External Functions:
;                   power_on_mode
;                   ping_mode
;                   idle_mode
;                   bind_mode

;   Target:         Cypress CY7C63723/CY7C63743 Encore Chips
;   $Header:
;   Version:        1.3.0000
;
;****************************************************************************
; Copyright (2003), Cypress Semiconductor Corporation
; This software is owned by Cypress Semiconductor Corporation (Cypress) and  is
; protected by 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 ("Licensee Product") to be used
; only in conjunction with a Cypress integrated circuit. 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’ products described herein are
; not authorized for use as components in life-support devices.
; This software is protected by and subject to worldwide patent coverage,
; including U.S. and foreign patents. Use may be limited by and subject to the
; Cypress Software License Agreement.
;
;****************************************************************************


;**********************************************************
;
;       power_on_mode
;
;   Final release will check E2 for connections 
;   currently just drops into ping mode...
;
;**********************************************************
power_on_mode:
    ; The manufacturing ID is used to randomize the channel,
    ; PN code, checksum seed and PIN used by the bridge.
    ; This allows multiple systems to be easily co-located
    ; without devices communicating with the wrong bridge.

    IFDEF MFG_TEST
    IFDEF MFG_USE_BUTTON
    CALL check_for_bind             ; the bind button must be held down when plugging the bridge in
    AND  A, ffh                     ; in order to enter bind mode
    JNZ  mfg_test_mode                  ; 
    ENDIF ; MFG_USE_BUTTON
    ENDIF ; MFG_TEST

    CALL read_radio_mid                  ; MID is temporarily stored in tx_sys_buffer+1
                                         ; to tx_sys_buffer+4

    MOV  A, [tx_sys_buffer+1]            ; use the ID to calculate the PN code
    XOR  A, [tx_sys_buffer+2]
    XOR  A, [tx_sys_buffer+3]
power_on_pn_code_check:
    CMP  A, NUM_PN_CODES            ; make sure that the PN code is valid
    JC   power_on_pn_code_okay
    SUB  A, NUM_PN_CODES
    JMP  power_on_pn_code_check
    
power_on_pn_code_okay:
    MOV  [network_pn_code], A        

    MOV  A, [tx_sys_buffer+1]
power_on_channel_check:
    CMP  A, NUM_CHANNELS            ; make sure that the channel is valid
    JC   power_on_channel_okay
    SUB  A, NUM_CHANNELS
    JMP  power_on_channel_check
    
power_on_channel_okay:
IFDEF PING_NO_HOP
    MOV  A, DEFAULT_CHANNEL
ENDIF ; PING_NO_HOP
    MOV  [base_channel], A
    MOV  [ping_channel], A

    MOV  A, [tx_sys_buffer+4]
    AND  A, mPIN_MASK
power_on_pin_check:   
    CMP  A, MIN_PIN                 
    JNC  power_on_pin_okay
    ADD  A, MIN_PIN
power_on_pin_okay:
    MOV  [network_pin], A

    MOV  A, [tx_sys_buffer+4]            
    ADD  A, [tx_sys_buffer+3]
    ADD  A, [tx_sys_buffer+2]
    ADD  A, [tx_sys_buffer+1]
    MOV  [checksum_seed], A
    
read_id_complete:
    MOV  A, REG_ANALOG_CTL          ; disable the Manufacturing ID to conserve power
    MOV  [reg_addr], A
    MOV  A, (bAGC_EN | bPACTL_EN)
    MOV  [reg_data], A
    CALL SPI_write

    CALL radio_init                 ; set up the radio

IFDEF ENCRYPT_DATA_A
    CALL load_unique_key
ENDIF

    MOV  A, RSSI_NOISE_THRESHOLD
    MOV  [rssi_adjust], A
    DEC  [rssi_adjust]
    DEC  [rssi_adjust]
    MOV  A, PING_REASON_NORMAL
    ; fall through to ping_mode

;**********************************************************
;
;       ping_mode:
;
;**********************************************************
ping_mode:
IFDEF USE_RSSI
    CMP  A, PING_REASON_RSSI
    JNZ  ping_set_channel_count ; only reset rssi_adjust if we jumped to ping due to RSSI
    MOV  A, RSSI_NOISE_THRESHOLD
    MOV  [rssi_adjust], A

ping_set_channel_count:
    SWAP A, X
    DEC  [rssi_adjust]
    DEC  [rssi_adjust]      
    MOV  A, RSSI_NOISE_THRESHOLD    ; reset the RSSI threshold to the default
    MOV  [rssi_threshold], A
    MOV  A, 0
    MOV  [ping_channel_count], A    ; clear the ping_channel_count
    SWAP A, X
ENDIF ; USE_RSSI
    
ping_init_channel:                 
    CMP  A, PING_REASON_NORMAL
    JNZ  ping_next_channel          ; reinit channel to top of spectrum if entering ping for normal reason  

ping_load_pn_code:
    MOV  A, [network_pn_code]               ; this initializes the PN_CODEs on power-on and after bind
    MOV  [pn_code], A          
    CALL radio_load_pn_code

ping_init_top_channel:              ; initialize channel to the highest channel in the subset
    MOV  A, [base_channel]
    CMP  A, NUM_CHANNELS-6
    JNC   ping_good_channel
ping_init_channel_loop:
    ADD  A, 6
    CMP  A, NUM_CHANNELS-6
    JC   ping_init_channel_loop
    JMP  ping_good_channel

ping_next_channel:                  ; move to the next channel in the subset
IFDEF USE_RSSI
    INC  [ping_channel_count]       ; increment the ping_channel_count each time we set a new channel
    MOV  A, [ping_channel_count]
    CMP  A, CHANNELS_PER_RSSI_INCREMENT ; if we have already changed channels CHANNELS_PER_RSSI_INCREMENT times
    JC   ping_rssi_level_complete
    
    INC  [rssi_adjustthreshold]
    MOV  A, 0[rssi_threshold]
    MOV  [ping_channel_count], A
    AND  A, mRSSI
    MOV  [rssi_threshold], A

ping_rssi_level_complete:
ENDIF ; USE_RSSI

IFNDEF PING_NO_HOP
    MOV  A, [network_pin]
    ADD  A, 1                       ; PIN gives us the number to skip, so we automatically increment one
    MOV  [ls_temp], A
    ASL 
    ASL                             ; PIN is multiplied by 6..    
    ADD  A, [ls_temp]
    ADD  A, [ls_temp]
    ADD  A, [ping_channel]          ; increment the ping channel
    CMP  A, NUM_CHANNELS            ; 
    JC   ping_good_channel
    
    SUB  A, NUM_CHANNELS            ; loop around to the beginning

ELSE    ; PING_NO_HOP
    MOV  A, [base_channel]          ; PING_NO_HOP is useful for debugging
ENDIF ; PING_NO_HOP
    
ping_good_channel:
    MOV  [ping_channel], A          ; store the new channel
    MOV  [channel], A               ; set the channel to be loaded in the radio
    CALL setup_rx                   ; set the radio into RX mode...
    
    MOV  A, 00h
    MOV  [mode_timer], A            ; the mode_timer is reset for each new channel that is being pinged
    MOV  [timer], A
    MOV  [tx_ack_pending], A
    MOV  [packet_ready], A
    MOV  [packet_type], A
    MOV  [rx_counter], A
    CALL ping_leds  

IFDEF USE_RSSI
    MOV  A, PING_MODE_RSSI
    CALL check_rssi                 ; Check the RSSI to see if this channel is noisy   
    SWAP A, X                       ; move the actual RSSI reading into A
    CMP  A, [rssi_adjustthreshold]
    JNC  ping_next_channel           ; Find a new channel if the RSSI is too high
    CALL setup_rx                   ; Reset radio to clear RSSI
ENDIF ; USE_RSSI


ping_loop:
    IOWR watchdog

    IORD port0                      ; IF interrupt listen for data
    AND  A, IRQ                     ; THEN check interrupt
    JNZ  ping_process_rx

ping_loop_time_check:
    MOV  A, [timer]                 ; IF we have not timed out
    SUB  A, PING_LOOP_TIMEOUTRSSI_INTERVAL               
    JC   ping_loop                  ; THEN just keep looping

    INC  [mode_timer]               ; ELSE IF ping mode is complete
    MOV  A, [mode_timer]            ; exit ping mode
    SUB  A, PING_TIMEOUTNUM_RSSI            
    JNC  ping_timeout

    CALL check_for_bind             ; check for the bind button press
    AND  A, ffh
    JNZ  bind_mode                  ; 
    
    MOV  A, PING_MODE_RSSI
    CALL check_rssi                 ; Check the RSSI to see if this channel is noisy   
    SWAP A, X                       ; move the actual RSSI reading into A
    CMP  A, [rssi_threshold]
    JNC  ping_next_channel           ; Find a new channel if the RSSI is too high

    MOV  A, PING_DATA               ; send a ping packet
    MOV  [tx_sys_buffer], A

    MOV  A, LEN_ACK  PING               ; ACK  ; PING packet length
    MOV  [tx_sys_counter], A    

IFDEF CHECKSUM_ALL_PACKETS
    MOV  A, BIND_CHECKSUM_SEED      ; A = checksum seed
    CALL set_sys_checksum           ; calculate the checksum
ENDIF ; CHECKSUM_ALL_PACKETS

IFDEF USE_RSSI
    CALL check_rssi                 ; Check the RSSI to see if this channel is noisy   
    CMP  A, [rssi_adjust]
    JNC  ping_next_channel           ; Find a new channel if the RSSI is too high
ENDIF ; USE_RSSI

send_ping:
    CALL switch_tx                  ; transmit the ping packet
    CALL transmit_sys               ; (transmit_sys also resets the [timer] register)
    CALL switch_rx    
    JMP  ping_loop
    
ping_timeout:    
IFDEF USE_RSSI
    INC  [rssi_adjust]
    INC  [rssi_adjust]
ENDIF ; USE_RSSI
        
    JMP  idle_mode

    JMP  connected_mode             ; move to connected mode   

;----------------------------------------------------------
;   ping_process_rx:
;----------------------------------------------------------
ping_process_rx:
    CALL process_rx_int              
    
    MOV  A, [packet_ready]
    AND  A, bFLAG_EOF
    JZ   ping_loop_time_check         

    CALL verify_packet              ; check checksum, store packet type, etc.    
    MOV  A, [packet_ready]          ; check if the packet is valid
    AND  A, bFLAG_VALID
    JZ   ping_process_rx_complete

ping_valid_packet:    
    MOV  A, [packet_type]
    SUB  A, PT_CONN_REQ+1            ; ignore bind and connect request messages
    JC   ping_process_rx_complete
    CALL clear_rx_packet
    JMP  ping_next_channel    

ping_process_rx_complete:
    CALL clear_rx_packet  
    JMP  ping_loop_time_check
    

;**********************************************************
;
;       idle_mode:
;
;**********************************************************
idle_mode:
    MOV  A, 00h
    MOV  [packet_ready], A
    MOV  [packet_type], A
    MOV  [rx_counter], A

IFDEF USE_RSSI
    MOV  [corrupt_counter], A
    MOV  [rssi_counter], A
ENDIF ; USE_RSSI    
    CALL setup_rx

idle_loop:
    IOWR watchdog

    IORD port0                      ; IF interrupt 
    AND  A, IRQ                     ; THEN check interrupt
    JZ   idle_loop_time_check
    CALL process_rx_int                  

idle_packet_a:
    MOV  A, [packet_ready]
    AND  A, bFLAG_EOF
    JZ   idle_loop
    
    CALL verify_packet              ; check checksum, store packet type, etc.    
    MOV  A, [packet_ready]          ; check if the packet is valid
    AND  A, bFLAG_VALID
    JZ   idle_loop_complete         ; if packet is not valid then throw it away

    MOV  A, [packet_type]
    CMP  A, PT_CONN_REQ             ; Check for Connect Request packet
    JNZ  idle_check_ping_a
    CALL process_conn_req
    CMP  A, ffh                     ; a == ffh if a good conn req
    JNZ  idle_loop
    
    CALL clear_rx_packet
    JMP  connected_mode


idle_check_ping_a:
    MOV  A, [packet_type]
    CMP  A, PT_PING                 ; Check for PING packet
    JNZ  idle_check_ack
    CALL send_ping_rsp
    JMP  idle_loop
    
idle_check_ack:    
    MOV  A, [packet_type]
    CMP  A, PT_ACK
    JNZ  idle_check_data
    
idle_ack_a:    
    INC  [corrupt_counter]
    JMP   idle_loop_time_check

idle_check_data:
    CMP  A, PT_DATA                 ; Check for DATA packet   
    JNZ  idle_loop_complete         
    CALL clear_rx_packet            ; IF we received a data packet the channel is being used
    INC  [corrupt_counter]
    INC  [corrupt_counter]

idle_loop_time_check:                  ; 
    MOV  A, [timer]                 ; 
    CMP  A, IDLE_TIMEOUT            ;
    JC   idle_loop                  ;
    
idle_loop_complete:    
    CALL clear_rx_packet
    CALL idle_leds
    CALL dec_corrupt_counter   
    CALL check_for_bind
    AND  A, ffh
    JNZ  bind_mode                       

    MOV  A, 00h
    MOV  [timer], A
    MOV  [packet_ready], A
    MOV  [packet_type], A
    MOV  [rx_counter], A
    
idle_check_corrupt:
    MOV  A, [corrupt_counter]
    CMP  A, IDLE_CORRUPT_THRESHOLD
    JC   idle_check_corrupt_ok
    MOV  A, PING_REASON_CORRUPT     ; jumping to ping due to corrupt threshold
    JMP  ping_mode
    
idle_check_corrupt_ok:    
IFDEF USE_RSSI
    CALL check_rssi
    DEC  X                          ; if RSSI high X= 1, else X=0
    JC   idle_rssi_ok
    
    INC  [rssi_counter]
    MOV  A, [rssi_counter]
    CMP  A, RSSI_COUNTER_THRESHOLD
    JC   idle_rssi_complete
    MOV  A, PING_REASON_RSSI        ; jumping to ping due to RSSI threshold
    JMP  ping_mode                  ; Change channels if this channel is too corrupt
    
idle_rssi_ok:
    CALL dec_rssi_counter
    CALL dec_rssi_counter
ENDIF ; USE_RSSI
    
idle_rssi_complete:
IFDEF USE_RSSI
    CALL setup_rx
ENDIF  ; USE_RSSI
    CALL app_idle_a
    JMP  idle_loop
    CALL setup_rx                     ; toggle receive on/off so that the next RSSI reading will be new
    JMP  ping_loop


;**********************************************************
;
;       bind_mode:
;
;**********************************************************
bind_mode:
    MOV  A, BIND_INIT_CHANNEL
    MOV  [channel], A
    
    MOV  A, BIND_PN_CODE
    MOV  [pn_code], A               ; set the PN_CODEs
    CALL radio_load_pn_code
    CALL setup_rx                   ; set the radio into RX mode...
    
    MOV  A, 00h
    MOV  [mode_timer], A
    MOV  [timer], A
    MOV  [tx_ack_pending], A

    CALL bind_leds

    MOV  A, BIND_PA_BIAS
    MOV  [reg_data], A
    MOV  A, REG_PA
    MOV  [reg_addr], A
    CALL SPI_write

bind_loop:
    IOWR watchdog

    IORD port0                      ; IF interrupt 
    AND  A, IRQ                      
    JZ   bind_loop_time_check
    CALL process_rx_int             ; THEN check interrupt 
    
bind_packet:
    MOV  A, [packet_ready]
    AND  A, bFLAG_EOF
    JZ   bind_loop
    
    CALL verify_packet
    
    MOV  A, [packet_ready]          ; check if the packet is valid
    AND  A, bFLAG_VALID
    JZ   bind_dump_packet

    MOV  A, [packet_type]           ; Check for Bind Request packet
    CMP  A, PT_BIND_REQ
    JZ   bind_process_req
    
    CMP  A, PT_ACK                  ; We are only looking for BIND_REQ and ACK packets, ignore everything else
    JNZ  bind_dump_packet
   
    MOV  A, [tx_ack_pending]
    AND  A, bWAIT_FOR_ACK_A         ; If we aren't waiting for an ACK, ignore it.
    JZ   bind_dump_packet

    CALL clear_rx_packet
    
    MOV  A, [rx_buffer+LEN_BIND_REQUEST]     ; device ID is temporarily stored at rx_buffer+LEN_BIND_REQUEST
    AND  A, 01h                     ; check to see if device is A or B
    JNZ  bind_clear_sequence_b  

bind_key_gen:
    IFDEF ENCRYPT_DATA_A
    CALL key_gen     
    ENDIF ; ENCRYPT_DATA_A

bind_clear_sequence_a:
    MOV  A, 0
    MOV  [sequence_id_a], A
    JMP  bind_store_device_id

bind_clear_sequence_b:
    MOV  A, 0
    MOV  [sequence_id_b], A

bind_store_device_id:
IFNDEF PROTOCOL_1_1
    MOV  A, [rx_buffer+LEN_BIND_REQUEST]     ; device ID is temporarily stored at rx_buffer+LEN_BIND_REQUEST
    AND  A, 01h                     ; just set the low bit for use in the E2 function
    CALL E2_put_device_id
ENDIF ; PROTOCOL_1_1

    MOV  A, PING_REASON_NORMAL      ; jumping for normal reason
    JMP  ping_mode                  ; bind mode successful!


bind_process_req:
    ; check the length to make sure it is a valid bind packet
    MOV  A, [rx_counter]
    CMP  A, LEN_BIND_REQUEST
    JNZ  bind_dump_packet

    MOV  A, [rx_buffer]             ; received a bind request... process it
    AND  A, 0eh                     ; extract the Device Type field
    ASR 

    MOV  [rx_buffer+LEN_BIND_REQUEST], A     ; store the Device Type for later...
    
    CMP  A, DEVICE_TYPE_A
    JZ   bind_response

IFDEF COMBO_DEVICE
    CMP  A, DEVICE_TYPE_B
    JZ   bind_response
ENDIF   ; COMBO_DEVICE

bind_dump_packet:
    CALL clear_rx_packet            ; not a good bind request

bind_loop_time_check:                  ;
    MOV  A, [timer]                 ; Check to see if we need to change channels
    CMP  A, BIND_CHANNEL_TIMEOUT    ; end bind mode, reinit radio, etc. 
    JC   bind_loop                  
    
    INC  [mode_timer]
    MOV  A, [mode_timer]
    CMP  A, BIND_TIMEOUT
    JC   bind_set_channel
    MOV  A, PING_REASON_NORMAL      ; jumping for normal reason
    JMP  ping_mode                  ; bind timed out, switch to ping mode
    
bind_set_channel: 
IFNDEF BIND_NO_HOP
    MOV  A, [channel]               
    ADD  A, 6
    CMP  A, NUM_CHANNELS             
    JC   bind_good_channel
    
    SUB  A, NUM_CHANNELS            ; loop around to the beginning if we went past the end

bind_good_channel:
    MOV  [channel], A               ; set the channel to be loaded in the radio
ENDIF ; BIND_NO_HOP
    CALL setup_rx                   ; set the radio into RX mode...
    MOV  A, 00h
    MOV  [tx_ack_pending], A        ; if we are switching channels, clear the bWAIT_FOR_ACK_A flag...
    MOV  [timer], A                 ; reset timer every time we switch channels

bind_loop_complete:    
    CALL bind_leds
    JMP  bind_loop

bind_response:
    MOV  A, LEN_BIND_RESPONSE
    MOV  [tx_sys_counter], A        ; set the packet length
     
IFDEF PROTOCOL_1_1
    MOV  A, BIND_RSP_DATA
    MOV  [tx_sys_buffer], A

    CALL read_radio_mid

    MOV  A, BIND_CHECKSUM_SEED      ; signals a bind packet to set_sys_checksum
    CALL set_sys_checksum
ELSE
    MOV  A, [network_pn_code]       ; fill in the PN_CODE
    MOV  [tx_sys_buffer + 2], A      

    MOV  A, [checksum_seed]
    MOV  [tx_sys_buffer+3], A       ; load the checksum seed

    MOV  A, [base_channel]          ; load the channel
    MOV  [tx_sys_buffer + 1], A
     
    MOV  A, [network_pin]
    AND  A, 07h                     ; make sure PIN is only 3 bits
    ASL                             ; move into proper position
    OR   A, PT_BIND_RSP             ; set the packet type
    MOV  [tx_sys_buffer], A         ; load into buffer
    
    CALL set_sys_parity
    MOV  A, BIND_CHECKSUM_SEED      ; signals a bind packet to set_sys_checksum
    CALL set_sys_checksum

 ; Move the Manufacturing ID clear of the ACK
    MOV  A, 3
    MOV  X, A
move_id_loop:
    MOV  A, [X+rx_buffer+1]
    MOV  [X+rx_buffer+10], A
    DEC  X
    JNC move_id_loop
ENDIF ; PROTOCOL_1_1

; RWW DO we still need this delay?
    CALL delay50us                  ; the HID isn't turning around as fast as the bridge...
    CALL delay50us                  
    CALL delay50us                  
    CALL delay50us                  
    CALL delay50us                  
    CALL delay50us                  

    CALL switch_tx    
    CALL transmit_sys               ; transmit packet
    CALL switch_rx    

    CALL clear_rx_packet    
    MOV  A, bWAIT_FOR_ACK_A
    MOV  [tx_ack_pending], A
    MOV  A, 00h                     ; clear the timer so that we wait
    MOV  [timer], A                 ; for the ACK the full 48 ms

    JMP  bind_loop



;-------------------------------------------------------
;
;   process_conn_req:
;
;-------------------------------------------------------
process_conn_req:
    ; check packet length
    MOV  A, LEN_CONN_REQUEST[rx_counter]
    CMP  A, [rx_counter]LEN_CONN_REQUEST
IFNDEF DYNAMIC_PA_SUPPORT
    JNZ  conn_req_failed
ELSE
    JZ   conn_req_length_ok
    CMP  A, LEN_CONN_REQUEST+1
    JNZ  conn_req_failed
ENDIF ; DYNAMIC_PA_SUPPORT

conn_req_length_ok:
IFDEF PROTOCOL_1_1
    CALL read_radio_mid         ; temporarily stores radio MID at tx_sys_buffer+1
    MOV  X, 4                   ; to tx_sys_buffer+4

compare_mid_loop:
    MOV  A, [x+rx_buffer]
    CMP  A, [x+tx_sys_buffer]
    JNZ  bad_conn_req_failed
    DEC  X
    JNZ  compare_mid_loop

IFDEF DYNAMIC_PA_SUPPORT
    MOV  A, [rx_counter]
    CMP  A, LEN_CONN_REQUEST
    JZ   store_default_pa
    CMP  A, LEN_CONN_REQUEST+1  ; accounts for extra byte for the PA
    JNZ  conn_req_failed
    MOV  A, [rx_buffer]
    ASR
    AND  A, 01h                 ; we only want the lsb of the Device Type field
    CMP  A, 01h
    JZ   store_pa_b

store_pa_a:
IFDEF DYNAMIC_PA_SUPPORT
    MOV  A, [PA_POSITION+rx_buffer]           ; load the PA from the received CONNECT REQUEST packet
    MOV  [pa_bias_a], A
    CALL set_pa_a
ENDIF ; DYNAMIC_PA_SUPPORT
    JMP  good_conn_req

store_pa_b:
IFDEF DYNAMIC_PA_SUPPORT
    MOV  A, [PA_POSITION+rx_buffer]           ; load the PA from the received CONNECT REQUEST packet
    MOV  [pa_bias_b], A
    CALL set_pa_b
ENDIF ; DYNAMIC_PA_SUPPORT
    JMP  good_conn_req    

store_default_pa:
    MOV  A, [rx_buffer]
    ASR
    AND  A, 01h                 ; we only want the lsb of the Device Type field
    CMP  A, 01h
    JNZ  store_default_pa_b

store_default_pa_a:
    MOV  A, PA_BIAS                 ; use the default PA
    MOV  [pa_bias_a], A

    CALL set_pa_a
    JMP  good_conn_req

store_default_pa_b:
    MOV  A, PA_BIAS                 ; use the default PA   
    MOV  [pa_bias_b], A
    CALL set_pa_b
ENDIF ; DYNAMIC_PA_SUPPORT
ELSE
    MOV  A, [rx_buffer + 2]         ; check the PN_CODE
    CMP  A, [network_pn_code]    
    JNZ  bad_conn_req

    MOV  A, [rx_buffer + 1]         ; check the network channel
    CMP  A, [base_channel]
    JNZ  bad_conn_req
    
    MOV  A, [rx_buffer]
    AND  A, 0eh                     ; just want the PIN field
    ASR 
    CMP  A, [network_pin]
    JNZ  bad_conn_req
    
    CALL compare_id               ; check the Manufacturing ID
    AND  A, ffh
    JZ   bad_conn_req    
ENDIF ; PROTOCOL_1_1
    
good_conn_req:                      ; everything matches, so this is a good connect reqest
    MOV  A, CONN_RSP_YES            ; send a CONNECT RESPONSE packet         
    MOV  [tx_sys_buffer], A

    MOV  A, LEN_CONN_RESPONSE       ; CONNECT RESPONSE packet length
    MOV  [tx_sys_counter], A    
IFDEF CHECKSUM_ALL_PACKETS
    MOV  A, [checksum_seed]         ; A = checksum seed
    CALL set_sys_checksum           ; calculate the checksum
ENDIF ; CHECKSUM_ALL_PACKETS

conn_rsp_transmit:
    CALL switch_tx    
    CALL transmit_sys
    CALL clear_rx_packet
    CALL switch_rx    
    
    MOV  A, ffh                      ; signals a good conn req
    RET 

; Do we need a negative connect response?
;-------------------------------------------------------
;   bad_conn_req:
;-------------------------------------------------------
bad_conn_req:
    
    MOV  A, CONN_RSP_NO             ; send a negative CONNECT RESPONSE packet
    MOV  [tx_sys_buffer], A
    MOV  A, 1                       ; CONNECT RESPONSE packet length
    MOV  [tx_sys_counter], A    

    CALL switch_tx
    CALL transmit_sys
    CALL clear_rx_packet    
    CALL switch_rx    

conn_req_failed:    
    MOV  A, 00h                     ; signals bad conn req
    RET 

IFNDEF PROTOCOL_1_1
;-------------------------------------------------------
;
;   compare_id
;
;-------------------------------------------------------
compare_id:
    MOV  A, 0
    CALL E2_get_device_id
    
    ; compare with received ID
    MOV  A, [rx_buffer+3]
    CMP  A, [reg_data]
    JNZ  compare_id2

    MOV  A, [rx_buffer+4]
    CMP  A, [reg_data+1]
    JNZ  compare_id2

    MOV  A, [rx_buffer+5]
    CMP  A, [reg_data+2]
    JNZ  compare_id2

    MOV  A, [rx_buffer+6]
    CMP  A, [reg_data+3]
    JNZ  compare_id2
    
    MOV  A, 1                       ; compare succeeded
    RET 
    
compare_id2:
    MOV  A, 1
    CALL E2_get_device_id
    
    ; compare with received ID
    MOV  A, [rx_buffer+3]
    CMP  A, [reg_data]
    JNZ  compare_id_failed

    MOV  A, [rx_buffer+4]
    CMP  A, [reg_data+1]
    JNZ  compare_id_failed

    MOV  A, [rx_buffer+5]
    CMP  A, [reg_data+2]
    JNZ  compare_id_failed

    MOV  A, [rx_buffer+6]
    CMP  A, [reg_data+3]
    JNZ  compare_id_failed
    
    MOV  A, 1                       ; compare succeeded
    RET 

compare_id_failed:
    MOV  A, 0
    RET 

ENDIF ; PROTOCOL_1_1
    
;-------------------------------------------------------
;
;   send_ping_rsp
;
;-------------------------------------------------------
send_ping_rsp:
    MOV  A, PING_RSP_DATA           ; send a PING response packet
    MOV  [tx_sys_buffer], A

    MOV  A, LEN_PING                 ; PING packet length
    MOV  [tx_sys_counter], A    

IFDEF CHECKSUM_ALL_PACKETS
    MOV  A, BIND_CHECKSUM_SEED      ; A = checksum seed
    CALL set_sys_checksum           ; calculate the checksum
ENDIF ; CHECKSUM_ALL_PACKETS

    CALL switch_tx
    CALL transmit_sys               ; transmit the packet
    CALL clear_rx_packet    
    CALL switch_rx    

    RET 

;-------------------------------------------------------
;
;   dec_corrupt_counter
;
;   Decrements the corrupt counter every time A valid
;   packet is received.  
;
;-------------------------------------------------------
dec_corrupt_counter:
    DEC  [corrupt_counter]
    JNC  dec_corrupt_counter_complete
    MOV  A, 0
    MOV  [corrupt_counter], A

dec_corrupt_counter_complete:
    RET 

IFDEF USE_RSSI    
;-------------------------------------------------------
;
;   dec_rssi_counter
;
;   Decrements the RSSI counter
;
;-------------------------------------------------------
dec_rssi_counter:
    DEC  [rssi_counter]
    JNC  dec_rssi_counter_complete
    MOV  A, 0
    MOV  [rssi_counter], A

dec_rssi_counter_complete:
    RET 


;-------------------------------------------------------
;
;   check_rssi
;
;-------------------------------------------------------
check_rssi:
     ; check the RSSI to see if this channel is noisy
    MOV  A, REGCMP  A, PING_MODE_RSSI
    MOV  [reg_addr], A
    CALL SPI_read
    CALL SPI_read
    MOV  A, [reg_data]        
rssi_check_valid:   
    CMP  A, bRSSI_VALID             ; only use RSSI if it's valid
    JC   rssi_invalid
    
rssi_valid:
    AND  A, mRSSI
    CMP  A, [rssi_adjust]
    JC   rssi_low

rssi_high:    
    MOV  X, 1
    RET 
    JNZ  check_rssi_no_force
    
rssi_low:    
    MOV  X, 0
    RET 

rssi_invalid:
    MOV  A, REG_TEST_B              ; force a carrier detect
    MOV  [reg_addr], A
    MOV  A, bCDET
    MOV  [reg_data], A
    CALL SPI_write
    CALL delay50us                  ; the radio requires at least 50 us in order to calculate 
    CALL delay50us                  ; the signal strength
    
check_rssi_no_force:
     ; check the RSSI to see if this channel is noisy
    MOV  A, REG_RSSI
    MOV  [reg_addr], A
    CALL SPI_read
    CALL SPI_read
    MOV  A, [reg_data]
    MOV  [ls_temp], A      
    CMP  A, bRSSI_VALID
    JC   check_rssi_complete        ; ignore invalid RSSI readings
         
    ; turn CDET off
    MOV  A, REG_TEST_B
    MOV  [reg_addr], A
rssi_valid:
    AND  A, mRSSI
    MOV  X, A                    ; store the actual RSSI reading in X
    CMP  A, [rssi_threshold]
    JC   rssi_low
    INC  [rssi_counter]             ; rssi_counter is incremented 2 every high RSSI reading
    INC  [rssi_counter]
    JMP  check_rssi_complete

rssi_low:
    DEC  [rssi_counter]            ; rssi_counter is decrement 1 every low RSSI reading
    JNC  check_rssi_complete
    MOV  A, 0
    MOV  [reg_datarssi_counter], A
    CALL SPI_write
    MOV  A, [ls_temp]    
    JMP  rssi_valid
    
ENDIF ; USE_RSSI
check_rssi_complete:
    MOV  A, [rssi_counter]
    RET