📄 lpspi.asm
字号:
E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A ; Write the address
IF (LP_SPI) ; ---------------------------------------------------------
IF (SYSTEM_LARGE_MEMORY_MODEL)
MOV A, [RadioWipPtr+1] ; MSByte adr
RAM_SETPAGE_MVR A ; MVR operates on RadioWipPtr page
ENDIF
.Burst: MVI A, [RadioWipPtr+0] ; Get the data
SPI_TX_EMPTY_WAIT
MOV REG[SPI_TX_REG], A
DEC X
JNC .Burst
; All done bursting, wait for last byte to leave the holding register
SPI_TX_EMPTY_WAIT
; Wait for shifting to complete and the SPI transaction to finish.
.L1: TST REG[SPI_CTRL_REG],SPI_DONE
JZ .L1
ELSE ; PRoC/enCoRe II ------------------------------------------------------
IF (SYSTEM_LARGE_MEMORY_MODEL)
MOV A, [RadioWipPtr+1] ; MSByte adr
RAM_SETPAGE_MVR A ; MVR operates on RadioWipPtr page
ENDIF
.Burst:
MVI A, [RadioWipPtr+0] ; Get the data.
SPI_TX_EMPTY_WAIT
E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A ; Write the address
DEC X
JNC .Burst
; All done bursting, wait for last byte to leave the holding register
SPI_TX_EMPTY_WAIT
; Clear RX flag, for next Loop, it takes 9+4+9=22 cycles to finish
MOV REG[INT_CLR0], ~INT_MSK0_SPI_RX
; Wait for shifting to complete and the SPI transaction to finish.
.L1: TST REG[INT_CLR0],INT_MSK0_SPI_RX
JZ .L1
E2_CLR_SPI_RXTX_FLAGS
ENDIF ; LP_SPI ; ----------------------------------------------------
RADIO_DESELECT
.Done:
POP_F_RET
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioBurstReadWip:
; Read a sequence of bytes from a sequence of Radio registers
; using RadioWipPtr as the buffer pointer.
;
; Assembly Call: RadioWipPtr: Address of buffer to read.
; A: The register number to write.
; (Top two bits MUST be clear.)
; X: Length of the buffer.
;
; Assembly Return: A: Undefined
; X: Undefined
;-----------------------------------------------------------------------------
RadioBurstReadWip::
OR A, bSPI_AUTO_INC ; Set the increment flag.
JMP RadioFileReadWip
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioBurstRead: Read a sequence of bytes from a sequence of Radio registers
;
; 'C' Call: void RadioBurstRead(unsigned char cnt);
; Must set RadioPtr via RadioSetPtr() before RadioBurstRead.
;
; See RadioFileRead() for entry/exit parameters
;-----------------------------------------------------------------------------
RadioBurstRead::
_RadioBurstRead::
OR A,bSPI_AUTO_INC ; Set the increment flag.
;-----------------------------------------------------------------------------
;
; RadioFileRead: Read a sequence of bytes from a single Radio registers.
;
; time-> |8spiclk|8spiclk|8spiclk|
; Assert Slave Select | | | |
; Write Address | | | |
; Wait for Empty(1)----+ | | |
; Write Nul Data | | |
; Wait for Empty(2)------------+ | |
; Write Nul Data | |
; Read Nul Data | |
; Wait for Empty(3)--------------------+ |
; Write Nul Data |
; Read Data |
; Wait for Empty and complete------------------+
; Read Data
; De-assert Slave Select
;
; The main loop of this routine is a littler slower than it
; should be. With a 12MHz CPU the burst is not always
; continuous. There are occasional gaps between bytes in the
; burst. It should be possible to correct this, but it's a
; minor problem and this is already pretty convoluted to deal
; with the latency caused by the TX and RX holding buffers.
;
; Properly handles all length cases, including zero and one.
;
; 'C' Call: (Must set RadioPtr and RadioLen by calling RadioSetPtr
; prior to RadioFileRead.)
; void RadioFileRead(BYTE regAddr, BYTE cnt);
;
; Assembly Call: A: The register number to write, top 2 bits MUST be clear!
; X: Length of the buffer.
; RadioPtr: Address of buffer to read.
; RadioLen: Size of buffer
;
; Assembly Return: A: Undefined
; X: Undefined
; CUR_PP: Large Memory Model sets to RadioDriverRamPage
; STK_PP: Large Memory Model sets to SYSTEM_STACK_PAGE
;-----------------------------------------------------------------------------
RadioFileRead::
_RadioFileRead::
RAM_SETPAGE_CUR >RadioDriverRamPage
IF (SYSTEM_LARGE_MEMORY_MODEL)
MOV [RadioWipPtr+1], [RadioPtr+1] ; LMM: MSB working pointer
ENDIF
MOV [RadioWipPtr+0], [RadioPtr+0] ; Initialize working pointer
MOV [RadioWipLen], [RadioLen] ; and length.
RadioFileReadWip::
RAM_SETPAGE_CUR >RadioDriverRamPage
PUSH_F_VIA_RAM ; PUSH F and disable GIE
DEC X ; Check for zero length case.
JC .exit0 ; If zero, nothing to do.
; Here, X = number of bytes in the file read -1. The final byte is
; handled specially by waiting for COMPLETE instead of EMPTY at
; .LastByte below.
; --------------------------------------------------------------------
RADIO_SELECT
E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A ; Write SPI address.
; --------------------------------------------------------------------
; Using the SP as a write data pointer is 6-cycles faster than MVI.
; (Since GIE is already disabled, using SP is safe).
; --------------------------------------------------------------------
SWAP A, SP
SWAP [RadioWipPtr+0], A ; LSByte of pointer
SWAP A, SP ; SP = RadioWipPtr
IF (SYSTEM_LARGE_MEMORY_MODEL)
MOV A, [RadioWipPtr+1] ; MSByte of pointer (page #)
MOV REG[STK_PP], A
ENDIF
SPI_RX_EMPTY_WAIT
SET_SPI_IN
E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A ; Write null data.
;
; We need to get three items set up for this execution of the routine and the
; next as well based on whether there is room in the buffer.
; bytes to read(X) - space in buffer(RadioWipLen)
; C (RadioWipLen>X) NC (RadioWipLen<=X)
;-----------------------------------------------------------------------------
; Reads that fit in buffer : X = X = RadioWipLen
; Reads thrown away : RadioSpiTemp = 0 = X-RadioWipLen
; Bytes left in buffer : RadioWipLen = RadioWipLen-X = 0
;
MOV A, X
SUB A, [RadioWipLen] ; CRY = 1 if user's buffer TOO SMALL
SPI_TX_EMPTY_WAIT ; cry preserved
JNC .S1 ; User buf holds ALL Radio Rx data
MOV [RadioSpiTemp], 0 ; User buf too small for Radio Rx data
MOV A, X
SUB [RadioWipLen], A
JMP .BurstBottom
; A = number of bytes we are going to move -1.
; We need to subtract the total number of bytes which is A+1.
;
.S1: MOV [RadioSpiTemp], A
MOV X, [RadioWipLen]
MOV [RadioWipLen], 0
JMP .BurstBottom
.BurstLoop1:
E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A ; Write null data.
SPI_TX_EMPTY_WAIT
MOV A, REG[SPI_RX_REG] ; Get SPI Rx data
PUSH A ; Save data in buffer, not real stack
.BurstBottom:
DEC X ; Count
JNC .BurstLoop1 ; Keep copying to User Buffer
; User Buffer is FULL, if Radio still has Rx data then read it and
; discard. If more data to dump, count is in RadioSpiTemp.
MOV X, [RadioSpiTemp]
JMP .trash0
.trash: E2_CLR_SPI_RXTX_FLAGS
MOV REG[SPI_TX_REG], A
SPI_TX_EMPTY_WAIT ; Don't bother reading SPI Rx data
.trash0: ; because User's Buffer is FULL
DEC X
JNC .trash
; --------------------------------------------------------------------
; Moved all data except for one last byte. Wait for it and if
; we have room in the buffer, get it and store it.
; --------------------------------------------------------------------
.LastByte:
IF (LP_SPI) ; ---------------------------------------------------------
TST REG[SPI_CTRL_REG], SPI_DONE
ELSE ; PRoC/enCoRe II ------------------------------------------------------
TST REG[INT_CLR0], INT_MSK0_SPI_RX
ENDIF ; ----------------------------------------------------
JZ .LastByte
CMP [RadioWipLen], 0
JZ .exit1 ; Exit w/cleanup
MOV A, REG[SPI_RX_REG] ; Get SPI Rx data
PUSH A ; Save data in buffer, not real stack
DEC [RadioWipLen]
.exit1:
E2_CLR_SPI_RXTX_FLAGS
SET_SPI_OUT
RADIO_DESELECT
SWAP A, SP ; Restore SP to STACK
SWAP [RadioWipPtr], A ; Restore SP to STACK
SWAP A, SP ; Restore SP to STACK
IF (SYSTEM_LARGE_MEMORY_MODEL)
MOV REG[STK_PP], SYSTEM_STACK_PAGE
ENDIF
.exit0:
POP_F_RET ; Restore GIE bit
.endsection
ENABLE_CODE_COMPRESSION
; ############################################################################
; END OF lpSpi.asm
; ############################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -