% Configure compilation environment
% setenv('MW_MINGW64_LOC','D:\msys64\ucrt64');
% mex -setup C++

filePath = fullfile(pwd, 'htra_api_mat');  

% Check if the folder exists, create it if not
if ~exist(filePath, 'dir')
    run('htra_api.m');
    filePath = fullfile(pwd, 'htra_api_mat');  
end

% Load htra_api.dll
if not(libisloaded('htra_api.dll'))   
    loadlibrary('.\htra_api\htra_api.dll','.\htra_api\htra_api.h'); % Make sure the path to .dll and .h is correct
end

libfunctions('htra_api'); % View all functions in the API

% Open device
Device = libpointer; % Create a Device pointer
DevNum = 0;
Status = 0;

load(fullfile(filePath, 'BootProfile.mat'));  % Load BootProfile_TypeDef struct
load(fullfile(filePath, 'BootInfo.mat'));     % Load BootInfo_TypeDef struct
load(fullfile(filePath, 'DeviceState.mat'));  % Load DeviceState_TypeDef struct

IS_USB = 1;  % Use USB by default; set to 0 if using Ethernet device

if IS_USB == 1
    % Configure USB interface
    BootProfile.PhysicalInterface = 0;
else
    % Configure Ethernet interface
    BootProfile.PhysicalInterface = 3;
    BootProfile.ETH_IPVersion = 0;
    BootProfile.ETH_RemotePort = 5000;
    BootProfile.ETH_ReadTimeOut = 5000;
    BootProfile.ETH_IPAddress = [192, 168, 1, 100];
end

% Call Device_Open function
Status = calllib('htra_api', 'Device_Open', Device, DevNum, BootProfile, BootInfo);

if Status == 0
    get(BootProfile); % Print BootProfile
    get(BootInfo);    % Print BootInfo    
    fprintf('Device successfully opened\n');
else
    % Device failed to open, handle based on different error codes
    switch Status
        case -1
            fprintf('Error - Check device power, data cable connection, and driver installation\n');
        case -3
            fprintf('Error - RF calibration file missing, please copy it to CalFile folder\n');
        case -4
            fprintf('Error - IF calibration file missing, please copy it to CalFile folder\n');
        case -5
            fprintf('Error - Profile missing, please copy it to CalFile folder\n');
        case -6
            fprintf('Error - Device spec file missing, please copy it to CalFile folder\n');
        otherwise
            fprintf('Device failed to open: Unknown error Status = %d', Status);
    end

    % return error value
    return ;
end

load(fullfile(filePath, 'IQS_Profile.mat'));  % Load IQS_Profile_TypeDef struct

% Define IQS_ProfileIn and IQS_ProfileOut
IQS_ProfileIn = IQS_Profile;
IQS_ProfileOut = IQS_Profile;

% Call IQS_ProfileDeInit function
Status = calllib('htra_api', 'IQS_ProfileDeInit', Device, IQS_ProfileIn);
get(IQS_ProfileIn); % Print IQS_ProfileIn

% Modify IQS parameters
IQS_ProfileIn.CenterFreq_Hz = 1e9;   % Set center frequency
IQS_ProfileIn.RefLevel_dBm = 0;      % Set reference level
IQS_ProfileIn.DecimateFactor = 2;    % Set decimation factor
IQS_ProfileIn.TriggerMode= 1;        % Set trigger mode
IQS_ProfileIn.TriggerLength = 16242; % Set number of points per trigger

% Load IQS_StreamInfo_TypeDef struct
load(fullfile(filePath, 'IQS_StreamInfo.mat')); 

% Call IQS_Configuration function
Status = calllib('htra_api', 'IQS_Configuration', Device, IQS_ProfileIn, IQS_ProfileOut, IQS_StreamInfo);

% If configuration is successful£¨Status == 0£©
if Status == 0
    get(IQS_ProfileOut); % Print IQS_ProfileOut
    get(IQS_StreamInfo); % Print StreamInfo
    fprintf('Configuration successfully completed\n');
else
    % If call fails, print error and close device
    fprintf('IQS_Configuration call error Status = %d\n', Status);
	% Use Device_Close function
    Device_Close(Device);  
	%return 0, end the function
    return;
end

% Load IQS_TriggerInfo_TypeDef struct
load(fullfile(filePath, 'TriggerInfo.mat'));     
% Load MeasAuxInfo_TypeDef struct
load(fullfile(filePath, 'MeasAuxInfo.mat'));     

DSP = libpointer; % Create DSP pointer
Status = calllib('htra_api', 'DSP_Open', DSP);

% Load DSP_FFT_TypeDef struct
load(fullfile(filePath, 'DSP_FFT.mat'));         

% Define input and output for DSP FFT
DSP_FFTIn = DSP_FFT;
DSP_FFTOut = DSP_FFT;

TracePoints = uint32(0);  
TracePoints_p = libpointer('uint32Ptr', TracePoints);
Status = calllib('htra_api', 'DSP_FFT_DeInit', DSP_FFTIn);

DSP_FFTIn.Calibration = 0;  % Enable/disable calibration: 0 = off, others = on
DSP_FFTIn.DetectionRatio = 1;  % Set detection ratio
DSP_FFTIn.TraceDetector = 2;   % Set detector mode
DSP_FFTIn.FFTSize = IQS_StreamInfo.PacketSamples * IQS_StreamInfo.PacketCount;  % FFT size
DSP_FFTIn.Intercept = 1;  % Set intercept ratio
DSP_FFTIn.SamplePts = IQS_StreamInfo.PacketSamples * IQS_StreamInfo.PacketCount; % Sampling points
DSP_FFTIn.WindowType = 0; % Set window type

RBWRatio = 0;  
RBWRatio_p = libpointer('doublePtr', RBWRatio);
Status = calllib('htra_api', 'DSP_FFT_Configuration', DSP, DSP_FFTIn, DSP_FFTOut, TracePoints_p, RBWRatio_p);

% Create arrays to store frequency and spectrum data
Frequency = double(1:TracePoints_p.Value);
Spectrum = single(1:TracePoints_p.Value);
disp(TracePoints_p.Value)

%create Frequency_p to store SWP data
Frequency_p = libpointer('doublePtr', Frequency);
Spectrum_p = libpointer('singlePtr', Spectrum);

%Load IQStream_TypeDef struct
load(fullfile(filePath, 'IQStream.mat'));  

n = 10000;

% Trigger based on TriggerMode value
if strcmp(IQS_ProfileOut.TriggerMode, 'Adaptive')
    % If TriggerMode == Adaptive, call IQS_BusTriggerStart once
    Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
end

for j = 1:n
    % If TriggerMode == FixedPoints, call IQS_BusTriggerStart each iteration
    if strcmp(IQS_ProfileOut.TriggerMode, 'FixedPoints')
        Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
    end
    for i = 1:IQS_StreamInfo.PacketCount      
        Status = calllib('htra_api', 'IQS_GetIQStream_PM1', Device, IQStream);      
        if Status ~= 0
            fprintf('IQS_GetIQStream call error Status = %d\n', Status);
            return;
        end
    end
    Status = calllib('htra_api', 'DSP_FFT_IQSToSpectrum', DSP, IQStream, Frequency_p, Spectrum_p);   

    if Status ~= 0
        fprintf('DSP_FFT_IQSToSpectrum call error Status = %d\n', Status);
        return;
    end

    % Plot SWP spectrum
    plot(Frequency_p.Value, Spectrum_p.Value);
    ylim([-130, IQStream.IQS_Profile.RefLevel_dBm]);
    xlim([min(Frequency_p.Value), max(Frequency_p.Value)]);
    pause(0.01);
end

% Call IQS_BusTriggerStop function
Status = calllib('htra_api', 'IQS_BusTriggerStop', Device);

% Call DSP_Close function
Status = calllib('htra_api', 'DSP_Close', DSP);

% Call Device_Close function
Status = calllib('htra_api', 'Device_Close', Device);

clear all;

% Unload the DLL
unloadlibrary('htra_api');   
disp('Uninstall complete');
