.include "tn26def.inc"

.def	A=r16
.def	B=r17
.def	C=r18
.def	D=r19
.def	aH=r20
.def	aL=r21
.def	E=r22
.def	flags=r23
.def	test=r24

	rjmp	RESET	;
	reti		;INT0
	reti		;PIN_CHG
	rjmp	TMCOMPA	;TMCOMPA
	reti		;TMCOMPB
	reti		;TMOVF1
	reti		;TMOVF0
	reti		;USI_STRT
	reti		;USI_OVF
	reti		;EE_RDY
	reti		;ANA_COMP
	reti		;ADC

;▼▼▼▼▼初期化
RESET:
	;▼スタックポインタ初期化
	LDI	A,LOW(RAMEND)
	out	sp,A

	;▼IO設定
	ldi	A,0b00000011
	out	PORTA,A
	ldi	A,0b00000011
	out	DDRA,A

	ldi	A,0b01111000
	out	PORTB,A
	ldi	A,0b00000101
	out	DDRB,A

	;▼タイマ設定
	ldi	A,0b11001101
	out	TCCR1B,A
	ldi	A,61
	out	OCR1A,A
	ldi	A,0b01000000
	out	TIMSK,A

	;▼I2C設定
	ldi	A,0b00100000
	out	USICR,A
	sbi	PORTB,0
	sbi	PORTB,2
	sbi	USIDR,7		;SDA開放

	;▼初期情報収集
	in	A,PINB		;DIPSW読み
	lsl	A
	swap	A
	andi	A,0b00001111
	mov	flags,A		;フラグにセット
	sbis	PINB,1		;SWチェック
	ori	flags,0b10000000;フラグにセット

	;▼EEPROMアドレス初期化
	rcall	ResetEepAd

	sei

main:
	nop
	rjmp	main

;▼▼▼EEPROMアドレス初期化
ResetEepAd:
	mov	aH,flags
	swap	aH
	andi	aH,0b01110000
	ldi	aL,0
	ldi	D,0b10101011	;停止番兵データ
	rcall	i2cW		;EEPROMアドレス初期化
	ret

;▼▼▼▼▼タイマ一致割り込み
TMCOMPA:
	push	A		;レジスタ退避
	in	A,SREG
	push	A
	push	B
	push	C
	push	D

	sbrc	flags,7		;書くか読むかで分岐
	rcall	write
	sbrc	flags,7
	rjmp	TM1
	rcall	read
TM1:
	ldi	A,0
	out	TCNT1,A
	pop	D		;レジスタ復帰
	pop	C
	pop	B
	pop	A
	out	SREG,A
	pop	A
	reti
;▼▼▼読み
read:
	cbi	PORTA,0		;LED R消し
	cbi	PORTA,1		;LED Y消し
	sbis	PINB,1		;SWチェック
	ori	flags,0b01000000;ONなら再生許可
	
	sbrs	flags,6		;再生許可フラグチェック
	rjmp	re1
	ldi	A,0b11111111	;IO設定
	out	DDRA,A

	sbi	PORTA,1		;LED Y灯ける
	rcall	i2c		;EEPROMよみ
	cpi	D,0b10101011	;番兵検査
	brne	re2
	ldi	A,0b00000000	;番兵の時
	out	PORTA,A		;　全モータ停止
	mov	A,flags		;　バンク加算
	inc	A
	andi	A,0b00000111
	andi	flags,0b11111000
	or	flags,A
	rcall	ResetEepAd	;　EEPROMアドレス初期化
	sbrs	flags,3		;　連続再生フラグチェック
	andi	flags,0b10111111;　　if(flags(3)==0)再生禁止
	ldi	A,0b00000011	;　I設定
	out	DDRA,A
	cbi	PORTA,1		;　LED Y消し
	rjmp	re1
re2:
	IN	A,PORTA		;データをポートに反映
	andi	A,0b00000011
	andi	D,0b11111100
	or	A,D
	out	PORTA,A
	ldi	A,0		;アドレス加算
	ldi	B,1
	add	aL,B
	adc	aH,A
re1:
	ret
;▼▼▼書き（記録）
write:

	sbic	PINB,1		;if(SW==0N(0) && flags(6)==0) then
	rjmp	wr2
	sbrc	flags,6
	rjmp	wr2
	ldi	A,0b00000011	;　io設定
	out	DDRA,A
	ldi	A,0b11111111	;テスト用
	out	PORTA,A		;テスト用
	cbi	PORTA,0		;LED R消し
	rjmp	wr1		;
wr2:				;else
	sbi	PORTA,0		;　LED R灯ける
	sbi	PORTA,1		;　LED Y灯ける
	ori	flags,0b01000000;　flags(6)=1
	in	D,PINA		;　データ採取
	andi	D,0b11111100
	rcall	i2cW
	ldi	A,0		;　アドレス加算
	ldi	B,1
	add	aL,B
	adc	aH,A
	sbic	PINB,1		;　if(SW==ON(0))
	rjmp	wr1
	cli			;　　全割り込み禁止
	ldi	A,0b00000000	;
	out	PORTA,A		;　　全モータ停止
	rcall	sentinel	;　　番兵書き込み
	rcall	sentinel	;　　番兵書き込み
	rcall	sentinel	;　　番兵書き込み
	andi	flags,0b01111111;　　flags(7)=0リードモード
	andi	flags,0b10111111;　　flags(6)=0再生禁止
	rcall	waitB
	rcall	ResetEepAd	;　　EEPROMアドレスリセット
	cbi	PORTA,1		;　　LEDY消し
