% Configure the 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'); %.dll and .h file paths must be correct
end

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

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

load(fullfile(filePath, 'BootProfile.mat'));  % Directly load BootProfile_TypeDef structure
load(fullfile(filePath, 'BootInfo.mat'));  % Directly load BootInfo_TypeDef structure

IS_USB = 1;  % Default to USB device, set to 0 for Ethernet device

if IS_USB == 1
    % Configure USB interface
    BootProfile.PhysicalInterface = 0;
else
    % Configure ETH 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 BootInfo value
    get(BootInfo); % Print BootInfo value    
    fprintf('Device successfully opened\n');
else
    % Device opening failed, handle based on error status
    switch Status
        case -1
            fprintf('Error - Check the power supply of the device, the connection of the data cable, and check that the driver is installed correctly\n');
        case -3
            fprintf('Error - RF calibration file is missing, please copy the RF calibration file to the CalFile folder\n');
        case -4
            fprintf('Error - IF calibration file is missing, please copy the IF calibration file to the CalFile folder\n');
        case -5
            fprintf('Error - Profile is missing, please copy the profile to the CalFile folder\n');
        case -6
            fprintf('Error - The device spec file is missing, please copy the device spec file to the CalFile folder\n');
        otherwise
            fprintf('Device turn on failed: Returns another error Status = %d', Status);
    end

    % Return error status value
    return ;
end

load(fullfile(filePath, 'SWP_Profile.mat'));   % Directly load SWP_Profile_TypeDef structure
% Define SWP_ProfileIn pointer and SWP_ProfileOut pointer
SWP_ProfileIn = SWP_Profile;
SWP_ProfileOut = SWP_Profile;

% Call SWP_ProfileIn function
Status = calllib('htra_api', 'SWP_ProfileDeInit', Device, SWP_ProfileIn);
get(SWP_ProfileIn); % Print SWP_ProfileIn value

% Modify some parameters of SWP_ProfileIn structure
SWP_ProfileIn.StartFreq_Hz = 9e3;
SWP_ProfileIn.StopFreq_Hz = 3e9;
SWP_ProfileIn.RBWMode = 0;
SWP_ProfileIn.RBW_Hz = 300e3;

load(fullfile(filePath, 'TraceInfo.mat'));   % Directly load SWP_TraceInfo_TypeDef structure

% Call SWP_Configuration function
Status = calllib('htra_api', 'SWP_Configuration', Device, SWP_ProfileIn, SWP_ProfileOut, TraceInfo);

% If configuration is successfully applied (Status == 0)
if Status == 0
    get(SWP_ProfileOut); % Print TraceInfo value
    get(TraceInfo); % Print TraceInfo value
    fprintf('Configuration successfully applied\n');
else
    % If there is an error, print error message and close device
    fprintf('SWP_Configuration Call error Status = %d\n', Status);
    Device_Close(Device); 
    
    % Return 0, end function execution
    return;
end

load(fullfile(filePath, 'ASG_Profile.mat'));  % Directly load ASG_Profile_TypeDef structure
% Define ASG_ProfileIn pointer and ASG_ProfileOut pointer
ASG_ProfileIn = ASG_Profile;
ASG_ProfileOut = ASG_Profile;

load(fullfile(filePath, 'ASG_Info.mat'));  % Directly load file

Status = calllib('htra_api', 'ASG_ProfileDeInit', Device, ASG_ProfileIn);     

% Select signal type: Choice=0: Tone signal, Choice=1: Frequency sweep signal, Choice=2: Power sweep signal
Choice = 1;
ASG_ProfileIn.Port = 0;                     % Default port is 1

switch Choice
    case 1
        % Tone signal
        ASG_ProfileIn.CenterFreq_Hz = 1e9;    % Set tone signal frequency
        ASG_ProfileIn.Mode = 1;                     % Default mode is tone signal mode
        ASG_ProfileIn.TriggerSource = 0;            % Default trigger source is 0
        ASG_ProfileIn.Level_dBm = 0;               % Default signal amplitude
        ASG_ProfileIn.TriggerOutMode = 0;           % Default trigger output mode is 0
        ASG_ProfileIn.ReferenceClockFrequency = 10e6; % Default reference clock frequency
    case 2
        % Frequency sweep signal
        ASG_ProfileIn.StartFreq_Hz = 1e6;   % Sweep start frequency
        ASG_ProfileIn.StopFreq_Hz = 6e9;    % Sweep stop frequency
        ASG_ProfileIn.StepFreq_Hz = 1e6;      % Sweep step frequency
        ASG_ProfileIn.Level_dBm = 0;               % Default signal amplitude
        ASG_ProfileIn.Mode = 2;                % Set mode to frequency sweep
    case 3
        % Power sweep signal
        ASG_ProfileIn.CenterFreq_Hz = 1e9;   % Set center frequency
        ASG_ProfileIn.StartLevel_dBm = -30;    % Set start power
        ASG_ProfileIn.StopLevel_dBm = 0;     % Set stop power
        ASG_ProfileIn.Mode = 3;                % Set mode to power sweep
    otherwise
        error('Invalid Choice value. It should be 0, 1, or 2.');
end

Status = calllib('htra_api', 'ASG_Configuration', Device, ASG_ProfileIn, ASG_ProfileOut, ASG_Info);     

% Create Frequency to store SWP spectrum data, create PowerSpec_dBm to store SWP amplitude data
Frequency = double(1:TraceInfo.FullsweepTracePoints);
PowerSpec_dBm = single(1:TraceInfo.FullsweepTracePoints);

% Convert C types to Matlab types
Frequency_p = libpointer('doublePtr', Frequency);
PowerSpec_dBm_p = libpointer('singlePtr', PowerSpec_dBm);

% The full spectrum of this device is made up of multiple frames. This parameter is used to return the sequence number of the current frame in the concatenation process.
HopIndex = int32(0);
% Indicates the index of the current frame in all frames, used to identify the position of the current frame in all frames.
FrameIndex = int32(0);
% Create pointer HopIndex_p.
HopIndex_p = libpointer('int32Ptr', HopIndex);
% Create pointer FrameIndex_p.
FrameIndex_p = libpointer('int32Ptr', FrameIndex);

load(fullfile(filePath, 'MeasAuxInfo.mat'));   % Directly load MeasAuxInfo_TypeDef structure

% Get n times of SWP data
n = 10000; 
for t = 1:n
   for i = 1:TraceInfo.TotalHops 
        Status = calllib('htra_api', 'SWP_GetPartialSweep', Device, Frequency_p + (i-1) * TraceInfo.PartialsweepTracePoints, PowerSpec_dBm_p + (i-1) * TraceInfo.PartialsweepTracePoints, HopIndex_p, FrameIndex_p, MeasAuxInfo);     
        if Status ~= 0
            % If there is an error, print error message and close device
            fprintf('SWP_Configuration Call error Status = %d\n', Status);
            % Return 0, end function execution
            return;
        end
   end
    
    % Plot SWP spectrum
    plot(Frequency_p.Value, PowerSpec_dBm_p.Value);
    ylim([-130, SWP_ProfileOut.RefLevel_dBm]);
    xlim([min(Frequency_p.Value), max(Frequency_p.Value)]);
    pause(0.01);
end

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

clear all;

% Unload library
unloadlibrary('htra_api');   
disp('Uninstall complete')
