📄 lpnonstreaming.asm
字号:
.section
;-----------------------------------------------------------------------------
;
; RadioGetReceiveState:
; Returns the state of the current receive operation.
; This call should be made after RadioStartReceive()
;
; Although bits in the state register in the hardware clear
; automatically, we make them sticky until RadioEndReceive.
;
; 'C' Call: RADIO_STATE RadioGetReceiveState(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: State
; X: Undefined
;-----------------------------------------------------------------------------
_RadioGetReceiveState::
RadioGetReceiveState::
RAM_SETPAGE_CUR >RadioDriverRamPage
TST_IRQ_PIN
JZ RGRSDone ; Nothing interesting, exit
RadioGetReceiveStateIsr: ; Entry via RadioInterrupt() wrapper
MOV A, RX_IRQ_STATUS_ADR
CALL RadioReadStatusDebounced
AND A, (RXBERR_IRQ | RXE_IRQ | RXC_IRQ)
OR [RadioState], A ; Make bits sticky
TST [RadioState], (RXBERR_IRQ | RXE_IRQ) ; If Error,
JZ RGRSDone ; then set RXC/RXE
OR [RadioState], (RXC_IRQ | RXE_IRQ) ; because radio is done
RGRSDone:
MOV A, [RadioState] ; State calls and return them.
RET
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioEndReceive: Complete a receive operation.
;
; 'C' Call: RADIO_LENGTH RadioEndReceive(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: length of packet or RADIO_ABORT_SUCCESS
; X: Undefined
;-----------------------------------------------------------------------------
_RadioEndReceive::
RadioEndReceive::
MOV A, RX_COUNT_ADR ; Total # bytes through RFIFO
CALL RadioRead ; (RadioRead also sets CUR_PP)
MOV [RadioTemp3], A ;
TST [RadioState], RXE_IRQ ; If we had a buffer error...
JZ .S1
MOV A, 0x10 ; ...burp full FIFO load.
MOV [RadioTemp3], RADIO_ABORT_SUCCESS
.S1:
MOV X, RX_BUFFER_ADR
SWAP A, X
CALL RadioFileReadWip ; Final RFIFO unload
RadioRxCleanup:
MOV A, [RadioXactConfig] ;
OR A, FRC_END_STATE ; Force to User's desired end-state
MOV X, XACT_CFG_ADR ;
CALL RadioWriteSwapped
.wait: MOV A, XACT_CFG_ADR ; Wait for FRC_END_STATE bit in
CALL RadioRead ; XACT_CFG register to clear
AND A, FRC_END_STATE ; indicating the Force End is
JNZ .wait ; complete.
MOV A, [RadioTemp3] ; Byte count or RADIO_ABORT_SUCCESS
JMP RadioEndTransmit
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioForceState: Force radio to desired state NOW.
; Updates global RadioXacConfig shadow variable.
; Sometimes used to wake/sleep radio to measure voltage.
;
; We must ensure SLEEP only transitions to IDLE (and recovers if problem).
; RadioForceState(END_STATE_IDLE) MUST be called prior to TX_GO or RX_GO
; whenever radio may be in SLEEP.
;
; 'C' Call: void RadioForceState(XACT_CONFIG endStateBitsOnly);
;
; Assembly Call: A: RadioXactConfig END_STATE bits only, no ACK_EN, ACK_TO
; X: Undefined
;
; Assembly Return: A,X: Undefined
;-----------------------------------------------------------------------------
macro IsRadioSleep: ; Ret ZERO if Radio is in SLEEP mode
MOV A, [RadioXactConfig] ; Current state, at least it should be
AND A, END_STATE_MSK ;
if END_STATE_SLEEP
CMP A, END_STATE_SLEEP ; optional since END_STATE_SLEEP == 0
endif
endm
_RadioForceState::
RadioForceState::
RAM_SETPAGE_CUR >RadioDriverRamPage
; Only invoke when radio is in SLEEP
PUSH A ; Save target state
IsRadioSleep
JNZ .noCdt ; Current state IS NOT SLEEP
MOV A, END_STATE_IDLE ; Get Radio IDLE before anything else
CALL forceState ; Force SLEEP--->IDLE
.noCdt:
POP A ; Restore target state
; fallthru ; NON_SLEEP ---> User's Radio state
forceState:
CALL frcState ; Write State w/Force
MOV [RadioScratch0], 0 ; Delay 5 mS max timeout
wait5: MOV A, XACT_CFG_ADR ;
CALL RadioRead ;
AND A, FRC_END_STATE ;
JZ return ; Wait for Force End State completion
DEC [RadioScratch0]
JNZ wait5 ; No timeout yet
; timeout possible ONLY when going SLEEP to IDLE
MOV A, END_STATE_SLEEP
CALL frcState
MOV A, END_STATE_IDLE ; Get Radio IDLE before anything else
JMP forceState
frcState:
AND [RadioXactConfig], ~END_STATE_MSK
OR A, [RadioXactConfig] ; Merge w/existing ACK_EN, ACK_TO bits
OR A, FRC_END_STATE ; Force the State
JMP RadioSetXactConfig
; ----------------------------------------------------------------------------
; wakeupRadio - If radio is in SLEEP, wake it up.
; Leave "unforced" END STATE in (RadioXactConfig) unchanged.
; ----------------------------------------------------------------------------
wakeupRadio:
IsRadioSleep
JNZ return ; Radio already awake
MOV A, END_STATE_IDLE
CALL forceState ; Radio SLEEP ---> IDLE
MOV A, [RadioXactConfig] ; Restore unforced END state to SLEEP
AND A, ~END_STATE_MSK
if END_STATE_SLEEP ;
OR A, END_STATE_SLEEP ; optional since END_STATE_SLEEP == 0
endif
JMP RadioSetXactConfig
return: RET
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioGetRssi: Returns the receiver signal strength indicator.
;
; 'C' Call: RADIO_RSSI RadioGetRssi(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: Rssi
; X: Undefined
;-----------------------------------------------------------------------------
_RadioGetRssi::
RadioGetRssi::
MOV A, RSSI_ADR
JMP RadioRead
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioAbort: Abort a receive operation.
;
; 'C' Call: RADIO_LENGTH RadioAbort(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: RADIO_ABORT_SUCCESS or Length of valid Rx packet
; X: Undefined
;-----------------------------------------------------------------------------
_RadioAbort::
RadioAbort::
RAM_SETPAGE_CUR >RadioDriverRamPage
TST [RadioState], RADIO_RX ; This Abort handling is RX specific.
JZ .Abort
; Don't issue Force End if receive has started.
; SOPDET is broken, use RXB1 or RXC/RXE instead to know when Rx
; starts RXC/RXE may take a while to arrive.
MOV X, ABORT_EN ; Try to avoid committing to a Receive
MOV A, RX_ABORT_ADR ; packet by invoking Digital Loopback
CALL RadioWrite ;
; Delay about 2mS @ 24MHz to see if get RXB1 or RXC/RXE
MOV X, 20 ;
.L1: DEC A ; 4 cycles ; 9 cycles @24MHz is about 375 nS
JNZ .L1 ; 5 cycles ;
DEC X ;
JNZ .L1
MOV A, RX_IRQ_STATUS_ADR ; See if Rx packet has started
CALL RadioReadStatusDebounced;
OR [RadioState], A ; Make bits sticky
TST [RadioState], RXB1_IRQ ; (based on RXB1 flag)
JNZ .RxOk ; Rx packet has started, finish it
CALL RadioRxCleanup ; Rx packet blocked, issue FORCE_END
.Abort: MOV A, RADIO_ABORT_SUCCESS
JMP .AbortExit
; ----------------------------------------------------------------------------
; Receiving a packet, allow to finish naturally.
; Probably has errors (RXE) because we activated Digital Loopback,
; but if Loopback activated during AutoAck, we'll have a valid packet
; (which was AutoAcked, so we'd better not discard it!).
; ----------------------------------------------------------------------------
.RxOk: CALL RadioGetReceiveState ; Keep servicing receiver
AND A, RXE_IRQ | RXC_IRQ
JZ .RxOk
CALL RadioEndReceive ; A = Rx result
.AbortExit:
PUSH A
MOV X, 0x00 ; Disable abort
MOV A, RX_ABORT_ADR
CALL RadioWrite
POP A
RET
.endsection
IF 0
.section
;-----------------------------------------------------------------------------
;
; RadioPoll: Same as RadioInterrupt() but pushes the Flag register on
; the stack to setup for RETI.
; RadioPoll() can be called from a polling loop or an ISR
; that can not JMP - ie. an ISR written in 'C'.
;
; Unlike RadioInterrupt(), RadioPoll() may destroy registers.
;
; RadioInterrupt: Manage the radio in an ISR or polling loop.
;
; For interrupt systems RadioInterrupt can be called from the
; GPIO interrupt. This function does nothing if the IRQ is
; not asserted thereby making it easy to share the IRQ with
; other GPIO interrupts.
;
; Using this function in an IRQ can eliminate latency caused
; by calling RadioGetTransmitState and/or
; RadioGetReceveiveState in a polling loop. The state of the
; radio is communicated to outside code through the global
; variable RadioState.
;
; RadioInterrupt terminates with a RETI. It is intended to be
; the target of a JMP instruction from the interrupt vector
; directly in systems where the radio does not share the GPIO
; interrupt, or it can be JMP'd to at the end of a ISR that
; manages the other GPIO interrupt sources in a system.
;
; Because RadioInterrupt is intended to be JMP'd to from the
; interrupt vector it leaves the registers unaffected.
;
; 'C' Call: void RadioInterrupt(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: Untouched
; X: Untouched
;-----------------------------------------------------------------------------
_RadioPoll::
RadioPoll::
RAM_SETPAGE_CUR >RadioDriverRamPage
PUSH_F_VIA_RAM ; PUSH F and disable GIE
; ----------------------------------------------------------------------------
; RadioInterrupt() - Jumped-to via an ISR (or simulated ISR)
;
; Assumes: 1. GIE is disabled
; 2. F register on top of stack (arrived via JMP from an ISR)
; 3. Direct Memory instructions access Page 0
;
; Large Memory Model: must preserve CUR_PP and possibly MVR_PP.
; may leave STK_PP = SYSTEM_STACK_PAGE on exit.
; ----------------------------------------------------------------------------
_RadioInterrupt::
RadioInterrupt::
TST_IRQ_PIN
JZ .exit0 ; IRQ not asserted, just RETI
PUSH A ; Save Regs
PUSH X ;
ISR_REG_PRESERVE (CUR_PP) ; LMM saves CUR_PP reg
TST [RadioState], RADIO_TX
JZ .rxChk
.txChk:
ISR_REG_PRESERVE (MVR_PP) ; LMM saves MVR_PP
CALL RadioGetTransmitStateIsr
ISR_REG_RESTORE (MVR_PP) ; LMM restores MVR_PP
JMP .exit1
.rxChk: TST [RadioState], RADIO_RX
JZ .exit1
CALL RadioGetReceiveStateIsr
; LMM Note:
; RadioGetReceiveStateIsr() leaves STK_PP set to SYSTEM_STACK_PAGE.
; Only a VERY unusual application would have a problem with this.
.exit1:
ISR_REG_RESTORE (CUR_PP) ; LMM restores CUR_PP
POP X ; Restore Regs
POP A ;
.exit0:
POP_F_RET ; Same as RETI
.endsection
.section
;-----------------------------------------------------------------------------
;
; RadioGetReceiveStatus:
; Returns the receiver status register.
;
; 'C' Call: RADIO_RX_STATUS RadioGetReceiveStatus(void);
;
; Assembly Call: A: Unused
; X: Unused
;
; Assembly Return: A: Status
; X: Undefined
;-----------------------------------------------------------------------------
_RadioGetReceiveStatus::
RadioGetReceiveStatus::
MOV A, RX_STATUS_ADR
JMP RadioRead
.endsection
ENDIF
ENABLE_CODE_COMPRESSION
; ############################################################################
; END OF lpNonStreaming.asm
; ############################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -