;****************************************************************
;*     Started 18/6/2009	
;2 Digit UP / Down Counter with FastCount after 2secs
;No buttons pressed - goes to Up/Down Counter
;Buttons "Up" and "Down" recognised when project turned on.
;Button A goes to DICE
;Button B goes to Random Number 00 to 99
;Port B drives 7 segment display
;Up sw on RA2   Down on RA3
;Units drive on RA0   Tens drive on RA1					
;* * Alarm when "00" added   9-8-2011											*
;****************************************************************

	list P = 16F628		;microcontroller 
	include <P16F628.inc>	;registers for F628


	__Config 	_cp_off & _lvp_off & _pwrte_on & _wdt_off & _intRC_osc_noclkout & _mclre_off
	
;code protection - off
;low-voltage programming - off
;power-up timer -  on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out


;****************************************************************
; variables - names and files
;****************************************************************


		;Files for F628 start at 20h 
 
						 			
temp1		equ 20h	;for delay
temp2		equ 21h	;for delay
temp3		equ 22h	;for delay
SwUp		equ	23h	;
SwDwn		equ	24h	;
units		equ	25h	;
tens		equ	26h	;
Sw_Flag		equ	27h	;
FastCount	equ	28h	;
Count		equ	29h	; counting 00 to 99

;****************************************************************
;Equates
;****************************************************************
status		equ	0x03
cmcon		equ	0x1F
rp1			equ	0x06
rp0			equ	0x05
portA 		equ 0x05
portB 		equ 0x06


;****************************************************************
;Beginning of program
;****************************************************************
reset	org		00				;reset vector address	
		goto	SetUp			;goto SetUp
			

table	addwf   PCL,F           ;02h,1  add W to program counter 
        retlw   b'00111111'     ; "0"   -|F|E|D|C|B|A
        retlw   b'00000110'     ; "1"   -|-|-|-|C|B|-
        retlw   b'01011011'     ; "2"   G|-|E|D|-|B|A
        retlw   b'01001111'     ; "3"   G|-|-|D|C|B|A 
        retlw   b'01100110'     ; "4"   G|F|-|-|C|B|-
        retlw   b'01101101'     ; "5"   G|F|-|D|C|-|A
        retlw   b'01111101'     ; "6"   G|F|E|D|C|-|A
        retlw   b'00000111'     ; "7"   -|-|-|-|C|B|A
        retlw   b'01111111'     ; "8"   G|F|E|D|C|B|A
        retlw   b'01101111'     ; "9"   G|F|-|D|C|B|A		


;****************************************************************
;* port A and B initialisation	
;Button Up  and Button Down recognised when project turned on.			
;****************************************************************

SetUp	bsf		status,rp0	
		movlw	b'00001100'		;Make RA0,1 out RA2 in(Up),RA3 in(Down)
		movwf	05h				;trisA
		clrf	06h				;trisB   Make all RB output
		bcf		status,rp0		;select programming area - bank0 
		movlw	b'10000000'		;Turn off T0CKI, prescale for TMR0 = 1:
		movwf	option_reg		
		clrf 	portB			;Clear Port B of junk 
		clrf	units			;zero the units file		
		clrf	tens			;zero the tens file		
		clrf	Sw_Flag
		movlw	07h				;turn comparators off and enable
		movwf	cmcon			;    pins for I/O functions	
		btfss	portA,2	
		goto	AAA				;Button A detected (detects LOW)
		btfsc	portA,3	
		goto 	Main
		clrf	Count
		goto	Random			;Button B detected
								
					
AAA		incf	tens,1			;remove beep 
		call	D_250mS
		btfsc	portA,2	
		goto	Dice
		bsf		portA,1			;Make RA1 HIGH for left display 
		bcf     portA,0		
		movlw	b'01011110'		; "d"   G|-|E|D|C|B|-
		movwf	portB
		call 	D_250mS
		movlw	b'00000110'		; "I"   -|-|-|-|C|B|-
		movwf	portB
		call 	D_250mS
		movlw	b'00111001'		; "C"   -|F|E|D|-|-|A
		movwf	portB
		call 	D_250mS
		movlw	b'01111001'		; "E"   G|F|E|D|-|-|A
		movwf	portB
		call 	D_250mS
		clrf	portB
		bcf		portA,1
		goto	AAA+1


