% 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, if not, create it
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 paths to .dll and .h files are correct
end

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

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

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

IS_USB = 1;  % Default is USB device. If using Ethernet device, set to 0

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 the value of BootInfo
    get(BootInfo); % Print the value of BootInfo    
    fprintf('Device successfully\n');
else
    % If opening the device failed, handle based on different error statuses
    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
    return ;
end

load(fullfile(filePath, 'RTA_Profile.mat'));  % Directly load RTA_Profile_TypeDef struct

% Define pointers for RTA_ProfileIn and RTA_ProfileOut
RTA_ProfileIn = RTA_Profile;
RTA_ProfileOut = RTA_Profile;

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

% Modify some parameters of RTA_ProfileIn structure
RTA_ProfileIn.CenterFreq_Hz = 1e9;    % Set center frequency
RTA_ProfileIn.RefLevel_dBm = 0;       % Set reference level
RTA_ProfileIn.DecimateFactor = 1;     % Set decimation factor
RTA_ProfileIn.TriggerAcqTime = 10e-6; % Set trigger acquisition time to 10us
RTA_ProfileIn.TriggerMode = 0;        % FixedPoints mode

load(fullfile(filePath, 'RTA_FrameInfo.mat'));  % Directly load RTA_FrameInfo_TypeDef struct

% Call RTA_Configuration function
Status = calllib('htra_api', 'RTA_Configuration', Device, RTA_ProfileIn, RTA_ProfileOut,RTA_FrameInfo);

% If configuration is successfully sent (Status == 0)
if Status == 0
    get(RTA_FrameInfo); % Print RTA_FrameInfo
    fprintf('Configuration successfully\n');
else
    % If error occurred, print error and close device
    fprintf('RTA_Configuration Call error Status = %d\n', Status);
    Device_Close(Device);
    
    % Return 0 to end function execution
    return;
end

% Directly load RTA_PlotInfo struct file
load(fullfile(filePath, 'RTA_PlotInfo.mat'));  
% Directly load TriggerInfo struct file
load(fullfile(filePath, 'TriggerInfo.mat'));  

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

% Create SpectrumStream to store RTA spectrum data
SpectrumStream = libpointer('uint8Ptr',1:RTA_FrameInfo.PacketValidPoints);
Power = 1:RTA_FrameInfo.FrameWidth;

% Calculate frequency axis
Freq = 1:RTA_FrameInfo.FrameWidth;
FreqStep = (RTA_FrameInfo.StopFrequency_Hz - RTA_FrameInfo.StartFrequency_Hz)/(RTA_FrameInfo.FrameWidth - 1);
for i=1:RTA_FrameInfo.FrameWidth   
    Freq(i) =  RTA_FrameInfo.StartFrequency_Hz + FreqStep * i;
end

% Create SpectrumBitmap to store RTA probability density image
SpectrumBitmap = libpointer('uint16Ptr',1:RTA_FrameInfo.FrameHeight * RTA_FrameInfo.FrameWidth);

% Acquire IQ data n times
n = 10000;

% Decide when to call RTA_BusTriggerStart based on TriggerMode
if strcmp(RTA_ProfileOut.TriggerMode, 'Adaptive')
    % If TriggerMode == Adaptive, call RTA_BusTriggerStart once before the loop
    Status = calllib('htra_api', 'RTA_BusTriggerStart', Device);
end

for t = 1:n
    % If TriggerMode == FixedPoints, call RTA_BusTriggerStart every loop
    if strcmp(RTA_ProfileOut.TriggerMode, 'FixedPoints')
        Status = calllib('htra_api', 'RTA_BusTriggerStart', Device);
    end

    for i=1:RTA_FrameInfo.PacketCount % When TriggerMode = Adaptive, PacketCount = 1
        Status = calllib('htra_api', 'RTA_GetRealTimeSpectrum', Device,SpectrumStream,SpectrumBitmap,RTA_PlotInfo, TriggerInfo, MeasAuxInfo);
        if Status ~= 0
            % If error occurred, print error and stop execution
            fprintf('RTA_GetRealTimeSpectrum Call error Status = %d\n', Status);
            return;
        end
    end
    
    % Keep only the first frame of spectrum
    for j=1:RTA_FrameInfo.FrameWidth   
        Power(j) = single(SpectrumStream.value(j)) * RTA_PlotInfo.ScaleTodBm + RTA_PlotInfo.OffsetTodBm; 
    end
    
    % Plot RTA spectrum
    plot(Freq,Power);  
    ylim([-130, RTA_ProfileOut.RefLevel_dBm]);
    xlim([min(Freq), max(Freq)]);
    pause(0.03);
end

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

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

clear all;

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