% % 配置编译环境
% % setenv('MW_MINGW64_LOC','D:\msys64\ucrt64');
% % mex -setup C++
% 
% filePath = fullfile(pwd, 'htra_api_mat');  
% 
% % 检查文件夹是否存在，如果不存在，创建文件夹
% if ~exist(filePath, 'dir')
%     run('htra_api.m');
%     filePath = fullfile(pwd, 'htra_api_mat');  
% end
% 
% % 加载htra_api.dll
% if not(libisloaded('htra_api.dll'))   
%     try
%         % 尝试加载动态链接库及其头文件
%         loadlibrary('.\htra_api\htra_api.dll','.\htra_api\htra_api.h'); 
%     catch ME
%         %  捕获加载过程中可能出现的错误，ME 是一个 MException 对象，包含了错误的详细信息
%         fprintf('Failed to load htra_api.dll or htra_api.h: %s\n', ME.message);
%         
%         % 结束程序，请检查此.m文件同级目录下的htra_api文件夹中是否有htra_api.dll 或 htra_api.h文件
%         %若不存在这两个文件，请将随寄资料\Windows\HTRA_API\x64\htra_api中的htra_api.dll 或htra_api.h文件，拷贝至.m文件同级目录下的htra_api文件夹中。
%         fprintf('The program will end, please check whether the file path and file exist.\n');
%         
%         return;
%         % 结束当前函数或脚本的执行
%     end
% end
% 
% %查看API中的所有函数
% libfunctions('htra_api'); 
% 
% %打开设备
% Device = libpointer; %创建Device指针
% DevNum = 0;
% Status = 0;
% 
% % 直接加载BootProfile_TypeDef结构体
% load(fullfile(filePath, 'BootProfile.mat'));  
% % 直接加载BootInfo_TypeDef结构体
% load(fullfile(filePath, 'BootInfo.mat'));  
% 
% IS_USB = 1;  % 默认为 USB 设备，如果使用网口型设备则设置为 0
% 
% if IS_USB == 1
%     % 配置 USB 接口
%     BootProfile.PhysicalInterface = 0;
% else
%     % 配置 ETH 接口
%     BootProfile.PhysicalInterface = 3;
%     BootProfile.ETH_IPVersion = 0;
%     BootProfile.ETH_RemotePort = 5000;
%     BootProfile.ETH_ReadTimeOut = 5000;
%     BootProfile.ETH_IPAddress = [192, 168, 1, 100];
% end
% 
% %调用Device_Open函数
% Status = calllib('htra_api', 'Device_Open', Device, DevNum, BootProfile, BootInfo);
% 
% if Status == 0
%     get(BootProfile);%打印BootInfo的值
%     get(BootInfo);%打印BootInfo的值    
%     fprintf('Device successfully\n');
% else
%     % 设备打开失败，根据不同的错误状态进行处理
%     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 ;
% end
% 
% % 直接加载 IQS_Profile_TypeDef结构体
% load(fullfile(filePath, 'IQS_Profile.mat')); 
% 
% %定义IQS_ProfileIn指针和IQS_ProfileOut指针
% IQS_ProfileIn = IQS_Profile;
% IQS_ProfileOut = IQS_Profile;
% 
% %调用IQS_ProfileDeInit函数
% Status = calllib('htra_api', 'IQS_ProfileDeInit', Device, IQS_ProfileIn);
% get(IQS_ProfileIn); %打印IQS_ProfileIn的值
% 
% %修改IQS_ProfileIn结构体的部分参数
% IQS_ProfileIn.CenterFreq_Hz = 1e9;   %配置中心频率
% IQS_ProfileIn.RefLevel_dBm = 0;      %配置参考电平
% IQS_ProfileIn.DecimateFactor = 2;    %配置抽取倍数
% IQS_ProfileIn.TriggerMode= 0;         %配置触发模式。（0为FixedPoints模式，1为Adaptive模式）
% IQS_ProfileIn.TriggerLength = 163840; %配置单次触发采集的点数
% 
%  %直接加载IQS_StreamInfo_TypeDef结构体
% load(fullfile(filePath, 'IQS_StreamInfo.mat'));  
% 
% %调用IQS_Configuration函数
% Status = calllib('htra_api', 'IQS_Configuration', Device, IQS_ProfileIn, IQS_ProfileOut,IQS_StreamInfo);
% 
% % 如果配置下发成功（Status == 0）
% if Status == 0
%     get(IQS_ProfileOut); %打印IQS_ProfileOut的值
%     get(IQS_StreamInfo); %打印StreamInfo的值
%     fprintf('Configuration successfully\n');
% else
%     % 如果调用出错，打印错误信息并关闭设备
%     fprintf('IQS_Configuration Call error Status = %d\n', Status);
%     
%     % 关闭设备的函数（Device_Close）。
%     Device_Close(Device); 
%     
%     % 返回 0，结束函数执行
%     return;
% end
% 
% %直接加载 IQS_TriggerInfo_TypeDef 结构体 
% load(fullfile(filePath, 'TriggerInfo.mat'));  
% %直接加载 MeasAuxInfo_TypeDef 结构体 
% load(fullfile(filePath, 'MeasAuxInfo.mat')); 
% 
% IQ_data = int16(1:IQS_StreamInfo.PacketSamples * 2);
% 
% % 交织分布的IQ时域数据，单路可能为i8 i16 i32 格式
% AlternIQStream=libpointer('int16Ptr',IQ_data);
% 
% % int类型至电压绝对值（V）的系数
% ScaleToV = single(0);                                           
% ScaleToV_p=libpointer('singlePtr',ScaleToV);
% 
% %创建 I 和 Q 数组分别存储 I 和 Q 数据
% I_data = 1:IQS_StreamInfo.StreamSamples;
% Q_data = 1:IQS_StreamInfo.StreamSamples;
% 
% % 获取n次IQ数据
% n = 10000;
% 
% % 根据 TriggerMode 值决定调用 IQS_BusTriggerStart 的位置以及数组空间开放大小
% if strcmp(IQS_ProfileOut.TriggerMode, 'Adaptive')
%     % 当 TriggerMode == Adaptive 时，先执行一次 IQS_BusTriggerStart
%     Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
%     I_data = 1:IQS_StreamInfo.PacketSamples;
%     Q_data = 1:IQS_StreamInfo.PacketSamples;
% end
% 
% for j = 1:n
%     if strcmp(IQS_ProfileOut.TriggerMode, 'FixedPoints')
%         Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
%     end
%     for i = 1:IQS_StreamInfo.PacketCount
% 
%         if Status == 0
%             Status = calllib('htra_api', 'IQS_GetIQStream', Device, AlternIQStream, ScaleToV_p, TriggerInfo, MeasAuxInfo);
%             % 确定当前包的有效点数,最后一包点数的处理
%             if i == IQS_StreamInfo.PacketCount && ...
%                mod(IQS_StreamInfo.StreamSamples, IQS_StreamInfo.PacketSamples) ~= 0 && ...
%                strcmp(IQS_ProfileOut.TriggerMode, 'FixedPoints')
%                 Points = mod(IQS_StreamInfo.StreamSamples, IQS_StreamInfo.PacketSamples);
%             else
%                 Points = IQS_StreamInfo.PacketSamples;
%             end
% 
%             % 提取当前数据包并转换
%             currentIQ = double(AlternIQStream.Value(1:2*Points)) * ScaleToV_p.Value;
% 
%             % 计算存储偏移量（MATLAB索引从1开始）
%             offset = (i-1) * IQS_StreamInfo.PacketSamples;
% 
%             % 分离I/Q并存入数组
%             I_Data(offset+1 : offset+Points) = currentIQ(1:2:end);
%             Q_Data(offset+1 : offset+Points) = currentIQ(2:2:end);
%         else
%             fprintf('IQS_GetIQStream Call error Status = %d\n', Status);
%             return;
%         end
%     end
%      
%     % 动态绘制累积数据
%     currentEnd = offset + Points;
%     plot(1:currentEnd, I_Data(1:currentEnd), 1:currentEnd, Q_Data(1:currentEnd));
% 
%     % 动态调整坐标轴
%     currentY = [I_Data(1:currentEnd), Q_Data(1:currentEnd)];
% %     yMin = min(double(AlternIQStream.Value(1:2*Points))* ScaleToV_p.Value) - 0.001;
% %     yMax = max(double(AlternIQStream.Value(1:2*Points))* ScaleToV_p.Value) + 0.001;
%     yMin = min(currentIQ) - 0.001;
%     yMax = max(currentIQ) + 0.001;
%     axis([0 currentEnd yMin yMax]);
% 
%     pause(0.01);
%     
% end
% 
% %调用 IQS_BusTriggerStop 函数
% Status = calllib('htra_api', 'IQS_BusTriggerStop', Device);
% 
% %调用Device_Close函数
% Status = calllib('htra_api', 'Device_Close', Device);
% 
% clear all;
% %卸载库文件
% unloadlibrary('htra_api');   
% disp('Uninstall complete')
% 
% 
% 
% 

