;*******************************************************************************
;PROGRAM			:	HotBoxController
;MICROCONTROLLER	:	PIC18F4431	
;*******************************************************************************
;
;	Author: 	Greg "Turbo" Linder
;
;	Version: 	0.6, 03/06/2005
;*******************************************************************************
; --- Changelog
;	03/06/05
;	The dual-resistor solution has been implemented- There is now an individually
;	settable setpoint for each resistor, H1 and H2. The cabling in the hotbox was
;	also updated on this day. There is also a continually running stirring fan,
;	separate from the heater fan, which is hooked directly the the AC mains switch
;	on the AC input connector.
;
;	03/05/05
;	Version 0.6 has been changed in the following ways:
;	The major change is to allow two separate heater elements to be switched
;	independently. This was done because the heaters chosen (Large wattage
;	resistors) have a lot of thermal mass, which means the box cannot be
;	regulated to better than 3 degrees C. The code changes allow each resistor
;	to have its own setpoint, which should alleviate this problem.
;
;
;	To facilitate these changes, the following changes were made
;	- The SETPOINT_DISPLAY routine now is responsible for showing "H1 off @:"
;	- The TOOHOT_DISPLAY routine is now responsible for showing "H2 off @:"
;	- Many variables have been removed or renamed-- These should be fairly obvious
;	- The system flags names have been relabled to make sense- AuxOn went away, is now H2On
;	Version 0.5 was the initial release using one heater element

	include		<p18f4431.inc>
;*******************************************************************************

;SwitchFLAGS bits
#define	Switch_Update	0		; Knob moved
#define Lock_Enable		1		; Key lock is on
#define	UpMenu			2		; Go to previous menu
#define	Unused_bit3		3
#define	ButtonPush		4		; Button was pushed
#define ButtonDown		5		; Last button movement was down
#define	Unused_Bit6		6		
#define	Unused_Bit7		7

;SystemFLAGS bits
#define	FanOn			0		; 1 Means Fan on
#define	H1On			1		; 1 Means Heater element #1 on
#define	H2On			2		; 1 Means Heater element #2 on
#define	Timer0Interrupt	3		; 1 Means Timer0 overflow
#define	OverTemp		4		; 1 Means we are in OverTemp condition (current temp >= TOOHOT
#define	TakeT1			5		; 1 Means last A/D sample was of T1

#define	Timer0Reload_H	0x09
#define Timer0Reload_L	0x89
;*******************************************************************************
;RAM locations in Access bank, uninitialized
;*******************************************************************************
	UDATA_ACS 

TEMP			res	1		; Temp value
DELAYCOUNTER	res 1		; General delay counter
DELAYCOUNTER1	res 1		; General delay counter
DELAYCOUNTER2	res 1		; General delay counter

SwitchFLAGS		res	1		; Flags for tracking the knob and switch
SystemFLAGS		res	1		; System flags- Fan, Heat, Aux, TimerOverflow
DisplayCounter	res	1		; Maintains the current position in the displays:
							; 0.Relay Control 1.Current Status 2.Setpoint(Now H1) 3.Hysteresis 4.TooHot(Now H2)
CursorPosition	res	1		; Used to indicate the cursor position in the display (0-31)
DisplayValue	res	1		; Used to specify number (00-99) for ASCII display
SerialWordL		res 1		; Used to send single words to the display (i.e. for numbers)
SerialWordH		res 1
H1SetPoint		res	1		; Setpoint for heater 1
H2SetPoint		res	1		; Setpoint for heater 2
HystValue		res 1		; Hysteresis of control loop
T1ADValue		res	1		; Raw T1 Value from A/D converter
T2ADValue		res	1		; Raw T2 Value from A/D converter
ScrollyCounter	res	1		; Counter to keep track of where in the scrolly message Current Status is.
ScrollyCounter2	res	1		; Other ScrollyCounter ot be used for "on" and "off" type messages.
ScaleMe			res	1		; Temporary value used for the A/D scaling
T1CurrentVal	res	1		; Scaled value (0-99) read from AD converter
T2CurrentVal	res	1		; Scaled value (0-99) read from AD converter

;*******************************************************************************
;*******************************************************************************
;						RESET AND INTERRUPT VECTORS
;*******************************************************************************
;*******************************************************************************
STARTUP	code 0x00
	goto	Start				;Reset Vector address 

	CODE	0x08
	goto	ISR_HIGH			;High priority ISR at 0x0008
	
;*******************************************************************************
;*******************************************************************************
;							INITIALIZATION
;*******************************************************************************
;*******************************************************************************
PROG1	code
Start
	call	DELAY_START
	call	DELAY_START				; Wait for the VFD to come up to power.
	call	INITIALIZE_REGISTERS
	call	Initialize_Serial_Port
	call	INITIALIZE_SWITCH
	call	INITIALIZE_TIMER0		; Sets up timer to drive interrupts for measurement
	call	INITIALIZE_INTERRUPTS	; Enables interrupt for timer0
	call	INITIALIZE_AD			; Initialize A/D converter

;*******************************************************************************	
;*******************************************************************************
; 								MAIN LOOP
;*******************************************************************************
;*******************************************************************************
start_main
	call	WELCOME_DISPLAY			; Display welcome message
	call	CHECK_SWITCH_STATUS		; Fix spurious startup thing with knob
	clrf	SwitchFLAGS
	call	DELAY_START				; Delay for a bit to read the startup message
	call	DELAY_START
	call	COPY_DATA_FROM_EEPROM   ; Responsible for getting values from EEPROM on powerup.

	call	POWERFAIL_DISPLAY		; Display power fail message and wait for click out
	call	STATUSMSG_DISPLAY
	call	STATUS_SCREEN
main_loop
	btfss	SwitchFLAGS, Switch_Update	; Only run through list of menus if knob val has changed
	bra		main_loop_end
	call	HANDLE_MENUS
	call	SETPOINT_SCREEN
	call	HYSTERESIS_SCREEN
	call	TOOHOT_SCREEN
	call	STATUS_SCREEN
	call	RELAY_SCREEN
	call	CHECK_SWITCH_STATUS

main_loop_end
	call	CHECK_SWITCH_STATUS
	bra		main_loop

;*******************************************************************************
;*******************************************************************************
; 							INTERRUPT SERVICE ROUTINES
;*******************************************************************************
;*******************************************************************************
	
;*******************************************************************************
;High priority interrupt service routine
;Timer0 overflow is checked
; It's a big interrupt handler- I know.. I should have written this _first_,
; then fooled around with other stuff.. This also does all the control, each
; time the clock is reset..
;*******************************************************************************
ISR_HIGH
	bsf		SystemFLAGS, Timer0Interrupt 	; Signal that overflow occured
	movlw	Timer0Reload_H					; Reload Timer0 for new values
	movwf	TMR0H
	movlw	Timer0Reload_L
	movwf	TMR0L

;Update relay outputs
	btfsc	SystemFLAGS, H1On
	bsf		PORTD, 5		; H1 is on
	btfss	SystemFLAGS, H1On
	bcf		PORTD, 5		; H1 is off
	btfsc	SystemFLAGS, FanOn
	bsf		PORTD, 4		; Fan is on
	btfss	SystemFLAGS, FanOn
	bcf		PORTD, 4		; Fan is off
	btfsc	SystemFLAGS, H2On
	bsf		PORTB, 0		; A2 is on
	btfss	SystemFLAGS, H2On
	bcf		PORTB, 0		; A2 is off

; Get A/D values
	btfsc	ADCON0, GO		; Is A/D sample done?
	bra		ISR_CONTINUE	; No, conversion still going
	; If conversion done, get values:
	btfss	SystemFLAGS, TakeT1 ; Was T1 the last sample taken? (AN0)?
	bra		ISR_CHECK_T1
	movff	ADRESH, T2ADValue		; Yes, we now have T2's value
	bcf		SystemFLAGS, TakeT1 ; T2 was just taken.
	movlw	b'00000011'
	movwf	ADCON0				; Start sample for T1
	bra		ISR_CONTINUE

ISR_CHECK_T1
	movff	ADRESH, T1ADValue		; Yes, now we're on T1
	bsf		SystemFLAGS, TakeT1	; Signal that T1 was just taken
	movlw	b'00000111'
	movwf	ADCON0				; Start sample for T2


; This is the thermostat.
; Currently it uses T1 for the reference.
; Commands heat up until the box temperature is > SetPoint + HystValue
;	Changes here made 3/5/05- Two thermostats are now actually running, one for each
;	of two elements- H1SetPoint controls one, H2SetPoint control the other, both
;	from the same temp sensor in the box (T1)
ISR_CONTINUE
; First, test for Auto/Manual operation
	btfss	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		ISR_END						; No- Don't use thermostat
; Yes, allow thermostat to operate
; Deal with H1 Operation
	movf	H1SetPoint, W
	subwf	T1CurrentVal, W			; W now has T1CurrentVal-H1SetPoint
	bn		H1_TURN_ON				; T1CurrentVal-H1SetPoint value is -, need to heat up
	cpfslt	HystValue				; Is T1CurrentVal-H1SetPoint > HystValue?
	bra		ISR_CHECKH2			; No, keep going until we are > than HystValue
	bra		H1_TURN_OFF				; Yes, turn off heater

H1_TURN_ON
	bsf		SystemFLAGS, H1On		; Turn on H1
	bsf		SystemFLAGS, FanOn		; and fan
	bra		ISR_CHECKH2

H1_TURN_OFF
	bcf		SystemFLAGS, H1On		; Turn off H1
;	bcf		SystemFLAGS, FanOn

; Deal with H2 Operation
ISR_CHECKH2
	movf	H2SetPoint, W
	subwf	T1CurrentVal, W			; W now has T1CurrentVal-H2SetPoint
	bn		H2_TURN_ON				; T1CurrentVal-H2SetPoint value is -, need to heat up
	cpfslt	HystValue				; Is T1CurrentVal-H2SetPoint > HystValue?
	bra		ISR_CHECK_FAN			; No, keep going until we are > than HystValue
	bra		H2_TURN_OFF				; Yes, turn off heater

H2_TURN_ON
	bsf		SystemFLAGS, H2On		; Turn on H2
	bsf		SystemFLAGS, FanOn		; and fan
	bra		ISR_CHECK_FAN

H2_TURN_OFF
	bcf		SystemFLAGS, H2On		; Turn off H2
;	bcf		SystemFLAGS, FanOn		

; Deal with FAN- Fan bits are set by H1 and H2 code, but need to be turned off
; seperately- If both H2 and H1 are OFF, then turn off the fan
ISR_CHECK_FAN
	btfsc	SystemFLAGS, H2On		
	bra		ISR_END					; H2 is on
	btfsc	SystemFLAGS, H1On
	bra		ISR_END					; H1 is on
	bcf		SystemFLAGS, FanOn		; Turn off fan if both H1 and H2 off.

ISR_END
	bcf		INTCON,TMR0IF			;Clear TMR0IF, restarts counter
	RETFIE	FAST	

;*******************************************************************************
;*******************************************************************************
; 						Control Routines
;
;*******************************************************************************
;*******************************************************************************
;***************************************************
;RELAY_SCREEN
;	Handles toggling on / off of relay values
;
;***************************************************
RELAY_SCREEN
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	movlw	0x00	; RELAY_SCREEN is #0
	cpfseq	DisplayCounter
	return

RELAY_SCREEN_LOOP
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, ButtonPush		; Has someone pushed the button?
	bra		RELAY_EDIT_VALUE_START		; Yup
	btfss	SwitchFLAGS, Switch_Update	; Has the knob moved?
	bra		RELAY_SCREEN_LOOP			; No		
	return								; Return to main loop

RELAY_EDIT_VALUE_START
	btfsc	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		RELAY_SCREEN_LOCKED			; Yes
	bcf		SwitchFLAGS, ButtonPush		; Make sure that the button is not selected when we enter the routine
	call	RELAY4_DISPLAY
	movlw	0x03
	movwf	DisplayValue

RELAY_EDIT_VALUE
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, Switch_Update	; Has knob been rotated?
	bra		RELAY_EDIT_LOOP				; Yes
	btfsc	SwitchFLAGS, ButtonPush		; Has someone pushed the button in this loop?
	call	CHANGE_RELAY_FLAGS			; Yes
	btfsc	SwitchFLAGS, UpMenu			
	bra		RELAY_EDIT_DONE				; Finish routine if UpMenu set
	bra		RELAY_EDIT_VALUE

RELAY_EDIT_LOOP
	bcf		SwitchFLAGS, ButtonPush		; Clear ButtonPush for scrolling through menu
	bcf		SwitchFLAGS, Switch_Update	; Acknowledge that switch has been dealt with.
	btfss	QEICON,5					; If set, go right
	bra		RELAY_EDIT_DEC_VALUE		; Left turn requested
	incf	DisplayValue				; Move right selects next option
	movlw	0x04						; There are four menu options
	cpfslt	DisplayValue
	clrf	DisplayValue				; If DisplayCounter > 0x03, reset DisplayCounter to 0
	bra		RELAY_EDIT_END

RELAY_EDIT_DEC_VALUE					; Go left in menu
	decf	DisplayValue
	movlw	0xFF
	cpfseq	DisplayValue				; Reset DisplayCounter to 4
	bra		RELAY_EDIT_END
	movlw	0x03
	movwf	DisplayValue

RELAY_EDIT_END
	call	DISPLAY_RELAY_EDIT_MENU
	call	CHECK_SWITCH_STATUS
	bra		RELAY_EDIT_VALUE

RELAY_EDIT_DONE
	movlw	0x15
	call	SEND_BYTE					; Clear Display
	call	RELAY_DISPLAY				; Display initial value of relay screen
	call	RELAY_DONE_DISPLAY
	bcf		SwitchFLAGS, UpMenu
	return

RELAY_SCREEN_LOCKED
	call	RELAYLOCKED_DISPLAY
	bra		RELAY_SCREEN


;***************************************************
;CHANGE_RELAY_FLAGS
;	Changes flags and updates display when menu options in relay menu
;	are selected
;
;***************************************************
CHANGE_RELAY_FLAGS
	movlw	0x00
	cpfseq	DisplayValue
	bra		CHANGE_RELAY_FLAGS_1
	btg		SystemFLAGS, H1On
	bra		CHANGE_RELAY_FLAGS_END
CHANGE_RELAY_FLAGS_1
	movlw	0x01
	cpfseq	DisplayValue
	bra		CHANGE_RELAY_FLAGS_2
	btg		SystemFLAGS, FanOn
	bra		CHANGE_RELAY_FLAGS_END
