;********************************************
;*****　　　　　電子マスカット
;*****　　　　　http://www.zea.jp/audio
;*****　　　　　yasuyuki-ishizuka
;*****　　　　　青い電子サイコロ
;********************************************

;*****使用デバイス*****
	list	P=PIC12F629
	include  "P12F629.INC"

;*****コンフィグビット*****
;データROMプロテクト-無効
;コードプロテクト-無効
;低電圧リセット検知-無効
;MCLR端子-無効（GP3）汎用入力端子として使用）
;パワーオンリセット-有効
;ウォッチドッグタイマ-無効
;OSC-内部発振（GP4:I/O端子で使用）
	__CONFIG _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

;*****レジスタ定義*****（20h～5fhまで利用可）
beept	equ	20h			;ブザー音の周期を決めるレジスタ
time1	equ	21h			;タイムディレイに使う
time2	equ	22h			;タイムディレイに使う
time3	equ	23h			;タイムディレイに使う
count1	equ	24h			;1～12まで変化するカウンタ（乱数として使用）
count2	equ	25h			;スリープへ移行するまでのカウンタ
count3	equ	26h			;スリープへ移行するまでのカウンタ
count4	equ	27h			;スリープへ移行するまでのカウンタ
saime	equ	28h			;サイコロの目
scnt	equ	29h			;低速回転数

;*****プログラム*****
	org	0
	goto	intset

;*****イニシャルセット*****
intset
	bsf		STATUS, RP0	;バンク1に移行
	call	3ffh		;内部発振周波数校正値リード
	movwf	OSCCAL		;内部発振周波数校正値ライト
	movlw	b'00001000'	;GP3のみ入力、その他を出力端子に設定
	movwf	TRISIO
	movlw	b'00000000'	;オプション設定（念のため設定）
	movwf	OPTION_REG
	movlw	b'00001000'	;GP3を状態変化として使用
	movwf	IOC
	bcf		STATUS, RP0	;バンク0に戻る
	clrf	GPIO
	movlw	b'00000111'
	movwf	CMCON		;GP0-2をデジタルI/Oに設定
	movlw	b'00001000'	;GPIO変化割り込み有効
	movwf	INTCON		;SLEEPからのwake-upのみで使用のためGIEは立てない

;*****saimeレジスタ初期値セット*****
	movlw	0x06
	movwf	saime

;*****スタート*****
start
	call	ondisp		;全点灯
	call	t100ms		;100m秒待ち
	clrf	GPIO		;全消灯
	call	t10ms		;10m秒待ち
	call	ondisp		;全点灯
	call	beep		;beep音
	call	t10ms
	clrf	GPIO
	call	t10ms
	call	ondisp
	call	beep
	call	t10ms
	clrf	GPIO
	call	t10ms
	call	ondisp
	call	beep

;*****ゲーム*****
game					;実ゲーム前にスイッチが離れていることを確認
	btfss	GPIO,3		;キーが離されるのを待つ
	goto	game
	call	t50ms

game1					;スタートスイッチの押下待ち。一定時間経過でスリープに移行。
	movlw	0x1e		;スリープへ移行する初期値（1の増減で約1秒変化する）:初期値は約30秒
	movwf	count2
game1a
	movlw	0x64		;スリープへ移行する初期値
	movwf	count3
game1b
	movlw	0x9b		;スリープへ移行する初期値
	movwf	count4
game1c
	movlw	0x0c		;スタートスイッチが押下されるまでにcount1レジスタは1～12まで高速に変化する
	movwf	count1		;これを乱数とみなして最後の低速回転数を決める

game1d
	btfss	GPIO,3
	goto	game2		;スタートスイッチが押下されていればgame2へ
	decfsz	count1,f
	goto	game1d

	decfsz	count4,f
	goto	game1c
	decfsz	count3,f
	goto	game1b
	decfsz	count2,f
	goto	game1a
	call	beep		;SLEEPへ移行する手順へ
	call	t20ms
	call	beep
	clrf	GPIO		;SLEEPへ移する前に全消灯させる
	bcf		INTCON,GPIF	;SLEEP寸前にGPIFビットをクリア
	sleep
	nop					;ここでスリープ
	goto	start		;Wake-UPはstartラベルから

game2					;低速回転数確定部
	movlw	0x06		;最低6回転がすことにした
	addwf	count1,f
game2a
	movf	count1,w	;count1レジスタをscntレジスタに転送
	movwf	scnt

game3					;高速回転ルーチン
	call	disp
	call	t5ms
	btfsc	GPIO,3		;スタートスイッチが離されればgame4へ
	goto	game4
	goto	game3

game4					;低速回転ルーチン
	call	disp
	call	t50ms
	btfss	GPIO,3		;低速回転中にスタートスイッチ押下でgame2へ
	goto	game2a
	decfsz	scnt		;算出した低速回転数を回して確定される
	goto	game4

	call	t300ms
	call	beep5		;ブザーを5回鳴らしてgameへ
;	call	t100ms
	goto	game

;*****beepサウンド*****
beep
	movlw	0x30
	movwf	beept
beep1
	bsf		GPIO,5
	call	t50us
	bcf		GPIO,5
	call	t50us
	decfsz	beept,f
	goto	beep1
	return

;*****タイムディレイライブラリ（時間はおおよその値）*****
t50us
	movlw	0x30
	movwf	time1
t50us1
	decfsz	time1,f
	goto	t50us1
	return

t1ms
	movlw	0x08
	movwf	time2
t1ms1
	movlw	0x7d
	movwf	time3
t1ms2
	decfsz	time3,f
	goto	t1ms2			
	decfsz	time2,f
	goto	t1ms1
	return

t5ms
	call	t1ms
	call	t1ms
	call	t1ms
	call	t1ms
	call	t1ms
	return

t10ms
	call	t5ms
	call	t5ms
	return

t20ms
	call	t10ms
	call	t10ms
	return

t50ms
	call	t10ms
	call	t20ms
	call	t20ms
	return

t100ms
	call	t50ms
	call	t50ms
	return

t300ms
	call	t100ms
	call	t100ms
	call	t100ms
	return

;*****表示ルーチン（呼び出される毎に表示をカウント）****
disp
	movf	saime,w			;saimeカウンタの数字に該当するビット情報を持ってくる
	call	digit
	movwf	GPIO			;ビット情報を出力
	call	beep			;ブザー音
	decfsz	saime,f			;saimeカウンタを1つ減算
	return
	movlw	0x06			;saimeカウンタが0だったら6にセット
	movwf	saime
	return

digit
	addwf	PCL,f
	retlw	b'00011111'		;0:saimeレジスタは1～6の値になるのでこのデータ[0]は使われない
	retlw	b'00001111'		;1:6の目を表示するときのビット状態
	retlw	b'00011101'		;2:5の目を表示するときのビット状態
	retlw	b'00001101'		;3:4の目を表示するときのビット状態
	retlw	b'00011100'		;4:3の目を表示するときのビット状態
	retlw	b'00001100'		;5:2の目を表示するときのビット状態
	retlw	b'00011000'		;6:1の目を表示するときのビット状態

;****全点灯*****
ondisp
	movlw	b'00010111'		;点灯
	movwf	GPIO
	return

;*****beepを5回発生*****
beep5
	call	beep
	call	t20ms
	call	beep
	call	t20ms
	call	beep
	call	t20ms
	call	beep
	call	t20ms
	call	beep
	return

;*****内蔵発振周波数キャリブレーション書込み*****
;事前にPIC12F629のプログラムメモリの最終データを控えておくこと!!!!!

	org		0x3ff		;最終番地
	retlw	0x38		;手持ちのPIC12F629をセット

	end
