#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; //设备0函数的返回值 
	int Status1 = 0; //设备1函数的返回值 

	int DevNum0 = 0; //指定设备0。
	int DevNum1 = 1; //指定设备1。

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

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

	BootInfo_TypeDef BootInfo0; //启动信息结构体0，包括设备信息、USB速率等。
	BootInfo_TypeDef BootInfo1; //启动信息结构体1，包括设备信息、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

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

	IQS_Profile_TypeDef IQS_ProfileOut0; //IQS输出设备0配置。
	IQS_Profile_TypeDef IQS_ProfileOut1; //IQS输出设备1配置。
		
	IQS_StreamInfo_TypeDef StreamInfo0;	//设备0当前配置下IQ数据信息，包括带宽, IQ单路采样率等。
	IQS_StreamInfo_TypeDef StreamInfo1;	//设备1当前配置下IQ数据信息，包括带宽, IQ单路采样率等。						

	IQS_ProfileDeInit(&Device0, &IQS_ProfileIn); //初始化配置设备0 IQS模式的相关参数。
	IQS_ProfileDeInit(&Device1, &IQS_ProfileIn); //初始化配置设备1 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);

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

	IQStream_TypeDef IQStream0;                              //设备0：存放IQ数据包数据，包括IQ数据、配置信息等。
	double* I_Data0 = new double[StreamInfo0.StreamSamples]; //设备0：创建I路数据数组。
	double* Q_Data0 = new double[StreamInfo0.StreamSamples]; //设备0：创建Q路数据数组。
	double* Power_Data0 = new double[StreamInfo0.StreamSamples];
	vector<double> Power_Data0_dBm(StreamInfo0.StreamSamples);

	IQStream_TypeDef IQStream1;                              //设备1：存放IQ数据包数据，包括IQ数据、配置信息等。
	double* I_Data1 = new double[StreamInfo1.StreamSamples]; //设备1：创建I路数据数组。
	double* Q_Data1 = new double[StreamInfo1.StreamSamples]; //设备1：创建Q路数据数组。
	double* Power_Data1 = new double[StreamInfo1.StreamSamples];
	vector<double> Power_Data1_dBm(StreamInfo1.StreamSamples);

	Status0 = IQS_MultiDevice_WaitExternalSync(&Device0, &IQS_ProfileOut0); //选择系统中的其中一台，进行触发信号的等待。该函数执行完说明系统已捕获到触发信号

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

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

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

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

			if (Status0 == 0)
			{
				/*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
				int16_t* IQ = (int16_t*)IQStream0.AlternIQStream; //取出IQ数据

				uint32_t Points = StreamInfo0.PacketSamples;

				if (j == StreamInfo0.PacketCount - 1 && StreamInfo0.StreamSamples % StreamInfo0.PacketSamples != 0) //可能最后一包不满一整包（16242个点）；所以只需要循环不满一包的点数。
				{
					Points = StreamInfo0.StreamSamples % StreamInfo0.PacketSamples;
				}

				for (uint32_t i = 0; i < Points; i++)
				{
					I_Data0[i + StreamInfo0.PacketSamples * j] = IQ[i * 2] * IQStream0.IQS_ScaleToV;     //将I路数据转为实际电压值
					Q_Data0[i + StreamInfo0.PacketSamples * j] = IQ[i * 2 + 1] * IQStream0.IQS_ScaleToV; //将Q路数据转为实际电压值
					Power_Data0[i + StreamInfo0.PacketSamples * j] = sqrt(pow(I_Data0[i + StreamInfo0.PacketSamples * j], 2) + pow(Q_Data0[i + StreamInfo0.PacketSamples * j], 2)); //计算幅度
					Power_Data0_dBm[i + StreamInfo0.PacketSamples * j] = 10 * log10(20 * (Power_Data0[i + StreamInfo0.PacketSamples * j] * Power_Data0[i + StreamInfo0.PacketSamples * j])); //转换为dBm
				}
			}
		}

		for (int j = 0; j < StreamInfo0.PacketCount; j++)
		{

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

			if (Status1 == 0)
			{
				/*注意：实际使用IQ模式时，建议开一个线程专门调用IQS_GetIQStream获取IQ数据，不能与处理IQ数据放在同一个线程里。*/
				int16_t* IQ = (int16_t*)IQStream1.AlternIQStream; //取出IQ数据

				uint32_t Points = StreamInfo1.PacketSamples;

				if (j == StreamInfo1.PacketCount - 1 && StreamInfo1.StreamSamples % StreamInfo1.PacketSamples != 0) //可能最后一包不满一整包（16242个点）；所以只需要循环不满一包的点数。
				{
					Points = StreamInfo1.StreamSamples % StreamInfo1.PacketSamples;
				}

				for (uint32_t i = 0; i < Points; i++)
				{
					I_Data1[i + StreamInfo1.PacketSamples * j] = IQ[i * 2] * IQStream1.IQS_ScaleToV;
					Q_Data1[i + StreamInfo1.PacketSamples * j] = IQ[i * 2 + 1] * IQStream1.IQS_ScaleToV;
					Power_Data1[i + StreamInfo1.PacketSamples * j] = sqrt(pow(I_Data1[i + StreamInfo1.PacketSamples * j], 2) + pow(Q_Data1[i + StreamInfo1.PacketSamples * j], 2));
					Power_Data1_dBm[i + StreamInfo1.PacketSamples * j] = 10 * log10(20 * (Power_Data1[i + StreamInfo1.PacketSamples * j] * Power_Data1[i + StreamInfo1.PacketSamples * j]));
				}
			}
		}

		vector<double> PacketSamplesDouble(StreamInfo0.PacketSamples);
		for (int i = 0; i < StreamInfo0.PacketSamples; i++)
		{
			PacketSamplesDouble[i] = i;
		}
	}

	//释放动态数组
	delete[] I_Data0;
	delete[] Q_Data0;
	delete[] I_Data1;
	delete[] Q_Data1;
	delete[] Power_Data0;
	delete[] Power_Data1;
	Device_Close(&Device0); //关闭设备0
	Device_Close(&Device1); //关闭设备1

	return 0;
}
