📄 voip8kisr.asm
字号:
MOV A, X ; junk for a Read
MOV REG[SPI_TX_REG], A
.wait2: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .wait2
.wait3: TST REG[SPI_CTRL_REG], SPI_DONE
JZ .wait3
radioDeselect
MOV A, REG[SPI_RX_REG] ; RetValue + update ZF
RET
; ----------------------------------------------------------------------------
;
; This routine is for 24MHz CPU and 3 MHz SPI
;
; isrRadioFileReadWip: Read up to 16 Bytes from Radio Rx register
;
; X: Number of bytes to copy
; [RadioWipPtr]: Destination for copy
; ----------------------------------------------------------------------------
macro SPI_WAIT_TXBUF
.Loop1: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .Loop1 ; Wait for holding reg empty
endm
macro SPI_WAIT_RXBUF
.Loop1: TST REG[SPI_CTRL_REG], SPI_RX_FULL
JZ .Loop1 ; Wait for holding reg empty
endm
; ----------------------------------------------------------------------------
isrRadioFileReadWip:
; --------------------------------------------------------------------
; Select Radio, Write Adr and start shifting-in first Read Byte
; --------------------------------------------------------------------
radioSelect
MOV REG[SPI_TX_REG], RX_BUFFER_ADR ; queue ADR clk
SPI_WAIT_TXBUF ; await ADR clocking
MOV REG[SPI_TX_REG], A ; queue DATA_1 clocking
; --------------------------------------------------------------------
; Using Stack Pointer is fastest way to write data
; --------------------------------------------------------------------
SWAP A, SP ; 5
SWAP [RadioWipPtr], A ; 7
SWAP A, SP ; 5
MOV A, REG[STK_PP]
MOV [timeTmpA], A
MOV REG[STK_PP], 0
DEC X
JZ .LastByte ; Only load ONE byte (it's the last)
; --------------------------------------------------------------------
; Copy all but final Byte
; --------------------------------------------------------------------
SPI_WAIT_TXBUF ; await DATA_1 to begin clocking
.Loop8:
MOV REG[SPI_TX_REG], A ; queue DATA_2 clocking
SPI_WAIT_TXBUF ; await DATA_2 to begin clocking
MOV A, REG[SPI_RX_REG] ; get DATA_1 result
PUSH A ; 4 Save the data.
DEC X ; 4 Count
JNZ .Loop8 ; 5 Repeat
; --------------------------------------------------------------------
; Get last byte by waiting for RX_BUFFER_FULL bit (0x08).
; WARNING: SPI_COMPLETE bit (0x20) SELF-CLEARS
; --------------------------------------------------------------------
.LastByte:
TST REG[SPI_CTRL_REG], SPI_RX_FULL
JZ .LastByte
MOV A,REG[SPI_RX_REG] ;[ 6] Get the data from last shift
PUSH A ;[ 4] Save the data
radioDeselect
MOV A, [timeTmpA] ; Return STACK to its
MOV REG[STK_PP], A ; original page
SWAP A, SP
SWAP [RadioWipPtr], A
SWAP A, SP
RET
; ----------------------------------------------------------------------------
;
; This routine is for 24MHz CPU and 3 MHz SPI
;
; isrRadioFileReadWipTrash: Read up to 16 Bytes from Radio Rx register
;
; Used both when "unwanted" data needs flushing. Note that "unwanted" data
; can be the second copy if the first copy is recieved.
;
; Entry: X = # bytes to copy to TRASH
; ----------------------------------------------------------------------------
isrRadioFileReadWipTrash:
; --------------------------------------------------------------------
; Select Radio, Write Adr and start shifting-in first Read Byte
; --------------------------------------------------------------------
radioSelect
MOV REG[SPI_TX_REG], RX_BUFFER_ADR ; queue ADR clk
SPI_WAIT_TXBUF ; await ADR clocking
MOV REG[SPI_TX_REG], A ; queue DATA_1 clocking
DEC X
JZ .LastByte ; Only load ONE byte (it's the last)
; --------------------------------------------------------------------
; Copy all but final Byte
; --------------------------------------------------------------------
SPI_WAIT_TXBUF ; await DATA_1 to begin clocking
.Loop8:
MOV REG[SPI_TX_REG], A ; queue DATA_2 clocking
SPI_WAIT_TXBUF ; await DATA_2 to begin clocking
MOV A, REG[SPI_RX_REG] ; get DATA_1 result
; discard data
DEC X ; 4 Count
JNZ .Loop8 ; 5 Repeat
; --------------------------------------------------------------------
; Get last byte by waiting for RX_BUFFER_FULL bit (0x08).
; WARNING: SPI_COMPLETE bit (0x20) SELF-CLEARS
; --------------------------------------------------------------------
.LastByte:
TST REG[SPI_CTRL_REG], SPI_RX_FULL
JZ .LastByte
MOV A,REG[SPI_RX_REG] ;[ 6] Get the data from last shift
; discard data
radioDeselect
RET
; ----------------------------------------------------------------------------
;
; isrRadioBurstWriteWip: Write a sequence of bytes to a single Radio register.
;
; Assembly Call: RadioPtr: Address of buffer to write.
; A: The register number to write.
; [txPktLen]: NON-Zero Length of the buffer.
; ----------------------------------------------------------------------------
isrRadioBurstWriteWip:
radioSelect
MOV REG[SPI_TX_REG], A
.next:
MVI A, [timeTmpA] ; Get the data (also SP -= 1)
.wait: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .wait
MOV REG[SPI_TX_REG], A
DEC X
JNZ .next
; Done bursting, wait for the last byte to leave the holding register.
.wait1: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .wait1
; Wait for shifting to complete and the SPI transaction to finish.
.wait2: TST REG[SPI_CTRL_REG], SPI_DONE
JZ .wait2
radioDeselect
RET
; ----------------------------------------------------------------------------
;
; This routine is for 24MHz CPU and 3 MHz SPI
;
; isrRadioFileWriteWip() - Write data string to Radio Tx buffer
;
; ----------------------------------------------------------------------------
isrRadioFileWriteWip:
MOV X, [txPktLen] ;[ 6] Packet length
radioSelect ;[ 9]
MOV REG[SPI_TX_REG], A ;[ 5] Address
.next: MVI A, [RadioWipPtr] ;[10]
.wait: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .wait
MOV REG[SPI_TX_REG], A
DEC X
JNZ .next
; Done bursting, wait for the last byte to leave the holding register.
.wait1: TST REG[SPI_CTRL_REG], SPI_TX_EMPTY
JZ .wait1
; Wait for shifting to complete and the SPI transaction to finish.
.wait2: TST REG[SPI_CTRL_REG], SPI_DONE
JZ .wait2
radioDeselect
RET
; -------------------------------------------------------------------
;
; outPreprocess() - Preprocess "raw" samples from USB
;
; 1) Convert data from 2's complement from USB to unipolar for ADPCM
; 0x8000 --> 0x0000 ( 0 scale voltage)
; 0xFFFF --> 0x7FFF (0.5 scale voltage - 1)
; 0x0000 --> 0x8000 (0.5 scale voltage)
; 0x7FFF --> 0xFFFF (1.0 scale voltage)
;
; 2) Convert from 16-bit USB to 15-bit for ADPCM
; High bit will eventually indicate insert/delete point
; -------------------------------------------------------------------
AREA bss (RAM, REL, CON) ; general use
nonIsrCt:: BLK 1
;_pg3ptr:: BLK 1
;_pg1ptr:: BLK 1
;PG3_DATA: EQU 0x80
AREA UserModules (ROM, REL)
; WORD * outPreprocess(WORD *pdat);
_outPreprocess::
AND F, ~FLAG_PGMODE_MASK
OR F, FLAG_PGMODE_2 ; Use IDX_PP here
MOV REG[IDX_PP], A
PUSH A
;; ============================================================================
;; ============================================================================
;; FOLLOWING CODE COPIES USB BUFFER TO PAGE 3 FOR NON-REALTIME DUMP
; mov a, [_pg3ptr]
; jnz .S10
;
; MOV A, REG[MVR_PP]
; push a
; mov a, reg[MVW_PP]
; push a
;
; mov reg[MVR_PP], 1
; mov [_pg1ptr], x
; mov reg[MVW_PP], 3
; mov [_pg3ptr], PG3_DATA
; mov [nonIsrCt], 8
;.L10:
; mvi a, [_pg1ptr]
; mvi [_pg3ptr], a
; mvi a, [_pg1ptr]
; mvi [_pg3ptr], a
; dec [nonIsrCt]
; jnz .L10
;
; pop a
; mov reg[MVW_PP], a
; pop a
; mov reg[MVR_PP], a
;.S10:
;; PRIOR CODE COPIES USB BUFFER TO PAGE 3 FOR NON-REALTIME DUMP
;; ============================================================================
;; ============================================================================
MOV [nonIsrCt], 8
.L1:
MOV A, [X+0] ; LSB
PUSH A
MOV A, [X+1] ; MSB
XOR A, 0x80 ; 2's complement to unipolar
AND F, ~FLAG_CARRY
RRC A
MOV [X+MSB], A ; Right-shift and store big-endian
POP A
RRC A
MOV [X+LSB], A
INC X ; Autmatically wraps within page
INC X
DEC [nonIsrCt]
JNZ .L1
OR F, FLAG_PGMODE_3 ; Restore Compiler's PageMode 3
POP A ; AX = new page
RET
; ----------------------------------------------------------------------------
; void _incUsbOutInCyclic(void);
; void _decUsbOutInCyclic(void);
; ----------------------------------------------------------------------------
_incUsbOutInCyclic::
INC [_usbOutIn+LSB] ; Inc LSByte only mod 256
INC [_usbOutIn+LSB] ; Inc LSByte only mod 256
RET
_decUsbOutInCyclic::
DEC [_usbOutIn+LSB] ; Dec LSByte only mod 256
DEC [_usbOutIn+LSB] ; Dec LSByte only mod 256
RET
; ----------------------------------------------------------------------------
; _nxtVoiceCh - Advance to next voice channel
; void nxtVoiceCh(void);
; ----------------------------------------------------------------------------
_nxtVoiceCh::
ADD [_voiceCh], CH_STEP_SIZE
CMP [_voiceCh], CH_MAX
JC .skip ; JLT
MOV [_voiceCh], CH_MIN-1
.skip:
MOV [_reqChWrite], 1 ; Request ISR machine to write ch
RET
; ----------------------------------------------------------------------------
;
; asmUsbInOtAdv() - circular advance USB IN unload pointer
; (it's tacky, but the compiler sucks)
; ----------------------------------------------------------------------------
macro PUSH_CUR_PP
MOV A, REG[CUR_PP]
PUSH A
MOV REG[CUR_PP], 0
endm
macro POP_CUR_PP
POP A
MOV REG[CUR_PP], A
endm
_asmUsbInOtAdv:: // void asmUsbInOtAdv(void)
PUSH_CUR_PP
ADD [_usbInOt+LSB], 16 ; 8 word samples, mod 256
POP_CUR_PP
RET
; ----------------------------------------------------------------------------
;
; asmIsUsbInEnough() - Keep usbIn buffer from over/underflowing
;
; ----------------------------------------------------------------------------
_asmIsUsbInEnough:: // BOOL asmIsUsbInEnough(void)
LIMIT_MAX: EQU 150
LIMIT_MIN: EQU 40
PUSH_CUR_PP
MOV A, [_usbInIn+LSB] ; Buffer insert point
SUB A, [_usbInOt+LSB] ; Buffer extract point
CMP A, LIMIT_MAX ; A = number of buffered bytes
JC .S1 ; jmp A < MAX
ADD [_usbInIn+LSB], 2 ; Buffer > MAX: Discard 1 sample
; fallthru
.S1: CMP A, LIMIT_MIN ;
JC .under ; A < MIN (Buffer underflow)
POP_CUR_PP ; Data available for USB
MOV A, 1 ; At least 8 sample words to unload
RET
.under: SUB [_usbInOt+LSB], 2 ; Buffer underflow: Add dummy sample
POP_CUR_PP
MOV A, 0 ; Nothing for USB
RET
; ###########################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -