;Tutorial 2.2 - Nigel Goodwin 2002
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _MCLRE_OFF		;sets the configuration settings (oscillator type etc.)

	cblock 	0x20 			;start of general purpose registers
		count1 			;used in delay routine
		counta 			;used in delay routine 
		countb 			;used in delay routine
	endc

LEDPORT	Equ	PORTA			;set constant LEDPORT = 'PORTA'
SWPORT	Equ	PORTA			;set constant SWPORT = 'PORTA'
LEDTRIS	Equ	TRISA			;set constant for TRIS register
SW1	Equ	7			;set constants for the switches
SW2	Equ	6
SW3	Equ	5
SW4	Equ	4
LED1	Equ	3			;and for the LED's
LED2	Equ	2
LED3	Equ	1
LED4	Equ	0

SWDel	Set	Del50			;set the de-bounce delay (has to use 'Set' and not 'Equ')

;end of defines
	
	org	0x0000			;org sets the origin, 0x0000 for the 16F628,
					;this is where the program starts running	
	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84)

   	bsf 	STATUS,		RP0	;select bank 1
   	movlw 	b'11110000'		;set PortA 4 inputs, 4 outputs
   	movwf 	LEDTRIS
	bcf	STATUS,		RP0	;select bank 0
	clrf	LEDPORT			;set all outputs low


Loop	btfss	SWPORT,	SW1
	call	Switch1
	btfss	SWPORT,	SW2
	call	Switch2
	btfss	SWPORT,	SW3
	call	Switch3
	btfss	SWPORT,	SW4
	call	Switch4
	goto	Loop

Switch1	call	SWDel			;give switch time to stop bouncing
	btfsc	SWPORT,	SW1		;check it's still pressed
	retlw	0x00			;return is not
	btfss	SWPORT,	LED1		;see if LED1 is already lit
	goto	LED1ON
	goto	LED1OFF

LED1ON	bsf	LEDPORT,	LED1	;turn LED1 on
	call	SWDel
	btfsc	SWPORT,	SW1		;wait until button is released
	retlw	0x00
	goto	LED1ON	

LED1OFF	bcf	LEDPORT,	LED1	;turn LED1 on
	call	SWDel
	btfsc	SWPORT,	SW1		;wait until button is released
	retlw	0x00
	goto	LED1OFF		

Switch2	call	SWDel			;give switch time to stop bouncing
	btfsc	SWPORT,	SW2		;check it's still pressed
	retlw	0x00			;return is not
	btfss	SWPORT,	LED2		;see if LED2 is already lit
	goto	LED2ON
	goto	LED2OFF

LED2ON	bsf	LEDPORT,	LED2	;turn LED2 on
	call	SWDel
	btfsc	SWPORT,	SW2		;wait until button is released
	retlw	0x00
	goto	LED2ON	

LED2OFF	bcf	LEDPORT,	LED2	;turn LED2 on
	call	SWDel
	btfsc	SWPORT,	SW2		;wait until button is released
	retlw	0x00
	goto	LED2OFF

Switch3	call	SWDel			;give switch time to stop bouncing
	btfsc	SWPORT,	SW3		;check it's still pressed
	retlw	0x00			;return is not
	btfss	SWPORT,	LED3		;see if LED3 is already lit
	goto	LED3ON
	goto	LED3OFF

LED3ON	bsf	LEDPORT,	LED3	;turn LED3 on
	call	SWDel
	btfsc	SWPORT,	SW3		;wait until button is released
	retlw	0x00
	goto	LED3ON	

LED3OFF	bcf	LEDPORT,	LED3	;turn LED3 on
	call	SWDel
	btfsc	SWPORT,	SW3		;wait until button is released
	retlw	0x00
	goto	LED3OFF

Switch4	call	SWDel			;give switch time to stop bouncing
	btfsc	SWPORT,	SW4		;check it's still pressed
	retlw	0x00			;return is not
	btfss	SWPORT,	LED4		;see if LED4 is already lit
	goto	LED4ON
	goto	LED4OFF

LED4ON	bsf	LEDPORT,	LED4	;turn LED4 on
	call	SWDel
	btfsc	SWPORT,	SW4		;wait until button is released
	retlw	0x00
	goto	LED4ON	

LED4OFF	bcf	LEDPORT,	LED4	;turn LED4 on
	call	SWDel
	btfsc	SWPORT,	SW4		;wait until button is released
	retlw	0x00
	goto	LED4OFF

;modified Delay routine, direct calls for specified times
;or load W and call Delay for a custom time.

Del0	retlw	0x00			;delay 0mS - return immediately
Del1	movlw	d'1'			;delay 1mS
	goto	Delay
Del5	movlw	d'5'			;delay 5mS
	goto	Delay
Del10	movlw	d'10'			;delay 10mS
	goto	Delay
Del20	movlw	d'20'			;delay 20mS
	goto	Delay
Del50	movlw	d'50'			;delay 50mS
	goto	Delay
Del100	movlw	d'100'			;delay 100mS
	goto	Delay
Del250	movlw	d'250'			;delay 250 ms
Delay	movwf	count1
d1	movlw	0xC7			;delay 1mS
	movwf	counta
	movlw	0x01
	movwf	countb
Delay_0
	decfsz	counta, f
	goto	$+2
	decfsz	countb, f
	goto	Delay_0

	decfsz	count1	,f
	goto	d1
	retlw	0x00
	end