using System;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using CgpibCs;

namespace CSubFuncCs
{
	/// <summary>
	/// Summary description for CSubFunc.
	/// </summary>
	public class CSubFunc
	{
		public CSubFunc()
		{
			// 
			// TODO: Add constructor logic here
			//
		}

		Cgpib	gpib = new Cgpib();

		///// [CheckRet] Function /////////////////////////////////////////////////////////////////////////////////////
		public int CheckRet(string Func, uint Ret, out string csBuf)
		{
			int	RetCode,Ret1;

			csBuf = new String('0', 1);
			RetCode = 0;										// Normality
			Ret1 = (int)Ret & 0xff;								// 0xFF Masking
			if (Ret1 >= 3)
			{													// Unusual
				RetCode = 1;									// Return of function(Unusual)
				switch (Ret1)
				{
					case 80:	csBuf = Func + " : It is I/O address error.";							break; // 0x50
					case 82:	csBuf = Func + " : Resistry setup is wrong. Review resistry setup.";	break; // 0x52
					case 128:	csBuf = Func + " : Data receiving was exceeded.and polling is not.";	break; // 0x80
					case 140:	csBuf = Func + " : Asynchronous function is executing now.";			break; // 0x8C
					case 141:	csBuf = Func + " : Asynchronous function is Stopped by GpStopAsync().";	break; // 0x8D
					case 200:	csBuf = Func + " : Thread can not be made.";							break; // 0xC8
					case 201:	csBuf = Func + " : Other event is in practice.";						break; // 0xC9
					case 210:	csBuf = Func + " : DMA could not be established.";						break; // 0xD2
					case 240:	csBuf = Func + " : [Esc] key was pushed.";								break; // 0xF0
					case 241:	csBuf = Func + " : It is an I/O error of file.";						break; // 0xF1
					case 242:	csBuf = Func + " : Address appoint is wrong.";							break; // 0xF2
					case 243:	csBuf = Func + " : Buffer Error.";										break; // 0xF3
					case 244:	csBuf = Func + " : Error of array size.";								break; // 0xF4
					case 245:	csBuf = Func + " : A buffer is too small.";								break; // 0xF5
					case 246:	csBuf = Func + " : It is an unjust object name.";						break; // 0xF6
					case 247:	csBuf = Func + " : A side check of a device name is invalid.";			break; // 0xF7
					case 248:	csBuf = Func + " : It is an unjust data model.";						break; // 0xF8
					case 249:	csBuf = Func + " : Device can not be added further.";					break; // 0xF9
					case 250:	csBuf = Func + " : A device name is not found out.";					break; // 0xFA
					case 251:	csBuf = Func + " : Delimiter is wrong between device.";					break; // 0xFB
					case 252:	csBuf = Func + " : It is an error of GP-IB.";							break; // 0xFC
					case 253:	csBuf = Func + " : Only a delimiter was receiving.";					break; // 0xFD
					case 254:	csBuf = Func + " : It was done a time out.";							break; // 0xFE
					case 255:	csBuf = Func + " : It is a parameter error.";							break; // 0xFF
					default:	break;
				}
			}
			else
			{
				csBuf = Func + " : It was terminated normally.";
			}

			// It was message when [Ifc] [Srq] received.		//
			Ret1 = (int)Ret & 0xff00;							// 0xFF Masking
			switch (Ret1)
			{
				case 0x100:		csBuf = Func + "-[SRQ] was receiving.<STATUS>";						break; // [256]decimal
				case 0x200:		csBuf = Func + "-[IFC] was receiving.<STATUS>";						break; // [512]decimal
				case 0x300:		csBuf = Func + "-[SRQ],[IFC] was receiving.<STATUS>";				break; // [768]decimal
				default:		break;
			}
			return	RetCode;
		}

		///// [Square] Function ///////////////////////////////////////////////////////////////////////////////////////
		public int Square(int x, int y)
		{
			int	tmp = 1;

			while (y-- > 0)										// Repeating counts 
				tmp *= x;										// Multiply
			return(tmp);
		}

		///// [Chr -> Hex] Function ///////////////////////////////////////////////////////////////////////////////////
		public uint chr2hex(string ch)
		{
			int	ret = 0, rettmp = 0;
			int	count, length;

			length	= ch.Length;								// Search length of ch 
			for (count = 0; count < length; count++)
			{													// Repeat
				if ((ch[count] >= 0x30) && (ch[count] <= 0x39))	// Get ASCII code to number
				{
					ret = (ch[count] - 0x30) * Square(0x10,(length - (count + 1)));	// 0 - 9 
				}
				else if ((ch[count] >= 0x41) && (ch[count] <= 0x46))
				{
					ret = (ch[count] - 0x37) * Square(0x10,(length - (count + 1)));	// A - F
				}
				else if ((ch[count] >= 0x61) && (ch[count] <= 0x66))
				{
					ret = (ch[count] - 0x57) * Square(0x10,(length - (count + 1)));	// a - f
				}
				else
				{
					ret = 0xff;									// Return is wrong when ret = 0xFF
				}

				rettmp = rettmp + ret;
			}
			return (uint)rettmp;
		}

		///// [Initialize] Function ///////////////////////////////////////////////////////////////////////////////////
		public int GpibInit(out string TextRet)
		{
//			uint	Delim, Eoi;
			uint	Ret;
			uint	Timeout, Ifctime;
			uint	Master;
			string	csBuf;

			Ret = gpib.Exit();									// Keep off initialize repeat
			Ret = gpib.Ini();									// GP-IB initialize
			CheckRet("GpIni", Ret, out csBuf);
			if ((Ret & 0xFF) != 0)
			{													// Check of GpIni
				TextRet = csBuf;
				return	1;
			}

			gpib.Boardsts(0x0a, out Master);					// Get Master/Slave mode
			if (Master == 0)
			{
				Ifctime = 1;									// Default
				Ret = gpib.Ifc(Ifctime);
				CheckRet("GpIfc", Ret, out csBuf);
				if ((Ret & 0xFF) != 0)
				{												// Check of GpIfc
					TextRet = csBuf;
					return	1;
				}
				Ret = gpib.Ren();
				CheckRet("GpRen", Ret, out csBuf);
				if ((Ret & 0xFF) != 0)
				{												// Check of GpRen
					TextRet = csBuf;
					return	1;
				}
			}

//			Delim = 1;											// CR+LF (Default)
//			Eoi = 1;											// (Default)
//			Ret = gpib.Delim(Delim, Eoi);
//			CheckRet("GpDelim", Ret, out csBuf);
//			if ((Ret & 0xFF) != 0)
//			{													// Check of GpDelim
//				TextRet = csBuf;
//				return	1;
//			}
			Timeout = 10000;									// 10000ms (Default)
			Ret = gpib.Timeout(Timeout);
			CheckRet("GpTimeout", Ret, out csBuf);
			if ((Ret & 0xFF) != 0)
			{													// Check of GpTimeout
				TextRet = csBuf;
				return	1;
			}

			TextRet = "Initialized.";							// Normality Ended.
			return	0;
		}

		///// [Exit] Function /////////////////////////////////////////////////////////////////////////////////////////
		public void GpibExit()
		{
			uint	Master;										// Master/Slave mode flag
			uint	Ret;
			uint[]	Cmd = new uint[32];
	
			Ret = gpib.Boardsts(0x0a, out Master);				// Mode check
			if (Ret == 80) return;								// If found error then not doing 
	
			if (Master == 0)
			{													// When mode is Master
				Cmd[0] = 2;										// Command count
				Cmd[1] = 0x3f;									// Unlisten / UNL
				Cmd[2] = 0x5f;									// UnTalken / UNT
				Ret = gpib.Comand(Cmd);							// Send command
				Ret = gpib.Resetren();							// Cancel remote
			}
			Ret = gpib.Exit();
		}

		///// [Str -> Num] Function ///////////////////////////////////////////////////////////////////////////////////
		public void Str2Num(string str, uint str_len , ref int[] num, uint num_len)
		{
			int		i, j=0, cnt;
			string	start;

			start = str;
			cnt = 0;
			for (i = 0; i < str_len; i++)
			{
				/* string to integer */
				if (str[i] == ',') 
				{
					if (i == 1)
					{
						start = str.Substring(j, i-j);
					}
					else
					{
						start = str.Substring(j, i-j);
					}
					try
					{
						num[cnt] = Convert.ToInt32(start);
					}
					catch (System.FormatException)
					{
						num[cnt] = 0;
					}
					j = i + 1;
					cnt++;
					if (cnt >= num_len)
					{
						break;
					}
				}
			}
			if (cnt >= num_len)
			{
				try
				{
					num[cnt] = Convert.ToInt32(start);
				}
				catch (System.FormatException)
				{
					num[cnt] = 0;
				}
			}
		}

		///// [Draw Graphic] Function /////////////////////////////////////////////////////////////////////////////////
		public void DrawGraph(Control Picture, int[] num, uint num_len, int min, int max)
		{
			Rectangle	Rect = Picture.ClientRectangle;
			Pen			hPen_Black, hPen_Red, hPen_White;
			Point[]		point = new Point[4];
			int			x_max, y_max;
			int			x_width, y_width;
			float		x_unit, y_unit;
			uint		i;

			/* Initialize */
			x_max = Rect.Right;
			y_max = Rect.Bottom;
			Graphics g = Picture.CreateGraphics();

			hPen_Black	= new Pen(Color.Black, 1);				/* Black */
			hPen_Red	= new Pen(Color.Red, 1);				/* Red   */
			hPen_White	= new Pen(Color.White, 1);				/* White */	
			/* Draw Structure */
			SolidBrush whiteBrush = new SolidBrush(Color.White);
			g.FillRectangle(whiteBrush, Picture.ClientRectangle);
			for (i = 0; i <= 10; i++)
			{
				g.DrawLine(hPen_Black, (x_max / 10) * i, 0, (x_max / 10) * i, y_max);
			}
			for (i = 0; i <= 10; i++)
			{
				g.DrawLine(hPen_Black, 0, (y_max / 10) * i, x_max, (y_max / 10) * i); 
			}
			point[0].X = (x_max / 10) * 5 - 1;	point[0].Y = 0;
			point[1].X = (x_max / 10) * 5 + 1;	point[1].Y = 0;
			point[2].X = (x_max / 10) * 5 + 1;	point[2].Y = y_max;
			point[3].X = (x_max / 10) * 5 - 1;	point[3].Y = y_max;
			g.DrawLines(hPen_Red, point);
			point[0].X = 0;		point[0].Y = (y_max / 10) * 5 - 1;
			point[1].X = 0;		point[1].Y = (y_max / 10) * 5 + 1;
			point[2].X = x_max;	point[2].Y = (y_max / 10) * 5 + 1;
			point[3].X = x_max;	point[3].Y = (y_max / 10) * 5 - 1;
			g.DrawLines(hPen_Red, point);
			/* Draw Graph */
			x_width = (int)num_len;
			y_width = max - min;
			x_unit = (float)((float)x_max / (float)x_width);
			y_unit = (float)((float)y_max / (float)y_width);
			for (i = 0; i < (num_len - 1); i++)
			{
				g.DrawLine(hPen_Black, x_unit * i, (y_width - (num[i] - min)) * y_unit, x_unit * (i + 1), (y_width - (num[i+1] - min)) * y_unit);
			}
		}

		// New function(Use Oscillo2/Tektronix TDS3000Series)

		///// [ GpibPrint ] function //////////////////////////////////////////////////////////////////////////////////
		public int GpibPrint(uint DevAddr, string Str)
		{
			string	srbuf = new string(' ', 10000);
			uint	MyAddr;
			uint[]	Cmd = new uint[16];
			string	ErrText;
			uint	Ret;
			int		RetTmp;
			uint	srlen;

			Ret = gpib.Boardsts(0x08, out MyAddr);
			Cmd[0] = 2;
			Cmd[1] = MyAddr;
			Cmd[2] = DevAddr;

			srlen = (uint)Str.Length;
			srbuf = Str;
			Ret = gpib.Talk(Cmd, srlen, srbuf);

			if (Ret >= 3)
			{
				RetTmp = CheckRet("GpTalk", Ret, out ErrText);
				ErrText += "Continue?";
				DialogResult Resul = MessageBox.Show(ErrText, null, MessageBoxButtons.YesNo);
				if (Resul == DialogResult.No)
				{
					return 1;
				}
			}
			return 0;
		}

		///// [ GpibInput ] function //////////////////////////////////////////////////////////////////////////////////
		public int GpibInput(uint DevAddr, StringBuilder Str)
		{
			uint	MyAddr,srlen;
			uint[]	Cmd = new uint[16];
			string	/*TmpStr, */ErrText;
			uint	Ret;
			int		RetTmp;

			Ret = gpib.Boardsts(0x08, out MyAddr);
			Cmd[0] = 2;
			Cmd[1] = DevAddr;
			Cmd[2] = MyAddr;
			srlen = 10000;
			Ret = gpib.Listen(Cmd, ref srlen, Str);
			if (Ret >= 3)
			{
				RetTmp = CheckRet("GpListen", Ret, out ErrText);
				ErrText += "Continue?";
				DialogResult Resul = MessageBox.Show(ErrText, null, MessageBoxButtons.YesNo);
				if (Resul == DialogResult.No)
				{
					return 1;
				}
			}
			return 0;
		}

