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

📄 mpc_play.asm

📁 8051 mp3 very good for using
💻 ASM
字号:
;-----------------------------------------------;
; Playback Mode

pb_start:
	 rcall	load_track	; Load resume status
	in	r6, SREG	; Save result
	 rcall	init_index	; 
	stsi	Stm1,STPHLD	; Check key holding time
	lds	r16,Stm1	; 
	tst	r16		; 
	breq	pb_suffle	; 
	lds	r16,KeyReg+1	; 
	tst	r16		; 
	brne	PC-7		; /
	out	SREG, r6	; Restore resume result
	breq	pb_main		; If can't resume or track top, start normaly.
	 rcall	ready_resume	; Ready to resume
	stsi	FtmMr,MTMR	; Trigger muting delayed release
	rjmp	pb_loop

pb_suffle:
	 rcall	beep2		; Confirmation beep
	inc	r18		; Make random base
	in	r16,PINB	; 
	com	r16		; 
	andi	r16,0b10011	; 
	brne	PC-4		; /
	 rcall	init_index	; Make suffled index
	sts	TrkIdx,_0


;-----------------------------------------------;

pb_main:			; Start new track
	 rcall	dac_off		; Muting
	cbi	PORTD,WSEN	; Stop DSP
	andi	_PbStat,0b001	; Clear playing state
	stsi	Stm1,TRKGAP	; Track gap timer

pb_loop:sbrc	_PbStat,2	; End of playing ?
	rjmp	pb_next2	;  yes, next track
	cli			; Load Key input
	lds	r18,KeyCmd	; 
	sts	KeyCmd,_0	; 
	sei			; /
	cpi	r18,K_STOP	;  STOP ?
	rjeq	pb_stop		;  /
	cpi	r18,K_PREV	;  PREV ?
	breq	pb_prev		;  /
	cpi	r18,K_NEXT	;  NEXT ?
	breq	pb_next		;  /
	cpi	r18,K_PLAY	;  PLAY/PAUSE ?
	breq	pb_pause	;  /
	cpi	r18,K_VOLU	;  VOL+ ?
	breq	pb_vol		;  /
	cpi	r18,K_VOLD	;  VOL- ?
	breq	pb_vol		;  /

	cpi	_PbStat,0b000	; In track gap ?
	brne	pb_loop		;  no, continue
	lds	r16,Stm1	; 500ms passed ?
	cpi	r16,0		;  no, continue
	brne	pb_loop		; /

	 rcall	disp_track	; Start to play
	 rcall	idx2trk		; Track number from track index
	 rcall	ready_play	; Ready to play
	stsi	FtmMr,MTMR	;  Trigger muting delayed release
	rjmp	pb_loop		; /


pb_next:			; NEXT button
	 rcall	beep1
pb_next2:			; Next track by EOT
	lds	r16,TrkIdx
	lds	r17,Tracks
	inc	r16
	cp	r16,r17
	brcs	PC+2
	ldi	r16,0
	sts	TrkIdx,r16
	rjmp	pb_main

pb_prev:			; PREV button
	 rcall	beep1
	sbrc	_PbStat,1
	rjmp	pb_main
	lds	r16,TrkIdx
	subi	r16,1
	brcc	PC+4
	lds	r16,Tracks
	dec	r16
	sts	TrkIdx,r16
	rjmp	pb_main

pb_vol:				; VOL+/- button
	 rcall	pb_volset
	brne	PC+3
	 rcall	beepL
	rjmp	pb_loop
	stsi	Stm2,VOLRATE
	lds	r16,Stm2
	tst	r16
	breq	PC-10
	lds	r16,KeyReg+1
	cp	r16,r18
	breq	PC-7
	rjmp	pb_loop
pb_volset:
	cpi	r18,K_VOLU
	rjeq	inc_volume
	rjmp	dec_volume

