;MP3 Player kunio.h  Ver1.0 H15.8.17
;**** 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	p_hold	= 7	;power hold & MP3~reset
;**  PORTD  **
.equ	mp3_dreq= 0
.equ	lcd_rs	= 1	
.equ	lcd_rw	= 2
.equ	lcd_enb	= 3
.equ	lcd_db4 = 4
.equ	lcd_db5 = 5
.equ	lcd_db6 = 6
.equ	lcd_db7 = 7
.equ	mp3_so  = 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 = 0b00000011
.equ	key_ff	 = 0b00000001
.equ	key_rew = 0b01000001
.equ	key_vp	 = 0b01000000
.equ	key_vm	 = 0b01000010

.dseg
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
vol_t:		.BYTE	1
v_t:		.BYTE	2
play_time:	.BYTE	2	;PLAY TIME SAVE	
id3:		.BYTE 128	;TAG V1
.eseg	;EEPROM
rom_pm:	.BYTE	1	;play music
rom_cl:	.BYTE	2	;cluster
rom_re:	.BYTE	2	;remainsec
rom_mu:	.BYTE	3	;musicsize
rom_pt:	.BYTE	2	;play_time
rom_vo:	.BYTE	1	;volume
.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 一致
	reti	;TIM1_OVF ;ﾀｲﾏ/ｶｳﾝﾀ1 ｵｰﾊﾞｰﾌﾛｰ
	reti	;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 命令操作可



;clk_ck:		;内部OSCﾁｪｯｸ用(clk/8)　不使用
;	cbi	PORTB,6
;	nop
;	nop		;2 clocks
;	sbi	PORTB,6
;	rjmp	clk_ck	;2 clocks
;*********************
;* メイン プログラム *
;*********************
start:
	ldi	temp1,low(RAMEND)
	out	SPL,temp1
	ldi	temp1,high(RAMEND)
	out	SPH,temp1	;init Stack Pointer 
	
	ldi	temp1,0x88	;
	out	OSCCAL,temp1
	
	ldi	temp1,(1<<sd_cs)|(1<<sw_0)|(1<<sw_1)|(1<<sw_6)|(1<<sd_in)  ;|(1<<p_hold)
	out	PORTB,temp1	; sd_out no pull up,sd_clk clr
	ldi	temp1,(1<<sd_cs)|(1<<sd_clk)|(1<<sd_in)|(1<<p_hold)
	out	DDRB,temp1	; sd_out,sw_0/1/6 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,0xfe
	out	DDRD,temp1	; pd1~7 output port,0(mp_dreq) input
	ldi	temp1,0x01	; pd1~7 clear,0  pull up	
	out	PORTD,temp1	
	
;time2_int:
;	outi	TIMSK,1<<OCIE2		;比較一致割込使用
;	outi	TCNT2,0			;カウンタクリア
;	outi	OCR2,255
;	outi	TCCR2,(1<<CS21)|(1<<CS21)|(1<<CS20)|(1<<WGM21)	;タイマ２on　CTC動作、CKT2=8M/1024=7812Hz
; LCD - Initialize LCD controller
lcd_init:
	ldi	temp1,15	; wait for 15+ms
	rcall	wait_ms		; /
	rcall	lcd_int		; /
	ldi	temp1,5		; Wait for 4.1ms+
	rcall	wait_ms		; /
	rcall	lcd_int		; /
	ldi	temp1,100 	;wait for 100us+
	rcall	wait_us		; /
	rcall	lcd_int		; /

	ldi	lcd_data,0x20
	rcall	lcd_cmd
	ldi	temp1,100 	;wait for 100us+
	rcall	wait_us		; /
	ldi	lcd_data,0x28	; Data=4bit, Line=2, Font=5x7
	rcall	lcd_cmd		; /
	ldi	lcd_data,0x0c	; Display=ON, Cursor=OFF, Blink=OFF
	rcall	lcd_cmd		; /
	ldi	lcd_data,6	; Increment, No shift
	rcall	lcd_cmd		; /