CHANGE_RELAY_FLAGS_2
	movlw	0x02
	cpfseq	DisplayValue
	bra		CHANGE_RELAY_FLAGS_3
	btg		SystemFLAGS, H2On
	bra		CHANGE_RELAY_FLAGS_END
CHANGE_RELAY_FLAGS_3
	movlw	0x03
	cpfseq	DisplayValue
	bra		CHANGE_RELAY_FLAGS_END
	bsf		SwitchFLAGS, UpMenu

CHANGE_RELAY_FLAGS_END
	bcf		SwitchFLAGS, ButtonPush
	call	DISPLAY_RELAY_STATUS
	return


;***************************************************
;DISPLAY_RELAY_STATUS
;	Outputs on / off data for relay status
;
;***************************************************
DISPLAY_RELAY_STATUS
	movlw	0x16
	call	SEND_BYTE		; Puts cursor in upper left corner
	movlw	0x12
	call	SEND_BYTE		; Overwrite last char
	movlw	0x20
	call	SEND_BYTE		; Prints first space

	btfsc	SystemFLAGS, H1On
	call	ON_DISPLAY		; Heater is on
	btfss	SystemFLAGS, H1On
	call	OFF_DISPLAY		; Must be off if it's not on

	movlw	0x20
	call	SEND_BYTE
	call	SEND_BYTE		; Format display with spaces

	btfsc	SystemFLAGS, FanOn
	call	ON_DISPLAY		; Fan is on
	btfss	SystemFLAGS, FanOn
	call	OFF_DISPLAY		; Fan is off

	movlw 	0x20
	call	SEND_BYTE

	btfsc	SystemFLAGS, H2On
	call	ON_DISPLAY		; Aux is on
	btfss	SystemFLAGS, H2On
	call	OFF_DISPLAY		; Aux is off

	return
;***************************************************
;DISPLAY_RELAY_EDIT_MENU
;	Update Relay edit menu options on buttonpush
;
;***************************************************
DISPLAY_RELAY_EDIT_MENU
	movlw	0x00
	cpfseq	DisplayValue
	bra		DISPLAY_RELAY_NEXT_1
	call	RELAY1_DISPLAY
	bra		DISPLAY_RELAY_NEXT_END
DISPLAY_RELAY_NEXT_1
	movlw	0x01
	cpfseq	DisplayValue
	bra		DISPLAY_RELAY_NEXT_2
	call	RELAY2_DISPLAY
	bra		DISPLAY_RELAY_NEXT_END
DISPLAY_RELAY_NEXT_2
	movlw	0x02
	cpfseq	DisplayValue
	bra		DISPLAY_RELAY_NEXT_3
	call	RELAY3_DISPLAY
	bra		DISPLAY_RELAY_NEXT_END
DISPLAY_RELAY_NEXT_3
	movlw	0x03
	cpfseq	DisplayValue
	bra		DISPLAY_RELAY_NEXT_END
	call	RELAY4_DISPLAY
DISPLAY_RELAY_NEXT_END
	call	DISPLAY_RELAY_STATUS
	return

;***************************************************
;STATUS_SCREEN
;	Implements scrolly-character display for the status information	
;
;***************************************************
STATUS_SCREEN
	bcf		SystemFLAGS, Timer0Interrupt ; Start with fresh interval in display
	bcf		SwitchFLAGS, ButtonPush		; Make sure there are no roving buttonpushes
	movlw	0x01						; STATUS_SCREEN is #1
	cpfseq	DisplayCounter
	return

STATUS_SCREEN_LOOP
	call	STATUSMSG_DISPLAY ; Refresh display
	movlw	0x11			; Puts cursor on top line
	call	SEND_BYTE

; Display first temperature
	movf	T1ADValue, W				; We're trying to get a good T1ADValue out of the thing..
	movwf	ScaleMe
	call	SCALE_AD_VALUE
	movff	ScaleMe, DisplayValue
	movff	ScaleMe, T1CurrentVal 		; Store current T1 Value for control loop
	movlw	0x03			; Cursor position on top line after T1: is 0x03
	movwf	CursorPosition
	call	DISPLAYNUMBER
; Display second temperature
	movf	T2ADValue, W
	movwf	ScaleMe
	call	SCALE_AD_VALUE
	movff	ScaleMe, T2CurrentVal 		; Store current T2 Value for control loop
	movff	ScaleMe, DisplayValue
	movlw	0x0B
	movwf	CursorPosition
	call	DISPLAYNUMBER

; Show scrolly display
	movlw	0x10
	call	SEND_BYTE		; Puts cursor on bottom line
	movlw	0x13
	call	SEND_BYTE		; Turns on horizontal scroll mode in bottom of display
	clrf	ScrollyCounter

STATUS_SCREEN_SCROLLY
	call	CHECK_SWITCH_STATUS			; Make sure we don't need to leave.
	btfsc	SwitchFLAGS, Switch_Update	; Has the knob moved?
	bra		STATUS_SCREEN_END			; yes

	btfss	SystemFLAGS, Timer0Interrupt
	bra		STATUS_SCREEN_SCROLLY

; Displays FAN on/off message
	movlw	0x29					; Fan: at 0x29
	cpfseq	ScrollyCounter
	bra		STATUS_SCREEN_SCROLL_HEAT
	btfsc	SystemFLAGS, FanOn
	call	SCROLLON
	btfss	SystemFLAGS, FanOn
	call	SCROLLOFF
	movlw	0x03		; Increment ScrollyCounter location
	addwf	ScrollyCounter
	
; Displays HEAT on/off message
STATUS_SCREEN_SCROLL_HEAT
	movlw	0x30					; H1: at 0x30
	cpfseq	ScrollyCounter
	bra		STATUS_SCREEN_SCROLL_AUX
	btfsc	SystemFLAGS, H1On
	call	SCROLLON
	btfss	SystemFLAGS, H1On
	call	SCROLLOFF
	movlw	0x03		; Increment ScrollyCounter location
	addwf	ScrollyCounter

; Displays AUX on/off message
STATUS_SCREEN_SCROLL_AUX
	movlw	0x37					; H2: at 0x37
	cpfseq	ScrollyCounter
	bra		STATUS_SCREEN_SCROLL_NEXT
	btfsc	SystemFLAGS, H2On
	call	SCROLLON
	btfss	SystemFLAGS, H2On
	call	SCROLLOFF
	movlw	0x03		; Increment ScrollyCounter location
	addwf	ScrollyCounter

STATUS_SCREEN_SCROLL_NEXT
; See if we are locked or not..
	btfss	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		STATUS_SCREEN_MANUAL		; No

	movlw	UPPER SCROLLYMESSAGE	;Initialize Table pointer to the first  
	movwf	TBLPTRU					;location of the table
	movlw	HIGH SCROLLYMESSAGE
	movwf	TBLPTRH
	movlw	LOW SCROLLYMESSAGE	
	addwf	ScrollyCounter, W		; Add counter position to SCROLLYMESSAGE
	movwf	TBLPTRL
	bra		STATUS_SCREEN_AFTER_LOCK

STATUS_SCREEN_MANUAL
	movlw	UPPER SCROLLYMESSAGE2	;Initialize Table pointer to the first  
	movwf	TBLPTRU					;location of the table
	movlw	HIGH SCROLLYMESSAGE2
	movwf	TBLPTRH
	movlw	LOW SCROLLYMESSAGE2	
	addwf	ScrollyCounter, W		; Add counter position to SCROLLYMESSAGE
	movwf	TBLPTRL

