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

📄 drivers.asm

📁 A MP3 Player Source Code, Enjoy it!
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	mov	dpl, a	ljmp	return_addr;*************************************************************;**                                                         **;**           MP3 Playback (DMA Request Queue)              **;**                                                         **;*************************************************************	;add a block (r2/r3) to the playback request queue	;c=0 for success, c=1 if request queue is full.  The	;application calls here to cause MP3 data to be played	;r4/r5 pass the number of bytesplay_block_c:	push flags2	 ;setb debug	 mov	dptr, #msg_play_block	 lcall	pstr_d	 mov	a, r3	 lcall	phex_d	 mov	a, r2	 lcall	phex_d	 lcall	space_d	 mov	a, r5	 lcall	phex_d	 mov	a, r4	 lcall	phex_d	 lcall	space_d	 lcall	block_desc_addr	 inc	dptr	 inc	dptr	 inc	dptr	 inc	dptr	 movx	a, @dptr	 inc	dptr	 push	acc	 movx	a, @dptr	 inc	dptr	 push	acc	 movx	a, @dptr	 inc	dptr	 lcall	phex_d	 pop	acc	 lcall	phex_d	 pop	acc	 lcall	phex_d	 lcall	space_d	 inc	dptr	 inc	dptr	 inc	dptr	 inc	dptr	 inc	dptr	 movx	a, @dptr	 inc	dptr	 push	acc	 movx	a, @dptr	 inc	dptr	 push	acc	 movx	a, @dptr	 inc	dptr	 push	acc	 movx	a, @dptr	 lcall	phex_d	 pop	acc	 lcall	phex_d	 pop	acc	 lcall	phex_d	 pop	acc	 lcall	phex_d	 lcall	newline_d	pop flags2	clr	c	mov	a, r5		;convert # bytes into 16 bit words	rrc	a	mov	r5, a	mov	a, r4	rrc	a	addc	a, #0	mov	r4, a	mov	a, r5	addc	a, #0	mov	r5, a	clr	ex0		; -- disable STA013 interrupt here	mov	a, play_req_head	cjne	a, #255, play_block2	;kickstart the playing, since we're not expecting an interrupt	push flags2	 ;setb debug	 mov	dptr, #msg_play_block	 lcall	pstr_d	 lcall	pstr_d	pop flags2	clr	a	mov	play_req_head, a	mov	play_req_tail, a	lcall	play_dma	setb	ex0	jb	mute_is_on, turn_mute_off	mov	dpl, #0	ljmp	return_addrturn_mute_off:	mov	r4, #20	mov	r3, #0	lcall	sta013_write		;mute off	mov	r0, #100		;brief delay, to transfer enough	djnz	r0, *			;mp3 data to get the sta013 to					;move from "init" to "decode" mode	mov	r4, #20	mov	r3, #0	lcall	sta013_write		;mute off	mov	r4, #114	mov	r3, #1	lcall	sta013_write		;start playing	clr	mute_is_on	mov	dpl, #0	ljmp	return_addrplay_block2:	inc	a	cjne	a, #play_req_size, play_block3	clr	aplay_block3:	cjne	a, play_req_tail, play_block4	;if we get here, the play request queue is full, so we	;can't add this block	setb	ex0		; -- reenable STA013 interrupt here	mov	dpl, #1	ljmp	return_addrplay_block4:	mov	play_req_head, a	rl	a	rl	a	add	a, #play_req & 255	mov	dpl, a	clr	a	addc	a, #play_req >> 8	mov	dph, a			;now DPTR points to new request	mov	a, r2	movx	@dptr, a		;write block number to queue	inc	dptr	mov	a, r3	movx	@dptr, a	inc	dptr	mov	a, r4			;write data length to queue	movx	@dptr, a	inc	dptr	mov	a, r5	movx	@dptr, a	setb	ex0		; -- reenable STA013 interrupt here	mov	dpl, #0	ljmp	return_addrplay_abort_c:	clr	ex0			;disable STA013 interrupt	mov	dptr, #dma_mp3_count+1	clr	a	movx	@dptr, a		;stop current DMA transfer, if any	mov	dptr, #dma_mp3_count	;actually set it so that just one	inc	a			;more word is to be transfered	movx	@dptr, a		;by tweaking "dma_mp3_count".	mov	a, play_req_head	cpl	a	jz	play_abort3play_abort2:	clr	a	mov	play_req_tail, a	;flush play request queue	mov	play_req_head, aplay_abort3:	setb	ex0			;reenable STA013 interrupt	;should tell the STA013 to flush its input buffer, if	;that can be done somehow	ljmp	return_addr	;normally this is done by the interrupt routine, but for	;the very first block played, we're not expecting an	;interrupt, so we have to start it manually.	; TODO: it would be cleaner if the FPGA had a feature	; to manually set the interrupt... then we could just	; set it and let "isr.asm" handle this task.play_dma:	;let's map the block with the MP3 data to 0x9000	mov	dptr, #dram_page_cfg + (0x09 * 2)	mov	a, r2	movx	@dptr, a	inc	dptr	mov	a, r3	movx	@dptr, a	;finally, we're done with the memory management stuff, and	;we can now set up the DMA transfer and start it.	mov	dptr, #dma_mp3_src	clr	a	movx	@dptr, a		;write LSB of src addr	inc	dptr	mov	a, #0x90	movx	@dptr, a		;write MSB of src addr	mov	dptr, #dma_mp3_count	mov	a, r4	movx	@dptr, a		;write LSB of length	inc	dptr	mov	a, r5	movx	@dptr, a		;write MSB of length	clr	a	mov	dptr, #dma_mp3_go	movx	@dptr, a		;begin the transfer	;now the DMA is happening... in all likelyhood, the STA013 has	;already asserted its DATA_REQ signal by the time we could get	;through all that work to set up the DMA transfer.  If the	;latency of this code ever gets to be a problem, the FPGA	;will probably have to be changed to double buffer STA013	;DMA requests, which would allow 0.1 second latency for the	;fastest MP3 (320 kbps) !!	mov	dptr, #num_blks_played	movx	a, @dptr	add	a, #1		;increment "num_blks_played"	movx	@dptr, a	inc	dptr	movx	a, @dptr	addc	a, #0	movx	@dptr, a	retplay_dma_irq_enable:        clr     a        mov     dptr, #irq_dma_ide_ack        movx    @dptr, a        mov     dptr, #irq_dma_mp3_ack        movx    @dptr, a        mov     dptr, #irq_memcpy_ack        movx    @dptr, a        mov     dptr, #irq_mask        mov     a, #00000010b        movx    @dptr, a        mov     play_req_head, #255        mov     play_req_tail, #255        anl     tcon, #0xF0             ;low level trigger interrupts        setb    ex0	clr	es	;shouldn't be here        setb    ea	ljmp	return_addr	;return the number of available position in the play	;queue.  If it's zero, the playback queue is full and	;an attempt to call "play_block" will return with C=1	; (perhaps there's a more efficient way to do this math?)play_queue_avail_c:	clr	ex0			;disable STA013 interrupt here	mov	r0, play_req_tail	mov	a, play_req_head	setb	ex0			;reenable STA013 interrupt here	cjne	a, #255, pqav2	mov	a, #play_req_size-1	mov	dpl, a	ljmp	return_addrpqav2:	clr	c	subb	a, r0	jnc	pqav3	add	a, #play_req_sizepqav3:	;now acc has the number that are in the queue	mov	r0, a	mov	a, #play_req_size	clr	c	subb	a, r0	;now acc has the number of avaiable slots, but	;one is never used, so we need to subtract 1	jz	pqav4	add	a, #255pqav4:	mov	dpl, a	ljmp	return_addr	; TODO: simplify this function	;return C=1 if the playback queue is completely emptyis_play_queue_empty_c:	mov	dptr, #msg_play_queue_empty	lcall	pstr_d	clr	ex0	mov	r0, play_req_head	mov	r1, play_req_tail	setb	ex0	mov	a, r0	lcall	phex_d	mov	a, #'-'	lcall	cout_d	mov	a, r1	lcall	phex_d	lcall	newline_d	mov	a, r0	cpl	a	jz	pqempty2	clr	c	mov	dpl, #0	ljmp	return_addrpqempty2:	setb	c	mov	dpl, #1	ljmp	return_addrplay_suspend_c:	clr	ea	;clr	ex0	mov	dptr, #irq_mask	;movx	a, @dptr	;anl	a, #11111101b	;movx	@dptr, a	mov	a, #00000000b		;turns off IDE interrupt	movx	@dptr, a	;setb	ex0	setb	ea	ljmp	return_addrplay_resume_c:	clr	ea	;clr	ex0	mov	dptr, #irq_mask	;movx	a, @dptr	;orl	a, #00000010b	;movx	@dptr, a	mov	a, #00000010b		;turns off IDE interrupt	movx	@dptr, a	;setb	ex0	setb	ea	ljmp	return_addr	;return the number of blocks played (since the last call	;to this function).  This will allow the appication to track	;the status of playback, perhaps to print elapsed/remaining	;time on the LCD display.play_num_sent:	mov	dptr, #num_blks_played	clr	ex0			;disable STA013 interrupt here	movx	a, @dptr	mov	r4, a	clr	a	movx	@dptr, a	inc	dptr	movx	a, @dptr	mov	r5, a	clr	a	movx	@dptr, a	setb	ex0			;reenable STA013 interrupt here	ret;this test may seem extreemly paranoid, but there have been problems;initializing some STA013 chips, where the problem basically shows;up as the data request pin being stuck either high or low and the;chip produces no sound.  The chip otherwise appears to be working,;so the only good way to detect the problem is to send a short clip;of MP3 data, larger than the STA013's input buffer, that is a known;length of time, and measure how long it takes the STA013 to consume;all the input data.  This code sends a 1/2 second clip of silent;MP3 (1046 bytes long), and measures the elapsed time with a simple;delay loop.  DPL=0 is the correct time elapses, of DPL=1 if the STA013;consumes the data too quickly or too slowly (including timeout).test_sta013_c:	;grab a block and map it at 0x9000.... this code is used	;before the memory manager is initialized, so we can not	;call malloc to get a block.  We'll just grab a block and	;use it.	mov	r2, #34	mov	r3, #0	mov	a, #9	lcall	map_block	;fill it with a null mp3 data that represents        ;approximately 0.26 seconds of silence	mov	dptr, #0x9000	mov	r1, #16        acall   fill_null_mp3        mov     dptr, #msg_test_sta013        lcall   pm2_pstr        mov     dptr, #dma_mp3_src        clr     a        movx    @dptr, a                ;write LSB of src addr        inc     dptr        mov     a, #0x90        movx    @dptr, a                ;write MSB of src addr        mov     dptr, #dma_mp3_count        mov     a, #0x40        movx    @dptr, a                ;write LSB of length        inc     dptr        mov     a, #0x03        movx    @dptr, a                ;write MSB of length        clr     a	mov	dptr, #irq_dma_mp3_ack	movx	@dptr, a		;make sure dma intr bit clear        mov     dptr, #dma_mp3_go        movx    @dptr, a                ;begin the transfer	;time how long it take for the STA013 to consume this data        mov     r7, #0                  ;r7 to count # of loopstest_mp3_wait:        mov     r6, #0test_mp3_wait2:        mov     dptr, #irq_ident        ;2        movx    a, @dptr                ;2        jb      acc.1, test_play_done   ;2        djnz    r6, test_mp3_wait2      ;2        inc     r7        cjne    r7, #80, test_mp3_wait2        ;now r7 will have an integer which represents how long we        ;had to wait for the sta013 to completely consume this data	; ... it should take r7 == 0x4Etest_play_done:        mov     dptr, #msg_play_len        lcall   pm2_pstr        mov     a, r7        lcall   pm2_phex	mov	a, #' '        lcall   pm2_cout	mov	a, #' '        lcall   pm2_cout        ;did we pass the test...        mov     a, r7        add     a, #190        jnc     test_sta013_fail        mov     a, r7        add     a, #166        jc      test_sta013_fail        mov     dptr, #mesg_ok        lcall   pm2_pstr	mov	dpl, #0	ljmp	return_addrtest_sta013_fail:        mov     dptr, #mesg_error        lcall   pm2_pstr	mov	dpl, #1	ljmp	return_addrfill_null_mp3_c:	mov	dpl, r2	mov	dph, r3	lcall	fill_null_mp3	ljmp	return_addr	;create silent MP3 bitstream data @ DPTR.  R1 specifies	;the number of frames to create.  Each frame is 104 bytes.	;the resulting mp3 data is 44.1 kHz mono samples encoded	;at 32 kbps (no padding, so bitrate is actually 31.9 kbps).	;each frame should play for 26 ms.fill_null_mp3:	mov	r0, #0f_null_loop1:	inc	r0	lcall	f_null_lookup	movx	@dptr, a	inc	dptr	cjne	r0, #18, f_null_loop1	mov	r0, #86	clr	af_null_loop2:	movx	@dptr, a	inc	dptr	djnz	r0, f_null_loop2	djnz	r1, fill_null_mp3	retf_null_lookup:	mov	a, r0	movc	a, @a+pc	ret	.db	0xFF, 0xFB, 0x10, 0xC4, 0x00, 0x03, 0xC0, 0x00, 0x01	.db	0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x80	sta013_get_attenuation:	mov	r4, #0x46	lcall	sta013_read	mov	dpl, r3	ljmp	return_addrsta013_set_attenuation:	mov	a, r3	add	a, #256 - max_attenuation	jnc	sta013_set_atn2	mov	r3, #max_attenuationsta013_set_atn2:	 ;mov	dptr, #mesg_sta013_vol	 ;lcall	pstr	 ;mov	a, r3	 ;lcall	phex	 ;lcall	newline	mov	r4, #0x46		;write left attenuation	lcall	sta013_write	mov	r4, #0x48	lcall	sta013_write		;write right attenuation	ljmp	return_addrmesg_sta013_vol:	.db	"STA013 attenuation = ",0;*************************************************************;**                                                         **;**      Detect Partitions and FAT32 Filesystem Info        **;**                                                         **;*************************************************************	;detect what type of filesystem we're using, and initialize	;all the filesystem variables for it.  Return DPL=0 if the	;filesystem could not be detected, of DPL=non-zero if it was	;properly detected.  Perhaps someday the non-zero code would	;represent what type of filesystem... but today we can only	;handle FAT32 on hard drives.	.equ	sector_buffer, 0x7000detect_filesystem:	mov	a, #1	lcall	malloc_blocks	mov	a, #7	lcall	map_blockread_mbr:	mov	f32_sector+3, #0	mov	f32_sector+2, #0	mov	f32_sector+1, #0	mov	f32_sector+0, #0	mov	dptr, #mesg_read_mbr	lcall	pstr	mov	dptr, #sector_buffer	lcall	ide_read_sector	mov	dptr, #sector_buffer + 0x1FE	movx	a, @dptr	cjne	a, #0x55, bad_mbr	inc	dptr	movx	a, @dptr	cjne	a, #0xAA, bad_mbr	mov	dptr, #sector_buffer + 0x1C2	movx	a, @dptr	mov	r2, #1	lcall	partition_type	jc	found_partition	mov	dptr, #sector_buffer + 0x1D2	movx	a, @dptr	mov	r2, #1	lcall	partition_type	jc	found_partition	mov	dptr, #sector_buffer + 0x1E2	movx	a, @dptr	mov	r2, #1	lcall	partition_type	jc	found_partition	mov	dptr, #sector_buffer + 0x1F2	movx	a, @dptr	mov	r2, #1

⌨️ 快捷键说明

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