% 配置编译环境
% setenv('MW_MINGW64_LOC','D:\msys64\ucrt64');
% mex -setup C++

filePath = fullfile(pwd, 'htra_api_mat');  

% 检查文件夹是否存在，如果不存在，创建文件夹
if ~exist(filePath, 'dir')
    run('htra_api.m');
    filePath = fullfile(pwd, 'htra_api_mat');  
end

% 加载htra_api.dll
if not(libisloaded('htra_api.dll'))   
    try
        % 尝试加载动态链接库及其头文件
        loadlibrary('.\htra_api\htra_api.dll','.\htra_api\htra_api.h'); 
    catch ME
        %  捕获加载过程中可能出现的错误，ME 是一个 MException 对象，包含了错误的详细信息
        fprintf('Failed to load htra_api.dll or htra_api.h: %s\n', ME.message);
        
        % 结束程序，请检查此.m文件同级目录下的htra_api文件夹中是否有htra_api.dll 或 htra_api.h文件
        %若不存在这两个文件，请将随寄资料\Windows\HTRA_API\x64\htra_api中的htra_api.dll 或htra_api.h文件，拷贝至.m文件同级目录下的htra_api文件夹中。
        fprintf('The program will end, please check whether the file path and file exist.\n');
        
        return;
        % 结束当前函数或脚本的执行
    end
end

%查看API中的所有函数
libfunctions('htra_api'); 

%打开设备
Device = libpointer; %创建Device指针
DevNum = 0;
Status = 0;

% 直接加载BootProfile_TypeDef结构体
load(fullfile(filePath, 'BootProfile.mat'));  
% 直接加载BootInfo_TypeDef结构体
load(fullfile(filePath, 'BootInfo.mat'));  

IS_USB = 1;  % 默认为 USB 设备，如果使用网口型设备则设置为 0

if IS_USB == 1
    % 配置 USB 接口
    BootProfile.PhysicalInterface = 0;
else
    % 配置 ETH 接口
    BootProfile.PhysicalInterface = 3;
    BootProfile.ETH_IPVersion = 0;
    BootProfile.ETH_RemotePort = 5000;
    BootProfile.ETH_ReadTimeOut = 5000;
    BootProfile.ETH_IPAddress = [192, 168, 1, 100];
end

%调用Device_Open函数
Status = calllib('htra_api', 'Device_Open', Device, DevNum, BootProfile, BootInfo);

if Status == 0
    get(BootProfile);%打印BootInfo的值
    get(BootInfo);%打印BootInfo的值    
    fprintf('Device successfully\n');
else
    % 设备打开失败，根据不同的错误状态进行处理
    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 ;
end

% 直接加载 IQS_Profile_TypeDef结构体
load(fullfile(filePath, 'IQS_Profile.mat')); 

%定义IQS_ProfileIn指针和IQS_ProfileOut指针
IQS_ProfileIn = IQS_Profile;
IQS_ProfileOut = IQS_Profile;

%调用IQS_ProfileDeInit函数
Status = calllib('htra_api', 'IQS_ProfileDeInit', Device, IQS_ProfileIn);
get(IQS_ProfileIn); %打印IQS_ProfileIn的值

%修改IQS_ProfileIn结构体的部分参数
IQS_ProfileIn.CenterFreq_Hz = 1e9;   %配置中心频率
IQS_ProfileIn.RefLevel_dBm = 0;      %配置参考电平
IQS_ProfileIn.DecimateFactor = 2;    %配置抽取倍数
IQS_ProfileIn.TriggerMode= 0;         %配置触发模式。
IQS_ProfileIn.TriggerLength = 16384; %配置单次触发采集的点数

 %直接加载IQS_StreamInfo_TypeDef结构体
load(fullfile(filePath, 'IQS_StreamInfo.mat'));  

%调用IQS_Configuration函数
Status = calllib('htra_api', 'IQS_Configuration', Device, IQS_ProfileIn, IQS_ProfileOut,IQS_StreamInfo);

% 如果配置下发成功（Status == 0）
if Status == 0
    get(IQS_ProfileOut); %打印IQS_ProfileOut的值
    get(IQS_StreamInfo); %打印StreamInfo的值
    fprintf('Configuration successfully\n');
else
    % 如果调用出错，打印错误信息并关闭设备
    fprintf('IQS_Configuration Call error Status = %d\n', Status);
    
    % 关闭设备的函数（Device_Close）。
    Device_Close(Device); 
    
    % 返回 0，结束函数执行
    return;
end

%直接加载 IQS_TriggerInfo_TypeDef 结构体 
load(fullfile(filePath, 'TriggerInfo.mat'));  
%直接加载 MeasAuxInfo_TypeDef 结构体 
load(fullfile(filePath, 'MeasAuxInfo.mat')); 

IQ_data = int16(1:IQS_StreamInfo.PacketSamples * 2);

% 交织分布的IQ时域数据，单路可能为i8 i16 i32 格式
AlternIQStream=libpointer('int16Ptr',IQ_data);

% int类型至电压绝对值（V）的系数
ScaleToV = single(0);                                           
ScaleToV_p=libpointer('singlePtr',ScaleToV);

%创建 I 和 Q 数组分别存储 I 和 Q 数据
I_data = 1:IQS_StreamInfo.StreamSamples;
Q_data = 1:IQS_StreamInfo.StreamSamples;

% 获取n次IQ数据
n = 10000;

% 根据 TriggerMode 值决定调用 IQS_BusTriggerStart 的位置以及数组空间开放大小
if strcmp(IQS_ProfileOut.TriggerMode, 'Adaptive')
    % 当 TriggerMode == Adaptive 时，先执行一次 IQS_BusTriggerStart
    Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
    I_data = 1:IQS_StreamInfo.PacketSamples;
    Q_data = 1:IQS_StreamInfo.PacketSamples;
end

for j = 1:n
    if strcmp(IQS_ProfileOut.TriggerMode, 'FixedPoints')
        Status = calllib('htra_api', 'IQS_BusTriggerStart', Device);
    end
    for i = 1:IQS_StreamInfo.PacketCount

        if Status == 0
            Status = calllib('htra_api', 'IQS_GetIQStream', Device, AlternIQStream, ScaleToV_p, TriggerInfo, MeasAuxInfo);
            % 确定当前包的有效点数,最后一包点数的处理
            if i == IQS_StreamInfo.PacketCount && ...
               mod(IQS_StreamInfo.StreamSamples, IQS_StreamInfo.PacketSamples) ~= 0 && ...
               strcmp(IQS_ProfileOut.TriggerMode, 'FixedPoints')
                Points = mod(IQS_StreamInfo.StreamSamples, IQS_StreamInfo.PacketSamples);
            else
                Points = IQS_StreamInfo.PacketSamples;
            end

            % 计算存储偏移量（MATLAB索引从1开始）
            offset = (i-1) * IQS_StreamInfo.PacketSamples;
            % 提取当前数据包并转换
            currentIQ = double(AlternIQStream.Value(1:2*Points)) * ScaleToV_p.Value;

            % 分离I/Q并存入数组
            I_Data(offset+1 : offset+Points) = currentIQ(1:2:end);
            Q_Data(offset+1 : offset+Points) = currentIQ(2:2:end);
           
        else
            fprintf('IQS_GetIQStream Call error Status = %d\n', Status);
            return;
        end
    end
       
    % 动态绘制累积数据
    currentEnd = offset + Points;
    plot(1:currentEnd, I_Data(1:currentEnd), 1:currentEnd, Q_Data(1:currentEnd));

    % 动态调整坐标轴
    currentY = [I_Data(1:currentEnd), Q_Data(1:currentEnd)];
    yMin = min(currentY);
    yMax = max(currentY);
    axis([0 currentEnd yMin yMax]);

    pause(0.01);
    
end

%调用 IQS_BusTriggerStop 函数
Status = calllib('htra_api', 'IQS_BusTriggerStop', Device);

%调用Device_Close函数
Status = calllib('htra_api', 'Device_Close', Device);

clear all;
%卸载库文件
unloadlibrary('htra_api');   
disp('Uninstall complete')






 