		// Add HIOKI
		///// [ GpibInputHioki Function ] function /////////////////////////////////////////////////////////////////////////////////
		public int GpibInputHioki(uint DevAddr, StringBuilder Str)
		{
			StringBuilder Srbuf = new StringBuilder(10000);		// String buffer
			uint	Srlen;										// String length
			uint	MyAddr;										// My address
			uint[]	Cmd = new uint[16];							// Message(command)
			string	ErrText;									// Error string
			uint	Ret;										// Return string

			Ret = gpib.Boardsts(0x08, out MyAddr);				// Get my address
			Cmd[0] = 2;											// Number of command
			Cmd[1] = DevAddr;									// Slave device
			Cmd[2] = MyAddr;									// My address(PC)

			Str.Clear();										// Initialise
			while (true)
			{
				Srlen = 10000;									// Max receive size
				Ret = gpib.Listen(Cmd, ref Srlen, Srbuf);
				if (Ret <= 2) 
				{												// Complete
					Srbuf.Remove(Convert.ToInt32(Srlen), Srbuf.Length - Convert.ToInt32(Srlen));
					Str.Append(Srbuf);
					break;
				}
				else if (Ret == 128)
				{												// Over
					Srbuf.Remove(Convert.ToInt32(Srlen), Srbuf.Length - Convert.ToInt32(Srlen));
					Str.Append(Srbuf);
					Cmd[0] = 0;									// GpListen
				}
				else
				{												// Error check
					CheckRet("GpListen", Ret, out ErrText);
					MessageBox.Show(ErrText, null, MessageBoxButtons.OK);
					return 1;									// Invalid
				}
			}
			return 0;											// Valid
		}

		///// [ GpibInputB ] function /////////////////////////////////////////////////////////////////////////////////
		public int GpibInputB(uint DevAddr, StringBuilder IntData)
		{
			StringBuilder	szData = new StringBuilder(10000);
			uint			Ret, MyAddr, srlen;
			int				RetTmp;
			uint[]			Cmd = new uint[8];
			string			ErrText = "";
			string			szDataVal;
			int				i;

			Ret = gpib.Delim(0, 1);
			Ret = gpib.Boardsts(0x08, out MyAddr);
			Cmd[0] = 2;
			Cmd[1] = DevAddr;
			Cmd[2] = MyAddr;
			srlen = 2;
			Ret = gpib.Listen(Cmd, ref srlen, szData);
			if (Ret >= 3)
			{
				RetTmp = CheckRet("GpListen", Ret, out ErrText);
				ErrText += "Continue?";
				DialogResult Resul = MessageBox.Show(ErrText, null, MessageBoxButtons.YesNo);
				if (Resul == DialogResult.No)
				{
					return 1;
				}
			}
			Cmd[0] = 0;
			szDataVal = szData.ToString().Substring(1, 1);
			for (i = 0; i < szDataVal.Length; i++)
			{
				if (Char.IsDigit(szDataVal, i) == false)
				{
					break;
				}
			}			
			szDataVal = szDataVal.Substring(0, i);
			if (i == 0)
			{
				srlen = 0;
			}
			else
			{
				srlen = uint.Parse(szDataVal);
			}

			Ret = gpib.Listen(Cmd, ref srlen, szData);
			
			for (i = 0; i < szData.Length; i++)
			{
				if (Char.IsDigit(szData.ToString(), i) == false)
				{
					break;
				}
			}
			szDataVal = szData.ToString().Substring(0, i);
			if (i == 0)
			{
				srlen = 1;
			}
			else
			{
				srlen = uint.Parse(szDataVal) + 1;
			}
			
			Ret = gpib.Listen(Cmd, ref srlen, IntData);
			Ret = gpib.Delim(3, 1);
			return 0;
		}

		///// [ GpibCommand ] /////////////////////////////////////////////////////////////////////////////////////////
		public int GpibCommand(uint DevAddr)
		{
			uint[]	Cmd = new uint[16];
			string	ErrText;
			uint	Ret;
			int		RetTmp;

			Cmd[0] = 2;
			Cmd[1] = 0x3F;
			Cmd[2] = 0x5F;

			Ret = gpib.Comand(Cmd);

			if (Ret != 0)
			{
				RetTmp = CheckRet("GpComand", Ret, out ErrText);
				MessageBox.Show(ErrText, null, MessageBoxButtons.OK);
				return 1;
			}
			return 0;
		}

		///// [ WaitOPC ] function ////////////////////////////////////////////////////////////////////////////////////
		public void WaitOPC(uint Dev)
		{
			int				Ret;
			StringBuilder	RdData = new StringBuilder(10000);

			Ret = GpibPrint(Dev, "*OPC?");
			Ret = GpibInput(Dev, RdData);
		}
	}
}
