;MP3 Player kunio.h Ver2.7(CPU:4MHz,VS1001K:12.288MHz) H16.2.25
;**** includes ****
.include "m8def.inc"
; Load immediate word into the resister pair.
; ldiw Z(X,Y),var
.macro ldiw
ldi @0L,low(@1)
ldi @0H,high(@1)
.endm
; Output immediate outi port,var
.macro outi
ldi r16,@1
out @0,r16
.endm
.MACRO cpi16 ;cpi16 ra,rb,0xHHHH ;ra:rb-0xHHHH set flags:N,C,Z
push @0
push @1
subi @1,low(@2)
sbci @0,high(@2)
pop @1
pop @0
.ENDMACRO
.MACRO addi16 ;addi16 ra,rb,0xHHHH
subi @1,low(-@2)
sbci @0,high(-@2)
.ENDMACRO
;*****************************
;* レジスタ変数 設定 *
;*****************************
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def temp4 = r19
.def lcd_data= r23
;*****************************
;* ビット 設定 *
;*****************************
;** PORTB ***
.equ sw_0 = 0
.equ sw_1 = 1
.equ sd_cs = 2 ;SS
.equ sd_in = 3 ;MOSI
.equ sd_out = 4 ;MISO
.equ sd_clk = 5 ;SCK
.equ sw_6 = 6
.equ sw_7 = 7
;** PORTD **
.equ mp3_dreq= 0
.equ p_hold = 1 ;power hold
.equ sw_2 = 2
.equ led = 3
.equ mp3_reset=4 ;MP3~reset
;.equ = 5
;.equ = 6
;.equ = 7
;** PORTC ***
.equ v_in = 0 ;batt volt
.equ mp3_si = 1
.equ mp3_sclk = 2
.equ mp3_cs = 3
.equ mp3_bsync= 4
.equ mp3_dclk = 5
;key_in 76543210
.equ key_stop= 0b11000011
.equ key_ff = 0b01000111
.equ key_rew = 0b10000111
.equ key_vp = 0b11000101
.equ key_vm = 0b11000110
.dseg
mode: .BYTE 1 ;1:desk repeat,0:1time,2:1music repeat
fattype: .BYTE 1 ;FAT16:1,FAT12:0
datastart: .BYTE 4 ;DATAstart[3:0]
dirstart: .BYTE 2 ;DIRstart[1:0]
secpcl: .BYTE 1 ;sectorspercluster
fatstart: .BYTE 2 ;FATstart[1:0]
rdirent: .BYTE 2 ;rootdirentriescount[1:0]
spi_arg: .BYTE 5 ;cmd,arg[3:0]
read32_arg: .BYTE 4 ;adr[3:0]
musiccount: .BYTE 1 ;MP3 file count
playmusic: .BYTE 1 ;play music count
musicsize: .BYTE 4 ;play file size
cluster: .BYTE 2 ;play cluster
remainsec: .BYTE 2 ;play remain sector
buff: .BYTE 32 ;buff[31:0]
fatcache: .BYTE 512 ;FATcache
fatsec: .BYTE 3 ;FATcache'sector
volume: .BYTE 1
key_in: .BYTE 1
key_input: .BYTE 1
key_c: .BYTE 1
v_t: .BYTE 2
led_time: .byte 1
.eseg ;EEPROM add
rom_pm: .BYTE 1 ;play music
rom_cl: .BYTE 2 ;cluster
rom_re: .BYTE 2 ;remainsec
rom_mu: .BYTE 3 ;musicsize
rom_vo: .BYTE 1 ;volume
rom_mo: .BYTE 1 ;mode
.cseg
;*********************
;* 割込みベクター *
;*********************
rjmp start ;各種リセット
reti ;RJMP EXT_INT0 ;外部割り込み要求0
reti ;EXT_INT1 ;外部割り込み要求1
reti ;TIM2_COMP ;タイマ/カウンタ2 比較一致
reti ;TIM2_OVF ;タイマ/カウンタ2 オーバーフロー
reti ;TIM1_CAPT ;タイマ/カウンタ1 キャプチャ�生
reti ;TIM1_COMPA ;タイマ/カウンタ1 比較A 一致
reti ;TIM1_COMPB ;タイマ/カウンタ1 比較B 一致
rjmp TIM1_OVF ;タイマ/カウンタ1 オーバーフロー
rjmp TIM0_OVF ;タイマ/カウンタ0 オーバーフロー
reti ;SPI_STC ;SPI 転送完了
reti ;USART_RXC ;USART 受信完了
reti ;USART_DRE ;USART 送信バッファ空
reti ;USART_TXC ;USART 送信完了
reti ;ADC_E ;ADC 変換完了
reti ;EE_RDY ;EEPROM 操作可
reti ; ANA_COMP ;アナログ コンパレータ出力遷移
reti ;TWSI ;2 線式シリアル インターフェース状態変化
reti ;SPM_RDY ;SPM 命令操作可
;*********************
;* メイン プログラム *
;*********************
start:
ldi temp1,low(RAMEND)
out SPL,temp1
ldi temp1,high(RAMEND)
out SPH,temp1 ;init Stack Pointer
ldi temp1,0xA0 ;
out OSCCAL,temp1
ldi temp1,(1<<sd_cs)|(1<<sw_0)|(1<<sw_1)|(1<<sw_6)|(1<<sd_in)|(1<<sw_7)
out PORTB,temp1 ; sd_out no pull up,sd_clk clr
ldi temp1,(1<<sd_cs)|(1<<sd_clk)|(1<<sd_in)
out DDRB,temp1 ; sd_out,sw_0/1/6/7 in port
ldi temp1,0x3e ;pc1~5 out port,pc0 ad_in
out DDRC,temp1 ;
ldi temp1,0 ;pc1,2,3,4,5 clear
out PORTC,temp1
ldi temp1,0b11111010
out DDRD,temp1 ; pd1(p_hold),3-7 output port,0(mp_dreq),2(sw_2) input
ldi temp1,0x05 ; pd1,3-7 clear,0,2 pull up
out PORTD,temp1
ADC_int:
outi ADMUX,(1<<REFS0)|(1<<REFS1) ;基準電圧2.56V、結果右揃え、Ch0選択
outi ADCSR,(1<<ADPS2)|(1<<ADPS1) ;ADCck=4M/64=62.5k
ldi temp1,250
rcall wait_ms
sbi PORTD,p_hold ;power hold
sbi PORTD,mp3_reset ;mp3 un_reset
clr temp1
sts mode,temp1
sbi PORTD,led ;LED ON
;**********************************************************
;osc_ck: ;内臓OSCクロック校正
; sbi PORTD,7 ;PD7をHに設定 (2clock)
; nop ;時間� わせ(1clock)
; nop ;時間� わせ(1clock)
; cbi PORTD,7 ;PD7をLに設定 (2clock)
; rjmp osc_ck ;osc_ckに戻る (2clock)
;**********************************************************
in temp1,PINB
andi temp1,0b11000011
in temp2,PIND
andi temp2,0b00000100
or temp1,temp2
cpi temp1,0b11000001 ; 'power on'+'vol+'
brne play_data_init
ldi temp1,5
rcall wait_ms
in temp1,PINB
andi temp1,0b11000011
in temp2,PIND
andi temp2,0b00000100
or temp1,temp2
cpi temp1,0b11000001
brne play_data_init
erorr_rest_mode:
in temp1,PINB
andi temp1,0b11000011
in temp2,PIND
andi temp2,0b00000100
or temp1,temp2
cpi temp1,0b11000111 ;no key_in
brne erorr_rest_mode
ldi temp1,1
sts playmusic,temp1
clr temp1
sts cluster,temp1
sts cluster+1,temp1
rjmp reset_start
play_data_init:
ldiw z,rom_pm
rcall EEPROM_RD
sts playmusic,temp2
ldiw z,rom_cl
rcall EEPROM_RD
sts cluster,temp2
ldiw z,rom_cl+1
rcall EEPROM_RD
sts cluster+1,temp2
ldiw z,rom_re
rcall EEPROM_RD
sts remainsec,temp2
ldiw z,rom_re+1
rcall EEPROM_RD
sts remainsec+1,temp2
ldiw z,rom_mu
rcall EEPROM_RD
sts musicsize,temp2
ldiw z,rom_mu+1
rcall EEPROM_RD
sts musicsize+1,temp2
ldiw z,rom_mu+2
rcall EEPROM_RD
sts musicsize+2,temp2
ldiw z,rom_mo
rcall EEPROM_RD
cpi temp2,3
brcs mode_int
clr temp2
mode_int:
sts mode,temp2
reset_start:
ldiw z,rom_vo
rcall EEPROM_RD
cpi temp2,0x8A+1
brcc vol_init
cpi temp2,0x12
brcs vol_init
rjmp vol_set
vol_init:
ldi temp2,0x42 ;init vol
vol_set:
sts volume,temp2
ldi temp1,10
sts v_t+1,temp1
ldi temp1,0
sts v_t,temp1
sts fatsec,temp1
sts fatsec+1,temp1
sts fatsec+2,temp1
sts led_time,temp1
key_off_ck: ;power_SWを離したか
in temp1,PINB
andi temp1,0b11000011
in temp2,PIND
andi temp2,0b00000100
or temp1,temp2
cpi temp1,0b11000111 ;no key_in
brne key_off_ck
timer1_int:
; outi TCCR1B,(1<<CS11)|(1<<CS10) ;0x8000/(4M/64)=0.524s
outi TIMSK,1<<TOIE1 ;time1 Overflow Interrupt
; outi TCNT1H,0x80
; outi TCNT1L,0
spi_0: ;SPI/SD/MMC_int
outi SPCR,0x52 ;SPI master,CPOL0,CPHA=0,CK=4M/64*2=125k
sbi SPSR,SPI2X
spi_01:
ldi temp3,10 ;SD SPI mode 80クロック送信
spi_1:
rcall spi_in ;dumy clock
dec temp3
brne spi_1 ;SD SPI mode 移行CMD
cbi PORTB,sd_cs ;CS=L
ldi temp1,0
sts spi_arg,temp1 ;cmd
ldi temp1,BYTE4(0)
sts spi_arg+1,temp1 ;arg3
ldi temp1,BYTE3(0)
sts spi_arg+2,temp1 ;arg2
ldi temp1,BYTE2(0)
sts spi_arg+3,temp1 ;arg1
ldi temp1,low(0)
sts spi_arg+4,temp1 ;arg0
spi_11:
rcall spi_com ;(0,0) temp2:spi_com_return
cpi temp2,0xff ;card busy? $FF
breq spi_22 ;card error
cpi temp2,1 ;card ok? until return=1
breq spi_2
ldi temp1,10
rcall wait_us ;wait
rjmp spi_11
spi_2:
ldi temp1,1
sts spi_arg,temp1
spi_21:
rcall spi_com;(1,0)
cpi temp2,1 ;int OK? until return!=1
breq spi_21
spi_22:
sbi PORTB,sd_cs ;CS=H
outi SPCR,0x50 ;SPI master,CPOL0,CPHA=0,CK=4M/4=1M
sbi SPSR,SPI2X ;ck x 2 -> 2M
cpi temp2,0xFF
brne main_1
ldi temp1,1
mov r0,temp1
rjmp loop
main_1:
rcall read_vfat
tst temp2
breq main_2
ldi temp1,2
mov r0,temp1
rjmp loop
main_2:
ldi temp1,0xff
rcall search_mp3;temp2 <- MP3 count
tst temp2
brne main_3
ldi temp1,3
mov r0,temp1
rjmp loop
main_3:
sts musiccount,temp2 ;music count
lds temp1,playmusic
tst temp1
brne main_4
ldi temp1,1
sts playmusic,temp1
main_4:
rcall search_mp3 ;sarch temp1 MP3
lds temp1,buff+28
lds temp2,musicsize
cp temp1,temp2
brne main_5
lds temp1,buff+29
lds temp2,musicsize+1
cp temp1,temp2
brne main_5
lds temp1,buff+30
lds temp2,musicsize+2
cp temp1,temp2
breq play
main_5:
ldi temp1,1
sts playmusic,temp1
clr temp2
sts cluster,temp2
sts cluster+1,temp2
play:
rcall v_read
cpi16 zH,zL,305 ;about 3.0Vup
brcs play_b1
ldi temp1,5
rjmp play_b9
play_b1:
cpi16 zH,zL,285 ;about 2.8-3.0V
brcs play_b2
ldi temp1,4
rjmp play_b9
play_b2:
cpi16 zH,zL,265 ;about 2.6-2.8V
brcs play_b3
ldi temp1,3
rjmp play_b9
play_b3:
cpi16 zH,zL,245 ;about 2.4-2.6V
brcs play_b4
ldi temp1,2
rjmp play_b9
play_b4:
cpi16 zH,zL,225 ;about 2.2-2.4V
brcs play0
ldi temp1,1
play_b9:
mov r0,temp1
play_ba:
cbi PORTD,led
ldi temp1,150
rcall wait_ms
sbi PORTD,led
ldi temp1,150
rcall wait_ms
dec r0
brne play_ba
lds r20,key_input
play0:
outi TCNT1H,0x80
outi TCNT1L,0
outi TCCR1B,(1<<CS11)|(1<<CS10)
sei
lds temp1,playmusic
lds temp2,musiccount
cp temp2,temp1
brpl play_1 ;files => play_No
ldi temp1,1 ; <
sts playmusic,temp1
cpi r20,key_ff
breq play_1
lds temp4,mode
cpi temp4,1
brpl play_1
rjmp play_stop
play_1:
rcall play_mp3 ;arg=playmusic(temp1),cluster,remainsec
cli
outi TCCR1B,0
tst temp2
breq play_3
brpl play_2
ldi temp1,4
mov r0,temp1
rjmp loop
play_2:
clr r1
inc r1
mov r0,r1
rcall beep ;high 1time
lds r20,key_input
cpi r20,key_ff
breq play_ff
cpi r20,key_rew
breq play_rew
cpi r20,key_stop
breq play_stop
lds temp1,playmusic ;key_input=error?
rjmp play_1
play_3:
lds temp1,mode
cpi temp1,2
breq play_ff1
play_ff:
lds temp1,playmusic
inc temp1
sts playmusic,temp1
play_ff1:
clr temp2
sts cluster,temp2
sts cluster+1,temp2
rjmp play
play_rew:
lds temp1,playmusic
dec temp1
brne play_rew1
lds temp1,musiccount
play_rew1:
sts playmusic,temp1
clr temp2
sts cluster,temp2
sts cluster+1,temp2
rjmp play
play_stop:
cli
lds temp1,playmusic
ldiw z,rom_pm
rcall EEPROM_WR
mov temp1,r10
ldiw z,rom_cl
rcall EEPROM_WR
mov temp1,r11
ldiw z,rom_cl+1
rcall EEPROM_WR
lds temp1,secpcl
inc temp1
sub temp1,r3
clr temp2
add temp1,r8
adc r9,temp2
ldiw z,rom_re
rcall EEPROM_WR
mov temp1,r9
ldiw z,rom_re+1
rcall EEPROM_WR
lds temp1,musicsize
ldiw z,rom_mu
rcall EEPROM_WR
lds temp1,musicsize+1
ldiw z,rom_mu+1
rcall EEPROM_WR
lds temp1,musicsize+2
ldiw z,rom_mu+2
rcall EEPROM_WR
lds temp1,volume
ldiw z,rom_vo
rcall EEPROM_WR
lds temp1,mode
ldiw z,rom_mo
rcall EEPROM_WR
play_stop0:
ldi temp1,0
ldi temp2,0
ldi temp3,0x10
rcall mp3_cmd ;0,0x0010 power down
ldi temp1,200
rcall wait_ms
cbi PORTD,led
key_off_ck1: ;power_SWを離したか
in temp1,PINB
andi temp1,0b11000011
in temp2,PIND
andi temp2,0b00000100
or temp1,temp2
cpi temp1,0b11000111 ;no key_in
brne key_off_ck1
ldi temp1,250
rcall wait_ms
cbi PORTD,mp3_reset
cbi PORTD,p_hold ;power down
play_stop1:
rjmp play_stop1
;**********************************************
loop:
cli
clr r1
inc r1
rcall beep
loop1:
rjmp play_stop0
;**********************************************
;play_MP3 ;arg=playmusic(temp1),cluster,remainsec
play_mp3:
rcall search_mp3 ;return=temp2
lds temp1,playmusic ;
cp temp1,temp2
breq p_mp3_1
ldi temp2,-1
ret
p_mp3_1:
lds r12,buff+28
lds r13,buff+29
lds r14,buff+30
lds r15,buff+31 ;musicsize=r15:14:13:12
tst r15
breq p_mp3_2 ;filesize < $FFFFFF(16MB)
ldi temp2,-9 ; >=
ret
p_mp3_2:
sts musicsize,r12
sts musicsize+1,r13
sts musicsize+2,r14
lds r10,buff+26 ;play start top
lds r11,buff+27 ;cluster=r11:10
clr temp3 ;r14:13:12/512=r9:8 (remainsec)
mov temp2,r14 ;r14:13:12 mod 512=r7:6(remain byte)
mov temp1,r13
lsr temp2
ror temp1
brcc p_mp3_21 ;carry_flag =0
ldi temp3,1 ; =1
p_mp3_21:
mov r8,temp1
mov r9,temp2
mov r6,r12
mov r7,temp3
lds r3,secpcl
p_mp3_8:
lds r10,buff+26
lds r11,buff+27
lds temp1,cluster
lds temp2,cluster+1
clr temp3
or temp3,temp1
or temp3,temp2
brne p_mp3_29
sts cluster,r10
sts cluster+1,r11
sts remainsec,r8
sts remainsec+1,r9
rjmp p_mp3_3
p_mp3_29:
mov r10,temp1 ;play cont
mov r11,temp2 ;
lds r8,remainsec
lds r9,remainsec+1
p_mp3_3:
mov temp1,r10
and temp1,r11 ;r11:10=0xFFFF?
cpi temp1,0xFF
breq p_mp3_4
tst r11
brne p_mp3_5
ldi temp1,2
cp r10,temp1
brcc p_mp3_5
p_mp3_4:
ldi temp2,-2
ret
p_mp3_5:
rcall sec_addr_set
rcall mp3_int
clr temp1
sts key_c,temp1
sts key_in,temp1
p_mp3_9:
ldi temp1,1
clr temp2
sub r8,temp1
sbc r9,temp2
brcc p_mp3_91
rjmp p_mp3_30
p_mp3_91:
sts spi_arg+1,r15
sts spi_arg+2,r14
sts spi_arg+3,r13
sts spi_arg+4,r12
rcall spi_read_open
ldi temp1,0xff
rcall spi_out ;first byte
ldiw y,0
p_mp3_09:
sbic PIND,mp3_dreq
rjmp p_mp3_09n
rcall Interrupt
tst r20
brmi p_mp3_09
p_mp3_090:
in temp4,SPDR
outi SPDR,0xff
adiw yL,1
cpi yH,0x02
breq p_mp3_092
p_mp3_091:
sbis SPSR,SPIF
rjmp p_mp3_091
rjmp p_mp3_090
p_mp3_092:
rcall spi_read_close
mov temp2,r20
ret
p_mp3_09n:
in temp4,SPDR
outi SPDR,0xff
sbi PORTC,mp3_bsync
ldi r20,8
p_mp3_10:
lsl temp4
brcc p_mp3_11
sbi PORTC,mp3_si
rjmp p_mp3_12
p_mp3_11:
cbi PORTC,mp3_si
nop
p_mp3_12:
sbi PORTC,mp3_dclk
dec r20
cbi PORTC,mp3_dclk
cbi PORTC,mp3_bsync
brne p_mp3_10
adiw yL,1
cpi yH,0x02 ;y=512(0x0200)?
brne p_mp3_09
rcall spi_read_close
dec r3
breq p_mp3_20
ldi temp1,0x02
clr temp2
add r13,temp1
adc r14,temp2
adc r15,temp2
rjmp p_mp3_9
p_mp3_20:
rcall next_cluster ;cluster=r11:10,return=r5:4
mov r10,r4
mov r11,r5
lds r3,secpcl
rcall sec_addr_set
rjmp p_mp3_9
p_mp3_30:
mov temp1,r6
or temp1,r7
brne p_mp3_31
clr temp2
ret ;remain btye=0
p_mp3_31:
sts spi_arg+1,r15
sts spi_arg+2,r14
sts spi_arg+3,r13
sts spi_arg+4,r12
rcall spi_read_open
ldi temp1,0xff
rcall spi_out ;first byte
ldiw y,0
p_mp3_40:
sbic PIND,mp3_dreq
rjmp p_mp3_40n
rcall Interrupt
tst r20
brmi p_mp3_40
p_mp3_400:
in temp4,SPDR
outi SPDR,0xff
adiw yL,1
cpi yH,0x02
breq p_mp3_402
p_mp3_401:
sbis SPSR,SPIF
rjmp p_mp3_401
rjmp p_mp3_400
p_mp3_402:
rcall spi_read_close
mov temp2,r20
ret
p_mp3_40n:
in temp4,SPDR
outi SPDR,0xff
cp yL,r6
cpc yH,r7
brcc p_mp3_50
sbi PORTC,mp3_bsync
ldi r20,8
p_mp3_41:
lsl temp4
brcc p_mp3_42
sbi PORTC,mp3_si
rjmp p_mp3_43
p_mp3_42:
cbi PORTC,mp3_si
nop
p_mp3_43:
sbi PORTC,mp3_dclk
dec r20
cbi PORTC,mp3_dclk
cbi PORTC,mp3_bsync
brne p_mp3_41
p_mp3_50:
adiw yL,1
cpi yH,0x02
brne p_mp3_40
rcall spi_read_close
clr temp2
ret
;**********************************************
Interrupt: ;割り込み処理 10ms(40000ck)以下
cli
outi TCCR1B,0
lds zL,v_t
lds zH,v_t+1
sbiw zL,1
breq inter95
inter94:
sts v_t,zL
sts v_t+1,zH
rjmp inter96
inter95:
ldi temp1,0
sts v_t,temp1
ldi temp1,10
sts v_t+1,temp1
rcall v_read
cpi16 zH,zL,195
brcc inter96
ldi temp1,1
rcall wait_ms
rcall v_read
cpi16 zH,zL,195
brcc inter96
ldi temp1,10
mov r0,temp1
clr r1
rcall beep ;low 10times
ldi temp1,key_stop
sts key_input,temp1
rjmp inter_stop ;shut down mode
inter96:
ldi temp1,3
rcall wait_ms
inter97:
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,0b11000111
breq inter98
lds temp1,key_in
cp temp1,temp4
breq inter0
inter98:
sts key_in,temp4
clr temp1
sts key_c,temp1
rjmp inter99
inter0:
lds temp4,key_c
inc temp4
cpi temp4,25
breq inter01
sts key_c,temp4
rjmp inter99
inter01:
sts key_input,temp1
clr temp4
sts key_in,temp4
sts key_c,temp4
cpi temp1,key_vp
brne inter1
lds temp2,volume
subi temp2,4
cpi temp2,0x12
brcc inter_vol
ldi temp2,0x12
rjmp inter_vol
inter1:
cpi temp1,key_vm
brne inter2
lds temp2,volume
subi temp2,-4
cpi temp2,0x8A
brcs inter_vol
ldi temp2,0x8A
rjmp inter_vol
inter2:
cpi temp1,key_ff
brne inter3
ldi r20,1
rjmp inter_end
inter3:
cpi temp1,key_rew
brne inter4
ldi r20,2
rjmp inter_end
inter_vol:
sts volume,temp2
ldi temp1,11
mov temp3,temp2
rcall mp3_cmd
inter99:
ldi r20,-1
rjmp inter_end
inter_stop:
ldi r20,3
inter_end:
outi TCNT1H,0x80
outi TCNT1L,0
sei
outi TCCR1B,(1<<CS11)|(1<<CS10)
ret
inter4:
cpi temp1,key_stop
brne inter99
ldi temp1,200
rcall wait_ms
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,key_stop
breq inter_stop
ldi temp1,70
rcall wait_ms
inter_wait0: ;timer0_int
outi TCNT0,0
outi TIMSK,1<<TOIE0 ;Overflow int
outi TCCR0,5 ;Tck=CK/1024 256/4M/1024---66ms
sei
inter_wait:
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,key_vp
brne inter_mode1
ldi temp1,100
rcall wait_ms
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,key_vp
brne inter_mode1
lds temp1,mode
dec temp1
brpl inter_mode2
ldi temp1,2
inter_mode2:
sts mode,temp1
clr r20
sts led_time,r20
inter_mode1:
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,key_stop
brne inter_wait
ldi temp1,50
rcall wait_ms
in temp4,PINB ;key ck
andi temp4,0b11000011
in temp3,PIND
andi temp3,0b00000100
or temp4,temp3
cpi temp4,key_stop
brne inter_wait
sbi PORTD,led
cli
outi TCCR0,0
outi TIMSK,1<<TOIE1
rjmp inter99
;**********************************************
v_read:
sbi ADCSR,ADEN ;adc on
sbi ADCSR,ADIF ;Reset interrupt flag
sbi ADCSR,ADSC ;Start A/D conversion
v_read1:
sbis ADCSR,ADIF
rjmp v_read1
in zL,ADCL ;
in zH,ADCH ;
cbi ADCSR,ADEN ;adc off
lsr zH ;V/2:256=X:1024
ror zL ;V=X/2 (uint0.01V)
ret
;**********************************************
mp3_int:
cbi PIND,mp3_reset
ldi temp1,5
rcall wait_ms
sbi PIND,mp3_reset
ldi temp1,0
ldi temp2,0
ldi temp3,4
rcall mp3_cmd ;0,0x0004 ;cmd=temp1,arg[H:L]=temp2:temp3
ldi temp1,1
rcall wait_ms
sbis PIND,mp3_dreq
rjmp mp3_int
ldi temp1,0
ldi temp2,0
ldi temp3,0
rcall mp3_cmd ;0,0x0000
ldi temp1,3
ldi temp2,0x98
ldi temp3,0x00 ;0x8000+12288000/2000
rcall mp3_cmd ;3,0x9800
ldi temp1,11
lds temp2,volume
mov temp3,temp2
rcall mp3_cmd ;11,left/right
ldiw z,mp3_0*2
rcall mp3_sin
ldiw z,mp3_0*2
rcall mp3_sin
ret
;**********************************************
mp3_cmd: ;com=temp1,arg=temp2:3
cbi PORTC,mp3_cs
ldi temp4,2
rcall mp3_write
mov temp4,temp1
rcall mp3_write
mov temp4,temp2
rcall mp3_write
mov temp4,temp3
rcall mp3_write
sbi PORTC,mp3_cs
ret
;**********************************************
mp3_write: ;data=temp4
ldi r20,8
mp3_write_0:
lsl temp4
brcc mp3_write_1
sbi PORTC,mp3_si
rjmp mp3_write_2
mp3_write_1:
cbi PORTC,mp3_si
nop
mp3_write_2:
sbi PORTC,mp3_sclk
dec r20
cbi PORTC,mp3_sclk
brne mp3_write_0
ret
;**********************************************
mp3_sin: ;data_addr Z
ldi r21,8
mp3_sin_0:
sbis PIND,mp3_dreq
rjmp mp3_sin_0
lpm temp4,z+
sbi PORTC,mp3_bsync
ldi r20,8
mp3_sin_1:
lsl temp4
brcc mp3_sin_2
sbi PORTC,mp3_si
rjmp mp3_sin_3
mp3_sin_2:
cbi PORTC,mp3_si
nop
mp3_sin_3:
sbi PORTC,mp3_dclk
dec r20
cbi PORTC,mp3_dclk
cbi PORTC,mp3_bsync
brne mp3_sin_1
dec r21
brne mp3_sin_0
ret
;**********************************************
beep: ;times:r0,High/Low:r1(=1/0)
rcall mp3_int
beep_0:
tst r1
breq beep_1
ldiw z,beep_H*2
rjmp beep_2
beep_1:
ldiw z,beep_L*2
beep_2:
rcall mp3_sin
ldi temp1,100 ;音の長さ
rcall wait_ms
ldiw z,beep_s*2
rcall mp3_sin
ldi temp1,30 ;無音の長さ
rcall wait_ms
dec r0
brne beep_0
ldiw z,beep_s*2
rcall mp3_sin
; rcall buff__clr
ret
;**********************************************
sec_addr_set:
clr r12
lds r13,datastart
lds r14,datastart+1
lds r15,datastart+2
mov temp1,r10
mov temp2,r11
subi temp1,2
sbci temp2,0
clr temp3
mul temp1,r3
add r13,r0
adc r14,r1
adc r15,temp3
mul temp2,r3
add r14,r0
adc r15,r1
lsl r13
rol r14
rol r15
ret
;**********************************************
next_cluster: ;cluster=r11:10 FAT16
clr temp1 ;fatstart*512 ->
lds temp2,fatstart ;temp4:3:2:1
lds temp3,fatstart+1
clr temp4
lsl temp2
rol temp3
rol temp4
mov r12,r10
mov r13,r11
clr r14 ;cluster*2
lsl r12
rol r13
rol r14
clr r15
add temp1,r12
adc temp2,r13
adc temp3,r14
adc temp4,r15 ;addr=temp4:3:2:1
ldiw z,0x01FF
and zL,temp1
and zH,temp2 ;addr&511 -> Z
addi16 zH,zL,fatcache ;Z+=fatcache
clr temp1
andi temp2,0xFE
lds r12,fatsec ;fatsec=H4:H3:H2 (H1=0)
lds r13,fatsec+1
lds r14,fatsec+2
cp r12,temp2 ;FATcache sec=fatsec ?
brne n_c_1 ;no
cp r13,temp3
brne n_c_1 ;no
cp r14,temp4
breq n_c_2 ;yes ,no next line
n_c_1:
sts spi_arg+1,temp4
sts spi_arg+2,temp3
sts spi_arg+3,temp2
sts spi_arg+4,temp1
rcall read_512 ;addr=spi_arg[4:1]
tst temp2
breq n_c_2
clr r4
clr r5
ret
n_c_2:
ld temp1,z+
ld temp2,z
cpi temp2,0xff
brne n_c_3
cpi temp1,0xf8
brmi n_c_3
ldi temp1,0xff
ldi temp2,0xff
n_c_3:
mov r4,temp1
mov r5,temp2
ret
;**********************************************
read_512: ;512byte read -> FATcache[511:0]
rcall spi_read_open
tst temp2
breq read_512_1
ret
read_512_1:
ldiw x,fatcache
read_512_2:
rcall spi_in
st x+,temp2
cpi xL,low(fatcache+512) ;+512
brne read_512_2
cpi xH,high(fatcache+512)
brne read_512_2
rcall spi_read_close
lds temp4,spi_arg+1
lds temp3,spi_arg+2
lds temp2,spi_arg+3
sts fatsec,temp2
sts fatsec+1,temp3
sts fatsec+2,temp4
clr temp2
ret
;**********************************************
;MP3 search ,temp1 MP3 file number
;return buff[]:last MP3 dir,temp2 found MP3 files
search_mp3:
mov r20,temp1
clr r21 ;return MP3_count
clr r12 ;dirstart[1:0]*512
lds r13,dirstart ; -> r15:14:13:12
lds r14,dirstart+1
clr r15
lsl r13
rol r14
rol r15
sts spi_arg+1,r15
sts spi_arg+2,r14
sts spi_arg+3,r13
sts spi_arg+4,r12
lds r10,rdirent
lds r11,rdirent+1
clr zL
clr zH
search_mp3_1:
cp zL,r10
cpc zH,r11
brpl search_mp3_e
rcall spi_read_open
tst temp2
breq search_mp3_2
mov temp2,r21
ret
search_mp3_2:
ldi r22,16 ;loop_count set
search_mp3_22:
ldiw x,buff
ldiw y,buff+32
search_mp3_3:
rcall spi_in
st x+,temp2
cp xL,yL
cpc xH,yH
brne search_mp3_3
lds temp1,buff
tst temp1 ;buff[0]=0?
breq search_mp3_e0 ;yes entry end
cpi temp1,0xE5 ;deleted file?
breq search_mp3_4 ;yes next entry
lds temp1,buff+26
lds temp2,buff+27
or temp1,temp2 ;buff[26]=0 & buff[27]=0
breq search_mp3_4 ;yes next entry
lds temp1,buff+11
andi temp1,0x18 ;buff[11]=0x10 or 0x08
brne search_mp3_4 ;Attr dir or Volume yes next entry
lds temp1,buff+8
cpi temp1,'M'
brne search_mp3_4 ;buff[8]="M" not next entry
lds temp1,buff+9
cpi temp1,'P'
brne search_mp3_4 ;buff[9]="P" not next entry
lds temp1,buff+10
cpi temp1,'3'
brne search_mp3_4 ;buff[10]="3" not next entry
inc r21 ;MP3_file found, MP3_count++
dec r20
breq search_mp3_e0 ;Loop_count=0 then end
search_mp3_4:
adiw zL,1 ;entri inc
dec r22
brne search_mp3_22 ;sector end? not next entry
rcall spi_read_close
ldi temp1,0x02 ;r15:14:13:12+=512
clr temp2 ;next sector addr set
add r13,temp1
adc r14,temp2
adc r15,temp2
sts spi_arg+1,r15
sts spi_arg+2,r14
sts spi_arg+3,r13
rjmp search_mp3_1
search_mp3_e0:
rcall spi_read_close
search_mp3_e:
mov temp2,r21
ret
;**********************************************
;Vfat read sector=512
read_vfat:
ldi temp1,BYTE4(446)
sts read32_arg,temp1
ldi temp1,BYTE3(446)
sts read32_arg+1,temp1
ldi temp1,BYTE2(446)
sts read32_arg+2,temp1
ldi temp1,low(446)
sts read32_arg+3,temp1
rcall read_32 ;(446)
lds r2,buff+8 ;buff[9:8]-->r3:r2=bpb
lds r3,buff+9 ;bpb top sec read
clr temp1
mov temp2,r2
mov temp3,r3
clr temp4
lsl temp2
rol temp3
rol temp4 ;temp4:3:2:1 <= x 512(9bit left_shift)
sts read32_arg,temp4
sts read32_arg+1,temp3
sts read32_arg+2,temp2
sts read32_arg+3,temp1
rcall read_32 ;(temp4:3:2:1)
lds temp1,buff+11 ;buff[12:11]-->r11:10=sec_log
lds temp2,buff+12
cpi16 temp2,temp1,0x0200
breq read_vfat1
ldi temp2,2 ;1sec not 512bytes
ret
read_vfat1:
lds temp1,buff+13
sts secpcl,temp1 ;buff[13]->secpcl
lds temp1,buff+14
lds temp2,buff+15
add temp1,r2
adc temp2,r3
sts fatstart,temp1
sts fatstart+1,temp2 ;buff[15:14]+bpb -> fatstart[1:0]
lds temp1,buff+17
lds temp2,buff+18
sts rdirent,temp1
sts rdirent+1,temp2 ;buff[18:17] -> rdirent[1:0]
lds r10,buff+22
lds r11,buff+23 ;buff[23:22] -> r11:10=fat_sectors
tst r10
brne read_vfat2
tst r11
brne read_vfat2
ldi temp2,1 ;not FAT16/12(FAT32?)
ret
read_vfat2:
lds temp3,buff+16 ;buff[16]
mul r10,temp3 ;buff[16]*fat_sectors_L -> r1:r0
mov temp2,r1 ;
mov temp1,r0 ;r1:r0 -> temp2:temp1
mul r11,temp3 ;buff[16]*fat_sectors_H -> r1:r0 (r1=0)
add temp2,r0 ;temp2:temp1 +=r0:0x00 (fat_sectors*buff[16])
lds temp3,fatstart
lds temp4,fatstart+1 ;temp4:temp3 <- fatstart[1:0]
add temp1,temp3
adc temp2,temp4 ;temp2:temp1= fat_sectors*buff[16]+ fatstart[1:0]
sts dirstart,temp1
sts dirstart+1,temp2 ;temp2:temp1 -> dirstart[1:0]
lds temp1,rdirent
lds temp2,rdirent+1
;temp2:temp1/16 -> temp2:temp1...temp4
swap temp2 ;H2:H1 -> H1:H2
mov temp3,temp2
andi temp3,0xF0 ;H1:0 H1 save
andi temp2,0x0F ;0:H2
ldi temp4,0x0F
and temp4,temp1 ;L1 save (temp2:temp1 MOD 16)
swap temp1 ;L2:L1 -> L1:L2
andi temp1,0x0F ;0:L2
or temp1,temp3 ;H1:L2 (n=temp2:temp1=0:H2:H1:L2)
tst temp4
breq read_vfat3
addi16 temp2,temp1,1
read_vfat3:
lds temp3,dirstart
lds temp4,dirstart+1
clr r0
clr r1
add temp3,temp1
adc temp4,temp2
adc r0,r1 ;n+dirstart[1:0] -> r1:r0:temp4:temp3
sts datastart,temp3 ;datastart[3:0] <- r1:r0:temp4:temp3
sts datastart+1,temp4
sts datastart+2,r0
sts datastart+3,r1
lds temp1,buff+19
lds temp2,buff+20 ;all_sectors= buff[20:19]
clr temp3 ;all_sectors=temp4:3:2:1 =0:0:XX:XX
clr temp4 ; (16bytes long)
clr r15
or r15,temp2
or r15,temp1 ;r15 <- r15|temp2|temp1
brne read_vfat4 ;(temp2:temp1=0)? not next
ldi temp1,32 ;yes bpb=r3:r2
clr r15 ;arg <- 32+bpb*512 (9bit left_shift)
lsl r2
rol r3
rol r15
sts read32_arg,r15
sts read32_arg+1,r3
sts read32_arg+2,r2
sts read32_arg+3,temp1
rcall read_32 ;(32+bpb*512)
lds temp1,buff
lds temp2,buff+1
lds temp3,buff+2
lds temp4,buff+3 ;all_sectors=temp4:3:2:1
read_vfat4:
lds r13,fatstart
lds r14,fatstart+1
clr r15
sub temp1,r13
sbc temp2,r14
sbc temp3,r15
sbc temp4,r15 ;all_sectors -= fatstart
clr r20 ;spcpcl -> r23:22:21:20 (base r20)
lds r21,secpcl ;***spcpcl*4096(12bit L_shift)***
mov r22,r21 ;r20->r21 8bit,r21=r22(H:L) copy
swap r21 ;r21 H<->L
andi r21,0xF0 ;r21 L0 (+4bit->12bit)
swap r22 ;r22 H<->L
andi r22,0x0F ;r22 0H
clr r23 ;spcpcl*4096 -> r23:22:21:20
cp temp1,r20
cpc temp2,r21
cpc temp3,r22
cpc temp4,r23 ;sec:spcpcl*4096
brmi read_vfat5
ldi temp1,1 ;FAT16
rjmp read_vfat6
read_vfat5:
clr temp1 ;FAT12
ldi temp2,3 ;
ret ;
read_vfat6:
sts fattype,temp1
clr temp2
ret
;**********************************************
;read_32 read32_arg[3:0]
read_32:
lds r15,read32_arg
lds r14,read32_arg+1
lds r13,read32_arg+2
lds r12,read32_arg+3
mov temp4,r15
mov temp3,r14
ldi temp2,0xFE
and temp2,r13
clr temp1
sts spi_arg+1,temp4
sts spi_arg+2,temp3
sts spi_arg+3,temp2
sts spi_arg+4,temp1
rcall spi_read_open
tst temp2
breq read_32_1
ret ;temp2=1 erro
read_32_1:
mov temp3,r12
ldi temp4,1
and temp4,r13 ;low_addr=temp4:3 <- addr&0x1FF
clr yL
clr yH ;Y:counter 0 to 511
ldiw x,buff
ldiw z,buff+32
read_32_2:
rcall spi_in
cp yL,temp3
cpc yH,temp4 ;Y:low_addr
brmi read_32_3 ;Y<low_addr
cp xL,zL ;Y>=low_addr
cpc xH,zH ;x:buff+32
brpl read_32_3 ;x>=buff+32
st x+,temp2 ;Y>=low_addr & x<buff+32
read_32_3:
adiw yL,1
cpi yH,0x02 ;Y=512?
brne read_32_2 ;no
read_32_e:
rcall spi_read_close
ret
;**********************************************
;spi_read_open spi_arg[4:1]
spi_read_open:
ldi temp4,100
s_r_o1:
cbi PORTB,sd_cs ;CS=L
ldi temp1,17
sts spi_arg,temp1
rcall spi_com
tst temp2
brne s_r_o3
ldiw x,4096
s_r_o2:
rcall spi_in
cpi temp2,0xFE
brne s_r_o21
clr temp2
ret
s_r_o21:
sbiw xL,1
brne s_r_o2
rjmp s_r_o4
s_r_o3:
cpi temp2,0xFE
brne s_r_o4
clr temp2
ret
s_r_o4:
sbi PORTB,sd_cs ;CS=H
ldi temp1,20
rcall wait_us
dec temp4
breq s_r_o5
rjmp s_r_o1
s_r_o5:
ldi temp2,1
ret
;**********************************************
;spi_read_close
spi_read_close:
rcall spi_in ;CRC
rcall spi_in ;CRC
ldiw y,2048
s_r_c1:
rcall spi_in
cpi temp2,0xFF
breq s_r_c2
sbiw yL,1
brne s_r_c1
s_r_c2:
sbi PORTB,sd_cs ;CS=H
ret
;**********************************************
;SPI DATA input
spi_in:
outi SPDR,0xff
spi_in1:
sbis SPSR,SPIF
rjmp spi_in1
in temp2,SPDR
ret
;**********************************************
;SPI DATA output data=temp1
spi_out:
out SPDR,temp1
spi_out1:
sbis SPSR,SPIF
rjmp spi_out1
ret
;**********************************************
;spi command
spi_com: ;cmd,arg[3:0],ret-->temp2
ldiw Y,2048
spi_com1:
rcall spi_in
cpi temp2,0xff
breq spi_com2
sbiw YL,1
brne spi_com1
ldi temp2,1
ret ;busy error return=1
spi_com2:
lds temp1,spi_arg
mov temp2,temp1
ori temp1,0x40
rcall spi_out ;cmd
lds temp1,spi_arg+1
rcall spi_out ;arg3
lds temp1,spi_arg+2
rcall spi_out ;arg2
lds temp1,spi_arg+3
rcall spi_out ;arg1
lds temp1,spi_arg+4
rcall spi_out ;arg0
tst temp2
brne spi_com3
ldi temp1,0x95 ;int CRC
rjmp spi_com4
spi_com3:
ldi temp1,1
spi_com4:
rcall spi_out ;CRC
ldiw Y,2048
spi_com5:
rcall spi_in
cpi temp2,0xFE
breq spi_com6 ;data talken start
ldi temp3,0x80
and temp3,temp2
breq spi_com6 ;cmd response (MSB=0)
sbiw YL,1
brne spi_com5
spi_com6: ;return=temp2
ret
;**********************************************
wait_us: ;base 4MHz temp1 us (4clocks)
nop ; 1clocks
dec temp1 ; 1clocks
brne wait_us ; 2clocks
ret ;
wait_ms:
;temp1 ms
ldi temp2,50 ;80*50=4000clocks
wait_ms_01:
ldi temp3,19 ;1clocks 4*(19+1)=80
wait_ms_02:
nop ; 1clocks
dec temp3 ; 1clocks
brne wait_ms_02 ; 2clocks
dec temp2 ; 1clocks
brne wait_ms_01 ; 2clocks
dec temp1 ; 1clocks
brne wait_ms ; 2clocks
ret
;*********************************************
EEPROM_WR:
rcall EEPROM_RD
cp temp1,temp2 ;同じ値ならスキップ
brne EEPROM_WR1
ret
EEPROM_WR1:
SBIC EECR,EEWE ;EEPROM書き込み完了ならばスキップ
RJMP EEPROM_WR1 ;以前のEEPROM書き込み完了まで待機
OUT EEARH,ZH ;EEPROMアドレス上位バイト設定
OUT EEARL,ZL ;EEPROMアドレス下位バイト設定
OUT EEDR,temp1 ;EEPROM書き込み値を設定
SBI EECR,EEMWE ;EEPROMマスタ書き込み許可ビット設定
SBI EECR,EEWE ;EEPROM書き込み開始(書き込み許可ビット設定)
RET ;呼び出し元へ復帰
;*********************************************
EEPROM_RD:
SBIC EECR,EEWE ;EEPROM書き込み完了ならばスキップ
RJMP EEPROM_RD ;以前のEEPROM書き込み完了まで待機
OUT EEARH,ZH ;EEPROMアドレス上位バイト設定
OUT EEARL,ZL ;EEPROMアドレス下位バイト設定
SBI EECR,EERE ;EEPROM読み出し開始(読み込み許可ビット設定)
IN temp2,EEDR ;EEPROM読み出し値を取得
RET ;呼び出し元へ復帰
;*********************************************
;BEEP data
beep_H: .db 0x53,0xEF,0x6E,0x31,0,0,0,0 ;1500Hz
beep_L: .db 0x53,0xEF,0x6E,0x35,0,0,0,0 ; 500Hz
beep_s: .db 0x45,0x78,0x69,0x74,0,0,0,0 ; stop
mp3_0: .db 0,0,0,0,0,0,0,0
;*********************************************
TIM1_OVF:
ldi temp1,low(RAMEND)
out SPL,temp1
ldi temp1,high(RAMEND)
out SPH,temp1 ;init Stack Pointer
lds temp1,playmusic
clr temp2
sts cluster,temp2
sts cluster+1,temp2
sei
rjmp play_1
;*********************************************
;LED_flush mode 0:66*3=200,1:66*6=400,2:66*12=800ms
TIM0_OVF:
in r0,SREG
lds r30,mode
ldi r31,3
TIM0_OVF1:
dec r30
brmi TIM0_OVF2
lsl r31
rjmp TIM0_OVF1
TIM0_OVF2:
lds r20,led_time
inc r20
cp r20,r31
brne TIM0_OVF9
clr r20
sbic PORTD,led
rjmp TIM0_OVF3
sbi PORTD,led
rjmp TIM0_OVF9
TIM0_OVF3:
cbi PORTD,led
TIM0_OVF9:
sts led_time,r20
out SREG,r0
reti