	title	88dot01
;
;=========================
;	PIC-88DOT01
;=========================
;
;	Copyright 2007 アルゴ算法堂
;
;	8X8 dot LED の表示テスト
;		hc238を使用
;	Clock4MHz Internal 版 
;
;	*最終的にはアプリケーションを仕込みたい
;	*クロックは外付け20MHzに変更予定（現在は4MHz)
;	*row スキャン信号は、キースキャンとして使えるはず？
;	スキャンタイミングは現在は1mS
;
;	アドレスポート(RA0:2)→HC238→RA3
;
;
;	更新履歴
;	=======
;	07/11/??	0x0402	Ver.1.02	キースキャン組み込み
;						スタートはb0キーで
;	07/11/15	0x0401	Ver.1.01	8qeen 組み込み
;	07/10/30	0x0400	Ver.1.00	最初の版
;
;	内蔵オシレータではMCLRをGPIOとして使用できない。
;
	list	 p=16f648a
	#include p16f648a.inc
	
; CONFIGRATIONS
	__config	_INTOSC_OSC_NOCLKOUT & _PWRTE_ON & _WDT_OFF & _BOREN_ON & _LVP_OFF & _MCLRE_ON & _DATA_CP_OFF & _CP_OFF


; Set User ID Memory
	__idlocs	0x0402
;
;
;
#define	option_val	b'10010001'
	;b7		RPBU	1: no pullup
	;b6		INTEDE	0:nouse	rb0/int
	;b5		T0CS	timer0 clock source 0:FOSC/4
	;b4		T0SE	nouse	timer0 clock edge
	;b3		PSA		0: prescaler to timer0
	;b2-b0	PSn		divider
	;				0:	1:2
	;				1:	1:4
	;				2:	1:8
	;				3:	1:16
	;				4:	1:32
	;				5:	1:64
	;				6:	1:128
	;				7:	1:255
;
#define	VRAM_SZ		8	; 8bytes
; IO BIT INDEX
#define	PORTA_ADR_0	0	;OUT for demultiplexer 
#define	PORTA_ADR_1	1	;OUT
#define	PORTA_ADR_2	2	;OUT
#define	PORTA_SW_0	3	;IN keyinput
;;PORTA_SW_1	equ	4	;IN
;
#define	PORTB_DATA_0	0	;OUT for LED segment A
#define PORTB_DATA_1	1	;OUT for LED segment B
#define PORTB_DATA_2	2	;OUT for LED segment C
#define PORTB_DATA_3	3	;OUT for LED segment D
#define PORTB_DATA_4	4	;OUT for LED segment E
#define PORTB_DATA_5	5	;OUT for LED segment F
#define PORTB_DATA_6	6	;OUT for LED segment G
#define PORTB_DATA_7	7	;OUT for LED segment dot
;
#define PORTA_ADR_MASK	((1<<PORTA_ADR_0)|(1<<PORTA_ADR_1)|(1<<PORTA_ADR_2))
;
#define		PORTA_DIR	b'00101000'
			; b0: 0 GPIO Output adr_0
			; b1: 0 GPIO Output adr_1
			; b2: 0 GPIO Output adr_2
			; b3: 1 GPIO Input for Keyport
			; b4: 0 GPIO Output nouse (OD)^
			; b5: 1 MCLR
			; b6: 0 GPIO Output (xtal)
			; b7: 0 GPIO Output (xtal)
#define		PORTB_DIR	b'00000000'
			; b0: 0 GPIO Output data_0
			; b1: 0 GPIO Output data_1
			; b2: 0 GPIO Output data_2
			; b3: 0 GPIO Output data_3
			; b4: 0 GPIO Output data_4
			; b5: 0 GPIO Output data_5
			; b6: 0 GPIO Output data_6
			; b7: 0 GPIO Output data_7
;
; COMMON REGISTERS (NON BANKED REGISTERS)
;	(0x70-0x7f)
	cblock	0x70
	irq_wback	; wk backup
	irq_sback	; swap backup
	irq_fsrback
	irq_pclathback
	endc
;
; bank0
;	banked works (0x20-0x6f)
;
	cblock	0x20
;
	temp			; temporary work for general(non ie)
	temp2
;
	timer0_count
	timer0_wait
;
	ctrl			; global status
	row_count		; row index
	vram:VRAM_SZ		; display data
;
;-- gpio bacup ----
;
	porta_back
;
;-- keyboard --
;
	key_status		; bit status
	key_oldval		; チャッタ対策保存
	key_val
;
;-- GRaohics ----
;
	g_bitpat:8
	g_x			; adr x
	g_y			; adr y
	g_temp			; temp in Graphics
;
;--- queen_works ------
;
	q_mapindex
	q_map:8
	q_count
;
	q_val
	q_temp
	endc
;
;	ctrl の　制御ビット
#define	CTRL_INHIBIT	0	; 表示禁止（キースキャンも行わない）
#define	CTRL_STT	1	; 開始後一回目のスキャンが終わった（これからキーを読める）
;

;
;	eeprom definition
;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;	programs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	org	0x0
;
;***************
;	startup
;***************
startup:
	call	initialize
	goto	main
;
	org	0x4
;
;***************
;	intrupt
;***************
irq:
	; prologue
	movwf	irq_wback	;save wk
	swapf	STATUS,w	;save status
	movwf	irq_sback
;
	bcf	STATUS,RP0
	bcf	STATUS,RP1
	bcf	STATUS,IRP
	;
	; prologue 2
	movf	FSR,w
	movwf	irq_fsrback
	movf	PCLATH,w
	movwf	irq_pclathback
	;
	;----------------
	btfsc	INTCON,T0IF
	call	tmr0irq
	;----------------
	; epilogue 2
	;
	movf	irq_pclathback,w
	movwf	PCLATH
	movf	irq_fsrback,w
	movwf	FSR
	;
	; epilogue
	swapf	irq_sback,w	;load status
	movwf	STATUS
	swapf	irq_wback,f	;load wk
	swapf	irq_wback,w
	retfie


;;;;;;;;;;;;
;***********************************
;	initialize for standard hardware
;***********************************
initialize:
	clrf	STATUS
;
; initialize portA & portB
;
	clrw
	movwf	PORTA
	movwf	porta_back
	movwf	PORTB		; 
;
; data directions
;
	bsf	STATUS,RP0
	movlw	PORTA_DIR
	movwf	TRISA
	movlw	PORTB_DIR
	movwf	TRISB
	bcf	STATUS,RP0
;
; option_reg
;
	bsf	STATUS,RP0
	movlw	option_val
	movwf	OPTION_REG
	bcf	STATUS,RP0
;
; ccp nouse (default)
;
; comparator(not used)
;
	movlw	0x07		; com off
	movwf	CMCON
;
; vref nouse (default)
; timer1(not used) default
; timer2(not used) default
;
; usart(not used)
;
; timer0(use)
;
	clrf	TMR0
; interupt
	clrf	INTCON
	bsf	INTCON,T0IE
	return
;
;*********************
;	main routine
;*********************

main:
;
	clrf	timer0_count
	clrf	ctrl
	clrf	row_count
	call	vramClr
;
	clrf	key_status
	clrf	key_oldval
;
;
	clrf	TMR0
	bsf	INTCON,GIE		; global irq
;;
	call	keyscanInit
;;
	call	keytest0		; 暫定
;;
main_loop:
	call	Queen
	goto	main_loop
;
;-------------------
; timer0 irq routine
;-------------------
tmr0irq:
	bcf	INTCON,T0IF
	incf	timer0_count,f
;
	btfsc	ctrl,CTRL_INHIBIT
	return
	goto	vramDisp

;--------------------
; timer_service
;--------------------

;----------/ tmr0wait /---------
;
;	in: w:count
;
tmr0wait
	movwf	timer0_wait
	clrf	timer0_count
tmr0wait_loop:
	movf	timer0_wait,w
	subwf	timer0_count,w
	btfss	STATUS,C
	goto	tmr0wait_loop
	return
;
;-------------------
; vramFunction
;-------------------
;
;
;----------/ vramDisp /----------
;
;	単純表示処理
;	キースキャンも兼ねる
;
;	ちらつき対策の表示手順は次の通り
;	bSf 	ctrl,CTRL_INHIBIT
;	clrf	adr_count
;	データをvramにセット
;	bcf	ctrl,CTRL_INHIBIT
;
vramDisp:
;
	; 表示を消す
	clrf	PORTB
	; 桁指定
	movlw	~PORTA_ADR_MASK
	andwf	porta_back,w
	iorwf	row_count,w
	movwf	porta_back
	movwf	PORTA
	; 内容出力
	movf	row_count,w
	addlw	vram
	movwf	FSR
	movf	INDF,w
	movwf	PORTB
	;;;; キー処理 ;;;;;
	bcf	STATUS,C
	btfsc	PORTA,PORTA_SW_0
	bsf	STATUS,C
	rrf	key_val,f
	movlw	7
	subwf	row_count,w
	btfss	STATUS,Z
	goto	vramDisp_next
	; 8個スキャンした
	movf	key_oldval,w
	subwf	key_val,w
	btfss	STATUS,Z
	goto	vramDisp_skip
	; 値が一致した
	movf	key_val,w
	movwf	key_status
	bsf	ctrl,CTRL_STT		;; キーが確定した
vramDisp_skip:
	movf	key_val,w
	movwf	key_oldval
vramDisp_next:
	;;;; 最終更新 ;;;;
	; count up
	incf	row_count,f
	movlw	7
	andwf	row_count,f
;
	return
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	メイン側の処理
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;-------/ vramClr /----------
;
;	値を0にする
;
vramClr:
	bsf 	ctrl,CTRL_INHIBIT
	clrf	row_count
;
	movlw	vram
	movwf	FSR
	movlw	8
	movwf	temp
vramClr_loop:
	clrf	INDF
	incf	FSR,f
	decfsz	temp,f
	goto	vramClr_loop
;
	bcf	ctrl,CTRL_INHIBIT
	return
;
;----------/ vramSetDbg /-------------
;
;	デバッグ用の表示1
;	現在は未使用
;
;	set debug value to registor
;
vramSetDbg:
	bsf 	ctrl,CTRL_INHIBIT
	clrf	row_count
;
	movlw	0x01
	movwf	vram+0
	movlw	0x02
	movwf	vram+1
	movlw	0x03
	movwf	vram+2
	movlw	0x04
	movwf	vram+3
	movlw	0x05
	movwf	vram+4
	movlw	0x06
	movwf	vram+5
	movlw	0x07
	movwf	vram+6
	movlw	0x08
	movwf	vram+7
;
	bcf	ctrl,CTRL_INHIBIT
	return
;
;========================
; Graphics
;========================
;
;-------/ ginit /---------
;
ginit
	movlw	g_bitpat
	movwf	FSR
	movlw	8
	movwf	temp
	movlw	1
ginit_loop:
	movwf	INDF
	bcf	STATUS,C
	rlf	INDF,w
	incf	FSR,f
	decfsz	temp,f
	goto	ginit_loop
	return
;
;--------/ pset /---------
;
;	点をオン
;
;	in: g_x,g_y
;
pset
	movlw	g_bitpat
	addwf	g_x,w
	movwf	FSR
	movf	INDF,w
	movwf	g_temp
	movlw	vram
	addwf	g_y,w
	movwf	FSR
	movf	g_temp,w
	iorwf	INDF,f
	return
;
;--------/ preset /--------
;
;	点をオフ
;
;	in: g_x,g_y
;
preset
	movlw	g_bitpat
	addwf	g_x,w
	movwf	FSR
	movf	INDF,w
	xorlw	0xff
	movwf	g_temp
	movlw	vram
	addwf	g_y,w
	movwf	FSR
	movf	g_temp,w
	andwf	INDF,f
	return
;
;-------/ pget /----------
;
;	点の値
;
;	in: 	g_x,g_y
;	out:	STATUS:Z	OFF
;				ON
;
pget
	movlw	g_bitpat
	addwf	g_x,w
	movwf	FSR
	movf	INDF,w
	movwf	g_temp
	movlw	vram
	addwf	g_y,w
	movwf	FSR
	movf	temp,w
	andwf	INDF,w
	return

;===================
; 8 queen
;===================
;
;	qbufに数字を順に入れながら検証する
;
;---------/ Queen /------------
;
Queen
	call	ginit
;
	clrf	q_count
;
	clrf	q_mapindex
	clrf	q_map		; map[0]
	clrf	g_x
	clrf	g_y
	call	pset
;
;
	goto	queenstep
;

;----------/ check /----------
;
; 現在の桁の現在の値を検証
;
; out:	STATUS:C	1:　ng
;			0: ok
;
check
;
; 左へ検証する
	movf	q_mapindex,w
	movwf	q_temp		;index
	addlw	q_map
	movwf	FSR
	movf	INDF,w
	movwf	q_val
check_loop1:
	decf	FSR,f
	decf	q_temp,f
	btfsc	q_temp,7
	goto	check_loop1e
	movf	INDF,w
	subwf	q_val,w
	btfss	STATUS,Z
	goto	check_loop1
	bsf	STATUS,C
	return
check_loop1e:
;
; 左上へ検証する
	movf	q_mapindex,w
	movwf	q_temp		;index
	addlw	q_map
	movwf	FSR
	movf	INDF,w
	movwf	q_val
check_loop2:
	decf	q_val,f
	btfsc	q_val,7
	goto	check_loop2e
	decf	FSR,f
	decf	q_temp,f
	btfsc	q_temp,7
	goto	check_loop2e
	movf	INDF,w
	subwf	q_val,w
	btfss	STATUS,Z
	goto	check_loop2
	bsf	STATUS,C
	return
check_loop2e:
;
; 左下へ検証する
;
	movf	q_mapindex,w
	movwf	q_temp		;index
	addlw	q_map
	movwf	FSR
	movf	INDF,w
	movwf	q_val
check_loop3:
	incf	q_val,f
	btfsc	q_val,3		;b3 ie 8
	goto	check_loop3e
	decf	FSR,f
	decf	q_temp,f
	btfsc	q_temp,7
	goto	check_loop3e
	movf	INDF,w
	subwf	q_val,w
	btfss	STATUS,Z
	goto	check_loop3
	bsf	STATUS,C
	return
check_loop3e:
;
	bcf	STATUS,C
	return


;--------/ queenstep /---------
;
; アルゴリズム確認用
;
queenstep
;
; 待ちの処理などここに入れる
;
	movlw	.30
	call	tmr0wait
;
; 位置を検証
	call	check
	btfsc	STATUS,C
	goto	queenstep_up
;　適合する場合
	; 次の桁があるか、確かめる
	incf	q_mapindex,f
	btfsc	q_mapindex,3	;b3 8
	goto	queenstep_found
     	; 次の桁がある
	movf	q_mapindex,w
	movwf	g_x		; 点灯するＸ座標
	addlw	q_map
	movwf	FSR
	clrf	INDF		; map[mapindex]=0
	clrf	g_y
	call	pset		; 新しい桁を点灯
	goto	queenstep	; 継続
;
queenstep_found:
	; 次の桁がない。結果が見つかった場合
	decf	q_mapindex,f
	incf	q_count,f
	; ここで見つかった場合のアニメーションを行う
	movlw	.128
	call	tmr0wait
	movlw	.128
	call	tmr0wait
	movlw	.128
	call	tmr0wait
	movlw	.128
	call	tmr0wait
	;
queenstep_up:
; 桁アップ
	; 現在桁を消す
	movf	q_mapindex,w
	movwf	g_x
	addlw	q_map
	movwf	FSR
	movf	INDF,w
	movwf	g_y
	call	preset
	; 現在桁をアップ
	movf	q_mapindex,w
	addlw	q_map
	movwf	FSR
	incf	INDF,f
	; 8以上かテスト
	btfsc	INDF,3	; b3 8
	goto	queenstep_up_cant
	; 8未満なのでアップできた。
	; 点灯する
	movf	q_mapindex,w
	movwf	g_x
	addlw	q_map
	movwf	FSR
	movf	INDF,w
	movwf	g_y
	call	pset
	;
	goto	queenstep	; 継続
queenstep_up_cant:
	; アップできない
	movf	q_mapindex,f
	btfsc	STATUS,Z
	return			; 継続しない
	decf	q_mapindex,f	; 桁を戻す
	goto	queenstep_up
; -- end of qeeunstep

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; キーボードテスト処理
;;	一列目に現在の状態を表示する
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;--------/ keyscanInit /-------
;
;　割り込み解除後、最初のキースキャンの終了を待つ
; 最初に一回ダミーで発行する
;
keyscanInit
keyscanInit_loop:
	btfss	ctrl,CTRL_STT
	goto	keyscanInit_loop
	return
;

;--------/ keytest0 /---------
;
;	b0:キーが新たに押されるまで…
;
keytest0
;
;	b0キーのブレークを確認
keytest0_loop1:
	btfsc	key_status,0
	goto	keytest0_loop1
;	b0キーのメークを確認
keytest0_loop2:
	btfss	key_status,0
	goto	keytest0_loop2
	return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; EEPROM ACCESS
;
;
;;
#if 0
;-------/ ReadRom /--------
;
;	eepromを読む処理
;
;	in:	w romadr
;	out	w value
ReadRom
	bsf	STATUS,RP0
	movwf	EEADR
	bsf	EECON1,RD
	movf	EEDATA,w
	bcf	STATUS,RP0
	return
#endif

;=========================
;	EEPROM SECTION
;=========================
;
;	256 bytes
;	action data
;
;
	org		0x2100
eeprom_top:
;
;
	end
