;CODE FOR PIC CONTROLLED DTMF DECODER WITH 512 BYTE EEPROM USING A
;HITACHI CONTROLLED 1X16 (LOGICAL 2X8) LCD DISPLAY
;======== DTMF DECODER ========
;--------------------------------------------
;
	list	p=16c84
	radix	hex

;----------------------------------------------
;	CPU REGISTER EQUATES (memory map)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tmr0	EQU	0x01
pc	EQU	0x02
status	EQU	0x03
porta	EQU	0x05
portb	EQU	0x06
intcon	EQU	0x0b
opt_reg	EQU	0x81
trisa	EQU	0x85
trisb	EQU	0x86
eecon1	EQU	0x88
eecon2	EQU	0x89

char	EQU	0x0C
AD_CTR	EQU	0x0D
scr_ctr	EQU	0x0E
save	EQU	0x0F
spctr1	EQU	0x10
spctr2	EQU	0x11
spctr3	EQU	0x12
flags	EQU	0x13	;BIT 0 CONTROLS WEATHER TO WRITE A SPACE
			;BIT 1 SET MEANS SPACE WAS LAST CHARACTER
			;WRITTEN TO LCD
			;BIT 2 SET MEANS WE'RE IGNORING 1+AREA CODE
			;BIT 3 is a "first time" flag for the 
			;ee_addr_hi function to facilitate
;access to 9-bit-wide  
			;eeprom memory space
EE_ADDR	EQU	0x14
RD_CTR	EQU	0x15
EE_CTR	EQU	0x16
txbuf	EQU	0x17
bits	EQU	0x18
eedat	EQU	0x19
;
loopCtr0	EQU	0x1A
loopCtr1	EQU	0x1B
loopCtr2	EQU	0x1C


;OUR OWN HOMEMADE OPTION REGISTER
OPTS		EQU	0x1D

;OPTS
;	  BITS
;	XXXXXXXX
;	      00	NO GAP
;	      01	SHORT GAP TIME		~ 4 SECONDS
;	      10	LONG GAP TIME		~ 7 SECONDS
;	      11	EXTRA LONG GAP TIME	~ 1 MINUTE
;	    00XX	IGNORE '1' WHEN DIALED FIRST
;	    01XX
;	    10XX
;	    11XX
;
OPTSTEST		EQU	0x1E
GAP		EQU	0x1F	;interdigit gap
IGNORE_CTR	EQU	0x20
EE_ADDR_HI	EQU	0x21

;----------------------------------------------
;        ALIASES
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rd		EQU	0
wr		EQU	1
wren		EQU	2
rp0		EQU	5
gie		EQU	7
C		EQU	0
Z		EQU	2
USER_ctrl	EQU	porta
USER		EQU	porta
LCD_ctrl		EQU	porta
LCD_data		EQU	portb
Playback		EQU	4
bPress		EQU	4
DV		EQU	0
RS		EQU	2
E		EQU	3
PWDN		EQU	1
CS		EQU	3	;SERIAL EEPROM CS TIED TO PORT B, PIN 3
CK		EQU	2	;SERIAL EEPROM CK TIED TO PORT B, PIN 2
DI		EQU	1	;SERIAL EEPROM DI TIED TO PORT B, PIN 1
DO		EQU	0	;SERIAL EEPROM DO TIED TO PORT B, PIN 0
EEPROM		EQU	portb	;EEPROM TIED TO LOW NIBBLE OF PORTB




	ERRORLEVEL -302
;----------------------------------------------

	org	0
;
;---------------------------------------------------------------------------
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
start

	clrwdt			;prep for assign prescaler
	bsf	status,rp0
	movlw	b'11010111'	;assign prescaler (divide by 256)
				;internal portb pull-ups disabled
	movwf	opt_reg
	movlw	b'00000000'	;load w with $00
	movwf	trisb
	movlw	b'00010001'	;Three output, two inputs 
	movwf	trisa
	bcf	status,rp0
	clrf	porta		;all lines low
	clrf	portb		;all lines low

	clrf	flags		;all flags low
	BSF	flags, 1		;set for ignore routine

;---------------------------------------------------------------------------
;				LCD INIT
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lcd_init
;	
	movlw	b'00110000'	;Function Set, 8-bit interface
	movwf	portb		;Put it on portb
	call	lcd_e
	call	lcd_e
	call	lcd_e

	movlw	b'00101000'	;Function Set, 4-bit interface, 4th bit = DUAL LINE DISP ok?
	movwf	portb		;put it on portb
	call	lcd_e
;
	movlw	b'00101000'	;4-bit interface, Single line display, font
	call	lcd_cmd
;
	movlw	b'00001111'	;DISP,BLINK ON/OFF,CURS (not respectivly:)
	call	lcd_cmd
;
	movlw	b'00000110'	;Entry mode set. What the hell does this do?
	call	lcd_cmd
;
	movlw	b'00000001'	
	call	lcd_cmd

;---------------------------------------------------------------------------
;				|    END LCD INIT  |
;				|		   |
;---------------------------------------------------------------------------
;						

	call	init_counters	;initialize all counters
	CALL	EWEN		;SERIAL EEPROM ERASE/WRITE ENABLE