pb_pause:			; PLAY/PAUSE button
	ldi	r16,0b001	; Toggle state flag
	eor	_PbStat,r16	; 
	sbrc	_PbStat,0	; 
	 rcall	beep1		; 
	 rcall	set_led		; /
	sbrs	_PbStat,1	; Playing ?
	rjmp	pb_loop		;  no, exit
	sbrs	_PbStat,0	; 
	rjmp	PC+4		; 
	 rcall	dac_off		; Muting
	cbi	PORTD,WSEN	; Stop DSP
	rjmp	pb_loop		; / 
	sbi	PORTD,WSEN	; Start DSP
	stsi	FtmMr,MTMR	; Trigger muting delayed release
	rjmp	pb_loop

pb_stop:			; STOP button
	 rcall	dac_off		; Muting
	cbi	PORTD,WSEN	; Stop DSP
	 rcall	save_volume	; Save volume setting
	lds	r16, KeyReg+1	; If LBD stop, save resume status.
	cpi	r16, K_STOP	; 
	rjne	save_track	; /
	stsi	Stm1,STPHLD	; When STOP button is pressed for one second,
	lds	r16,KeyReg+1	;  stop with save resume status.
	cpi	r16,K_STOP	;  If released within one second,
	brne	pb_end		;  stop immediataly without save.
	lds	r16,Stm1	; 
	tst	r16		; 
	brne	PC-7		; /
pb_save:
	 rcall	save_track	; Save resume status and short beep.
	 rcall	beep1		; 
	lds	r16,StmBp	; 
	tst	r16		; 
	brne	PC-3		; /
pb_end:
	ret			; Terminate playback mode



set_led:			; Set LED state
	sbic	DDRD,VREF
	ret
	ldi	r16,0x40
	sbrs	_PbStat,0
	ldi	r16,0xff
	sts	MskLed,r16
	ret

beep2:	ldi	r16,0b00001000	; Double beep
	ldi	r17,0b00000010
	rjmp	beep
beepL:	ldi	r16,0b00001000	; Long beep
	ldi	r17,0b00000111
	rjmp	beep
beep1:	ldi	r16,0b00000100	; Short beep
	ldi	r17,0b00000011
beep:	sts	StmBp,r16
	sts	MskBp,r17
	out	TCNT1H,_0
	out	TCNT1L,_0
	out	OCR1AH,_0
	outi	OCR1AL,13
	ret



;-----------------------------------------------;
; Display Track info

disp_track:
	ldi	r16,0x0a	; LF
	 rcall	xmit		; /
	 rcall	idx2trk		; Get track number and display
	push	r16		; 
	 rcall	cv_dec		; 
	 rcall	dp_byte		; /
	ldi	r16,'.'		; ". "
	 rcall	xmit		; 
	 rcall	space		; /
	pop	r16		; ID3 tag...
	 rcall	disp_id3	; /
	ldi	r16,0x0d	; CR
	rjmp	xmit		; /



