/*********************************************************************
 *                    Flowcode One Wire Component Code
 *
 * File: PIC_One_Wire.c
 *
 * (c) 2009 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 240407 | ST | Created
 * 100109 |JCMB| Macro 1W_get_IDByte, oo_get_next_id() modified
 * 250109 |JCMB| CUSTOM_Dummy_Function() rename ONEW_Dummy_Function()
 * 170209 |JCMB| 1W_get_IDByte test (octet>7) added for error
 * 240309 | BR | Moved private functions from AddDefines section
 * 130509 | BR | Added % definitions to DefinesCode section
 * 210709 | BR | Changed Sw 1us Delays to BoostC internal Delay routine
 * 100909 | BR | Added HiTECH compatible functions
 ********************************************************************/

/*********************************************************************

 Return & parameter types:
   void
   char
   short
   char*
   oo_tdata

 Pin directions:
   0 = OUTPUT
   2 = INPUT
   3 = BIDIRECTIONAL

**********************************************************************

[Settings]
CLSID={}
IsAnalogue=0
MultipleAllowed=0
Description=One Wire Flowcode Component

**********************************************************************

[Port]
DesiredPort=0
PortMandatory=0
SamePortAsID=0

[Pins]
Count=1
1=OneWirePin

[PinPort]
# PORTA = 0
# PORTB = 1
# PORTC = 2
# PORTD = 3
# PORTE = 4
1=0

[PinDesiredBit]
1=0

[PinDirection]
# DIR_INPUT = 2
# DIR_OUTPUT = 0
# DIR_BIDIRECTIONAL = 3
1=0

[PinMustUsePort]
# char
1=1

[SamePortAsPinX]
# -1 = any pin
# otherwise, the pin number
1=-1

[PinMustUsePin]
# char
1=1

[PinValue]
# char (0 = off, 1 = on)
1=0

**********************************************************************

[MacroNames]
Count=16
1=oo_crc_shuffle_byte
2=oo_crc_init
3=rx_bit
4=tx_bit
5=oo_get_next_id
6=oo_busreset
7=oo_get_pad_byte
8=oo_tx_byte
9=oo_rx_byte
10=oo_scanbus
11=oo_get_devicecount
12=oo_read_device
13=oo_get_IDByte
14=DS1820_start_conversion
15=DS1820_read_scratchpad
16=DS1820_get_temp

[MacroReturns]
1=void
2=void
3=char
4=void
5=char
6=char
7=char
8=void
9=char
10=char
11=char
12=char
13=char
14=char
15=char
16=short

[MacroIsPrivate]
1=1
2=1
3=1
4=1
5=1
6=0
7=0
8=0
9=0
10=0
11=0
12=0
13=0
14=0
15=0
16=0


[MacroParameters_oo_crc_shuffle_byte]
Count=1
1=input

[MacroParamTypes_oo_crc_shuffle_byte]
1=char

[MacroParameters_oo_crc_init]
Count=0

[MacroParamTypes_oo_crc_init]


[MacroParameters_rx_bit]
Count=0

[MacroParamTypes_rx_bit]


[MacroParameters_tx_bit]
Count=1
1=out

[MacroParamTypes_tx_bit]
1=char

[MacroParameters_oo_get_next_id]
Count=0

[MacroParamTypes_oo_get_next_id]


[MacroParameters_oo_busreset]
Count=0

[MacroParamTypes_oo_busreset]


[MacroParameters_oo_get_pad_byte]
Count=1
1=index

[MacroParamTypes_oo_get_pad_byte]
1=char

[MacroParameters_oo_tx_byte]
Count=1
1=data

[MacroParamTypes_oo_tx_byte]
1=char

[MacroParameters_oo_rx_byte]
Count=0

[MacroParamTypes_oo_rx_byte]


[MacroParameters_oo_scanbus]
Count=0

[MacroParamTypes_oo_scanbus]


[MacroParameters_oo_get_devicecount]
Count=0

[MacroParamTypes_oo_get_devicecount]


[MacroParameters_oo_read_device]
Count=1
1=count

[MacroParamTypes_oo_read_device]
1=char

[MacroParameters_oo_get_IDByte]
Count=2
1=device
2=octet

[MacroParamTypes_oo_get_IDByte]
1=char
2=char

[MacroParameters_DS1820_start_conversion]
Count=0

[MacroParamTypes_DS1820_start_conversion]


[MacroParameters_DS1820_read_scratchpad]
Count=0

[MacroParamTypes_DS1820_read_scratchpad]


[MacroParameters_DS1820_get_temp]
Count=0

[MacroParamTypes_DS1820_get_temp]


 ********************************************************************/

