;**************************************************************************** ; ; file: radio.asm ; Description: This file contains all the procedures necessary to interface ; with the LS radio ; External Functions: ; radio_interface_init ; radio_reset ; radio_init ; radio_idle ; radio_suspend ; radio_resume ; radio_setup_rx ; radio_switch_rx ; radio_setup_tx ; radio_switch_tx ; radio_load_pn_code ; ; 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. ; ;**************************************************************************** ;------------------------------------------------------- ; ; radio_interface_init ; ;------------------------------------------------------- radio_interface_init: MOV A, ffh MOV [port0Shadow], A MOV A, fdh MOV [port1Shadow], A clr_port_1 nPD_R clr_port_0 nRESET set_port_1 PWR_EN clr_port_1 nPD_R set_port_1 DIO0 set_port_0 EnSS set_port_0 EMOSI set_port_0 EMISO set_port_0 ESCLK MOV A, (0h) IOWR port1_mode0 MOV A, (ffh) IOWR port1_mode1 MOV A, P0_MODE_0_DEFAULT IOWR port0_mode0 MOV A, P0_MODE_1_DEFAULT IOWR port0_mode1 CALL delay200us set_port_1 nPD_R ; spi configuration MOV A, ( MODE0 | CPHA) IOWR spi_control set_port_0 nRESET ; bring the radio out of reset RET ;------------------------------------------------------- ; ; radio_init ; ;------------------------------------------------------- radio_init: MOV X, 00h ; reset X radio_loop: IOWR watchdog MOV A, X INC X INDEX radio_table MOV [reg_addr], A MOV A, X INC X INDEX radio_table MOV [reg_data], A CALL SPI_write MOV A, X SUB A, (end_radio_table - radio_table) JC radio_loop IOWR watchdog radio_init_complete: RET ;------------------------------------------------------- ; ; radio_idle ; ; Turns Rx AND Tx off. Called by setup_rx ; ;------------------------------------------------------- radio_idle: MOV A, REG_CONTROL MOV [reg_addr], A MOV A, 00h MOV [reg_data], A CALL SPI_write RET ;------------------------------------------------------- ; ; setup_rx ; ; Sets up the radio for Rx ;------------------------------------------------------- setup_rx: MOV A, REG_CONTROL ; clear REG_CONTROL MOV [reg_addr], A MOV A, 00h MOV [reg_data], A CALL SPI_write MOV A, REG_CHANNEL ; set the channel MOV [reg_addr], A MOV A, [channel] ADD A, CHANNEL_OFFSET AND A, mCHANNEL MOV [reg_data], A CALL SPI_write switch_rx: MOV A, REG_CONTROL MOV [reg_addr], A MOV A, (bRX_ENABLE | bAUTO_SYNTH_COUNT) MOV [reg_data], A CALL SPI_write ; clear RX Interrupts MOV A, REG_RX_INT_STAT MOV [reg_addr], A CALL SPI_read MOV A, REG_RX_DATA_A MOV [reg_addr], A CALL SPI_read RET ;------------------------------------------------------- ; ; setup_tx ; ;------------------------------------------------------- setup_tx: MOV A, REG_CONTROL ; clear REG_BB_CONTROl MOV [reg_addr], A MOV A, 00h MOV [reg_data], A CALL SPI_write MOV A, REG_CHANNEL ; set the channel MOV [reg_addr], A MOV A, [channel] ADD A, CHANNEL_OFFSET AND A, mCHANNEL MOV [reg_data], A CALL SPI_write switch_tx: MOV A, REG_CONTROL MOV [reg_addr], A MOV A, (bTX_ENABLE | bAUTO_SYNTH_COUNT) MOV [reg_data], A CALL SPI_write ; Clear TX Interrupt MOV A, REG_TX_INT_STAT MOV [reg_addr], A CALL SPI_read RET IFDEF AGC_SUPPORT ;------------------------------------------------------- ; ; radio_agc_on ; ;------------------------------------------------------- radio_agc_on: MOV A, [agc_control] CMP A, FFh JZ radio_agc_on_complete MOV A, REG_AGC_CTL MOV [reg_addr], A MOV A, bAGC_ON MOV [reg_data], A CALL SPI_write MOV A, FFh MOV [agc_control], A radio_agc_on_complete: RET ;------------------------------------------------------- ; ; radio_agc_off ; ;------------------------------------------------------- radio_agc_off: MOV A, [agc_control] CMP A, FFh JNZ radio_agc_on_complete MOV A, REG_AGC_CTL MOV [reg_addr], A MOV A, bAGC_OFF MOV [reg_data], A CALL SPI_write MOV A, 00h MOV [agc_control], A radio_agc_off_complete: RET ENDIF ; AGC_SUPPORT ;------------------------------------------------------- ; ; SPI_put ; ;------------------------------------------------------- SPI_put: IOWR spi_data sp_wait_done: IOWR watchdog IORD spi_control AND A, TCMP JZ sp_wait_done MOV A, (MODE0 | CPHA) IOWR spi_control RET ;------------------------------------------------------- ; ; SPI_write ; ;------------------------------------------------------- SPI_write: DI clr_port_0 EnSS MOV A, [reg_addr] OR A, 80h CALL SPI_put MOV A, [reg_data] CALL SPI_put set_port_0 EnSS EI RET ;------------------------------------------------------- ; ; SPI_read ; ;------------------------------------------------------- SPI_read: DI clr_port_0 EnSS MOV A, [reg_addr] AND A, 3fh CALL SPI_put MOV A, 0 ; dummy data CALL SPI_put IORD spi_data MOV [reg_data], A set_port_0 EnSS EI RET ;**************************************************************************** ; radio_suspend ; ; Processing: ; The radio is put into Suspend state ; ;**************************************************************************** radio_suspend : CALL radio_idle ; disable Tx, Rx IFDEF USE_XTL_ADJ MOV A, REG_XTAL_ADJ ; turn off crystal adjust MOV [reg_addr], A MOV A, 00h MOV [reg_data], A CALL SPI_write ENDIF ; USE_XTL_ADJ IFDEF USE_WAKE_INT MOV A, REG_WAKE_EN ; set wake int MOV [reg_addr], A MOV A, bWAKE_EN MOV [reg_data], A CALL SPI_write ENDIF ; USE_WAKE_INT clr_port_1 nPD_R ; power down radio RET ;**************************************************************************** ; radio_resume ; ; Processing: ; The radio is taken out of Suspend state ; ;**************************************************************************** radio_resume : CALL delay200us set_port_1 nPD_R ; power up radio MOV A, F8h ; use the timer to break out of a possible infinite loop MOV [timer], A ; which occurs in radio_clock_valid_loop if the clock ; never became invalid during sleep IFDEF USE_WAKE_INT radio_clock_valid_loop: IORD port0 ; IF interrupt AND A, IRQ ; THEN check interrupt JNZ radio_clock_valid MOV A, [timer] AND A, ffh JNZ radio_clock_valid_loop radio_clock_valid: MOV A, REG_WAKE_STAT MOV [reg_addr], A CALL SPI_read ELSE ; RWW I think we only need to delay 3ms ; Delay 6ms for the radio's clock to settle CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us ENDIF ; USE_WAKE_INT IFDEF USE_XTL_ADJ MOV A, REG_XTAL_ADJ ; turn on crystal adjust MOV [reg_addr], A MOV A, (bCLOCK_DISABLE | (XTL_ADJ & mXTAL_ADJ)) MOV [reg_data], A CALL SPI_write ; xtal adj typically takes 1.8ms CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us CALL delay200us ENDIF ; USE_XTL_ADJ IFDEF USE_WAKE_INT MOV A, REG_WAKE_EN MOV [reg_addr], A MOV A, 0h MOV [reg_data], A CALL SPI_write ENDIF ; USE_WAKE_INT radio_resume_complete: CALL setup_rx RET ;------------------------------------------------------- ; ; radio_load_pn_code ; Loads the desired PN_CODE from the PN_CODE tables into ; the radio. ; ; A: contains PN code index ;------------------------------------------------------- ;IFDEF PN_CODE_64_TABLE radio_load_pn_code: IFDEF PN_CODE_64_TABLE MOV A, [pn_code] CMP A, 32 ; The PN_CODE's are split into two tables, with the JNC pn_code2_prep ; first table containing 32 PN_CODE's. ENDIF ; PN_CODE_64_TABLE ASL ; pn_code is the PN_CODE's position in the ROM table, ASL ; which takes 8 bytes, so multiply by 8 ASL ; to get the position of the first byte of the PN_CODE MOV [ls_temp], A MOV X, 0 pn_code1_move_loop: ; Now that the pn_code is set we can load the PN_CODE into the radio MOV A, X ADD A, REG_PN_CODE MOV [reg_addr], A MOV A, X ADD A, [ls_temp] INDEX pn_code_1_table MOV [reg_data], A CALL SPI_write INC X MOV A, X SUB A, 8 JC pn_code1_move_loop RET IFDEF PN_CODE_64_TABLE pn_code2_prep: ; MOV A, [pn_code] ; pn_code is the PN_CODE's position in the ROM table, SUB A, 32 ; which takes 8 bytes, so first subtract 32 because the ASL ; first 32 PN_CODE's are in the other table, then ASL ; multiply by 8 to get the position of ASL ; the first byte of the PN_CODE MOV [ls_temp], A MOV X, 0 pn_code2_move_loop: MOV A, X ADD A, REG_PN_CODE MOV [reg_addr], A MOV A, X ADD A, [ls_temp] INDEX pn_code_2_table MOV [reg_data], A CALL SPI_write INC X MOV A, X SUB A, 8 JC pn_code2_move_loop RET ENDIF ; PN_CODE_64_TABLE ;------------------------------------------------------- ; ; read_radio_mid ; ;------------------------------------------------------- read_radio_mid: MOV A, REG_ANALOG_CTL ; enable ID MOV [reg_addr], A MOV A, (bAGC_EN | bPACTL_EN | bID_EN) MOV [reg_data], A CALL SPI_write MOV A, REG_MFG_ID+3 MOV [reg_addr], A CALL SPI_read MOV A, [reg_data] MOV [tx_sys_buffer+4], A MOV A, REG_MFG_ID+2 MOV [reg_addr], A CALL SPI_read MOV A, [reg_data] MOV [tx_sys_buffer+3], A MOV A, REG_MFG_ID+1 MOV [reg_addr], A CALL SPI_read MOV A, [reg_data] MOV [tx_sys_buffer+2], A MOV A, REG_MFG_ID MOV [reg_addr], A CALL SPI_read MOV A, [reg_data] MOV [tx_sys_buffer+1], A MOV A, REG_ANALOG_CTL ; disable the ID to conserve power MOV [reg_addr], A MOV A, (bAGC_EN | bPACTL_EN) MOV [reg_data], A CALL SPI_write RET IFDEF DYNAMIC_PA_SUPPORT ;------------------------------------------------------- ; ; set_pa_a and set_pa_b ; ;------------------------------------------------------- set_pa_a: MOV A, [pa_bias_a] JMP set_pa set_pa_b: MOV A, [pa_bias_b] set_pa: AND A, mPA_BIAS MOV [reg_data], A MOV A, REG_PA MOV [reg_addr], A CALL SPI_write RET ENDIF ; DYNAMIC_PA_SUPPORT XPAGEOFF radio_table: db REG_CONTROL, 00h ; TX, RX disable db REG_DATA_RATE, RADIO_MODE ; 32/64 chip PN_CODE, DDR select, etc. (see config.inc) db REG_CONFIG, bCMOS ; CMOS Active high IRQ pin db REG_THOLD_L, THRESHOLD_L ; correlation threshold db REG_THOLD_H, THRESHOLD_H ; correlation threshold IFDEF USE_XTL_ADJ db REG_XTAL_ADJ, (bCLOCK_DISABLE | (XTL_ADJ & mXTAL_ADJ)) ELSE db REG_XTAL_ADJ, (bCLOCK_DISABLE) ENDIF db REG_VCO_CAL, bMINUS5_PLUS5 db REG_PA, (PA_BIAS & mPA_BIAS) db REG_RX_INT_EN, (bRX_EOF_A | bRX_FULL_A) ; only Full AND EOF on channel A db REG_TX_INT_EN, (bTX_EMPTY | bTX_EOF) ; empty A, EOF db REG_SERDES_CTL, (bSERDES_ENABLE | (mEND_OF_FRAME_LEN & EOF_BITS)) db REG_TX_VALID, FFh ; ALL valid bits (we are transmitting full bytes) db REG_ANALOG_CTL, (bAGC_EN | bPACTL_EN) db REG_AGC_CTL, bAGC_OFF db REG_SYN_LOCK_CNT, SYNTH_LOCK_COUNT db REG_CLOCK_MANUAL, 41h ; Manually override RSSI clock and RC clock db REG_CLOCK_ENABLE, 41h db REG_TEST_B, bCDET end_radio_table: XPAGEON IFDEF PN_CODE_64_TABLE XPAGEOFF ; The first section of Channel Access Codes (PN_CODE) (Only 32 Codes will fit in A table) pn_code_1_table: db 83h, F7h, A8h, 2Dh, 7Ah, 44h, 64h, D3h db 3Fh, 2Ch, 4Eh, AAh, 71h, 48h, 7Ah, C9h db 17h, FFh, 9Eh, 21h, 36h, 90h, C7h, 82h db A6h, 46h, B5h, 9Ah, 3Ah, 30h, B6h, ADh db BCh, 5Dh, 9Ah, 5Bh, EEh, 7Fh, 42h, EBh db 24h, F5h, DDh, F8h, 7Ah, 77h, 74h, E7h db 3Dh, 70h, 7Ch, 94h, DCh, 84h, ADh, 95h db 1Eh, 6Ah, F0h, 37h, 52h, 7Bh, 11h, D4h db 62h, F5h, 2Bh, AAh, FCh, 33h, BFh, AFh db 40h, 56h, 32h, D9h, 0Fh, D9h, 5Dh, 97h db 8Eh, 4Ah, D0h, A9h, A7h, FFh, 20h, CAh db 38h, B3h, 31h, ABh, 24h, 78h, A6h, BDh db 4Ch, 97h, 9Dh, BFh, B8h, 3Dh, B5h, BEh db 0Ch, 5Dh, 24h, 30h, 9Fh, CAh, 6Dh, BDh db 29h, 29h, 7Bh, B5h, C8h, F4h, 4Dh, 8Ah db 50h, 14h, 33h, DEh, F1h, 78h, 95h, ADh db D6h, A6h, AAh, 10h, 96h, B3h, A6h, A7h db F6h, CEh, 0Dh, 12h, E3h, 66h, A6h, 94h db 0Ch, 3Ch, FAh, F9h, F0h, F2h, 10h, C9h db F4h, DAh, 06h, DBh, BFh, 4Eh, 6Fh, B3h db 93h, 9Ch, 4Eh, 14h, 1Ah, 39h, CFh, E6h db C9h, 2Ch, 06h, 93h, 86h, B9h, 9Eh, D7h db 9Eh, 08h, D1h, AEh, 59h, 5Eh, E8h, F0h db C0h, 90h, 8Fh, BBh, 7Ch, 8Eh, 2Bh, 8Eh db 80h, 69h, 26h, 80h, 08h, F8h, 49h, E7h db 7dh, 2dh, 49h, 54h, d0h, 80h, 40h, C1h db B6h, F2h, E6h, 1Bh, 80h, 5Ah, 36h, B4h db 42h, AEh, 9Ch, 1Ch, DAh, 67h, 05h, F6h db 9Bh, 75h, F7h, E0h, 14h, 8Dh, B5h, 80h db BFh, 54h, 98h, B9h, B7h, 30h, 5Ah, 88h db 35h, D1h, FCh, 97h, 23h, D4h, C9h, 88h db E1h, D6h, 31h, 26h, 5Fh, BDh, 40h, 93h end_pn_code_1_table: XPAGEON XPAGEOFF ; The second section of PN_CODE's pn_code_2_table: db DCh, 68h, 08h, 99h, 97h, AEh, AFh, 8Ch db C3h, 0Eh, 01h, 16h, 0Eh, 32h, 06h, BAh db E0h, 83h, 01h, FAh, ABh, 3Eh, 8Fh, ACh db 5Ch, D5h, 9Ch, B8h, 46h, 9Ch, 7Dh, 84h db F1h, C6h, FEh, 5Ch, 9Dh, A5h, 4Fh, B7h db 58h, B5h, B3h, DDh, 0Eh, 28h, F1h, B0h db 9Ah, D6h, 95h, BAh, A4h, C5h, 32h, 9Ch db 5Fh, 30h, 3Bh, 56h, 96h, 45h, F4h, A1h db 03h, BCh, 6Eh, 8Ah, EFh, BDh, FEh, F8h db 88h, 17h, 13h, 3Bh, 2Dh, BFh, 06h, D6h db F1h, 94h, 30h, 21h, A1h, 1Ch, 88h, A9h db D0h, D2h, 8Eh, BCh, 82h, 2Fh, E3h, B4h db 8Ch, FAh, 47h, 9Bh, 83h, A5h, 66h, D0h db 07h, BDh, 9Fh, 26h, C8h, 31h, 0Fh, B8h db D7h, A1h, 54h, B1h, 5Eh, 89h, AEh, 86h db EFh, 03h, 95h, 89h, B4h, 71h, 61h, 9Dh db 40h, BAh, 97h, D5h, 86h, 4Fh, CCh, D1h end_pn_code_2_table: XPAGEON ENDIF ; PN_CODE_64_TABLE IFDEF PN_CODE_32_TABLE XPAGEOFF pn_code_1_table: db 6Ah, E7h, 01h, EAh, 03h, FDh, 13h, D2h db DCh, C0h, 6Bh, B8h, 2Bh, 09h, BBh, B2h db A3h, 1Eh, F2h, A4h, 31h, 32h, 7Ah, B3h db 44h, 83h, 3Bh, DDh, 14h, CFh, 8Eh, C9h db 35h, 35h, 4Eh, C5h, F3h, 52h, 47h, B0h db 7Ch, 23h, 8Ah, CEh, 45h, 5Ch, 54h, D7h db 81h, ACh, FBh, 83h, 7Ah, 9Ah, 61h, ACh db 3Ch, 12h, 5Fh, 9Ch, 39h, 98h, F6h, 8Ah end_pn_code_table: XPAGEON ENDIF