
; CC5X Version 3.0E, Copyright (c) B. Knudsen Data
; C compiler for the PICmicro family
; ************  15. Apr 2000   2:09  *************

	processor  16F876
	radix  DEC

PCL         EQU   0x02
PORTA       EQU   0x05
TRISA       EQU   0x85
PORTB       EQU   0x06
TRISB       EQU   0x86
PCLATH      EQU   0x0A
Carry       EQU   0
Zero_       EQU   2
RP0         EQU   5
RP1         EQU   6
PORTC       EQU   0x07
RCSTA       EQU   0x18
TXREG       EQU   0x19
RCREG       EQU   0x1A
ADRESH      EQU   0x1E
ADCON0      EQU   0x1F
TRISC       EQU   0x87
TXSTA       EQU   0x98
SPBRG       EQU   0x99
ADRESL      EQU   0x9E
ADCON1      EQU   0x9F
TXIF        EQU   4
RCIF        EQU   5
ADIF        EQU   6
GO          EQU   2
ADIE        EQU   6
RS          EQU   2
EN          EQU   5
SOUND       EQU   4
KEYPAD      EQU   0x06
WFT         EQU   4
number      EQU   0x22
ms          EQU   0x24
tempcount   EQU   0x25
nyble       EQU   0x27
temp        EQU   0x28
byte        EQU   0x25
nibble      EQU   0x26
row         EQU   0x24
column      EQU   0x25
tmpa        EQU   0x26
index       EQU   0x27
ms_2        EQU   0x24
x           EQU   0x25
y           EQU   0x26
x_2         EQU   0x20
Instruction EQU   0x21
key         EQU   0x22
lastkey_2   EQU   0x23
regbuf      EQU   0x24

	GOTO main

  ; FILE C:\PROGRA~1\MPLAB\CCS\NETWORK\NODE.C
			;/*
			;
			;	Home Automation Terminal
			;	Version 0.1.1
			;	Copyright 2000, Adam Davis
			;	adavis@ubasics.org
			;	
			;	Code, schematic and other resources found at
			;	HTTP://WWW.UBASICS.COM/adam/electronics/ha
			;
			;	NODE.C
			;
			;	18-Apr-00	v0.1.1
			;		I've redone the schematic so the A/D is open for use.  The thermister
			;		is now on PORTA:0 as a voltage divider with a 12k resister.  The LCD
			;		connections are as follows:
			;			LCD[D0:D3]	Ground
			;			LCD[D4:D7]	PORTC[0:3]
			;			LCD[RW]		Ground (if needed, use PORTA[4])
			;			LCD[RS]		PORTA[2]
			;			LCD[EN]		PORTA[5]
			;		This leaves 3 A/D ports free(one being used by the thermister) for either
			;		A/D usage of digital i/o.  It also leave PORTA[4] free for use (if 
			;		LCD[RW] is tied to ground).  This is useful for timing applications, or
			;		other uses of an open collector output.
			;
			;	26-Feb-00	v0.1.0
			;		Up to this point this has been a jumble of code for using the LCD,
			;		keypad, thermister, and basic rs-232 usage.  This is the foundation.
			;*/
			;
			;#include "c:\progra~1\ccs\16f876.h"
			;#define CP_off  |= 0x3F30		// Code protect (for whatever reason) is not in the include file
			;										// and is defined here instead
			;#pragma config CP_off,PWRTE=on,WDTE=off,FOSC=HS,BODEN=on,ID=0x0001
			;		// No code protect, power up timer on, watch dog off, OSC=high speed, brown out detect on,
			;		// ID = xxyz version number expressed here, xx = device type, y is major and z is minor (0.0 to 15.15)
			;		// 0x001f is device type 0 (up to 256 types, 0 is undefined/preproduction) ver 1.15
			;
			;#pragma bit RS @ PORTA.2		// LCD Register Select (1=data, 0=instruction)
			;#pragma bit EN @ PORTA.5		// LCD Enable LCD latches data at H->L transition
			;#pragma bit RW @ PORTA.4		// Read/Write select (1=Read, 0=Write) Tied to ground, pin not used
			;#pragma bit SOUND @ PORTC.4	// Speaker is connected to this pin
			;#pragma char KEYPAD @ PORTB	//	Keypad is connected to this port
			;
			;#define ESCCHAR  0x1B	// This is the escape character to denote an instruction
			;								// for the LCD, or ask for a temperature measurement
			;								// 0x1B is 27 ascii, which is the escape character.
			;
			;void delayms(uns8 ms);
			;void write8(uns8 byte);
			;
			;//#pragma rambank 0	// Rambank 0 is assumed allready
			;char checksum[2];		// Two byte checksum
			;char packet1[64];		// First 64 bytes of packet (part 1)
			;uns8 lastkey;			// Last key pressed/scanned
			;char header[5];		// Five bytes for header
			;char CountPacket;		// Counter for packet
			;bit WOP;					//	Working on Packet flag
			;bit WOH;					// Working on Header flag
			;bit WOD;					// Working on Data flag
			;bit WOC;					// Working on Checksum flag
			;bit WFT;					// Waiting for temp measurement flag (actually, A/D, not just temp)
			;
			;#pragma rambank 2		// The following variable definition(s) should be made in rambank 3
			;char packet2[96];		// Part two of the packet memory, 96 bytes
			;
			;#pragma rambank 3		// The following variable definition(s) should be made in rambank 3
			;char packet3[96];		// Part three of the packet memory, 96 bytes
			;
			;#pragma rambank 0		// Any following variable definitions should be made in rambank 0
			;
			;char initmsg(char number)
			;{	skip(number);					// This is an initialization message for the device (mostly for testing)
initmsg
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF number
	CLRF  PCLATH
	MOVF  number,W
	ADDWF PCL,1
			;#pragma return[16] = "Micro Basics HAT"
	RETLW .77
	RETLW .105
	RETLW .99
	RETLW .114
	RETLW .111
	RETLW .32
	RETLW .66
	RETLW .97
	RETLW .115
	RETLW .105
	RETLW .99
	RETLW .115
	RETLW .32
	RETLW .72
	RETLW .65
	RETLW .84
			;}
			;
			;void delayms(uns8 ms)
			;{		// This routine delays ABOUT ms milliseconds.  NOT PRECISION.
delayms
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF ms
			;	uns8 tempcount;				// Temporary variable for holding current count
			;	while(ms != 0)					// While we still need to delay (could/should probably use for here)
m001	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  ms,1
	BTFSC 0x03,Zero_
	GOTO  m004
			;	{
			;		tempcount = 125;			// It takes about 125 of these inner loops each ms
	MOVLW .125
	MOVWF tempcount
			;		while(tempcount != 0)	// Each inner loop is about 8 instruction cycles (including jumps)
m002	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  tempcount,1
	BTFSC 0x03,Zero_
	GOTO  m003
			;			tempcount--;			// End of inner loop, decrement tempcount
	DECF  tempcount,1
	GOTO  m002
			;		ms--;							// Decrement ms.
m003	BCF   0x03,RP0
	BCF   0x03,RP1
	DECF  ms,1
			;	}
	GOTO  m001
			;	
			;	return;							// All done.
m004	RETURN
			;}
			;
			;void write4(uns8  nyble)
			;{		// Writes data to the LCD in 4-bit chunks
write4
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF nyble
			;	uns8 temp;				// Holding variable
			;//	RW = 0;					// Set the R/W to Write (R/W is tied to ground, so we don't need to do this)
			;	nyble &= 0xf;			// Make sure we are only using the bottom four bits of nyble
	MOVLW .15
	ANDWF nyble,1
			;	temp = PORTC & 0xf0;	// Copy the four high bits of PORTC into temp
	MOVLW .240
	ANDWF PORTC,W
	MOVWF temp
			;	temp |= nyble;			// Put nyble and temp together, four low bits of nyble, and four high bits of PORTC
	MOVF  nyble,W
	IORWF temp,1
			;	PORTC = temp;			// Write it all to PORTC.  High 4 bits should be unchanged, lower four bits are from nyble
	MOVF  temp,W
	MOVWF PORTC
			;	EN=1;						// Bring enable high
	BSF   0x05,EN
			;	nop();					// Wait a teensy bit
	NOP  
			;	EN=0;						// Bring Enable Low
	BCF   0x05,EN
			;	return;
	RETURN
			;}
			;
			;void write8(uns8 byte)
			;{		// Writes 8 bits to the LCD using the 4-bit interface
write8
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF byte
			;	uns8 nibble;						// Holding space for each nibble
			;	nibble = (byte & 0xf0) >> 4;	// Rotate the high nibble of byte into nibble
	MOVLW .240
	ANDWF byte,W
	MOVWF nibble
	SWAPF nibble,W
	ANDLW .15
	MOVWF nibble
			;	write4(nibble);					// Send the high 4 bits first
	MOVF  nibble,W
	CALL  write4
			;	nibble = byte & 0xf;				// Copy lower four bits of byte into nibble
	MOVLW .15
	BCF   0x03,RP0
	BCF   0x03,RP1
	ANDWF byte,W
	MOVWF nibble
			;	write4(nibble);					// Send the lower four bits second
	MOVF  nibble,W
	GOTO  write4
			;}
			;
			;void initlcd(void)
			;{		// This goes through Hitachi's recomended powerup sequence to set a display to 4-bit interface
initlcd
			;	delayms(20);	// Wait for LCD to power up ( >15ms )
	MOVLW .20
	CALL  delayms
			;						// All the delays are to let the LCD execute the instruction before moving on.
			;	RS=0;				// Set RS low for instruction 
	BCF   0x03,RP0
	BCF   0x03,RP1
	BCF   0x05,RS
			;	write4(3);		// Set interface to 8 bits 
	MOVLW .3
	CALL  write4
			;	delayms(5);
	MOVLW .5
	CALL  delayms
			;	write4(3);		// Set interface to 8 bits 
	MOVLW .3
	CALL  write4
			;	delayms(1);
	MOVLW .1
	CALL  delayms
			;	write4(3);		// Set interface to 8 bits 
	MOVLW .3
	CALL  write4
			;	delayms(5);		// At this point we could actually start using the busy flag
	MOVLW .5
	CALL  delayms
			;						// instead of blind delays
			;	write4(2);		// Set the display to 4 bit interface 
	MOVLW .2
	CALL  write4
			;	delayms(5);
	MOVLW .5
	CALL  delayms
			;						// Having gone through hitachi's suggested powerup sequence,
			;						// we can now treat this as a 4 bit interface.
			;	write8(0x28);	// Set the LCD to 4-bit interface and two lines
	MOVLW .40
	CALL  write8
			;	delayms(5);
	MOVLW .5
	CALL  delayms
			;	write8(6);		// Curser moves right, display does not shift
	MOVLW .6
	CALL  write8
			;	delayms(5);
	MOVLW .5
	CALL  delayms
			;	write8(1);		// Clear all DDRAM, set current position to line one column one
	MOVLW .1
	CALL  write8
			;	delayms(5);
	MOVLW .5
	CALL  delayms
			;	write8(0xf);	// Turn display on, turn curser on, make curser blink
	MOVLW .15
	CALL  write8
			;	delayms(5);
	MOVLW .5
	GOTO  delayms
			;	return;
			;}
			;
			;char scankp(void)
			;{		// Simple key scanner, checks a 3x5 matrix for key presses.  Debounces keypress, and exits
scankp
			;		// EVEN IF THE KEY IS STILL PRESSED.  This way it doesn't lock up the processor while the
			;		// user holds down a key.  There is a line commented out which will keep you in this routine
			;		// until the key is released, if there is one pressed.
			;
			;	char row, column, tmpa, index;		// Variables to hold current row, and column
			;													// And other stuff
			;	
			;	TRISB=0x7;									// PORTB[7:3] need to be output
	MOVLW .7
	BSF   0x03,RP0
	BCF   0x03,RP1
	MOVWF TRISB
			;	KEYPAD=0x00;								// Set them all low
	BCF   0x03,RP0
	CLRF  KEYPAD
			;
			;	for (tmpa = 0x8; tmpa != 0; ) 		// Start with the fifth row
	MOVLW .8
	MOVWF tmpa
m005	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  tmpa,1
	BTFSC 0x03,Zero_
	GOTO  m015
			;	{                      
			;		KEYPAD = tmpa;							// Bring row high to check if key pressed on that row
	MOVF  tmpa,W
	MOVWF KEYPAD
			;		column = (KEYPAD & 0x07);			// column now holds the keypress (if one is pressed)
	MOVLW .7
	ANDWF KEYPAD,W
	MOVWF column
			;		if (column > 0)						// If a key is pressed, get row & save the column
	MOVF  column,1
	BTFSC 0x03,Zero_
	GOTO  m014
			;		{
			;			row = (KEYPAD & 0xF8) >> 3;	// This is the row
	MOVLW .248
	ANDWF KEYPAD,W
	MOVWF row
	BCF   0x03,Carry
	RRF   row,1
	BCF   0x03,Carry
	RRF   row,1
	BCF   0x03,Carry
	RRF   row,1
			;			for (index = 0; index < 255; index++) ; // Delay for awhile to allow for bouncing contacts
	CLRF  index
m006	BCF   0x03,RP0
	BCF   0x03,RP1
	INCF  index,W
	BTFSC 0x03,Zero_
	GOTO  m007
	INCF  index,1
	GOTO  m006
			;			if ((KEYPAD & 0x07) == column)// Make sure key is still pressed.
m007	MOVLW .7
	BCF   0x03,RP0
	BCF   0x03,RP1
	ANDWF KEYPAD,W
	XORWF column,W
	BTFSS 0x03,Zero_
	GOTO  m013
			;			{
			;				//while (KEYPAD & 0x07);	// Wait for key release (not used here)
			;													// Convert from row & column to key number (1-15)
			;				tmpa = 1;						// Assume first column and first row
	MOVLW .1
	MOVWF tmpa
			;				if(row.1)						// If it was in the 2nd row, assume 4th key (first column)
	BTFSS row,1
	GOTO  m008
			;					tmpa = 4;
	MOVLW .4
	MOVWF tmpa
			;				if(row.2)						// If it was in the 2nd row, assume 7th key (first column)
m008	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS row,2
	GOTO  m009
			;					tmpa = 7;
	MOVLW .7
	MOVWF tmpa
			;				if(row.3)						// If it was in the 2nd row, assume 10th key (first column)
m009	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS row,3
	GOTO  m010
			;					tmpa = 10;
	MOVLW .10
	MOVWF tmpa
			;				if(row.4)						// If it was in the 2nd row, assume 13th key (first column)
m010	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS row,4
	GOTO  m011
			;					tmpa = 13;
	MOVLW .13
	MOVWF tmpa
			;				if(column.1)					// If it was in the second column, add one key
m011	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSC column,1
			;					tmpa += 1;
	INCF  tmpa,1
			;				if(column.2)					// If it was in the third column, add two keys
	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS column,2
	GOTO  m012
			;					tmpa += 2;
	MOVLW .2
	ADDWF tmpa,1
			;				TRISB=0xff;						// Set the port to all inputs
m012	MOVLW .255
	BSF   0x03,RP0
	BCF   0x03,RP1
	MOVWF TRISB
			;				return tmpa;					// Return key number
	BCF   0x03,RP0
	MOVF  tmpa,W
	RETURN
			;			}
			;			else									// Key is still bouncing, was released, or was never pressed
			;			{
			;				TRISB=0xff;						// Set the port to all inputs
m013	MOVLW .255
	BSF   0x03,RP0
	BCF   0x03,RP1
	MOVWF TRISB
			;				return 0x00;           		// return no keys pressed
	RETLW .0
			;			}
			;		}
			;		tmpa = tmpa << 1;						// No keys pressed in that row, move one row over
m014	BCF   0x03,Carry
	BCF   0x03,RP0
	BCF   0x03,RP1
	RLF   tmpa,1
			;	}
	GOTO  m005
			;        return 0x00;							// All rows checked out, no keys pressed, exit
m015	RETLW .0
			;} 
			;
			;void beep(uns8 ms)
			;{										// This function emits a short beep of duration ms milliseconds
beep
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF ms_2
			;										// I used to know the frequency, but don't now.
			;	uns8 x,y;						//	x is a temp variable to create a delay between flipping the speaker
			;										// y is a temp variable, it will 'flip' the speaker 2 times each ms
			;	for( ; ms != 0; ms--)		// Count down the number of ms we are supposed to beep
m016	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  ms_2,1
	BTFSC 0x03,Zero_
	GOTO  m023
			;	{
			;		for(y=4; y!=0;y--)		// 'flip' the speaker 4 times (pull on it twice)
	MOVLW .4
	MOVWF y
m017	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  y,1
	BTFSC 0x03,Zero_
	GOTO  m022
			;		{
			;			if(SOUND == 1)			// If the speaker is out, pull it in.
	BTFSS 0x07,SOUND
	GOTO  m018
			;				SOUND = 0;
	BCF   0x07,SOUND
			;			else						// The speaker is in, let it go
	GOTO  m019
			;				SOUND = 1;		
m018	BCF   0x03,RP0
	BCF   0x03,RP1
	BSF   0x07,SOUND
			;			for(x=36;x!=0;x--);	// Delay for about 1/4 ms
m019	MOVLW .36
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF x
m020	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  x,1
	BTFSC 0x03,Zero_
	GOTO  m021
	DECF  x,1
	GOTO  m020
			;		}
m021	BCF   0x03,RP0
	BCF   0x03,RP1
	DECF  y,1
	GOTO  m017
			;	}
m022	BCF   0x03,RP0
	BCF   0x03,RP1
	DECF  ms_2,1
	GOTO  m016
			;	SOUND = 1;						// Let the speaker rest (no current consumption
m023	BCF   0x03,RP0
	BCF   0x03,RP1
	BSF   0x07,SOUND
			;}
	RETURN
			;
			;void main(void)
			;{
main
			;	uns8 x;						// Temporary variable
			;	uns8 Instruction;			// 'Last char recieved was instruction' buffer (should be bit, not byte)
			;
			;	PORTA = 0b.0000.0000; 	// All ports low at start
	BCF   0x03,RP0
	BCF   0x03,RP1
	CLRF  PORTA
			;	PORTB = 0b.0000.0000;
	CLRF  PORTB
			;	PORTC = 0b.0000.0000;
	CLRF  PORTC
			;
			;	TRISA = 0b.1100.1011; 	// 7:6,3,1:0 Input(1), 5:4,2 Output(0) :Thermister,n/a,LCD[RS],n/a,n/a,LCD[EN]
	MOVLW .203
	BSF   0x03,RP0
	MOVWF TRISA
			;	TRISB = 0b.1111.1111; 	// 7:0 Input, no output 					:Keypad[COL0:COL2][ROW0:ROW4]
	MOVLW .255
	MOVWF TRISB
			;	TRISC = 0b.1100.0000; 	// 7:0 Output                  			:LCD[D0:D3], Speaker, n/a,UART[TX:RX]
	MOVLW .192
	MOVWF TRISC
			;
			;	// *** Setup UART ***
			;	SPBRG=25;  					// 25 if bgrh=1, 6 if bgrh=0 when Fosc=4MHz
	MOVLW .25
	MOVWF SPBRG
			;	TXSTA=0x24; 				//	Enable Transmitter, async, 8bit, bgrh = 1
	MOVLW .36
	MOVWF TXSTA
			;	RCSTA=0x90;					// Enable UART, 8bit
	MOVLW .144
	BCF   0x03,RP0
	MOVWF RCSTA
			;
			;	// *** Setup A/D Converter ***
			;	ADCON1=0b.1000.1110; 	// Set PORTA:0 to analog, Right justify A/D results
	MOVLW .142
	BSF   0x03,RP0
	MOVWF ADCON1
			;	ADCON0=0b.1100.0001; 	// Set A/D clock to RC, select PORTA:0 for input to A/D, Turn A/D on
	MOVLW .193
	BCF   0x03,RP0
	MOVWF ADCON0
			;	ADIE=0;						//	Disable Interrupts from A/D
	BSF   0x03,RP0
	BCF   0x0C,ADIE
			;	ADIF=0;						// Clear the A/D Interrupt flag (just a good idea, not needed)
	BCF   0x03,RP0
	BCF   0x0C,ADIF
			;	WFT=0;						// Clear the Waiting for Temp flag
	BCF   0x6E,WFT
			;
			;	// *** Setup LCD ***	
			;	initlcd(); 					// Initialize LCD
	CALL  initlcd
			;	
			;	// *** Send the initialization string to the LCD ***	
			;	RS = 1;     				// Send the following characters to the data register of the LCD
	BCF   0x03,RP0
	BCF   0x03,RP1
	BSF   0x05,RS
			;	for(x=0;x < 16;x++)		// Loop through all 16 characters
	CLRF  x_2
m024	MOVLW .16
	BCF   0x03,RP0
	BCF   0x03,RP1
	SUBWF x_2,W
	BTFSC 0x03,Carry
	GOTO  m025
			;		write8(initmsg(x));	// Write the character to the LCD
	MOVF  x_2,W
	CALL  initmsg
	CALL  write8
	BCF   0x03,RP0
	BCF   0x03,RP1
	INCF  x_2,1
	GOTO  m024
			;
			;	// *** Send the initialization string to the serial interface ***	
			;	for(x=0;x<16;x++)			// Loop through all 16 characters
m025	BCF   0x03,RP0
	BCF   0x03,RP1
	CLRF  x_2
m026	MOVLW .16
	BCF   0x03,RP0
	BCF   0x03,RP1
	SUBWF x_2,W
	BTFSC 0x03,Carry
	GOTO  m028
			;	{
			;		TXREG = initmsg(x);	// Send the next character out
	MOVF  x_2,W
	CALL  initmsg
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF TXREG
			;		while(!TXIF);			// Wait for the character to complete sending
m027	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS 0x0C,TXIF
	GOTO  m027
			;	}				
	BCF   0x03,RP0
	BCF   0x03,RP1
	INCF  x_2,1
	GOTO  m026
			;	
			;//	RS=0;							// Next write to LCD goes to the instruction register
			;//	write8(0x01);				// Clear LCD
			;//	delayms(2);					// Let the LCD clear before we send any other commands
			;//	RS=1;							// Next write to the LCD goes to the data register
			;	
			;	while(1)								// This is the main program loop.  Loop forever.
			;	{
			;		uns8 key, lastkey;			// Buffers for the current key being pressed, and the
			;											// last key which was pressed
			;		PORTC = 0xff;					// Set PORTC.  Why?  I don't know... Probably due to
m028	MOVLW .255
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF PORTC
			;											// the beep routine, and earlier LED signals.
			;
			;		if(WFT)							// There is an analog conversion waiting to be checked
	BTFSS 0x6E,WFT
	GOTO  m029
			;		{
			;			if(!GO)						// The conversion is complete
	BTFSC 0x1F,GO
	GOTO  m029
			;			{
			;					TXREG = ADRESL;	// Send the low byte first
	BSF   0x03,RP0
	MOVF  ADRESL,W
	BCF   0x03,RP0
	MOVWF TXREG
			;					delayms(1);			// 2ms is enough time to send nearly two bytes
	MOVLW .1
	CALL  delayms
			;					TXREG = ADRESH;	// Send the high byte of the conversion
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  ADRESH,W
	MOVWF TXREG
			;					ADIF=0;				// Reset the A/D interrupt
	BCF   0x0C,ADIF
			;					WFT=0;				// Reset the Waiting for Temp flag
	BCF   0x6E,WFT
			;			}
			;		}
			;
			;		if(RCIF)							// A character has been received
m029	BCF   0x03,RP0
	BCF   0x03,RP1
	BTFSS 0x0C,RCIF
	GOTO  m033
			;		{									// We should check here for overrun and framing errors...
			;			uns8 regbuf;				// A place to store the received character
			;			regbuf = RCREG;			// Store the received character in regbuf
	MOVF  RCREG,W
	MOVWF regbuf
			;			if(regbuf == ESCCHAR)	// Character is escape
	MOVF  regbuf,W
	XORLW .27
	BTFSS 0x03,Zero_
	GOTO  m031
			;			{
			;				if(Instruction == 1)	// If the last char was esc, send the temperature
	DECFSZ Instruction,W
	GOTO  m030
			;				{
			;					GO=1;					// Start A/D conversion
	BSF   0x1F,GO
			;					WFT=1;				// Set conversion in progress flag
	BSF   0x6E,WFT
			;					TXREG='T';			// Send conversion in progress signal
	MOVLW .84
	MOVWF TXREG
			;					Instruction = 0;	// Instruction executed, next character is normal
	CLRF  Instruction
			;				}
			;				else
	GOTO  m033
			;				{
			;					Instruction = 1;	// next char is Instruction
m030	MOVLW .1
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF Instruction
			;				}
			;			}
			;			else
	GOTO  m033
			;			{
			;				if(Instruction == 1)	// This char is an instruction(escaped by
m031	BCF   0x03,RP0
	BCF   0x03,RP1
	DECFSZ Instruction,W
	GOTO  m032
			;				{
			;					RS=0;					// Send to instruction register
	BCF   0x05,RS
			;					write8(regbuf);
	MOVF  regbuf,W
	CALL  write8
			;					RS=1;					// Next char to data on LCD
	BCF   0x03,RP0
	BCF   0x03,RP1
	BSF   0x05,RS
			;					Instruction = 0;	// Instruction executed, next character is normal
	CLRF  Instruction
			;				}
			;				else						// Last character was not the escape character
	GOTO  m033
			;				{
			;					write8(regbuf);	// Nothing special, send char to LCD
m032	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  regbuf,W
	CALL  write8
			;				}
			;			}
			;		}
			;		
			;		key = scankp();				// Scan the keypad
m033	CALL  scankp
	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVWF key
			;		if(key != 0)					// There is a key being pressed
	MOVF  key,1
	BTFSC 0x03,Zero_
	GOTO  m034
			;			if(key != lastkey)		// The key being pressed is different than the previous scan
	MOVF  key,W
	XORWF lastkey_2,W
	BTFSC 0x03,Zero_
	GOTO  m034
			;			{
			;				TXREG=key;				// Send key
	MOVF  key,W
	MOVWF TXREG
			;				beep(50);				// Beep to let user know the key was accepted
	MOVLW .50
	CALL  beep
			;			}
			;		lastkey = key;					// If the next scan is the same, we'll ignore it
m034	BCF   0x03,RP0
	BCF   0x03,RP1
	MOVF  key,W
	MOVWF lastkey_2
			;
			;	}
	GOTO  m028
			;}

	ORG 0x2000
	DATA 0000H
	DATA 0000H
	DATA 0000H
	DATA 0001H
	ORG 0x2007
	DATA 3F72H
	END
