//Author: LabJack
//July 18, 2007
//This example program calls the TimerCounter function, and reads both
//counters and enables 2 timers with PWM output.  Connect FIO0/FIO1 to 
//FIO2/FIO3 to have the counter read something.  After 1 second the
//counters' counts are outputted to the screen.

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

namespace ue9TimerCounter
{
	public class timerCounterUSBForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Label errorLabel;
		private System.Windows.Forms.TextBox errorBox;
		private System.Windows.Forms.Button timerCounterButton;
		private System.Windows.Forms.TextBox counter0Box;
		private System.Windows.Forms.Label counter0Text;
		private System.Windows.Forms.TextBox timerClockDivisorBox;
		private System.Windows.Forms.Label timerClockDivisorText;
		private System.Windows.Forms.TextBox counter1Box;
		private System.Windows.Forms.Label counter1Text;
		private System.Windows.Forms.Label messageText;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.Label idLabel;
		private System.Windows.Forms.NumericUpDown idBox;
		private UE9 ue9Dev;

		public timerCounterUSBForm()
		{
			InitializeComponent();
		}
		/// <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.idLabel = new System.Windows.Forms.Label();
			this.errorLabel = new System.Windows.Forms.Label();
			this.errorBox = new System.Windows.Forms.TextBox();
			this.timerCounterButton = new System.Windows.Forms.Button();
			this.counter0Box = new System.Windows.Forms.TextBox();
			this.counter0Text = new System.Windows.Forms.Label();
			this.timerClockDivisorBox = new System.Windows.Forms.TextBox();
			this.timerClockDivisorText = new System.Windows.Forms.Label();
			this.counter1Box = new System.Windows.Forms.TextBox();
			this.counter1Text = new System.Windows.Forms.Label();
			this.messageText = new System.Windows.Forms.Label();
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.idBox = new System.Windows.Forms.NumericUpDown();
			// 
			// 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(96, 16);
			this.idLabel.Text = "UE9 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(40, 20);
			this.errorLabel.Text = "Error:";
			// 
			// errorBox
			// 
			this.errorBox.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold);
			this.errorBox.Location = new System.Drawing.Point(56, 240);
			this.errorBox.ReadOnly = true;
			this.errorBox.Size = new System.Drawing.Size(176, 21);
			this.errorBox.Text = "";
			// 
			// timerCounterButton
			// 
			this.timerCounterButton.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.timerCounterButton.Location = new System.Drawing.Point(88, 144);
			this.timerCounterButton.Size = new System.Drawing.Size(72, 24);
			this.timerCounterButton.Text = "Run";
			this.timerCounterButton.Click += new System.EventHandler(this.timerCounterButton_Click);
			// 
			// counter0Box
			// 
			this.counter0Box.Location = new System.Drawing.Point(136, 64);
			this.counter0Box.ReadOnly = true;
			this.counter0Box.Size = new System.Drawing.Size(80, 22);
			this.counter0Box.Text = "";
			// 
			// counter0Text
			// 
			this.counter0Text.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.counter0Text.Location = new System.Drawing.Point(16, 64);
			this.counter0Text.Size = new System.Drawing.Size(112, 32);
			this.counter0Text.Text = "Counter0 (FIO2) after 1 sec:";
			// 
			// timerClockDivisorBox
			// 
			this.timerClockDivisorBox.Location = new System.Drawing.Point(192, 176);
			this.timerClockDivisorBox.MaxLength = 3;
			this.timerClockDivisorBox.Size = new System.Drawing.Size(40, 22);
			this.timerClockDivisorBox.Text = "3";
			// 
			// timerClockDivisorText
			// 
			this.timerClockDivisorText.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.timerClockDivisorText.Location = new System.Drawing.Point(8, 176);
			this.timerClockDivisorText.Size = new System.Drawing.Size(176, 16);
			this.timerClockDivisorText.Text = "TimerClockDivisor (0-255):";
			// 
			// counter1Box
			// 
			this.counter1Box.Location = new System.Drawing.Point(136, 104);
			this.counter1Box.ReadOnly = true;
			this.counter1Box.Size = new System.Drawing.Size(80, 22);
			this.counter1Box.Text = "";
			// 
			// counter1Text
			// 
			this.counter1Text.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.counter1Text.Location = new System.Drawing.Point(16, 104);
			this.counter1Text.Size = new System.Drawing.Size(112, 32);
			this.counter1Text.Text = "Counter1 (FIO3) after 1 sec:";
			// 
			// messageText
			// 
			this.messageText.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
			this.messageText.Location = new System.Drawing.Point(16, 8);
			this.messageText.Size = new System.Drawing.Size(208, 48);
			this.messageText.Text = "FIO0 is a Timer with 16 bit PWM output.  FIO1 is a Timer with 8 bit PWM output.";
			// 
			// idBox
			// 
			this.idBox.Location = new System.Drawing.Point(112, 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});
			// 
			// timerCounterUSBForm
			// 
			this.Controls.Add(this.idBox);
			this.Controls.Add(this.messageText);
			this.Controls.Add(this.counter1Box);
			this.Controls.Add(this.counter1Text);
			this.Controls.Add(this.timerClockDivisorBox);
			this.Controls.Add(this.timerClockDivisorText);
			this.Controls.Add(this.counter0Box);
			this.Controls.Add(this.counter0Text);
			this.Controls.Add(this.timerCounterButton);
			this.Controls.Add(this.idLabel);
			this.Controls.Add(this.errorLabel);
			this.Controls.Add(this.errorBox);
			this.Menu = this.mainMenu1;
			this.MinimizeBox = false;
			this.Text = "ue9TimerCounter USB";

		}
		#endregion

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

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

		private void timerCounterButton_Click(object sender, System.EventArgs e)
		{
			int err = 0;
			Error errorText = new Error(); 
			ue9Dev = new UE9();
			errorBox.Text = "";
			counter0Box.Text = "";
			counter1Box.Text = "";

			if((err = ue9Dev.openUSBConnection(Convert.ToInt32(idBox.Value))) < 0)
			{
				errorBox.Text = errorText.getError(err);// + ;
				return;
			}

			
			if( (err = timerCounter_example()) <= -1)
			{
				errorBox.Text = errorText.getError(err);
				if(err == -18)
					errorBox.Text += ue9Dev.errorcode;

				ue9Dev.closeUSBConnection();				
				return;
			}			
			
			if( (err = ue9Dev.closeUSBConnection()) <= -1)
			{
				errorBox.Text = errorText.getError(err);
				return;
			}
		}

		int timerCounter_example()
		{
			byte []sendBuff = new byte[30];
			byte []recBuff = new byte[40];
			int err = 0;
			uint cnt = 0;
			uint divisor = 0;

			try
			{
				divisor = Convert.ToUInt32(timerClockDivisorBox.Text);
				if(divisor < 0 || divisor > 255)
					throw(new Exception());
			}
			catch
			{
				return -19;
			}

			//
			//Enable timers and counters   
			//
			sendBuff[1] = (byte)(0xF8);  //command byte
			sendBuff[2] = (byte)(0x0C);  //number of data words
			sendBuff[3] = (byte)(0x18);  //extended command number
			sendBuff[6] = (byte)(divisor);  //TimerClockDivisor = divisor
			sendBuff[7] = (byte)(0x9A);  //EnableMask : Updating Config,  2 Timers enabled, Counter0 and Counter1 enabled
			sendBuff[8] = (byte)(0x00);  //TimerClockConfig = 750 kHz (if using system clock, call
			                             //ControlConfig first and set the PowerLevel to a fixed state)
			sendBuff[9] = (byte)(0x00);  //UpdateReset: not reseting anything
			sendBuff[10] = (byte)(0x00); //Timer0Mode = 16-Bit PWM
			
			//Timer0Value = 32768
			sendBuff[11] = (byte)(0x00); //Timer0Value (low byte)
			sendBuff[12] = (byte)(0x80); //Timer0Value (high byte)
			sendBuff[13] = (byte)(0x01); //Timer1Mode = 8-Bit PWM
			
			//Timer0Value = 32768
			sendBuff[14] = (byte)(0x00); //Timer0Value (low byte)
			sendBuff[15] = (byte)(0x80); //Timer0Value (high byte)
  
			for(int i = 16; i < 28; i++)
				sendBuff[i] = (byte)(0x00);

			sendBuff[28] = (byte)(0x00);  //Counter0Mode (pass 0)
			sendBuff[29] = (byte)(0x00);  //Counter1Mode (pass 0) 

			UE9.extendedChecksum(ref sendBuff, 30);

			try
			{
				if(UE9.LJUSB_BulkWrite(ue9Dev.handle, UE9.UE9_PIPE_EP1_OUT, sendBuff, 30) != 30)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -14;
			}

			try
			{
				if(UE9.LJUSB_BulkRead(ue9Dev.handle, UE9.UE9_PIPE_EP1_IN, recBuff, 40) != 40)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -15;
			}

			if((err = errorCheck(recBuff)) < 0)
				return err;

			//
			//wait 1 sec, read counters
			//
			System.Threading.Thread.Sleep(1000);  

			//Not updating our configuration, just want to read back the counters
			for(int i = 6; i < 30; i++)
				sendBuff[i] = (byte)(0x00);

			UE9.extendedChecksum(ref sendBuff, 30);
			
			try
			{
				if(UE9.LJUSB_BulkWrite(ue9Dev.handle, UE9.UE9_PIPE_EP1_OUT, sendBuff, 30) != 30)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -14;
			}

			try
			{
				if(UE9.LJUSB_BulkRead(ue9Dev.handle, UE9.UE9_PIPE_EP1_IN, recBuff, 40) != 40)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -15;
			}

			if((err = errorCheck(recBuff)) < 0)
				return err;

			cnt = (uint)recBuff[32] + ((uint)recBuff[33] << 8) + ((uint)recBuff[34] << 16) + ((uint)recBuff[35] << 24);
			counter0Box.Text = cnt.ToString();
			cnt = (uint)recBuff[36] + ((uint)recBuff[37] << 8) + ((uint)recBuff[38] << 16) + ((uint)recBuff[39] << 24);
			counter1Box.Text = cnt.ToString();

			//
			//disable timers and counters
			//
			sendBuff[6] = (byte)(0x00);  //TimerClockDivisor = 0
			sendBuff[7] = (byte)(0x80);  //Updating: 0 Timers enabled, Counter0 and Counter1 disabled 

			//setting bytes 8 - 30 to zero since nothing is enabled
			for(int i = 8; i < 30; i++)
				sendBuff[i] = (byte)(0x00);

			UE9.extendedChecksum(ref sendBuff, 30);

			try
			{
				if(UE9.LJUSB_BulkWrite(ue9Dev.handle, UE9.UE9_PIPE_EP1_OUT, sendBuff, 30) != 30)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -14;
			}

			try
			{
				if(UE9.LJUSB_BulkRead(ue9Dev.handle, UE9.UE9_PIPE_EP1_IN, recBuff, 40) != 40)
					throw new Exception();
			}
			catch(System.Exception)
			{
				return -15;
			}

			if((err = errorCheck(recBuff)) < 0)
				return err;

			return 1;
		}


		int errorCheck(byte []buffer)
		{
			ushort checksumTotal;

			checksumTotal = UE9.extendedChecksum16(buffer, 40);
			if( (byte)((checksumTotal / 256) & 0xff) != buffer[5])
				return -16;

			if( (byte)(checksumTotal & 0xff) != buffer[4])
				return -16;

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

			if(buffer[1] != (byte)(0xF8) || buffer[2] != (byte)(0x11) || buffer[3] != (byte)(0x18))
				return -10;
  
			if( buffer[6] != 0)
			{
				ue9Dev.errorcode = (int)buffer[6];
				return -18;
			}

			return 0;
		}
	}
}
