' ************** TemperatureSensor.bas **************

'     This program runs on a PICAXE-20X2 at 4MHz which reads the temperature from a 
'	DS18B20 temperature sensor & sends it to an HD44780 compatible 16x2 LCD display.
'	
'	Developed by Simon Carter March 10, 2013.

' *** Constants ***
	symbol EnablePin = C.7					' LCD Enable pin connected to C.7
	symbol RegSelPin = C.4					' LCD Register Selelect pin connected to C.4
	symbol TempPin   = C.1					' Temperature sensor data connected to C.1
' *** Variables ***
	symbol  	char =  b0					' character to be sent to LCD
	symbol 	index = b1					' used as counter in For-Next loops
	symbol 	degc  = b2					' the temperature value received from the DS18B20 sensor
	symbol 	intgval=b3					' used to temporarily hold each integer value extracted from the number received from the sensor
	symbol    degflag = b4					' a flag used when dealing with negative temperature ranges. 0 = Postive range, 1 = Negative range
	symbol 	 degf = b5					' used for holding degrees farenheight values
' *** Directives ***
	#com 3							' specify download port
	#picaxe 20X2						' specify processor
	#no_data							' save time downloading
	#terminal off						' disable terminal window
	
' *** Table ***
	Table  0, ("The Temperature ")
	
' *** Main Program ***
 	dirsB = %11111111						' set all portB pins as outputs
 	dirsC = %10111001						' set  C.6 and C.2, C.1 as inputs
 	pullup  %00000010						' enable C.6 internal pullup resistor	
 	
' *** Initialize the LCD ***								 
	pause 200							' pause 200 mS for LCD initialization as per HD44780 specs
	char = 56							' setup for 8-bits, 2 lines & 5X8 display
 	gosub CmdLCD						' send instruction to LCD
	char = 12							' display on, cursor off
	gosub CmdLCD						' send instruction to LCD		
 	char = 1							' clear display,go home to line 1 of LCD display	
 	gosub CmdLCD						' send instruction to LCD
	wait 1
	
' *** Send text - "Temperature"to line 1 of the LCD ***	
 	for index = 0 to 15
 	readtable index, char					' read text characters in the Table
 	gosub TxtLCD						' send text in the Table to LCD
 	next index
 	
' *** Main loop - read DS18B20 sensor ***
do 	
 
  	char = 194							' move cursor to the start of line two	
 	gosub CmdLCD						' send the instruction to LCD 		
  	readtemp TempPin, degc					' read the temperature value received from the DS18B20 sensor on pin C1.0
 	pause 800							' pause >750 mS for sensor as per DS18B20 specs
' 	degc = 24 							  insert temperature test values here to check code function
 	degflag = 0							' reset the flag to 0 i.e. assume positive temperature range to start with
 	gosub BelowZeroC						' check for below zero temperatures						
 	gosub IntgOnly						' extract 10's and 1's integers from DS18B20 data
 	gosub DegCsign    					' generate deg C sign
 	gosub CheckFlag						' check if dealing with temperatures in the minus range and adjust degc value
 	gosub BelowZeroF						' check for below zero temperatures	
 	gosub DegFsign						' check for below zero temperatures	
									' generate deg F sign 	
loop
	
' *** Subroutines ***

CmdLCD:
	low RegSelPin						' set up LCD for a command byte
	goto LoadLCD								

TxtLCD:								' set up LCD for text byte
	high RegSelPin						

LoadLCD:								; execute loading byte into LCD
	outpinsB = char						' load byte onto outpinsB
	pulsout EnablePin,1					' load bytes onto LCD
	return				

LoadIntgLCD:							' execute loading temperature text byte that has been converted to an integer						
	high RegSelPin						' set up LCD for text byte
	outpinsB = intgval					' load byte onto outpinsB
	pulsout EnablePin,1					' execute loading byte into LCD				
	return
					
