//Author: LabJack
//July 12, 2007
//Example UE9 helper class and calibration structure
using System;
using System.Runtime.InteropServices;

namespace LabJack
{
	public struct U3_CALIBRATION_INFORMATION
	{

		public double []unipolarSlope;
		public double []unipolarOffset;
		public double bipolarSlope;
		public double bipolarOffset;
		public double []DACSlope;
		public double []DACOffset;
		public double tempSlope;
		public double tempSlopeLow;
		public double calTemp;
		public double Vref;
		public double VrefDiv2;
		public double VsSlope;
		public double hiResUnipolarSlope;
		public double hiResUnipolarOffset;
		public double hiResBipolarSlope;
		public double hiResBipolarOffset;

		public void init()
		{
			bipolarSlope = 0;
			bipolarOffset = 0;
			tempSlope = 0;
			tempSlopeLow = 0;
			calTemp = 0;
			Vref = 0;
			VrefDiv2 = 0;
			VsSlope = 0;
			hiResUnipolarSlope = 0;
			hiResUnipolarOffset = 0;
			hiResBipolarSlope = 0;
			hiResBipolarOffset = 0;
			unipolarSlope = new double[4];
			unipolarOffset = new double[4];
			DACSlope = new double[2];
			DACOffset = new double[2];
		
			for(int i =0; i < 4; i++)
			{
				unipolarSlope[i] = 0;
				unipolarOffset[i] = 0;
				if(i < 2)
				{
					DACSlope[i] = 0;
					DACOffset[i] = 0;
				}
			}
		}

	}

