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

📄 mp3drq.asm

📁 这项工程将让您把自己的MP3播放器平台
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;   R0 contains the address of the next buffer on the play list.  Update
; m_pPlayListHead to remove that buffer from the list...
ISR11:	MOV  	_g_pPlayListHead, @R0	;  ... m_pPlayListHead = m_pPlayListHead->pNext
	MOV	R1, AR10		; copy R0 so we don't have to restore it later
;   Load R6/R7 with the address (in xdata) of the actual data buffer that goes
; with this BCB, and load R4/R5 with the count of bytes (up to 512) in this buffer.
	INC	R1			; pbBuffer is the second field in the BCB
	MOV	A, @R1			;  ... get the low byte
	MOV	R7, A			;  ... we keep that in R7
	INC	R1			; and then the high byte
	MOV	A, @R1			;  ...
	MOV	R6, A			;  ... (R6/R7) = (R0)->pbBuffer;
	INC	R1			; cbBuffer is the next field in the BCB
	MOV	A, @R1			;  ... low byte
	MOV	R5, A			;  ...
	INC	R1			;  ...
	MOV	A, @R1			;  ... and high byte 
	MOV	R4, A			;  ... (R4/R5) = (R0)->cbBuffer;

;   Here if the current buffer and is valid and, by implication, so are R4/R5
; and R6/R7....
ISR20:	MOV  	DPL, R7			; load DPTR with the address of the next byte
	MOV  	DPH, R6			;  ...
	MOVX	A, @DPTR		; load the next byte of MP3 data
	INC	DPTR			; and increment the buffer pointer
	MOV	R7, DPL			; save the new address for next time
	MOV	R6, DPH			;  ...

	.if	FAST_SDI
;   In FAST_SDI mode we need to reverse the order of the bits in this byte
; (using m_abReverseBits, of course) and then send it to SBUF.  The 8051
; UART hardware will handle the rest.  Note that it's not necessary to
; check the TI flag here because the 8051 will shift out the byte in only
; 9 machine cycles, and this loop takes far longer than that!
	MOV  	DPTR, #m_abReverseBits	; point to m_abReverseBits
	MOVC 	A, @A+DPTR		; lookup m_abReverseBits[data]
	MOV  	SBUF, A			; and send that to the STA013
	.else
;   In DEBUG (non-FAST_SDI) mode, we have to shift out the eight bits
; one at a time, MSB first, and toggle SCK (serial clock) for each one.
	MOV	R1, #8			; shift out 8 bits
ISR21:	RLC	A			; move the MSB into the carry
	MOV	STA013_ALT_SDI, C	; output the data bit
	SETB	STA013_ALT_SCK		; pulse the clock
	CLR	STA013_ALT_SCK		; ...
	DJNZ	R1, ISR21		; and loop for 8 bits
	.endif

;   Decrement the count of bytes remaining (kept in R4/R5) and, if it's zero,
; put this buffer on the free list and clear R0.  Clearing R0 will make the
; code at the beginning of this ISR attempt to pull a new buffer off the play
; list the next time around.
	DEC	R5			; decrement the LSB of cbBuffer
	CJNE	R5, #0xFF, ISR30	; jump if there's no borrow
	DEC	R4			;  ... and decrement the MSB if there is
ISR30:	MOV	A, R5			; see if cbBuffer == 0
	ORL	A, R4			;  ...
	JZ	ISR31			; jump if this buffer is empty
;   The current buffer still has data.  If the STA013 is still asserting DRQ,
; then loop back and send it another byte.  If, however, the STA013 has rel-
; eased DRQ then we can safely exit from this interrupt.  Remember that the
; DRQ input is active LOW!!!
	JNB	STA013_DATAREQ, ISR20	; jump if the STA013 wants more data
	SJMP	ISR99			; nope - go dismiss this interrupt

;   Here if we've sent all the bytes in this buffer.  First, put the current
; buffer on the free list (otherwise it'll be lost forever!) and the get a
; new buffer...
ISR31:  MOV  	@R0, _g_pFreeBufferList	; (R0)->pNext = m_pFreeBufferList
	MOV  	_g_pFreeBufferList, R0	; m_pFreeBufferList = R0
	MOV	R0, #0			; R0 == NULL indicates no current buffer
;   If the STA013 is still asserting DRQ (remember that its active low!) then
; try to get another buffer now.  Otherwise, we can safely exit now as long
; as R0 contains NULL...
	JNB	STA013_DATAREQ, ISR10	; jump if the STA013 wants more data
;	SJMP	ISR99			; nope - go dismiss this interrupt
	
;   One way or another, we're all done with this interrupt.  Restore the
; original registers and register bank and return...
ISR99:	CLR  	LED_BIT			; (LED off for timing purposes)
	POP  	PSW			; restore register bank and flags
	POP  	DPL			; restore other registers
	POP  	DPH			;  ...
	POP  	ACC			;  ...
	RETI 				; and dismiss the interrupt


;++
; BOOL IsPlayListEmpty (void)
;
;   This routine will return TRUE if the current MP3 buffer queue is empty
; and FALSE if data still remains.  You might be tempted to simply say
; "if (g_pPlayListHead == NULL)", but that doesn't work because MP3DRQ actually
; removes the current buffer from the play list.  Therefore g_pPlayListHead
; will become NULL even though there's still one more buffer left in the
; works...
;--
_IsPlayListEmpty:
;   The first thing is just to test the play list queue - if g_pPlayListHead
; isn't null, then it's guaranteed that the play list isn't empty...
	MOV	DPL, #0			; assume the result is FALSE
	MOV  	A, _g_pPlayListHead	; check the play list queue
	JZ	EMPTY1			; jump if it's empty
	RET				; not empty - return FALSE now

;   Here if the queue is empty - check to see if there's still a buffer "in
; progress" (the pointer to the BCB will in R0 of register bank #1).  Note
; that this code cheats a bit, bit it's must faster than explicitly changing
; register banks (which requires disabling interrupts and the whole thing!).
EMPTY1:	MOV	A, AR10			; fetch R0 from register bank 1
	JZ	EMPTY2			; jump if pBCB == NULL
	RET				; not null - return FALSE

; Here if the play list really is empty...
EMPTY2:	MOV	DPL, #0xFF		; return TRUE
	RET				; and we're outta here
	

;++
; void FlushPlayList (void)
;
;   This routine will flush the MP3 "to be played" buffer queue, plus any
; buffer that's currently playing now.  This doesn't actually stop the
; STA013 decoder, and it's probably a good idea for the caller to do that
; first!
;--
_FlushPlayList:
	PUSH	IE			; all interrupts off while we change
	CLR	EA			;  ... the register bank
	MOV	PSW, #0x08		; select register bank 1

; Put the currently playing buffer (pBCB is in R0) on the free list...
	CJNE	R0, #0, FLUSH1		; is there a current buffer ?
	SJMP	FLUSH2			; nope - skip this
FLUSH1:	MOV  	@R0, _g_pFreeBufferList	; (R0)->pNext = m_pFreeBufferList
	MOV  	_g_pFreeBufferList, R0	; m_pFreeBufferList = R0

; Now return all the buffers in the playlist to the free pool...
FLUSH2:	MOV  	R0, _g_pPlayListHead	; remove the next BCB from the play list
	CJNE	R0, #0, FLUSH3		; jump if we really got a buffer
	SJMP	FLUSH4			; no more buffers on the list
FLUSH3:	MOV  	_g_pPlayListHead, @R0	;  ... m_pPlayListHead = m_pPlayListHead->pNext
	MOV  	@R0, _g_pFreeBufferList	; (R0)->pNext = m_pFreeBufferList
	MOV  	_g_pFreeBufferList, R0	; m_pFreeBufferList = R0
	SJMP	FLUSH2			; and keep flushing

; Reset all the registers and then we can return...
FLUSH4:	SJMP	INIT10			; (re)initialize all registers and return


;++
; void InitializeMP3DRQ (void)
;
;   This routine will initialize the MP3 data request handler.  It will
; configure the 8051's external interrupt hardware as required and it will
; initialize the register bank used by the ISR.  It does NOT, however, turn
; on the interrupts!
;--
_InitializeMP3DRQ:

; Initialize the register bank used by the ISR...
	PUSH	IE		; no interrupts while we've changed
	CLR	EA		;  ... the register bank
	MOV  	PSW, #0x08	; select register bank 1
INIT10:	MOV	A, #0		; clear registers 0..7
	MOV	R0, A		;  ...
	MOV	R1, A		;  ...
	MOV	R2, A		;  ...
	MOV	R3, A		;  ...
	MOV	R4, A		;  ...
	MOV	R5, A		;  ...
	MOV	R6, A		;  ...
	MOV	R7, A		;  ...

;   Initialize the playback buffer queue to empty.  Note that if there
; are any _real_ buffers on this list (if, for example, we just aborted
; a playback) then the caller had better free them before calling this
; routine again!
	MOV	_g_pPlayListHead, #0
	MOV	_g_pPlayListEnd, #0

; Now we can re-enable interrupts...
	MOV	PSW, #0x00	; back to the default register bank
	POP	IE		; and restore interrupts

	.if	FAST_SDI
;   For FAST_SDI mode, configure the 8051's hardware UART to mode 0
; (synchronous shift register).  This mode is automatically clocked
; at 1/6th the CPU clock (on a 6 clock per cycle Philips part; it's
; 1/12th the CPU clock on a regular 8051), so no timer is needed to
; generate a baud rate.
	MOV	SCON, #0x1C	; mode 0
	.else
;   For DEBUG (slow) mode, configure the alternate STA013 clock and
; data outputs....
	CLR	STA013_ALT_SCK	; clock low
	CLR	STA013_ALT_SDI	; and data low too
	.endif

; Configure the 8051's interrupt system...
	CLR	IT0		; INT0 level sensitive
; Set interrupt priority here???
	
	RET

⌨️ 快捷键说明

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