STATUS_SCREEN_AFTER_LOCK
	TBLRD*							; Get byte from SCROLLYMESSAGE
	movf	TABLAT,W

	call	SEND_BYTE				; Display it


STATUS_SCREEN_CONTINUE
	incf	ScrollyCounter
	movlw	0x4B					; Length of SCROLLYCOUNTER
	cpfslt	ScrollyCounter
	bra		STATUS_SCREEN_LOOP		; Reset ScrollyCounter, update top display line.
	bcf		SystemFLAGS, Timer0Interrupt
	bra		STATUS_SCREEN_SCROLLY

STATUS_SCREEN_END
	return

;***************************************************
;SCALE_AD_VALUE
;	Uses lookup table indexed by AD value to get
;	scaled 0-99 range for use with DISPLAYNUMBER
;
;***************************************************
SCALE_AD_VALUE
	movlw	UPPER VOLTAGE_SCALE_TABLE			;Initialize Table pointer to the first  
	movwf	TBLPTRU								;location of the table
	movlw	HIGH VOLTAGE_SCALE_TABLE
	movwf	TBLPTRH
	movlw	LOW VOLTAGE_SCALE_TABLE
	movwf	TBLPTRL

	bcf		STATUS, C
	rrcf	ScaleMe			; Divide by 2 to start scaling, as there are only 128 vals in the scale table
	movf	ScaleMe, W
	addwf	TBLPTRL					; Index of # stored in WREG
	tblrd*
	movff	TABLAT, ScaleMe

	return
;***************************************************
;SCROLLON
;	Scrolls the word "ON " across the display
;
;***************************************************
SCROLLON
	clrf	ScrollyCounter2
SCROLLON_WAIT
	btfss	SystemFLAGS, Timer0Interrupt
	bra		SCROLLON_WAIT

	movlw	UPPER ON 	;Initialize Table pointer to the first  
	movwf	TBLPTRU					;location of the table
	movlw	HIGH ON
	movwf	TBLPTRH
	movlw	LOW ON
	addwf	ScrollyCounter2, W		; Add counter position
	movwf	TBLPTRL

	TBLRD*							; Get byte from ON
	movf	TABLAT,W

	call	SEND_BYTE				; Display it

	incf	ScrollyCounter2
	bcf		SystemFLAGS, Timer0Interrupt
	movlw	0x04					; Length of ON
	cpfseq	ScrollyCounter2			; At end of message, return
	bra		SCROLLON_WAIT
	return

;***************************************************
;SCROLLOFF
;	Scrolls the word "OFF" across the display
;
;***************************************************
SCROLLOFF
	clrf	ScrollyCounter2
SCROLLOFF_WAIT
	btfss	SystemFLAGS, Timer0Interrupt
	bra		SCROLLOFF_WAIT

	movlw	UPPER OFF	;Initialize Table pointer to the first  
	movwf	TBLPTRU					;location of the table
	movlw	HIGH OFF
	movwf	TBLPTRH
	movlw	LOW OFF
	addwf	ScrollyCounter2, W		; Add counter position
	movwf	TBLPTRL

	TBLRD*							; Get byte from OFF
	movf	TABLAT,W

	call	SEND_BYTE				; Display it

	incf	ScrollyCounter2
	bcf		SystemFLAGS, Timer0Interrupt
	movlw	0x04					; Length of OFF
	cpfseq	ScrollyCounter2			; At end of message, return
	bra		SCROLLOFF_WAIT
	return

;***************************************************
;FETCH_ASCII_VALUES
;	Returns ASCII value of request # in SerialWordL and SerialWordH
;
;***************************************************
FETCH_ASCII_VALUES
	movlw	UPPER ASCII_NUMBER_TABLE			;Initialize Table pointer to the first  
	movwf	TBLPTRU								;location of the table
	movlw	HIGH ASCII_NUMBER_TABLE
	movwf	TBLPTRH
	movlw	LOW ASCII_NUMBER_TABLE
	movwf	TBLPTRL

	movf	DisplayValue, W
	addwf	TBLPTRL					; Index of # stored in WREG
	rlncf	TBLPTRL					; We are reading WORDS- need to multiply by 2!
	tblrd*+
	movff	TABLAT, SerialWordL
	tblrd*
	movff	TABLAT, SerialWordH		; Get values from table- SerialWord(H/L) now
									; has the number in ASCII for the serial port
	return

;***************************************************
;TOOHOT_SCREEN
;	-- 3/5/05 - This routine no longer displays TOOHOT- This was changed on this date
;	such that now this code is responsible for the menu option which reads "H2 off @:"
;	This was changed in order to facilitate the use of two smaller heating elements,
;	each one able to be turned on or off independtly.
;	Runs the TOOHOT screen- Handles changing value through calls to
;	HANDLE_TEMPEDIT, writing new value to EEPROM, and dealing with appropriate
;	responces	
;
;***************************************************
TOOHOT_SCREEN
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	movlw	0x04	; TOOHOT screen is #4
	cpfseq	DisplayCounter
	return

	movlw	0x09
	movwf	CursorPosition	; Set CursorPosition to be at end of current line
	movf	H2SetPoint, W
	movwf	DisplayValue
	call	DISPLAYNUMBER

TOOHOT_SCREEN_LOOP
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, ButtonPush		; Has someone pushed the button?
	bra		TOOHOT_EDIT_VALUE			; Yup
	btfss	SwitchFLAGS, Switch_Update	; Has the knob moved?
	bra		TOOHOT_SCREEN_LOOP			; No		
	return								; Return to main loop

TOOHOT_EDIT_VALUE
	btfsc	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		TOOHOT_SCREEN_LOCKED		; Yes
	call	UNLOCKED_DISPLAY			; No
	call	HANDLE_TEMPEDIT
	movlw	0x08						; Data position 0x08 in EEPROM is for H2SetPoint
	movwf	TEMP						; Address in EEPROM specified in TEMP
	call	WRITE_EEPROM
	call	SAVED_DISPLAY
	movf	DisplayValue, W
	movwf	H2SetPoint
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	bra		TOOHOT_SCREEN_LOOP
TOOHOT_SCREEN_LOCKED
	call	LOCKED_DISPLAY
	bra		TOOHOT_SCREEN

;***************************************************
;WRITE_EEPROM
;	Writes the value stored in DisplayValue into the EEPROM
;	at the location specified by the value currently in TEMP
;	Location:	Value:
;	0x00		H2SetPoint
;	0x01		H1SetPoint
;	0x02		HystValue
;***************************************************

WRITE_EEPROM
	movf	TEMP, W
	movwf	EEADR						; Address in EEADR register
	movff	DisplayValue, EEDATA		; Data to write goes in EEDATA
	bcf		PIR2, EEIF					; Clear bit from previous write
	bcf		EECON1, EEPGD				; Point to DATA memory
	bcf		EECON1, CFGS				; Access data EEPROM instead of config registers
	bsf		EECON1, WREN				; Enable writes
	bcf		INTCON, GIE					; Disable Interrupts
	movlw	0x55						; The 55 and AA are required to write the EEPROM
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf		EECON1, WR					; Begin write
WAITFOREEPROM
	btfss	PIR2, EEIF					; Is write finished?
	bra		WAITFOREEPROM
	bsf		INTCON, GIE					; Enable interrupts
	bcf		EECON1, WREN				; Disable writes
	return