/********************************************************************
 * ADDITIONAL CODE
 ********************************************************************/

/*DefinesCode_Start*/

/**** Macro Substitutions ****
%a = CRC Check Enable (0-Off / 1-On)
%b = One Wire Port Register
%c = One Wire Data Direction Register
%d = One Wire Pin
%e = Clock Cycles For A 1us Delay
******************************/

#define CRC_CHECKING  	%a
#define OO_PORT  		%b
#define OO_TRIS  		%c
#define OO_PIN  		%d

//Global Variables

char oo_scratchpad[9];
// Scratchpad contents
// 0	Temperature LSB
// 1	Temperature MSB
// 2	Hi alarm temperature
// 3	Lo alarm temperature
// 4	Reserved, 0xFF
// 5	Reserved, 0xFF
// 6	Remainder register
// 7	Nr of counts per degree
// 8	CRC of pad contents


// Commands for the OO
//    1. ROM function commands
#define        OO_READROM        	0x33
#define        OO_MATCHROM       	0x55
#define        OO_SKIPROM        	0xCC
#define        OO_SEARCHROM      	0xF0
#define        OO_ALARMSEARCH    	0xEC
//    2. Memory Command Functions
#define        OO_WRITEPAD       	0x4E
#define        OO_READPAD        	0xBE
#define        OO_COPYPAD        	0x48
#define        OO_CONVERTT       	0x44
#define        OO_RECALLE2			0xB8
#define        OO_READSUPPLY		0xB4


//I/O for the OO
#define Float_OO {set_bit(OO_TRIS, OO_PIN);}
#define Clear_OO {clear_bit(OO_TRIS, OO_PIN);	clear_bit(OO_PORT, OO_PIN);}


char oo_get_next_id();
void tx_bit(char out);
char rx_bit();

// CRC working variable
char crc = 0;