	public class UE9
	{
		[DllImport("labjackusb", EntryPoint = "LJUSB_OpenDevice", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern UInt32 LJUSB_OpenDevice(uint DevNum, uint dwReserved, uint ProductID);
		
		[DllImport("labjackusb", EntryPoint = "LJUSB_BulkRead", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern uint LJUSB_BulkRead(UInt32 hDevice, uint Pipe, [In, Out] byte[] pBuff, uint Count);
		
		[DllImport("labjackusb", EntryPoint = "LJUSB_BulkWrite", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern uint LJUSB_BulkWrite(UInt32 hDevice, uint Pipe, [In, Out] byte[] pBuff, uint Count);

		[DllImport("labjackusb", EntryPoint = "LJUSB_CloseDevice", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern void LJUSB_CloseDevice(UInt32 hDevice);

		[DllImport("labjackusb", EntryPoint = "LJUSB_GetDevCount", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern uint LJUSB_GetDevCount(uint ProductID);
		
		[DllImport("labjackusb", EntryPoint = "LJUSB_AbortPipe", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern bool LJUSB_AbortPipe(UInt32 hDevice, uint Pipe);

		public const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;
		public const uint UE9_PRODUCT_ID	= 9;
		public const uint UE9_MAX_DEVICES	= 9;
		public const uint UE9_PIPE_EP1_OUT  = 0;	
		public const uint UE9_PIPE_EP1_IN	= 1;	
		public const uint UE9_PIPE_EP2_OUT  = 2;	
		public const uint UE9_PIPE_EP2_IN	= 3;

		public U3_CALIBRATION_INFORMATION caliInfo;

		/// <summary>
		///  This should be set when there is an errorcode in the response buffer.
		///  This is not set by this class on its own.
		/// </summary>
		public int errorcode = 0;

		/// <summary>
		///  This is set by the openUSBConnection function.
		/// </summary>
		public UInt32 handle;
		
		
		/// <summary>
		///  Constructor
		/// </summary>
		public UE9() 
		{
			caliInfo.init();
		}

		/// <summary>
		/// Adds checksum to a data packet for normal command format.
		/// </summary>
		/// <param name="b">Data packet array for normal command.</param>
		/// <param name="n">Size of data packet.</param>
		public static void normalChecksum(ref byte []b, int n)
		{
			b[0] = UE9.normalChecksum8(b,n);
		}


		/// <summary>
		/// Adds checksum to a data packet for extended command format.
		/// </summary>
		/// <param name="b">Data packet array for extended command.</param>
		/// <param name="n">Size of data packet.</param>
		public static void extendedChecksum(ref byte []b, int n)
		{
			ushort a;

			a = UE9.extendedChecksum16(b,n);
			b[4] = (byte)(a & 0xff);
			b[5] = (byte)((a / 256) & 0xff);
			b[0] = UE9.extendedChecksum8(b);
		}


		/// <summary>
		/// Calculates the Checksum8 for a normal command data packet.
		/// </summary>
		/// <param name="b">Data packet array for normal command.</param>
		/// <param name="n">Size of data packet.</param>
		/// <returns>The Checksum8 for a normal command data packet.</returns>
		public static byte normalChecksum8(byte []b, int n)
		{
			int i;
			ushort a, bb;
  
			//Sums bytes 1 to n-1 unsigned to a 2 byte value. Sums quotient and
			//remainder of 256 division.  Again, sums quotient and remainder of
			//256 division.
			for(i = 1, a = 0; i < n; i++) 
				a += (ushort)b[i];

			bb = (ushort)(a/256);
			a = (ushort)((a-256*bb)+bb);
			bb = (ushort)(a/256);

			return ((byte)((a-256*bb)+bb));
		}


		/// <summary>
		/// Calculates the Checksum16 for a extended command data packet.
		/// </summary>
		/// <param name="b">Data packet array for extended command.</param>
		/// <param name="n">Size of data packet.</param>
		/// <returns>Returns the Checksum16 for a extended command data packet.</returns>
		public static ushort extendedChecksum16(byte []b, int n)
		{
			int i;
			ushort a;

			//Sums bytes 6 to n-1 to a unsigned 2 byte value
			for(i = 6, a = 0; i < n; i++)
				a += (ushort)b[i];

			return a;
		}

		/// <summary>
		/// Calculates the Checksum8 for a extended command data packet.
		/// </summary>
		/// <param name="b">Data packet array for extended command.</param>
		/// <returns>The Checksum8 for a extended command data packet.</returns>
		public static byte extendedChecksum8(byte []b)
		{
			uint i, a, bb;

			//Sums bytes 1 to 5. Sums quotient and remainder of 256 division. Again, sums
			//quotient and remainder of 256 division.
			for(i=1,a=0;i<6;i++)
				a += (ushort)b[i];
  
			bb = (ushort)(a/256);
			a = (ushort)((a-256*bb)+bb);
			bb = (ushort)(a/256);
  
			return ((byte)((a-256*bb)+bb));  
		}

		/// <summary>
		/// Opens a UE9.
		/// </summary>
		/// <param name="localID">The local ID of the UE9 you want to open.</param>
		/// <returns>INVALID_HANDLE_VALUE or negaitive value on error, or a handle value on success</returns>
		public int openUSBConnection(int localID)
		{
			byte []buffer = new byte[38];
			ushort checksumTotal = 0;
			UInt32 hDevice = 0;
			uint numDevices = 0;

			try
			{
				numDevices = LJUSB_GetDevCount(UE9_PRODUCT_ID);

				if(numDevices == 0)
					return -2;

				for(uint dev = 1;  dev <= numDevices; dev++)
				{
					hDevice = LJUSB_OpenDevice(dev, 0, UE9_PRODUCT_ID);
					
					if(hDevice != INVALID_HANDLE_VALUE)
					{
						if(localID < 0)
						{
							this.handle = hDevice;
							return 0;
						}
						else
						{
							checksumTotal = 0;
	
							//setting up a CommConfig command
							buffer[1] = (byte)(0x78);
							buffer[2] = (byte)(0x10);
							buffer[3] = (byte)(0x01);

							for(int i = 6; i < 38; i++)
								buffer[i] = (byte)(0x00);

							extendedChecksum(ref buffer,38);

							if(LJUSB_BulkWrite(hDevice, UE9.UE9_PIPE_EP1_OUT, buffer, 38) != 38)
								throw new Exception("close");

							buffer = new byte[38];

							if(LJUSB_BulkRead(hDevice, UE9.UE9_PIPE_EP1_IN, buffer, 38) != 38)
								throw new Exception("close");
							
							checksumTotal = extendedChecksum16(buffer, 38);
							if( (byte)((checksumTotal / 256) & 0xff) != buffer[5])
								throw new Exception("close");

							if( (byte)(checksumTotal & 0xff) != buffer[4])
								throw new Exception("close");

							if( extendedChecksum8(buffer) != buffer[0])
								throw new Exception("close");

							if( buffer[1] != (byte)(0x78) || buffer[2] != (byte)(0x10) || buffer[3] != (byte)(0x01) )
								throw new Exception("close");

							if((int)buffer[8] == localID)
							{
								this.handle = hDevice;
								return 0;
							}
							else 
							{
								LJUSB_CloseDevice(hDevice);
							}

						}	//else localID >= 0 end
	
					}  //if hDevice != INVALID_HANDLE_VALUE end

				} //for end

			}
			catch (System.Exception y)
			{
				if(y.ToString() == "close")
					LJUSB_CloseDevice(hDevice);
								
				return -3;
			}
	
			return -2;
		}


		public int closeUSBConnection()
		{
			try
			{
				LJUSB_CloseDevice(this.handle);
			}
			catch (System.Exception)
			{
				return -4;
			}

			return 0;
		}

		/// <summary>
		/// </summary>
		/// <returns>Returns the number of milliseconds that have elasped since the system was started.</returns>
		public static long getTickCount() 
		{
			return( (long)(System.Environment.TickCount & Int32.MaxValue));  
		}


		/// <summary>
		///  Gets calibration information from memory blocks 0-4 of a UE9.
		///  Sets the calibration information in a calibrationInfo structure of the class.
		/// </summary>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int getCalibrationInfo() 
		{
			byte []sendBuffer = new byte[8];
			byte []recBuffer = new byte[136];
			uint sentRec = 0;
  
			//////////////////////////////
			//reading block 0 from memory 
			//////////////////////////////
			sendBuffer[1] = (byte)(0xF8);  //command byte
			sendBuffer[2] = (byte)(0x01);  //number of data words
			sendBuffer[3] = (byte)(0x2A);  //extended command number
			sendBuffer[6] = (byte)(0x00);
			sendBuffer[7] = (byte)(0x00);  //Blocknum = 0
			extendedChecksum(ref sendBuffer, 8);
  
			sentRec = LJUSB_BulkWrite(handle, UE9_PIPE_EP1_OUT, sendBuffer, 8);
			if(sentRec < 8)
				return -54;

			sentRec = LJUSB_BulkRead(handle, UE9_PIPE_EP1_IN, recBuffer, 136);
			if(sentRec < 136)	
				return -55;

			if(recBuffer[1] != (byte)(0xF8) || recBuffer[2] != (byte)(0x41) || recBuffer[3] != (byte)(0x2A))
				return -56;

			//block data starts on byte 8 of the buffer
			caliInfo.unipolarSlope[0] = FPuint8ArrayToFPDouble(recBuffer, 0 + 8);
			caliInfo.unipolarOffset[0] = FPuint8ArrayToFPDouble(recBuffer, 8 + 8);
			caliInfo.unipolarSlope[1] = FPuint8ArrayToFPDouble(recBuffer, 16 + 8);
			caliInfo.unipolarOffset[1] = FPuint8ArrayToFPDouble(recBuffer, 24 + 8);
			caliInfo.unipolarSlope[2] = FPuint8ArrayToFPDouble(recBuffer, 32 + 8);
			caliInfo.unipolarOffset[2] = FPuint8ArrayToFPDouble(recBuffer, 40 + 8);
			caliInfo.unipolarSlope[3] = FPuint8ArrayToFPDouble(recBuffer, 48 + 8);
			caliInfo.unipolarOffset[3] = FPuint8ArrayToFPDouble(recBuffer, 56 + 8);
  
			//////////////////////////////
			//reading block 1 from memory 
			//////////////////////////////
			sendBuffer[7] = (byte)(0x01);    //Blocknum = 1
			extendedChecksum(ref sendBuffer, 8);
  
			sentRec = LJUSB_BulkWrite(handle, UE9_PIPE_EP1_OUT, sendBuffer, 8);
			if(sentRec < 8)
				return -54;

			sentRec = LJUSB_BulkRead(handle, UE9_PIPE_EP1_IN, recBuffer, 136);
			if(sentRec < 136)
				return -55;

			if(recBuffer[1] != (byte)(0xF8) || recBuffer[2] != (byte)(0x41) || recBuffer[3] != (byte)(0x2A))
				return -56;
  
			caliInfo.bipolarSlope = FPuint8ArrayToFPDouble(recBuffer, 0 + 8);
			caliInfo.bipolarOffset = FPuint8ArrayToFPDouble(recBuffer, 8 + 8);
  
			//////////////////////////////
			//reading block 2 from memory 
			//////////////////////////////
			sendBuffer[7] = (byte)(0x02);    //Blocknum = 2
			extendedChecksum(ref sendBuffer, 8);
  
			sentRec = LJUSB_BulkWrite(handle, UE9_PIPE_EP1_OUT, sendBuffer, 8);
			if(sentRec < 8)
				return -54;
	
			sentRec = LJUSB_BulkRead(handle, UE9_PIPE_EP1_IN, recBuffer, 136);
			if(sentRec < 136)
				return -55;

			if(recBuffer[1] != (byte)(0xF8) || recBuffer[2] != (byte)(0x41) || recBuffer[3] != (byte)(0x2A))
				return -56;
  
			caliInfo.DACSlope[0] = FPuint8ArrayToFPDouble(recBuffer, 0 + 8);
			caliInfo.DACOffset[0] = FPuint8ArrayToFPDouble(recBuffer, 8 + 8);
			caliInfo.DACSlope[1] = FPuint8ArrayToFPDouble(recBuffer, 16 + 8);
			caliInfo.DACOffset[1] = FPuint8ArrayToFPDouble(recBuffer, 24 + 8);
			caliInfo.tempSlope = FPuint8ArrayToFPDouble(recBuffer, 32 + 8);
			caliInfo.tempSlopeLow = FPuint8ArrayToFPDouble(recBuffer, 48 + 8);
			caliInfo.calTemp = FPuint8ArrayToFPDouble(recBuffer, 64 + 8);
			caliInfo.Vref = FPuint8ArrayToFPDouble(recBuffer, 72 + 8);
			caliInfo.VrefDiv2 = FPuint8ArrayToFPDouble(recBuffer, 88 + 8);
			caliInfo.VsSlope = FPuint8ArrayToFPDouble(recBuffer, 96 + 8);

			//////////////////////////////
			//reading block 3 from memory 
			//////////////////////////////
			sendBuffer[7] = (byte)(0x03);    //Blocknum = 3
			extendedChecksum(ref sendBuffer, 8);

			sentRec = LJUSB_BulkWrite(handle, UE9_PIPE_EP1_OUT, sendBuffer, 8);
			if(sentRec < 8)
				return -54;
	
			sentRec = LJUSB_BulkRead(handle, UE9_PIPE_EP1_IN, recBuffer, 136);
			if(sentRec < 136)
				return -55;

			if(recBuffer[1] != (byte)(0xF8) || recBuffer[2] != (byte)(0x41) || recBuffer[3] != (byte)(0x2A))
				return -56;

			//block data starts on byte 8 of the buffer
			caliInfo.hiResUnipolarSlope = FPuint8ArrayToFPDouble(recBuffer, 0 + 8);
			caliInfo.hiResUnipolarOffset = FPuint8ArrayToFPDouble(recBuffer, 8 + 8);

			//////////////////////////////
			//reading block 4 from memory 
			//////////////////////////////
			sendBuffer[7] = (byte)(0x04);    //Blocknum = 4
			extendedChecksum(ref sendBuffer, 8);

			sentRec = LJUSB_BulkWrite(handle, UE9_PIPE_EP1_OUT, sendBuffer, 8);
			if(sentRec < 8)
				return -54;
	
			sentRec = LJUSB_BulkRead(handle, UE9_PIPE_EP1_IN, recBuffer, 136);
			if(sentRec < 136)
				return -55;

			if(recBuffer[1] != (byte)(0xF8) || recBuffer[2] != (byte)(0x41) || recBuffer[3] != (byte)(0x2A))
				return -56;

			//block data starts on byte 8 of the buffer
			caliInfo.hiResBipolarSlope = FPuint8ArrayToFPDouble(recBuffer, 0 + 8);
			caliInfo.hiResBipolarOffset = FPuint8ArrayToFPDouble(recBuffer, 8 + 8);

			return 0;
		}
		
		/// <summary>
		/// Converts a fixed point byte array (starting a startIndex) to a floating point double value.  This function is used primarily by getCalibrationInfo.
		/// </summary>
		/// <param name="buffer">A ReadMem from calibration memory response buffer.</param>
		/// <param name="startIndex">The index in the buffer where to start the fixed point conversion.  Data starts at byte 8. </param>
		/// <returns>Returns a floating point double value.</returns>
		public double FPuint8ArrayToFPDouble(byte []buffer, int startIndex) 
		{ 
			uint resultDec = 0;
			int resultWh = 0;

			for(int i = 0; i < 4; i++) 
			{
				resultDec += (uint)(buffer[startIndex + i] * Math.Pow(2, i*8)); 			
				resultWh += (int)(buffer[startIndex + i + 4] * Math.Pow(2, i*8));
			}

			return ( (double)resultWh + (double)(resultDec)/4294967296.0 );
		}

		/// <summary>
		///  Translates the binary analog input bytes read from the UE9, to a voltage value
		///  (calibrated).  Call getCalibrationInfo first to set up caliInfo. 
		/// </summary>
		/// <param name="gainBip">The gain option and bipolar setting.  The high bit of the byte is the
		///  bipolar setting and the lower 3 bits is the gain option.  See the
		///  Feedback function in Section 5.3.3 of the UE9 User's Guide for a table
		///  of BipGain values that can be passed.</param>
		/// <param name="resolution">The resolution of the analog reading.</param>
		/// <param name="bytesVoltage">The 2 byte voltage that will be converted to a analog value.</param>
		/// <param name="analogVoltage">The converted analog voltage.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int binaryToCalibratedAnalogVoltage(byte gainBip, byte resolution, ushort bytesVoltage, ref double analogVoltage) 
		{
			double slope;
			double offset;

			if(resolution < 18)
			{
				switch(gainBip)
				{
					case 0:
						slope = caliInfo.unipolarSlope[0];
						offset = caliInfo.unipolarOffset[0];
						break;
					case 1:
						slope = caliInfo.unipolarSlope[1];
						offset = caliInfo.unipolarOffset[1];
						break;
					case 2:
						slope = caliInfo.unipolarSlope[2];
						offset = caliInfo.unipolarOffset[2];
						break;
					case 3:
						slope = caliInfo.unipolarSlope[3];
						offset = caliInfo.unipolarOffset[3];
						break;
					case 8:
						slope = caliInfo.bipolarSlope;
						offset = caliInfo.bipolarOffset;
						break;
					default:
						return -50;
				}
			}
			else  //UE9 Pro high res
			{
				switch(gainBip)
				{
					case 0:
						slope = caliInfo.hiResUnipolarSlope;
						offset = caliInfo.hiResUnipolarOffset;
						break;
					case 8:
						slope = caliInfo.hiResBipolarSlope;
						offset = caliInfo.hiResBipolarOffset;
						break;
					default:
						return -50;
				}
			}

			analogVoltage = (slope*(double)bytesVoltage) + offset;

			return 0;
		}

		/// <summary>
		///  Translates the binary analog bytes read from the UE9, to a Kelvin temperature
		///  value (calibrated).  Call getCalibrationInfo first to set up caliInfo.
		/// </summary>
		/// <param name="powerLevel">The power level the UE9 is set at.  (0x00: Fixed high, system clock = 48 MHz; 0x01: Fixed low, system clock = 6 MHz)</param>
		/// <param name="bytesTemperature">The 2 byte temperature that will be converted to an analog value.</param>
		/// <param name="analogTemperature">The converted analog temperature.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int binaryToCalibratedAnalogTemperature(int powerLevel, ushort bytesTemperature, ref double analogTemperature) 
		{
			double slope = 0;
 
			switch(powerLevel)
			{
				case 0:     //high power 
					slope = caliInfo.tempSlope;  
					break;
				case 1:     //low power
					slope = caliInfo.tempSlopeLow;
					break;
				default:  
					return -51;
			}
  
			analogTemperature = (double)(bytesTemperature)*slope;
			return 0;
		}

		/// <summary>
		/// Translates a voltage value to binary analog input bytes (calibrated) that can
		///  be sent to a UE9.  Call getCalibrationInfo first to set up caliInfo.
		/// </summary>
		/// <param name="channelNumber">Channel number of the DAC.</param>
		/// <param name="analogVoltage">the analog voltage that will be converted to a 2 byte value.</param>
		/// <param name="bytesVoltage">The converted 2 byte voltage.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int analogToCalibratedBinaryVoltage(int DACNumber, double analogVoltage, ref ushort bytesVoltage) 
		{
			double slope;
			double offset;
			double tempBytesVoltage;
  
			switch(DACNumber) 
			{
				case 0:
					slope = caliInfo.DACSlope[0];
					offset = caliInfo.DACOffset[0];
					break;
				case 1:
					slope = caliInfo.DACSlope[1];
					offset = caliInfo.DACOffset[1];
					break;
				default:
					return -52;
			}	    
  
			tempBytesVoltage = slope*analogVoltage + offset;
  
			//Checking to make sure bytesVoltage will be a value between 0 and 4095, 
			//or that a uint16 overflow does not occur.  A too high analogVoltage 
			//(above 5 volts) or too low analogVoltage (below 0 volts) will cause a 
			//value not between 0 and 4095.
			if(tempBytesVoltage < 0)
				tempBytesVoltage = 0;
			if(tempBytesVoltage > 4095)  
				tempBytesVoltage = 4095;
  
			bytesVoltage = (ushort)tempBytesVoltage; 
     
			return 0;
		}

		/// <summary>
		///  Translates the binary analog input bytes read from the UE9, to a voltage value (uncalibrated).
		/// </summary>
		/// <param name="gainBip">the gain option and bipolar setting.  The high bit of the byte is the
		///  bipolar setting and the lower 3 bits is the gain option.  See the
		///  Feedback function in Section 5.3.3 of the UE9 User's Guide for a table
		///  of BipGain values that can be passed.</param>
		/// <param name="resolution">The resolution of the analog reading.</param>
		/// <param name="bytesVoltage">The 2 byte voltage that will be converted to a analog value.</param>
		/// <param name="analogVoltage">The converted analog voltage.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int binaryToUncalibratedAnalogVoltage(byte gainBip, byte resolution, ushort bytesVoltage, ref double analogVoltage) 
		{
			double slope;
			double offset;

			if(resolution < 18)
			{
				switch(gainBip)
				{
					case 0:
						slope = 0.000077503;
						offset = -0.012;
						break;
					case 1:
						slope = 0.000038736;
						offset = -0.012;
						break;
					case 2:
						slope = 0.000019353;
						offset = -0.012;
						break;
					case 3:
						slope = 0.0000096764;
						offset = -0.012;
						break;
					case 8:
						slope = 0.00015629;
						offset = -5.1760;
						break;
					default:
						return -53;
				}
			}
			else  //UE9 Pro high res
			{
				switch(gainBip)
				{
					case 0:
						slope = 0.000077503;
						offset = 0.012;
						break;
					case 8:
						slope = 0.00015629;
						offset = -5.176;
						break;
					default:
						return -53;
				}
			}

			analogVoltage = (slope*(double)bytesVoltage) + offset;
			return 0;
		}

		/// <summary>
		///  Translates a voltage value to binary analog input bytes (uncalibrated) that
		///  can be sent to a UE9.
		/// </summary>
		/// <param name="analogVoltage">The analog voltage that will be converted to a 2 byte value.</param>
		/// <param name="bytesVoltage">The converted 2 byte voltage.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int analogToUncalibratedBinaryVoltage(double analogVoltage, ref ushort bytesVoltage)
		{
			double tempBytesVoltage;
  
			tempBytesVoltage = 842.59*analogVoltage;
  
			//Checking to make sure bytesVoltage will be a value between 0 and 4095, 
			//or that a uint16 overflow does not occur.  A too high analogVoltage 
			//(above 5 volts) or too low analogVoltage (below 0 volts) will cause a 
			//value not between 0 and 4095.
			if(tempBytesVoltage < 0)
				tempBytesVoltage = 0;
			if(tempBytesVoltage > 4095)  
				tempBytesVoltage = 4095;
  
			bytesVoltage = (ushort)tempBytesVoltage;

			return 0;
		}

		/// <summary>
		///  Translates the binary analog bytes read from the UE9, to a Kelvin temperature value (uncalibrated).
		/// </summary>
		/// <param name="bytesTemperature">The 2 byte temperature that will be converted to an analog value.</param>
		/// <param name="analogTemperature">The converted analog temperature.</param>
		/// <returns>A negative value on error, 0 on success.</returns>
		public int binaryToUncalibratedAnalogTemperature(ushort bytesTemperature, ref double analogTemperature)
		{
			analogTemperature = (double)(bytesTemperature)*0.012968;
			return 0;
		}
	}
}