;---------------------------------------------------------------------------
;				LOADOPTS
;	Load the previously saved options from last eeprom memory space
;---------------------------------------------------------------------------

	CALL	ST_BIT		;Set a start bit
	
	MOVLW	D'2'		;Prep two bits for op-code
	MOVWF	bits	
	MOVLW	B'10000000'	;SET OPCODE
	MOVWF	txbuf		;prep to send
	CALL	TX		;send op code
	
	CALL	SEND_OPT_ADDR	;send address of our homemade option register

	CALL	RX		;READ THE BYTE

	BCF	EEPROM, CS	;LOW CHIP SELECT

	MOVF	char, W		;RX read the byte into char
	MOVWF	OPTS		;Get the byte into our OPTIONS register for use throughout the
				;program execution			


	MOVWF	OPTSTEST
	clrf	GAP		;DEFAULT VALUE FOR GAP

	MOVLW	b'00110011'
	ANDWF	OPTSTEST, F	;strip IGNORE bits for GAP tests

CHK_NO_GAP
	bcf	status, Z	;Clear Zero flag for test
	movlw	b'00000011'
	andwf	OPTSTEST, W
	btfsc	status, Z	;Z flag raised?
	goto	moveon

CHK_SHRT_GAP
	bcf	status, Z	;clear zero flag for test
	movlw	b'00110001'
	subwf	OPTSTEST, W
	btfss	status, Z	;Zero flag raised?
	goto	CHK_LONG_GAP		
	BSF	GAP, 3		;set GAP to Equal THREE iterations if OPTS=1 (approx 4 sec.)
	goto	moveon	
		
CHK_LONG_GAP
	bcf	status, Z	;clear zero flag for test
	movlw	b'00110010'	;LSB's at 10 = long gap
	subwf	OPTSTEST, W
	btfss	status, Z	;Zero flag raised?
	goto	CHK_XLONG_GAP		
	BSF	GAP, 4		;set GAP to Equal FOUR iterations if OPTS=2 (approx 14 sec.)
	goto	moveon

CHK_XLONG_GAP
	bcf	status, Z	;clear zero flag for test
	movlw	b'00110011'	;LSB's at 11 = long gap
	subwf	OPTSTEST, W
	btfss	status, Z	;Zero flag raised?
	goto	moveon		
	BSF	GAP, 7		;set GAP to Equal SEVEN iterations if OPTS=2 (approx 1 min.)	

;***************************** FALL THROUGH TO MOVEON *********************
moveon
;---------------------------------------------------------------------------
;			MONITOR DTMF DATA BUS
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	call	b_inputs		;change b3-7 to inputs
	bcf	flags, 0
	btfsc	USER_ctrl,Playback	;SEE IF USER WANTS TO CLEAR LOG OR SETUP OPTIONS
	call	OPTIONS
	call	init_counters		;re-initialize after setting options

dtmf	
	btfss	LCD_ctrl,DV	;DV high?
	goto	polluser	;no, see if user wants anything
	bsf	flags,0	;Set the space flag
	clrf	spctr1		;Clear all space counters
	clrf	spctr2		;so interdigit pause times will not be added
	clrf	spctr3		;together
loop	btfsc	LCD_ctrl,DV	;DV low?
	goto	loop		;wait for DV to go low to prevent errors
	movf	portb,w		;ready to decode & write tone
	andlw	b'11110000'	;mask off low nibble noise
	call	get_tone
	call	lcd_write
	call	WR_EEPROM	;Write char to eeprom
	goto	dtmf

;---------------------------------------------------------------------------
;				POLL USER
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polluser
	;***** BEGIN INTERDIGIT AND IGNORE GAP COUNTER LOOP
	
	incf	spctr1,f		;increment space counter each time
	btfsc	spctr1,7		;we at 128 yet?
	incf	spctr2,f
	btfsc	spctr1,7		;if we're at 128 then . . .
	clrf	spctr1			;clear spctr1 and restart

	btfsc	spctr2,7		;space counter 2 at 128 yet?
	incf	spctr3,f		;yes, increment space counter 3
	btfsc	spctr2,7		;no, check again for clear
	clrf	spctr2			;clear spctr2 if 128

	bcf	status, Z		;clear Zero flag for test
	incf	GAP
	decfsz	GAP
	goto	nonzerogap
	movlw	d'4'			;default gap time for timing
					;ignore routines when no gap
	goto	zerogap			;SKIP AHEAD AND SET IT IF GAP=0

nonzerogap				;USE USER SETTINGS FOR IGNORE IF GAP>0
	movf	GAP, W			;Load GAP time into W

zerogap					
	subwf	spctr3, W		;Subtract GAP time from spctr3
	btfsc	status, Z		;Result Zero?
	call	wr_space		;Yes, call write space
					;No, keep counting

	;***** END INTERDIGIT & IGNORE GAP COUNTER LOOP

	btfss	USER_ctrl,Playback	;Port A, Bit 4 Set?
	goto	dtmf			;no
debounc	btfsc	USER_ctrl,Playback	;yes, wait till no for debounce
	goto	debounc
	goto	RD_EEPROM		;yes, playback eeprom
	goto	dtmf
;---------------------------------------------------------------------------
;				WRITE SPACE
;	Writes a space to the LCD after a pre-specified inter-digit pause
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wr_space

	BTFSS	flags, 0
	goto	skipit		;CLEAR? Then only update counters & timer-dependent flags
	incf	GAP, F		;increment GAP for test
	decfsz	GAP		;GAP tested Zero?
	goto	dontskip	;NO, so continue on to write space
	goto	skipit		;YES, so skip over writing the space
dontskip
	movlw	a' '		;load a space
	call	lcd_write	;write a space
	call	WR_EEPROM	;write it to the eeprom too
skipit	
	bcf	flags,0	;SO SPACES WON'T KEEP WRITING
	clrf	spctr1		;clear all counters
	clrf	spctr2
	clrf	spctr3
	BSF	flags,1	;Set this bit to indicate last thing
				;written to LCD was a space
				;used to decide whether to ignore '1' when
				;dialed first
	BCF	flags, 2	;WHEN SET, WE'RE IGNORING 1+AREA CODE
				;CLEAR IT TO SHOW A SPACE HAS BEEN WRITTEN
				;IN CASE LESS THAN THREE DIGITS FOLLOW THE
				;INITIAL '1'. PREVENTS ERRORS.
	clrf	IGNORE_CTR	;reset ignore counter once gap time expires
	return
;---------------------------------------------------------------------------
;				GET_TONE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
get_tone
	movwf	char		;Do this here to free up W register
	

	BTFSS	OPTS, 3		;1+AREA IGNORE OPTION SET?
	goto	continue	;NO
				;YES
	BTFSS	flags, 2	;Have we already ignored a '1' this round?
	goto	continue	;No, continue
	bcf	flags, 0	;YES, clear the space flag so space won't write
				;after ignored digits
	incf	IGNORE_CTR	;increment the ignore counter
	btfss	IGNORE_CTR, 2	;Have we ignored 4 digits yet?
	goto	NOnext		;NO, keep flag set and keep counting
	bcf	flags, 2	;YES, clear the multi-ignore flag
	clrf	IGNORE_CTR	;YES, clear the ignore counter
	
NOnext
	goto	dtmf

continue
	btfss	flags,1	;Is this the first digit in the series?
	goto	dontignore	;NO
	bcf	flags, 1	;show that last thing written to LCD was
				;NOT a space
	btfss	OPTS, 2		;ignore 1 set in OPTS?
	goto	dontignore	;NO

	bcf	status, Z	;clear Z flag for test	
	movlw	b'10000000'	;DTMF '1' IN HIGH NIBBLE RIGHT NOW
	subwf	char, W
	btfss	status, Z	;Zero flag set?
	goto	dontignore	;NO, move on
	BSF	flags, 2	;SHOW THAT WE'VE IGNORED A 1
	incf	IGNORE_CTR	;increment the ignore counter
	bcf	flags,0	;YES, Clear the space flag so space won't write
	goto	dtmf		;after '1' ignored; then return to dtmf

dontignore			;JUMP HERE IF NOTHING TO IGNORE
	swapf	char,W		;PUT NIBBLE IN CORRECT POSITION
	addwf	pc,f		;Add offset to program counter
	retlw	0x44	;D	;RETURN CORRESPONDING DTMF CHARACTER
	retlw	0x38	;8
	retlw	0x34	;4
	retlw	0x23	;#
	retlw	0x32	;2
	retlw	0x30	;0
	retlw	0x36	;6
	retlw	0x42	;B
	retlw	0x31	;1
	retlw	0x39	;9
	retlw	0x35	;5
	retlw	0x41	;A
	retlw	0x33	;3
	retlw	0x2a	;*
	retlw	0x37	;7
	retlw	0x43	;C

;---------------------------------------------------------------------------
;	4			LCD ENABLE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lcd_e
	bsf	LCD_ctrl,E	;LCD Enable on
	call delay		;for higher clock speed
	bcf	LCD_ctrl,E	;LCD Enable off
	return			;go back
;
;---------------------------------------------------------------------------
;	36			LCD COMMAND
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lcd_cmd
	call	b_outputs	;MAKE HIGH NIBBLE BPORT OUTPUTS
	bcf	LCD_ctrl,RS	;LOW RS for command
	movwf	char		;Place W in char for manipulation. Code saved by kyle!
	movwf	portb		;Place W (character) in PORTB
	call	lcd_e		;strobe the enable line
	swapf	char,0		;Place low nibble at high nibble (data port)
	movwf	portb		;put it on port b
	call	lcd_e		;strobe LCD enable line
	bsf	LCD_ctrl,RS	;HIGH RS back to "write mode"
	call	b_inputs	;MAKE HIGH NIBBLE BPORT INPUTS
	return

;---------------------------------------------------------------------------
;	149 max			LCD WRITE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lcd_write
	btfsc	AD_CTR,3	;address counter 8?
	call	jump		;yes, jump to next screen address

	call	b_outputs	;MAKE HIGH NIBBLE BPORT OUTPUTS
	movwf	char		;Place W in char for manipulation
	movwf	portb		;Place W (character) in PORTB
	call	lcd_e		;strobe the LCD enable line
	swapf	char,W		;Place low nibble at high nibble (data port)
	movwf	portb		;Put it on port b
	call	lcd_e		;Strobe LCD enable line
	swapf	char,W		;put it back in prep for WR_EEPROM
	incf	AD_CTR,f	;KEEP TRACK OF LCD ADDRESS
	call	b_inputs	;MAKE HIGH NIBBLE BPORT INPUTS
	return

;---------------------------------------------------------------------------
;	91			JUMP
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
jump
	movwf	save		;save w pin state
	movlw	b'11000000'	
	call	lcd_cmd
	clrf	AD_CTR
	incf	scr_ctr,f
	btfsc	scr_ctr,1
	call	clr_scr
	movf	save,w		;return w pin state
	return				

;---------------------------------------------------------------------------
;	42				
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
clr_scr
	movlw	b'00000001'
	call	lcd_cmd
	clrf	AD_CTR		;zero address counter
	clrf	scr_ctr		;zero screen counter
	return	

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				DELAY SUBROUTINE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
delay
;IFDEF PROD
	clrf	tmr0		;clear TMR0, start counting
again	btfss	tmr0,5		;bit 5 set ?
	goto 	again		;no, clear, again
;ENDIF
	return			;yes, end delay


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
init_counters
	movlw	b'00000001'	;Clear LCD Screen
	call	lcd_cmd
	clrf	AD_CTR		;zero address counter
	clrf	scr_ctr		;zero screen counter
	clrf	EE_ADDR
	movlw	B'01111111'	;set ee_addr_hi to 127, when incremented
	movwf	EE_ADDR_HI	;bit 7 will rollover to 1 for easy feed
				;into txbuf & tx routine to send a 1
	clrf	EE_CTR
	clrf	RD_CTR
	clrf	IGNORE_CTR
	return
	
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;	6			
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b_inputs
	bsf	status,rp0
	movlw	b'11110001'	;load w with $ff
	movwf	trisb
	bcf	status,rp0
	return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;	8				
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b_outputs
	bsf	status,rp0
	movwf	char		;save w pin state
	movlw	b'00000001'	;load w with $00
	movwf	trisb
	movf	char,W		;return w pin state
	bcf	status,rp0
	return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				EEPROM FULL
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eefull
	call	clr_scr

	movlw	a'M'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a'm'
	call	lcd_write
	movlw	a'o'
	call	lcd_write
	movlw	a'r'
	call	lcd_write
	movlw	a'y'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'F'
	call	lcd_write
	movlw	a'u'
	call	lcd_write
	movlw	a'l'
	call	lcd_write
	movlw	a'l'
	call	lcd_write
	bsf	USER_ctrl,PWDN	;put 8870 to sleep
	sleep		;put PIC to sleep
			;wakeup via reset
			;No need for return statements

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				GET KEY				
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
get_key
	btfss	USER_ctrl,Playback	;Port A, Bit 2 Set?
	goto	get_key
keywait	btfsc	USER_ctrl,Playback	;Port A, Bit 2 Clear?
	goto	keywait
	return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			ERASE/WRITE ENABLE SUBROUTINE								
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EWEN
	CALL	ST_BIT
	
	MOVLW	D'2'		;SET # BITS TO 2
	MOVWF	bits

	MOVLW	B'00000000'	;GET THE OPCODE (00)
	MOVWF	txbuf		;INTO THE TX BUFFER

	CALL	TX

	MOVLW	D'9'		;SET # BITS TO 9
	MOVWF	bits
	MOVLW	B'11000000'	;GET OPCODE AND ADDRESS INTO OUTPUT BUFFER
	MOVWF	txbuf
	CALL	TX
	BCF	EEPROM,CS	;LOW CHIP SELECT
	NOP
				;ERASE/WRITE NOW ENABLED
	RETURN
	
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			SERIAL EEPROM WRITE SUBROUTINE							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_EEPROM

	CALL	ST_BIT

	MOVLW	D'2'		;SET # BITS TO 2
	MOVWF	bits

	MOVLW	B'01000000'	;GET THE OPCODE (00)
	MOVWF	txbuf		;INTO THE TX BUFFER

	CALL	TX

	CALL	SET_ADDRESS

	;SEND DATA BITS
	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	bits
	MOVF	char, W		;PUT CHAR IN WORKING REGISTER
	MOVWF	txbuf
	CALL	TX
	BCF	EEPROM, CS	;LOW CHIP SELECT

	NOP			;250nS delay
	BSF	EEPROM, CS
hold
	btfss	EEPROM, DO
	goto	hold		;wait for eeprom to do internal write

	BCF	EEPROM, CS
	
	NOP
	NOP

	BCF	status, Z	;CLEAR Z FLAG FOR TEST
	INCFSZ	EE_ADDR		;INCREMENT ADDRESS COUNTER
	goto	upupup
	INCF	EE_ADDR_HI	;If ee_addr is at 0, ee_addr_hi will go to 1
upupup
	btfss	EE_ADDR_HI, 7	;See if we're in the 2nd go-'round
	goto	jmp_ret		;no
				;yes, start counting to end
	BCF	status, Z	;CLEAR ZERO FLAG FOR TEST
	MOVLW	D'255'		;LOAD W WITH 255
	SUBWF	EE_ADDR, W	;SUBTRACT W FROM ADDRESS
	BTFSC	status, Z	;IS IT 0?
	CALL	eefull		;YES
				;NO, CONTINUE	
jmp_ret	
	RETURN			;RETURN FROM WR_EEPROM SUBROUTINE

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			SERIAL EEPROM READ SUBROUTINE							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RD_EEPROM
	CALL	init_counters	;INITIALIZE ALL COUNTERS

	MOVLW	d'16'
	MOVWF	RD_CTR		;LOAD READ COUNTER WITH 16

RDLOOP	
	CALL	ST_BIT	
	
	MOVLW	D'2'
	MOVWF	bits
	MOVLW	B'10000000'	;SET OPCODE
	MOVWF	txbuf
	CALL	TX

CALL	SET_ADDRESS
	INCFSZ	EE_ADDR, F	;INCREMENT EE_ADDR
goto	upup

;GETS HERE AFTER 16TH SCREEN
btfss	flags, 3		;been here before?
goto	jmpfirsttime	;no
	CALL	RX		;yes, READ THE last BYTE
	BCF	EEPROM, CS	;LOW CHIP SELECT
	MOVF	char, W		;put char in W to send to lcd
	CALL	lcd_write	;WRITE THE character
call	get_key		
goto	start
	
jmpfirsttime		
	INCF	EE_ADDR_HI	;If ee_addr is at 0, ee_addr_hi will go to 1
	bsf	flags, 3

upup
	CALL	RX		;READ THE BYTE
	BCF	EEPROM, CS	;LOW CHIP SELECT
	MOVF	char, W		;put char in W to send to lcd
	CALL	lcd_write	;WRITE THE character

	DECFSZ	RD_CTR		;DECREMENT RD_CTR, SKIP NEXT LINE IF ZERO
	GOTO	RDLOOP

	MOVLW	d'16'
	MOVWF	RD_CTR		;LOAD READ COUNTER WITH 16
	call	get_key		;PAUSE AFTER 1 SCRN SO USER CAN VIEW OUTPUT
	
;	btfss	flags, 3		;flags, bit 3, is a "first time" flag so
				;EE_ADDR will cycle another 256
;	btfss	EE_ADDR_HI, 7	;WE IN 2nd GO 'ROUND YET?
;	goto	jmp_rd_lp	;no
				;yes
;	BCF	status, Z	;CLEAR ZERO FLAG FOR TEST
;	movlw	D'256'		;Really a 0 as MSB would be ignored. 
;Using 256 for clarity.
;	subwf	EE_ADDR,W	;SUBTRACT W FROM EE_ADDR		
;	btfss	status, Z	;TEST FOR ZERO FLAG
;jmp_rd_lp	

	GOTO	RDLOOP		;NOT ZERO. HAVEN'T DONE 32 SCREENS YET.
				;ZERO. WE'VE OUTPUT 32 SCREENS. WRAP IT UP.

;	call	init_counters	;reset again to receive, record & display
				;DTMF tones
;	goto	start
	;RETURN			;RETURN FROM RD_EEPROM SUBROUTINE

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			START BIT SUBROUTINE	
;	CLEARS, DI, SC, & CK THEN SETS CS HIGH, THEN SETS DI HIGH FOR 
;	START BIT						
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ST_BIT
	BCF	EEPROM, DI	;DATA IN LOW
	BCF	EEPROM, CS	;CHIP SELECT LOW
	BCF	EEPROM, CK	;CLOCK LOW TO START
	NOP

	BSF	EEPROM, CS	;CHIP SELECT HIGH

	BSF	EEPROM, DI	;SET START BIT
	NOP

	BSF	EEPROM, CK	;SET CLOCK LINE HIGH TO GENERATE START BIT
	NOP	
	NOP

	BCF	EEPROM, CK	;CLOCK LOW
	RETURN


SET_ADDRESS
	MOVLW	D'1'		;SET # BITS TO 8
	MOVWF	bits
	MOVF	EE_ADDR_HI, W	;SET ADDRESS
	MOVWF	txbuf		;INTO XMIT BUFFER
	CALL	TX
	NOP
	NOP

	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	bits
	MOVF	EE_ADDR, W	;SET ADDRESS
	MOVWF	txbuf		;INTO XMIT BUFFER
	CALL	TX
	NOP
	NOP

	RETURN


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			TRANSMIT SERIAL DATA TO THE EEPROM						
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TX
	movf	bits, w
	movwf	EE_CTR
TXLP
	bcf	eedat, 7	;assume bit 7 is low
	btfsc	txbuf, 7	;is bit 7 clear?
	bsf	eedat, 7	;no, set to 1
	call	BITOUT		;transmit to serial eeprom
	rlf	txbuf		;rotate txbuf left
	decfsz	EE_CTR		;all bits done?
	goto	TXLP		;no, do another
	return			;yes, jump out


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				BITOUT
;			SEND A BIT TO THE EEPROM									
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BITOUT
	btfss	eedat, 7	;check state of data bit
	goto	bitlow		;low, goto bitlow
	bsf	EEPROM, DI	;high, set DI high
	goto	clkout		;clock it

bitlow
	bcf	EEPROM, DI	;output a logic low

clkout	
	bsf	EEPROM, CK	;set CK high
	nop
	bcf	EEPROM, CK	;return CK low

	return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;			RECEIVE DATA FROM THE SERIAL EEPROM						
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RX
	CLRF	char
	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	EE_CTR
	BCF	status, 0	;MAKE SURE CARRY FLAG IS LOW
RXLP
	CALL	BITIN		;READ 1 BIT
	BCF	char, 7		;ASSUME BIT WAS LOW
	BTFSC	eedat, 7		;CHECK THE BIT
	BSF	char, 7		;SET HIGH IF NECESSARY
	RLF	char
	DECFSZ	EE_CTR		;8 BITS DONE?
	GOTO	RXLP		;NO, DO ANOTHER
	RLF	char		;Rotate char through carry flag
	RETURN

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				    BITIN
;			GET A BIT FROM THE SERIAL EEPROM										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BITIN
	BSF	eedat, 7	;ASSUME BIT HIGH
	BSF	EEPROM, CK	;CLOCK HIGH
	NOP
	BTFSS	EEPROM, DO	;READ THE BIT AT THE PORT
	BCF	eedat, 7		;BIT WAS LOW
	BCF	EEPROM, CK	;CLOCK LOW
	RETURN


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;				OPTIONS
; 	This is where user can clear log, set interdigit gap time, set 
;	option to Ignore digits such as 1, 1xxx, 1010, etc.			
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OPTIONS
	btfsc	USER, bPress	;wait for button up
	goto	OPTIONS		
	movlw	a'C'
	call	lcd_write
	movlw	a'l'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a'a'
	call	lcd_write
	movlw	a'r'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'L'
	call	lcd_write
	movlw	a'o'
	call	lcd_write
	movlw	a'g'
	call	lcd_write
	movlw	a'?'
	call	lcd_write
	movlw	a' '
	call	lcd_write


;***** Counter loop **********************************
; Seconds?
YES
	movlw	a'Y'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a's'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a' '
	call	lcd_write
	CALL	INITLOOP

YESLP
	btfsc	USER, bPress		;User pressed a button?
	goto	WRAL			;yes, clear the log
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	NOGAP			;7-seconds up, goto next option 
	goto	YESLP			;Not 7s yet, go to YES

WRAL
	btfss	USER, bPress		;Wait for button up
	goto	WRAL
	CALL	ST_BIT
		
	MOVLW	D'2'		;SET # BITS TO 2
	MOVWF	bits

	MOVLW	B'00000000'	;GET THE OPCODE (00)
	MOVWF	txbuf		;INTO THE TX BUFFER

	CALL	TX

	MOVLW	D'9'		;SET # BITS TO 9
	MOVWF	bits
	MOVLW	B'01000000'	;GET OPCODE AND ADDRESS INTO OUTPUT BUFFER
	MOVWF	txbuf
	CALL	TX

	;SEND DATA BITS
	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	bits
	MOVLW	b'11110100'	;Omega Symbol
;	MOVLW	b'00000000'	;Zero out 255. Once only, then comment out this line.
	MOVWF	txbuf
	CALL	TX
	BCF	EEPROM,CS	;LOW CHIP SELECT
	
	NOP			;250nS delay
	BSF	EEPROM, CS
ewenhold
	btfss	EEPROM, DO
	goto	ewenhold	;wait for eeprom to do internal write

	BCF	EEPROM, CS
	CALL	WR_OPT		;Put Options back at ee address 255

;************************ FALL THROUGH TO INTERDIGIT GAP SELCTION ROUTINES **********************

NOGAP
	btfsc	USER, bPress	;Wait for button up
	goto	NOGAP
	movlw	a'S'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a't'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'G'
	call	lcd_write
	movlw	a'a'
	call	lcd_write
	movlw	a'p'
	call	lcd_write
	movlw	a':'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'N'
	call	lcd_write
	movlw	a'o'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'G'
	call	lcd_write
	movlw	a'a'
	call	lcd_write
	movlw	a'p'
	call	lcd_write
	movlw	a'.'
	call	lcd_write

	CALL	INITLOOP

;NO GAP SELECTION LOOP
NOGAP_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_NOGAP_OPT		;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	SHORTGAP		;YES, DELAY TIME EXPIRED GO TO NEXT USER OPTION 
	goto	NOGAP_SEL_LP		;NO, KEEP COUNTING DELAY CYCLES

;------------------------------------------------------------------------------------------------
;				WRITE NO GAP OPTION							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_NOGAP_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_NOGAP_OPT
	movlw	b'00001100'	;Prepare strip mask
	
	andwf	OPTS, F		;strip off 2 lsb's in prep for rewrite of interdigit gap time opt
	movlw	b'00110000'	;NO GAP
	xorwf	OPTS, F		;XOR toggles only one bit
	CALL	WR_OPT
	goto	IGNORE1

;------------------------------------------------------------------------------------------------
;					SHORT GAP							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SHORTGAP
	btfsc	USER, bPress	;Wait for button up
	goto	SHORTGAP

	;BACK UP LCD, OVERWRITE ONLY CHARACTERS THAT NEED OVERWRITING TO 
	;SAVE PROGRAM MEMORY
	MOVLW	d'7'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	decf	scr_ctr, f	
	MOVLW	b'10000111'	;move cursor to end of first lcd screen
	CALL	lcd_cmd

	movlw	a' '
	call	lcd_write
	movlw	a'T'
	call	lcd_write
	movlw	a'i'
	call	lcd_write
	movlw	a'm'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'S'
	call	lcd_write
	movlw	a'h'
	call	lcd_write
	movlw	a't'
	call	lcd_write

	CALL	INITLOOP

;SHORT GAP SELECTION LOOP
SHGAP_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_SHGAP_OPT		;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	LONG_GAP		;YES, DELAY TIME EXPIRED GO TO NEXT USER OPTION 
	goto	SHGAP_SEL_LP		;NO, KEEP COUNTING DELAY CYCLES

;------------------------------------------------------------------------------------------------
;				WRITE SHORT GAP OPTION							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_SHGAP_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_SHGAP_OPT
	movlw	b'00001100'	;Prepare strip mask
	
	andwf	OPTS, F		;strip off 2 lsb's in prep for rewrite of interdigit gap time opt
	movlw	b'00110001'	;8 seconds (high bits protect other options from overwrite
	xorwf	OPTS, F		;XOR toggles only one bit
	CALL	WR_OPT
	goto	IGNORE1

;************************* FALL THROUGH TO LONG GAP *********************************************
LONG_GAP
	btfsc	USER, bPress	;Wait for button up
	goto	LONG_GAP

	MOVLW	d'5'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	MOVLW	b'11000101'	;CURSOR BACK THREE SPACES
	CALL	lcd_cmd

	movlw	a'L'
	call	lcd_write
	movlw	a'n'
	call	lcd_write
	movlw	a'g'
	call	lcd_write
	CALL	INITLOOP

;LONG GAP SELECTION LOOP
LGAP_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_LGAP_OPT		;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	XLONG_GAP		;YES, DELAY TIME EXPIRED. GO TO NEXT OPTION. 
	goto	LGAP_SEL_LP		;NO, KEEP COUNTING DELAY CYCLES.

;------------------------------------------------------------------------------------------------
;					WRITE LONG GAP OPTION										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_LGAP_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_LGAP_OPT
	movlw	b'00001100'	;Prepare strip mask
	andwf	OPTS, F		;strip off 2 lsb's in prep for rewrite of interdigit gap time opt
	movlw	b'00110010'	;16 seconds (high bits protect other options from overwrite
	xorwf	OPTS, F		;XOR toggles only one bit
	CALL	WR_OPT
	goto	IGNORE1

;************************ FALL THROUGH TO EXTRA LONG GAP OPTION *********************************
XLONG_GAP
	btfsc	USER, bPress	;Wait for button up
	goto	XLONG_GAP

	MOVLW	d'5'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	MOVLW	b'11000101'	;CURSOR BACK THREE SPACES
	CALL	lcd_cmd

	movlw	a'X'
	call	lcd_write
	movlw	a'l'
	call	lcd_write
	movlw	a'g'
	call	lcd_write
	CALL	INITLOOP

XLGAP_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_XLGAP_OPT		;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	IGNORE1			;YES, DELAY TIME EXPIRED. GO TO NEXT OPTION. 
	goto	XLGAP_SEL_LP		;NO, KEEP COUNTING DELAY CYCLES.

;------------------------------------------------------------------------------------------------
;					WRITE LONG GAP OPTION										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_XLGAP_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_XLGAP_OPT
	movlw	b'00001100'	;Prepare strip mask
	andwf	OPTS, F		;strip off 2 lsb's in prep for rewrite of interdigit gap time opt
	movlw	b'00110011'	;SET TO 3 FOR EXTRA LONG GAP TIME	
	xorwf	OPTS, F
	CALL	WR_OPT

;************ FALL THROUGH TO IGNORE 1 ROUTINE ***********

;------------------------------------------------------------------------------------------------
;					IGNORE 1 WHEN DIALED FIRST										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IGNORE1
	btfsc	USER, bPress	;Wait for button up
	goto	IGNORE1

	MOVLW	d'4'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	decf	scr_ctr, f	
	MOVLW	b'10000100'	;CURSOR BACK TO DD RAM 4 (fifth block)
	CALL	lcd_cmd

	movlw	a'I'
	call	lcd_write
	movlw	a'g'
	call	lcd_write
	movlw	a'n'
	call	lcd_write
	movlw	a'o'
	call	lcd_write
	movlw	a'r'
	call	lcd_write
	movlw	a'e'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'1'
	call	lcd_write
	movlw	a'?'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a' '
	call	lcd_write
	

	CALL	INITLOOP

IGNORE1_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_IGNORE1_OPT		;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	IGNORE1AREA		;YES, DELAY TIME EXPIRED. GO TO NEXT OPTION. 
	goto	IGNORE1_SEL_LP		;NO, KEEP COUNTING DELAY CYCLES.

;------------------------------------------------------------------------------------------------
;					WRITE IGNORE1 OPTION										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_IGNORE1_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_IGNORE1_OPT
	movlw	b'00000011'	;Prepare strip mask
	andwf	OPTS, F		;strip off high nible MSBs in prep for rewrite of interdigit gap time opt
	movlw	b'00110100'	;SET TO IGNORE 1	
	xorwf	OPTS, F
	CALL	WR_OPT
	goto	PROGEND


;------------------------------------------------------------------------------------------------
;				IGNORE 1+AREA CODE WHEN DIALED FIRST										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IGNORE1AREA
	btfsc	USER, bPress	;Wait for button up
	goto	IGNORE1AREA

	MOVLW	d'4'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	MOVLW	b'11000100'	;CURSOR BACK TO DD RAM 4 (fifth block)
	CALL	lcd_cmd

	movlw	a'A'
	call	lcd_write
	movlw	a'R'
	call	lcd_write
	movlw	a'E'
	call	lcd_write
	movlw	a'A'
	call	lcd_write
	

	CALL	INITLOOP

IGNORE1AREA_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_IGNORE1AREA_OPT	;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	IGNORENONE		;YES, DELAY TIME EXPIRED. GO TO NEXT OPTION. 
	goto	IGNORE1AREA_SEL_LP	;NO, KEEP COUNTING DELAY CYCLES.

;------------------------------------------------------------------------------------------------
;				WRITE IGNORE 1+AREA CODE OPTION										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_IGNORE1AREA_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_IGNORE1AREA_OPT
	movlw	b'00000011'	;Prepare strip mask
	andwf	OPTS, F		;strip off high nibble MSBs in prep for rewrite of interdigit gap time opt
	movlw	b'00111100'	;SET TO IGNORE 1+AREA CODE	
	xorwf	OPTS, F
	CALL	WR_OPT
	goto	PROGEND


;------------------------------------------------------------------------------------------------
;				IGNORE NONE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IGNORENONE
	btfsc	USER, bPress	;Wait for button up
	goto	IGNORENONE

	MOVLW	d'2'		;UPDATE COUNTERS TO REFLECT ADDRESS CHANGE
	MOVWF	AD_CTR
	MOVLW	b'11000010'	;CURSOR BACK TO DD RAM 2 (fifth block)
	CALL	lcd_cmd

	movlw	a' '
	call	lcd_write
	movlw	a'N'
	call	lcd_write
	movlw	a'O'
	call	lcd_write
	movlw	a'N'
	call	lcd_write
	movlw	a'E'
	call	lcd_write
	movlw	a'?'
	call	lcd_write
	
	CALL	INITLOOP

IGNORENONE_SEL_LP
	btfsc	USER, bPress		;User pressed a button?
	goto	WR_IGNORENONE_OPT	;yes, 
	incf	loopCtr0,f		;increment counter each time
	btfsc	loopCtr0,7		;we at 128 yet?
	incf	loopCtr1,f
	btfsc	loopCtr0,7		;if we're at 128 then . . .
	clrf	loopCtr0		;clear spctr1 and restart

	btfsc	loopCtr1,7		;LC1 at 128 yet?
	incf	loopCtr2,f		;yes, increment LC2
	btfsc	loopCtr1,7		;no, check again for clear
	clrf	loopCtr1		;clear LC1 if 128

	btfsc	loopCtr2,4		;LC2 at 16 yet?
	goto	PROGEND			;YES, DELAY TIME EXPIRED. GO TO NEXT OPTION. 
	goto	IGNORENONE_SEL_LP	;NO, KEEP COUNTING DELAY CYCLES.

;------------------------------------------------------------------------------------------------
;				WRITE IGNORE NONE OPTION										
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_IGNORENONE_OPT
	btfsc	USER, bPress	;Wait for button up
	goto	WR_IGNORENONE_OPT
	movlw	b'00000011'	;Prepare strip mask
	andwf	OPTS, F		;strip off high nibble MSBs in prep for rewrite of interdigit gap time opt
	movlw	b'00110000'	;SET TO IGNORE NONE	
	xorwf	OPTS, F
	CALL	WR_OPT
	goto	PROGEND

;------------------------------------------------------------------------------------------------
;						WR_OPT
;				WRITE TO OUR HOMEMADE OPTION REGISTER							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WR_OPT
	CALL	ST_BIT

	MOVLW	D'2'		;SET # BITS TO 2
	MOVWF	bits

	MOVLW	B'01000000'	;GET THE OPCODE (00)
	MOVWF	txbuf		;INTO THE TX BUFFER

	CALL	TX

	CALL	SEND_OPT_ADDR

	;SEND DATA BITS
	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	bits
	MOVF	OPTS, W		;Put current option values into W register
	MOVWF	txbuf
	CALL	TX
	BCF	EEPROM, CS	;LOW CHIP SELECT

	NOP			;250nS delay
	BSF	EEPROM, CS
opthold
	btfss	EEPROM, DO
	goto	opthold		;wait for eeprom to do internal write

	BCF	EEPROM, CS
	
	NOP
	NOP
	RETURN


SEND_OPT_ADDR
	MOVLW	D'1'		;SET # BITS TO 1
	MOVWF	bits
	MOVLW	b'11111111'	;SET ADDRESS, 511 (of 0-511), homemade option register
	MOVWF	txbuf		;INTO XMIT BUFFER
	CALL	TX
	NOP
	NOP

	MOVLW	D'8'		;SET # BITS TO 8
	MOVWF	bits
	MOVLW	b'11111111'	;SET ADDRESS, 511 (of 0-511), homemade option register
	MOVWF	txbuf		;INTO XMIT BUFFER
	CALL	TX
	NOP
	NOP
	RETURN


;---------------------------------------------------------------------------
;				INIT LOOP							
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
INITLOOP
	clrf	loopCtr0
	clrf	loopCtr1
	clrf	loopCtr2
	RETURN

PROGEND
	movlw	a'P'
	call	lcd_write
	movlw	a'R'
	call	lcd_write
	movlw	a'E'
	call	lcd_write
	movlw	a'S'
	call	lcd_write
	movlw	a'S'
	call	lcd_write
	movlw	a' '
	call	lcd_write
	movlw	a'K'
	call	lcd_write
	movlw	a'E'
	call	lcd_write
	movlw	a'Y'
	call	lcd_write
ENDLP
	BTFSS	USER, bPress	;PAUSE ON THIS SCREEN
	GOTO	ENDLP
ENDLP2
	BTFSC	USER, bPress	;WAIT FOR BUTTON UP
	GOTO	ENDLP2
	GOTO	start

	END