;***************************************************
;HYSTERESIS_SCREEN
;	Runs the HYSTERESIS screen- Handles changing value through calls to
;	HANDLE_TEMPEDIT, writing new value to EEPROM, and dealing with appropriate
;	responces	
;
;***************************************************
HYSTERESIS_SCREEN
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	movlw	0x03	; Hysteresis screen is #3
	cpfseq	DisplayCounter
	return

	movlw	0x0B
	movwf	CursorPosition	; Set CursorPosition to be at end of current line
	movf	HystValue, W
	movwf	DisplayValue
	call	DISPLAYNUMBER
HYSTERESIS_SCREEN_LOOP
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, ButtonPush		; Has someone pushed the button?
	bra		HYSTERESIS_EDIT_VALUE			; Yup
	btfss	SwitchFLAGS, Switch_Update	; Has the knob moved?
	bra		HYSTERESIS_SCREEN_LOOP			; No		
	return


HYSTERESIS_EDIT_VALUE
	btfsc	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		HYSTERESIS_SCREEN_LOCKED	; Yes
	call	UNLOCKED_DISPLAY			; No
	call	HANDLE_TEMPEDIT
	movlw	0x47						; Data position 0x47 in EEPROM is for HystValue
	movwf	TEMP						; Address in EEPROM specified in TEMP
	call	WRITE_EEPROM
	call	SAVED_DISPLAY
	movf	DisplayValue, W
	movwf	HystValue
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	bra		HYSTERESIS_SCREEN_LOOP
HYSTERESIS_SCREEN_LOCKED
	call	LOCKED_DISPLAY
	bra		HYSTERESIS_SCREEN

;***************************************************
;SETPOINT_SCREEN
;	-- 3/5/05 - This was changed to now say "H1 off @:"- This is due to the
;	same reasons that required the TOOHOT_SCREEN routine to be re-written.
;	It wasn't worth changing all the labels to reflect the newly displayed messages.
;	Runs the SETPOINT screen- Handles changing value through calls to
;	HANDLE_TEMPEDIT, writing new value to EEPROM, and dealing with appropriate
;	responses	
;
;***************************************************
SETPOINT_SCREEN
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	movlw	0x02	; Setpoint screen is #2
	cpfseq	DisplayCounter
	return

	movlw	0x09
	movwf	CursorPosition	; Set CursorPosition to be at end of current line
	movf	H1SetPoint, W
	movwf	DisplayValue
	call	DISPLAYNUMBER

SETPOINT_SCREEN_LOOP
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, ButtonPush		; Has someone pushed the button?
	bra		SETPOINT_EDIT_VALUE			; Yup
	btfss	SwitchFLAGS, Switch_Update	; Has the knob moved?
	bra		SETPOINT_SCREEN_LOOP			; No		
	return

SETPOINT_EDIT_VALUE
	btfsc	SwitchFLAGS, Lock_Enable	; Is keylock on?
	bra		SETPOINT_SCREEN_LOCKED		; Yes
	call	UNLOCKED_DISPLAY			; No
	call	HANDLE_TEMPEDIT
	movlw	0x20						; Data position 0x20 in EEPROM is for H1SetPoint
	movwf	TEMP						; Address in EEPROM specified in TEMP
	call	WRITE_EEPROM
	call	SAVED_DISPLAY
	movf	DisplayValue, W
	movwf	H1SetPoint
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	bra		SETPOINT_SCREEN_LOOP
SETPOINT_SCREEN_LOCKED
	call	LOCKED_DISPLAY				; No
	bra		SETPOINT_SCREEN

;***************************************************
;HANDLE_TEMPEDIT
;	Looks at the switch flags to read and change the displayed number
;	The number is input and output as DisplayValue
;***************************************************
HANDLE_TEMPEDIT
	bcf		SwitchFLAGS, ButtonPush		; Make sure no roving buttonpushes in screen.
	call	CHECK_SWITCH_STATUS
	btfsc	SwitchFLAGS, ButtonPush
	return
	btfss	SwitchFLAGS, Switch_Update
	bra		HANDLE_TEMPEDIT
	bcf		SwitchFLAGS, Switch_Update	; Acknowledge that switch has been dealt with.


	btfss	QEICON,5					; If set, go right
	bra		DEC_VALUE					; Left turn requested
	incf	DisplayValue				; Move right increments temperature
	movlw	0x64						; There are 100 values total (0-99)
	cpfslt	DisplayValue
	clrf	DisplayValue				; If DisplayCounter > 0x04, reset DisplayCounter to 0
	bra		HANDLE_TEMPEDIT_END
	

DEC_VALUE								; Go left
	decf	DisplayValue
	movlw	0xFF
	cpfseq	DisplayValue				; Reset DisplayCounter to 4
	bra		HANDLE_TEMPEDIT_END
	movlw	0x63
	movwf	DisplayValue

HANDLE_TEMPEDIT_END
	call	DISPLAYNUMBER
	bra		HANDLE_TEMPEDIT
	return


;***************************************************
;DISPLAYNUMBER
;	Displays DisplayValue over the serial port
;	at the cursor position specified by CursorPosition
;***************************************************
DISPLAYNUMBER
	call	FETCH_ASCII_VALUES
	movlw	0x1B			; Hex command for cursor position
	call	SEND_BYTE
	movf	CursorPosition, W
	call	SEND_BYTE		; Cursor should now be positioned.

	movf	SerialWordH, W	; Send numbers
	call	SEND_BYTE
	movf	SerialWordL, W
	call	SEND_BYTE

	movlw	0x7E			; Send "DegC" markings
	call	SEND_BYTE
	movlw	0x43
	call	SEND_BYTE	
	return

;***************************************************
;CHECK_SWITCH_STATUS
;	Polls the knob to see if it has changed position.
;	If it has, set a flag.
;***************************************************
CHECK_SWITCH_STATUS
	movlw	0xFE
	cpfseq	CAP2BUFL
	bra		CHECK_SWITCH_RIGHT
	bra		CHECK_SWITCH_STATUS_CONTINUE
CHECK_SWITCH_RIGHT
	movlw	0x02
	cpfseq	CAP2BUFL
	bra		CHECK_SWITCH_STATUS_CONTINUE2
CHECK_SWITCH_STATUS_CONTINUE
	clrf	CAP2BUFL
	bsf		SwitchFLAGS, Switch_Update	; If our counter != 0, then we have, Set the flag to show it


; The following code makes it such that it takes a complete down-up cycle on the buttons
; to select things. Without this, the processor moves so fast it sets the flags
; before the switch springs up!
CHECK_SWITCH_STATUS_CONTINUE2
	btfss	PORTA, 5				; Is button down?
	bsf		SwitchFLAGS, ButtonDown	; Yes- Button is down, active LOW for this project!
	movlw	0xFF
	movwf	TEMP
SWITCH_DEBOUNCE
	decfsz	TEMP
	bra		SWITCH_DEBOUNCE
	btfsc	PORTA, 5				; No- Check if button is UP
	btfss	SwitchFLAGS, ButtonDown ; Yes- Button is UP. Was it most recently down?
	bra		CHECK_SWITCH_STATUS_CONTINUE3	; NO- Not most recently down.
	bsf		SwitchFLAGS, ButtonPush	; Yes- most recently down
	bcf		SwitchFLAGS, ButtonDown

CHECK_SWITCH_STATUS_CONTINUE3
	btfss	PORTE, 0		; Is Keylock on?- ACTIVE LOW- When input = 0 LOCK ON!
	bra		CHECK_SWITCH_ENABLE_LOCK	; Yes
	bcf		SwitchFLAGS, Lock_Enable	; No
	bra		CHECK_SWITCH_END

