; MULTIBTN.ASM: sensing upto 15 pushbuttons with one I/O (pin6: GP1/CIN-) 
; BENABADJI Noureddine - ORAN - Dec. 11...14th, 2013
;
	Errorlevel -302		; avoid warning #302: Register in operand not in bank0. 
						; Ensure that bank bits are correct.
	List P = 12F683  		    
#include "p12f683.inc" 			
	__CONFIG    _INTOSCIO&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF&_FCMEN_OFF&_IESO_OFF&_BOD_ON&_CPD_OFF&_CP_OFF

#define	 LED1	GPIO, 0	; output bit0 of the 4-bit binary LED display
#define	 LED2	GPIO, 2	; output bit1 of the 4-bit binary LED display
#define	 LED3	GPIO, 4	; output bit2 of the 4-bit binary LED display
#define	 LED4	GPIO, 5	; output bit3 of the 4-bit binary LED display

;----------------------------- define variables ------------------------------

	CBLOCK	0x20	; bank0 = [0x20...0x7F] = 94 bytes
;delay
	cnt1, cnt2, cnt3 ; counters
	ENDC

;------------------------------------------------------------------------------
BANK0	macro
	BCF	STATUS, RP0		 ; bank0
	endm
;------------------------------------------------------------------------------
BANK1	macro
	BSF	STATUS, RP0		 ; bank1
	endm
;------------------------------------------------------------------------------
SIregGEval8b	macro	file, val, jmpOk	; if (file >= val) goto jmpOk ;
	MOVLW	val
	SUBWF	file, w		; w = file - val
	BTFSC	STATUS, C
	GOTO	jmpOk		; yes
	endm

;/////////////////////////////////////////////////////////////////////////////
;	MAIN PROGRAM
;/////////////////////////////////////////////////////////////////////////////
	ORG		0x00			; reset vector
	GOTO	Setup
	ORG		0X04			; interrupt vector
	GOTO	IntCmp
;/////////////////////////////////////////////////////////////////////////////

;-----------------------------------------------------------------------------
LEDsOFF
	CALL	Delay256ms
	CLRF	GPIO	; all LEDs off
	RETLW	0
;-----------------------------------------------------------------------------
Delay256ms
	CLRF	cnt2
	CLRF	cnt1
	NOP				; 1us
	DECFSZ	cnt1, f	; 1us 
	GOTO	$-2		; 2us => 4*256 = 1024 us, approx. 1 ms internal delay loop
	DECFSZ	cnt2, f	; approx. 256 ms external delay loop
	GOTO	$-4
	RETLW	0

;/////////////////////////////////////////////////////////////////////////////
Setup
	BANK1
	CLRF	TRISIO		 ; config. all I/O as outputs
	BCF	OPTION_REG, T0CS ; use pin5 as GP2, not TOCKI
	CLRF	ANSEL		 ; use all AN as digital I/O

	BANK0
	CLRF	GPIO		; all LEDs off

	MOVLW	b'00000111'
	MOVWF	CMCON0		 ;comparator off

splash ; (initial test for LEDs)
	BSF		LED1
	CALL	LEDsOFF
	BSF		LED2
	CALL	LEDsOFF
	BSF		LED3
	CALL	LEDsOFF
	BSF		LED4
	CALL	LEDsOFF
;;;;;;;;;;
initializeComparator
	BANK1
	MOVLW	b'00001010'	 ;config. GP1 as input (will be CIN-)
	MOVWF	TRISIO
	;BANK0

	MOVLW	b'10100001'
	;BANK1
	MOVWF	VRCON		 ;Vref on, low range, VR<3:0>=0001 => ratio = 1/24
	BANK0

	MOVLW	b'00000100'
	MOVWF	CMCON0		 ;comparator on: CIN- = GP1; CIN+ = Vref; Cout internal
;;;;;;;;;
	
;enable interrupt
	BANK1
	BSF	INTCON, PEIE	 ; enable interrupt on Comparator trip
	BSF	PIE1, CMIE		 ; enable interrupt on Comparator trip
	BANK0
	BSF	INTCON, GIE		 ; set general interrupt enable

	goto $				 ; infinite loop (waiting for an interrupt)

;-----------------------------------------------------------------------------
; Comparator trip interrupt routine
;-----------------------------------------------------------------------------
IntCmp
;don't need to save any context, only interrupting a goto $
	BANK0
	MOVLW	.1
	MOVWF	cnt3
nextBtn
	INCF	cnt3, F
	SIregGEval8b cnt3, .16, whichBtn ; if (cnt3 >= 16) goto whichBtn ;

	MOVLW	b'10100000'
	ADDWF	cnt3, W
	BANK1
	MOVWF	VRCON		 ;Vref on, low range, VR<3:0>=cnt3<3:0>
	BANK0
	BTFSS	CMCON0, COUT	 ; Cout == 1 ?
	GOTO	nextBtn

whichBtn
	DECF	cnt3, F
	BTFSC	cnt3, 0
	BSF		LED1
	BTFSC	cnt3, 1
	BSF		LED2
	BTFSC	cnt3, 2
	BSF		LED3
	BTFSC	cnt3, 3
	BSF		LED4
	CALL	LEDsOFF
	
endIntCmp
	MOVLW	b'10100001'
	BANK1
	MOVWF	VRCON		 ;Vref on, low range, VR<3:0>=0001 => ratio = 1/24
	BANK0

	BCF	PIR1, CMIF		 ; clear comparator interrupt flag
	RETFIE
;-----------------------------------------------------------------------------
	END
