📄 mpc_play.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 + -