;
;=========================
;	PIC-7SEG04
;=========================
;
;	Copyright 2007 アルゴ算法堂
;
;	7seg_ledでPIC_MIDICV用のチャンネル表示器
;		アノードコモンのドライブトランジスタを省略したもの
;
;	Clock4MHz Internal 版
;	duty 1/16 版
;
;	更新履歴
;	=======
;	07/10/29	Ver.1.00	最初の版(id=0x0330)
;
;	内蔵オシレータでは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	0x0330
;
;
;
option_val	equ	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
;
; IO BIT INDEX
PORTA_DATA_1	equ	0	;IN
PORTA_DATA_0	equ	1	;IN
PORTA_SEL_0	equ	2	;OUT
PORTA_SEL_1	equ	3	;OUT
PORTA_SW	equ	4	;IN
PORTA_DATA_3	equ	6	;IN
PORTA_DATA_2	equ	7	;IN

;
PORTB_DATA_0	equ	0	;OUT for LED segment A
PORTB_DATA_1	equ	1	;OUT for LED segment B
PORTB_DATA_2	equ	2	;OUT for LED segment C
PORTB_DATA_3	equ	3	;OUT for LED segment D
PORTB_DATA_4	equ	4	;OUT for LED segment E
PORTB_DATA_5	equ	5	;OUT for LED segment F
PORTB_DATA_6	equ	6	;OUT for LED segment G
PORTB_DATA_7	equ	7	;OUT for LED segment dot
;
PORTA_SEL_MASK	equ	((1<<PORTA_SEL_0)|(1<<PORTA_SEL_1))
;
; COMMON REGISTERS (NON BANKED REGISTERS)
;
	cblock	0x70
	irq_wback	; wk backup
	irq_sback	; swap backup
	irq_fsrback
	irq_pclathback
	endc
;
; bank0
;	banked works
;
	cblock	0x20
;
	temp1			; dont use in interupt
	temp2			; dont use in interupt
;
	timer0_count
;
	curval			; current channel value
	loadval			; direct read channel data
;
	ctrl
	font:d'10'		; font copy area
	maskpat:8		; segment maskpattern
	seg_count		; segment index
	vram:2			; display data: upper,lower

;
;
;-- gpio bacup ----
;
	porta_back
; --
	endc
;
;	ctrl の　制御ビット
CTRL_INHIBIT	equ	0	; 表示抑制

;
;	eeprom definition
;
;
; 74ls47 fonts 0-9
;
#if 0
#define	LS47FONT	(ls47font - eeprom_top)
#endif
#define	LS247FONT	(ls247font - eeprom_top)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;	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			; porta value,sel is low level
	movwf	PORTA
	movwf	porta_back
	movlw	0xff
	movwf	PORTB
;
; data directions
;
	bsf	STATUS,RP0
	movlw	b'11110011'
			; b0: 1 GPIO Input data 1
			; b1: 1 GPIO Input data 0
			; b2: 0 GPIO Output sel 0
			; b3: 0 GPIO Input  sel 1
			; b4: 1 GPIO Input  sw
			; b5: 1 MCLR
			; b6: 1 GPIO Input data 3
			; b7: 1 GPIO Input data 2
	movwf	TRISA
	movlw	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
	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:
;
	call	loadfont	;　フォントを準備する
	call	makemask	; セグメントのマスクテーブルを作成する
;
; 作業領域初期化
;
	movlw	0xff
	movwf	curval
	clrf	ctrl
	clrf	seg_count
	movlw	0xff
	movwf	vram
	movwf	vram+1
;
; 割り込み準備
;
	clrf	TMR0
	clrf	timer0_count
	bsf	INTCON,GIE		; global irq
main_loop:
;
	call	loadsw			; 入力データを取り込む
;
	subwf	curval,w
	btfsc	STATUS,Z
	goto	main_loop	; 変化がなければなにもしない
	movf	loadval,w
	movwf	curval
;
; データを表示形式に変換
	bsf	ctrl,CTRL_INHIBIT
	clrf	seg_count
;
	movlw	d'10'
	subwf	loadval,w
	btfss	STATUS,C
	goto	main_below10
	addlw	font
	movwf	FSR
	movf	INDF,w
	movwf	vram+1
	movf	font+1,w	; 数字1を強制的に表示
	movwf	vram
	bcf	ctrl,CTRL_INHIBIT
	goto	main_loop

main_below10:
	movf	curval,w
	addlw	font
	movwf	FSR
	movf	INDF,w
	movwf	vram+1
	movlw	0xff	; 0 サプレス
	movwf	vram
	bcf	ctrl,CTRL_INHIBIT
	goto	main_loop
;
;--------/ loadsw /-------
;
;	out:	loadval & wreg :value
;
loadsw
	movf	PORTA,w
	movwf	loadval
	clrw
	btfsc	PORTA,PORTA_SW		; 正論理、負論理を判断
	goto	loadsw_posi	
; 負論理
	btfss	loadval,PORTA_DATA_0
	iorlw	1
	btfss	loadval,PORTA_DATA_1
	iorlw	2
	btfss	loadval,PORTA_DATA_2
	iorlw	4
	btfss	loadval,PORTA_DATA_3
	iorlw	8
	addlw	1		; チャンネルは1から
	movwf	loadval
	return
; 正論理
loadsw_posi:
	btfsc	loadval,PORTA_DATA_0
	iorlw	1
	btfsc	loadval,PORTA_DATA_1
	iorlw	2
	btfsc	loadval,PORTA_DATA_2
	iorlw	4
	btfsc	loadval,PORTA_DATA_3
	iorlw	8
	addlw	1		; チャンネルは1から
	movwf	loadval
	return
;
;;;;;;;;;;;;;;;;;;;;;;;;;
;	ドライバー処理	;
;;;;;;;;;;;;;;;;;;;;;;;;;
;
;-------------------
; timer0 irq routine
;-------------------
tmr0irq:
	bcf	INTCON,T0IF
	incf	timer0_count,f
;
	btfsc	ctrl,CTRL_INHIBIT
	return
	goto	vramDisp
;
;-------------------
; vramFunction
;-------------------
;
;
;----------/ vramDisp /----------
;
;	1回に1セグメントの処理
;
;	表示手順は次の通り
;	bSf 	ctrl,CTRL_INHIBIT
;	clrf	seg_count
;	データをvramにセット
;	bcf	ctrl,CTRL_INHIBIT
;
vramDisp
;
	; 表示を消す
	movlw	0xff
	movwf	PORTB
	; 桁指定
	movlw	~PORTA_SEL_MASK
	andwf	porta_back,w
	btfss	seg_count,3
	iorlw	(1<<PORTA_SEL_0)
	btfsc	seg_count,3
	iorlw	(1<<PORTA_SEL_1)
	movwf	porta_back
	movwf	PORTA
	; 内容出力
	movf	seg_count,w
	andlw	7
	addlw	maskpat
	movwf	FSR
;
	movf	vram,w
	btfsc	seg_count,3
	movf	vram+1,w
	iorwf	INDF,w
	movwf	PORTB
;	カウント
	incf	seg_count,f
	movlw	d'15'
	andwf	seg_count,f
;
	return

;
;--------/ loadfont /----------
;
;	フォントをramにセットする
;
loadfont
;
	movlw	font
	movwf	FSR
	movlw	LS247FONT
	movwf	temp1
	movlw	d'10'
	movwf	temp2
loadfont_loop:
	movf	temp1,w
	call	ReadRom
	movwf	INDF
	incf	temp1,f
	incf	FSR,f
	decfsz	temp2,f
	goto	loadfont_loop
;
	return
;
;--------/ makemask /--------
;
;	1segパターン用
;
makemask
	movlw	maskpat
	movwf	FSR
	movlw	~1
	movwf	temp1
	movlw	8
	movwf	temp2
makemask_loop:
	movf	temp1,w
	movwf	INDF
	bsf	STATUS,C
	rlf	temp1,f
	incf	FSR,f
	decfsz	temp2,f
	goto	makemask_loop
;
	return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; EEPROM ACCESS
;
;
;;
;-------/ ReadRom /--------
;
;	割り込み内と地面の双方から呼ばれるが
;	大丈夫
;
;	in:	w romadr
;	out	w value
ReadRom
	bsf	STATUS,RP0
	movwf	EEADR
	bsf	EECON1,RD
	movf	EEDATA,w
	bcf	STATUS,RP0
	return

;=========================
;	EEPROM SECTION
;=========================
;
;	256 bytes
;	action data
;
;
	org		0x2100
eeprom_top:
;
; hexfont
;	ls247
;
ls247font:
	de	0xC0	; 0
	de	0xF9	; 1
	de	0xA4	; 2
	de	0xB0	; 3
	de	0x99	; 4
	de	0x92	; 5
	de	0x82	; 6
	de	0xF8	; 7
	de	0x80	; 8
	de	0x90	; 9
#if 0
;
; 74ls47 fonts 0-9
;
ls47font:
	de	0xC0	; 0
	de	0xF9	; 1
	de	0xA4	; 2
	de	0xB0	; 3
	de	0x99	; 4
	de	0x92	; 5
	de	0x83	; 6
	de	0xF8	; 7
	de	0x80	; 8
	de	0x98	; 9
#endif
;
	end
