using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HTRA_CSharp_Examples
{
    class IQS_GetIQdata_Standard
    {
		public void Example()
		{
			#region 1 Open device

			int Status = 0;              //Function return value.
			IntPtr Device = IntPtr.Zero; //Current device memory address.
			int DevNum = 0;              //Specify device number.

			HtraApi.BootProfile_TypeDef BootProfile = new HtraApi.BootProfile_TypeDef(); //Boot configuration structure, including physical interface, power supply, etc.
			HtraApi.BootInfo_TypeDef BootInfo = new HtraApi.BootInfo_TypeDef();          //Boot info structure, including device information, USB speed, etc.

			BootProfile.DevicePowerSupply = HtraApi.DevicePowerSupply_TypeDef.USBPortAndPowerPort; //Use both USB data port and independent power port for dual power supply.


			//If the device data interface is USB, run directly. If it's Ethernet, change #if true to #if false
#if true
			BootProfile.PhysicalInterface = HtraApi.PhysicalInterface_TypeDef.USB;
#else
			//Configure network parameters
			BootProfile.PhysicalInterface = HtraApi.PhysicalInterface_TypeDef.ETH;
			BootProfile.ETH_IPVersion = HtraApi.IPVersion_TypeDef.IPv4;
			BootProfile.ETH_RemotePort = 5000;
			BootProfile.ETH_ReadTimeOut = 5000;
			BootProfile.ETH_IPAddress = new byte[16];
			BootProfile.ETH_IPAddress[0] = 192;
			BootProfile.ETH_IPAddress[1] = 168;
			BootProfile.ETH_IPAddress[2] = 1;
			BootProfile.ETH_IPAddress[3] = 100;
#endif

			Status = HtraApi.Device_Open(ref Device, DevNum, ref BootProfile, ref BootInfo); //Open the device

			if (Status == 0)
			{
				System.Console.WriteLine("Device is opened successfully");
			}

			/*If device opening fails, return an error message. If the following errors occur, the device will not operate normally. It is recommended to follow the prompts and try reopening the device.*/
			else
			{
				switch (Status)
				{
					case HtraApi.APIRETVAL_ERROR_BusOpenFailed:
						System.Console.WriteLine("Error - Check the device power supply, data cable connection and driver installation");
						return;

					case HtraApi.APIRETVAL_ERROR_RFACalFileIsMissing:
						System.Console.WriteLine("Error - RF calibration file is missing");
						return;

					case HtraApi.APIRETVAL_ERROR_IFACalFileIsMissing:
						System.Console.WriteLine("Error - IF calibration file is missing");
						return;

					case HtraApi.APIRETVAL_ERROR_DeviceConfigFileIsMissing:
						System.Console.WriteLine("Error - Configuration file missing");
						return;

					case HtraApi.APIRETVAL_ERROR_DeviceSpecFileIsMissing:
						System.Console.WriteLine("Error - Device specification file is missing");
						return;
					
					case HtraApi.APIRETVAL_ERROR_FirmwareVersionMismatch:
						System.Console.WriteLine("Error - Firmware Version Mismatch");
						break;

					default:
						System.Console.WriteLine("Return other errors! Status = " + Status);
						return;
				}
			}
			#endregion

			#region 2 Configure Parameters
			HtraApi.IQS_Profile_TypeDef IQS_ProfileIn = new HtraApi.IQS_Profile_TypeDef();    //IQS input configuration, including start frequency, stop frequency, RBW, reference level, etc.
			HtraApi.IQS_Profile_TypeDef IQS_ProfileOut = new HtraApi.IQS_Profile_TypeDef();	  //IQS output configuration.
			HtraApi.IQS_StreamInfo_TypeDef StreamInfo = new HtraApi.IQS_StreamInfo_TypeDef(); //IQ stream information under the current configuration, including bandwidth, IQ single-path sampling rate, etc.

			HtraApi.IQS_ProfileDeInit(ref Device, ref IQS_ProfileIn); //Initialize the related parameters in IQS mode.

			IQS_ProfileIn.CenterFreq_Hz = 1e9;                                   //Set the center frequency.
			IQS_ProfileIn.RefLevel_dBm = 0;                                      //Set the reference level.
			IQS_ProfileIn.DecimateFactor = 2;                                    //Set the decimation factor.
			IQS_ProfileIn.DataFormat = HtraApi.DataFormat_TypeDef.Complex16bit;  //Set the IQ data format.
			IQS_ProfileIn.TriggerSource = HtraApi.IQS_TriggerSource_TypeDef.Bus; //Set the trigger source to internal bus trigger.

			//The FixedPoints mode samples after the rising edge of the trigger signal and ends after capturing TriggerLength points. 
			//Use Adaptive mode directly. To use FixedPoints mode, change #if true to #if false
#if true
			IQS_ProfileIn.TriggerMode = HtraApi.TriggerMode_TypeDef.Adaptive;
#else
			//Configure parameters for FixedPoints mode
			IQS_ProfileIn.TriggerMode = HtraApi.TriggerMode_TypeDef.FixedPoints;    
			IQS_ProfileIn.TriggerLength = 20000; //Set the number of points to capture in a single trigger. Only effective when TriggerMode is set to FixedPoints.
#endif

			Status = HtraApi.IQS_Configuration(ref Device, ref IQS_ProfileIn, ref IQS_ProfileOut, ref StreamInfo); //Apply the IQS mode configuration.
			if (Status == 0)
			{
				System.Console.WriteLine("configuration delievery succeeded");
			}
			else
			{
				System.Console.WriteLine("SWP_Configuration call is incorrect,Status = " + Status);
				HtraApi.Device_Close(ref Device);
			}

			System.Int16[] AlternIQStream = new System.Int16[StreamInfo.StreamSamples * 2]; //Create an array to store the IQ data, and store the data in the format IQIQIQ....

			HtraApi.IQStream_TypeDef IQStream = new HtraApi.IQStream_TypeDef(); //Stores IQ stream data, including IQ data and configuration information.
			System.Int16[] I_Data = new System.Int16[StreamInfo.PacketSamples]; //Create array for I-channel data.
			System.Int16[] Q_Data = new System.Int16[StreamInfo.PacketSamples]; //Create array for Q-channel data.
			#endregion

			#region 3 Data Acquisition
			//Use Adaptive mode directly. To use FixedPoints mode, change #if true to #if false
#if true
			Status = HtraApi.IQS_BusTriggerStart(ref Device); //Call IQS_BusTriggerStart to trigger the device. If the trigger source is external, this function is not needed.

			while (true)
			{
				Status = HtraApi.IQS_GetIQStream_PM1(ref Device, ref IQStream); //Retrieve IQ data packet, trigger information, max value of I-channel data, and max value array index
				if (Status == 0)
				{

					// UserCode here
					//Example of operation: The IQ data packet returned by IQS_GetIQStream contains header data, IQ data, and footer data. Below is the process to extract the IQ data.
					//Note: When using IQ mode, it is recommended to run a separate thread dedicated to calling IQS_GetIQStream to retrieve IQ data; do not mix this with IQ data processing in the same thread.
					unsafe
					{
						System.Int16* IQ = (System.Int16*)IQStream.AlternIQStream; //Used to extract IQ data
						for (int i = 0; i < StreamInfo.PacketSamples; i++)
						{
							I_Data[i] = IQ[i * 2];
							Q_Data[i] = IQ[i * 2 + 1];
						}
					}
					//End of the operation example, you can write your code here for further processing
				}

                else
                {
					/*In case of data retrieval failure, return an error message. If the following errors occur, it is recommended to take actions as prompted.*/
					switch (Status)
					{
						case HtraApi.APIRETVAL_ERROR_BusError:  //IQS_GetIQStream returns -8, it is recommended to reconfigure parameters and try to retrieve data again
							System.Console.WriteLine("Error - Bus communication error");
							Status = HtraApi.IQS_Configuration(ref Device, ref IQS_ProfileIn, ref IQS_ProfileOut, ref StreamInfo);
							break;

						case HtraApi.APIRETVAL_ERROR_BusDataError: //IQS_GetIQStream returns -9, it is recommended to reconfigure parameters and try to retrieve data again
							System.Console.WriteLine("Error - The data content is incorrect");
							Status = HtraApi.IQS_Configuration(ref Device, ref IQS_ProfileIn, ref IQS_ProfileOut, ref StreamInfo);
							break;

						case HtraApi.APIRETVAL_WARNING_BusTimeOut: //IQS_GetIQStream returns -10, it is recommended to check if the trigger source is triggered normally
							System.Console.WriteLine("Warning - Get data timed out, check if the trigger source is triggered normally");
							break;

						case HtraApi.APIRETVAL_WARNING_IFOverflow: //IQS_GetIQStream returns -12, it is recommended to reconfigure parameters and try to retrieve data again
							System.Console.WriteLine("WARNING - IF saturation is recommended to be reconfigured, reference level <= signal power");
							break;

						case HtraApi.APIRETVAL_WARNING_ReconfigurationIsRecommended: //IQS_GetIQStream returns -14, it is recommended to reconfigure parameters and try to retrieve data again
							System.Console.WriteLine("Warning - The current device temperature has changed significantly relative to the configured temperature, and it is recommended to reconfigure \n");
							break;

						case HtraApi.APIRETVAL_WARNING_ClockUnlocked_SYSCLK: //IQS_GetIQStream returns -15, it is recommended to reconfigure parameters and try to retrieve data again
							System.Console.WriteLine("Warning - There may be an anomaly in the hardware status of the device and reconfiguration is recommended\n");
							break;
						default:
							break;
					}
					System.Console.WriteLine("Status = " + Status);
				}
			}
#else
			while (true)
			{
				Status = HtraApi.IQS_BusTriggerStart(ref Device); // Call IQS_BusTriggerStart to trigger the device. If the trigger source is external, this function is not needed.
				if (Status == 0)
				{
					// UserCode here

					/*The IQ data packet obtained from IQS_GetIQStream contains header data, IQ data, and trailer data. The following operation extracts the IQ data from the IQ packet.*/
					/*Note: In actual use of IQ mode, it is recommended to use a separate thread to call IQS_GetIQStream to retrieve IQ data, and not to combine it with data processing in the same thread. */
					for (System.UInt64 k = 0; k < StreamInfo.PacketCount; ++k)
					{
						Status = HtraApi.IQS_GetIQStream_PM1(ref Device, ref IQStream); //Get the IQ data packet, trigger information, I channel data maximum value, and index of the maximum value array.
						if (Status != 0)
						{
							break;
						}
						unsafe
						{
							System.Int16* IQ = (System.Int16*)IQStream.AlternIQStream;  // Used to extract IQ data
							UInt32 points = StreamInfo.PacketSamples;                  // Number of data points in the current packet
							if (k == StreamInfo.PacketCount - 1 && StreamInfo.StreamSamples % StreamInfo.PacketSamples != 0) // Check for the last packet: if it's the last packet and it is not full
							{
							    points = (UInt32)StreamInfo.StreamSamples % StreamInfo.PacketSamples; // Calculate the number of data points in the last (partial) packet
							}
							for (int j = 0; j < points * 2; j++) // Concatenate IQ data across multiple packets
							{
								AlternIQStream[j + StreamInfo.PacketSamples * (int)k * 2] = IQ[j];
							}
						}
					}

					if (Status == 0)
					{
						for (int i = 0; i < StreamInfo.PacketSamples; i++)
						{
							System.Console.WriteLine("I:" + AlternIQStream[2 * i].ToString() + ",  " + "Q:" + AlternIQStream[2 * i + 1].ToString());
						}
						continue;
					}
				}

				else
				{
					/*If data retrieval fails, return an error message. The following errors may occur, and the recommended actions are provided.*/
					switch (Status)
					{
						case HtraApi.APIRETVAL_ERROR_BusError:  //When IQS_GetIQStream returns -8, it is recommended to reconfigure parameters and attempt data retrieval again
							System.Console.WriteLine("Error - Bus communication error");
							Status = HtraApi.IQS_Configuration(ref Device, ref IQS_ProfileIn, ref IQS_ProfileOut, ref StreamInfo);
							break;

						case HtraApi.APIRETVAL_ERROR_BusDataError: //When IQS_GetIQStream returns -9, it is recommended to reconfigure parameters and attempt data retrieval again
							System.Console.WriteLine("Error - The data content is incorrect");
							Status = HtraApi.IQS_Configuration(ref Device, ref IQS_ProfileIn, ref IQS_ProfileOut, ref StreamInfo);
							break;

						case HtraApi.APIRETVAL_WARNING_BusTimeOut: //When IQS_GetIQStream returns -10, check if the trigger source is triggered properly before retrying
							System.Console.WriteLine("Warning - Get data timed out, check if the trigger source is triggered normally");
							break;

						case HtraApi.APIRETVAL_WARNING_IFOverflow: //When IQS_GetIQStream returns -12, it is recommended to reconfigure parameters and attempt data retrieval again
							System.Console.WriteLine("WARNING - IF saturation is recommended to be reconfigured, reference level <= signal power");
							break;

						case HtraApi.APIRETVAL_WARNING_ReconfigurationIsRecommended: //When IQS_GetIQStream returns -14, it is recommended to reconfigure parameters and attempt data retrieval again
							System.Console.WriteLine("Warning - The current device temperature has changed significantly relative to the configured temperature, and it is recommended to reconfigure \n");
							break;

						case HtraApi.APIRETVAL_WARNING_ClockUnlocked_SYSCLK: //When IQS_GetIQStream returns -15, it is recommended to reconfigure parameters and attempt data retrieval again
							System.Console.WriteLine("Warning - There may be an anomaly in the hardware status of the device and reconfiguration is recommended\n");
							break;
						default:
							break;
					}
					System.Console.WriteLine("Status = " + Status);
				}
			}
#endif

			#endregion

			#region 4 Close
			Status = HtraApi.IQS_BusTriggerStop(ref Device); //Call IQS_BusTriggerStop to stop the triggering of the device. If the trigger source is external, this function is not required.
			HtraApi.Device_Close(ref Device);
			#endregion
		}
	}
}
