⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voip8kisr.asm

📁 Cypress 的VOIP DEMO 研究VOIP终端的朋友可以研究研究
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	CMP	A, [_usbOutIn+LSB]
	JNZ	.s1			; USB data available, use it
	MOV	X, 0x40			; No USB data yet, just feed
	MOV	A, 0x00			;  uint15 half-scale values
	JMP	.goDat
	; ^^^^^^^^ No USB data
.s1:	AND	F, ~FLAG_PGMODE_MASK
	OR	F,  FLAG_PGMODE_2	; Use IDX_PP here
	MOV	A, [_usbOutOt+MSB]	; page #
	MOV	REG[IDX_PP], A
	MOV	X, [_usbOutOt+LSB]	; page index

	TST	[X+0], 0x80		; Test if insert or delete here
	JZ	.norm			; no

	MOV	A, [_nulInsDel]
	MOV	[_nulInsDel], 0		; Release so main() can adjust again
	CMP	A, 1
	JZ	.ins
.del:	INC	X			; Delete just skips this sample
	INC	X
	JMP	.norm
	; ^^^^^^^^ Delete/Skip this sample
.ins:	AND	[X+0], 0x7F		; Erase "special" bit (use next ISR)
	MOV	X, [_insertVal+MSB]	;  and fetch synthesized sample.
	MOV	A, [_insertVal+LSB]	; LSB
	JMP	.goDat
	; ^^^^^^^^ Insert sample
.norm:	MOV	A, [X+0]		; MSB
	PUSH	A
	MOV	A, [X+1]		; LSB
	ADD	[_usbOutOt+1], 2 	; ptr += 2
	POP	X			; MSB

	; --------------------------------------------------------------------
	; X,A = 15-bit unipolar PCM data to be compressed
	; --------------------------------------------------------------------
.goDat:	AND	F, ~FLAG_PGMODE_MASK	; Restore ISR PageMode_0
	CALL	adpcmEncode		;    X,A = 15-bit unsigned PCM
					; A[3:0] = ADPCM
  IF	LOOPBACK_ADPCM		;#############################################
	MOV	[timeTmpA], A	; save encoded ADPCM sample for decoding below
  ENDIF	; LOOPBACK_ADPCM	;#############################################
	MOV	X, [bufTxVoipPtr]
       	TST	[_slotCt], 1		; test for Odd Slot
       	JNZ	.msn			; Odd slots put ADPCM in MSNibble
	MOV	[X+0], A		; Load LSN, zero MSN
	JMP	.decode
.msn:	ASL	A
	ASL	A
	ASL	A
	ASL	A
	OR	[X+0], A		; Merge MSN with existing LSN
	INC	[bufTxVoipPtr]		; Next nibble goes in new Byte

; ----------------------------------------------------------------------------
;
; Decode 4-bit ADPCM Radio Sample to 16-bit, 2's complement for USB
;
; ----------------------------------------------------------------------------
.decode:
	; Get 4-bit ADPCM sample from Radio Rx buffer
	; -------------------------------------------
	MOV	A, [bufRxVoipPtr]       ; Zero if no Rx RF Frame available
	JZ	.noRxSamples
	MOV	X, A
	MOV	A, [X]			; A[7:4],[3:0] = ADPCM samples
	TST	[_slotCt], 1
	JZ	.lsn			; Even slots get ADPCM from LSNibble
	ASR	A			;  Odd slots get ADPCM from MSNibble
	ASR	A			;
	ASR	A			;
	ASR	A			;
	INC	[bufRxVoipPtr]		; Next nibble comes from new Byte
.lsn:	AND	A, 0x0F
  IF	LOOPBACK_ADPCM		;#############################################
	MOV	A, [timeTmpA]	; 					;#####
  ENDIF	; LOOPBACK_ADPCM	;#############################################
	LCALL	adpcmDecode		;  4-bit ADPCM -->15-bit unipolar PCM

	MOV	[timeTmpA], X		; Convert [14: 0] unipolar to 
	ASL	A			;  [15: 0] 2's complement for USB
	RLC	[timeTmpA]		; [timeTmpA],A = 16-bit unipolar
	XOR	[timeTmpA], 0x80	; [timeTmpA],A = 2's complement
	JMP	.save

	; --------------------------------------------------------------------
	; No RF frame received for this 24-sample set
	;
	; n = n - (n>>3) low-pass filter
	; --------------------------------------------------------------------
.noRxSamples:
  IF	LOOPBACK_ADPCM		;#############################################
	MOV	A, [timeTmpA]		; keep feeding data to track
	LCALL	adpcmDecode		;  4-bit ADPCM -->15-bit unipolar PCM
  ENDIF	; LOOPBACK_ADPCM	;#############################################
	MOV	A, 0			; No ADPCM samples,
	MOV	[timeTmpA], 0		;  use 1/2 scale 2's complement PCM
	; --------------------------------------------------------------------
.save:
	PUSH	A			; Park [ 7: 0] of PCM
	AND	F, ~FLAG_PGMODE_MASK
	OR	F,  FLAG_PGMODE_2	; Use IDX_PP here
	MOV	A, [_usbInIn+MSB]	; Page #
	MOV	REG[IDX_PP], A
	MOV	X, [_usbInIn+LSB]	; adr within page

	MOV	A, [timeTmpA]
	MOV	[X+1], A		; Store MSB (little-endian for USB)
	POP	A
	MOV	[X+0], A		; Store LSB (little-endian for USB)
	ADD	[_usbInIn+LSB], 2	; buffer wraps mod 256 on single page

	AND	F, ~FLAG_PGMODE_MASK	; Restore ISR PageMode_0
; ----------------------------------------------------------------------------


; ----------------------------------------------------------------------------
ctrIsrX:
	; -----------------------------
	POP	A			; Restore Direct page pointer
	MOV	REG[CUR_PP], a
	; -----------------------------
	POP	A			; Restore X page pointer
	MOV	REG[IDX_PP], a
	; -----------------------------
	POP	A			; Restore MVI Write page pointer
	MOV	REG[MVW_PP], A
	; -----------------------------
	POP	A			; Restore MVI Read page pointer
	MOV	REG[MVR_PP], A
	; -----------------------------

; ----------------------------------------------------------------------------
; USB OUT WORKAROUND
; Either use non-standard USB workaround: manual increment in USB.ASM
; Or use standard API workaround and possible return to 12 MHz
; ----------------------------------------------------------------------------
 IF NOT_NDX_WORKAROUND
	M8C_SetBank1			; START USB OUT ENDPOINT WORKAROUND
	POP	A			;
	MOV	reg[OSC_CR0],A		; Restore clock to 12 or 24 MHz clock
	M8C_SetBank0			; STOP USB OUT ENDPOINT WORKAROUND
  ENDIF
	TEST_LED_LO	; =======================
	POP	X			; Restore X
	POP	A			; Restore A
	RETI

; ----------------------------------------------------------------------------
;
; startIsr - Do initial synchronization to received VoIP stream
;
; Synchronizes to two consecutive 15-Byte frames with the same content.
; It's imperfect because the frames may have intervening frames of 
;  non-15 byte lengths
;
; ----------------------------------------------------------------------------
_startIsr::				; Called by non-ISR to request 
	MOV	[_slotCt], -1		;  synchronization at next ISR


//	MOV	[isrBufTxCtrlOfsIn], (isrBufTxCtrl + 1)
//	MOV	[bufTxVoipOfsIn], (bufTxVoip + 1)

	; Start loading a NEW Tx frame (basically just initialize vars)
	MOV	[bufTxVoip+0], [_iEncPredict+0]
	MOV	[bufTxVoip+1], [_iEncPredict+1]
	MOV	[bufTxVoip+2], [_bEncStepSizePtr]
	MOV	[bufTxVoipPtr], bufTxVoip+3	; Load new frame ADPCM here

	MOV	[_voiceCh], CH_MIN-1
	MOV	[rssiCh], CH_MIN-1
	MOV	[p3RssiFilt], _rssiFiltTbl

	MOV	[txPktLen], VOIP_PKT_LEN

	MOV	[bufTxCtlPtr], (bufTxCtl+1)

	MOV	A, ISR_VAL_NOM_LSB
	MOV	[isrPeriod], A
	MOV	X, ISR_VAL_NOM_MSB
	LCALL	PWM16_1_WritePeriod
	LCALL	PWM16_1_Start
	LCALL	PWM16_1_EnableInt

	RET

