#include <stdio.h>
#include <vector>
#include "htra_api.h"
#include "example.h"
#include <string>
#include<iostream>

using namespace std;
//在使用此范例时，请确保设备次版本与API次版本相同，如若设备的MCU版本为0.55.41，则API版本也相应为0.55.xx。

#define IS_USB 1 //默认使用的是USB型设备，若使用的是网口型设备则将IS_USB定义为0。

int SWP_CalibrateRefClock()
{
	int Status = 0;      //函数的返回。
	void* Device = NULL; //当前设备的内存地址。
	int DevNum = 0;      //指定设备号。

	BootProfile_TypeDef BootProfile; //启动配置结构体，包括物理接口、供电方式等。
	BootInfo_TypeDef BootInfo;       //启动信息结构体，包括设备信息、USB速率等。

	BootProfile.DevicePowerSupply = USBPortAndPowerPort; //使用USB数据端口及独立电源端口双供电。

#if IS_USB==1
	//配置USB接口。
	BootProfile.PhysicalInterface = USB;
#else 
	//配置ETH接口。
	BootProfile.PhysicalInterface = ETH;
	BootProfile.ETH_IPVersion = IPv4;
	BootProfile.ETH_RemotePort = 5000;
	BootProfile.ETH_ReadTimeOut = 5000;
	BootProfile.ETH_IPAddress[0] = 192;
	BootProfile.ETH_IPAddress[1] = 168;
	BootProfile.ETH_IPAddress[2] = 1;
	BootProfile.ETH_IPAddress[3] = 100;
#endif

	Status = Device_Open(&Device, DevNum, &BootProfile, &BootInfo); //打开设备。

	Device_Open_ErrorHandling(Status, &Device, DevNum, &BootProfile, &BootInfo); //当Status不为0时，根据Status的返回值进行相对应的错误处理。

	SWP_Profile_TypeDef SWP_ProfileIn;  //SWP输入配置，包括起始频率、终止频率、RBW、参考电平等。
	SWP_Profile_TypeDef SWP_ProfileOut; //SWP输出配置。
	SWP_TraceInfo_TypeDef TraceInfo;    //当前配置下的迹线信息，包括迹线点数、跳频点数等。

	SWP_ProfileDeInit(&Device, &SWP_ProfileIn); //调用此函数初始化配置SWP模式的相关参数。


	SWP_ProfileIn.StartFreq_Hz = 9e3;    //配置起始频率。
	SWP_ProfileIn.StopFreq_Hz = 2e9;    //配置终止频率。
	SWP_ProfileIn.RBWMode = RBW_Manual; //设置RBW模式。
	SWP_ProfileIn.RBW_Hz = 10e3;        //配置RBW。

	Status = SWP_Configuration(&Device, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); //下发SWP模式的相关配置。

	SWP_Configuration_ErrorHandling(Status, &Device, DevNum, &BootProfile, &BootInfo, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); //当Status不为0时，根据Status的返回值进行相对应的错误处理。

	vector<double> Frequency(TraceInfo.FullsweepTracePoints);    //创建频率数组。
	vector<float> PowerSpec_dBm(TraceInfo.FullsweepTracePoints); //创建功率数组。
	MeasAuxInfo_TypeDef MeasAuxInfo;                             //测量数据的辅助信息，包括：功率最大值索引、功率最大值、设备温度、经纬度、绝对时间戳等。
	double Freq_Max = 0;                                         //放置峰值对应频率值。
	float Power_Max = 0;                                         //放置峰值频率值。

	Status = SWP_GetFullSweep(&Device, Frequency.data(), PowerSpec_dBm.data(), &MeasAuxInfo); //获取频谱数据。

	SWP_ErrorHandlingExceptOpenAndConfiguration(Status, &Device, DevNum, &BootProfile, &BootInfo, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); //当Status不为0时，根据Status的返回值进行相对应的错误处理。

	Freq_Max = Frequency[MeasAuxInfo.MaxIndex]; //找出校准前频谱峰值频率。
	Power_Max = MeasAuxInfo.MaxPower_dBm;	    //找出校准前频谱峰值功率。

	cout << "Frequency corresponding to the peak: " << Freq_Max << endl; //输出校准前频谱峰值频率。
	cout << "Peak power : " << Power_Max << endl;    //输出校准前频谱峰值功率。

	ClkCalibrationSource_TypeDef ClkCalibrationSource = CalibrateByExternal; //通过外部触发进行Clock校准，若使用的为GNSS1PPS触发，请联系技术支持人员。
	double TriggerPeriod_s = 1;												 //设置校准信号的准确信号。
	uint64_t TriggerCount = 2;												 //设置校准的触发次数。
	bool RewriteRFCal = true;												 //设置为false，校准结果不写入校准文件，设备下电后校准结果失效，true校准结果写入校准文件（不可逆），设备上下电后仍然保持校准状态。
	double RefCLKFreq_Hz = 0;												 //反馈本次校准得到的新的参考时钟频率，即校准结果。

	Status = Device_CalibrateRefClock(&Device, ClkCalibrationSource, TriggerPeriod_s, TriggerCount, RewriteRFCal, &RefCLKFreq_Hz); //开始校准。

	SWP_ProfileIn.ReferenceClockFrequency = RefCLKFreq_Hz; //下发本次校准得到的新的参考时钟频率。

	Status = SWP_Configuration(&Device, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); //通过调用此函数下发SWP模式的相关配置。

	SWP_Configuration_ErrorHandling(Status, &Device, DevNum, &BootProfile, &BootInfo, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); //当Status不为0时，根据Status的返回值进行相对应的错误处理。

	vector<double> Frequency_a(TraceInfo.FullsweepTracePoints);    //创建频率数组。
	vector<float> PowerSpec_dBm_a(TraceInfo.FullsweepTracePoints); //创建功率数组。
	double Freq_Max_a = 0;                                         //放置校准后的峰值对应频率值。
	float Power_Max_a = 0;                                         //放置校准后的峰值功率值。
	MeasAuxInfo_TypeDef MeasAuxInfo_a;                             //此结构体用于存放测量数据的辅助信息。

	Status = SWP_GetFullSweep(&Device, Frequency_a.data(), PowerSpec_dBm_a.data(), &MeasAuxInfo_a); //获取频谱数据。

	if (Status == APIRETVAL_NoError)
	{
		// UserCode here
		/*

		例如：显示频谱 或 对频谱做其他处理等。

		*/
	}

	else //当Status不为0时，根据Status的返回值进行相对应的错误处理。
	{
		SWP_ErrorHandlingExceptOpenAndConfiguration(Status, &Device, DevNum, &BootProfile, &BootInfo, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo);
	}

	Freq_Max_a = Frequency_a[MeasAuxInfo_a.MaxIndex]; //找出校准后频谱峰值频率。
	Power_Max_a = MeasAuxInfo_a.MaxPower_dBm;		  //找出校准后频谱峰值功率。

	std::cout << "Frequency corresponding to the peak: " << Freq_Max_a << std::endl; //输出校准后的峰值对应的频率值。
	std::cout << "Peak power: " << Power_Max_a << std::endl; //输出校准后的峰值功率值。

	Device_Close(&Device); //关闭设备。

	return 0;
}