;**************************************************************************** ; ; 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