;ADC_int:
	outi	ADMUX,(1<<REFS0)|(1<<REFS1)	;基準電圧2.56V、結果右揃え、Ch0選択
	outi	ADCSR,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);|(1<<ADEN);ADCck=8M/128=62.5k

	ldiw	z,ready*2
	rcall	lcd_dat_dsp
	ldi	temp1,50
	rcall wait_ms	
	sbi	PORTB,p_hold	;mp3 un reset&power hold
	ldi	temp1,100
	rcall wait_ms	
	rcall	v_read
	rcall	v_dsp
	in	temp1,PINB
	andi	temp1,0b01000011
	cpi	temp1,key_vm
	brne	play_data_init
	ldi	temp1,5
	rcall	wait_ms	
	in	temp1,PINB
	andi	temp1,0b01000011
	cpi	temp1,key_vm
	brne	play_data_init
erorr_rest_mode:	; 'power on'+'vol-'
	in	temp1,PINB
	andi	temp1,0b01000011
	cpi	temp1,0b01000011
	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_pt
	rcall	EEPROM_RD
	sts	play_time,temp2
	ldiw	z,rom_pt+1
	rcall	EEPROM_RD
	sts	play_time+1,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,6
	sts	v_t,temp1
	ldi	temp1,0
	sts	v_t+1,temp1

;SPI/SD/MMC_int
spi_0:
	outi	SPCR,0x52	;SPI master,CPOL0,CPHA=0,CK=8M/64=125k
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=8M/4=2M
	sbi	SPSR,SPI2X	;ck x 2 -> 4M

	cpi	temp2,0xFF
	brne	main_1
	ldiw	z,sd_err*2
	rcall	lcd_dat_dsp
	rjmp	loop
main_1:
	rcall	read_vfat
	tst	temp2
	breq	main_2
	ldiw	z,fat_err*2
	rcall	lcd_dat_dsp
	rjmp	loop
main_2:
	ldi	temp1,0xff
	rcall search_mp3;temp2 <- MP3 count
	tst	temp2
	brne	main_3
	ldiw	z,no_mp3*2
	rcall	lcd_dat_dsp
	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
	brne	main_5
;	lds	temp1,buff+31
;	lds	temp2,musicsize+3
;	cp	temp1,temp2
;	brne	main_5

	rjmp	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,220	;about 2.2V down
	brcc	play0		;beep
	ldi	temp1,3
	mov	r0,temp1
	ldi	temp1,1
	mov	r1,temp1	
	rcall	beep	;high 3times
play0:
	rcall	v_dsp
	ldi	temp1,255
	sts	vol_t,temp1
	lds	temp1,playmusic
	lds	temp2,musiccount
	cp	temp2,temp1	
	brpl	play_1			;files => play_No 
	ldi	temp1,1		;	<
	sts	playmusic,temp1
play_1:
	rcall	play_mp3	;arg=playmusic(temp1),cluster,remainsec
	tst	temp2
	breq	play_3
	brpl	play_2
	ldiw	z,mp3_err*2
	rcall	lcd_dat_dsp
	rjmp	loop
play_2:
	ldi	temp1,4
	rcall	mp3_read
	lds	temp1,play_time
	lds	temp2,play_time+1
	add	r0,temp1
	adc	r1,temp2
	sts	play_time,r0
	sts	play_time+1,r1
	clr	r1
	inc	r1
	mov	r0,r1	
	rcall	beep	;high 1time
	lds	r20,key_input
	cpi	r20,key_ff
	breq	play_3
	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:;(ff)
	lds	temp1,playmusic
	inc	temp1
	sts	playmusic,temp1
	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:
	lds	temp1,play_time
	ldiw	z,rom_pt
	rcall	EEPROM_WR
	lds	temp1,play_time+1
	ldiw	z,rom_pt+1
	rcall	EEPROM_WR
	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
	ldi	temp1,5
	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
	ldiw	z,shut_down*2
	rcall	lcd_dat_dsp
play_stop0:
;	rcall	mp3_int
	ldi	temp1,0
	ldi	temp2,0
	ldi	temp3,0x10
	rcall	mp3_cmd	;0,0x0010 power down
	ldi	temp1,200
	rcall	wait_ms
	ldi	temp1,200
	rcall	wait_ms
	cbi	PORTB,p_hold	;power down