CHECK_SWITCH_ENABLE_LOCK
	bsf		SwitchFLAGS, Lock_Enable

CHECK_SWITCH_END
	return

;***************************************************
;HANDLE_MENUS
;	Looks at the switch flags to Display the right heading
;	and update the menu counter
;***************************************************
HANDLE_MENUS
	btfss	SwitchFLAGS, Switch_Update
	return
	bcf		SwitchFLAGS, Switch_Update	; Acknowledge that switch has been dealt with.

	btfss	QEICON, 5					; If set, go right
	bra		MOVE_LEFT					; Left turn requested
	incf	DisplayCounter				; Move right goes up through menus
	movlw	0x05						; There are five menus total
	cpfslt	DisplayCounter
	clrf	DisplayCounter				; If DisplayCounter > 0x04, reset DisplayCounter to 0
	bra		HANDLE_MENUS_END
	
MOVE_LEFT								; Go left
	decf	DisplayCounter
	movlw	0xFF
	cpfseq	DisplayCounter				; Reset DisplayCounter to 4
	bra		HANDLE_MENUS_END
	movlw	0x04
	movwf	DisplayCounter

HANDLE_MENUS_END
	call	SHOW_MENU
	return


;***************************************************
;SHOW_MENU
;	Turns the menu counter into an actual label to display
;***************************************************
SHOW_MENU
	movlw	0x00
	cpfseq	DisplayCounter
	bra		SHOW_NEXT_1
	call	RELAY_DISPLAY
	bra		SHOW_MENU_END
SHOW_NEXT_1
	movlw	0x01
	cpfseq	DisplayCounter
	bra		SHOW_NEXT_2
	call	STATUSMSG_DISPLAY
	bra		SHOW_MENU_END
SHOW_NEXT_2
	movlw	0x02
	cpfseq	DisplayCounter
	bra		SHOW_NEXT_3
	call	H1offat_DISPLAY
	bra		SHOW_MENU_END
SHOW_NEXT_3
	movlw	0x03
	cpfseq	DisplayCounter
	bra		SHOW_NEXT_4
	call	HYSTERESIS_DISPLAY
	bra		SHOW_MENU_END
SHOW_NEXT_4
	movlw	0x04
	cpfseq	DisplayCounter
	bra		SHOW_MENU_END
	call	H2offat_DISPLAY
SHOW_MENU_END
	return

;***************************************************
;DELAY_START
;	Pauses the processor after reset long enough for the display to come up.
;***************************************************
DELAY_START
	movlw	0xFF
	movwf	DELAYCOUNTER
	movwf	DELAYCOUNTER1
	movlw	0x15
	movwf	DELAYCOUNTER2
first_delay
	decfsz	DELAYCOUNTER
	bra		first_delay
	movlw	0xFF
	movwf	DELAYCOUNTER
	decfsz	DELAYCOUNTER1
	bra		first_delay
	movlw	0xFF
	movwf	DELAYCOUNTER
	movwf	DELAYCOUNTER1
	decfsz	DELAYCOUNTER2
	bra		first_delay
	return

;*******************************************************************************
;*******************************************************************************
; 						Serial Output Code
;
;*******************************************************************************
;*******************************************************************************

;*******************************************************************************
; Message Definitions- Places the proper memory locations of the messages
; into the table reads for the serial output
;
;*******************************************************************************
WELCOME_DISPLAY
	movlw	UPPER WELCOME	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH WELCOME
	movwf	TBLPTRH
	movlw	LOW WELCOME
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY1_DISPLAY
	movlw	UPPER RELAY1	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY1
	movwf	TBLPTRH
	movlw	LOW RELAY1
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY2_DISPLAY
	movlw	UPPER RELAY2	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY2
	movwf	TBLPTRH
	movlw	LOW RELAY2
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY3_DISPLAY
	movlw	UPPER RELAY3	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY3
	movwf	TBLPTRH
	movlw	LOW RELAY3
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY4_DISPLAY
	movlw	UPPER RELAY4	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY4
	movwf	TBLPTRH
	movlw	LOW RELAY4
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY_DISPLAY
	movlw	UPPER RELAY	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY
	movwf	TBLPTRH
	movlw	LOW RELAY
	movwf	TBLPTRL
	bra		SEND_DATA

STATUSMSG_DISPLAY	
	movlw	UPPER STATUSMSG	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH STATUSMSG
	movwf	TBLPTRH
	movlw	LOW STATUSMSG
	movwf	TBLPTRL
	call	SEND_DATA
	return

H1offat_DISPLAY
	movlw	UPPER H1offat		;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH H1offat
	movwf	TBLPTRH
	movlw	LOW H1offat
	movwf	TBLPTRL
	bra		SEND_DATA

HYSTERESIS_DISPLAY
	movlw	UPPER HYSTERESIS	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH HYSTERESIS
	movwf	TBLPTRH
	movlw	LOW HYSTERESIS
	movwf	TBLPTRL
	bra		SEND_DATA

H2offat_DISPLAY
	movlw	UPPER H2offat	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH H2offat
	movwf	TBLPTRH
	movlw	LOW H2offat
	movwf	TBLPTRL
	bra		SEND_DATA

LOCKED_DISPLAY
	movlw	UPPER LOCKED	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH LOCKED
	movwf	TBLPTRH
	movlw	LOW LOCKED
	movwf	TBLPTRL
	bra		SEND_DATA

UNLOCKED_DISPLAY
	movlw	UPPER UNLOCKED	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH UNLOCKED
	movwf	TBLPTRH
	movlw	LOW UNLOCKED
	movwf	TBLPTRL
	bra		SEND_DATA

POWERFAIL_DISPLAY
	movlw	UPPER POWERFAIL	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH POWERFAIL
	movwf	TBLPTRH
	movlw	LOW POWERFAIL
	movwf	TBLPTRL
	call	SEND_DATA

POWERFAIL_DISPLAY_WAIT
	call	CHECK_SWITCH_STATUS
	btfss	SwitchFLAGS, ButtonPush
	bra		POWERFAIL_DISPLAY_WAIT
	bcf		SwitchFLAGS, ButtonPush
	bcf		SwitchFLAGS, Switch_Update
	return

SAVED_DISPLAY
	movlw	UPPER SAVED	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH SAVED
	movwf	TBLPTRH
	movlw	LOW SAVED
	movwf	TBLPTRL
	bra		SEND_DATA

RELAYLOCKED_DISPLAY
	movlw	UPPER RELAYLOCKED	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAYLOCKED
	movwf	TBLPTRH
	movlw	LOW RELAYLOCKED
	movwf	TBLPTRL
	bra		SEND_DATA

RELAY_DONE_DISPLAY
	movlw	UPPER RELAY_DONE		;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH RELAY_DONE
	movwf	TBLPTRH
	movlw	LOW RELAY_DONE
	movwf	TBLPTRL
	bra		SEND_DATA

ON_DISPLAY
	movlw	UPPER ON	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH ON
	movwf	TBLPTRH
	movlw	LOW ON
	movwf	TBLPTRL
	bra		SEND_DATA

OFF_DISPLAY
	movlw	UPPER OFF	;Initialize Table pointer to the first  
	movwf	TBLPTRU				;location of the table
	movlw	HIGH OFF
	movwf	TBLPTRH
	movlw	LOW OFF
	movwf	TBLPTRL
	bra		SEND_DATA


