//Author: LabJack
//July 18, 2007
//This example demonstates how to write and read some or all analog and digital
//I/O.  It records the time for 1000 iterations and divides by 1000, to allow
//measurement of the basic command/response communication times.  These times
//should be comparable to the Window's command/response communication times
//documented in Section 3.1 of the UE9 User's Guide.

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

namespace ue9AllIOUSB
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class AllIOUSBForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.NumericUpDown idBox;
		private System.Windows.Forms.Label idLabel;
		private System.Windows.Forms.Label errorLabel;
		private System.Windows.Forms.Button allIOButton;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.Label label1;
		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.TabControl tabControl1;
		private System.Windows.Forms.TabPage tabPage1;
		private System.Windows.Forms.TabPage tabPage2;
		private System.Windows.Forms.DataGridTableStyle dataGridTableStyle1;
		private System.Windows.Forms.DataGridTextBoxColumn dataGridTextBoxColumn1;
		private System.Windows.Forms.Label label6;
		private System.Windows.Forms.TextBox msPerIterBox;
		private System.Windows.Forms.TextBox statusBox;
		private System.Windows.Forms.TextBox ainBox;
		private System.Windows.Forms.TextBox dinBox;
		private System.Windows.Forms.NumericUpDown resBox;
		private System.Windows.Forms.NumericUpDown numAINBox;
		private System.Windows.Forms.NumericUpDown numIterBox;
		
		private UE9 ue9Dev;
		private int numChannels;   //Number of AIN channels, 0-16.
		private int ainResolution; 
		private int settlingTime;
		private long numIterations;
		private System.Windows.Forms.Label label7;
		private System.Windows.Forms.NumericUpDown settlingTimeBox;

		public AllIOUSBForm()
		{
			InitializeComponent();
			numChannels = 8;
			ainResolution = 12;
			settlingTime = 0;
			numIterations = 1000;
		}
		/// <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.idBox = new System.Windows.Forms.NumericUpDown();
			this.idLabel = new System.Windows.Forms.Label();
			this.errorLabel = new System.Windows.Forms.Label();
			this.statusBox = new System.Windows.Forms.TextBox();
			this.allIOButton = new System.Windows.Forms.Button();
			this.resBox = new System.Windows.Forms.NumericUpDown();
			this.label1 = new System.Windows.Forms.Label();
			this.numAINBox = new System.Windows.Forms.NumericUpDown();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.msPerIterBox = new System.Windows.Forms.TextBox();
			this.numIterBox = new System.Windows.Forms.NumericUpDown();
			this.label4 = new System.Windows.Forms.Label();
			this.label5 = new System.Windows.Forms.Label();
			this.ainBox = new System.Windows.Forms.TextBox();
			this.tabControl1 = new System.Windows.Forms.TabControl();
			this.tabPage1 = new System.Windows.Forms.TabPage();
			this.tabPage2 = new System.Windows.Forms.TabPage();
			this.dinBox = new System.Windows.Forms.TextBox();
			this.label6 = new System.Windows.Forms.Label();
			this.dataGridTableStyle1 = new System.Windows.Forms.DataGridTableStyle();
			this.dataGridTextBoxColumn1 = new System.Windows.Forms.DataGridTextBoxColumn();
			this.label7 = new System.Windows.Forms.Label();
			this.settlingTimeBox = new System.Windows.Forms.NumericUpDown();
			// 
			// idBox
			// 
			this.idBox.Location = new System.Drawing.Point(80, 208);
			this.idBox.Maximum = new System.Decimal(new int[] {
																  255,
																  0,
																  0,
																  0});
			this.idBox.Minimum = new System.Decimal(new int[] {
																  1,
																  0,
																  0,
																  -2147483648});
			this.idBox.Size = new System.Drawing.Size(56, 20);
			this.idBox.Value = new System.Decimal(new int[] {
																1,
																0,
																0,
																-2147483648});
			// 
			// idLabel
			// 
			this.idLabel.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.idLabel.Location = new System.Drawing.Point(8, 208);
			this.idLabel.Size = new System.Drawing.Size(64, 16);
			this.idLabel.Text = "Local ID :";
			// 
			// errorLabel
			// 
			this.errorLabel.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.errorLabel.Location = new System.Drawing.Point(8, 240);
			this.errorLabel.Size = new System.Drawing.Size(64, 20);
			this.errorLabel.Text = "Status:";
			// 
			// statusBox
			// 
			this.statusBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold);
			this.statusBox.Location = new System.Drawing.Point(72, 240);
			this.statusBox.ReadOnly = true;
			this.statusBox.Size = new System.Drawing.Size(160, 21);
			this.statusBox.Text = "";
			// 
			// allIOButton
			// 
			this.allIOButton.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.allIOButton.Location = new System.Drawing.Point(160, 208);
			this.allIOButton.Size = new System.Drawing.Size(72, 24);
			this.allIOButton.Text = "Run";
			this.allIOButton.Click += new System.EventHandler(this.allIOButton_Click);
			// 
			// resBox
			// 
			this.resBox.Location = new System.Drawing.Point(128, 48);
			this.resBox.Maximum = new System.Decimal(new int[] {
																   17,
																   0,
																   0,
																   0});
			this.resBox.Size = new System.Drawing.Size(48, 20);
			this.resBox.Value = new System.Decimal(new int[] {
																 12,
																 0,
																 0,
																 0});
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label1.Location = new System.Drawing.Point(8, 48);
			this.label1.Size = new System.Drawing.Size(104, 16);
			this.label1.Text = "Resolution :";
			this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight;
			// 
			// numAINBox
			// 
			this.numAINBox.Location = new System.Drawing.Point(128, 16);
			this.numAINBox.Maximum = new System.Decimal(new int[] {
																	  16,
																	  0,
																	  0,
																	  0});
			this.numAINBox.Size = new System.Drawing.Size(48, 20);
			this.numAINBox.Value = new System.Decimal(new int[] {
																	8,
																	0,
																	0,
																	0});
			// 
			// label2
			// 
			this.label2.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label2.Location = new System.Drawing.Point(8, 16);
			this.label2.Size = new System.Drawing.Size(104, 16);
			this.label2.Text = "# of AIN :";
			this.label2.TextAlign = System.Drawing.ContentAlignment.TopRight;
			// 
			// label3
			// 
			this.label3.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label3.Location = new System.Drawing.Point(8, 176);
			this.label3.Size = new System.Drawing.Size(112, 16);
			this.label3.Text = "ms per iteration :";
			// 
			// msPerIterBox
			// 
			this.msPerIterBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold);
			this.msPerIterBox.Location = new System.Drawing.Point(128, 176);
			this.msPerIterBox.ReadOnly = true;
			this.msPerIterBox.Size = new System.Drawing.Size(104, 21);
			this.msPerIterBox.Text = "";
			// 
			// numIterBox
			// 
			this.numIterBox.Location = new System.Drawing.Point(104, 112);
			this.numIterBox.Maximum = new System.Decimal(new int[] {
																	   2147483647,
																	   0,
																	   0,
																	   0});
			this.numIterBox.Size = new System.Drawing.Size(96, 20);
			this.numIterBox.Value = new System.Decimal(new int[] {
																	 1000,
																	 0,
																	 0,
																	 0});
			// 
			// 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(72, 32);
			this.label4.Text = "# of iterations :";
			// 
			// label5
			// 
			this.label5.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label5.Location = new System.Drawing.Point(40, 8);
			this.label5.Size = new System.Drawing.Size(40, 16);
			this.label5.Text = "AIN";
			// 
			// ainBox
			// 
			this.ainBox.AcceptsReturn = true;
			this.ainBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular);
			this.ainBox.Location = new System.Drawing.Point(16, 32);
			this.ainBox.Multiline = true;
			this.ainBox.ReadOnly = true;
			this.ainBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
			this.ainBox.Size = new System.Drawing.Size(88, 96);
			this.ainBox.Text = "";
			// 
			// tabControl1
			// 
			this.tabControl1.Controls.Add(this.tabPage1);
			this.tabControl1.Controls.Add(this.tabPage2);
			this.tabControl1.SelectedIndex = 0;
			this.tabControl1.Size = new System.Drawing.Size(240, 168);
			// 
			// tabPage1
			// 
			this.tabPage1.Controls.Add(this.settlingTimeBox);
			this.tabPage1.Controls.Add(this.label7);
			this.tabPage1.Controls.Add(this.numIterBox);
			this.tabPage1.Controls.Add(this.label4);
			this.tabPage1.Controls.Add(this.numAINBox);
			this.tabPage1.Controls.Add(this.label1);
			this.tabPage1.Controls.Add(this.resBox);
			this.tabPage1.Controls.Add(this.label2);
			this.tabPage1.Location = new System.Drawing.Point(4, 4);
			this.tabPage1.Size = new System.Drawing.Size(232, 142);
			this.tabPage1.Text = "Settings";
			// 
			// tabPage2
			// 
			this.tabPage2.Controls.Add(this.dinBox);
			this.tabPage2.Controls.Add(this.label6);
			this.tabPage2.Controls.Add(this.label5);
			this.tabPage2.Controls.Add(this.ainBox);
			this.tabPage2.Location = new System.Drawing.Point(4, 4);
			this.tabPage2.Size = new System.Drawing.Size(232, 142);
			this.tabPage2.Text = "Last Iteration Readings";
			// 
			// dinBox
			// 
			this.dinBox.AcceptsReturn = true;
			this.dinBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular);
			this.dinBox.Location = new System.Drawing.Point(128, 32);
			this.dinBox.Multiline = true;
			this.dinBox.ReadOnly = true;
			this.dinBox.Size = new System.Drawing.Size(72, 24);
			this.dinBox.Text = "";
			// 
			// label6
			// 
			this.label6.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))));
			this.label6.Location = new System.Drawing.Point(120, 8);
			this.label6.Size = new System.Drawing.Size(96, 24);
			this.label6.Text = "Digital Inputs";
			// 
			// dataGridTableStyle1
			// 
			this.dataGridTableStyle1.GridColumnStyles.Add(this.dataGridTextBoxColumn1);
			// 
			// dataGridTextBoxColumn1
			// 
			this.dataGridTextBoxColumn1.MappingName = "test";
			this.dataGridTextBoxColumn1.NullText = "(null)";
			// 
			// label7
			// 
			this.label7.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.label7.Location = new System.Drawing.Point(8, 80);
			this.label7.Size = new System.Drawing.Size(104, 16);
			this.label7.Text = "Settling Time :";
			this.label7.TextAlign = System.Drawing.ContentAlignment.TopRight;
			// 
			// settlingTimeBox
			// 
			this.settlingTimeBox.Location = new System.Drawing.Point(128, 80);
			this.settlingTimeBox.Maximum = new System.Decimal(new int[] {
																			255,
																			0,
																			0,
																			0});
			this.settlingTimeBox.Size = new System.Drawing.Size(56, 20);
			// 
			// AllIOUSBForm
			// 
			this.Controls.Add(this.tabControl1);
			this.Controls.Add(this.idBox);
			this.Controls.Add(this.idLabel);
			this.Controls.Add(this.errorLabel);
			this.Controls.Add(this.statusBox);
			this.Controls.Add(this.allIOButton);
			this.Controls.Add(this.msPerIterBox);
			this.Controls.Add(this.label3);
			this.Menu = this.mainMenu1;
			this.Text = "ue9AllIO USB";

		}
		#endregion

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

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

		private void allIOButton_Click(object sender, System.EventArgs e)
		{
			msPerIterBox.Text = "";
			ainBox.Text = "";
			dinBox.Text = "";
			statusBox.Text = "";

			ainResolution = Convert.ToInt32(resBox.Text);
			numIterations = Convert.ToInt64(numIterBox.Text);
			numChannels = Convert.ToInt32(numAINBox.Text);
			settlingTime = Convert.ToInt32(settlingTimeBox.Text);

			int err = 0;
			Error errorText = new Error(); 
			ue9Dev = new UE9();

			if((err = ue9Dev.openUSBConnection(Convert.ToInt32(idBox.Value))) < 0)
			{
				statusBox.Text = errorText.getError(err);
				return;
			}
			
			if( (err = ue9Dev.getCalibrationInfo()) < 0)
			{
				statusBox.Text = errorText.getError(err);
				ue9Dev.closeUSBConnection();				
				return;
			}

			if( (err = allIO()) < 0)
			{
				statusBox.Text = errorText.getError(err);
				ue9Dev.closeUSBConnection();				
				return;
			}
			
			if( (err = ue9Dev.closeUSBConnection()) < 0)
			{
				statusBox.Text = errorText.getError(err);
				return;
			}
		}

		/// <summary>
		///  Sends 1000 Feedback low-level commands to read digital IO and analog inputs.
		///  On the first send, the following are set: DAC0 to 2.5 volts, DAC1 to 3.5
		///  volts, and digital IOs to inputs.
		/// </summary>
		/// <returns>A negative value on error, 0 on success.</returns>
		private int allIO()
		{
			byte []sendBuff = new byte[34];
			byte []recBuff = new byte[64];
			uint sendChars = 0, recChars = 0;
			ushort checksumTotal = 0, bytesVoltage = 0;
			int initialize = 1;  //boolean to init. DAC and digital IO settings
			long time = 0;
			double []valueAIN = new double[16];
			int valueDIPort = 0;
			ushort ainMask = 0;
			int error = 0;

			for(int i = 0; i < 16; i++)
				valueAIN[i] = 9999.0;

			ainMask = (byte)(Math.Pow(2.0, numChannels) - 1);

			sendBuff[1] = (byte)(0xF8);  //command byte
			sendBuff[2] = (byte)(0x0E);  //number of data words
			sendBuff[3] = (byte)(0x00);  //extended command number

			sendBuff[6] = 255;  //FIOMask : setting the mask of all FIOs
			sendBuff[7] = 0;    //FIODir : setting all FIO directions to input
			sendBuff[8] = 0;    //FIOState : all FIO directions are input, so
								//           state writes do not apply
			sendBuff[9] = 255;  //EIOMask : setting the mask of all EIOs
			sendBuff[10] = 0;   //EIODir : setting all EIO directions to input
			sendBuff[11] = 0;   //EIOState : all EIO directions are input, so
								//           state writes do not apply
			sendBuff[12] = 15;  //CIOMask : setting the mask of all CIOs
			sendBuff[13] = 0;   //CIODirState : setting all CIO directions to input,
								//              state writes do not apply

			sendBuff[14] = 7;   //MIOMask : setting the mask of all MIOs
			sendBuff[15] = 0;   //MIODirState : setting all MIO directions to input,
								//              state writes do not apply

			//getting binary DAC0 value of 2.5 volts 
			if( (error = ue9Dev.analogToCalibratedBinaryVoltage(0, 2.500, ref bytesVoltage)) < 0)
				return error;

			//setting the voltage of DAC0 to 2.5
			sendBuff[16] = (byte)(bytesVoltage & 255);		//low bits of DAC0
			sendBuff[17] = (byte)(bytesVoltage/256 + 192);	//high bits of DAC0 
															//(bit 7 : Enable,
															//bit 6: Update)
															//getting binary DAC1 value of 3.5 volts
			if((error = ue9Dev.analogToCalibratedBinaryVoltage(1, 3.500, ref bytesVoltage)) < 0)
				return error;    

			//setting the voltage of DAC1 to 3.5 volts
			sendBuff[18] = (byte)(bytesVoltage & 255);		//low bits of DAC1
			sendBuff[19] = (byte)(bytesVoltage/256 + 192);	//high bits of DAC1 
															//(bit 7 : Enable,
															//bit 6: Update)

			//AINMask - reading the number of AINs specified by numChannels
			sendBuff[20] = (byte)(ainMask & 255);  //AINMask (low byte)
			sendBuff[21] = (byte)(ainMask/256);    //AINMask (high byte)
			sendBuff[22] = 14;             //AIN14ChannelNumber :  setting to channel 14
			sendBuff[23] = 15;             //AIN15ChannelNumber :  setting to channel 15
			sendBuff[24] = (byte)ainResolution;  //Resolution : Resolution specified by
			//             ainResolution
			sendBuff[25] = (byte)settlingTime;   //SettlingTime

			//setting all BipGains (Gain = 1, Bipolar = 1) 
			for(int i = 26; i < 34; i++)
				sendBuff[i] = 0;

			UE9.extendedChecksum(ref sendBuff, 34);
			
			statusBox.Text = "Reading AIN and DIO ";
			
			time = UE9.getTickCount();
			for(int i = 0; i < numIterations; i++)
			{
				//Sending command to UE9
				try
				{
					if((sendChars = UE9.LJUSB_BulkWrite(ue9Dev.handle, UE9.UE9_PIPE_EP1_OUT, sendBuff, 34)) < 34)
						throw new Exception();
				}
				catch
				{
					return -14;
				}

				//Reading response from UE9
				try
				{
					if((recChars = UE9.LJUSB_BulkRead(ue9Dev.handle, UE9.UE9_PIPE_EP1_IN, recBuff, 64)) < 64)
						throw new Exception();
				}
				catch
				{
					return -15;
				}

				checksumTotal = UE9.extendedChecksum16(recBuff, 64);
				if( (byte)((checksumTotal / 256) & 0xff) != recBuff[5] || (byte)(checksumTotal & 255) != recBuff[4])
					return -16;

				if( UE9.extendedChecksum8(recBuff) != recBuff[0])
					return -17;

				if(recBuff[1] != (byte)(0xF8) || recBuff[2] != (byte)(0x1D) || recBuff[3] != (byte)(0x00))
					return -10;

				for(int j = 0; j < numChannels && j < 16; j++)
					ue9Dev.binaryToCalibratedAnalogVoltage(0x00, (byte)ainResolution, (ushort)(recBuff[12 + j*2] + recBuff[13 + j*2]*256), ref valueAIN[j]);

				valueDIPort = recBuff[7] + recBuff[9]*256 + (recBuff[10] & 15)*65536 + (recBuff[11] & 7)*1048576;

				if(initialize == 1)
				{
					//unsetting digital IO bit masks since we only want to read states now 
					sendBuff[6] = 0;  //FIOMask 
					sendBuff[9] = 0;  //EIOMask
					sendBuff[12] = 0; //CIOMask 
					sendBuff[14] = 0; //MIOMask 

					//turning off Update bit of DACs
					sendBuff[17] = (byte)(sendBuff[17] - 64);  //high bits of DAC0  
					sendBuff[19] = (byte)(sendBuff[19] - 64);  //high bits of DAC1 

					UE9.extendedChecksum(ref sendBuff, 34);

					initialize = 0;
				}
			}
			time = UE9.getTickCount() - time;

			msPerIterBox.Text = string.Format("{0:f3}", ((double)time / (double)numIterations));
			dinBox.Text = valueDIPort.ToString();
			ainBox.Text = "";

			for(int j = 0; j < numChannels; j++)
				ainBox.Text += j + " : " + 	string.Format("{0:f3}", valueAIN[j]) + "\r\n";

			statusBox.Text = "Done";
			return 0;
		}
	}
}
