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

using namespace std;

#define IS_USB 1 // Default to using USB-type devices. Set IS_USB to 0 if using Ethernet-type devices.

int RTAMode_EZStandard()
{
	int Status = 0;      // Return value of the function.
	void* Device = NULL; // Memory address of the current device.
	int DevNum = 0;      // Device index.

	BootProfile_TypeDef BootProfile; // Boot configuration struct, including physical interface, power supply method, etc.
	BootInfo_TypeDef BootInfo;       // Boot info struct, including device info, USB speed, etc.

	BootProfile.DevicePowerSupply = USBPortAndPowerPort; // Use USB data port and separate power port for dual power supply.

#if IS_USB==1
	// Configure USB interface
	BootProfile.PhysicalInterface = USB;
#else 
	// Configure ETH interface
	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); // Open the device.

	Device_Open_ErrorHandling(Status, &Device, DevNum, &BootProfile, &BootInfo); // When Status is not 0, handle the error based on Status value.

	RTA_EZProfile_TypeDef RTA_EZProfileIn;  // RTA input config, including center frequency, decimation factor, reference level, etc. 
	RTA_EZProfile_TypeDef RTA_EZProfileOut; // RTA output config.
	RTA_FrameInfo_TypeDef FrameInfo;        // RTA data info under current config, including start frequency, end frequency, number of data points, etc.

	RTA_EZProfileDeInit(&Device, &RTA_EZProfileIn); // Initialize RTA mode related parameters.

	RTA_EZProfileIn.CenterFreq_Hz = 1e9;    // Set center frequency.
	RTA_EZProfileIn.RefLevel_dBm = 0;       // Set reference level.
	RTA_EZProfileIn.DecimateFactor = 1;	    // Set decimation factor.
	RTA_EZProfileIn.TriggerMode = Adaptive; // Set trigger mode.
	RTA_EZProfileIn.TriggerSource = Bus;    // Set trigger source as internal bus trigger.
	RTA_EZProfileIn.TriggerAcqTime = 0.1;   // Set sampling time after trigger to 0.1s, only effective in FixedPoints mode.

	Status = RTA_EZConfiguration(&Device, &RTA_EZProfileIn, &RTA_EZProfileOut, &FrameInfo); // Apply RTA mode configuration.
	double step = (FrameInfo.StopFrequency_Hz - FrameInfo.StartFrequency_Hz) / FrameInfo.FrameWidth; //Calculate frequency step

	if (Status == 0)
	{
		cout << "Configuration applied successfully!" << endl;
	}
	else
	{
		cout << "Error in RTA_EZConfiguration call. Status = " << Status << endl;
		Device_Close(&Device);
		return 0;
	}

	vector<double> Frequency(FrameInfo.FrameWidth);  // Create the frequency array.
	vector<uint8_t> SpectrumTrace(FrameInfo.PacketValidPoints);                    // Create spectrum array.
	vector<uint16_t> SpectrumBitmap(FrameInfo.FrameHeight * FrameInfo.FrameWidth); // Create bitmap array for spectrum.
	vector<float> Spectrum(FrameInfo.FrameWidth);                                  // Create spectrum array in dBm.
	RTA_PlotInfo_TypeDef RTA_PlotInfo;                                             // Plotting information.
	RTA_TriggerInfo_TypeDef TriggerInfo;                                           // Trigger information.
	MeasAuxInfo_TypeDef MeasAuxInfo;                                               // Auxiliary info for measurement, includes: max power index, max power, device temperature, GPS, absolute timestamp, etc.

	bool tag = false; // When RTA_ProfileOut.TriggerMode = Adaptive, control trigger once before data acquisition.

	while (1)
	{
		if (RTA_EZProfileOut.TriggerMode == Adaptive && tag != true) // When TriggerMode is Adaptive, only trigger once.
		{
			Status = RTA_BusTriggerStart(&Device);                   // Trigger the device using RTA_BusTriggerStart. Not needed if trigger source is external.
			tag = true;
		}
		if (RTA_EZProfileOut.TriggerMode == FixedPoints)             // When TriggerMode is FixedPoints, trigger each loop.
		{
			Status = RTA_BusTriggerStart(&Device);                   // Trigger the device using RTA_BusTriggerStart. Not needed if trigger source is external.
		}
		for (uint32_t i = 0; i < FrameInfo.PacketCount; i++)	     // Only effective when TriggerMode is FixedPoints. When Adaptive, StreamInfo.PacketCount is 1.
		{
			Status = RTA_GetRealTimeSpectrum(&Device, SpectrumTrace.data(), SpectrumBitmap.data(), &RTA_PlotInfo, &TriggerInfo, &MeasAuxInfo); // Get RTA data and trigger info.
			if (Status == 0)
			{
				// UserCode here
				

				// Convert RTA spectrum data to dBm
				for (int i = 0; i < FrameInfo.FrameWidth; i++)
				{
					Spectrum[i] = (float)SpectrumTrace[i] * RTA_PlotInfo.ScaleTodBm + RTA_PlotInfo.OffsetTodBm;
					Frequency[i] = FrameInfo.StartFrequency_Hz + i * step;
				}

				
			}
			else
			{
				switch (Status)
				{
				case APIRETVAL_WARNING_IFOverflow:
					std::cout << "Warning - IF saturation detected. Reconfiguration recommended. Reference level <= signal power." << std::endl;
					break;
				case APIRETVAL_WARNING_ReconfigurationIsRecommended:
					std::cout << "Warning - Significant temperature change detected on the device. Reconfiguration of temperature is recommended." << std::endl;
					break;
			    default:
					std::cout << "Other error returned. Status = " << Status << std::endl;
					Device_Close(&Device);
					break;
				}
			}
		}
	}

	Status = RTA_BusTriggerStop(&Device); // Stop triggering the device. Not needed if trigger source is external.

	Device_Close(&Device); // Close the device.

	return 0;
}
