#include <hidef.h>      /* common defines and macros */
#include <mc9s12c128.h>     /* derivative information */
#include "lcd_subroutines.h"
#pragma LINK_INFO DERIVATIVE "mc9s12c128"

//DS18S20 (Dallas Semiconductor 1-wire Bus Temperature Sensor) Interfacing Example
//9S12C332 pins used: LCD Display: PTT7:2, Temp Sensor: PTM0.
//This example works for any LCD Module made by Optrex, Hitachi, etc.
//This example is based on information in the DS18S20 datasheet 
//and Dallas Semiconductor App Note #162 "Interfacing the DS18x20 1-wire temp
//sensor in a microcontroller environment"
//Chip Type: 9S12C128
//Bus Clock Frequency: 24 MHz
//Written by KEH on 10/28/2007
  #define DQ PTM_PTM3       //Use PTM3 as the one-wire bus line, define it as "DQ"
  #define DQDDR DDRM_DDRM3  //Define "DQDDR" as DDRM bit #3, which controls state of DQ.
                            //Throughout this program, we shall keep DQ set to 0,
                            // and thus if DQDDR = 0 => DQ line floats
                            // (The DQ line is quickly pulled high through a 4.7kohm pullup resistor.)
                            // But if DQDDR = 1, => DQ line is quickly pulled LOW.
  void INIT_PLL(void);
	unsigned char one_wire_reset(void);
	void delay6us(unsigned int);
	void write_byte_one_wire(char);
	unsigned char read_byte_one_wire(void);
	void write_bit_one_wire(char);
	unsigned char read_bit_one_wire(void);
	char lschar,middlechar,mschar,fractchar;
	int temp;
	char scratchdat[10],msbtemp,lsbtemp;
	void main(void)
{		
	unsigned char j;
	INIT_PLL();
	LCD_INIT();
	for(;;) {	  
  DQDDR = 0;	//DQ is pulled high through 4.7 kilohm external pullup resistor.
  while(one_wire_reset());		 //Hang here if 1-wire sensor not present
	write_byte_one_wire(0xcc);	//skip ROM Command
	                            //(Only allowed when there is only 1 device on bus)
	write_byte_one_wire(0x44);	//Start Conversion
	delay6us(18);
	while(one_wire_reset());		//Hang here if 1-wire sensor not present
	write_byte_one_wire(0xcc);	//Skip ROM Command 
	write_byte_one_wire(0xBE);	//Read Scratch Pad inside Temp Sensor
	lsbtemp = read_byte_one_wire();	 //First two bytes from scratchpad hold Centigrade Temp.
	msbtemp = read_byte_one_wire();
	for(j=0;j<7;j++)						//Read the rest of the scratchpad, even though we
		scratchdat[j] = read_byte_one_wire(); //will do nothing with it.
	temp = lsbtemp + (msbtemp<<8); //Variable "temp" holds temperature in 0.5 deg C units
	if (temp & 1 == 1) {
	  fractchar = '5';
	}															//Look at LSB of "temp" to determine fractional part
	else {															//(either 0.5 deg C or 0.0 deg C.)
	  fractchar = '0'; 
	}
	temp = temp>>1;											//Now integer in "temp" is in degrees C
	lschar = temp%10 + 0x30;						//Decompose "temp" into three decimal ASCII digits
	temp = temp/10;
	middlechar = temp%10 + 0x30;
	temp = temp/10;
	mschar = temp%10 + 0x30;	
	LCD_ADDRESS(0);											//Home the LCD panel display.
	LCD_DTA(mschar);										//Display integer part of temp
	LCD_DTA(middlechar);
	LCD_DTA(lschar);
	LCD_DTA('.');												//Insert decimal point
	LCD_DTA(fractchar);									//Display fractional part (0.0 or 0.5 deg C)
	delay6us(30000);										//Wait about 0.2 seconds between temperature samples
	}
}

void delay6us(unsigned int nr6us)			//Wait for nr of 6us intervals in argument
{	unsigned int i,j;
	for (i = 0; i < nr6us; i++)
		{
			for(j=0;j<22;j++);
		}
}

unsigned char one_wire_reset(void)		//Begin each transfer sequence with one_wire_reset
{	unsigned char presence;
	DQ = 0;
	DQDDR = 1;	//Pull DQ line low
	delay6us(80);	//Wait for 480 US
	DQDDR = 0;	//Allow DQ to be pulled high
	delay6us(12);	//Wait for 70 US
	presence = DQ;	//Read state of DQ 
			//(hopefully presence pulse being sent by temp sensor!)
	delay6us(68);	//Wait 410 US for presence pulse to finish.
	return(presence);	
}

unsigned char read_bit_one_wire(void)	 //Read one bit
{	unsigned char i;
	DQ = 0;
	DQDDR = 1;	//Pull DQ low to start timeslot
	DQDDR = 0;	//Then let DQ line be pulled high.
	delay6us(2);	//delay 15 us from start of timeslot
	i = DQ;
	return(i);		//return value of DQ line (as set by temp sens)
}

void write_bit_one_wire(char bitval)	 //Write one bit
{	DQ = 0;
	DQDDR = 1;		//Pull DQ low to start timeslot
	if(bitval == 1) DQDDR = 0; 	//Let DQ go high to write a 1
	delay6us(18);	//delay 108 us
	DQDDR = 0;		//Let DQ line go high to end cycle
}

unsigned char read_byte_one_wire(void)  //Read a byte from 1-wire device
{
	unsigned char i;
	unsigned char value = 0;
	
	for(i=0;i<8;i++)
		{
		  if(read_bit_one_wire()) value=value | 1<<i;    //Read byte in one bit at a time
		  delay6us(18);						  				            //Wait for rest of timeslot
		}
	return(value);
}

void write_byte_one_wire(char val)			//Write a byte to the 1-wire device
{
	unsigned char i;
	unsigned char temp;

	for(i=0;i<8;i++)			//Write byte, one bit at a time
		{
		  temp = val>>i;		//Shift ith bit into LSB position
		  temp = temp & 1;		//Mask out LSB bit value
		  write_bit_one_wire(temp);	//Write it to temp sensor
		}
	delay6us(18);
}