% 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

% Directly load the GNSSInfo_TypeDef structure.
load(fullfile(filePath, 'GNSSInfo.mat'));  

GNSSInfo.GNSS_LockState = 0;
GNSSInfo.GNSSAntennaState = 0;

Status = calllib('htra_api', 'Device_SetGNSSAntennaState', Device, GNSSInfo.GNSSAntennaState);

while ~GNSSInfo.GNSS_LockState
    % Get real-time GNSS information.
    Status = calllib('htra_api', 'Device_GetGNSSInfo_Realtime', Device, GNSSInfo);
    disp(['GNSS_LockState: ', num2str(GNSSInfo.GNSS_LockState)]);
    pause(1);  
end

get(GNSSInfo); % Print the value of GNSSInfo.

% BootInfo.DeviceInfo.HardwareVersion is the hardware version number.
HardwareVersion = BootInfo.DeviceInfo.HardwareVersion;

% Extract the value of OCXO_Enable.
OCXO_Enable = bitand(bitshift(HardwareVersion, -10), 3);

% Set the DOCXO work mode to disciplining mode.
% This setting takes effect only after the antenna is locked.
GNSSInfo.DOCXO_WorkMode = 0;

% Check whether OCXO is enabled.
if OCXO_Enable 
    % Set the DOCXO work mode in GNSS.
    Status = calllib('htra_api', 'Device_SetDOCXOWorkMode', Device, GNSSInfo.DOCXO_WorkMode);

    % Get the current time.
    startTime = tic;  % Start timing.

    % If DOCXO is already locked.
    if GNSSInfo.DOCXO_LockState == 1
       disp(['GNSS_LockState: ', num2str(int16(GNSSInfo.GNSS_LockState))]);
       disp(['DOCXO_LockState: ', num2str(int16(GNSSInfo.DOCXO_LockState))]);
    else
        while 1
            % Get the DOCXO work state in GNSS.
            Status = calllib('htra_api', 'Device_GetGNSSInfo_Realtime', Device, GNSSInfo);

            % Check the lock state.
            if GNSSInfo.DOCXO_LockState == 1 && GNSSInfo.GNSS_LockState == 1
                disp(['GNSS_LockState: ', num2str(int16(GNSSInfo.GNSS_LockState))]);
                disp(['DOCXO_LockState: ', num2str(int16(GNSSInfo.DOCXO_LockState))]);
                break;
            end

            if GNSSInfo.GNSS_LockState == 0
                GNSSInfo.DOCXO_WorkMode = 1;

                % Set the DOCXO work mode in GNSS.
                Status = calllib('htra_api', 'Device_SetDOCXOWorkMode', Device, GNSSInfo.DOCXO_WorkMode);
            end

            disp(['GNSS_LockState: ', num2str(int16(GNSSInfo.GNSS_LockState))]);

            % Print the current state.
            disp(['DOCXO_LockState: ', num2str(int16(GNSSInfo.DOCXO_LockState))]);

            % Check timeout: whether it exceeds 600 seconds.
            elapsedTime = toc(startTime);  % Get the elapsed time.
            if elapsedTime > 600
                disp('The DOCXO is not locked, please check whether the cable connection is normal.');
                break;
            end

            pause(1);  % Delay for 1 second.
        end
    end
end

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

clear all;

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