% 配置编译环境
% setenv('MW_MINGW64_LOC','D:\Apps\msys64\mingw64');
% 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'))   
    loadlibrary('.\htra_api\htra_api.dll','.\htra_api\htra_api.h'); %.dll和.h的文件路径一定要注意
end

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

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

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

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('The device is turned on 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

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

%定义RTA_ProfileIn指针和RTA_ProfileOut指针
RTA_ProfileIn = RTA_Profile;
RTA_ProfileOut = RTA_Profile;

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

%修改RTA_ProfileIn结构体的部分参数
RTA_ProfileIn.CenterFreq_Hz = 2.44e9;    %设置中心频率
RTA_ProfileIn.RefLevel_dBm = -30;       %设置参考电平
RTA_ProfileIn.DecimateFactor = 1;     %设置抽取倍数
RTA_ProfileIn.TriggerAcqTime = 0.1; %一次触发采集10us
RTA_ProfileIn.TriggerMode = 0;        % FixedPoints模式

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

%调用RTA_Configuration函数
Status = calllib('htra_api', 'RTA_Configuration', Device, RTA_ProfileIn, RTA_ProfileOut,RTA_FrameInfo);

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

% 直接加载RTA_PlotInfo结构体文件
load(fullfile(filePath, 'RTA_PlotInfo.mat'));  
% 直接加载TriggerInfo结构体文件
load(fullfile(filePath, 'TriggerInfo.mat'));  

% 直接加载MeasAuxInfo结构体文件
load(fullfile(filePath, 'MeasAuxInfo.mat'));  

%创建SpectrumStream，存放RTA的频谱数据
SpectrumStream = libpointer('uint8Ptr',1:RTA_FrameInfo.PacketValidPoints);
%Power = 1:RTA_FrameInfo.FrameWidth;

%计算频率轴
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
Freq = Freq';
        
%创建SpectrumBitmap，存放RTA的概率密度图
SpectrumBitmap = libpointer('uint16Ptr',1:RTA_FrameInfo.FrameHeight * RTA_FrameInfo.FrameWidth);

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

% 根据 TriggerOutMode 值决定调用 IQS_BusTriggerStart 的位置
if strcmp(RTA_ProfileOut.TriggerMode, 'Adaptive')
    % 当 TriggerOutMode == 1 时，先执行一次 IQS_BusTriggerStart
    Status = calllib('htra_api', 'RTA_BusTriggerStart', Device);
end

Power = single(zeros(RTA_FrameInfo.FrameWidth, RTA_FrameInfo.PacketFrame));

for t = 1:n
    % 如果 TriggerOutMode == 0，则每次循环时执行 IQS_BusTriggerStart
    if strcmp(RTA_ProfileOut.TriggerMode, 'FixedPoints')
        Status = calllib('htra_api', 'RTA_BusTriggerStart', Device);
    end

    for i=1:RTA_FrameInfo.PacketCount %当RTA_ProfileOut.TriggerMode=Adaptive时，RTA_FrameInfo.PacketCount = 1。
        Status = calllib('htra_api', 'RTA_GetRealTimeSpectrum', Device,SpectrumStream,SpectrumBitmap,RTA_PlotInfo, TriggerInfo, MeasAuxInfo);
        if Status ~= 0
            fprintf('RTA_GetRealTimeSpectrum Call error Status = %d\n', Status); % 如果调用出错，打印错误信息并关闭设备
            return; % 返回 0，结束函数执行
        end
        
        Power(:) = SpectrumStream.value(1:RTA_FrameInfo.FrameWidth * RTA_FrameInfo.PacketFrame); % 直接将 SpectrumStream.value 重新排列成一个 FrameWidth x PacketFrame 的矩阵
        Power = Power * RTA_PlotInfo.ScaleTodBm + RTA_PlotInfo.OffsetTodBm; % 使用 Scale 和 Offset

        time = 0:0.0667:2.4; % 假设时间轴是0到2.4秒，步长为 0.0667
        surf(time, Freq, Power, 'EdgeColor', 'none'); % 绘制 3D 表面图
        xlabel('Time(secs)');
        ylabel('Frequency(Hz)');
        zlabel('Power(dBm)');
        colorbar;
        colormap jet;  % 使用 Jet 色图
        view(45, 45);  % 调整视角

        % 设置色条范围
        caxis([-120, RTA_ProfileOut.RefLevel_dBm]);  % 设置颜色条的功率范围
        title('频谱分析');
        axis xy; axis tight; colormap(jet); 
        xlabel('时间(ms)');
        ylabel('频率(Hz)');
        pause(0.03);   
        
        % 预先创建图形对象
        h = surf(time, Freq, Power, 'EdgeColor', 'none');
        xlabel('Time(secs)');
        ylabel('Frequency(Hz)');
        zlabel('Power(dBm)');
        zlim([-120, RTA_ProfileOut.RefLevel_dBm]);  
        caxis([-120, RTA_ProfileOut.RefLevel_dBm]);
        colorbar;
        colormap jet;
        view(45, 45);  % 调整视角
        title('频谱分析');
        axis xy; axis tight;

        if i > 1
            offset = 0;
            for cnt = 1:RTA_FrameInfo.PacketFrame
                % 获取新的数据列，从 SpectrumStream.value 中读取偏移后的数据
                new_data = single(SpectrumStream.value(offset + 1:offset + RTA_FrameInfo.FrameWidth));  % 获取当前列数据
                new_data = new_data * RTA_PlotInfo.ScaleTodBm + RTA_PlotInfo.OffsetTodBm;
                
                % 将 new_data 插入到 Power 的末尾，同时删除第一列
                Power(:, 1:end-1) = Power(:, 2:end);  % 删除 Power 的第一列
                Power(:, end) = new_data;  % 将新数据列插入到 Power 的末尾

                % 更新偏移量，确保下次读取的数据正确
                offset = offset + RTA_FrameInfo.FrameWidth;  % 每次偏移 FrameWidth 个数据点
                pause(0.06);

                time = flip(0:0.0667:2.4);  % 假设时间轴是0到2.4秒，步长为 0.0667
                surf(time, Freq, Power, 'EdgeColor', 'none');  % 绘制 3D 表面图
                xlabel('Time(secs)');
                ylabel('Frequency(Hz)');
                zlabel('Power(dBm)');
                colorbar;
                colormap jet;  % 使用 Jet 色图
                view(45, 45);  % 调整视角

                % 设置色条范围
                zlim([-120, RTA_ProfileOut.RefLevel_dBm]); 
                caxis([-120, RTA_ProfileOut.RefLevel_dBm]);  % 设置颜色条的功率范围
                title('频谱分析');
                axis xy; axis tight;
                xlabel('时间(ms)');
                ylabel('频率(Hz)');
                pause(0.03);  % 控制显示间隔
            end
        else
            Power(:) = SpectrumStream.value(1:RTA_FrameInfo.FrameWidth * RTA_FrameInfo.PacketFrame); % 直接将 SpectrumStream.value 重新排列成一个 FrameWidth x PacketFrame 的矩阵
            Power = Power * RTA_PlotInfo.ScaleTodBm + RTA_PlotInfo.OffsetTodBm; % 使用 Scale 和 Offset

            time = flip(0:0.0667:2.4); % 假设时间轴是0到2.4秒，步长为 0.0667
            surf(time, Freq, Power, 'EdgeColor', 'none'); % 绘制 3D 表面图
            xlabel('Time(secs)');
            ylabel('Frequency(Hz)');
            zlabel('Power(dBm)');
            zlim([-120, RTA_ProfileOut.RefLevel_dBm]);  % 设置 z 轴范围
            colorbar;
            colormap jet;  % 使用 Jet 色图
            view(45, 45);  % 调整视角

            % 设置色条范围
            caxis([-120, RTA_ProfileOut.RefLevel_dBm]);  % 设置颜色条的功率范围
            caxis([-120, RTA_ProfileOut.RefLevel_dBm]);  % 设置颜色条的功率范围
            title('频谱分析');
            axis xy; axis tight; colormap(jet); 
            xlabel('时间(ms)');
            ylabel('频率(Hz)');
            pause(0.001);   
        end
    end
        
    %画出RTA的频谱图
    plot(Freq,Power);  
    ylim([-130, RTA_ProfileOut.RefLevel_dBm]);
    xlim([min(Freq), max(Freq)]);
    pause(0.03);
end

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

clear all;

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