//Author: LabJack
//April 29, 2008
//This example program calls the Feedback low-level function in a continuous loop. 
//It will read the voltages from AIN0-AIN3, set and read the states and directions 
//from FIO4 - FIO5, set DAC0, read Counter1 (FIO7) and run Timer0.  This example 
//also uses the ConfigIO and ConfigTimerClock low-level functions to configure the 
//IO channels and set the timer clock.  The first U3 device found is used in this example. 

using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using LabJack;

namespace u3Feedback
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class u3Feedback : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Timer updateTimer;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.Label label6;
		private System.Windows.Forms.Label label7;
		private System.Windows.Forms.Label label8;
		private System.Windows.Forms.Label label9;
		private System.Windows.Forms.TextBox errorBox;
		private System.Windows.Forms.Label ain0lbl;
		private System.Windows.Forms.Label ain1lbl;
		private System.Windows.Forms.Label ain2lbl;
		private System.Windows.Forms.Panel panel1;
		private System.Windows.Forms.Panel panel2;
		private System.Windows.Forms.Label label10;
		private System.Windows.Forms.Label label11;
		private System.Windows.Forms.Label label12;
		private System.Windows.Forms.Label label13;
		private System.Windows.Forms.Label label14;
		private System.Windows.Forms.Panel panel3;
		private System.Windows.Forms.Panel panel4;
		private System.Windows.Forms.Label label16;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.Label count1lbl;
		private System.Windows.Forms.CheckBox fio4StateCB;
		private System.Windows.Forms.CheckBox fio4DirCB;
		private System.Windows.Forms.CheckBox fio5DirCB;
		private System.Windows.Forms.CheckBox fio5StateCB;
		private System.Windows.Forms.Button dac0Inc;
		private System.Windows.Forms.Button dac0Dec;
		private System.Windows.Forms.TextBox dac0Box;
		private System.Windows.Forms.Label ain3lbl;
		
		//ain0-3 voltage
		private double ain0;
		private double ain1;
		private double ain2;
		private double ain3;
		
		//fio4-5 state
		private bool fio4State;	
		private bool fio5State;	
		
		private UInt32 count1;		 //Counter1 count
		private string error;		 //error
		private double dac0;		 //dac0
		private bool updateFIODAC;	 //update dac0, fio4, and fio5?
		private bool openU3;		 //open u3 device?
		private bool useUpdateTimer; //can use update timer? (false if busy or closing
		private bool exitApp;		 //exit application?
		private U3 u3;
		
		public u3Feedback()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			myInit();
			fio4State = false;
			fio5State = false;
			dac0 = 0;
			error = "";
			errorBox.Text = "";
			useUpdateTimer = true;
			exitApp = false;
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			base.Dispose( disposing );
		}
		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.label1 = new System.Windows.Forms.Label();
			this.updateTimer = new System.Windows.Forms.Timer();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.label4 = new System.Windows.Forms.Label();
			this.label5 = new System.Windows.Forms.Label();
			this.label6 = new System.Windows.Forms.Label();
			this.label7 = new System.Windows.Forms.Label();
			this.label8 = new System.Windows.Forms.Label();
			this.label9 = new System.Windows.Forms.Label();
			this.errorBox = new System.Windows.Forms.TextBox();
			this.ain0lbl = new System.Windows.Forms.Label();
			this.ain1lbl = new System.Windows.Forms.Label();
			this.ain2lbl = new System.Windows.Forms.Label();
			this.ain3lbl = new System.Windows.Forms.Label();
			this.count1lbl = new System.Windows.Forms.Label();
			this.panel1 = new System.Windows.Forms.Panel();
			this.label13 = new System.Windows.Forms.Label();
			this.label10 = new System.Windows.Forms.Label();
			this.panel2 = new System.Windows.Forms.Panel();
			this.fio4StateCB = new System.Windows.Forms.CheckBox();
			this.fio4DirCB = new System.Windows.Forms.CheckBox();
			this.label14 = new System.Windows.Forms.Label();
			this.label12 = new System.Windows.Forms.Label();
			this.label11 = new System.Windows.Forms.Label();
			this.fio5DirCB = new System.Windows.Forms.CheckBox();
			this.fio5StateCB = new System.Windows.Forms.CheckBox();
			this.panel3 = new System.Windows.Forms.Panel();
			this.panel4 = new System.Windows.Forms.Panel();
			this.dac0Inc = new System.Windows.Forms.Button();
			this.dac0Dec = new System.Windows.Forms.Button();
			this.dac0Box = new System.Windows.Forms.TextBox();
			this.label16 = new System.Windows.Forms.Label();
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label1.Location = new System.Drawing.Point(16, 32);
			this.label1.Size = new System.Drawing.Size(16, 16);
			this.label1.Text = "0";
			// 
			// updateTimer
			// 
			this.updateTimer.Enabled = true;
			this.updateTimer.Interval = 1000;
			this.updateTimer.Tick += new System.EventHandler(this.updateTimer_Tick);
			// 
			// label2
			// 
			this.label2.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label2.Location = new System.Drawing.Point(16, 56);
			this.label2.Size = new System.Drawing.Size(16, 16);
			this.label2.Text = "1";
			// 
			// label3
			// 
			this.label3.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label3.Location = new System.Drawing.Point(16, 80);
			this.label3.Size = new System.Drawing.Size(16, 16);
			this.label3.Text = "2";
			// 
			// label4
			// 
			this.label4.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label4.Location = new System.Drawing.Point(16, 104);
			this.label4.Size = new System.Drawing.Size(16, 16);
			this.label4.Text = "3";
			// 
			// label5
			// 
			this.label5.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label5.Location = new System.Drawing.Point(16, 32);
			this.label5.Size = new System.Drawing.Size(16, 20);
			this.label5.Text = "4";
			// 
			// label6
			// 
			this.label6.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label6.Location = new System.Drawing.Point(16, 56);
			this.label6.Size = new System.Drawing.Size(16, 20);
			this.label6.Text = "5";
			// 
			// label7
			// 
			this.label7.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold);
			this.label7.Location = new System.Drawing.Point(6, 32);
			this.label7.Size = new System.Drawing.Size(194, 24);
			this.label7.Text = "Timer0(FIO6) has output freq. of 31250 Hz.";
			// 
			// label8
			// 
			this.label8.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label8.Location = new System.Drawing.Point(16, 8);
			this.label8.Size = new System.Drawing.Size(96, 16);
			this.label8.Text = "Count1(FIO7):";
			// 
			// label9
			// 
			this.label9.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label9.Location = new System.Drawing.Point(8, 240);
			this.label9.Size = new System.Drawing.Size(56, 16);
			this.label9.Text = "Error";
			// 
			// errorBox
			// 
			this.errorBox.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(224)), ((System.Byte)(224)), ((System.Byte)(224)));
			this.errorBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular);
			this.errorBox.Location = new System.Drawing.Point(56, 232);
			this.errorBox.Multiline = true;
			this.errorBox.ReadOnly = true;
			this.errorBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
			this.errorBox.Size = new System.Drawing.Size(168, 32);
			this.errorBox.Text = "";
			// 
			// ain0lbl
			// 
			this.ain0lbl.Location = new System.Drawing.Point(48, 32);
			this.ain0lbl.Size = new System.Drawing.Size(48, 16);
			this.ain0lbl.Text = "99999.999";
			// 
			// ain1lbl
			// 
			this.ain1lbl.Location = new System.Drawing.Point(48, 56);
			this.ain1lbl.Size = new System.Drawing.Size(48, 16);
			this.ain1lbl.Text = "99999.999";
			// 
			// ain2lbl
			// 
			this.ain2lbl.Location = new System.Drawing.Point(48, 80);
			this.ain2lbl.Size = new System.Drawing.Size(48, 16);
			this.ain2lbl.Text = "99999.999";
			// 
			// ain3lbl
			// 
			this.ain3lbl.Location = new System.Drawing.Point(48, 104);
			this.ain3lbl.Size = new System.Drawing.Size(48, 16);
			this.ain3lbl.Text = "99999.999";
			// 
			// count1lbl
			// 
			this.count1lbl.Location = new System.Drawing.Point(112, 8);
			this.count1lbl.Size = new System.Drawing.Size(76, 16);
			this.count1lbl.Text = "4294967296";
			// 
			// panel1
			// 
			this.panel1.BackColor = System.Drawing.Color.White;
			this.panel1.Controls.Add(this.label13);
			this.panel1.Controls.Add(this.label10);
			this.panel1.Controls.Add(this.ain1lbl);
			this.panel1.Controls.Add(this.label2);
			this.panel1.Controls.Add(this.label4);
			this.panel1.Controls.Add(this.label1);
			this.panel1.Controls.Add(this.label3);
			this.panel1.Controls.Add(this.ain3lbl);
			this.panel1.Controls.Add(this.ain0lbl);
			this.panel1.Controls.Add(this.ain2lbl);
			this.panel1.Location = new System.Drawing.Point(8, 8);
			this.panel1.Size = new System.Drawing.Size(104, 128);
			// 
			// label13
			// 
			this.label13.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label13.Location = new System.Drawing.Point(8, 8);
			this.label13.Size = new System.Drawing.Size(32, 16);
			this.label13.Text = "AIN";
			// 
			// label10
			// 
			this.label10.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label10.Location = new System.Drawing.Point(40, 8);
			this.label10.Size = new System.Drawing.Size(56, 16);
			this.label10.Text = "Voltage";
			// 
			// panel2
			// 
			this.panel2.BackColor = System.Drawing.Color.White;
			this.panel2.Controls.Add(this.fio4StateCB);
			this.panel2.Controls.Add(this.fio4DirCB);
			this.panel2.Controls.Add(this.label14);
			this.panel2.Controls.Add(this.label12);
			this.panel2.Controls.Add(this.label11);
			this.panel2.Controls.Add(this.label6);
			this.panel2.Controls.Add(this.label5);
			this.panel2.Controls.Add(this.fio5DirCB);
			this.panel2.Controls.Add(this.fio5StateCB);
			this.panel2.Location = new System.Drawing.Point(120, 8);
			this.panel2.Size = new System.Drawing.Size(112, 80);
			// 
			// fio4StateCB
			// 
			this.fio4StateCB.Location = new System.Drawing.Point(78, 32);
			this.fio4StateCB.Size = new System.Drawing.Size(16, 16);
			this.fio4StateCB.Click += new System.EventHandler(this.fio4StateCB_Click);
			// 
			// fio4DirCB
			// 
			this.fio4DirCB.Location = new System.Drawing.Point(46, 32);
			this.fio4DirCB.Size = new System.Drawing.Size(16, 16);
			this.fio4DirCB.Click += new System.EventHandler(this.fioDirCB_Click);
			// 
			// label14
			// 
			this.label14.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label14.Location = new System.Drawing.Point(8, 8);
			this.label14.Size = new System.Drawing.Size(28, 16);
			this.label14.Text = "FIO";
			// 
			// label12
			// 
			this.label12.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label12.Location = new System.Drawing.Point(64, 8);
			this.label12.Size = new System.Drawing.Size(40, 16);
			this.label12.Text = "State";
			// 
			// label11
			// 
			this.label11.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label11.Location = new System.Drawing.Point(40, 8);
			this.label11.Size = new System.Drawing.Size(24, 16);
			this.label11.Text = "Dir";
			// 
			// fio5DirCB
			// 
			this.fio5DirCB.Location = new System.Drawing.Point(46, 56);
			this.fio5DirCB.Size = new System.Drawing.Size(16, 16);
			this.fio5DirCB.Click += new System.EventHandler(this.fioDirCB_Click);
			// 
			// fio5StateCB
			// 
			this.fio5StateCB.Location = new System.Drawing.Point(78, 56);
			this.fio5StateCB.Size = new System.Drawing.Size(16, 16);
			this.fio5StateCB.Click += new System.EventHandler(this.fio5StateCB_Click);
			// 
			// panel3
			// 
			this.panel3.BackColor = System.Drawing.Color.White;
			this.panel3.Controls.Add(this.count1lbl);
			this.panel3.Controls.Add(this.label8);
			this.panel3.Controls.Add(this.label7);
			this.panel3.Location = new System.Drawing.Point(16, 160);
			this.panel3.Size = new System.Drawing.Size(208, 64);
			// 
			// panel4
			// 
			this.panel4.BackColor = System.Drawing.Color.White;
			this.panel4.Controls.Add(this.dac0Inc);
			this.panel4.Controls.Add(this.dac0Dec);
			this.panel4.Controls.Add(this.dac0Box);
			this.panel4.Controls.Add(this.label16);
			this.panel4.Location = new System.Drawing.Point(120, 96);
			this.panel4.Size = new System.Drawing.Size(112, 56);
			// 
			// dac0Inc
			// 
			this.dac0Inc.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Bold);
			this.dac0Inc.Location = new System.Drawing.Point(88, 36);
			this.dac0Inc.Size = new System.Drawing.Size(16, 16);
			this.dac0Inc.Text = "+";
			this.dac0Inc.Click += new System.EventHandler(this.dac0Inc_Click);
			// 
			// dac0Dec
			// 
			this.dac0Dec.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Bold);
			this.dac0Dec.Location = new System.Drawing.Point(72, 36);
			this.dac0Dec.Size = new System.Drawing.Size(16, 16);
			this.dac0Dec.Text = "-";
			this.dac0Dec.Click += new System.EventHandler(this.dac0Dec_Click);
			// 
			// dac0Box
			// 
			this.dac0Box.Location = new System.Drawing.Point(56, 8);
			this.dac0Box.Size = new System.Drawing.Size(48, 22);
			this.dac0Box.Text = "0.000";
			this.dac0Box.Validating += new System.ComponentModel.CancelEventHandler(this.dac0Box_Validating);
			// 
			// label16
			// 
			this.label16.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label16.Location = new System.Drawing.Point(8, 8);
			this.label16.Size = new System.Drawing.Size(44, 16);
			this.label16.Text = "DAC0:";
			// 
			// u3Feedback
			// 
			this.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(224)), ((System.Byte)(224)), ((System.Byte)(224)));
			this.Controls.Add(this.panel4);
			this.Controls.Add(this.panel3);
			this.Controls.Add(this.panel2);
			this.Controls.Add(this.panel1);
			this.Controls.Add(this.errorBox);
			this.Controls.Add(this.label9);
			this.Menu = this.mainMenu1;
			this.MinimizeBox = false;
			this.Text = "U3 Feedback Example";
			this.Click += new System.EventHandler(this.focusClick);
			this.Closing += new System.ComponentModel.CancelEventHandler(this.u3Feedback_Closing);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>

		static void Main() 
		{
			Application.Run(new u3Feedback());
		}

		private void myInit()
		{
			//Initializing variables
			ain0 = 99999.999;
			ain1 = 99999.999;
			ain2 = 99999.999;
			ain3 = 99999.999;
			count1 = 0;
			updateFIODAC = true;
			openU3 = true;
			this.Invoke(new EventHandler(updateAINLabels));
			this.Invoke(new EventHandler(updateCount1Label));
		}

		private void updateTimer_Tick(object sender, System.EventArgs e)
		{
			if(exitApp == false && useUpdateTimer == true)
			{
				Thread updateThread = new Thread(new ThreadStart(update));
				updateThread.Start();
			}
			
			if(exitApp == true )
			{
				if(openU3 == false)
				{
					configIO_example(false);
					u3.closeUSBConnection();
				}
				updateTimer.Enabled = false;
				this.Close();
			}
		}

		private void update()
		{
			int err = 0;
			error = "";
			this.Invoke(new EventHandler(updateErrorBox));
			useUpdateTimer = false;

			try
			{
				if(openU3 == true)
				{
					//Creating new U3 object and opening first found U3
					u3 = new U3();
					if(u3.openUSBConnection(-1) < 0)
						throw new Exception((error = u3.errorText));

					openU3 = false;

					//Getting the opened U3's calibration information
					if(u3.getCalibrationInfo() < 0)
						throw new Exception((error = u3.errorText));

					//Configure analog, digital, timers, counters IOs
					if( (err = configIO_example(true)) < 0)
					{
						if(err != -100)
							error = "ConfigIO " + getError(err);
						throw new Exception();
					}

					//configure timer clock
					if( (err = this.configTimerClock_example()) < 0)
					{
						if(err != -100)
							error = "ConfigTimerClock " + getError(err);
						throw new Exception();
					}

					//Configure timer 0 mode
					if( (err = this.timer0Config_example()) < 0)
					{
						if(err != -100)
							error = "Timer0Config " + getError(err);
						throw new Exception();
					}
				}

				if( (err = feedback_example()) < 0)
				{
					if(err != -100)
						error = "Feedback " + getError(err);
					throw new Exception();
				}
			}
			catch(Exception e)
			{
				error += " " + e.Message;
				this.Invoke(new EventHandler(updateErrorBox));

				if(openU3 == false)
					u3.closeUSBConnection();
		
				myInit();
			}
			
			useUpdateTimer = true;
		}

		/// <summary>
		/// Configures analog, digital, timers, counters IOs with the ConfigIO low-level function.
		/// </summary>
		/// <param name="enable">If true, timer 0 and counter 1 will be enabled with a TimerCounterPinOffset 
		/// of 6, and FIO0 - 3 wil be set as analog and FIO 4-5 will be set as digital.
		/// If false, timers and counters will be turned off and FIO0-7 will be set as analog.</param>
		/// <returns>Negative number on error, 0 on success.</returns>
		private int configIO_example(bool enable)
		{
			byte []sendBuff = new byte[12];
			byte []recBuff = new byte[12];
			ushort checksumTotal;
			byte timerCounterConfig;
			byte fioAnalog;

			if(enable == true)
			{
				timerCounterConfig = 105;		//Enabling 1 timer (bits 0-1), Counter 1 (bit 3), 
												//and setting TimerCounterPinOffset (bits 4-7) to 6
				fioAnalog = 15;					//Setting FIO0-FIO3 (bits 0-3) to analog input  				 
			}
			else
			{
				timerCounterConfig = 64;		//Disabling timers (bits 0 and 1) and Counters
												//(bits 2 and 3), setting TimerCounterPinOffset
												//to 4 (bits 4-7)
				fioAnalog = 255;				//Setting all FIOs to analog 
			}			

			sendBuff[1] = (byte)(0xF8);			//Command byte
			sendBuff[2] = (byte)(0x03);			//Number of data words
			sendBuff[3] = (byte)(0x0B);			//Extended command number

			sendBuff[6] = 7;					//Writemask : Setting writemask for timerCounterConfig (bit 0), 
												//            DAC1Enable (bit 1) and FIOAnalog (bit 2)
  
			sendBuff[7] = 0;					//Reserved
			sendBuff[8] = timerCounterConfig;	//TimerCounterConfig
			sendBuff[9] = 0;					//DAC1 enable : disabling (ignored in hardware versions >= 1.30)
			sendBuff[10] = fioAnalog;			//FIOAnalog
			sendBuff[11] = 0;					//EIOAnalog : Not setting anything                       
			U3.extendedChecksum(ref sendBuff,12);

			if( U3.LJUSB_BulkWrite(u3.handle, U3.U3_PIPE_EP1_OUT, sendBuff, 12) < 12)
				return -1;;
			
			if( U3.LJUSB_BulkRead(u3.handle, U3.U3_PIPE_EP1_IN, recBuff, 12) < 12)
				return -2;

			checksumTotal = U3.extendedChecksum16(recBuff, 12);
			if( (byte)((checksumTotal/256) & 0xff) != recBuff[5]
				|| (byte)(checksumTotal & 0xff) != recBuff[4])
				return -4;
			
			if( U3.extendedChecksum8(recBuff) != recBuff[0])
				return -3;

			if( recBuff[1] != (byte)(0xF8) || recBuff[2] != (byte)(0x03) || recBuff[3] != (byte)(0x0B) )
				return -6;

			if( recBuff[6] != 0)
			{
				u3.errorcode = recBuff[6];
				return -200;
			}
  
			if( recBuff[8] != timerCounterConfig)
			{
				error = "ConfigIO error : TimerCounterConfig did not get set correctly";
				return -100;
			}

			if( recBuff[10] != fioAnalog)
			{
				error = "ConfigIO error : FIOAnalog did not set correctly";
				return -100;
			}

			return 0;  
		}


		/// <summary>
		/// Configures the TimerClockBase to 48 MHz/Divisor with a Divisor of 6 using the ConfigTimerClock 
		/// low-level function, giving a timer clock of 8 MHz.
		/// </summary>
		/// <returns>Negative number on error, 0 on success.</returns>
		private int configTimerClock_example()
		{
			byte []sendBuff = new byte[10];
			byte []recBuff = new byte[10];
			ushort checksumTotal;
			byte timerClockConfig;

			sendBuff[1] = (byte)(0xF8);	//Command byte
			sendBuff[2] = (byte)(0x02);	//Number of data words
			sendBuff[3] = (byte)(0x0A);	//Extended command number

			sendBuff[6] = 0;			//Reserved
			sendBuff[7] = 0;			//Reserved

			timerClockConfig = 134;		//TimerClockConfig : Configuring the clock (bit 7)
										//and setting the TimerClockBase (bits 0-2) to 48 MHz/Div
			sendBuff[8] = timerClockConfig;
			sendBuff[9] = 6;			//TimerClockDivisor : set to 6 so that actual timer clock is 8 MHz
			U3.extendedChecksum(ref sendBuff, 10);

			if( U3.LJUSB_BulkWrite(u3.handle, U3.U3_PIPE_EP1_OUT, sendBuff, 10) < 10)
				return -1;
		
			if( U3.LJUSB_BulkRead(u3.handle, U3.U3_PIPE_EP1_IN, recBuff, 10) < 10)
				return -2;

			checksumTotal = U3.extendedChecksum16(recBuff, 10);
			if( (byte)((checksumTotal >> 8) & 0xff) != recBuff[5]
				|| (byte)(checksumTotal & 0xff) != recBuff[4])
				return -4;
			
			if( U3.extendedChecksum8(recBuff) != recBuff[0])
				return -3;
			

			if( recBuff[1] != (byte)(0xF8) || recBuff[2] != (byte)(0x02) || recBuff[3] != (byte)(0x0A) )
				return -6;

			if( recBuff[6] != 0)
			{
				u3.errorcode = recBuff[6];
				return -200;
			}

			return 0;
		}


		/// <summary>
		/// Configures the timer 0 mode and its value using the Feedback low-level function.  
		/// The mode will be set to a 8 bit PWM output with a value of 32768. 
		/// </summary>
		/// <returns>Negative number on error, 0 on success.</returns>
		private int timer0Config_example()
		{
			byte []sendBuff = new byte[16];
			byte []recBuff = new byte[14];
			ulong checksumTotal;
			uint recChar = 0;

			sendBuff[1] = (byte)(0xF8);	//Command byte
			sendBuff[2] = 5;			//Number of data words (.5 word for echo, 4 words for IOTypes 
										//and data, and .5 word for the extra byte)   
			sendBuff[3] = (byte)(0x00);	//Extended command number

			sendBuff[6] = 0;			//Echo  

			sendBuff[7] = 43;			//IOType is Timer0Config
			sendBuff[8] = 1;			//TimerMode is 8 bit PWM output (mode 1)
			sendBuff[9] = 0;			//Value LSB
			sendBuff[10] = 0;			//Value MSB

			sendBuff[11] = 42;			//IOType is Timer0
			sendBuff[12] = 1;			//UpdateReset
			sendBuff[13] = 0;			//Value LSB
			sendBuff[14] = 128;			//Value MSB, Whole value is 32768
			sendBuff[15] = 0;

			U3.extendedChecksum(ref sendBuff,16);

			if( U3.LJUSB_BulkWrite(u3.handle, U3.U3_PIPE_EP1_OUT, sendBuff, 16) < 16)
				return -1;
  
			if((recChar = U3.LJUSB_BulkRead(u3.handle, U3.U3_PIPE_EP1_IN, recBuff, 14)) < 9)
				return -2;
			  
			checksumTotal = U3.extendedChecksum16(recBuff, Convert.ToInt32(recChar));
			if( (byte)((checksumTotal/256) & 0xff) != recBuff[5]
				|| (byte)(checksumTotal & 0xff) != recBuff[4])
				return -4;
			
			if( U3.extendedChecksum8(recBuff) != recBuff[0])
				return -3;
			
			if( recBuff[1] != (byte)(0xF8) || recBuff[3] != (byte)(0x00) )
				return -6;

			if( recBuff[6] != 0)
			{
				error = "Feedback error: received errorcode " + recBuff[6] + " in frame " + recBuff[7];
				return -100;
			}

			if(recBuff[2] != 4)
				return -6;
  
			return 0;
		}


		/// <summary>
		///  Reads the voltages of AIN0-4, states of FIO5-6 and the count of counter1 using the Feedback
		///  low-level function.  If needed, the direction and states of FIO5-6 and the voltage of DAC0 will
		///	 be updated.
		/// </summary>
		/// <returns>Negative number on error, 0 on success.</returns>
		private int feedback_example()
		{
			byte []sendBuff;
			byte []recBuff;
			ushort checksumTotal;
			uint recChars = 0;
			double voltage = 0;


			/* Update the direction and states of FIO5-6 and the voltage of DAC0 */

			if(updateFIODAC == true )
			{
				byte maskDirSt = 0;
				sendBuff = new byte[24];
				recBuff = new byte[10];

				sendBuff[1] = (byte)(0xF8);	//Command byte
				sendBuff[2] = 9;			//Number of data words (Hardware version < 1.30: .5 word 
											//for echo, 8 words for IOTypes and data, and .5 word for
											//the extra byte.  
											//For hardware version 1.30, .5 word for echo, 8.5 words 
											//for IOTypes and data)
				sendBuff[3] = (byte)(0x00);	//Extended command number

				sendBuff[6] = 0;			//Echo  

				sendBuff[7] = 29;			//IOType is PortDirWrite
				sendBuff[8] = 48;			//WriteMask - setting bits 4 and 5 (FIO4 and 5)
				sendBuff[9] = 0;			//WriteMask
				sendBuff[10] = 0;			//WriteMask

				if(fio4DirCB.Checked == true)
					maskDirSt += 16;		//setting (FIO4) as output
				if(fio5DirCB.Checked == true)
					maskDirSt += 32;		//setting (FIO5) of output
				
				sendBuff[11] = maskDirSt;	//Direction - Setting bits 4 and 5 (FIO4 and 5)
				sendBuff[12] = 0;			//Direction
				sendBuff[13] = 0;			//Direction
				
				sendBuff[14] = 27;			//IOType is PortStateWrite
				sendBuff[15] = maskDirSt;	//WriteMask
				sendBuff[16] = 0;			//WriteMask
				sendBuff[17] = 0;			//WriteMask

				maskDirSt = 0;
				if(fio4StateCB.Checked == true && fio4DirCB.Checked == true)
					maskDirSt += 16;		//setting (FIO4) as high
				
				if(fio5StateCB.Checked == true && fio5DirCB.Checked == true)
					maskDirSt += 32;		//setting (FIO5) of high
				
				sendBuff[18] = maskDirSt;	//State
				sendBuff[19] = 0;			//State
				sendBuff[20] = 0;			//State

				if(u3.calibrationInfo.hardwareVersion < 1.30)
				{
					sendBuff[21] = 34;		//IOType is DAC0 (8-bit)

					//Value of the DAC0 volts (in 8 bit binary form)
					u3.analogToCalibratedBinary8BitVoltage(0, dac0, ref sendBuff[22]);
					sendBuff[23] = 0;		//Extra byte
				}
				else
				{
					ushort binVoltage16 = 0;

					sendBuff[21] = 38;   //IOType is DAC0 (16-bit)

					//Value of the DAC0 volts (in 16 bit binary form)
					u3.analogToCalibratedBinary16BitVoltage(0, dac0, ref binVoltage16);

					sendBuff[22] = (byte)(binVoltage16&255);			//Value LSB
					sendBuff[23] = (byte)((binVoltage16&65280)/256);	//Value MSB
				}

				U3.extendedChecksum(ref sendBuff,24);

				if( U3.LJUSB_BulkWrite(u3.handle, U3.U3_PIPE_EP1_OUT, sendBuff, 24) < 24)
					return -1;
  
				if( U3.LJUSB_BulkRead(u3.handle, U3.U3_PIPE_EP1_IN, recBuff, 10) < 10)
					return -2;
  
				checksumTotal = U3.extendedChecksum16(recBuff, 10);
				if( (byte)((checksumTotal/256) & 0xff) != recBuff[5]
					|| (byte)(checksumTotal & 0xff) != recBuff[4])
					return -4;

				if( U3.extendedChecksum8(recBuff) != recBuff[0])
					return -3;
			
				if( recBuff[1] != (byte)(0xF8) || recBuff[3] != (byte)(0x00) )
					return -6;

				if( recBuff[6] != 0)
				{
					error = "Feedback error: received errorcode " + recBuff[6] + " in frame " + recBuff[7];
					return -100;
				}

				if( recBuff[2] != 2)
					return -6;

				updateFIODAC = false;
			}

			/* Reading the AIN0-4, FIO5-6 and counter1 */
			
			sendBuff = new byte[22];
			recBuff = new byte[24];


			sendBuff[1] = (byte)(0xF8);	//Command byte
			sendBuff[2] = 8;			//Number of data words (.5 word for echo, and 7.5 words for IOTypes 
										//and data)   
			sendBuff[3] = (byte)(0x00);	//Extended command number

			sendBuff[6] = 0;			//Echo

			sendBuff[7] = 1;			//IOType is AIN
			sendBuff[8] = 0;			//Positive channel is 0
			sendBuff[9] = 31;			//Negative channel is SE (31)
  
			sendBuff[10] = 1;			//IOType is AIN
			sendBuff[11] = 1;			//Positive channel is 1
			sendBuff[12] = 31;			//Negative channel is SE (31)
  
			sendBuff[13] = 1;			//IOType is AIN
			sendBuff[14] = 2;			//Positive channel is 2
			sendBuff[15] = 31;			//Negative channel is SE (31)
  
			sendBuff[16] = 1;			//IOType is AIN
			sendBuff[17] = 3;			//Positive channel is 3
			sendBuff[18] = 31;			//Negative channel is SE (31)

			sendBuff[19] = 26;			//IOType is PortStateRead
		
			sendBuff[20] = 55;			//IOType is Counter1
			sendBuff[21] = 0;			//Reset (bit 0) is not set

			U3.extendedChecksum(ref sendBuff,22);

			if( U3.LJUSB_BulkWrite(u3.handle, U3.U3_PIPE_EP1_OUT, sendBuff, 22) < 22)
				return -1;
  
			recChars = U3.LJUSB_BulkRead(u3.handle, U3.U3_PIPE_EP1_IN, recBuff, 24);
					
			checksumTotal = U3.extendedChecksum16(recBuff, Convert.ToInt32(recChars));

			if( (byte)((checksumTotal/256) & 0xff) != recBuff[5]
				|| (byte)(checksumTotal & 0xff) != recBuff[4])
				return -4;
			
			if( U3.extendedChecksum8(recBuff) != recBuff[0])
				return -3;
			
			if( recBuff[1] != (byte)(0xF8) || recBuff[3] != (byte)(0x00) )
				return -6;
			
			if( recBuff[6] != 0)
			{
				error = "Feedback error: received errorcode " + recBuff[6] + " in frame " + recBuff[7];
				switch(recBuff[7])
				{
					case 1: error += "(AIN0)\n"; break;
					case 2: error += "(AIN1)\n"; break;
					case 3: error += "(AIN2)\n"; break;
					case 4: error += "(AIN3)\n"; break;					
					case 5: error += "(PortStateRead)\n"; break;
					case 6: error += "(Counter1)\n"; break;
					default: error += "(Unknown)\n"; break;
				}
				return -100;
			}
			
			if( recBuff[2] != 9)
				return -6;

			//Converting AIN readings from 16 bit value to a voltage
			if(u3.calibrationInfo.hardwareVersion >= 1.30)
			{
				u3.binaryToCalibratedAnalogVoltage_hw130(0, 31, (ushort)(recBuff[9] + recBuff[10]*256), ref voltage); 
				ain0 = voltage;
				u3.binaryToCalibratedAnalogVoltage_hw130(1, 31, (ushort)(recBuff[11] + recBuff[12]*256), ref voltage);     
				ain1 = voltage;
				u3.binaryToCalibratedAnalogVoltage_hw130(2, 31, (ushort)(recBuff[13] + recBuff[14]*256), ref voltage); 
				ain2 = voltage;
				u3.binaryToCalibratedAnalogVoltage_hw130(3, 31, (ushort)(recBuff[15] + recBuff[16]*256), ref voltage);
				ain3 = voltage;
			}
			else
			{
				u3.binaryToCalibratedAnalogVoltage(false, 31, (ushort)(recBuff[9] + recBuff[10]*256), ref voltage); 
				ain0 = voltage;
				u3.binaryToCalibratedAnalogVoltage(false, 31, (ushort)(recBuff[11] + recBuff[12]*256), ref voltage);     
				ain1 = voltage;
				u3.binaryToCalibratedAnalogVoltage(false, 31, (ushort)(recBuff[13] + recBuff[14]*256), ref voltage); 
				ain2 = voltage;
				u3.binaryToCalibratedAnalogVoltage(false, 31, (ushort)(recBuff[15] + recBuff[16]*256), ref voltage);     
				ain3 = voltage;
			}

			//Checking if FIO4 (bit 4) state is high (1) or low (0)
			if(fio4DirCB.Checked == false)
			{
				if( (recBuff[17]&16) == 16 )
					fio4State = true;
				else
					fio4State = false;
			}

			//Checking if FIO5 (bit 5) state is high (1) or low (0)
			if(fio5DirCB.Checked == false)
			{
				if( (recBuff[17]&32) == 32 )
					fio5State = true;
				else
					fio5State = false;
			}

			//Getting the count of Counter1
			this.count1 = (uint)recBuff[20] + (uint)recBuff[21]*256 + (uint)recBuff[22]*65536 + (uint)recBuff[23]*16777216;

			//Updating the values and check boxes of the application
			this.Invoke(new EventHandler(updateAINLabels));
			this.Invoke(new EventHandler(updateFIOStateCB));
			this.Invoke(new EventHandler(updateCount1Label));

			return 0;
		}


		/// <summary>
		/// Gets the error message for the application (Does not translate U3 errorcodes).
		/// </summary>
		/// <param name="error">The negative number returned from a function.</param>
		/// <returns>The error message.</returns>
		private string getError(int error)
		{
			switch(error)
			{
				case 0: return("");  //no errors
				case -1: return("error : send failed");
				case -2: return("error : receive failed");
				case -3: return("error : received bad checksum8");
				case -4: return("error : received bad checksum16");
				case -5: return("error : received bad checksum");
				case -6: return("error : received wrong command bytes");
				case -7: return("error : received buffer has wrong IOType");
				case -200: return("error : received error code " + u3.errorcode + " from the response"); 
				default: return("error");
			}
		}

		private void updateErrorBox(object sender, System.EventArgs e)
		{
			errorBox.Text = error;
		}

		private void updateAINLabels(object sender, System.EventArgs e)
		{
			ain0lbl.Text = string.Format("{0:f3}", ain0);
			ain1lbl.Text = string.Format("{0:f3}", ain1);
			ain2lbl.Text = string.Format("{0:f3}", ain2);
			ain3lbl.Text = string.Format("{0:f3}", ain3);
		}

		private void updateFIOStateCB(object sender, System.EventArgs e)
		{
			fio4StateCB.Checked = fio4State;
			fio5StateCB.Checked = fio5State;		
		}

		private void updateCount1Label(object sender, System.EventArgs e)
		{
			count1lbl.Text = count1.ToString();
		}

		private void dac0Inc_Click(object sender, System.EventArgs e)
		{
			try
			{
				if(dac0 + 0.1 >= 5.0)
				{
					dac0 = 5;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				else if(dac0 + 0.1 <= 0.0)
				{
					dac0 = 0;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				else
				{
					dac0 += 0.1;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				updateFIODAC = true;
			}
			catch
			{}
		}

		private void dac0Dec_Click(object sender, System.EventArgs e)
		{
			try
			{
				if(dac0 - 0.1 <= 0.0)
				{
					dac0 = 0;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				else if(dac0 - 0.1 >= 5.0)
				{
					dac0 = 5;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				else
				{
					dac0 -= 0.1;
					dac0Box.Text = string.Format("{0:f3}", dac0);
				}
				updateFIODAC = true;
			}
			catch
			{}
		}

		private void dac0Box_Validating(object sender, System.ComponentModel.CancelEventArgs e)
		{
			double dac0Conv = 0;
			try
			{
				if((dac0Conv = Convert.ToDouble(dac0Box.Text)) != dac0)
				{
					if(dac0Conv > 5.0 || dac0Conv < 0.0)
					{
						dac0Box.Text = string.Format("{0:f3}", dac0);
					}
					else
					{
						dac0 = dac0Conv;
						dac0Box.Text = string.Format("{0:f3}", dac0);
					}
				}
			}
			catch
			{
				dac0Box.Text = string.Format("{0:f3}", dac0);
			}
			
			updateFIODAC = true;
		}
		
		private void focusClick(object sender, System.EventArgs e)
		{
			this.Focus();
		}

		private void u3Feedback_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			useUpdateTimer = false;
			exitApp = true;
		}

		private void fioDirCB_Click(object sender, System.EventArgs e)
		{
			updateFIODAC = true;
		}

		private void fio4StateCB_Click(object sender, System.EventArgs e)
		{
			
			if(fio4StateCB.Checked == true)
				fio4State = true;
			else
				fio4State = false;
			updateFIODAC = true;
		}

		private void fio5StateCB_Click(object sender, System.EventArgs e)
		{
			if(fio5StateCB.Checked == true)
				fio5State = true;
			else
				fio5State = false;
			updateFIODAC = true;
		}
	}
}
