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

filePath = fullfile(pwd, 'htra_api_mat');  

% Check whether the folder exists. If it does not exist, 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'); % Pay attention to the file paths of the .dll and .h files.
end

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

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

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

IS_USB = 1;  % USB device by default. Set this value to 0 if a network-port device is used.

if IS_USB == 1
    % Configure the USB interface.
    BootProfile.PhysicalInterface = 0;
else
    % Configure the 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 the Device_Open function.
Status = calllib('htra_api', 'Device_Open', Device, DevNum, BootProfile, BootInfo);

if Status == 0
    get(BootProfile); % Print the value of BootProfile.
    get(BootInfo);    % Print the value of BootInfo.
    fprintf('Device successfully\n');
else
    % Device opening failed. Handle different error status values.
    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 the error status value.
    return;
end

load(fullfile(filePath, 'DET_Profile.mat'));  % Directly load the DET_Profile_TypeDef structure.

% Define the DET_ProfileIn pointer and DET_ProfileOut pointer.
DET_ProfileIn = DET_Profile;
DET_ProfileOut = DET_Profile;

% Call the DET_ProfileDeInit function.
Status = calllib('htra_api', 'DET_ProfileDeInit', Device, DET_ProfileIn);
get(DET_ProfileIn); % Print the value of DET_ProfileIn.

DET_ProfileIn.CenterFreq_Hz = 1e9;   % Configure the center frequency.
DET_ProfileIn.RefLevel_dBm = 0;      % Configure the reference level.
DET_ProfileIn.DecimateFactor = 2;    % Configure the decimation factor.
DET_ProfileIn.TriggerLength = 16242; % Configure the number of points collected in a single trigger. This is valid only when TriggerMode is set to FixedPoints.

load(fullfile(filePath, 'DET_StreamInfo.mat'));    % Directly load the DET_StreamInfo_TypeDef structure.

% Call the DET_Configuration function.
Status = calllib('htra_api', 'DET_Configuration', Device, DET_ProfileIn, DET_ProfileOut, DET_StreamInfo);

% If the configuration is successfully applied (Status == 0)
if Status == 0
    get(DET_ProfileOut); % Print the value of DET_ProfileOut.
    get(DET_StreamInfo); % Print the value of StreamInfo.
    fprintf('Configuration successfully\n');
else
    % If the call fails, print the error message and close the device.
    fprintf('DET_Configuration Call error Status = %d\n', Status);
    
    % Device close function (Device_Close).
    Device_Close(Device);  
    
    % Return 0 and terminate the function execution.
    return;
end

load(fullfile(filePath, 'TriggerInfo.mat')); % Directly load the IQS_TriggerInfo_TypeDef structure.

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

% Create NormalizedPowerStream to store DET data.
NormalizedPowerStream = 1:DET_StreamInfo.StreamSamples;
NormalizedPowerStream_p = libpointer('singlePtr', NormalizedPowerStream);
disp(DET_StreamInfo.StreamSamples);

% This parameter is the scale factor of the absolute amplitude in volts.
ScaleToV = single(0);                                           
ScaleToV_p = libpointer('singlePtr', ScaleToV);

% Acquire IQ data n times.
n = 10000;

% When TriggerMode == Adaptive, execute DET_BusTriggerStart once first.
if strcmp(DET_ProfileOut.TriggerMode, 'Adaptive')
    Status = calllib('htra_api', 'DET_BusTriggerStart', Device);
end

for j = 1:n
    % If TriggerMode == FixedPoints, execute DET_BusTriggerStart in each loop.
    if strcmp(DET_ProfileOut.TriggerMode, 'FixedPoints')
        Status = calllib('htra_api', 'DET_BusTriggerStart', Device);
    end

    for i = 1:DET_StreamInfo.PacketCount
        Status = calllib('htra_api', 'DET_GetPowerStream', Device, NormalizedPowerStream_p, ScaleToV_p, TriggerInfo, MeasAuxInfo);
        if Status ~= 0
            % If the call fails, print the error message and close the device.
            fprintf('DET_GetPowerStream Call error Status = %d\n', Status);

            % Return 0 and terminate the function execution.
            return;
        end
    end 

    % Convert the unit of DET data to dBm.
    for i = 1:DET_StreamInfo.StreamSamples
        NormalizedPowerStream(i) = 10 * log10(20 * power(NormalizedPowerStream_p.Value(i) * ScaleToV_p.Value, 2));
    end

    % Plot the DET spectrum.
    plot(1:DET_StreamInfo.StreamSamples, NormalizedPowerStream);
    ylim([-130, DET_ProfileOut.RefLevel_dBm]);
    xlim([0, DET_StreamInfo.StreamSamples]);
    pause(0.01);
end

% Call the DET_BusTriggerStop function.
Status = calllib('htra_api', 'DET_BusTriggerStop', Device);

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

clear all;

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