wr3:	sbis	PINB,1		;
	rjmp	wr3		;　　SW離すまで待つ
	sei
wr1:
	cbi	PORTA,1		;LED Y 消し
	ret
sentinel:
	ldi	D,0b10101011
	rcall	waitB
	rcall	i2cW
	ldi	A,0		;　アドレス加算
	ldi	B,1
	add	aL,B
	adc	aH,A
	ret
;▼▼▼i2cEEPROM書き（アドレス：aH,AL データ:D）
i2cW:
	sbis	PINB,2		;SCL開放待ち
	rjmp	i2cW
	cbi	USIDR,7		;開始条件生成
	rcall	waitA
	sbi	USISR,USISIF	;開始条件保持解除
	sbi	USICR,USITC	;SCLをLに
	rcall	waitA
	ldi	A,0b10100000	;writeのアドレス設定
	out	USIDR,A		;ディバイスアドレスをセット
	rcall	isend		;writeのアドレス送信
	out	USIDR,aH	;上位アドレスをセット
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	isend		;上位アドレス送信
	out	USIDR,aL	;下位アドレスをセット
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	isend		;下位アドレス送信
	out	USIDR,D		;記憶データをセット
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	isend		;記憶データ送信
	rcall	waitA
	cbi	USIDR,7		;SDAをLに
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	waitA
	sbi	USICR,USITC	;SCL開放
	rcall	waitA
	sbi	USIDR,7		;SDA開放(終了条件)
	rcall	waitA
	ret

isend:	sbi	USISR,USICNT3	;4bitカウンタに8を書き込む
	rcall	waitA
isend2:	sbi	USICR,USITC	;SCL開放
isend1:	sbis	PINB,2		;SCL開放待ち
	rjmp	isend1
	rcall	waitA
	sbi	USICR,USITC	;SCLをLに
	rcall	waitA
	sbi	USICR,USICLK	;シフトレジスタをシフト、
	rcall	waitA
	sbis	USISR,USIOIF	;4bitカウンタオーバーフローまで
	rjmp	isend2		;繰り返し
	sbi	USISR,USIOIF	;オーバーフローフラグ解除
	rcall	waitA
	sbi	USICR,USITC	;SCL開放(StartACK)
	rcall	waitA
	rcall	waitA		;ACK
	rcall	waitA
	ret
;▼▼▼i2cEEPROM読み（アドレスaH,aL:カレント データ:D）
i2c:	sbi	USISR,USICNT3	;4bitカウンタに8を書き込む
	sbis	PINB,2		;SCL開放待ち
	rjmp	i2c
	cbi	USIDR,7		;開始条件生成
	rcall	waitA
	sbi	USISR,USISIF	;開始条件保持解除
	sbi	USICR,USITC	;SCLをLに
	rcall	waitA
	ldi	A,0b10100001	;readでアドレス設定
	out	USIDR,A		;送信データをセット
	rcall	waitA
i2:	sbi	USICR,USITC	;SCL開放
i1:	sbis	PINB,2		;SCL開放待ち
	rjmp	i1
	rcall	waitA
	sbi	USICR,USITC	;SCLをLに
	rcall	waitA
	sbi	USICR,USICLK	;シフトレジスタをシフト、
	rcall	waitA
	sbis	USISR,USIOIF	;4bitカウンタオーバーフローまで
	rjmp	i2		;繰り返し
	sbi	USISR,USIOIF	;オーバーフローフラグ解除
	rcall	waitA
	sbi	USICR,USITC	;SCL開放(StartACK)
	rcall	waitA
	rcall	waitA
	rcall	waitA
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	waitA
	sbi	USISR,USICNT3	;4bitカウンタに8を書き込む
	ldi	A,0b11111111
	out	USIDR,A		;データ入力もーど
i3:	sbi	USICR,USITC	;SCL開放
	rcall	waitA
	sbi	USICR,USICLK	;シフトレジスタをシフト、
	rcall	waitA
	sbi	USICR,USITC	;SCLをLに
	rcall	waitA
	sbis	USISR,USIOIF	;4bitカウンタオーバーフローまで
	rjmp	i3		;繰り返し
	sbi	USISR,USIOIF	;オーバーフローフラグ解除
	in	D,USIDR		;データを採取
	sbi	USIDR,7		;ACKをHで発行
	rcall	waitA
	sbi	USICR,USITC	;SCL開放(StartACK)
	rcall	waitA
	rcall	waitA
	rcall	waitA
	sbi	USICR,USITC	;SCLをLに(EndACK)
	rcall	waitA
	cbi	USIDR,7		;SDALに
	rcall	waitA
	sbi	USICR,USITC	;SCL開放
	rcall	waitA
	sbi	USIDR,7		;SDA開放(終了条件生成)
	rcall	waitA
	ret

waitA:	push	A
	ldi	A,5
wA1:	dec	A
	brne	wA1
	pop	A
	ret

waitB:
	push	B
	push	A
	ldi	B,10
wB2:	ldi	A,255
wB1:	dec	A
	brne	wB1
	dec	B
	brne	wB2
	pop	A
	pop	B
	ret
