;;	連打マウスプログラム
;;		Copyright(C) 2000 by Alarmist. All Rights Reserved.
;;; 履歴
;;; Ver0.70	7,Apr	公開バージョン
;;; Ver0.71	10,Apr	修正
.INCLUDE "1200def.inc"

.DEF TEMP = R16
.DEF button = R17
.DEF status = R18		; 連射中のフラグ
.DEF STACK = R19		; すたっく
.DEF SPEED = R20
.DEF SSTACK = R21
	
.DEF storespeed = R22

	; リセットベクトルと割り込みベクトルの指定
	RJMP	RESET		; リセット ($000)
	RJMP	RESET		; 外部割り込み ($001)
	RJMP	TIM0_OVF	; タイマー０オーバーフロー($002)
	RJMP	RESET		; アナログコンパレータ($003)

RESET:

	; EEPROM access
	ldi	TEMP, $01
	out	EEAR, TEMP	; set EEPROM adrs =$01
	sbi	EECR, EERE
	in	storespeed, EEDR	; 内容をstoreSPEEDに。

	; タイマーカウンタの設定
	LDI	TEMP, $ce	; 1MHz / 1024 / 49 = 19.9Hz = 0.05sec
	OUT	TCNT0, TEMP	; タイマーカウンタ 1/に設定
	
	LDI	TEMP, ((1<<CS02) + (1<<CS00))	; 内部クロック 1/1024
	OUT	TCCR0, TEMP
   
    ; タイマーオーバーフロー割り込みを指定
	LDI	TEMP, (1<<TOIE0)
	OUT	TIMSK, TEMP

	SEI

	; 数値の初期設定
;	LDI	SPEED, $0a	; 0.05s x 10 = 0.5s 
;	LDI	SSTACK, $0a
	mov	SSTACK, storespeed
	mov	SPEED,SSTACK
	LDI	status, $00

	; ポート入出力の設定
	LDI	TEMP,$FF
	OUT	DDRB,TEMP	; ポートＢは全て出力に使用する

	LDI	TEMP,$00	
	OUT	PORTB,TEMP	; 出力の初期値＝Ｌ

	LDI	TEMP,$00
	OUT	DDRD,TEMP	; ポートＤは全て入力に使用する

	LDI	TEMP,0b11111100
	OUT	PORTD,TEMP	; 入力プルアップは全て無効

MAIN_LOOP:
	cpi	status,$50	; status=50は例外(^^;
	breq	nooff
	cpi	status,$11	; 
	brsh	MAIN_LOOP	; thrust 10以上なら出力オフ
nooff:
	IN	button,PIND	; ポートＤからの入力
	andi	button, $03
	OUT	PORTB,button	; を、そのままBに出力
	RJMP 	MAIN_LOOP	; ずっと繰り返すのだ。

;	タイマ割り込み処理るーちん
;	0.05sごとに飛んでくる。
TIM0_OVF:
	IN	STACK, SREG		; フラグの待避

	in	button, PIND		; 現在のボタンの状態を得る
	andi	button, $03		; 下２ビットのみ有効に

;分岐
	cpi	status,$00
	brne	no0
	rjmp	status0
no0:
	cpi	status,$10
	brne	no10
	rjmp	status1
no10:
	cpi	status,$20
	brne	no20
	rjmp	status2
no20:
	cpi	status,$21
	brne	no21
	rjmp	status21
no21:
	cpi	status,$22
	brne	no22
	rjmp	status22
no22:
	cpi	status,$30
	brne	no30
	rjmp	status3
no30:
	cpi	status,$31
	brne	no31
	rjmp	status31
no31:
	cpi	status,$32
	brne	no32
	rjmp	status32
no32:
	cpi	status,$40
	brne	no40
	rjmp	status4
no40:
	cpi	status,$50
	brne	no50
	rjmp	status50
no50:
	cpi	status,$51
	brne	no51
	rjmp	status51
no51:
	cpi	status,$52
	brne	no52
	rjmp	status52
no52:
	cpi	status,$ff
	brne	noff
	rjmp	THRUST_MODE
noff:
	rjmp	status_reset	; for fail-safe
; normal mode
;-------------
status0:
	mov	SSTACK,storespeed
	cpi	button,$01
	breq	status1
	cpi	button,$02
	brne	nost0
	rjmp	status50
nost0:

	rjmp	status_reset

status1:
	ldi	status,$10
	sbrs	button,0	;button の0ビット目が1なら次スキップ
	rjmp	status_reset	; 左離した→リセットへ
	sbrs	button,1
	rjmp	status_nochange
;	rjmp	status2

status2:
	ldi	status,$20
	cpi	button,$03
	brne	s2_nb3
	rjmp	status_nochange
s2_nb3:
	cpi	button,$02
	breq	status3
	cpi	button,$01
	breq	status21
	rjmp	status_reset

status21:
	ldi	status,$21
	cpi	button,$01
	brne	s21n01
	rjmp	status_nochange
s21n01:
	cpi	button,$03
	breq	status22
	rjmp	status_reset

status22:
	ldi	status,$22
	cpi	button,$03
	brne	s22n03
	rjmp	status_nochange
s22n03:
	cpi	button,$02
	breq	status3
	cpi	button,$01
	breq	s22n04
	rjmp	s22_exit
s22n04:
	inc	SSTACK
	cpi	SSTACK, $19
	brlt	status21
	ldi	SSTACK, $18
	rjmp	status21
s22_exit:
	rjmp	status_reset

status3:
	ldi	status,$30
	cpi	button,$02
	breq	status_nochange
	cpi	button,$03
	breq	status31
	cpi	button,$00
	breq	status4
	rjmp	status_reset

status31:
	ldi	status,$31
	cpi	button,$03
	breq	status_nochange
	cpi	button,$02
	brne	status_reset
	dec	SSTACK
	cpi	SSTACK, $02
	brge	status32
	ldi	SSTACK, $03
	rjmp	status32

status32:
	ldi	status,$32
	cpi	button,$02
	breq	status_nochange
	cpi	button,$03
	breq	status31
	cpi	button,$00
	breq	status4
	rjmp	status_reset

status4:
	ldi	status,$40

	; EEPROM access
;	ldi	TEMP, $01
;	out	EEAR, TEMP	; set EEPROM adrs =$01
;	sbi	EECR, EERE
;	in	storespeed, EEDR	; 内容をstoreSPEEDに。

	cp	storespeed, SSTACK	; ROMの内容と現在速度が同じなら焼かない
	breq	go_thrust

	; EEPROM write
	ldi	TEMP, $01
	out	EEAR, TEMP

	out	EEDR, SSTACK
	sbi	EECR, EEWE
	
wait:
	sbic	EECR, EEWE
	rjmp	wait
	; EEPROM end
	mov	storespeed, SSTACK	; storespeedに焼いた速度をストック

go_thrust:
	mov	SPEED, SSTACK
	rjmp	THRUST_MODE

;	status50-51 for EEPROM reset routine
status50:
	ldi	status,$50
	cpi	button,$02
	breq	status_nochange
	cpi	button,$03
	brne	s50exit
	ldi	TEMP,$28	; $28=40loops =2sec
	rjmp	status51
s50exit:
	rjmp	status_reset

status51: 
	ldi	status,$51
	cpi	button,$03
	brne	s51exit
	dec	TEMP
	cpi	TEMP,$00	;40x0.05=2sec間押しっぱなしにする
	brne	status_nochange
	rjmp	status52		; rom-erase
s51exit:
	rjmp	status_reset

status52:
	ldi	status,$52
	cpi	button,$03
	breq	status_nochange
	cpi	button,$00
	brne	status_nochange
	rjmp	all_reset

status_reset:
	ldi	status,$00
status_nochange:
	rjmp	TIM0_EXT

;------------------------------------------
THRUST_MODE:
	ldi	status, $FF
	cpi	button, $00		; 両ボタン離れてる？
	brne	THRUST_END		; 何か押されたら連打終了

	;両ボタン離れている間は以下の通りに連打する
	ldi	TEMP, $00
	out	PORTB, TEMP		; 左右出力オフ
	dec	SPEED
	cpi	SPEED, $00		; 1/SPEED回だけ発射する
	breq	THRUST_FIRE		
	rjmp	TIM0_EXT

THRUST_END:
	mov	SPEED,SSTACK
	ldi	status,$00
	ldi	button,$00
	out	PORTB,button		; 出力もオフ
	rjmp	TIM0_EXT

THRUST_FIRE:
	ldi	TEMP, $01		; 左ボタンをON
	mov	SPEED, SSTACK		; スピードカウンタをリセット
	out	PORTB, TEMP		; 左出力
	rjmp	TIM0_EXT

;------------------------------

TIM0_EXT:
	out	SREG, STACK ; フラグを戻す
	reti

all_reset:
	cli
	; EEPROM write
	ldi	TEMP, $01
	out	EEAR, TEMP

	ldi	TEMP, $10	; 0.05 x 16= 0.8sec
	out	EEDR, TEMP
	sbi	EECR, EEWE
	
wait2:
	sbic	EECR, EEWE
	rjmp	wait2

	rjmp	RESET
