#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
#include <string>
#include <sstream>
#include <vector>
#include "htra_api.h"
#include "math.h"
#include <ctime>
#include <iomanip> 
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include "example.h"
#define EXAMPLE_MACRO_NAME
using namespace std;

int IQS_MultiDevSync_fixed()
{
	int Status0 = 0; //函数的返回值 24002e M-60
	int Status1 = 0; //函数的返回值 460020 M-80
	int Status2 = 0; //函数的返回值 3E0029 E-200
	int Status3 = 0; //函数的返回值 070022 M-80

	int DevNum0 = 0; //指定设备0。
	int DevNum1 = 1; //指定设备1。
	int DevNum2 = 2; //指定设备2。
	int DevNum3 = 3; //指定设备3。

	void* Device0 = NULL; //当前设备0的内存地址。
	void* Device1 = NULL; //当前设备1的内存地址。
	void* Device2 = NULL; //当前设备2的内存地址。
	void* Device3 = NULL; //当前设备3的内存地址。

	BootProfile_TypeDef BootProfile; //启动配置结构体，包括物理接口、供电方式等。

	BootInfo_TypeDef BootInfo0; //启动信息结构体0，包括设备信息、USB速率等。
	BootInfo_TypeDef BootInfo1; //启动信息结构体1，包括设备信息、USB速率等。
	BootInfo_TypeDef BootInfo2; //启动信息结构体2，包括设备信息、USB速率等。
	BootInfo_TypeDef BootInfo3; //启动信息结构体3，包括设备信息、USB速率等。

	BootProfile.DevicePowerSupply = USBPortAndPowerPort; //使用USB数据端口及独立电源端口双供电。
	BootProfile.PhysicalInterface = USB;				 //使用USB接口进行数据传输。

	Status0 = Device_Open(&Device0, DevNum0, &BootProfile, &BootInfo0);          //打开设备0
	Status1 = Device_Open(&Device1, DevNum1, &BootProfile, &BootInfo1);          //打开设备1
	Status2 = Device_Open(&Device2, DevNum2, &BootProfile, &BootInfo2);          //打开设备0
	Status3 = Device_Open(&Device3, DevNum3, &BootProfile, &BootInfo3);          //打开设备1

	Device_Open_ErrorHandling(Status0, &Device0, DevNum0, &BootProfile, &BootInfo0); //当Status0不为0时，根据Status0的返回值进行相对应的错误处理
	Device_Open_ErrorHandling(Status1, &Device1, DevNum1, &BootProfile, &BootInfo1); //当Status1不为0时，根据Status1的返回值进行相对应的错误处理
	Device_Open_ErrorHandling(Status2, &Device2, DevNum2, &BootProfile, &BootInfo2); //当Status2不为0时，根据Status2的返回值进行相对应的错误处理
	Device_Open_ErrorHandling(Status3, &Device3, DevNum3, &BootProfile, &BootInfo3); //当Status3不为0时，根据Status3的返回值进行相对应的错误处理

	IQS_Profile_TypeDef IQS_ProfileIn; //IQS输入配置，包括起始频率、终止频率、RBW、参考电平等。

	IQS_Profile_TypeDef IQS_ProfileOut0; //IQS输出设备0配置。
	IQS_Profile_TypeDef IQS_ProfileOut1; //IQS输出设备1配置。
	IQS_Profile_TypeDef IQS_ProfileOut2; //IQS输出设备2配置。			
	IQS_Profile_TypeDef IQS_ProfileOut3; //IQS输出设备3配置。		

	IQS_StreamInfo_TypeDef StreamInfo0;	//设备0当前配置下IQ数据信息，包括带宽, IQ单路采样率等。
	IQS_StreamInfo_TypeDef StreamInfo1;	//设备1当前配置下IQ数据信息，包括带宽, IQ单路采样率等。						
	IQS_StreamInfo_TypeDef StreamInfo2;	//设备2当前配置下IQ数据信息，包括带宽, IQ单路采样率等。						 
	IQS_StreamInfo_TypeDef StreamInfo3;	//设备3当前配置下IQ数据信息，包括带宽, IQ单路采样率等。						  

	IQS_ProfileDeInit(&Device0, &IQS_ProfileIn); //初始化配置设备0 IQS模式的相关参数。
	IQS_ProfileDeInit(&Device1, &IQS_ProfileIn); //初始化配置设备1 IQS模式的相关参数。
	IQS_ProfileDeInit(&Device2, &IQS_ProfileIn); //初始化配置设备2 IQS模式的相关参数。
	IQS_ProfileDeInit(&Device3, &IQS_ProfileIn); //初始化配置设备3 IQS模式的相关参数。

	IQS_ProfileIn.CenterFreq_Hz = 1e9;               //配置中心频率。
	IQS_ProfileIn.RefLevel_dBm = 0;                  //配置参考电平。
	IQS_ProfileIn.DecimateFactor = 2;		         //配置抽取倍数。
	IQS_ProfileIn.DataFormat = Complex16bit;         //配置IQ数据格式。
	IQS_ProfileIn.TriggerMode = FixedPoints;         //配置触发模式。
	IQS_ProfileIn.TriggerSource = MultiDevSyncByExt; //配置触发源为外部触发，外部触发信号到来时，多机做同步触发行为。
	IQS_ProfileIn.TriggerLength = 16242;			 //配置单次触发采集的点数。仅当TriggerMode设置为FixedPoints时生效。

	//多台设备采用同样的配置（也可采用不同的，但是触发源必须都是MultiDevSync）
	Status0 = IQS_Configuration(&Device0, &IQS_ProfileIn, &IQS_ProfileOut0, &StreamInfo0);
	Status1 = IQS_Configuration(&Device1, &IQS_ProfileIn, &IQS_ProfileOut1, &StreamInfo1);
	Status2 = IQS_Configuration(&Device2, &IQS_ProfileIn, &IQS_ProfileOut2, &StreamInfo2);
	Status3 = IQS_Configuration(&Device3, &IQS_ProfileIn, &IQS_ProfileOut3, &StreamInfo3);

	IQS_Configuration_ErrorHandling(Status0, &Device0, DevNum0, &BootProfile, &BootInfo0, &IQS_ProfileIn, &IQS_ProfileOut0, &StreamInfo0); //当Status不为0时，根据Status的返回值进行相对应的错误处理
	IQS_Configuration_ErrorHandling(Status1, &Device1, DevNum1, &BootProfile, &BootInfo1, &IQS_ProfileIn, &IQS_ProfileOut1, &StreamInfo1); //当Status不为0时，根据Status的返回值进行相对应的错误处理
	IQS_Configuration_ErrorHandling(Status2, &Device2, DevNum2, &BootProfile, &BootInfo2, &IQS_ProfileIn, &IQS_ProfileOut2, &StreamInfo2); //当Status不为0时，根据Status的返回值进行相对应的错误处理
	IQS_Configuration_ErrorHandling(Status3, &Device3, DevNum3, &BootProfile, &BootInfo3, &IQS_ProfileIn, &IQS_ProfileOut3, &StreamInfo3); //当Status不为0时，根据Status的返回值进行相对应的错误处理

	/*查询系统中设备的状态*/
	DeviceState_TypeDef DeviceState0;
	DeviceState_TypeDef DeviceState1;
	DeviceState_TypeDef DeviceState2;
	DeviceState_TypeDef DeviceState3;

	IQStream_TypeDef IQStream0;                                //设备0：存放IQ数据包数据，包括IQ数据、配置信息等。
	int32_t* I_Data0 = new int32_t[StreamInfo0.PacketSamples]; //设备0：创建I路数据数组。
	int32_t* Q_Data0 = new int32_t[StreamInfo0.PacketSamples]; //设备0：创建Q路数据数组。

	IQStream_TypeDef IQStream1;                                //设备1：存放IQ数据包数据，包括IQ数据、配置信息等。
	int32_t* I_Data1 = new int32_t[StreamInfo1.PacketSamples]; //设备1：创建I路数据数组。
	int32_t* Q_Data1 = new int32_t[StreamInfo1.PacketSamples]; //设备1：创建Q路数据数组。

	IQStream_TypeDef IQStream2;                                //设备2：存放IQ数据包数据，包括IQ数据、配置信息等。
	int32_t* I_Data2 = new int32_t[StreamInfo2.PacketSamples]; //设备2：创建I路数据数组。
	int32_t* Q_Data2 = new int32_t[StreamInfo2.PacketSamples]; //设备2：创建Q路数据数组。

	IQStream_TypeDef IQStream3;                                //设备3：存放IQ数据包数据，包括IQ数据、配置信息等。
	int32_t* I_Data3 = new int32_t[StreamInfo3.PacketSamples]; //设备3：创建I路数据数组。
	int32_t* Q_Data3 = new int32_t[StreamInfo3.PacketSamples]; //设备3：创建Q路数据数组。

	int32_t* Power_Dataa = new int32_t[StreamInfo0.PacketSamples]; //4机的采样长度均等同，选其中一台设备的StreamInfo对应点数
	int32_t* Power_Data1 = new int32_t[StreamInfo0.PacketSamples];
	int32_t* Power_Data2 = new int32_t[StreamInfo0.PacketSamples];
	int32_t* Power_Data3 = new int32_t[StreamInfo0.PacketSamples];
	
	Status0 = IQS_MultiDevice_WaitExternalSync(&Device0, &IQS_ProfileOut0); //选择系统中的其中一台，进行触发信号的等待。该函数执行完说明系统已捕获到触发信号

	//在系统捕获到触发信号后，使能多机同步运行
	Status0 = IQS_MultiDevice_Run(&Device0);
	Status1 = IQS_MultiDevice_Run(&Device1);
	Status2 = IQS_MultiDevice_Run(&Device2);
	Status3 = IQS_MultiDevice_Run(&Device3);

	void* AlternIQStream0 = nullptr;       //存储设备0获取的IQ数据
	float ScaleToV0;                       //将设备0获取的IQ数据流转换为实际的电压值
	IQS_TriggerInfo_TypeDef  TriggerInfo0; //设备0触发信息
	MeasAuxInfo_TypeDef MeasAuxInfo0;      //设备0测量数据的辅助信息，包括：功率最大值索引、功率最大值、设备温度、经纬度、绝对时间戳等。

	void* AlternIQStream1 = nullptr;       //存储设备1获取的IQ数据
	float ScaleToV1;                       //将设备1获取的IQ数据流转换为实际的电压值
	IQS_TriggerInfo_TypeDef  TriggerInfo1; //设备1触发信息
	MeasAuxInfo_TypeDef MeasAuxInfo1;      //设备1测量数据的辅助信息，包括：功率最大值索引、功率最大值、设备温度、经纬度、绝对时间戳等。

	void* AlternIQStream2 = nullptr;       //存储设备2获取的IQ数据
	float ScaleToV2;                       //将设备2获取的IQ数据流转换为实际的电压值
	IQS_TriggerInfo_TypeDef  TriggerInfo2; //设备2触发信息
	MeasAuxInfo_TypeDef MeasAuxInfo2;      //设备2测量数据的辅助信息，包括：功率最大值索引、功率最大值、设备温度、经纬度、绝对时间戳等。

	void* AlternIQStream3 = nullptr;       //存储设备3获取的IQ数据
	float ScaleToV3;                       //将设备3获取的IQ数据流转换为实际的电压值
	IQS_TriggerInfo_TypeDef  TriggerInfo3; //设备3触发信息
	MeasAuxInfo_TypeDef MeasAuxInfo3;      //设备3测量数据的辅助信息，包括：功率最大值索引、功率最大值、设备温度、经纬度、绝对时间戳等。

	while (1)
	{
		/*获取Dev0的数据*/
		Status0 = IQS_GetIQStream_PM1(&Device0, &IQStream0); //获取设备0IQ数据包、触发信息、I路数据最大值及最大值数组下标。

		if (Status0 == 0)
		{
			/*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
			int16_t* IQ = (int16_t*)IQStream0.AlternIQStream; //取出IQ数据
			for (int i = 0; i < StreamInfo0.PacketSamples; i++)
			{
				Q_Data0[i] = IQ[i * 2];
				I_Data0[i] = IQ[i * 2 + 1];
				Power_Dataa[i] = sqrt(pow(I_Data0[i], 2) + pow(Q_Data0[i], 2)); //以功率检波的方式计算得到功率
			}
			int breakpoint = 0;
		}

		else //当Status0不为0时，根据Status0的返回值进行相对应的错误处理
		{
			IQS_ErrorHandlingExceptOpenAndConfiguration(Status0, &Device0, DevNum0, &BootProfile, &BootInfo0, &IQS_ProfileIn, &IQS_ProfileOut0, &StreamInfo0);
		}

		/*获取Dev1的数据*/
		Status1 = IQS_GetIQStream_PM1(&Device1, &IQStream1); //获取设备1IQ数据包、触发信息、I路数据最大值及最大值数组下标

		if (Status1 == 0)
		{
			/*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
			int16_t* IQ = (int16_t*)IQStream1.AlternIQStream;                          //用于取出IQ数据
			for (int i = 0; i < StreamInfo1.PacketSamples; i++)
			{
				Q_Data1[i] = IQ[i * 2];
				I_Data1[i] = IQ[i * 2 + 1];
				Power_Data1[i] = sqrt(pow(I_Data1[i], 2) + pow(Q_Data1[i], 2)); //以功率检波的方式计算得到功率
			}
			int breakpoint = 0;
		}

		else //当Status1不为0时，根据Status1的返回值进行相对应的错误处理
		{
			IQS_ErrorHandlingExceptOpenAndConfiguration(Status1, &Device1, DevNum1, &BootProfile, &BootInfo1, &IQS_ProfileIn, &IQS_ProfileOut1, &StreamInfo1);
		}

		/*获取Dev2的数据*/
		Status2 = IQS_GetIQStream_PM1(&Device2, &IQStream2); //获取设备2IQ数据包、触发信息、I路数据最大值及最大值数组下标

		if (Status2 == 0)
		{
			///*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
			int16_t* IQ = (int16_t*)IQStream2.AlternIQStream;                   //取出IQ数据
			for (int i = 0; i < StreamInfo2.PacketSamples; i++)
			{
				Q_Data2[i] = IQ[i * 2];
				I_Data2[i] = IQ[i * 2 + 1];
				Power_Data2[i] = sqrt(pow(I_Data2[i], 2) + pow(Q_Data2[i], 2)); //以功率检波的方式计算得到功率
			}
			int breakpoint = 0;
		}

		else //当Status2不为0时，根据Status2的返回值进行相对应的错误处理
		{
			IQS_ErrorHandlingExceptOpenAndConfiguration(Status2, &Device2, DevNum2, &BootProfile, &BootInfo2, &IQS_ProfileIn, &IQS_ProfileOut2, &StreamInfo2);
		}

		/*获取Dev3的数据*/
		Status3 = IQS_GetIQStream_PM1(&Device3, &IQStream3); //获取设备3IQ数据包、触发信息、I路数据最大值及最大值数组下标

		if (Status3 == 0)
		{
			/*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
			int16_t* IQ = (int16_t*)IQStream3.AlternIQStream;                   //取出IQ数据
			for (int i = 0; i < StreamInfo3.PacketSamples; i++)
			{
				Q_Data3[i] = IQ[i * 2];
				I_Data3[i] = IQ[i * 2 + 1];
				Power_Data3[i] = sqrt(pow(I_Data3[i], 2) + pow(Q_Data3[i], 2)); //以功率检波的方式计算得到功率
			}
			int breakpoint = 0;
		}

		else //当Status3不为0时，根据Status3的返回值进行相对应的错误处理。
		{
			IQS_ErrorHandlingExceptOpenAndConfiguration(Status3, &Device3, DevNum3, &BootProfile, &BootInfo3, &IQS_ProfileIn, &IQS_ProfileOut3, &StreamInfo3);
		}
	}

	//释放动态数组
	delete[] I_Data0;
	delete[] Q_Data0;
	delete[] I_Data1;
	delete[] Q_Data1;
	delete[] I_Data2;
	delete[] Q_Data2;
	delete[] I_Data3;
	delete[] Q_Data3;
	delete[] Power_Dataa;
	delete[] Power_Data1;
	delete[] Power_Data2;
	delete[] Power_Data3;

	Device_Close(&Device0); //关闭设备0
	Device_Close(&Device1); //关闭设备1
	Device_Close(&Device2); //关闭设备2
	Device_Close(&Device3); //关闭设备3

	return 0;
}