#include <stdio.h>
#include <string.h>
#include<iostream>
#include <vector>
#include<fstream>
#include"msgpack.h"
#include "htra_api.h"
#define FILE_BUFFER_LENGTH 3000000

union FloatConversion {
	float f;
	uint32_t i;
};
union DoubleConversion {
	double d;
	uint64_t i;
};

using namespace std;

// Parse the parameter information issued in RTA mode.
int GetRTARecordConfig(const char* FilePath, RTA_Profile_TypeDef* RTA_Profile, RTA_FrameInfo_TypeDef* RTA_FrameInfo, uint64_t* PacketCount)
{
	int Status = 0;									   // Declare a variable for the function return value.
	fstream file;									   // Declare a file stream object.
	string FilePath_Config = FilePath;				   // Copy the input file path parameter FilePath to FilePath_Config.
	file.open(FilePath_Config, ios::in | ios::binary); // Open the file in binary read mode.
	if (!file.is_open())							   // If the file fails to open.
	{
		cout << "The file failed to be opened, please check whether there is a record file under the path!" << endl;
		return Status;
	}
	file.seekg(8, ios::beg);															 // Move the file pointer to the 8th byte after the beginning (skip the first 8 bytes of the file header).
	uint32_t APIVersion;																 // Declare a variable to store the API version.
	uint64_t PacketCount_Config;														 // Declare a variable to store the packet count value.
	file.read(reinterpret_cast<char*>(&APIVersion), sizeof(APIVersion));				 // Read 4 bytes from the file into the APIVersion variable.
	file.seekg(64, ios::beg);															 // Move the file pointer to the 64th byte after the beginning.
	file.read(reinterpret_cast<char*>(&PacketCount_Config), sizeof(PacketCount_Config)); // Read 8 bytes from the file into the PacketCount_Config variable.
	
	uint32_t APIVersion_1 = ((APIVersion & 0xFF) << 24) | // Convert the APIVersion variable from little-endian to big-endian byte order.
		((APIVersion & 0xFF00) << 8) |
		((APIVersion & 0xFF0000) >> 8) |
		((APIVersion & 0xFF000000) >> 24);
	// Extract the high 16 bits, second highest 8 bits, and lowest 8 bits of the APIVersion_1 variable and assign them to x, y, z respectively.
	uint16_t x = (uint16_t)(((APIVersion_1) & 0xffff0000) >> 16);
	uint8_t y = (uint8_t)(((APIVersion_1) & 0x0000ff00) >> 8);
	uint8_t z = (uint8_t)((APIVersion_1) & 0x000000ff);
	cout << "The API version is:" << x << "." << y << "." << z << endl; // Print the API version information.
 
	uint64_t PacketCount_ptr = (((PacketCount_Config & 0xff) << 56) |
		((PacketCount_Config & 0xff00) << 40) |
		((PacketCount_Config & 0xff0000) << 24) |
		((PacketCount_Config & 0xff000000) << 8) |
		((PacketCount_Config & 0xff00000000) >> 8) |
		((PacketCount_Config & 0xff0000000000) >> 24) 
		| ((PacketCount_Config & 0xff000000000000) >> 40) 
		| ((PacketCount_Config & 0xff00000000000000) >> 56));     // Convert the PacketCount_Config variable from little-endian to big-endian byte order and assign it to PacketCount_ptr.
	*PacketCount = PacketCount_ptr;                               // Assign the rearranged PacketCount_ptr value to the input PacketCount pointer.
	cout << "Number of file packets:" << PacketCount_ptr << endl; // Print the number of packets recorded in the file.

	if (y != 55)
	{
		cout << "The file is not version 55, please select the version 55 file!" << endl;
		Status = -110;
		return Status;
	}

	file.seekg(72 + 10 * 1024 * 1024, ios::beg);                         // Move the file pointer to the position 72 + 10MB after the beginning, start reading data (72+10M~73+10M+length).
	uint16_t Length;											         // Declare a 16-bit unsigned integer variable to store the length of the configuration information and trace information.
	file.read(reinterpret_cast<char*>(&Length), sizeof(Length));         // Read 2 bytes (16 bits) from the file into the Length variable.
	uint16_t Length_1 = ((Length & 0xff) << 8 | (Length & 0xff00) >> 8); // Convert the read Length from little-endian to big-endian byte order.
	file.seekg(74 + 10 * 1024 * 1024, ios::beg);                         // Move the file pointer to the position 74 + 10MB after the beginning to prepare for reading the configuration and trace information.
	char* ConData = new char[Length_1];				                     // Dynamically allocate a char array to store the read contents.
	vector<char>ConData1(Length_1);					                     // Create a char-type vector of length Length_1 to temporarily store the read data.
	file.read(ConData1.data(), ConData1.size());	                     // Read Length_1 bytes from the file into the ConData1 vector.
	memcpy(ConData, ConData1.data(), ConData1.size());                   // Copy the data from ConData1 to ConData.
	
	if (ConData == NULL)
	{
		cout << "The file failed to be read!" << endl;
		return -1;
	}
	
	msgpack_unpacked msg;        // Declare a variable of type msgpack_unpacked for unpacking.
	msgpack_unpacked_init(&msg); // Initialize the msg object for unpacking.
	size_t length_1 = Length_1;
	size_t off = 0;				 // Initialize the offset to 0, indicating to start unpacking from the beginning of the data.

	msgpack_unpack_next(&msg, ConData, length_1, &off);    // Unpack the current object and move to the next object.
	RTA_Profile->CenterFreq_Hz = (double)msg.data.via.f64; // Unpack and assign the CenterFreq_Hz (center frequency) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->RefLevel_dBm = (double)msg.data.via.f64; // Unpack and assign the RefLevel_dBm (reference level) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->RBW_Hz = (double)msg.data.via.f64; // Unpack and assign the RBW_Hz (resolution bandwidth) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->VBW_Hz = (double)msg.data.via.f64; // Unpack and assign the VBW_Hz (video bandwidth) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off); 
	RTA_Profile->RBWMode = (RBWMode_TypeDef)msg.data.via.i64; // Unpack and assign the RBWMode (resolution bandwidth mode) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off); 
	RTA_Profile->VBWMode = (VBWMode_TypeDef)msg.data.via.i64; // Unpack and assign the VBWMode (video bandwidth mode) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->DecimateFactor = (uint32_t)msg.data.via.u64; // Unpack and assign the DecimateFactor (decimation factor) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->Window = (Window_TypeDef)msg.data.via.i64; // Unpack and assign the Window (window function) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->SweepTimeMode = (SweepTimeMode_TypeDef)msg.data.via.i64; // Unpack and assign the SweepTimeMode (sweep time mode) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->SweepTime = (double)msg.data.via.f64; // Unpack and assign the SweepTime (sweep time) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->Detector = (Detector_TypeDef)msg.data.via.i64; // Unpack and assign the Detector (detector) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TraceDetectMode = (TraceDetectMode_TypeDef)msg.data.via.i64; // Unpack and assign the TraceDetectMode (trace detection) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TraceDetectRatio = (uint32_t)msg.data.via.u64; // Unpack and assign the TraceDetectRatio (trace detection ratio) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TraceDetector = (TraceDetector_TypeDef)msg.data.via.i64; // Unpack and assign the TraceDetector (trace detector) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->RxPort = (RxPort_TypeDef)msg.data.via.i64; // Unpack and assign the RxPort (RF input port) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->BusTimeout_ms = (uint32_t)msg.data.via.u64; // Unpack and assign the BusTimeout_ms (bus timeout time) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerSource = (RTA_TriggerSource_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerSource (trigger source) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerEdge = (TriggerEdge_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerEdge (input trigger edge) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerMode = (TriggerMode_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerMode (trigger mode) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerAcqTime = (double)msg.data.via.f64; // Unpack and assign the TriggerAcqTime (sampling time after trigger) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerOutMode = (TriggerOutMode_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerOutMode (trigger output mode) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerOutPulsePolarity = (TriggerOutPulsePolarity_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerOutPulsePolarity (trigger output pulse polarity) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerLevel_dBm = (double)msg.data.via.f64; // Unpack and assign the TriggerLevel_dBm (threshold for level trigger) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerLevel_SafeTime = (double)msg.data.via.f64; // Unpack and assign the TriggerLevel_SafeTime (debounce safe time for level trigger, in seconds) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerDelay = (double)msg.data.via.f64; // Unpack and assign the TriggerDelay (trigger delay for level trigger, in seconds) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->PreTriggerTime = (double)msg.data.via.f64; // Unpack and assign the PreTriggerTime (pre-trigger time for level trigger, in seconds) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerTimerSync = (TriggerTimerSync_TypeDef)msg.data.via.i64; // Unpack and assign the TriggerTimerSync (timer trigger: synchronization with external trigger edge option) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->TriggerTimer_Period = (double)msg.data.via.f64; // Unpack and assign the TriggerTimer_Period (timer trigger: period) of RTA_Profile.

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->EnableReTrigger = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableReTrigger (Auto retrigger: enables the device to respond multiple times after one trigger).

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->ReTrigger_Period = (double)msg.data.via.f64; // Unpack RTA_Profile's ReTrigger_Period (Auto retrigger: time interval between multiple responses).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->ReTrigger_Count = (uint16_t)msg.data.via.u64; // Unpack RTA_Profile's ReTrigger_Count (Auto retrigger: number of automatic retrigger executions after each original trigger).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->GainStrategy = (GainStrategy_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's GainStrategy (Gain strategy).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->Preamplifier = (PreamplifierState_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's Preamplifier (Preamplifier action).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->AnalogIFBWGrade = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's AnalogIFBWGrade (IF bandwidth grade).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->IFGainGrade = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's IFGainGrade (IF gain grade).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->EnableDebugMode = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableDebugMode (Debug mode).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->ReferenceClockSource = (ReferenceClockSource_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's ReferenceClockSource (Reference clock source).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->ReferenceClockFrequency = (double)msg.data.via.f64; // Unpack RTA_Profile's ReferenceClockFrequency (Reference clock frequency).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->EnableReferenceClockOut = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableReferenceClockOut (Enable reference clock output).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->SystemClockSource = (SystemClockSource_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's SystemClockSource (System clock source).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->ExternalSystemClockFrequency = (double)msg.data.via.f64; // Unpack RTA_Profile's ExternalSystemClockFrequency (External system clock frequency, Hz).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->Atten = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's Atten (Attenuation).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->DCCancelerMode = (DCCancelerMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's DCCancelerMode (DC suppression).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->QDCMode = (QDCMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's QDCMode (IQ amplitude and phase corrector).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->QDCIGain = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCIGain (Normalized linear gain I path).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->QDCQGain = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCQGain (Normalized linear gain Q path).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->QDCPhaseComp = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCPhaseComp (Normalized phase compensation coefficient).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->DCCIOffset = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's DCCIOffset (DC offset of I channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->DCCQOffset = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's DCCQOffset (DC offset of Q channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile->LOOptimization = (LOOptimization_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's LOOptimization (LO optimization).
	
	// RTA_FrameInfo_TypeDef parsing content
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->StartFrequency_Hz = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's StartFrequency_Hz (Start frequency of spectrum).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->StopFrequency_Hz = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's StopFrequency_Hz (Stop frequency of spectrum).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->POI = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's POI (Minimum signal duration).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->TraceTimestampStep = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's TraceTimestampStep (Timestamp step for traces within each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->TimeResolution = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's TimeResolution (Sampling time for each time-domain data).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->PacketAcqTime = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's PacketAcqTime (Acquisition time corresponding to each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->PacketCount = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketCount (Total number of data packets).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->PacketFrame = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketFrame (Number of valid frames in each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->FFTSize = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FFTSize (Number of points per FFT frame).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->FrameWidth = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FrameWidth (Number of points after FFT frame cropping).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->FrameHeight = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FrameHeight (Amplitude range corresponding to FFT frame).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->PacketSamplePoints = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketSamplePoints (Number of sampling points corresponding to each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->PacketValidPoints = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketValidPoints (Number of valid frequency-domain points in each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->MaxDensityValue = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's MaxDensityValue (Maximum element value of probability density bitmap).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo->GainParameter = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's GainParameter (Gain-related parameter).
	return 0;
}

// RTA data parsing function.
int GetRTARecordFileData(const char* FilePath, uint64_t PacketNum, uint8_t SpectrumStream[], RTA_PlotInfo_TypeDef RTA_PlotInfo[], RTA_TriggerInfo_TypeDef RTA_TriggerInfo[], MeasAuxInfo_TypeDef MeasAuxInfo[])
{
    int Status = 0;                                  // Initialize the function return value variable.
    fstream file;                                    // Declare a file stream object for reading the file.
    string FilePath1 = FilePath;                     // Assign the input file path string to a new variable FilePath1.
    file.open(FilePath1, ios::in | ios::binary);     // Open the file in binary read mode. If the file does not exist or cannot be opened, it returns false.

    // Check whether the file is successfully opened.
    if (!file.is_open())
    {
        cout << "The file failed to be opened, please check whether there is a record file under the path!" << endl;
        Status = -109;
        return Status;
    }

    uint64_t PacketCount = 0;                                              // Define the variable PacketCount to store the packet count read from the file.
    file.seekg(64, ios::beg);                                               // Move the file pointer to the 64th byte from the beginning.
    file.read(reinterpret_cast<char*>(&PacketCount), sizeof(PacketCount)); // Read 64-bit data from the file and store it in the PacketCount variable.
    PacketCount = (((PacketCount & 0xff) << 56) |                           // Endianness conversion.
                   ((PacketCount & 0xff00) << 40) |
                   ((PacketCount & 0xff0000) << 24) |
                   ((PacketCount & 0xff000000) << 8) |
                   ((PacketCount & 0xff00000000) >> 8) |
                   ((PacketCount & 0xff0000000000) >> 24) |
                   ((PacketCount & 0xff000000000000) >> 40) |
                   ((PacketCount & 0xff00000000000000) >> 56));

    file.seekg(72 + 10 * 1024 * 1024, ios::beg);        // Move the file pointer to the position at offset 72 + 10MB.
    uint16_t Length = 0;                               // Define the variable Length.
    file.read(reinterpret_cast<char*>(&Length), sizeof(Length)); // Read 2 bytes of data from the file into Length.
    Length = ((Length & 0xff) << 8 | (Length & 0xff00) >> 8);    // Handle byte order conversion (big-endian to little-endian).
    file.seekg(74 + 10 * 1024 * 1024, ios::beg);        // Move the file pointer to the actual data starting position (at 74 + 10MB).

    char* ConData = new char[Length];                  // Create an array to store the read data.
    vector<char> ConData1(Length);
    file.read(ConData1.data(), ConData1.size());        // Read data from the file into ConData1.
    memcpy(ConData, ConData1.data(), ConData1.size());  // Copy data from ConData1 into ConData.

    if (ConData == NULL) // Check whether the data was successfully read. If ConData is a null pointer, the read failed.
    {
        cout << "The file failed to be read!" << endl;
        return -1;
    }

    // Define and initialize two structures for processing subsequent data.
    RTA_Profile_TypeDef RTA_Profile;
    RTA_FrameInfo_TypeDef RTA_FrameInfo;

    msgpack_unpacked msg;        // Create and initialize a msgpack unpacking object.
    msgpack_unpacked_init(&msg); // Initialize the msg object.

    size_t length_1 = Length; // Assign the value of Length to the variable length_1.
    size_t off = 0;           // Initialize the offset off to 0, meaning reading starts from the beginning.

    msgpack_unpack_next(&msg, ConData, length_1, &off);   // Unpack the current object and point to the next object.
    RTA_Profile.CenterFreq_Hz = (double)msg.data.via.f64; // Unpack RTA_Profile's CenterFreq_Hz (center frequency).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.RefLevel_dBm = (double)msg.data.via.f64; // Unpack RTA_Profile's RefLevel_dBm (reference level).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.RBW_Hz = (double)msg.data.via.f64; // Unpack RTA_Profile's RBW_Hz (resolution bandwidth).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.VBW_Hz = (double)msg.data.via.f64; // Unpack RTA_Profile's VBW_Hz (video bandwidth).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.RBWMode = (RBWMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's RBWMode (resolution bandwidth mode).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.VBWMode = (VBWMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's VBWMode (video bandwidth mode).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.DecimateFactor = (uint32_t)msg.data.via.u64; // Unpack RTA_Profile's DecimateFactor (decimation factor).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.Window = (Window_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's Window (window function).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.SweepTimeMode = (SweepTimeMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's SweepTimeMode (sweep time mode).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.SweepTime = (double)msg.data.via.f64; // Unpack RTA_Profile's SweepTime (sweep time).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.Detector = (Detector_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's Detector.

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TraceDetectMode = (TraceDetectMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TraceDetectMode (trace detection).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TraceDetectRatio = (uint32_t)msg.data.via.u64; // Unpack RTA_Profile's TraceDetectRatio (trace detection ratio).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TraceDetector = (TraceDetector_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TraceDetector (trace detector).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.RxPort = (RxPort_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's RxPort (RF input port).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.BusTimeout_ms = (uint32_t)msg.data.via.u64; // Unpack RTA_Profile's BusTimeout_ms (bus timeout).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TriggerSource = (RTA_TriggerSource_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerSource (trigger source).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TriggerEdge = (TriggerEdge_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerEdge (trigger edge).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TriggerMode = (TriggerMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerMode (trigger mode).

    msgpack_unpack_next(&msg, ConData, length_1, &off);
    RTA_Profile.TriggerAcqTime = (double)msg.data.via.f64; // Unpack RTA_Profile's TriggerAcqTime (sampling time after trigger).

	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerOutMode = (TriggerOutMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerOutMode (trigger output mode).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerOutPulsePolarity = (TriggerOutPulsePolarity_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerOutPulsePolarity (trigger output pulse polarity).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerLevel_dBm = (double)msg.data.via.f64; // Unpack RTA_Profile's TriggerLevel_dBm (level trigger: threshold).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerLevel_SafeTime = (double)msg.data.via.f64; // Unpack RTA_Profile's TriggerLevel_SafeTime (level trigger: debounce safe time, in seconds).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerDelay = (double)msg.data.via.f64; // Unpack RTA_Profile's TriggerDelay (level trigger: trigger delay, in seconds).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.PreTriggerTime = (double)msg.data.via.f64; // Unpack RTA_Profile's PreTriggerTime (level trigger: pre-trigger time, in seconds).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerTimerSync = (TriggerTimerSync_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's TriggerTimerSync (timer trigger: synchronization option with external trigger edge).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.TriggerTimer_Period = (double)msg.data.via.f64; // Unpack RTA_Profile's TriggerTimer_Period (timer trigger: period).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.EnableReTrigger = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableReTrigger (automatic re-trigger: enable multiple responses after a single trigger).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.ReTrigger_Period = (double)msg.data.via.f64; // Unpack RTA_Profile's ReTrigger_Period (automatic re-trigger: time interval between multiple responses).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.ReTrigger_Count = (uint16_t)msg.data.via.u64; // Unpack RTA_Profile's ReTrigger_Count (automatic re-trigger: number of re-triggers after each original trigger).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.GainStrategy = (GainStrategy_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's GainStrategy (gain strategy).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.Preamplifier = (PreamplifierState_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's Preamplifier (preamplifier action).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.AnalogIFBWGrade = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's AnalogIFBWGrade (analog IF bandwidth grade).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.IFGainGrade = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's IFGainGrade (IF gain grade).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.EnableDebugMode = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableDebugMode (debug mode).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.ReferenceClockSource = (ReferenceClockSource_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's ReferenceClockSource (reference clock source).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.ReferenceClockFrequency = (double)msg.data.via.f64; // Unpack RTA_Profile's ReferenceClockFrequency (reference clock frequency).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.EnableReferenceClockOut = (uint8_t)msg.data.via.u64; // Unpack RTA_Profile's EnableReferenceClockOut (enable reference clock output).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.SystemClockSource = (SystemClockSource_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's SystemClockSource (system clock source).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.ExternalSystemClockFrequency = (double)msg.data.via.f64; // Unpack RTA_Profile's ExternalSystemClockFrequency (external system clock frequency, Hz).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.Atten = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's Atten (attenuation).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.DCCancelerMode = (DCCancelerMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's DCCancelerMode (DC suppression).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.QDCMode = (QDCMode_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's QDCMode (IQ amplitude-phase corrector).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.QDCIGain = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCIGain (normalized linear gain for I channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.QDCQGain = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCQGain (normalized linear gain for Q channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.QDCPhaseComp = (float)msg.data.via.f64; // Unpack RTA_Profile's QDCPhaseComp (normalized phase compensation coefficient).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.DCCIOffset = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's DCCIOffset (DC offset for I channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.DCCQOffset = (int8_t)msg.data.via.i64; // Unpack RTA_Profile's DCCQOffset (DC offset for Q channel).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_Profile.LOOptimization = (LOOptimization_TypeDef)msg.data.via.i64; // Unpack RTA_Profile's LOOptimization (local oscillator optimization).
	
	// Parsing RTA_FrameInfo_TypeDef contents
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.StartFrequency_Hz = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's StartFrequency_Hz (spectrum start frequency).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.StopFrequency_Hz = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's StopFrequency_Hz (spectrum stop frequency).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.POI = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's POI (minimum signal duration).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.TraceTimestampStep = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's TraceTimestampStep (timestamp step for each trace within a packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.TimeResolution = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's TimeResolution (sampling time for each time-domain data point).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.PacketAcqTime = (double)msg.data.via.f64; // Unpack RTA_FrameInfo's PacketAcqTime (acquisition time for each data packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.PacketCount = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketCount (total number of packets).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.PacketFrame = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketFrame (valid frames per packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.FFTSize = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FFTSize (FFT points per frame).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.FrameWidth = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FrameWidth (points after FFT frame truncation).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.FrameHeight = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's FrameHeight (spectral magnitude range corresponding to FFT frame).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.PacketSamplePoints = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketSamplePoints (sample points per packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.PacketValidPoints = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's PacketValidPoints (number of valid frequency-domain points per packet).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.MaxDensityValue = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's MaxDensityValue (maximum value for probability density bitmap elements).
	
	msgpack_unpack_next(&msg, ConData, length_1, &off);
	RTA_FrameInfo.GainParameter = (uint32_t)msg.data.via.u64; // Unpack RTA_FrameInfo's GainParameter (gain-related parameter).
	
	file.seekg(74 + 10 * 1024 * 1024 + Length, ios::beg); // Move the file pointer to the start of the data packet, skipping the first 74 bytes, 10 MB, and Length bytes.	
 
	for (int j = 0; j < PacketCount; j++)                                                                                                               // Loop through each data packet.
	{
		int Packetsize = 0;                                                                                                                             // Variable to store the current packet size.
		file.read(reinterpret_cast<char*>(&Packetsize), sizeof(Packetsize));                                                                            // Read the current packet size (4 bytes) from the file.
		Packetsize = (((Packetsize & 0xff) << 24) | ((Packetsize & 0xff00) << 8) | ((Packetsize & 0xff0000) >> 8) | ((Packetsize & 0xff000000) >> 24)); // Convert the packet size from big-endian to little-endian.
	
		if (j == PacketNum)                                                      // If the current packet being processed is the specified packet (PacketNum).
		{
			for (int k = 0; k < RTA_FrameInfo.PacketValidPoints; k++)            // For the current packet, read its frequency data.
			{
				uint8_t Spectrum;                                                // Variable to store the frequency data for the current point.
				file.read(reinterpret_cast<char*>(&Spectrum), sizeof(Spectrum)); // Read one frequency value (1 byte) from the file.
				SpectrumStream[k] = Spectrum;                                    // Store the frequency data in SpectrumStream.
			}
		}
		else
		{
			for (int k = 0; k < RTA_FrameInfo.PacketValidPoints; k++)            // For packets that are not the target packet, simply skip the frequency data.
			{
				uint8_t Spectrum;                                                // Variable to store the frequency data for the current point.
				file.read(reinterpret_cast<char*>(&Spectrum), sizeof(Spectrum)); // Read one frequency value (1 byte) from the file but do not save it (skip the data).
			}
		}
	
		union FloatConversion u; // Define a union containing both float and int types, for converting between float and int.
	
		file.read(reinterpret_cast<char*>(&RTA_PlotInfo[j].ScaleTodBm), sizeof(RTA_PlotInfo[j].ScaleTodBm)); // Read ScaleTodBm data and perform byte order conversion.
		u.f = RTA_PlotInfo[j].ScaleTodBm;                                                                    // Assign the read float value to the float member of the union.
		
		float ScaleTodBm = ((u.i & 0xFF) << 24) | ((u.i & 0xFF00) << 8) | ((u.i & 0xFF0000) >> 8) | ((u.i & 0xFF000000) >> 24); // Convert the ScaleTodBm value from big-endian to little-endian.
		float little_endian_float11;
		u.i = ScaleTodBm;                                   // Assign the converted integer value back to the int member of the union.
		little_endian_float11 = u.f;                        // Convert the value back to float.
		RTA_PlotInfo[j].ScaleTodBm = little_endian_float11; // Store the converted value in the structure.
	
		file.read(reinterpret_cast<char*>(&RTA_PlotInfo[j].OffsetTodBm), sizeof(RTA_PlotInfo[j].OffsetTodBm));                             // Read OffsetTodBm data and perform byte order conversion.
		u.f = RTA_PlotInfo[j].OffsetTodBm;                                                                                                 // Assign the read float value to the union.
		RTA_PlotInfo[j].OffsetTodBm = ((u.i & 0xFF) << 24) | ((u.i & 0xFF00) << 8) | ((u.i & 0xFF0000) >> 8) | ((u.i & 0xFF000000) >> 24); // Convert OffsetTodBm from big-endian to little-endian.
		float little_endian_float111;
		u.i = RTA_PlotInfo[j].OffsetTodBm;                    // Assign back to the union's integer member.
		little_endian_float111 = u.f;                         // Convert the integer back to float.
		RTA_PlotInfo[j].OffsetTodBm = little_endian_float111; // Store the converted result.
	
		file.read(reinterpret_cast<char*>(&RTA_PlotInfo[j].SpectrumBitmapIndex), sizeof(RTA_PlotInfo[j].SpectrumBitmapIndex)); // Read SpectrumBitmapIndex data and perform byte order conversion.
		uint64_t SpectrumBitmapindex_1 =(((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff) << 56) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff00) << 40) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff0000) << 24) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff000000) << 8) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff00000000) >> 8) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff0000000000) >> 24) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff000000000000) >> 40) |
			((RTA_PlotInfo[j].SpectrumBitmapIndex & 0xff00000000000000) >> 56)); // Perform byte order conversion for the 64-bit integer.
		RTA_PlotInfo[j].SpectrumBitmapIndex = SpectrumBitmapindex_1;             // Store the converted value.
	

		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint), sizeof(RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint)); // Read SysTimerCountOfFirstDataPoint data and perform byte order conversion.
		uint64_t SysTimerCountOfFirstDataPoint =(((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff) << 56) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff00) << 40) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff0000) << 24) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff000000) << 8) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff00000000) >> 8) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff0000000000) >> 24) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff000000000000) >> 40) |
			((RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint & 0xff00000000000000) >> 56)); // Perform byte order conversion for SysTimerCountOfFirstDataPoint.
		RTA_TriggerInfo[j].SysTimerCountOfFirstDataPoint = SysTimerCountOfFirstDataPoint;     // Store the converted result.
	

		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].InPacketTriggeredDataSize), sizeof(RTA_TriggerInfo[j].InPacketTriggeredDataSize)); // Read InPacketTriggeredDataSize data and perform byte order conversion.
		uint16_t InPacketTriggeredDataSize =(((RTA_TriggerInfo[j].InPacketTriggeredDataSize & 0x00ff) << 8) |
				((RTA_TriggerInfo[j].InPacketTriggeredDataSize & 0xff00) >> 8));                                                                 // Perform byte order conversion for InPacketTriggeredDataSize.
	
		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].InPacketTriggerEdges), sizeof(RTA_TriggerInfo[j].InPacketTriggerEdges)); // Read InPacketTriggerEdges data and perform byte order conversion.
		uint16_t InPacketTriggerEdges =(((RTA_TriggerInfo[j].InPacketTriggerEdges & 0x00ff) << 8) |
				((RTA_TriggerInfo[j].InPacketTriggerEdges & 0xff00) >> 8));                                                            // Perform byte order conversion for InPacketTriggerEdges.
		RTA_TriggerInfo[j].InPacketTriggerEdges = InPacketTriggerEdges;                                                                // Store the converted result.
	
		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].StartDataIndexOfTriggerEdges), sizeof(RTA_TriggerInfo[j].StartDataIndexOfTriggerEdges)); // Read StartDataIndexOfTriggerEdges data.
	
		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].SysTimerCountOfEdges), sizeof(RTA_TriggerInfo[j].SysTimerCountOfEdges)); // Read SysTimerCountOfEdges data.
	
		file.read(reinterpret_cast<char*>(&RTA_TriggerInfo[j].EdgeType), sizeof(RTA_TriggerInfo[j].EdgeType)); // Read EdgeType data.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].MaxIndex), sizeof(MeasAuxInfo[j].MaxIndex)); // Read MaxIndex data and perform byte order conversion (big-endian to little-endian).
		uint32_t MaxIndex_1 = ((MeasAuxInfo[j].MaxIndex & 0xFF) << 24) |                               // Get the lowest byte and move it to the highest bit.
			((MeasAuxInfo[j].MaxIndex & 0xFF00) << 8) |                                                // Get the second-lowest byte and move it to the second-highest bit.
			((MeasAuxInfo[j].MaxIndex & 0xFF0000) >> 8) |                                              // Get the second-highest byte and move it to the second-lowest bit.
			((MeasAuxInfo[j].MaxIndex & 0xFF000000) >> 24);                                            // Get the highest byte and move it to the lowest bit.
		MeasAuxInfo[j].MaxIndex = MaxIndex_1;                                                          // Store the converted result in MaxIndex.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].MaxPower_dBm), sizeof(MeasAuxInfo[j].MaxPower_dBm)); // Read MaxPower_dBm data and perform byte order conversion (little-endian to big-endian).
		u.f = MeasAuxInfo[j].MaxPower_dBm;                                                                     // Convert MaxPower_dBm to floating-point format.
		float MaxPower_1 = ((u.i & 0xFF) << 24) |                                                              // Get the lowest byte and move it to the highest bit.
			((u.i & 0xFF00) << 8) |                                                                            // Get the second-lowest byte and move it to the second-highest bit.
			((u.i & 0xFF0000) >> 8) |                                                                          // Get the second-highest byte and move it to the second-lowest bit.
			((u.i & 0xFF000000) >> 24);                                                                        // Get the highest byte and move it to the lowest bit.
		float little_endian_float; u.i = MaxPower_1; little_endian_float = u.f;                                // Convert the byte order result back.
		MeasAuxInfo[j].MaxPower_dBm = little_endian_float;                                                     // Update MaxPower_dBm.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].Temperature), sizeof(MeasAuxInfo[j].Temperature)); // Read Temperature data and perform byte order conversion.
		int16_t Temperature_1 = ((MeasAuxInfo[j].Temperature & 0xff) << 8 |                                  // Get the lowest byte and move it to the highest bit.
			(MeasAuxInfo[j].Temperature & 0xff00) >> 8);                                                     // Get the highest byte and move it to the lowest bit.
		MeasAuxInfo[j].Temperature = Temperature_1 * 0.01;                                                   // Convert to actual temperature value, unit is ℃.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].RFState), sizeof(MeasAuxInfo[j].RFState)); // Read RFState data and perform byte order conversion.
		uint16_t RFState_1 = ((MeasAuxInfo[j].RFState & 0xff) << 8 |                                 // Get the lowest byte and move it to the highest bit.
			(MeasAuxInfo[j].RFState & 0xff00) >> 8);                                                 // Get the highest byte and move it to the lowest bit.
		MeasAuxInfo[j].RFState = RFState_1;                                                          // Update RFState.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].BBState), sizeof(MeasAuxInfo[j].BBState)); // Read BBState data and perform byte order conversion.
		uint16_t BBState_1 = ((MeasAuxInfo[j].BBState & 0xff) << 8 |                                 // Get the lowest byte and move it to the highest bit.
			(MeasAuxInfo[j].BBState & 0xff00) >> 8);                                                 // Get the highest byte and move it to the lowest bit.
		MeasAuxInfo[j].BBState = BBState_1;                                                          // Update BBState.
	
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].GainPattern), sizeof(MeasAuxInfo[j].GainPattern)); // Read GainPattern data and perform byte order conversion.
		uint16_t GainPattern_1 = ((MeasAuxInfo[j].GainPattern & 0xff) << 8 |                                 // Get the low byte and move it to the high position.
			(MeasAuxInfo[j].GainPattern & 0xff00) >> 8);                                                     // Get the high byte and move it to the low position.
		MeasAuxInfo[j].GainPattern = GainPattern_1;                                                          // Update GainPattern.
		
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].ConvertPattern), sizeof(MeasAuxInfo[j].ConvertPattern)); // Read ConvertPattern data and perform byte order (big-endian to little-endian) conversion.
		uint32_t ConvertPattern_1 = ((MeasAuxInfo[j].ConvertPattern & 0xFF) << 24) |                               // Get the lowest byte and move it to the highest position.
			((MeasAuxInfo[j].ConvertPattern & 0xFF00) << 8) |                                                       // Get the second-lowest byte and move it to the second-highest position.
			((MeasAuxInfo[j].ConvertPattern & 0xFF0000) >> 8) |                                                    // Get the second-highest byte and move it to the second-lowest position.
			((MeasAuxInfo[j].ConvertPattern & 0xFF000000) >> 24);                                                  // Get the highest byte and move it to the lowest position.
		MeasAuxInfo[j].ConvertPattern = ConvertPattern_1;                                                          // Update ConvertPattern.
		
		union DoubleConversion q; // Read SysTimeStamp data and perform byte order (big-endian to little-endian) conversion.
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].SysTimeStamp), sizeof(MeasAuxInfo[j].SysTimeStamp));
		q.d = MeasAuxInfo[j].SysTimeStamp;                    // Convert SysTimeStamp to double type.
		uint64_t SysTimeStamp_1 = ((q.i & 0xFF) << 56) |    // Get the lowest byte and move it to the highest position.
			((q.i & 0xFF00) << 40) |                        // Get the second-lowest byte and move it to the second-highest position.
			((q.i & 0xFF0000) << 24) |                        // Get the second-highest byte and move it to the second-lowest position.
			((q.i & 0xFF000000) << 8) |                        // Get the highest byte and move it to the second-lowest position.
			((q.i >> 8) & 0xFF000000) |                        // Move the remaining byte.
			((q.i >> 24) & 0xFF0000) |
			((q.i >> 40) & 0xFF00) |
			((q.i >> 56) & 0xFF);                            // Get the highest byte and move it to the lowest position.
		double little_endian_double;
		q.i = SysTimeStamp_1;
		little_endian_double = q.d;                            // Assign the converted byte order result to double type.
		MeasAuxInfo[j].SysTimeStamp = little_endian_double; // Update SysTimeStamp.
		
		union DoubleConversion A;                                                                                         // Define a union to store both double and uint64_t types of data.
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].AbsoluteTimeStamp), sizeof(MeasAuxInfo[j].AbsoluteTimeStamp)); // Read AbsoluteTimeStamp field from the file and perform byte order conversion.
		A.d = MeasAuxInfo[j].AbsoluteTimeStamp;                                                                             // Assign AbsoluteTimeStamp to union A (convert double type data to uint64_t type).
		// Convert the read byte order to little-endian byte order
		uint64_t AbsoluteTimeStamp_1 = ((A.i & 0xFF) << 56) |                                                                 // Move the lowest byte to the highest position.
			((A.i & 0xFF00) << 40) |                                                                                         // Move the second-lowest byte to the second-highest position.
			((A.i & 0xFF0000) << 24) |                                                                                         // Move the second-highest byte to the second-lowest position.
			((A.i & 0xFF000000) << 8) |                                                                                         // Move the highest byte to the lowest position.
			((A.i >> 8) & 0xFF000000) |                                                                                         // Move the remaining byte.
			((A.i >> 24) & 0xFF0000) |                                                                                         // Move the remaining byte.
			((A.i >> 40) & 0xFF00) |                                                                                         // Move the remaining byte.
			((A.i >> 56) & 0xFF);                                                                                             // Move the highest byte to the lowest position.
		double little_endian_double1;                                                                                         // Assign the converted byte order back to the union and convert it to double type.
		A.i = AbsoluteTimeStamp_1;                                                                                             // Update the union A's i member.
		little_endian_double1 = A.d;                                                                                         // Get the converted double type data.
		MeasAuxInfo[j].AbsoluteTimeStamp = little_endian_double1;                                                         // Store the converted absolute timestamp value back into MeasAuxInfo[j].
		
		union FloatConversion L;                                                                           // Define a union to store both float and uint32_t types of data.
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].Latitude), sizeof(MeasAuxInfo[j].Latitude)); // Read Latitude field from the file and perform byte order conversion.
		L.f = MeasAuxInfo[j].Latitude;                                                                           // Assign Latitude to union L (convert float type data to uint32_t type).
		// Convert the read byte order to little-endian byte order
		float Latitude_1 = ((L.i & 0xFF) << 24) |                                                       // Move the lowest byte to the highest position.
			((L.i & 0xFF00) << 8) |                                                                       // Move the second-lowest byte to the second-highest position.
			((L.i & 0xFF0000) >> 8) |                                                                   // Move the second-highest byte to the second-lowest position.
			((L.i & 0xFF000000) >> 24);                                                                   // Move the highest byte to the lowest position.
		float little_endian_float1;                                                                           // Assign the converted byte order back to the union and convert it to float type.
		L.i = Latitude_1;                                                                               // Update the union L's i member.
		little_endian_float1 = L.f;                                                                         // Get the converted float type data.
		MeasAuxInfo[j].Latitude = little_endian_float1;                                                   // Store the converted latitude value back into MeasAuxInfo[j].
		
		union FloatConversion Lo;                                                                           // Define a union to store both float and uint32_t types of data.
		file.read(reinterpret_cast<char*>(&MeasAuxInfo[j].Longitude), sizeof(MeasAuxInfo[j].Longitude)); 	// Read Longitude field from the file and perform byte order conversion.
		Lo.f = MeasAuxInfo[j].Longitude;                                                                    // Assign Longitude to union Lo (convert float type data to uint32_t type).
		// Convert the read byte order to little-endian byte order
		float Longitude_1 = ((Lo.i & 0xFF) << 24) |                                                         // Move the lowest byte to the highest position.
			((Lo.i & 0xFF00) << 8) |                                                                        // Move the second-lowest byte to the second-highest position.
			((Lo.i & 0xFF0000) >> 8) |                                                                      // Move the second-highest byte to the second-lowest position.
			((Lo.i & 0xFF000000) >> 24);                                                                    // Move the highest byte to the lowest position.
		float little_endian_float2;                                                                         // Assign the converted byte order back to the union and convert it to float type.
		Lo.i = Longitude_1;                                                                                 // Update the union Lo's i member.
		little_endian_float2 = Lo.f;                                                                        // Get the converted float type data.
		MeasAuxInfo[j].Longitude = little_endian_float2;                                                    // Store the converted longitude value back into MeasAuxInfo[j].
	}
	return 0;
}		