//CRC for the OO
#if CRC_CHECKING == 1

	// CRC lookup table
	#ifdef _BOOSTC
		rom char* crc_rom = {0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
			157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
			35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
			190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
			70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
			219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
			101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
			248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
			140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
			17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
			175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
			50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
			202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
			87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
			233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
			116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
	#endif

	#ifdef HI_TECH_C
		const char crc_rom[] = {0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
			157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
			35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
			190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
			70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
			219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
			101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
			248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
			140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
			17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
			175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
			50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
			202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
			87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
			233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
			116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
	#endif

#endif


// Internal variables
char        id[8];
signed char conflict;
char        new_conflict;


//Device ID Variables
char num_devices = 0;
char DevID[64] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
						0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * FUNCTIONS
 ********************************************************************/

////////////////////////////////////////////////////////////
// oo_get_next_id()
// Helper function for the scanbus option. Gets the next
// id on the bus.
////////////////////////////////////////////////////////////
char oo_get_next_id()
{
/*Macro_oo_get_next_id_Start*/
	char val0 = 0;
	char val1 = 0;
	char counter    = 0;
	char bit_index  = 0;
	char byte_index = 0;
	//char current_conflict = -1;

	//added JCMB 10/01/09
	char lz_selected = 0;
	char go_on = 0;
	char bit_test;

	new_conflict = 0;

	if ( oo_busreset() )	// Reset the bus
	{
		return 1; // -> error
	}
	// Issue the search ROM command
	oo_tx_byte(OO_SEARCHROM);

	// Start the search for the sensor
	for (byte_index = 0; byte_index < 8; byte_index++)
	{
		char data_in_byte = 0;
		for (bit_index = 0; bit_index < 8; bit_index++)
		{
			// Read 2 consecutive bits from the One Wire bus
			val0 = rx_bit();						//Test Input
			val1 = rx_bit();						//Test Input

			// Evaluate the result
			if ((val0 == 0) && (val1 == 0))
			{
				//current_conflict = counter;
				// if conflict occurs earlier than the previous conflict, then use the previous value
				if (counter < conflict)
				{
					// use previous value
					bit_test = id[byte_index] >> bit_index;		//added JCMB 10/01/09
					if (bit_test & 0x01)
					{
						val0 = 1;
					}
					else
					{
						val0 = 0;
						lz_selected = counter;				//added JCMB 10/01/09
						go_on = 1;							//added JCMB 10/01/09
					}
				}
				else if (counter == conflict)
				{
					// use 1
					val0 = 1;
				}
				else
				{
					// use zero on new conflicts
					val0 = 0;
					conflict = counter;
					new_conflict = 1;
				}
			}
			else if (val0 && val1) // 1 et 1 impossible
			{
				return 2;
			}
			// Store the bit in the ID array
			data_in_byte = data_in_byte >> 1;
			if (val0)
			{
				data_in_byte |= 0x80;
			}

			tx_bit(val0);

			counter++;
		}
		id[byte_index] = data_in_byte;
	}

        //added JCMB 10/01/09
	if ((new_conflict == 0) && go_on)
	{
		new_conflict = 1;
		conflict = lz_selected ;
	}

	// Verify ID CRC
	#if CRC_CHECKING == 1
		oo_crc_init();
	#endif

	for (byte_index = 0; byte_index < 8; byte_index++)
	{
		#if CRC_CHECKING == 1
				oo_crc_shuffle_byte(id[byte_index]);
		#endif
	}
	// Bail on CRC errors
#if CRC_CHECKING == 1
	if (crc) return crc;
#endif
	return 0;
/*Macro_oo_get_next_id_End*/
}


void tx_bit(char out)
{
/*Macro_tx_bit_Start*/
	char count;
	Clear_OO;							//Clear Output Pin
	delay_us(1);						//Delay 1us
	if (out & 0x01)
		Float_OO;						//Float Output Pin
	delay_us(60);						//Delay 60us
	Float_OO;							//Float Output Pin
	delay_us(10);						//Delay 10us
/*Macro_tx_bit_End*/
}


char rx_bit()
{
/*Macro_rx_bit_Start*/
	char oo_bit, count;
	Clear_OO;							//Clear Output Pin
	delay_us(1);						//Delay 1us
	Float_OO;							//Float Output Pin
	delay_us(10);						//Delay 10us
	oo_bit = test_bit(OO_PORT, OO_PIN);	//Test Input
	delay_us(50);						//Delay 50us
	return oo_bit;
/*Macro_rx_bit_End*/
}



////////////////////////////////////////////////////////////
// oo_crc_init()
// Initialise the CRC working register to be able to
// start a new calculation
////////////////////////////////////////////////////////////
void oo_crc_init()
{
/*Macro_oo_crc_init_Start*/
	#if CRC_CHECKING == 1
		crc = 0;
	#endif
/*Macro_oo_crc_init_End*/
}



////////////////////////////////////////////////////////////
// oo_crc_shuffle_byte()
//
// Shuffle the next byte into the CRC
////////////////////////////////////////////////////////////
void oo_crc_shuffle_byte(char input)
{
/*Macro_oo_crc_shuffle_byte_Start*/
	#if CRC_CHECKING == 1
		crc = crc_rom[crc ^ input];
	#endif
/*Macro_oo_crc_shuffle_byte_End*/
}



////////////////////////////////////////////////////////////
// oo_busreset()
//
// Issues a 'ping' on the bus. If there is at least one
// sensor on the bus, it will generate a presence pulse.
// Returns: 0 if a presence pulse was detected
//          1 if no device was detected
////////////////////////////////////////////////////////////
char oo_busreset()
{
/*Macro_oo_busreset_Start*/
	Float_OO; 						// Release bus
	Clear_OO;						// Send the reset pulse
	delay_us(200);					// Wait for 600 µs, this is the reset pulse
	delay_us(200);
	delay_us(200);
	Float_OO; 						// Release bus
	delay_us(60);					// Wait 60 us (release) let device drive the bus
	if (test_bit(OO_PORT, OO_PIN) == 1)	// Now sample, if there is a sensor on the bus, the line should be low
		return 1; 					// <<-error
	delay_us(140);					// Wait another 540 us to complete the reset sequence
	delay_us(200);
	delay_us(200);
	return 0;
/*Macro_oo_busreset_End*/
}



////////////////////////////////////////////////////////////
// char oo_get_pad_byte(char index)
// Returns the data from a byte in the last read scratchpad
////////////////////////////////////////////////////////////
char oo_get_pad_byte(char index)
{
/*Macro_oo_get_pad_byte_Start*/
	return oo_scratchpad[index];
/*Macro_oo_get_pad_byte_End*/
}



////////////////////////////////////////////////////////////
// oo_tx_byte(char data)
// Transmits a single byte to the bus
////////////////////////////////////////////////////////////
void oo_tx_byte(char data)
{
/*Macro_oo_tx_byte_Start*/
	char counter = 0;
	while (counter < 8)
	{
		tx_bit(data);
		data = data >> 1;				//Rotate to next bit of data
		counter++;						//Increment Counter
	}
/*Macro_oo_tx_byte_End*/
}



////////////////////////////////////////////////////////////
// char oo_rx_byte()
// Receives a single byte from the bus
////////////////////////////////////////////////////////////
char oo_rx_byte()
{
/*Macro_oo_rx_byte_Start*/
	char counter = 0;
	char data    = 0;
	char oo_bit  = 0;
	while (counter < 8)
	{
		oo_bit = rx_bit();
		data = data >> 1;					//Shift incoming data to next bit
		if (oo_bit > 0)
		{
			data = data | 0x80;				//Append incoming bit to data byte
		}
		counter++;							//Increment Counter
	}
	#ifdef OO_CRC_CHECKING
		oo_crc_shuffle_byte(data);			//Check CRC
	#endif
	return data;
/*Macro_oo_rx_byte_End*/
}



////////////////////////////////////////////////////////////
// oo_scanbus()
// Scan the bus to detect all devices
////////////////////////////////////////////////////////////
char oo_scanbus(void)
{
/*Macro_oo_scanbus_Start*/
	char retval = 0;
	char device_count = 0;
	char loper;
	conflict = -1;
	new_conflict = 1;
	// Reset the bus, wake up devices.
	retval = oo_busreset();
	if (retval == 1)
	{
		return 255; // -> error
	}
	// new_conflict gets updated in the oo_get_next_id() function.
	while (new_conflict)
	{
		retval = oo_get_next_id();
		// Bail in case of errors
		if (retval) return retval;
		// Add the device id to EEPROM
		for (loper=0; loper < 8; loper++)
		{
			DevID[loper+(device_count<<3)] = id[loper];
		}
		device_count++;
	}
	// Write number of devices to the EEPROM
	num_devices = device_count;
	return 0;
/*Macro_oo_scanbus_End*/
}



////////////////////////////////////////////////////////////
// char oo_get_devicecount()
// Returns the number of detected devices
////////////////////////////////////////////////////////////
char oo_get_devicecount()
{
/*Macro_oo_get_devicecount_Start*/
	return num_devices;
/*Macro_oo_get_devicecount_End*/
}



////////////////////////////////////////////////////////////
// char oo_read_device()
// Reads the temperature of the device @ location 'count'
// in the DevID array
////////////////////////////////////////////////////////////
char oo_read_device(char count)
{
/*Macro_oo_read_device_Start*/
	char loper = 0;
	char counter = 0;
	char temp;
	short value;
	oo_busreset();
	oo_tx_byte(OO_MATCHROM);
	for (loper=0; loper < 8; loper++)
	{
		id[loper] = DevID[loper+(count<<3)];
		oo_tx_byte(id[loper]);
	}
	oo_tx_byte(OO_READPAD);
	#if CRC_CHECKING == 1
		oo_crc_init();			//Reset the CRC register, CRC is updated in the oo_rx_byte() function.
	#endif
	while (counter < 9)
	{
		temp = oo_rx_byte();
		oo_scratchpad[counter] = temp;
		counter++;
	}
	#if CRC_CHECKING == 1
		return crc;				//Verify the CRC
	#endif
	return 0;
/*Macro_oo_read_device_End*/
}



////////////////////////////////////////////////////////////
// added JCMB 10/01/09
// Returns byte octet of the 64-Bit Lasered ROM Code, 255 on error
////////////////////////////////////////////////////////////
char oo_get_IDByte(char device, octet)
{
/*Macro_oo_get_IDByte_Start*/
	char retval = 255;
	if ((device >= num_devices) | (octet > 7))
	{
		return retval ; //error
	}
        retval = DevID[octet+(device<<3)];
	return retval ;
/*Macro_oo_get_IDByte_End*/
}


////////////////////////////////////////////////////////////
// DS1820_start_conversion()
// DS1820 specific
// Commands all sensors to start a temperature conversion
////////////////////////////////////////////////////////////
char DS1820_start_conversion()
{
/*Macro_DS1820_start_conversion_Start*/
	char in = 0;
	char counter = 0;
	oo_busreset();
	oo_tx_byte(OO_SKIPROM);		// Command all temp sensors on the bus to start a conversion
	oo_tx_byte(OO_CONVERTT);	// Convert temperature
	while (in == 0)
	{
		in = oo_rx_byte();
		delay_ms(4);
		counter++;
		if (counter == 0xFF)		// Security: if the conversion is not completed
			return 1;				// after > 1 sec -> break.
	}
	return 0;
/*Macro_DS1820_start_conversion_End*/
}



////////////////////////////////////////////////////////////
// char DS1820_read_scratchpad()
// Reads the scratchpad of the currently selected device
////////////////////////////////////////////////////////////
char DS1820_read_scratchpad()
{
/*Macro_DS1820_read_scratchpad_Start*/
	char temp;
	char counter = 0;
	if ( oo_busreset() )
		return (1);
	oo_tx_byte(OO_SKIPROM);		//Command all temp sensors on the bus to start a conversion
	oo_tx_byte(OO_READPAD);		//Convert temperature
	#if CRC_CHECKING == 1
		oo_crc_init();			//Reset the CRC register, CRC is updated in the oo_rx_byte() function.
	#endif
	while (counter < 9)
	{
		temp = oo_rx_byte();
		oo_scratchpad[counter] = temp;
		counter++;
	}
	#if CRC_CHECKING == 1
		return crc;				//Verify the CRC
	#endif
	return 0;
/*Macro_DS1820_read_scratchpad_End*/
}



////////////////////////////////////////////////////////////
// short DS1820_get_temp()
// DS1820 specific
// Returns the 2-byte value of the temperature register
////////////////////////////////////////////////////////////
short DS1820_get_temp()
{
/*Macro_DS1820_get_temp_Start*/
	short retval;
	retval = oo_scratchpad[1];
	retval = retval << 8;
	retval = retval | oo_scratchpad[0];
	return retval;
/*Macro_DS1820_get_temp_End*/
}