; ----------------------------------------------------------------------------
; doSynchronize - Scan looking for VoIP stream from a Remote.
;		Entry and Exit via ISR level.
; ----------------------------------------------------------------------------
doSynchronize:
; LOCAL VARIABLES
rxCnt:		equ	timeTmpA
dwellTime:	equ	timeTmpB
ct_277uS:	equ	timeTmpC
diffVar:	equ	timeTmpD
bufPtr:		equ	timeTmpE
parkTime:	equ	timeTmpF	; sit on initial new chan longer

	; General ISR initialization

	LCALL	PWM16_1_Stop		; No ISRs while synchronizing

	MOV	[_rxPktAve_Q3], 15<<3	; Start w/best Rx Packet average


	; Clear error statistics
	mov	[_mibMissRx_1 + 0], 0
	mov	[_mibMissRx_1 + 1], 0
	mov	[_mibMissRx_2 + 0], 0
	mov	[_mibMissRx_2 + 1], 0
	mov	[_mibMissTx + 0], 0
	mov	[_mibMissTx + 1], 0

	; ---------- goto Rx mode
	MOV	A, XACT_CFG_ADR + bSPI_WRITE
	MOV	X, (FRC_END_STATE + END_STATE_RXSYNTH)
	CALL	isrRadioWrite
.L2:	MOV	A, XACT_CFG_ADR		; Wait for the FRC_END_STATE
	CALL	isrRadioRead		;  bit in the XACT_CFG register
	AND	A, FRC_END_STATE	;  to clear indicating the force has
	JNZ	.L2			;  completed.

	; --------------------------------------------------------------------
	; parkTime - Wait longer on the first new channel because farside 
	;     takes about 50 mS to recognize that we are gone.  Farside 
	;     may not recognize a problem until our resynchronization begins.
	; --------------------------------------------------------------------
	MOV	[parkTime], 1

	; ---------- RX_GO
.doRxGo:
	MOV	[dwellTime], 9		;  9 = 2.5 mS at 24 MHz
.park:
	MOV	X, [_voiceCh]
	MOV	A, CHANNEL_ADR + bSPI_WRITE
	CALL	isrRadioWrite

	MOV	A, RX_CTRL_ADR + bSPI_WRITE
	MOV	X, (RX_GO + RXC_IRQ)	; IRQ at RX_COMPLETE (for polling)
	CALL	isrRadioWrite		;
	MOV	A, RSSI_ADR		; Clear any pending SOP bit
	CALL	isrRadioRead

	; --------------------------------------------------------------------
	; Wait (possibly forever) for RX_COMPLETE IRQ from Radio
	; Peiodically change channels.
	; Wait for 750uS * 3 for a Rx burst before changing channels
	; --------------------------------------------------------------------
	MOV	[ct_277uS], 0
.Loop3:	IS_IRQ_ON
	JNZ	.rxPkt			; Evaluate Rx packet
	DEC	[ct_277uS]
	JNZ	.Loop3
	DEC	[dwellTime]
	JNZ	.Loop3

	call	_nxtVoiceCh		; Next channel
	MOV	A, [parkTime]
	JZ	.doRxGo			; Not 1st new ch, short wait
	MOV	[parkTime], 0		; 1st new ch has long wait
	MOV	[dwellTime], 180	;  180 = 50 mS at 24 MHz
	JMP	.park

	; --------------------------------------------------------------------
	; Rx Complete, evaluate frame
	; --------------------------------------------------------------------