;****************************************************************
;* Delay 10mS 		10 x 1,000uS			*
;****************************************************************

D_2mS	movlw	02h
		movwf	temp2
D_e		nop
		decfsz 	temp1,1
		goto 	D_e
		decfsz 	temp2,1
		goto 	D_e	
		retlw 	00
					

D_10mS	movlw	0Ah
		movwf	temp2
D_a		nop
		decfsz 	temp1,1
		goto 	D_a
		decfsz 	temp2,1
		goto 	D_a	
		retlw 	00		
		
		
D_100mS	movlw	d'100'
		movwf	temp2
D_b		nop
		decfsz 	temp1,1
		goto 	D_b
		decfsz 	temp2,1
		goto 	D_b	
		retlw 	00	
		
D_250mS	movlw	d'250'
		movwf	temp2
D_c		nop
		decfsz 	temp1,1
		goto 	D_c
		decfsz 	temp2,1
		goto 	D_c	
		retlw 	00			
		
		
D_3Sec	movlw	d'15'
		movwf	temp3		
D_d		nop
		decfsz 	temp1,1
		goto 	D_d
		decfsz 	temp2,1
		goto 	D_d	
		decfsz 	temp3,1
		goto 	D_d	
		retlw 	00					
		
		
FastUp	btfss	Sw_Flag,2	;First time through loop?
		goto	FU_2		;yes
		btfsc	Sw_Flag,7	;Has 5Hz bit been set?
		goto	FU_3
FU_1	incfsz	FastCount,1	;Increment FastCount
		movlw	d'100'
		xorwf	FastCount,0
		btfss	status,2	;reached 100 loops?
		retlw	00
		clrf	FastCount
		bsf		Sw_Flag,7	;set bit for 5Hz incrementing					
		

FU_2	bsf		Sw_Flag,2	;Up button has been pressed				
		incf	units,1
		movlw	0Ah			;put 10 into w
		xorwf	units,0		;compare units file with 10
		btfss	status,2	;zero flag in status file. Will be set if units is 10
		retlw	00
		clrf	units
		incf	tens,1
		movlw	0Ah			;put 10 into w
		xorwf	tens,0		;compare units file with 10
		btfsc	status,2	;zero flag in status file. Will be set if tens is 10
		clrf	tens				
		retlw	00			;display passes 99 but not below 0
		
		
FU_3	incfsz	FastCount,1	;Increment FastCount
		movlw	d'5'
		xorwf	FastCount,0
		btfss	status,2	;reached 5 loops?
		retlw	00
		clrf	FastCount		
		goto	FU_2
		
			
		
Dwn		btfsc	Sw_Flag,3
		retlw	00
		bsf		Sw_Flag,3
		decf	units,1
		movlw	0FFh		;put FFh into w
		xorwf	units,0		;compare units file with FFh
		btfss	status,2	;zero flag in status file. Will be set if units is 10
		retlw	00
		movlw	09
		movwf	units		;put 9 into units file
		decf	tens,1
		movlw	0FFh		;put 0FFh into w
		xorwf	tens,0		;compare tens file with 0FFh
		btfsc	status,2	;zero flag in status file. Will be set if tens is 0FFh
		goto	$+2			;tens file is 0FFh
		retlw	00						
		clrf	tens
		clrf	units
		retlw	00			;display  not below 0	
		
			
;****************************************************************
;* Dice 	Produces a random number from 1 to 6 on display
;  The display flashes before settling on a number - called attract mode.
;Program detects timing of button-push to generate number		*
;****************************************************************

Dice	incf	units,f
		btfss	portA,2		;look for button-push			
		goto	Start		;button A pushed
		movf	units,w
		xorlw	06
		btfss	status,2		
		goto	Dice
		clrf	units
		goto	Dice
		