int RTAMode_PlayBack()
{
	int Status = 0;
	const char* FilePath = "./data/0029_20241231_170710.part1.rtspectrum"; 	// Modify the record file name as needed, e.g., 0022_20241225_094541.part1.rtspectrum.
	uint64_t PacketCount; 													// Define the variable PacketCount to store the number of packets.
	RTA_Profile_TypeDef RTA_Profile; 										// Define the variable RTA_Profile of type RTA_Profile to store configuration information.
	RTA_FrameInfo_TypeDef RTA_FrameInfo;									// Define the variable RTA_FrameInfo of type RTA_FrameInfo to store configuration related to frame information.
	uint64_t PacketNum = 5; 												// Define the variable PacketNum to specify reading the 5th packet.

	Status = GetRTARecordConfig(FilePath, &RTA_Profile, &RTA_FrameInfo, &PacketCount); // Call GetRTARecordConfig function to read the configuration data from the file.

	static uint32_t PacketVaPoints = RTA_FrameInfo.PacketValidPoints; // Static initialization of the variable PacketVaPoints and set it to the PacketValidPoints obtained from RTA_FrameInfo.

	// Initialize multiple vector data structures using the size of PacketCount. These structures will store different types of data.
	vector<MeasAuxInfo_TypeDef> MeasAuxInfo(PacketCount);
	vector<RTA_PlotInfo_TypeDef> RTA_PlotInfo(PacketCount);
	vector<RTA_TriggerInfo_TypeDef> RTA_TriggerInfo(PacketCount);
	vector<uint8_t> SpectrumStream(PacketVaPoints);
	vector<float> Spectrum(RTA_FrameInfo.FrameWidth); // Array to store the spectrum in dBm units.

	char FileName[255]; 								// Define a character array for the file name.
	sprintf_s(FileName, "./data/RTAMode_Data.txt");	 	// Format the file name as "RTAMode_Data.txt".
	fstream File1; 										// Create an fstream object to handle file operations for storing parsed IQ data.
	File1.open(FileName, ios::out); 					// Open the file in write mode.
	
	for (int i = 0; i < 3; i++) // This function extracts data from the file based on PacketNum (the current packet number) and stores it into the previously allocated data structures.
	{
		Status = GetRTARecordFileData(FilePath, i, SpectrumStream.data(), RTA_PlotInfo.data(), RTA_TriggerInfo.data(), MeasAuxInfo.data()); // Call GetRTARecordFileData function to read specific data from the data file.

		for (int j = 0; j < RTA_FrameInfo.FrameWidth; j++) // Convert the RTA spectrum data units to dBm.
		{
			Spectrum[j] = (float)SpectrumStream[j] * RTA_PlotInfo[i].ScaleTodBm + RTA_PlotInfo[i].OffsetTodBm;
			File1 << Spectrum[j] << "\n";
		}
		cout << "The " << i << " pack has been saved" << endl;
	}
	
	File1.close(); // Close the file stream, save, and release resources.
	return 0;
}
		