;*******************************************************************************
; Outputs data in table to serial port
;*******************************************************************************
SEND_DATA
	TBLRD*+
	movf	TABLAT,W
	btfsc	STATUS,Z
	return
SEND_BYTE_FROM_WREG
	btfss	PIR1,TXIF
	goto	SEND_BYTE_FROM_WREG
	movwf	TXREG
	bra		SEND_DATA	

;*******************************************************************************
;This routine sends the byte in the WREG over the serial port.
;*******************************************************************************
SEND_BYTE
	btfss	PIR1,TXIF
	goto	SEND_BYTE
	movwf	TXREG
	return

;*******************************************************************************
;*******************************************************************************
; 						INITIALIZATION SUBROUTINES
;*******************************************************************************
;*******************************************************************************

;***************************************************
;COPY_DATA_FROM_EEPROM- Eventually will get all the
;constant values from the PICs EEPROM. For now, just
;copies known values into variables.
;	Location:	Value:
;	0x08		H2SetPoint
;	0x20		H1SetPoint
;	0x47		HystValue
;***************************************************
COPY_DATA_FROM_EEPROM
	movlw	0x08			; For H2SetPoint
	movwf	EEADR
	bcf		EECON1, EEPGD	; Point to DATA memory
	bsf		EECON1, RD		; EEPROM read
	movff	EEDATA, H2SetPoint

	movlw	0x20
	movwf	EEADR
	bcf		EECON1, EEPGD	; Point to DATA memory
	bsf		EECON1, RD		; EEPROM read
	movff	EEDATA, H1SetPoint

	movlw	0x47
	movwf	EEADR
	bcf		EECON1, EEPGD	; Point to DATA memory
	bsf		EECON1, RD		; EEPROM read
	movff	EEDATA, HystValue

	return
;***************************************************
;INITIALIZE_REGISTERS- A place to put random
; initialization stuff
;***************************************************
INITIALIZE_REGISTERS
	movlw	0x01			; Initialize at menu #1, the Current Status screen
	movwf	DisplayCounter	; Start at position 1 in the menus
	clrf	CursorPosition	; Clear CursorPosition to 0
	clrf	DisplayValue	; Should display "00" if not defined
	clrf	SystemFLAGS		; Clear SystemFLAGS
	movlw	0x46
	movwf	H2SetPoint
	movlw	0x44
	movwf	H1SetPoint
	movlw	0x01
	movwf	HystValue
;	clrf	HystValue		; Make sure key control variables are reset to
;	clrf	H2SetPoint		; known state on powerup, but before EEPROM reads.
;	clrf	H1SetPoint
	return

;***************************************************
;INITIALIZE_SWITCH- Initializes things having to do with
; the knob input stuff. Using the processors built-in QEI
; interface. Inputs on CAP2/QEA and CAP3/QEB (Pins 5 and 6)
;***************************************************
INITIALIZE_SWITCH
	clrf	SwitchFLAGS		; Initialize SwitchFLAGS to known value

	movlw	b'00111000'		; Enable inputs on pin 5,6,7 (QEA, QEB, and the pushbutton)
	movwf	TRISA

	movlw	b'00000001'		; Sets up Pin #8 as input for keylock
	movwf	TRISE

	movlw	b'00000000'		; Set up RD4 and RD5 as outputs (Fan and Heat respectively)
	movwf	TRISD

	movlw	b'00000000'		; Set up RB0 as output (AUX)
	movwf	TRISB

	clrf	ANSEL0			; Make sure we start with fresh I/O pins
	clrf	PORTA

	clrf	CAP2BUFL		; Uses position counter to determine if knob
	clrf	CAP2BUFH		; value has changed. Needs to be zeroed.
	movlw	b'00110011'		; Enable filters on input
	movwf	DFLTCON

	movlw	b'00000100'		; Enable QEI mode with 2x Update Mode
	movwf	QEICON
	return

;***************************************************
;Initialize USART paramaters
;***************************************************
Initialize_Serial_Port
	movlw	b'00001000'
	movwf	BAUDCTL

	movlw	0x08		;Baudrate = 9600
	movwf	SPBRG
	movlw	0x02
	movwf	SPBRGH

	movlw	b'00100100'	;8-bit transmission, enable transmission;	
	movwf	TXSTA		;Asynchronous mode with High speed transmission
	
	movlw	b'10010000'	;Enable the serial port
	movwf	RCSTA		;with 8-bit continuous reception

	bcf	TRISC,6
	bsf	TRISC,7

	return

;*******************************************************************************
;INITIALIZER_TIMER0
;	Initialize the timer0, the key timebase for the whole thing.
;*******************************************************************************
INITIALIZE_TIMER0
	movlw	b'10000010'					;T0Con
	movwf	T0CON						;a) TMR0 ON, 
										;b) 16-bit operation, 
										;c) clock source is T0CKL, 
										;d) prescalar is 1:8

	movlw	Timer0Reload_H				;Timer0 Initialisation 
	movwf	TMR0H
	movlw	Timer0Reload_L
	movwf	TMR0L	
	return


;*******************************************************************************
;INITIALIZE_INTERRUPTS-
;	Sets up timer0 high priority interrupt and brownout status stuff
;*******************************************************************************
INITIALIZE_INTERRUPTS
	bsf		INTCON,TMR0IE				;Timer0 overflow Interrupt enable
	bsf		INTCON2,TMR0IP				;Timer0 overflow Interrupt high priority
;	bsf		PIE2, EEIE					; Enable EEPROM interrupt

	movlw	b'10010011'					;Power ON reset status bit/Brownout reset status bit
	movwf	RCON						;and Instruction flag bits are set
										;Enable Priority levels on Interrupts
	bsf		INTCON,GIEH					;Enable high priority interrupts
	return

;*******************************************************************************
;INITIALIZE_AD-
;	Initializes A/D channels
;	We have two A/D inputs, on AN0 and AN1 diode-clamped to not exceed
;	5 volts.
;*******************************************************************************
INITIALIZE_AD
	bsf		TRISA, 0		; Set up AN0 and AN1 as inputs
	bsf		TRISA, 1

	movlw	b'00000011'		; AN0 and AN1 are enabled as analog inputs
	movwf	ANSEL0

	movlw	b'00000000'		; Group B is AN1, Group A is AN0
	movwf	ADCHS

	movlw	b'00000000'		; No interrupts or FIFOs needed
	movwf	ADCON3

	movlw	b'00110010'		; Left justified, acq. time 12 Tad, Conversion clock Fosc/32
	movwf	ADCON2

	movlw	b'00000000'		; No FIFO, Avdd and Avss not changed
	movwf	ADCON1

	movlw	b'00000011'		; A/D enabled in single-channel mode, sample start.
	movwf	ADCON0


	return
;*******************************************************************************
;*******************************************************************************
; 						Serial Messages
;
; Special Note:
; 0x15 is clear display
; 0x10 is write on bottom line
; 0x11 is write on top line
; 0x12 is disable carriage return
; 0x00 must end each line.
;*******************************************************************************
;*******************************************************************************
TABLE2	code	0x0800
WELCOME ;"HotBox V0.6     G. Linder, 2005"
	db	0x15,0x48,0x6F,0x74,0x42,0x6F,0x78,0x20,0x56,0x30,0x2E,0x36,0x20,0x20,0x20,0x20,0x20,0x47,0x2E,0x4C,0x69,0x6E,0x64,0x65,0x72,0x2C,0x20,0x32,0x30,0x30,0x35,0x0E,0x00