.rxPkt:	
	MOV	A, RX_IRQ_STATUS_ADR
	CALL	isrRadioRead
	MOV	[diffVar], A
	TST	[diffVar], RXBERR_IRQ + RXE_IRQ
	JZ	.noErr
	; --------------------------------------------------------------------
	; Reject: Frame had errors, flush radio buffer if has data
	; --------------------------------------------------------------------
	TST	[diffVar], (RXB16_IRQ + RXB8_IRQ + RXB1_IRQ)
	JZ	.doRxGo			; Wait for another Rx frame
	MOV	X, 16			; X = Length
	CALL	isrRadioFileReadWipTrash ; Unload data from Radio
	JMP	.doRxGo			; Wait for another Rx frame

.noErr:	MOV	A, RX_COUNT_ADR
	CALL	isrRadioRead
	OR	A, 0			; Test flags
	JZ	.doRxGo			; Ignore frame, No payload data
	MOV	[rxCnt], A 
	XOR	A, VOIP_PKT_LEN		; Test Rx packet against VoIP length
	MOV	[diffVar], A		; Z if VoIP length, NZ if wrong len

	; --------------------------------------------------------------------
	; Copy data from radio buffer to local buffer in Stack Page
	; During copy, compare each byte to "matching" byte in opposite buf
	; This copy/compare takes about 160uS at 24 MHz CPU, 3 MHz SPI
	; --------------------------------------------------------------------
	MOV	[bufPtr], bufRxVoip0
.Loop4:
	MOV	A, RX_BUFFER_ADR
	CALL	isrRadioRead		; Read 1 Byte
	PUSH	A
	MOV	X, [bufPtr]		;
	XOR	A, [X]			; Compare NEW byte with OLD byte
	OR	[diffVar], A		; NZ if different
	POP	A
	MOV	[X], A			; Store NEW byte
	INC	[bufPtr]
	DEC	[rxCnt]
	JNZ	.Loop4			; Keep loading frame bytes

	MOV	A, [diffVar]
	JNZ	.doRxGo			; Wait until get duplicate frames

; ----------------------------------------------------------------------------
;
; Synchronized to Far-End Tx stream: Received duplicate valid VoIP frame.
;
; Now delay to proper phase and begin Rx/Tx cycling
;
; ----------------------------------------------------------------------------
	TEST_TIK_HI	; =======================
LOOP_DLY: 	equ	(445 * CPU_MHZ/9)	// 1 radio
CTR_INT_DLY:	equ	2
	MOV	X, >LOOP_DLY		;
	MOV	A, <LOOP_DLY		; Dead delay to sync
.Loop5:	DEC	A			; 4  (4 + 5) = 9 cycles/iteration
	JNZ	.Loop5			; 5
	DEC	X			;
	JNC	.Loop5			;
	; --------------------------------------------------------------------
	MOV	A, ISR_VAL_NOM_LSB
	MOV	X, ISR_VAL_NOM_MSB
	LCALL	PWM16_1_WritePeriod	; Resync counter to NOW
	LCALL	PWM16_1_Start
	; --------------------------------------------------------------------

	TEST_TIK_LO	; =======================
	MOV	[_slotCt], 6		; Next is Rx Slot 0
	JMP	ctrIsrX

; ----------------------------------------------------------------------------
;
; SHORTER VERSIONS OF RADIO DRIVER FUNCTIONS
;
;			 This routine is for 24MHz CPU and 3 MHz SPI
;
; isrRadioWrite:   A: The register number to write.
;                  X: The value to write to the selected register.
; isrRadioRead :   A: The register number to write.
;                  X: undefined
; ----------------------------------------------------------------------------
isrRadioWrite:
isrRadioRead:
	radioSelect
	; Write the address.
	MOV	REG[SPI_TX_REG], A
.wait1:	TST	REG[SPI_CTRL_REG], SPI_TX_EMPTY
	JZ	.wait1

     	; Write the data (Read just clocks the shift-register)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -