clear; close all; clc; %% LabVIEW界面参数配置-发送模式-界面选择部分 cfgUI.ChannelBandwidth = 'CBW20'; % 下拉选择:'CBW20''CBW40''CBW80' cfgUI.NTX2_enabled = 1; % 与第三方硬件连接 max_run_time = 60; %最大允许的等待时间 SEED = 1; cfgUI.numUsers = 1; % 当前版本用户数量,1-2 cfgUI.DataType = 'test'; % 下拉选择:'test''text''photo'image.png numPkt = 5; %时隙内包的数量,当前版本1~5 pktLength = 1001; % 包长度设定下拉选择(short,medium,long)对应几个数字1001,7007,12012,赋值给APEPLength if strcmp(cfgUI.DataType,'photo') txPSDUByte = imread('image.png'); I_gray = im2gray(txPSDUByte); [len,width] = size(I_gray); binary = dec2bin(I_gray(:),8); bitstream = reshape(binary',1,[]);%将二进制数连接起来形成比特流 byte_array = reshape(bitstream',8,[])';%将比特流转换为字节流 txPSDUByte = bin2dec(byte_array); % 包长度与包个数自适应判断 zjd3.26 if numPkt*pktLength >= length(txPSDUByte) % 如果当前包长度在5个包内能传输当前数据量 for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据 if pktNum*pktLength >= length(txPSDUByte) numPkt = pktNum; break end end else % 当前包长度不能在5个包内能传输当前数据量,自动调整 if numPkt*7007 >= length(txPSDUByte) for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据 if pktNum*7007 >= length(txPSDUByte) numPkt = pktNum; pktLength = 7007; break end end else for pktNum = 1:numPkt % 判断当前包长度下最少用几个包传数据 if pktNum*12012 >= length(txPSDUByte) numPkt = pktNum; pktLength = 12012; break end end end end txPSDUByteUser = zeros(len*width+3,cfgUI.numUsers); % 将图片分给两个用户 for i = 1:cfgUI.numUsers byteLen = length(txPSDUByte); byteLenBit = int2bit(byteLen,16); Len1 = bit2int(byteLenBit(1:8),8); Len2 = bit2int(byteLenBit(9:16),8); txPSDUByteUser(1:len*width+2,i) = [Len1;Len2;txPSDUByte]; txPSDUByteUser(end,i) = mod(sum(txPSDUByteUser(:,i)),256); end txPSDUByteUser = uint8(txPSDUByteUser); save('TXPackets\txPSDUByteUser.mat','txPSDUByteUser'); elseif strcmp(cfgUI.DataType,'text') else txPSDUByteUser = 0; end cfgUI.UserMode = 'SU'; % 使用模式下拉选择:'MU','SU',SU情况下只有单用户、可扩展40MHz、STBC等,MU模式可以对单用户进行资源分配(lxr) cfgUI.FeedbackMode = 'openloop'; % 下拉选择: 'openloop','feedback',对应菜单栏的‘手动’和‘智能’ SoundingMode = 0; % 环境感知模式,作为一个按钮 cfgUI.numTx = 1; % 发射天线数,当前版本1~2 cfgUI.numRx = 1; % 接收天线数,当前版本1~2 cfgUI.AI.PAPR = 'PAPR'; % 下拉选择:'default','PAPR-Net' cfgUI.PhySecur = 'default'; % 下拉选择:'无','CP随机化','信道密钥' %----------------以下是可以手动配置的部分--------------------- %---资源矩阵部分 cfgUI.user1.s = 1; cfgUI.user1.f = [1,1,1,1]; % 显示为4个方格,可用则为黑色为1,不可用则为白色为0 cfgUI.user1.t = ones(1,numPkt); % 显示为numPkt个方格,可用则为黑色为1,不可用则为白色为0 cfgUI.user1.p = 0.5; % cfgUI.user2.s = 1; cfgUI.user2.f = [1,1,1,1]; cfgUI.user2.t = ones(1,numPkt); cfgUI.user2.p = 0.5; %---波形参数部分---user1 cfgUI.user1.ChannelCode = 'LDPC'; % 下拉选择编码方式:BCC or LDPC cfgUI.user1.CodeRate = 3/4; % 编码码率下拉选择:1/2 or 2/3 or 3/4 or 5/6 cfgUI.user1.CodeLengt = 1600; % 编码码长:200*8=1600,800 cfgUI.user1.InterWeaveMode = 'random'; % 交织方式下拉选择:random,horizontal cfgUI.user1.InterWeaveDepth = 1024; % 交织深度:2048,1024 cfgUI.user1.ScrambleLength = 6; % 扰码长度:32 cfgUI.user1.CPLength = '1/4'; % CP长度下拉选择:1/16 or 1/8 or 1/4 cfgUI.user1.FFTSize = 256; % FFT尺寸:128 or 256 or 512 cfgUI.user1.NumSubcarrier = 242; % 子载波数:128 or 256 or 512 cfgUI.user1.ModulationMode = '16QAM'; % 调制方式下拉选择:4QAM or 8QAM or 16QAM or 32QAM or 64QAM cfgUI.user1.MultiAntennaMode = 'STBC'; % 多天线方式下拉选择:'ZF-BF','MMSE-BF', SU模式下才能使用STBC'STBC' cfgUI.user1.SpatialMapping = 'Hadamard'; % 空间映射方式下拉选择:'Direct','Hadamard','Fourier','Custom'----------zjd 3.21修改 cfgUI.user1.APEPlength = pktLength; % 包长度设定下拉选择(short,medium,long)对应几个数字1001,7007,12012 cfgUI.user1.pilotInterval = 5; %---波形参数部分---user2 cfgUI.user2.ChannelCode = 'LDPC'; % 编码方式:BCC or LDPC cfgUI.user2.CodeRate = 3/4; % 编码码率:1/2 or 2/3 or 3/4 or 5/6 cfgUI.user2.CodeLengt = 1600; % 编码码长:200*8=1600,800 cfgUI.user2.InterWeaveMode = 'random'; % 交织方式:random,horizontal cfgUI.user2.InterWeaveDepth = 1024; % 交织深度:2048,1024 cfgUI.user2.ScrambleLength = 6; % 扰码长度:32 cfgUI.user2.CPLength = '1/4'; % CP长度:1/16 or 1/8 or 1/4 cfgUI.user2.FFTSize = 256; % FFT尺寸:128 or 256 or 512 cfgUI.user2.NumSubcarrier = 242; % 子载波数:128 or 256 or 512 cfgUI.user2.ModulationMode = '16QAM'; % 调制方式:4QAM or 8QAM or 16QAM or 32QAM or 64QAM cfgUI.user2.MultiAntennaMode = 'ZF-BF'; % 多天线方式:'ZF-BF','MMSE-BF','STBC' cfgUI.user2.SpatialMapping = 'Direct'; % 空间映射方式:'Direct','Hadamard','Fourier' cfgUI.user2.APEPlength = pktLength; % 包长度设定 cfgUI.user2.pilotInterval = 5; %% TX运行 if SoundingMode %%% 判断TX工作状态 tic; feedback_stat = false; while feedback_stat==false && toc < max_run_time % 没接收到反馈或者超过最大等待时间 txNDP = channelSounding(cfgUI); % 开始发送探测和NDP序列 tx_data = txNDP; save('TXPackets\transmit_data.mat','tx_data','cfgUI');% 发送NDP pause(1); % 暂停5s等待反馈 numUsers = cfgUI.numUsers; feedback_data = struct(); % 初始化结构体 stat = zeros(1,numUsers); for uid = 1:numUsers filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat']; stat(uid) = 1; if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在 filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件 stat(uid) = 0; % 此时反馈参数为0 end feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); % 加载每个用户对应的反馈文件---需补充snr等(lxr) end feedback_stat = all(stat == 1); % 判断反馈状态 end % 超时停止 if feedback_stat==false error("Time Out !!!"); else disp("feedback received"); end elseif strcmp(cfgUI.FeedbackMode,'openloop') while(1) % 进入数据传输步骤 numUsers = cfgUI.numUsers; % 读取用户数 feedback_data = struct(); % 初始化结构体 for uid = 1:numUsers filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat']; if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在 filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件 end feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); % 加载每个用户对应的反馈文件 if eval(['isnan(sum(feedback_data.user' num2str(uid) '.staFeedback,"all")) || isempty(feedback_data.user' num2str(uid) '.staFeedback)']) % 判断staFeedback是否为空或NaN filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 改为读取默认的反馈文件 feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); end end [paraCal,tx_data,cfgUI,errorMessage] = TX_transmit(numPkt,SEED,cfgUI,feedback_data,txPSDUByteUser); save('TXPackets\transmit_data.mat','tx_data','cfgUI'); if cfgUI.AI.PAPR == 'PAPR' % PAPR DPD end end elseif strcmp(cfgUI.FeedbackMode,'feedback') while(1) tic; feedback_stat = false; while feedback_stat==false && toc < max_run_time txNDP = channelSounding(cfgUI); % 开始发送探测和NDP序列 tx_data = txNDP; save('TXPackets\transmit_data.mat','tx_data','cfgUI');% 发送NDP pause(0); % 暂停5s等待反馈 numUsers = cfgUI.numUsers; % 读取用户数 stat = zeros(1,numUsers); % 初始化stat参数 feedback_data = struct(); % 初始化结构体 for uid = 1:numUsers filename = ['TXPackets/NDPfeedback_for_User' num2str(uid) '.mat']; stat(uid) = 1; if exist(filename,'file') ~= 2 % 待读取的反馈文件不存在 filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 读取默认的反馈文件 stat(uid) = 0; % 此时反馈参数为0 end feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); if eval(['isnan(sum(feedback_data.user' num2str(uid) '.staFeedback,"all")) || isempty(feedback_data.user' num2str(uid) '.staFeedback)']) % 判断staFeedback是否为空或NaN filename = ['TXPackets/NDPfeedback_Default_for_User' num2str(uid) '.mat']; % 改为读取默认的反馈文件 feedback_data = setfield(feedback_data,['user' num2str(uid)],loadfeedback(filename)); end end feedback_stat = all(stat == 1); % 判断反馈状态 end % 超时停止 if feedback_stat==false error("Time Out !!!"); else disp("feedback received"); end % % 进入参数配置步骤,数据传输步骤 ack_feedback_stat=true; stat = 1; while ack_feedback_stat==true && stat==1 load('TXPackets\feedback.mat'); feedback_data = feedback; [paraCal,tx_data,cfgUI,errorMessage] = TX_transmit(numPkt,SEED,cfgUI,feedback_data,txPSDUByteUser); save('TXPackets\transmit_data.mat','tx_data','cfgUI'); if cfgUI.AI.PAPR == 'PAPR' % PAPR+DPD end pause(1); % 暂停 等待反馈 ACK_feedback = cell(1,numUsers); for uid = 1:numUsers load(['TXPackets\ACKfeedback_for_User' num2str(uid) '.mat']) ACK_feedback{uid} = ACK; end % 显示空口波形参数,PAPR,以及AI算法的reward show2LabVIEW(); %!!! end end end