📄 psocradio.asm
字号:
;--------------------------------------------------------------------------
;
; Filename: psocradio.asm
;
; Description: User functions to access an SPI based radio on PSoC.
;
;--------------------------------------------------------------------------
; $Archive: /WirelessUSB/LS2/Firmware/Pert/Pert_9248_29466/psocradio.asm $
; $Modtime: 3/13/06 2:11p $
; $Revision: 26 $
;--------------------------------------------------------------------------
;
; Copyright 2005-2006, 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.
;
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------;
; ;
; I N C L U D E F I L E S ;
; ;
;--------------------------------------------------------------------------;
INCLUDE "lpradio.inc"
INCLUDE "spim_radio.inc"
INCLUDE "psocgpioint.inc"
INCLUDE "lpregs.inc"
INCLUDE "irqmacros.inc"
INCLUDE "voip.inc"
// -----------------------------------------------------------
// -----------------------------------------------------------
// rwf: HACK TO SUPPORT TWO RADIOS ON DIFFERENT CHIP SELECTS
// 1) the original LP_nSS
// 2) the new LP_nSS2
// -----------------------------------------------------------
// -----------------------------------------------------------
; ----------------------------------------------------------------------------
; radioSelect and radioDeselect are also called by radio API
; ----------------------------------------------------------------------------
macro radioSelect
AND REG[LP_nSS_Data_ADDR], ~LP_nSS_MASK
endm
macro radioDeselect
OR REG[LP_nSS_Data_ADDR], LP_nSS_MASK
endm
;--------------------------------------------------------------------------;
; ;
; V A R I A B L E S ;
; ;
;--------------------------------------------------------------------------;
AREA bss
RadioWipPtr:: BLK 1 ; Working pointer.
RadioWipLen:: BLK 1 ; Working buffer length.
RadioPtr:: BLK 1 ; Parameter to SPI access routines - address.
RadioLen:: BLK 1 ; Parameter to SPI access routines - length.
RadioSpiTemp: BLK 1 ; Local working temp.
;--------------------------------------------------------------------------;
; ;
; C O D E ;
; ;
;--------------------------------------------------------------------------;
AREA UserModules (ROM, REL)
;
; Disable code compression.
;
DISABLE_CODE_COMPRESSION
;--------------------------------------------------------------------------
;
; Some comments on the operation of the SPI PSoC block:
;
; The SPIM_Radio_SPIM_SPI_COMPLETE and SPIM_Radio_SPIM_TX_BUFFER_EMPTY status
; bits are self-clearing. After you've read SPIM_Radio_CONTROL_REG these
; bits will be cleared. During a multibyte SPI transaction we use the
; SPIM_Radio_SPIM_TX_BUFFER_EMPTY status to pace the data, but at the end
; of a transaction we use SPIM_Radio_SPIM_SPI_COMPLETE to determine that
; we can de-assert the slave select.
;
; Although the hardware generates the SPIM_Radio_CONTROL_REG status
; one full byte time before SPIM_Radio_SPIM_TX_BUFFER_EMPTY if you are
; not reading the SPIM_Radio_CONTROL_REG register fast enough you might
; see both of those status indications occur together, and after you've
; read the SPIM_Radio_CONTROL_REG status it will clear and you will not see
; it again. In the case that the SPI clock is very fast, or if interrupts
; are left enabled during the execution of these routines then it is very
; possible to see both of these indications occur together.
;
; In order for these routines to allow interrupts to be enabled during their
; execution they are structured to allow the assertion of the two status
; bits SPIM_Radio_SPIM_SPI_COMPLETE and SPIM_Radio_SPIM_TX_BUFFER_EMPTY
; on the same read of SPIM_Radio_CONTROL_REG. Although this is a real world
; condition, you will only see it under stressed conditions.
;
; One other strangeness of the PSoC SPI block is that the
; SPIM_Radio_SPIM_SPI_COMPLETE status ONLY INDICATES THE STATE OF THE
; SHIFTER - it does not include the state of the holding register. This
; means that when we need to poll SPIM_Radio_SPIM_SPI_COMPLETE at the
; end of a transaction we need to make sure we see the status incdication
; SPIM_Radio_SPIM_TX_BUFFER_EMPTY to know that the complete wasn't for
; the previous byte.
;
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------;
; ;
; I N I T I A L I Z A T I O N ;
; ;
;--------------------------------------------------------------------------;
.section
;--------------------------------------------------------------------------
;
; RadioReset: Hard reset of the FPGA.
;
; 'C' Call: void RadioReset(void);
;
; Assembly Call: A: none
; X: none
;
; Assembly Return: A: Garbage
; X: Garbage
;
_RadioReset::
RadioReset:: UPDATE_PERM_IE_THROUGH_A
; Deassert the Slave Select.
radioDeselect
MOV [RadioLen], 255 ; Start out assuming a big buffer.
MOV A, MODE_OVERRIDE_ADR ; Reset the Radio through the SPI (soft reset).
MOV X, RST ; This way we don't have to worry
JMP RadioWrite ; about the reset wire.
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioWriteSwapped:
; Write a single byte to an Radio register. This is the same as
; the "normal" RadioWrite, but the parameters are in A and X
; "swapped". This is because the C calling conventions make
; it much easier to set the registers up this way.
;
; This is an assembly call only with no external linkage.
;
; 'C' Call: None.
;
; Assembly Call: A: The value to write to the selected register.
; X: The register number to write.
;
; (For both the 'C' and assembly call the top two bits of
; the register number MUST be clear.)
;
; Assembly Return: A: Undefined
; X: Undefined
;
RadioWriteSwapped::
SWAP A, X ; Fall into RadioWrite.
;-----------------------------------------------------------------------------
;
; RadioWrite: Write a single byte to an Radio register.
;
; 'C' Call: void RadioWrite(RADIO_REG_ADDR regAddr, BYTE value);
;
; Assembly Call: A: The register number to write.
; X: The value to write to the selected register.
;
; (For both the 'C' and assembly call the top two bits of
; the register number MUST be clear.)
;
; Assembly Return: A: Undefined
; X: Untouched
;
RadioWrite::
_RadioWrite:: OR A, bSPI_WRITE ; Set the Write Bit.
;--------------------------------------------------------------------------------
;
; RadioRead: Read a single byte from an Radio register.
;
; 'C' Call: BYTE RadioRead(RADIO_REG_ADDR regAddr);
;
; Assembly Call: A: The register number to read
; X: none
;
; (For both the 'C' and assembly call the top two bits of
; the register number MUST be clear.)
;
; Assembly Return: A: Value from register
; X: Undefined
;
; TODO: Remove Empty/Complete race and IRQ disable.
;
RadioRead::
_RadioRead:: CLEAR_TEMP_IE
radioSelect
MOV REG[SPIM_Radio_TX_BUFFER_REG],A
; Write the address.
.WaitLoop1: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_TX_BUFFER_EMPTY
JZ .WaitLoop1
MOV A,X ; For read this is garbage
MOV REG[SPIM_Radio_TX_BUFFER_REG],A
; Write the data.
.WaitLoop2: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_TX_BUFFER_EMPTY
JZ .WaitLoop2
.WaitLoop3: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_SPI_COMPLETE
JZ .WaitLoop3
MOV A,REG[SPIM_Radio_RX_BUFFER_REG]
; Get the return value.
radioDeselect
; Deassert the Slave Select
RET_RESTORE_IE_THROUGH_X
.endsection
.section
;--------------------------------------------------------------------------------
;
; RadioReadRxStatusDebounced:
; Read a single byte from the RX_IRQ_STATUS_ADR register and
; debounce the update of the RXC and RXE bits. If only one of
; those two bits is set, read the register a second time and
; or them together. This second read happens in the same
; SPI transaction as a burst to the same address.
;
; 'C' Call: BYTE RadioReadDebounced(RADIO_REG_ADDR regAddr);
;
; Assembly Call: A: none
; X: none
;
; (For both the 'C' and assembly call the top two bits of
; the register number MUST be clear.)
;
; Assembly Return: A: Value from register
; X: Untouched
;
; TODO: Remove Empty/Complete race and IRQ disable.
;
RadioReadStatusDebounced::
_RadioReadStatusDebounced::
CLEAR_TEMP_IE
radioSelect
MOV REG[SPIM_Radio_TX_BUFFER_REG],A
; Write the address.
.WaitLoop1: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_TX_BUFFER_EMPTY
JZ .WaitLoop1
MOV REG[SPIM_Radio_TX_BUFFER_REG],A
; Write the data.
.WaitLoop2: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_TX_BUFFER_EMPTY
JZ .WaitLoop2
.WaitLoop3: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_SPI_COMPLETE
JZ .WaitLoop3
;
; If the RXC and RXE (or TXC and TXE) bits are set the same then skip the debounce read.
;
MOV A,REG[SPIM_Radio_RX_BUFFER_REG]
MOV [RadioSpiTemp], A
AND A, RXC_IRQ | RXE_IRQ
JZ .Done
CMP A, RXC_IRQ | RXE_IRQ
JZ .Done
;
; The complete and error bits are different. Read a second time to make sure both bits
; have updated.
;
MOV REG[SPIM_Radio_TX_BUFFER_REG],A
.WaitLoop4: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_TX_BUFFER_EMPTY
JZ .WaitLoop4
.WaitLoop5: TST REG[SPIM_Radio_CONTROL_REG],SPIM_Radio_SPIM_SPI_COMPLETE
JZ .WaitLoop5
MOV A, REG[SPIM_Radio_RX_BUFFER_REG]
OR [RadioSpiTemp], A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -