; bk0402B 0.2.1 (c) 2004 - 2005 Cyril BARBATO
; PIC16F84 / 3Mhz2768 CRISTAL
; * DISCLAIMER OF ALL WARRANTIES *
; main.asm

#include "p16f84.inc"
        
list     p=16f84,f=inhx8m

__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC   ;watch dog disabled, QTZ oscillator
__IDLOCS H'0000'

; **********
; EQU & DEF
; **********
	; ----------
	; µC ports & pins
	; ----------
#DEFINE CS		PORTA	; cs digit
#DEFINE KEYS		PORTB	; keys
#DEFINE DATA		PORTB	; bcd data
#DEFINE DP		PORTB, 3 ; point
;- ??? futur devel
;- ??? #DEFINE BEEP	PORTA, 4

	; ----------
	; application const
	; ----------
	DIGIT_REFRESH_STEP	equ	.1
	TICK_STEP		equ	.200	
	EVENT_SECOND		equ	1
	EVENT_MINUTE		equ	2
	EVENT_KEY_PRESSED	equ	3	
	
	; ----------
	; application var
	; ----------	
	cblock	H'0C'
		d1		; digit 1
		d2		; digit 2
		d3		; digit 3
		d4		; digit 4
		digit_index	; index pointer of cs digit
		digit_refresh_count	; decremented each interrupt
		key		; value
		event_flags	; event flags
		tick		; tick decounter
		second		; second decounter
		s_w		; w saver
		s_status		; status saver
	endc
	
; **********
; RESET
; **********
	org     	H'00'                      
       	goto    	Main

; **********
; INTERRUPT  ROUTINE
; **********
	org	H'04'
Int	movwf	s_w		; save w
	swapf	STATUS, 0	; swap status, w
	movwf	s_status		; save status(nibble swap, remember)
	
	; clear watchdog timer to ensure startup --
	;clrwdt

	; refresh count / refresh digit --
	decfsz	digit_refresh_count, 1
	goto	Int_next0
	movlw	DIGIT_REFRESH_STEP
	movwf	digit_refresh_count
	call	Digit_refresh

	; scan keyboard --
	bcf	event_flags, EVENT_KEY_PRESSED	 ; clear key pressed
	movlw	B'00000111'
	andwf	KEYS, 0
	btfss	STATUS, Z
	bsf	event_flags, EVENT_KEY_PRESSED	; notify each key pressed 

Int_next0
	; Second comput 200 x 256 x 16 x 4 = Clock Cristal  
	decfsz	tick, 1
	goto	Int_restoring

	movlw	TICK_STEP
	movwf	tick		; reinit tick counter

	; flag minute set 
	bsf	event_flags, EVENT_SECOND 	; notify each seconde

	decfsz	second, 1
	goto	Int_restoring

	movlw	.60
	movwf	second		; reinit second counter

	; flag minute set 
	bsf	event_flags, EVENT_MINUTE		; notify each minute

Int_restoring
	; restoring --
	swapf	s_status, 0	;fetch status, reswap nibbles
	movwf	STATUS		;restore status
	swapf	s_w, 1		;swap nibbles in preparation
	swapf	s_w, 0		;for the swap restoration of w
	bcf	INTCON,2		;clear interrupt flag before return
	
Int_end	retfie			;return from interrupt

; **********
; TABLES
; **********

TABLE_SELECT
	addwf   PCL, 1
	retlw	B'00000000'	;blank
	retlw	B'00000001'	;CS1
	retlw	B'00000010'	;CS2
	retlw	B'00000100'	;CS3
	retlw	B'00001000'	;CS4

TABLE_DATA
	addwf   PCL, 1
	retlw	B'00110000'	;0
	retlw	B'00100000'	;1
	retlw	B'00000000'	;2
	retlw	B'00010000'	;3
	retlw	B'10000000'	;4
	retlw	B'11010000'	;5
	retlw	B'01010000'	;6
	retlw	B'01000000'	;7
	retlw	B'11000000'	;8
	retlw	B'10010000'	;9
	retlw	B'11110000'	;blank

; **********
; SUB ROUTINES
; **********
	; ----------
	; Refresh current digit
	; ----------
Digit_refresh
	; select digit --
	movfw	digit_index
	call	TABLE_SELECT
	movwf	CS
	; load digit data --
	movlw	H'0C' - 1		; place point on begin of ram table digit
	movwf	FSR
	movfw	digit_index
	addwf	FSR, 1
	movfw	INDF
	call	TABLE_DATA
	movwf	DATA
	; next digit --
	decfsz	digit_index, 1	; change digit selection
	;goto	Int_restoring
	goto	Refresh_digit_end
	movlw	.4		; reinit digit_index_on cs4 
	movwf	digit_index	; restart on digit number 4 
Refresh_digit_end	
	return

	; ----------
	; format time for digit
	; ----------
Check_time
	; d4 --
	incf	d4, 1
	movlw	.10
	subwf	d4, 0
	btfss	STATUS, Z
	goto	Check_time_end
	clrf	d4
	; d3
	incf	d3, 1
	movlw	.6
	subwf	d3, 0
	btfss	STATUS, Z
	goto	Check_time_end
	clrf	d3
	; d2 --
Check_time_d2
	incf	d2, 1
	movlw	.10
	subwf	d2, 0
	btfss	STATUS, Z
	goto	Check_time_test24h
	clrf	d2
	;d1 
	incf	d1, 1
Check_time_test24h	
	movlw	.2
	subwf	d1, 0
	btfss	STATUS, Z
	goto	Check_time_end
	movlw	.4
	subwf	d2, 0
	btfss	STATUS, Z
	goto	Check_time_end
	clrf	d1
	clrf	d2
				; !!!! correction of derivation !!!!
	movlw	.10
	addwf	second, 1		; - 10s per day

Check_time_end
	bcf	event_flags, EVENT_MINUTE
	return	
	
	; ----------
	; check keys
	; ----------

Check_keys
	movlw	B'00000010'	; key1
	andwf	KEYS, 0
	btfsc	STATUS, Z
	call	Check_time_d2
	movlw	B'00000001'	; key 2
	andwf	KEYS, 0
	btfsc	STATUS, Z
	call	Check_time

Check_keys_loop
	btfsc	event_flags, EVENT_KEY_PRESSED
	goto	Check_keys_loop
	return

; **********
; MAIN
; **********
Main	; ----------
	; ports init
	; ----------
	clrf	PORTA		; clear all ports
	clrf	PORTB
	bsf     	STATUS, RP0	; access bank 1 
	movlw   	B'10000'		; set port A (3 outputs)
       	movwf   	TRISA		; port A 
  	movlw	B'00000011'       	; set port B (3 inputs, 5 outputs) ; !!!!!!!! RB2 CLV3 NOT USED !!!!
	movwf   	TRISB		; port B
	;bsf	OPTION_REG, NOT_RBPU 	; port b pull-ups disabled
	bcf     	STATUS, RP0	; access bank 0

	; ----------
	; timer init
	; ----------
	clrf	TMR0		; clear TMR0 reg
	bcf	INTCON, 2	; clear TMR0 int flag
	bsf	INTCON, 7	; enable global int
	bsf	INTCON, 5	; enable TMR0 int
	;clrwdt			; clear watch dog
	bsf     	STATUS, RP0	; access bank 1 
	movlw	B'11010011'	; set timer prescaler TMR0, and disable port b pull-ups
				; TMRO Rate 1:16
	movwf	OPTION_REG 	
	bcf     	STATUS, RP0	; access bank 0
	clrf	TMR0		; start timer

	; ----------
	; ram init
	; ----------
	clrf	d1		; clear hours
	clrf	d2		; clear minutes
	clrf	d3		; clear minutes
	clrf	d4		; clear minutes
	clrf	event_flags	; clear all event flags	
	movlw	.4		; digit_index on cs4 
	movwf	digit_index	; start on digit number 4 
	
	movlw	TICK_STEP
	movwf	tick		; reinit  tick counter
	movlw	.60
	movwf	second		; reinit second counter 

; **********
; MAIN LOOP
; **********	
Main_loop
	btfsc	event_flags, EVENT_MINUTE
	call	Check_time
	btfsc	event_flags, EVENT_KEY_PRESSED
	call	Check_keys
	goto	Main_loop

; **********
; END
; **********
	END