IntgOnly:								' extract 100's, 10's and 1's integers from DS18B20 data
	for index = 2 to 0 step -1				' set index to extract 100's integer first then 10's integer then 1's 
	let intgval = degc dig index				' Use DIG function to extract integers

	
	     
	     if intgval = 0 and index =2 then let intgval =%00100000	'Blank any leading "0" on display	
	else if intgval = 0 then let intgval =%00110000	' Convert integers to LCD character codes
	else if intgval = 1 then let intgval =%00110001
	else if intgval = 2 then let intgval =%00110010
	else if intgval = 3 then let intgval =%00110011
	else if intgval = 4 then let intgval =%00110100
	else if intgval = 5 then let intgval =%00110101
	else if intgval = 6 then let intgval =%00110110
	else if intgval = 7 then let intgval =%00110111
	else if intgval = 8 then let intgval =%00111000
	else if intgval = 9 then let intgval =%00111001
	     
	endif
	     
	gosub LoadIntgLCD						' execute loading temperature text byte that has been converted to an integer	
	next index
	return

DegCsign:								' create Degrees C text on display
	intgval =%11011111					' set character to be sent to LCD to "Degree" Character Code
	gosub LoadIntgLCD						' send characters to LCD
	
	intgval =%01000011					' set character to be sent to LCD to "C" Character Code for Centigrade
	gosub LoadIntgLCD						' send characters to LCD

	intgval =%00100000					' set character to be sent to LCD to " " Character Code for a space before the farenheight value
	gosub LoadIntgLCD						' send characters to LCD
	return

DegFsign:								' create Degrees F text on display
	intgval =%11011111					' set character to be sent to LCD to "Degree" Character Code
	gosub LoadIntgLCD						' send characters to LCD
	
	intgval =%01000110					' set character to be sent to LCD to "F" Character Code for Farenheight
	gosub LoadIntgLCD						' send characters to LCD
	return
	
	intgval =%00100000					' set character to be sent to LCD to " " Character Code for a space after farenheight value to clear when minus sign used
	gosub LoadIntgLCD						' send characters to LCD
	
	intgval =%00100000					' set character to be sent to LCD to " " Character Code for a space after farenheight value to clear when intgval>100 used
	gosub LoadIntgLCD						' send characters to LCD


DegFcalc:								' derive Farenheight value for positive Farenheight readings
	degc=degc*9/5+32						' calculate Farenheight value from Centigrade value
	gosub IntgOnly						' begin process to extract 100's, 10's and 1's integers for Farenheight value
	debug
	return

DegFcalcPos:							' derive Farenheight value for positive Farenheight readings when celcius is negative
	degc=degc*9/5						' calculate Farenheight value from Centigrade value
	degc=32-degc						' calculate Farenheight value from Centigrade value
	gosub IntgOnly						' begin process to extract 100's, 10's and 1's integers for Farenheight value
	return

DegFcalcNeg:							' derive Farenheight value for negative Farenheight readings
	degc=degc*9/5-32						' calculate Farenheight value from Centigrade value
	gosub IntgOnly						' begin process to extract 100's, 10's and 1's integers for Farenheight value
	return

MinusSign:
	intgval ="-"						' set character to be sent to LCD to "minus sign" Character Code
	gosub LoadIntgLCD
	return
	
BelowZeroC:								' check for below zero deg C
	select case degc
	case 0 to 125						' ignore this case - temperature in the normal positive range
	
	case 129 to 183						' the case where celsius is in the minus range send a minus sign character to LCD						
	degc=degc-128						' correct for the DSDS18B20 setting MSB to "1" or 128 for minus temperature condition
	degflag = 1							' set flag indicating negative temperature condition
	gosub MinusSign						' the case where celsius is in the minus range send a minus sign character to LCD
	endselect
	return

BelowZeroF:
	select case degc
	case 0 to 124						' ignore this case - temperature in the normal positive range
	gosub DegFcalc

	case 129 to 146						' the case where only celsius is in the minus range	      					
	degc=degc-128						' correct for the DSDS18B20 setting MSB to "1" or 128 for minus temperature conditio
	gosub DegFcalcPos

	case 147 to 183    					' the case where farenheight is in the minus range send a minus sign character to LCD
	degc=degc-128	      				' correct for the DSDS18B20 setting MSB to "1" or 128 for minus temperature condition
	gosub MinusSign						' the case where farenheight is in the minus range send a minus sign character to LCD
	gosub DegFcalcNeg
	endselect
	return

CheckFlag:
	if degflag = 1 then let degc = degc+128		' Reset the correction for the DSDS18B20 setting MSB to "1" or 128 for minus temperature condition
 	endif
 	return