Start	movlw	08
		movwf	temp3
		call	Attract
		decfsz	temp3,f
		goto	$-2		
		goto	Show		;
		
		
Attract	bsf		portA,0	;Make RA0 HIGH for right-hand display 	
		movlw	b'00001000'	;	
		movwf	portB				
		call	D_100mS			
		movlw	b'01000000'	;	
		movwf	portB				
		call	D_100mS		
		movlw	b'00001000'	;	
		movwf	portB				
		call	D_100mS
		movlw	b'00000001'	;	
		movwf	portB				
		call	D_100mS				
		retlw	00
		
Show	movf	units,w		
		call	table
		movwf	portB
Show1	call	D_250mS
		btfss	portA,2		;look for button not pushed		
		goto	Show1
		goto	Dice
		
		
;****************************************************************
;* Random - produces random numbers from 00 to 99			*
;****************************************************************

Random 	movlw	08
		movwf	temp3
		call	Flash
		decfsz	temp3,f
		goto	$-2		
		goto	Rand_1		;
		
		
Flash	bsf		portA,1	;Make RA1 HIGH for left-hand display 	
		movlw	b'00001000'	;	
		movwf	portB				
		call	D_100mS	
		bcf		portA,1	
		nop	
		bsf		portA,0	;Make RA0 HIGH for right-hand display 	
		movwf	portA
		movlw	b'00001000'	;	
		movwf	portB				
		call	D_100mS	
		bcf		portA,0	
		retlw	00				
		
		
							;convert Count to 0..99
Rand_1	movf	Count,w
		clrf    tens    	; W = 0x00..0x63, 0..99 input
		decf    tens,F     	; preset temp to -1
sub10   incf    tens,F     	; unconditionally
        addlw   -0Ah      	; subtract 10. borrow?
        btfsc   status,0    ; no, test carry bit
		goto	sub10
		addlw	0Ah
        movwf	units
   	
        
Disp    movf	units,w		
		call	table
		movwf	portB
		bsf		portA,0		;Make RA0 HIGH for right-hand display 	
		call 	D_2mS
		bcf		portA,0
		movf	tens,w		
		call	table
		movwf	portB
		bsf		portA,1		;Make RA1 HIGH for left-hand display 	
		call 	D_2mS
		bcf		portA,1
		incf	Count,f
		movf	Count,w
		xorlw	d'100'
		btfsc	Status,2	;test zero flag
		clrf	Count		
		btfsc	portA,2		;look for button not pushed		
		goto	Disp
		goto	Random			
					
		
;****************************************************************
;* Main 							*
;****************************************************************

Main			
		movf	units,1
		btfss   03,2			;test zero flag    flag=1 when file=0		
		goto	$+6				
		movf	tens,1	
		btfss   03,2	
		goto	$+3		
		bsf		portA,6         ;make pin 15 HIGH
		goto    $+2
		bcf		portA,6			
        btfss	portA,2			;test switch-press for UP
		call	FastUp			;UP switch pressed
		btfss	portA,3			;test switch-press for Down
		call	Dwn				;Down switch pressed
		bsf		portA,0		;Make RA0 HIGH for units drive 	
		movf	units,0			;copy unit value into w
		call	table			;unit display value will return in w
		movwf	portB			;output units value
		call	D_10mS			;call delay
		bcf		portA,0
		clrf	portB				;clear display
		bsf		portA,1			;Make RA1 HIGH for tens drive 	
		movf	tens,0			;copy tens value into w		
		call	table			;tens display value will return in w
		movwf	portB			;output tens value
		call	D_10mS			;call delay
		bcf		portA,1
		clrf	portB			;clear display		
		btfsc	portA,3			;bit will be zero when sw is pressed
		bcf		Sw_Flag,3		;button not pressed. Clear down flag		
		btfss	portA,2			;bit will be zero when sw is pressed
		goto	Main
		bcf		Sw_Flag,2		;button not pressed. Clear Up flag
		bcf		Sw_Flag,7		;Clear Up repeat flag
		clrf	FastCount
		goto	Main		
		
		END
	
	
	