RELAY  ;"  H1  Fan H2  ^"
	db  0x15,0x10,0x11,0x20,0x20,0x48,0x31,0x20,0x20,0x46,0x61,0x6E,0x20,0x48,0x32,0x20,0x20,0x5E,0x00

RELAY1 ;" [H1] Fan H2  ^"
	db	0x15,0x10,0x11,0x20,0x5B,0x48,0x31,0x5D,0x20,0x46,0x61,0x6E,0x20,0x48,0x32,0x20,0x20,0x5E,0x00

RELAY2	;"  H1 [Fan]H2  ^"
	db  0x15,0x10,0x11,0x20,0x20,0x48,0x31,0x20,0x5B,0x46,0x61,0x6E,0x5D,0x48,0x32,0x20,0x20,0x5E,0x00

RELAY3	;"  H1  Fan[H2]  ^"
	db  0x15,0x10,0x11,0x20,0x20,0x48,0x31,0x20,0x20,0x46,0x61,0x6E,0x5B,0x48,0x32,0x5D,0x20,0x5E,0x00

RELAY4	;"  H1  Fan H2  [^]:
	db  0x15,0x10,0x12,0x20,0x20,0x48,0x31,0x20,0x20,0x46,0x61,0x6E,0x20,0x48,0x32,0x20,0x5B,0x5E,0x5D,0x00

STATUSMSG ;"T1:     T2:    "
	db	0x15,0x54,0x31,0x3A,0x20,0x20,0x20,0x20,0x20,0x54,0x32,0x3A,0x20,0x20,0x20,0x20,0x00

H1offat ;"H1 off @:"
	db	0x15,0x48,0x31,0x20,0x6F,0x66,0x66,0x20,0x40,0x3a,0x00

H2offat ;"H2 off @:"
	db	0x15,0x48,0x32,0x20,0x6F,0x66,0x66,0x20,0x40,0x3a,0x00

HYSTERESIS ;"Hysteresis:"
	db	0x15,0x48,0x79,0x73,0x74,0x65,0x72,0x65,0x73,0x69,0x73,0x3a,0x00

LOCKED ;"Setting Locked"
	db	0x10,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x4C,0x6F,0x63,0x6B,0x65,0x64,0x11,0x00

UNLOCKED ;"Setting Unlocked"
	db	0x10,0x12,0x0B,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x55,0x6E,0x6C,0x6F,0x63,0x6B,0x65,0x64,0x11,0x0C,0x00

RELAYLOCKED ;"Setting Locked"
	db	0x11,0x16,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x4C,0x6F,0x63,0x6B,0x65,0x64,0x11,0x00

SAVED	;"Saved Setting"
	db	0x10,0x12,0x53,0x61,0x76,0x65,0x64,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x20,0x20,0x20,0x11,0x00

POWERFAIL ;"WARNING:        POWER FAIL"
	db	0x15,0x57,0x41,0x52,0x4E,0x49,0x4E,0x47,0x3A,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0B,0x50,0x4F,0x57,0x45,0x52,0x20,0x46,0x41,0x49,0x4C,0x0C,0x00

ON ; "ON "
	db	0x4F,0x4E,0x20,0x00

OFF ; "OFF"
	db	0x4F,0x46,0x46,0x00

RELAY_DONE ; "Done."
	db	0x11,0x16,0x44,0x6F,0x6E,0x65,0x2E,0x00

TABLE3	code	0x0B00
SCROLLYMESSAGE ; "Hotbox mode: Auto   Fan:    H1:    H2:    "
	db	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
	db	0x20,0x48,0x6F,0x74,0x62,0x6F,0x78,0x20,0x6D,0x6F,0x64,0x65,0x3A,0x20,0x41,0x75
	db	0x74,0x6F,0x20,0x20,0x20,0x46,0x61,0x6E,0x3A,0x20,0x20,0x20,0x20,0x48,0x31,0x3A
	db	0x20,0x20,0x20,0x20,0x48,0x32,0x3A,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
	db	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20

SCROLLYMESSAGE2 ; "CAUTION:MANUAL MODE  Fan:    H1:    H2:   "
	db	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
	db	0x43,0x41,0x55,0x54,0x49,0x4F,0x4E,0x3A,0x4D,0x41,0x4E,0x55,0x41,0x4C,0x20,0x4D
	db	0x4F,0x44,0x45,0x20,0x20,0x46,0x61,0x6E,0x3A,0x20,0x20,0x20,0x20,0x48,0x31,0x3A
	db	0x20,0x20,0x20,0x20,0x48,0x32,0x3A,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
	db	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20

;*********************************
; In order to save headaches for displaying numbers, all numbers from 00-99 are here in ASCII-
;	Just look up the word 45 for the ASCII values corresponding to "45"
;
;*********************************
TABLE1	code	0x0A00

ASCII_NUMBER_TABLE
	dw	0x3030,0x3031,0x3032,0x3033,0x3034,0x3035,0x3036,0x3037,0x3038,0x3039,0x3130,0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137,0x3138,0x3139
	dw	0x3230,0x3231,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237,0x3238,0x3239,0x3330,0x3331,0x3332,0x3333,0x3334,0x3335,0x3336,0x3337,0x3338,0x3339
	dw	0x3430,0x3431,0x3432,0x3433,0x3434,0x3435,0x3436,0x3437,0x3438,0x3439,0x3530,0x3531,0x3532,0x3533,0x3534,0x3535,0x3536,0x3537,0x3538,0x3539
	dw	0x3630,0x3631,0x3632,0x3633,0x3634,0x3635,0x3636,0x3637,0x3638,0x3639,0x3730,0x3731,0x3732,0x3733,0x3734,0x3735,0x3736,0x3737,0x3738,0x3739
	dw	0x3830,0x3831,0x3832,0x3833,0x3834,0x3835,0x3836,0x3837,0x3838,0x3839,0x3930,0x3931,0x3932,0x3933,0x3934,0x3935,0x3936,0x3937,0x3938,0x3939


TABLE4	code	0x0c00

VOLTAGE_SCALE_TABLE
	db	0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0A,0x0A,0x0B,0x0C
	db	0x0D,0x0E,0x0E,0x0F,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x16,0x16,0x17,0x18,0x19
	db	0x1A,0x1A,0x1B,0x1C,0x1D,0x1E,0x1E,0x1F,0x20,0x21,0x22,0x22,0x23,0x24,0x25,0x26
	db	0x26,0x27,0x28,0x29,0x2A,0x2A,0x2B,0x2C,0x2D,0x2E,0x2E,0x2F,0x30,0x31,0x32,0x32
	db	0x33,0x34,0x35,0x36,0x36,0x37,0x38,0x39,0x3A,0x3A,0x3B,0x3C,0x3D,0x3E,0x3E,0x3F
	db	0x40,0x41,0x42,0x42,0x43,0x44,0x45,0x46,0x46,0x47,0x48,0x49,0x4A,0x4A,0x4B,0x4C
	db	0x4D,0x4E,0x4E,0x4F,0x50,0x51,0x52,0x52,0x53,0x54,0x55,0x56,0x56,0x57,0x58,0x59
	db	0x5A,0x5A,0x5B,0x5C,0x5D,0x5E,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x64,0x64,0x64
	db	0x64


	END