;-----------------------------------------------;
; Get track number from track index
;
; Call: TrkIdx = Track index
; Ret:  r16 = Track number (0..

idx2trk:
	lds	r16,TrkIdx
	ldiw	Z,TrkTbl
	add	ZL,r16
	adc	ZH,_0
	ld	r16,Z
	ret



;-----------------------------------------------;
; Ready to play with direct numbered
;
; Call: r16 = Track number to play

ready_play:
	 rcall	get_trkpar	; Get track top and length
	ldi	r16,2		; Purge tail page.
	sub	_CntL,r16	; 
	sbc	_CntM,_0	; 
	sbc	_CntH,_0	; /

;-----------------------------------------------;
; Ready to resume
;
; Call: _PageX,_CntX = Resume parameters

ready_resume:
	 rcall	sm_rd_page	; Read page data
	ldi	_PgPtL,low(512)	; Page xfer count
	ldi	_PgPtH,high(512); /
	ori	_PbStat,0b010	; Enable xfering
	andi	_PbStat,0b011	; /
	sbi	PORTD,WSEN	; Start DSP
	ret



;-----------------------------------------------;
; Initialize track order table
;
; Call: r18 = 0:Incremental, >0:Randomize

init_index:
	sts	Random,r18	; Save randomize base
	ldiw	Z,TrkTbl	; Z = track table

	tst	r18		; if > 0 make suffled table
	brne	PC+6		; else make sequencial table
	st	Z+,r18		; Make sequencial table
	inc	r18		; 
	cpi	r18,NTRK	; 
	brcs	PC-3		; /
	ret

	ldi	r19,1
	lds	_LoopL,Tracks
	mov	_LoopM,_LoopL
	ldi	_LoopH,1
mki_lp:	bst	r18,3		;PN code generator (r19:r18)
	bld	r16,0		; length = 9 bit
	eor	r16,r19		; dir = left
	lsr	r16		; tap = 9,3
	rol	r18		;
	rol	r19		;/
	mov	r16,r18		;r16 = r18 mod Trasks
	sub	r16,_LoopM	;
	brcc	PC-1		;
	add	r16,_LoopM	;/
	ldiw	Y,TrkTbl	;Check duplicated track
	mov	r5,_LoopH	;
	rjmp	PC+4		;
	ld	r17,Y+		;
	cp	r16,r17		;
	breq	mki_lp		;
	dec	r5		;
	brne	PC-4		;/
	st	Z+,r16		;Put a track number into table
	inc	_LoopH
	dec	_LoopL
	brne	mki_lp
	ret


;-----------------------------------------------;
; MPEG data transfer
;
; This routine is called by 500Hz interrupt handler

.macro	sbmpd
	bst	r16,@0
	bld	r17,MPDAT
	out	PORTC,r17
	cbi	PORTC,MPCK
.endm


mpeg_xfer:
	sbrs	_PbStat,1	; Playing ?
	ret			;  no, exit
	cbi	PORTC,CE	; Enable SM
	ldi	_Loop,67	; Xfer limitation par interrupt
mpx_lp:	sbis	PIND,DRQ	; Has DSP requesting data ?
	rjmp	mpx_e		;  no, exit data xfer
	dec	_Loop		; Xfer limit par interrupt is reached ?
	rjeq	mpx_e		;  yes, leave off xfering
	cbi	PORTC,RE	; Load byte data into r16
	nop			; 
	in	r16,PINA	; 
	sbi	PORTC,RE	; /
	in	r17,PORTC	; Get PortC data into r17
	sbr	r17,(1<<MPCK)	; /
	sbmpd	7		; Send from bit7 trough bit0
	sbmpd	6		; *Show macro "sbmpd"
	sbmpd	5		; 
	sbmpd	4		; 
	sbmpd	3		; 
	sbmpd	2		; 
	sbmpd	1		; 
	sbmpd	0		; /
	subi	_PgPtL,1	; Loop Count--
	sbci	_PgPtH,0	; If not reached end of page,
	brne	mpx_lp		;  continue byte-loop.
	ldi	r16,1		; If --_CntX == 0, stop playback
	sub	_CntL,r16	; 
	sbc	_CntM,_0	; 
	sbc	_CntH,_0	; 
	breq	PC+11		; /
	 rcall	sm_read		; Get linked next page#
	mov	_PageL,r16	; 
	 rcall	sm_read		; 
	mov	_PageM,r16	; 
	 rcall	sm_read		; 
	mov	_PageH,r16	; /
	 rcall	sm_rd_page	; Read next page data
	ldi	_PgPtL,low(512)	; Page count
	ldi	_PgPtH,high(512); /
	rjmp	mpx_lp		; Continue xfering

	rcall	dac_off		; Mute
	ldi	_PbStat,0b100	; Stop with end of track

mpx_e:	sbi	PORTC,CE	; Disable SM
	ret


⌨️ 快捷键说明

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