play_stop1:
	rjmp	play_stop1
;**********************************************
loop:
	ldi	temp1,10
	mov	r0,temp1
	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
	push	r9
	push	r8
	lds	r3,secpcl
	rcall	tagv1
	ldiw	x,id3
	ld	temp1,x+
	cpi	temp1,'T'
	brne	p_mp3_5n
	ld	temp1,x+
	cpi	temp1,'A'
	brne	p_mp3_5n
	ld	temp1,x+
	cpi	temp1,'G'
	breq	p_mp3_6
p_mp3_5n:
	ldiw	z,no_tag*2
	rcall	lcd_dat_dsp
	rjmp	p_mp3_8
p_mp3_6:
	ldi	lcd_data,0x80
	rcall	lcd_cmd
p_mp3_61:
	ld	lcd_data,x+
	rcall	str_ck
	rcall	lcd_dsp
	cpi16	xH,xL,id3+19
	brne	p_mp3_61
	ldiw	x,id3+33
	ldi	lcd_data,0xC0
	rcall	lcd_cmd
p_mp3_7:
	ld	lcd_data,x+
	rcall	str_ck
	rcall	lcd_dsp
	cpi16	xH,xL,id3+43
	brne	p_mp3_7
p_mp3_8:
	pop	r8
	pop	r9
	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
	clr	temp1
	sts	play_time,temp1
	sts	play_time+1,temp1
	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:
;	lds	r10,cluster
;	lds	r11,cluster+1
;	lds	r8,remainsec
;	lds	r9,remainsec+1
	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(80000ck）以下
	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,6
	sts	v_t,temp1
	ldi	temp1,0
	sts	v_t+1,temp1
	rcall	v_read
	cpi16	zH,zL,200
	brcc	inter96
	ldi	temp1,3
	rcall	wait_ms
	rcall	v_read
	cpi16	zH,zL,200
	brcc	inter96
	ldi	temp1,4
	rcall	mp3_read
	lds	temp1,play_time
	lds	temp2,play_time+1
	add	r0,temp1
	adc	r1,temp2
	sts	play_time,r0
	sts	play_time+1,r1
	ldi	r23,0xc0
	rcall	lcd_dsp
	ldiw	z,batt_low*2
	rcall	lcd_dat_dsp1
	ldi	temp1,10
	mov	r0,temp1
	clr	r1	
	rcall	beep	;low 10times
	ldi	temp1,key_stop
	sts	key_input,temp1
	ldi	r20,3
	ret	;shut down mode
inter96:
	ldi	temp1,3
	rcall	wait_ms
	lds	temp1,vol_t
	dec	temp1
	sts	vol_t,temp1
	brne  inter97
	inc	temp1
	sts	vol_t,temp1
	rcall	time_dsp
inter97:
	in	temp4,PINB	;key ck
	andi	temp4,0b01000011
	cpi	temp4,0b01000011
	breq	inter98
	lds	temp1,key_in
	cp	temp1,temp4
	breq	inter0
inter98:
	sts	key_in,temp4
	clr	temp1
	sts	key_c,temp1
inter99:
	ldi	r20,-1
	ret
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
	ret
inter3:
	cpi	temp1,key_rew
	brne	inter4
	ldi	r20,2	
	ret
inter4:
	cpi	temp1,key_stop
	brne	inter99
	ldi	temp1,150
	rcall	wait_ms
	in	temp4,PINB	;key ck
	andi	temp4,0b01000011
	cpi	temp4,key_stop
	breq	inter_stop
	ldi	temp1,100
	rcall	wait_ms
	ldi	r23,0xCA
	rcall	lcd_cmd
	ldiw	z,pause*2
	rcall	lcd_dat_dsp1
inter_wait:
	in	temp4,PINB	;key ck
	andi	temp4,0b01000011
	cpi	temp4,key_stop
	brne	inter_wait
	ldi	temp1,30
	rcall	wait_ms
	in	temp4,PINB	;key ck
	andi	temp4,0b01000011
	cpi	temp4,key_stop
	brne	inter_wait
	rcall	time_dsp
	ldi	r20,-1
	ret
inter_stop:		
	ldi	r20,3
	ret
inter_vol:
	sts	volume,temp2
	ldi	temp1,11
	mov	temp3,temp2
	rcall	mp3_cmd
	rcall	vol_dsp
	ldi	r20,-1
	ret
;**********************************************
time_dsp:
	ldi	temp1,4
	rcall	mp3_read
	ldi	r23,0xCA
	rcall	lcd_cmd
	ldi	r23,' '
	rcall	lcd_dsp
	lds	temp1,play_time
	lds	temp2,play_time+1

	add	temp1,r0
	adc	temp2,r1
min:
	clr	r22
	clr	r21
	clr	r20
	clr	r19
min0:
	cpi16	temp2,temp1,60
	brmi	sec0
	subi	temp1,60
	sbci	temp2,0
	inc	r21
	rjmp	min0	
sec0:
	cpi	temp1,10
	brmi	sec1
	subi	temp1,10
	inc	r20
	rjmp	sec0
sec1:
	mov	r19,temp1
	mov	temp1,r21
min1:
	cpi	temp1,10
	brmi	min2
	subi	temp1,10
	inc	r22
	rjmp	min1
min2:
	mov	r0,r22
	mov	r1,temp1
	rcall	bindec2
	ldi	r23,':'
	rcall	lcd_dsp
	mov	r0,r20
	mov	r1,r19
	rcall	bindec2
	ret
;**********************************************
vol_dsp:
	ldi	r23,0xCA
	rcall	lcd_cmd
	ldiw	z,vol*2
	rcall	lcd_dat_dsp1
	lds	temp3,volume
vol_dsp0:
	ldi	temp2,0x8A
	sub	temp2,temp3
	lsr	temp2
	lsr	temp2
	clr	r0
	clr	r1
bindec:
	cpi	temp2,10
	brmi	bindec1
	subi	temp2,10
	inc	r0
	rjmp	bindec
bindec1:
	mov	r1,temp2
bindec2:
	mov	r23,r0
	subi	r23,-48
	rcall	lcd_dsp
	mov	r23,r1
	subi	r23,-48
	rcall	lcd_dsp
	ldi	temp1,255
	sts	vol_t,temp1
	ret
;**********************************************
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
v_dsp:
	ldi	r23,0xCA
	rcall	lcd_cmd
	ldi	r23,'V'
	rcall	lcd_dsp
	ldi	r23,':'
	rcall	lcd_dsp
	ldi	r23,0x30
v_read2:
	cpi16	zH,zL,100
	brmi	v_read3
	subi	zL,100
	sbci	zH,0
	inc		r23
	rjmp	v_read2
v_read3:
	rcall	lcd_dsp
	ldi	r23,'.'
	rcall	lcd_dsp
	ldi	r23,0x30
v_read4:
	cpi	zL,10
	brmi 	v_read5
	subi	zL,10
	inc	r23
	rjmp	v_read4
v_read5:
	rcall	lcd_dsp
	ldi	r23,0x30
	add	r23,zL
	rcall	lcd_dsp
	ret
;**********************************************
str_ck:	;特殊文字を空白にする
	cpi	lcd_data,0x20
	brcs	str_ck1
	cpi	lcd_data,0xE0
	brcc	str_ck1
	cpi	lcd_data,0xA0
	brcc	str_ck2
	cpi	lcd_data,0x80
	brcs	str_ck2	
str_ck1:
	ldi	lcd_data,' '
str_ck2:
	ret
;**********************************************
mp3_int:
	sbis	PIND,mp3_dreq
	rjmp	mp3_int
	ldi	temp1,5
	rcall	wait_ms
	ldi	temp1,0
	ldi	temp2,0
	ldi	temp3,4
	rcall	mp3_cmd	;0,0x0004 ;cmd=temp1,arg[H:L]=temp2:temp3
	ldi	temp1,10
	rcall	wait_us
	ldi	temp1,0
	ldi	temp2,0
	ldi	temp3,0
	rcall	mp3_cmd	;0,0x0000
mp3_int1:
	sbis	PIND,mp3_dreq
	rjmp	mp3_int1		
	ldi	temp1,3
	ldi	temp2,0x9B
	ldi	temp3,0xF7	;0x8000+14318180/2000
	rcall	mp3_cmd	;3,0x9bF7		
	ldi	temp1,11
	lds	temp2,volume
	mov	temp3,temp2
	rcall	mp3_cmd	;11,left/right
	ldi	temp1,1
	rcall	wait_ms
	ldiw	z,mp3_0*2
	rcall	mp3_sin
	ret	
;**********************************************
mp3_read:	;addr=temp1	ret:data=r1:r0
	cbi	DDRD,mp3_so	;input
	sbi	PORTD,mp3_so	;pull up
	clr	r1
	clr	r0
	ldi	r21,16
	cbi	PORTC,mp3_cs
	ldi	temp4,3
	rcall	mp3_write
	mov	temp4,temp1
	rcall	mp3_write
mp3_read1:
	sbi	PORTC,mp3_sclk
	nop
	sbis	PIND,mp3_so
	rjmp	mp3_read2	
	sec
	rjmp	mp3_read3
mp3_read2:
	clc	
mp3_read3:
	rol	r0
	rol	r1
	cbi	PORTC,mp3_sclk
	dec	r21
	brne	mp3_read1
	sbi	PORTC,mp3_cs
	sbi	DDRD,mp3_so	;output
	cbi	PORTD,mp3_so	;clear
	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
	ret	
;**********************************************
tagv1:	;tag_read   r7:6(remain byte) ,r9:8 (remainsec)	
	mov	temp1,r7
	or	temp1,r6	;r6 or r7=0?
	breq	tagv1_z1	;端数ﾊﾞｲﾄなし next
	ldi	temp1,1		;remainsec：端数ﾊﾞｲﾄ分 +1　
	clr	temp2
	add	r8,temp1
	adc	r9,temp2
tagv1_z1:	
	mov	r20,r3		;Tagがｾｸﾀをまたぐかﾁｪｯｸしﾌﾗｸﾞ設定 
	inc	r20		;<- secpcl+1 ｸﾗｽﾀまたぎのﾁｪｯｸ用:最終ｸﾗｽﾀのｾｸﾀ数=1　　
	clr	r21		
	ldi	temp1,0x80	;remain byte >= 128ﾊﾞｲﾄ?
	cp	r6,temp1	
	brpl	tagv1_z	;r6=>128 　128ﾊﾞｲﾄ以上
	tst	r7		;r7<1　?
	brne	tagv1_z	;r6<128 ＆ r7<1　no
	ldi	r21,1		;Tagがｾｸﾀをまたぐ：ﾌﾗｸﾞ設定 
tagv1_z:
	tst	r9	;last-1 cluster & mod sec=1? 
	brne	tagv1_a	;r25 !=0 ,no
	tst	r21	;Tagがｾｸﾀをまたぐ?
	breq	tagv1_a	;no
	cp	r8,r20
	breq	tagv1_a0	;クラスタをまたぎ＆remain<128byte
tagv1_a:
	rcall	next_cluster	;cluster=r11:10,nextcluster=r5:4
	clr	temp1
	sub	r8,r3
	sbc	r9,temp1	;last cluster
	brcs	tagv1_a1	;secpcl <= rimain
	breq	tagv1_a1
	mov	r11,r5
	mov	r10,r4
	rjmp	tagv1_z
tagv1_a1:			;ｸﾗｽﾀをまたがない
	add	r8,r3		;端数ｾｸﾀが0ならr8=secpcl
	mov	r24,r8		;remainsec 
	tst	r21		;remain >= 128byte?
	brne	tagv1_a2	;no <128
	mov	r22,r6	;yes　read start addr set	
	mov	r23,r7	;remain-128 から読む
	subi	r22,128
	sbci	r23,0	
	rcall	tagv1_b  
	ret
tagv1_a0:	;ｸﾗｽﾀ(セクタ)をまたぐ
	mov	r24,r3	;(最終-1)ｸﾗｽﾀの最終ｾｸﾀ　ﾎﾟｲﾝﾀ(secpcl-1)
	ldi	r22,low(384)
	ldi	r23,high(384)	;read start addr set
	add	r22,r6		;512-(128-remain)=384+remain
	adc	r23,r7
	rcall	tagv1_b	;(最終-1)ｾｸﾀを384+remainﾊﾞｲﾄから読む
	push	xH
	push	xL
	rjmp	tagv1_1	;残りを最終ｸﾗｽﾀのｾｸﾀ(最終ｾｸﾀ）のはじめから読む
tagv1_a2:	;ｾｸﾀをまたぐ
	dec	r24	 	
	ldi	r22,low(384)
	ldi	r23,high(384)	;read start addr set
	add	r22,r6		;512-(128-remain)=384+remain
	adc	r23,r7
	rcall	tagv1_b		;(最終-2)ｾｸﾀを384+remainﾊﾞｲﾄから読む
	push	xH
	push	xL
	ldi	temp1,0x02	;lastsec addr set
	clr	temp2
	add	r13,temp1	;addr+512
	adc	r14,temp2
	adc	r15,temp2
	rjmp	tagv1_1a	;残りを最終ｾｸﾀのはじめから読む
tagv1_b:	; cluster read
	rcall	sec_addr_set	;r15:14:13:12
	ldi	temp1,0x02
	dec	r24
	mul	temp1,r24
	clr	temp1
	add	r13,r0
	adc	r14,r1		;last or last-1 sector
	adc	r15,temp1	;addset ;r12=0
	sts	spi_arg+1,r15
	sts	spi_arg+2,r14
	sts	spi_arg+3,r13	
	sts	spi_arg+4,r12
	rcall	spi_read_open
	ldiw	y,0
	ldiw	x,id3
	ldi	temp3,low(id3+128)
	ldi	temp4,high(id3+128)
tagv1_01:
	rcall	spi_in
	cp	yL,r22
	cpc	yH,r23
	brcs	tagv1_02	;remain-128 から
	cp	xL,temp3	;
	cpc	xH,temp4	;128byte読む
	brpl	tagv1_02
	st	x+,temp2
tagv1_02:
	adiw	yL,1
	cpi	yH,0x02
	brne	tagv1_01
	rcall	spi_read_close
	ret
tagv1_1:
	rcall	next_cluster
	mov	r11,r5
	mov	r10,r4
	rcall	sec_addr_set	;r15:14:13:12
tagv1_1a:
	sts	spi_arg+1,r15
	sts	spi_arg+2,r14
	sts	spi_arg+3,r13
	sts	spi_arg+4,r12
	rcall	spi_read_open
	ldiw	y,0
	pop	xL
	pop	xH
	ldi	temp3,low(id3+128)
	ldi	temp4,high(id3+128)
tagv1_10:
	rcall	spi_in
	cp	xL,temp3
	cpc	xH,temp4
	brpl	tagv1_11
	st	x+,temp2
tagv1_11:
	adiw	yL,1
	cpi	yH,0x02
	brne	tagv1_10
	rcall	spi_read_close
	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




;**********************************************
;LCD  メッセージ表示
lcd_dat_dsp:
	ldi	lcd_data,1	; clear ,homepos
	rcall	lcd_cmd
	ldi	lcd_data,0x82
 	rcall	lcd_cmd
lcd_dat_dsp1:
	lpm	lcd_data,z+
	cpi	lcd_data,13
	brne	lcd_dat_dsp2
	ret
lcd_dat_dsp2:
	rcall	lcd_dsp
	rjmp	lcd_dat_dsp1
;**********************************************
; LCD - Send a data/cmd into LCD
	;PORTD   7   6   5   4   3   2    1   0
	;write   <-data(H/L)->  enb r/w  R/S  mp_dreq=1
	;read   BF / address   
 
lcd_int:	; Internal reset
	ldi	lcd_data,0x31	; data='0011',RW = "L",E = "L",RS = "L"
	out	PORTD,lcd_data	; mp_dreq=1
	sbi	PORTD,lcd_enb	; E = "H"
	nop			; I/O delay
	nop			; I/O delay
	nop			; I/O delay
	cbi	PORTD,lcd_enb	; E = "L"
	ret
lcd_dsp:
	rcall	lcd_bfch
	ldi	temp3,3		; RW = "L",E = "L", RS = "H",data='xxxx'
	rjmp	lcd_cmd1	; mp_dreq=1
lcd_cmd:
	rcall	lcd_bfch
	ldi	temp3,1		; RW = "L",E = "L",RS = "L",data='xxxx'
lcd_cmd1:			; mp_dreq=1
	mov	temp2,lcd_data
	swap	temp2
	andi	temp2,0xf0	;data_L save
	andi	lcd_data,0xf0   ;data_H set
	or	lcd_data,temp3
	out	PORTD,lcd_data	; PORTD = data_H,RW
	sbi	PORTD,lcd_enb	; E = "H"
	mov	lcd_data,temp2	; 
	or	lcd_data,temp3	;data_L set
	nop					
	cbi	PORTD,lcd_enb	; E = "L"
	nop			; I/O delay				
	out	PORTD,lcd_data	; PORTD = data_L,RW
					
	sbi	PORTD,lcd_enb	; E = "H"
	nop			; I/O delay
	nop			; I/O delay
	nop			; I/O delay
	cbi	PORTD,lcd_enb	; E = "L"
	ret
lcd_bfch:
	cbi	DDRD,lcd_db7	; lcd_db7 = INPUT
	sbi	PORTD,lcd_db7	; pullup
	sbi	PORTD,lcd_rw	; RW = "H"
	cbi	PORTD,lcd_rs	; RS = "L"
lcd_bfch1:
	sbi	PORTD,lcd_enb	; E = "H"
	nop			; I/O delay
	nop			; I/O delay
	in	temp1,PIND
	cbi	PORTD,lcd_enb	; E = "L"
	nop
	nop
	sbi	PORTD,lcd_enb	; E = "H"
	nop			; I/O delay
	nop			; I/O delay
	in	temp2,PIND
	cbi	PORTD,lcd_enb	; E = "L"
	andi	temp1,0x80	; Wait until busy flag becomes zero.
	brne	lcd_bfch1
	sbi	DDRD,lcd_db7	; lcd_db7 = OUTPUT
	cbi	PORTD,lcd_db7	; clear
	ret

wait_us:	;base 8MHz  temp1　us (8clocks)
	nop			; 1clocks
	nop			; 1clocks
	nop			; 1clocks
	nop			; 1clocks
	nop			; 1clocks		
	dec	temp1		; 1clocks
	brne	wait_us		; 2clocks
	ret			; 

wait_ms:
				;temp1　ms
	ldi	temp2,125	;64*125=8000clocks
wait_ms_01:
	ldi	temp3,15    	;1clocks  4*(15+1)=64
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
;*********************************************
;main_test:
;	ldi	lcd_data,0x80
; 	rcall	lcd_cmd
;	ldiw	y,buff
;main_21:
;	ld	r20,y+
;	rcall	dsp_dec
;	cpi16	yh,yl,buff+8
;	brne	main_22
;	ldi	lcd_data,0xC0
;	rcall	lcd_cmd
;main_22:
;	cpi16	yH,YL,buff+16
;	brne	main_21
;**********************************************
dsp_dec:
	ldi	r23,0xF0
	and	r23,temp4
	swap	r23
	cpi	r23,10
	brmi	dsp_dec1
	subi	r23,-7
dsp_dec1:
	subi	r23,-48
	rcall	lcd_dsp
	ldi	r23,0x0F
	and	r23,temp4
	cpi	r23,10
	brmi	dsp_dec2
	subi	r23,-7
dsp_dec2:
	subi	r23,-48
	rcall	lcd_dsp	
	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	 	 	 ;呼び出し元へ復帰
;*********************************************
;LCD DATA
ready:		.db "MP3 Player ",13
fat_err:	.db "VFAT error ",13
sd_err:	.db "SD error   ",13
no_mp3:	.db "No MP3 files ",13
mp3_err:	.db "MP3 error  ",13
no_tag:	.db "No ID3 Tag V1",13
vol:		.db "Vol:",13,0
batt_low:	.db "  Battery Low   ",13,0
shut_down:	.db "Shut Down",13
pause:		.db	" Pause",13,0
;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
