根据第一段代码,优化第二段代码,解决“开始TDM系统仿真…
信号数量: 3, 总时隙数: 50, 策略: priority, 编码: PCM, 调制: 16QAM
使用外部提供的原始信号…
编码信号 (PCM)…
信号1: 编码后长度=8000, 填充位=0
信号2: 编码后长度=8000, 填充位=0
信号3: 编码后长度=8000, 填充位=0
调制信号…
分配时隙…
时隙分配结果:
信号 1 (正弦波 (50Hz), 无调制): 17 个时隙 (优先级: 0.33, 调制: BPSK)
信号 2 (方波 (50Hz), 无调制): 17 个时隙 (优先级: 0.33, 调制: QPSK)
信号 3 (随机噪声, 无调制): 16 个时隙 (优先级: 0.33, 调制: 16QAM)
TDM复用 (包含帧头)…
仿真过程中发生错误: 要串联的数组的维度不一致。”的问题。第一段代码:classdef TDMApp8888 < matlab.apps.AppBase
properties (Access = public)
UIFigure matlab.ui.Figure
% 左侧控制面板 ControlPanel matlab.ui.container.Panel SignalConfigPanel matlab.ui.container.Panel NumSignalsEditField matlab.ui.control.NumericEditField NumSignalsLabel matlab.ui.control.Label SignalTypeDropDown matlab.ui.control.DropDown SignalTypeLabel matlab.ui.control.Label FrequencyEditField matlab.ui.control.NumericEditField FrequencyLabel matlab.ui.control.Label AddSignalButton matlab.ui.control.Button RemoveSignalButton matlab.ui.control.Button SignalsListBox matlab.ui.control.ListBox SignalsListLabel matlab.ui.control.Label % 新增载波频率控件 CarrierFrequencyLabel matlab.ui.control.Label CarrierFrequencyEditField matlab.ui.control.NumericEditField StrategyPanel matlab.ui.container.Panel FixedRadioButton matlab.ui.control.RadioButton PriorityRadioButton matlab.ui.control.RadioButton StrategyButtonGroup matlab.ui.container.ButtonGroup TotalSlotsEditField matlab.ui.control.NumericEditField TotalSlotsLabel matlab.ui.control.Label % 编码配置控件 EncodingPanel matlab.ui.container.Panel EncodingTypeDropDown matlab.ui.control.DropDown EncodingTypeLabel matlab.ui.control.Label QuantBitsEditField matlab.ui.control.NumericEditField QuantBitsLabel matlab.ui.control.Label StepSizeEditField matlab.ui.control.NumericEditField StepSizeLabel matlab.ui.control.Label % 调制配置控件 ModulationPanel matlab.ui.container.Panel ModulationTypeDropDown matlab.ui.control.DropDown ModulationTypeLabel matlab.ui.control.Label % 帧配置控件 FrameConfigPanel matlab.ui.container.Panel FrameHeaderEditField matlab.ui.control.EditField FrameHeaderLabel matlab.ui.control.Label CRCCheckBox matlab.ui.control.CheckBox % 右侧控制面板 SimulationPanel matlab.ui.container.Panel RunSimulationButton matlab.ui.control.Button RunFeedbackButton matlab.ui.control.Button RunAnalysisButton matlab.ui.control.Button SNREditField matlab.ui.control.NumericEditField SNRLabel matlab.ui.control.Label IterationsEditField matlab.ui.control.NumericEditField IterationsLabel matlab.ui.control.Label DurationEditField matlab.ui.control.NumericEditField DurationLabel matlab.ui.control.Label SamplingRateEditField matlab.ui.control.NumericEditField SamplingRateLabel matlab.ui.control.Label StatusLabel matlab.ui.control.Label ProgressBar matlab.ui.control.Lamp % 结果显示区域 ResultsTabGroup matlab.ui.container.TabGroup SignalsTab matlab.ui.container.Tab OriginalAxes matlab.ui.control.UIAxes TDMAxes matlab.ui.control.UIAxes DemuxAxes matlab.ui.control.UIAxes SyncedAxes matlab.ui.control.UIAxes PerformanceTab matlab.ui.container.Tab BERAxes matlab.ui.control.UIAxes ParametersTab matlab.ui.container.Tab ParametersTextArea matlab.ui.control.TextArea end properties (Access = private) signals % 存储信号配置的cell数组 params % 系统参数结构体 tdmSystem % TDMSystem实例 controller % TDMFeedbackController实例 analyzer % TDMPerformanceAnalyzer实例 end methods (Access = private) function updateParams(app) % 更新系统参数 app.params = struct(); % 确保所有UI组件都存在且有效 try app.params.fs = app.SamplingRateEditField.Value; app.params.duration = app.DurationEditField.Value; app.params.numSignals = numel(app.signals); app.params.snrDb = app.SNREditField.Value; app.params.iterations = app.IterationsEditField.Value; app.params.totalSlots = app.TotalSlotsEditField.Value; % 编码参数 if isvalid(app.EncodingTypeDropDown) app.params.encodingType = app.EncodingTypeDropDown.Value; else app.params.encodingType = 'PCM'; % 默认值 end app.params.quantBits = app.QuantBitsEditField.Value; app.params.stepSize = app.StepSizeEditField.Value; % 调制参数 if isvalid(app.ModulationTypeDropDown) app.params.modulationType = app.ModulationTypeDropDown.Value; else app.params.modulationType = 'BPSK'; % 默认值 end % 帧配置 if isvalid(app.FrameHeaderEditField) app.params.frameHeader = app.FrameHeaderEditField.Value; else app.params.frameHeader = 'A5A5'; % 默认值 end if isvalid(app.CRCCheckBox) app.params.useCRC = app.CRCCheckBox.Value; else app.params.useCRC = true; % 默认值 end % 时隙分配策略 if isvalid(app.FixedRadioButton) && isvalid(app.PriorityRadioButton) if app.FixedRadioButton.Value app.params.strategy = 'fixed'; else app.params.strategy = 'priority'; end else app.params.strategy = 'priority'; % 默认值 end % 设置信号调制方式和时钟漂移 app.params.signalModulations = cell(1, app.params.numSignals); app.params.clockDrift = zeros(1, app.params.numSignals); for i = 1:app.params.numSignals if i <= numel(app.signals) app.params.signalModulations{i} = app.signals{i}.modulation; else app.params.signalModulations{i} = 'BPSK'; % 默认值 end % 设置时钟漂移 (确保长度与信号数量匹配) if i == 1 app.params.clockDrift(i) = 0.001; elseif i == 2 app.params.clockDrift(i) = 0.002; else app.params.clockDrift(i) = -0.001; end end catch ME % 错误处理:记录错误并恢复默认值 disp('更新参数时出错:'); disp(ME.message); app.params = struct('fs', 1000, 'duration', 1, 'numSignals', 0); end end function generateSignals(app) % 生成信号数据 (使用linspace确保精确采样点) if isempty(app.params) || ~isfield(app.params, 'fs') || ~isfield(app.params, 'duration') return; % 参数无效,跳过 end t = linspace(0, app.params.duration, app.params.fs * app.params.duration); app.tdmSystem.originalSignals = zeros(app.params.numSignals, length(t)); app.tdmSystem.signalInfo = cell(app.params.numSignals, 1); for i = 1:app.params.numSignals if i <= numel(app.signals) sigConfig = app.signals{i}; else % 默认值包含载波频率 sigConfig = struct('type', '正弦波', 'frequency', 50, ... 'modulation', 'BPSK', 'carrierFrequency', 1000); end baseSignal = []; % 存储基带信号 switch sigConfig.type case '正弦波' freq = sigConfig.frequency; baseSignal = sin(2*pi*freq*t); baseInfo = sprintf('正弦波 (%dHz)', freq); case '方波' freq = sigConfig.frequency; baseSignal = square(2*pi*freq*t); baseInfo = sprintf('方波 (%dHz)', freq); case '随机噪声' baseSignal = randn(1, length(t)); baseInfo = '随机噪声'; case '锯齿波' freq = sigConfig.frequency; baseSignal = sawtooth(2*pi*freq*t); baseInfo = sprintf('锯齿波 (%dHz)', freq); case '脉冲信号' freq = sigConfig.frequency; duty = 0.3; % 占空比 pulseTrain = pulstran(t, 0:1/freq:app.params.duration, ... 'rectpuls', duty/freq); % 确保长度匹配 if length(pulseTrain) > length(t) baseSignal = pulseTrain(1:length(t)); else baseSignal = zeros(1, length(t)); baseSignal(1:length(pulseTrain)) = pulseTrain; end baseInfo = sprintf('脉冲信号 (%dHz)', freq); end % ========== 应用载波调制 ========== carrierFreq = sigConfig.carrierFrequency; switch sigConfig.modulation case 'AM' % 幅度调制: (1 + m(t)) * cos(2πf_c t) modulatedSignal = (1 + 0.5*baseSignal) .* cos(2*pi*carrierFreq*t); modInfo = sprintf('AM调制 (%dHz载波)', carrierFreq); case 'FM' % 频率调制: cos(2πf_c t + 2πΔf ∫m(t)dt) kf = 0.1; % 调制指数 integral_m = cumsum(baseSignal) / app.params.fs; modulatedSignal = cos(2*pi*carrierFreq*t + 2*pi*kf*integral_m); modInfo = sprintf('FM调制 (%dHz载波)', carrierFreq); case 'PM' % 相位调制: cos(2πf_c t + k_p m(t)) kp = 1; % 相位偏移常数 modulatedSignal = cos(2*pi*carrierFreq*t + kp*baseSignal); modInfo = sprintf('PM调制 (%dHz载波)', carrierFreq); otherwise % 无调制或未知调制类型 modulatedSignal = baseSignal; modInfo = '无调制'; end app.tdmSystem.originalSignals(i, :) = modulatedSignal; app.tdmSystem.signalInfo{i} = [baseInfo ', ' modInfo]; end % 设置编码参数 if isfield(app.params, 'encodingType') && isfield(app.params, 'quantBits') && isfield(app.params, 'stepSize') app.tdmSystem.encodingParams = struct(... 'type', app.params.encodingType, ... 'quantBits', app.params.quantBits, ... 'stepSize', app.params.stepSize); else app.tdmSystem.encodingParams = struct('type', 'PCM', 'quantBits', 8, 'stepSize', 0.05); % 默认值 end % 设置调制参数 if isfield(app.params, 'modulationType') && isfield(app.params, 'signalModulations') app.tdmSystem.modulationParams = struct(... 'type', app.params.modulationType, ... 'signalModulations', {app.params.signalModulations}); else app.tdmSystem.modulationParams = struct('type', 'BPSK', 'signalModulations', {{'BPSK', 'BPSK'}}); % 默认值 end % 设置帧配置 if isfield(app.params, 'frameHeader') && isfield(app.params, 'useCRC') app.tdmSystem.frameConfig = struct(... 'header', app.params.frameHeader, ... 'useCRC', app.params.useCRC); else app.tdmSystem.frameConfig = struct('header', 'A5A5', 'useCRC', true); % 默认值 end end function updateParametersDisplay(app) % 更新参数显示 try paramText = sprintf('系统参数:\n'); if isfield(app.params, 'fs') paramText = [paramText sprintf('采样频率: %d Hz\n', app.params.fs)]; end if isfield(app.params, 'duration') paramText = [paramText sprintf('信号持续时间: %.2f 秒\n', app.params.duration)]; end if isfield(app.params, 'numSignals') paramText = [paramText sprintf('信号源数量: %d\n', app.params.numSignals)]; end if isfield(app.params, 'snrDb') paramText = [paramText sprintf('信噪比: %d dB\n', app.params.snrDb)]; end if isfield(app.params, 'strategy') paramText = [paramText sprintf('时隙分配策略: %s\n', app.params.strategy)]; end if isfield(app.params, 'totalSlots') paramText = [paramText sprintf('总时隙数量: %d\n', app.params.totalSlots)]; end if isfield(app.params, 'iterations') paramText = [paramText sprintf('仿真迭代次数: %d\n', app.params.iterations)]; end % 编码参数 paramText = [paramText sprintf('\n编码配置:\n')]; if isfield(app.params, 'encodingType') paramText = [paramText sprintf(' 编码类型: %s\n', app.params.encodingType)]; end if isfield(app.params, 'quantBits') paramText = [paramText sprintf(' 量化位数: %d bits\n', app.params.quantBits)]; end if isfield(app.params, 'stepSize') paramText = [paramText sprintf(' 步长: %.4f\n', app.params.stepSize)]; end % 调制参数 paramText = [paramText sprintf('\n调制配置:\n')]; if isfield(app.params, 'modulationType') paramText = [paramText sprintf(' 系统调制类型: %s\n', app.params.modulationType)]; end % 帧配置 paramText = [paramText sprintf('\n帧配置:\n')]; if isfield(app.params, 'frameHeader') paramText = [paramText sprintf(' 帧头: %s\n', app.params.frameHeader)]; end if isfield(app.params, 'useCRC') paramText = [paramText sprintf(' CRC校验: %s\n', ifelse(app.params.useCRC, '启用', '禁用'))]; end % 信号信息 - 包含载波频率 paramText = [paramText sprintf('\n信号配置:\n')]; for i = 1:min(app.params.numSignals, numel(app.signals)) sig = app.signals{i}; paramText = [paramText sprintf('信号 %d: %s (基带频率: %d Hz, 调制: %s, 载波频率: %d Hz)\n', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency)]; end app.ParametersTextArea.Value = paramText; catch ME disp('更新参数显示时出错:'); disp(ME.message); app.ParametersTextArea.Value = '系统参数显示错误'; end end function plotSignals(app) % 绘制原始信号 try t = linspace(0, app.params.duration, app.params.fs * app.params.duration); cla(app.OriginalAxes); hold(app.OriginalAxes, 'on'); colors = lines(app.params.numSignals); for i = 1:min(app.params.numSignals, size(app.tdmSystem.originalSignals, 1)) plot(app.OriginalAxes, t, app.tdmSystem.originalSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', app.tdmSystem.signalInfo{i}); end hold(app.OriginalAxes, 'off'); legend(app.OriginalAxes, 'Location', 'best'); title(app.OriginalAxes, '原始信号'); xlabel(app.OriginalAxes, '时间 (s)'); ylabel(app.OriginalAxes, '幅度'); grid(app.OriginalAxes, 'on'); % 绘制TDM信号(支持复数信号) cla(app.TDMAxes); if ~isempty(app.tdmSystem.tdmSignal) && isfield(app.params, 'duration') t_tdm = linspace(0, app.params.duration, length(app.tdmSystem.tdmSignal)); plot(app.TDMAxes, t_tdm, real(app.tdmSystem.tdmSignal)); hold(app.TDMAxes, 'on'); plot(app.TDMAxes, t_tdm, imag(app.tdmSystem.tdmSignal)); hold(app.TDMAxes, 'off'); legend(app.TDMAxes, {'实部', '虚部'}, 'Location', 'best'); end title(app.TDMAxes, ['TDM复用信号 (' app.params.strategy '策略)']); xlabel(app.TDMAxes, '时间 (s)'); ylabel(app.TDMAxes, '幅度'); grid(app.TDMAxes, 'on'); % 绘制解复用信号 cla(app.DemuxAxes); hold(app.DemuxAxes, 'on'); for i = 1:min(app.params.numSignals, size(app.tdmSystem.demuxSignals, 1)) if size(app.tdmSystem.demuxSignals, 2) >= length(t) plot(app.DemuxAxes, t,app.tdmSystem.demuxSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', ['信号 ' num2str(i)]); end end hold(app.DemuxAxes, 'off'); legend(app.DemuxAxes, 'Location', 'best'); title(app.DemuxAxes, '解复用信号'); xlabel(app.DemuxAxes, '时间 (s)'); ylabel(app.DemuxAxes, '幅度'); grid(app.DemuxAxes, 'on'); % 绘制同步后信号 cla(app.SyncedAxes); hold(app.SyncedAxes, 'on'); for i = 1:min(app.params.numSignals, size(app.tdmSystem.syncedSignals, 1)) if size(app.tdmSystem.syncedSignals, 2) >= length(t) plot(app.SyncedAxes, t, app.tdmSystem.syncedSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', app.tdmSystem.signalInfo{i}); end end hold(app.SyncedAxes, 'off'); legend(app.SyncedAxes, 'Location', 'best'); title(app.SyncedAxes, '同步后信号'); xlabel(app.SyncedAxes, '时间 (s)'); ylabel(app.SyncedAxes, '幅度'); grid(app.SyncedAxes, 'on'); % 绘制误码率和信噪比 cla(app.BERAxes); if ~isempty(app.tdmSystem.performance) && isfield(app.tdmSystem.performance, 'ber') && isfield(app.tdmSystem.performance, 'snr') yyaxis(app.BERAxes, 'left'); bar(app.BERAxes, 1:app.params.numSignals, app.tdmSystem.performance.ber, 0.6, 'FaceColor', [0.2 0.6 0.8]); ylabel(app.BERAxes, '误码率 (BER)'); yyaxis(app.BERAxes, 'right'); plot(app.BERAxes, 1:app.params.numSignals, app.tdmSystem.performance.snr, 'o-', 'LineWidth', 2, 'MarkerSize', 8); ylabel(app.BERAxes, 'SNR (dB)'); title(app.BERAxes, '信号质量分析'); xlabel(app.BERAxes, '信号编号'); grid(app.BERAxes, 'on'); xticks(app.BERAxes, 1:app.params.numSignals); legend(app.BERAxes, {'BER', 'SNR'}, 'Location', 'best'); end catch ME disp('绘图时出错:'); disp(ME.message); end end end % Callbacks that handle component events methods (Access = private) % Code that executes after component creation function startupFcn(app) % 初始化参数 app.signals = {}; app.params = struct(); app.StatusLabel.Text = '准备就绪'; app.ProgressBar.Color = 'green'; % 设置默认参数 app.SamplingRateEditField.Value = 1000; app.DurationEditField.Value = 1; app.SNREditField.Value = 20; app.IterationsEditField.Value = 5; app.TotalSlotsEditField.Value = 50; app.NumSignalsEditField.Value = 0; app.PriorityRadioButton.Value = true; % 编码参数默认值 app.EncodingTypeDropDown.Value = 'PCM'; app.QuantBitsEditField.Value = 8; app.StepSizeEditField.Value = 0.05; % 调制参数默认值 app.ModulationTypeDropDown.Value = 'BPSK'; % 帧配置默认值 app.FrameHeaderEditField.Value = 'A5A5'; app.CRCCheckBox.Value = true; % 载波频率默认值 app.CarrierFrequencyEditField.Value = 1000; % 更新参数显示 updateParams(app); updateParametersDisplay(app); end % Button pushed function: AddSignalButton function AddSignalButtonPushed(app, ~) % 添加新信号(包含载波频率) try signalType = app.SignalTypeDropDown.Value; frequency = app.FrequencyEditField.Value; modulationType = app.ModulationTypeDropDown.Value; % 获取调制类型 carrierFrequency = app.CarrierFrequencyEditField.Value; % 获取载波频率 if frequency <= 0 uialert(app.UIFigure, '基带频率必须大于0', '无效参数'); return; end if carrierFrequency <= 0 uialert(app.UIFigure, '载波频率必须大于0', '无效参数'); return; end newSignal = struct(... 'type', signalType, ... 'frequency', frequency, ... 'modulation', modulationType, ... 'carrierFrequency', carrierFrequency); % 添加载波频率 app.signals{end+1} = newSignal; app.NumSignalsEditField.Value = numel(app.signals); % 更新信号列表(包含载波频率) signalList = cell(1, numel(app.signals)); for i = 1:numel(app.signals) sig = app.signals{i}; signalList{i} = sprintf('信号 %d: %s (%d Hz基带, %s调制, %d Hz载波)', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency); end app.SignalsListBox.Items = signalList; % 更新参数 updateParams(app); updateParametersDisplay(app); app.StatusLabel.Text = sprintf('已添加信号: %s (%d Hz基带, %s调制, %d Hz载波)', ... signalType, frequency, modulationType, carrierFrequency); catch ME app.StatusLabel.Text = ['添加信号错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Button pushed function: RemoveSignalButton function RemoveSignalButtonPushed(app, ~) % 移除选中的信号(包含载波频率) try selectedIdx = app.SignalsListBox.Value; if isempty(selectedIdx) || selectedIdx > numel(app.signals) uialert(app.UIFigure, '请选择要删除的信号', '无选择'); return; end % 移除信号 removedSig = app.signals{selectedIdx}; app.signals(selectedIdx) = []; % 更新信号列表(包含载波频率) app.NumSignalsEditField.Value = numel(app.signals); signalList = cell(1, numel(app.signals)); for i = 1:numel(app.signals) sig = app.signals{i}; signalList{i} = sprintf('信号 %d: %s (%d Hz基带, %s调制, %d Hz载波)', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency); end app.SignalsListBox.Items = signalList; % 如果没有信号,清除选择 if isempty(app.signals) app.SignalsListBox.Value = []; else app.SignalsListBox.Value = min(selectedIdx, numel(app.signals)); end % 更新参数 updateParams(app); updateParametersDisplay(app); app.StatusLabel.Text = sprintf('已移除信号: %s (%d Hz基带, %s调制, %d Hz载波)', ... removedSig.type, removedSig.frequency, removedSig.modulation, removedSig.carrierFrequency); catch ME app.StatusLabel.Text = ['移除信号错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: NumSignalsEditField function NumSignalsEditFieldValueChanged(app, ~) % 信号数量变化时更新 try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新信号数量错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: SamplingRateEditField function SamplingRateEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新采样率错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: DurationEditField function DurationEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新持续时间错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: SNREditField function SNREditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新信噪比错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: IterationsEditField function IterationsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新迭代次数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: TotalSlotsEditField function TotalSlotsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新总时隙数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Selection changed function: StrategyButtonGroup function StrategyButtonGroupSelectionChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新策略错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % 编码参数变化回调 function EncodingTypeDropDownValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新编码类型错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function QuantBitsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新量化位数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function StepSizeEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新步长错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % 调制参数变化回调 function ModulationTypeDropDownValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新调制方式错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function FrameHeaderEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新帧头错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function CRCCheckBoxValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新CRC设置错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Button pushed function: RunSimulationButton function RunSimulationButtonPushed(app, ~) % 运行基础仿真 app.StatusLabel.Text = '运行基础仿真...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建TDM系统 app.tdmSystem = TDMSystem(app.params); % 生成信号 generateSignals(app); % 运行仿真 app.tdmSystem = app.tdmSystem.runSimulation(); % 显示结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '基础仿真完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['基础仿真错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end % Button pushed function: RunFeedbackButton function RunFeedbackButtonPushed(app, ~) % 运行反馈控制仿真 app.StatusLabel.Text = '运行反馈控制仿真...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建反馈控制器 app.controller = TDMFeedbackController(app.params); % 生成信号 generateSignals(app); % 将生成的信号复制到控制器 app.controller.originalSignals = app.tdmSystem.originalSignals; app.controller.signalInfo = app.tdmSystem.signalInfo; app.controller.encodingParams = app.tdmSystem.encodingParams; app.controller.modulationParams = app.tdmSystem.modulationParams; app.controller.frameConfig = app.tdmSystem.frameConfig; % 运行反馈仿真 app.controller = app.controller.runSimulation(); % 显示结果 app.tdmSystem = app.controller; % 用于显示基本结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '反馈控制仿真完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['反馈控制错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end % Button pushed function: RunAnalysisButton function RunAnalysisButtonPushed(app, ~) % 运行性能分析 app.StatusLabel.Text = '运行性能分析...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建性能分析器 app.analyzer = TDMPerformanceAnalyzer(app.params); % 生成信号 generateSignals(app); % 将生成的信号复制到分析器 app.analyzer.originalSignals = app.tdmSystem.originalSignals; app.analyzer.signalInfo = app.tdmSystem.signalInfo; app.analyzer.encodingParams = app.tdmSystem.encodingParams; app.analyzer.modulationParams = app.tdmSystem.modulationParams; app.analyzer.frameConfig = app.tdmSystem.frameConfig; % 运行性能分析 app.analyzer = app.analyzer.runPerformanceAnalysis(); % 显示结果 app.tdmSystem = app.analyzer; % 用于显示基本结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '性能分析完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['性能分析错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end end % App initialization and construction methods (Access = private) % Create UIFigure and components function createComponents(app) % 创建主窗口 app.UIFigure = uifigure; app.UIFigure.Position = [100 100 1400 900]; app.UIFigure.Name = 'TDM通信系统仿真'; app.UIFigure.Scrollable = 'on'; % 创建控制面板容器 app.ControlPanel = uipanel(app.UIFigure); app.ControlPanel.Title = '控制面板'; app.ControlPanel.Position = [20 20 450 850]; % ==== 信号配置面板 ==== app.SignalConfigPanel = uipanel(app.ControlPanel); app.SignalConfigPanel.Title = '信号配置'; app.SignalConfigPanel.Position = [20 585 410 240]; % 增加高度以容纳载波频率控件 % 信号数量控件 app.NumSignalsLabel = uilabel(app.SignalConfigPanel); app.NumSignalsLabel.Position = [20 190 80 22]; app.NumSignalsLabel.Text = '信号数量:'; app.NumSignalsEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.NumSignalsEditField.Position = [110 190 60 22]; app.NumSignalsEditField.Value = 0; app.NumSignalsEditField.ValueChangedFcn = createCallbackFcn(app, @NumSignalsEditFieldValueChanged, true); % 信号类型控件 app.SignalTypeLabel = uilabel(app.SignalConfigPanel); app.SignalTypeLabel.Position = [20 160 80 22]; app.SignalTypeLabel.Text = '信号类型:'; app.SignalTypeDropDown = uidropdown(app.SignalConfigPanel); app.SignalTypeDropDown.Position = [110 160 80 22]; app.SignalTypeDropDown.Items = {'正弦波', '方波', '随机噪声', '锯齿波', '脉冲信号'}; % 基带频率控件 app.FrequencyLabel = uilabel(app.SignalConfigPanel); app.FrequencyLabel.Position = [20 130 80 22]; app.FrequencyLabel.Text = '基带频率 (Hz):'; app.FrequencyEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.FrequencyEditField.Position = [110 130 60 22]; app.FrequencyEditField.Value = 50; % 载波频率控件 app.CarrierFrequencyLabel = uilabel(app.SignalConfigPanel); app.CarrierFrequencyLabel.Position = [210 130 100 22]; app.CarrierFrequencyLabel.Text = '载波频率 (Hz):'; app.CarrierFrequencyEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.CarrierFrequencyEditField.Position = [300 130 60 22]; app.CarrierFrequencyEditField.Value = 1000; % 默认值 % 添加/移除按钮 app.AddSignalButton = uibutton(app.SignalConfigPanel, 'push'); app.AddSignalButton.ButtonPushedFcn = createCallbackFcn(app, @AddSignalButtonPushed, true); app.AddSignalButton.Position = [210 160 80 22]; app.AddSignalButton.Text = '添加信号'; app.RemoveSignalButton = uibutton(app.SignalConfigPanel, 'push'); app.RemoveSignalButton.ButtonPushedFcn = createCallbackFcn(app, @RemoveSignalButtonPushed, true); app.RemoveSignalButton.Position = [300 160 80 22]; app.RemoveSignalButton.Text = '移除信号'; % 信号列表 app.SignalsListLabel = uilabel(app.SignalConfigPanel); app.SignalsListLabel.Position = [20 100 80 22]; app.SignalsListLabel.Text = '信号列表:'; app.SignalsListBox = uilistbox(app.SignalConfigPanel); app.SignalsListBox.Position = [20 5 370 90]; app.SignalsListBox.Items = {}; % ==== 策略配置面板 ==== app.StrategyPanel = uipanel(app.ControlPanel); app.StrategyPanel.Title = '时隙分配策略'; app.StrategyPanel.Position = [20 425 410 150]; % 策略按钮组 app.StrategyButtonGroup = uibuttongroup(app.StrategyPanel); app.StrategyButtonGroup.SelectionChangedFcn = createCallbackFcn(app, @StrategyButtonGroupSelectionChanged, true); app.StrategyButtonGroup.Position = [20 40 200 80]; app.StrategyButtonGroup.Title = '选择策略'; % 单选按钮 app.FixedRadioButton = uiradiobutton(app.StrategyButtonGroup); app.FixedRadioButton.Text = '固定分配'; app.FixedRadioButton.Position = [11 35 75 22]; app.PriorityRadioButton = uiradiobutton(app.StrategyButtonGroup); app.PriorityRadioButton.Text = '优先级分配'; app.PriorityRadioButton.Position = [11 10 100 22]; app.PriorityRadioButton.Value = true; % 总时隙数 app.TotalSlotsLabel = uilabel(app.StrategyPanel); app.TotalSlotsLabel.Position = [240 30 80 22]; app.TotalSlotsLabel.Text = '总时隙数:'; app.TotalSlotsEditField = uieditfield(app.StrategyPanel, 'numeric'); app.TotalSlotsEditField.ValueChangedFcn = createCallbackFcn(app, @TotalSlotsEditFieldValueChanged, true); app.TotalSlotsEditField.Position = [300 30 60 22]; app.TotalSlotsEditField.Value = 50; % ==== 编码配置面板 ==== app.EncodingPanel = uipanel(app.ControlPanel); app.EncodingPanel.Title = '编码配置'; app.EncodingPanel.Position = [20 300 410 120]; app.EncodingTypeLabel = uilabel(app.EncodingPanel); app.EncodingTypeLabel.Position = [20 75 80 22]; app.EncodingTypeLabel.Text = '编码类型:'; app.EncodingTypeDropDown = uidropdown(app.EncodingPanel); app.EncodingTypeDropDown.Position = [110 75 100 22]; app.EncodingTypeDropDown.Items = {'PCM', 'DPCM', 'DM'}; app.EncodingTypeDropDown.Value = 'PCM'; app.EncodingTypeDropDown.ValueChangedFcn = createCallbackFcn(app, @EncodingTypeDropDownValueChanged, true); app.QuantBitsLabel = uilabel(app.EncodingPanel); app.QuantBitsLabel.Position = [20 45 80 22]; app.QuantBitsLabel.Text = '量化位数:'; app.QuantBitsEditField = uieditfield(app.EncodingPanel, 'numeric'); app.QuantBitsEditField.Position = [110 45 60 22]; app.QuantBitsEditField.Value = 8; app.QuantBitsEditField.ValueChangedFcn = createCallbackFcn(app, @QuantBitsEditFieldValueChanged, true); app.StepSizeLabel = uilabel(app.EncodingPanel); app.StepSizeLabel.Position = [20 15 80 22]; app.StepSizeLabel.Text = '步长:'; app.StepSizeEditField = uieditfield(app.EncodingPanel, 'numeric'); app.StepSizeEditField.Position = [110 15 60 22]; app.StepSizeEditField.Value = 0.05; app.StepSizeEditField.ValueChangedFcn = createCallbackFcn(app, @StepSizeEditFieldValueChanged, true); % ==== 调制配置面板 ==== app.ModulationPanel = uipanel(app.ControlPanel); app.ModulationPanel.Title = '调制配置'; app.ModulationPanel.Position = [20 225 410 70]; app.ModulationTypeLabel = uilabel(app.ModulationPanel); app.ModulationTypeLabel.Position = [20 15 80 22]; app.ModulationTypeLabel.Text = '调制方式:'; app.ModulationTypeDropDown = uidropdown(app.ModulationPanel); app.ModulationTypeDropDown.Position = [110 15 100 22]; app.ModulationTypeDropDown.Items = {'None', 'BPSK', 'QPSK', '16QAM'}; app.ModulationTypeDropDown.Value = 'BPSK'; app.ModulationTypeDropDown.ValueChangedFcn = createCallbackFcn(app, @ModulationTypeDropDownValueChanged, true); % ==== 帧配置面板 ==== app.FrameConfigPanel = uipanel(app.ControlPanel); app.FrameConfigPanel.Title = '帧配置'; app.FrameConfigPanel.Position = [20 150 410 70]; app.FrameHeaderLabel = uilabel(app.FrameConfigPanel); app.FrameHeaderLabel.Position = [20 15 80 22]; app.FrameHeaderLabel.Text = '帧头:'; app.FrameHeaderEditField = uieditfield(app.FrameConfigPanel, 'text'); app.FrameHeaderEditField.Position = [110 15 100 22]; app.FrameHeaderEditField.Value = 'A5A5'; app.FrameHeaderEditField.ValueChangedFcn = createCallbackFcn(app, @FrameHeaderEditFieldValueChanged, true); app.CRCCheckBox = uicheckbox(app.FrameConfigPanel); app.CRCCheckBox.Text = '启用CRC校验'; app.CRCCheckBox.Position = [220 15 120 22]; app.CRCCheckBox.Value = true; app.CRCCheckBox.ValueChangedFcn = createCallbackFcn(app, @CRCCheckBoxValueChanged, true); % ==== 仿真控制面板 ==== app.SimulationPanel = uipanel(app.ControlPanel); app.SimulationPanel.Title = '仿真控制'; app.SimulationPanel.Position = [20 5 410 140]; % 参数输入 app.SamplingRateLabel = uilabel(app.SimulationPanel); app.SamplingRateLabel.Position = [20 95 80 22]; app.SamplingRateLabel.Text = '采样率 (Hz):'; app.SamplingRateEditField = uieditfield(app.SimulationPanel, 'numeric'); app.SamplingRateEditField.ValueChangedFcn = createCallbackFcn(app, @SamplingRateEditFieldValueChanged, true); app.SamplingRateEditField.Position = [110 95 60 22]; app.SamplingRateEditField.Value = 1000; app.DurationLabel = uilabel(app.SimulationPanel); app.DurationLabel.Position = [20 65 80 22]; app.DurationLabel.Text = '持续时间 (s):'; app.DurationEditField = uieditfield(app.SimulationPanel, 'numeric'); app.DurationEditField.ValueChangedFcn = createCallbackFcn(app, @DurationEditFieldValueChanged, true); app.DurationEditField.Position = [110 65 60 22]; app.DurationEditField.Value = 1; app.SNRLabel = uilabel(app.SimulationPanel); app.SNRLabel.Position = [20 35 80 22]; app.SNRLabel.Text = '信噪比 (dB):'; app.SNREditField = uieditfield(app.SimulationPanel, 'numeric'); app.SNREditField.ValueChangedFcn = createCallbackFcn(app, @SNREditFieldValueChanged, true); app.SNREditField.Position = [110 35 60 22]; app.SNREditField.Value = 20; app.IterationsLabel = uilabel(app.SimulationPanel); app.IterationsLabel.Position = [200 95 80 22]; app.IterationsLabel.Text = '迭代次数:'; app.IterationsEditField = uieditfield(app.SimulationPanel, 'numeric'); app.IterationsEditField.ValueChangedFcn = createCallbackFcn(app, @IterationsEditFieldValueChanged, true); app.IterationsEditField.Position = [290 95 60 22]; app.IterationsEditField.Value = 5; % 状态显示 app.StatusLabel = uilabel(app.SimulationPanel); app.StatusLabel.HorizontalAlignment = 'center'; app.StatusLabel.Position = [20 5 100 22]; app.StatusLabel.Text = '准备就绪'; app.ProgressBar = uilamp(app.SimulationPanel); app.ProgressBar.Position = [150 5 110 20]; app.ProgressBar.Color = [0.47 0.67 0.19]; % 仿真按钮 app.RunSimulationButton = uibutton(app.SimulationPanel, 'push'); app.RunSimulationButton.ButtonPushedFcn = createCallbackFcn(app, @RunSimulationButtonPushed, true); app.RunSimulationButton.Position = [200 20 80 30]; app.RunSimulationButton.Text = '基础仿真'; app.RunFeedbackButton = uibutton(app.SimulationPanel, 'push'); app.RunFeedbackButton.ButtonPushedFcn = createCallbackFcn(app, @RunFeedbackButtonPushed, true); app.RunFeedbackButton.Position = [290 20 80 30]; app.RunFeedbackButton.Text = '反馈控制'; app.RunAnalysisButton = uibutton(app.SimulationPanel, 'push'); app.RunAnalysisButton.ButtonPushedFcn = createCallbackFcn(app, @RunAnalysisButtonPushed, true); app.RunAnalysisButton.Position = [200 60 170 30]; app.RunAnalysisButton.Text = '性能分析'; % ==== 结果显示区域 ==== app.ResultsTabGroup = uitabgroup(app.UIFigure); app.ResultsTabGroup.Position = [480 20 900 850]; % 信号可视化标签页 app.SignalsTab = uitab(app.ResultsTabGroup); app.SignalsTab.Title = '信号可视化'; % 创建2x2网格布局 grid = uigridlayout(app.SignalsTab); grid.RowHeight = {'1x', '1x'}; grid.ColumnWidth = {'1x', '1x'}; grid.Padding = [10 10 10 10]; grid.RowSpacing = 10; grid.ColumnSpacing = 10; % 原始信号坐标轴 app.OriginalAxes = uiaxes(grid); title(app.OriginalAxes, '原始信号'); xlabel(app.OriginalAxes, '时间 (s)'); ylabel(app.OriginalAxes, '幅度'); app.OriginalAxes.Layout.Row = 1; app.OriginalAxes.Layout.Column = 1; % TDM信号坐标轴 app.TDMAxes = uiaxes(grid); title(app.TDMAxes, 'TDM复用信号'); xlabel(app.TDMAxes, '时间 (s)'); ylabel(app.TDMAxes, '幅度'); app.TDMAxes.Layout.Row = 1; app.TDMAxes.Layout.Column = 2; % 解复用信号坐标轴 app.DemuxAxes = uiaxes(grid); title(app.DemuxAxes, '解复用信号'); xlabel(app.DemuxAxes, '时间 (s)'); ylabel(app.DemuxAxes, '幅度'); app.DemuxAxes.Layout.Row = 2; app.DemuxAxes.Layout.Column = 1; % 同步后信号坐标轴 app.SyncedAxes = uiaxes(grid); title(app.SyncedAxes, '同步后信号'); xlabel(app.SyncedAxes, '时间 (s)'); ylabel(app.SyncedAxes, '幅度'); app.SyncedAxes.Layout.Row = 2; app.SyncedAxes.Layout.Column = 2; % 性能分析标签页 app.PerformanceTab = uitab(app.ResultsTabGroup); app.PerformanceTab.Title = '性能分析'; % BER坐标轴 app.BERAxes = uiaxes(app.PerformanceTab); title(app.BERAxes, '信号质量分析'); xlabel(app.BERAxes, '信号编号'); app.BERAxes.Position = [100 200 700 500]; yyaxis(app.BERAxes, 'left'); ylabel(app.BERAxes, 'BER'); yyaxis(app.BERAxes, 'right'); ylabel(app.BERAxes, 'SNR (dB)'); % 系统参数标签页 app.ParametersTab = uitab(app.ResultsTabGroup); app.ParametersTab.Title = '系统参数'; % 参数文本区域 app.ParametersTextArea = uitextarea(app.ParametersTab); app.ParametersTextArea.Position = [20 20 860 800]; app.ParametersTextArea.Value = {'系统参数将在此显示'}; end end methods (Access = public) % Construct app function app = TDMApp8888 % Create and configure components createComponents(app) % Register the app with App Designer registerApp(app, app.UIFigure) % Execute the startup function runStartupFcn(app, @startupFcn) if nargout == 0 clear app end end % Code that executes before app deletion function delete(app) % Delete UIFigure when app is deleted delete(app.UIFigure) end end
end
% 辅助函数
function out = ifelse(condition, true_val, false_val)
if condition
out = true_val;
else
out = false_val;
end
end
第二段代码:classdef TDMSystem
properties
params % 系统参数
originalSignals % 原始未编码信号
encodedSignals % 编码后信号(二进制位流)
modulatedSignals % 调制后信号
demodulatedSignals % 解调后信号(二进制位流)
decodedSignals % 解码后信号
tdmSignal % TDM复用信号
receivedSignal % 接收信号
demuxSignals % 解复用信号
syncedSignals % 同步后信号
signalInfo % 信号信息
allocatedSlots % 分配的时隙
slotAssignment % 时隙分配矩阵
performance % 性能指标
encodingParams % 编码参数
modulationParams % 调制参数
frameConfig % 帧配置
quantizationError % 量化误差
frameHeaders % 帧头位置
crcErrors % CRC错误统计
constellationPoints % 星座图数据
paddingInfo % 填充信息(记录填充位数)
debugInfo % 调试信息
end
methods function obj = TDMSystem(params) % 参数验证和默认值设置 if ~isstruct(params) error('输入参数必须是结构体'); end % 必需参数检查 requiredFields = {'fs', 'duration', 'numSignals', 'snrDb', ... 'totalSlots', 'strategy', 'signalModulations'}; for i = 1:length(requiredFields) if ~isfield(params, requiredFields{i}) error('缺少必需的参数字段: %s', requiredFields{i}); end end % 设置默认值 if ~isfield(params, 'clockDrift') params.clockDrift = zeros(1, params.numSignals); end if ~isfield(params, 'priorities') params.priorities = ones(1, params.numSignals); end if ~isfield(params, 'frameHeader') params.frameHeader = 'A5A5'; end if ~isfield(params, 'useCRC') params.useCRC = true; end if ~isfield(params, 'encodingType') params.encodingType = 'PCM'; end if ~isfield(params, 'quantBits') && strcmp(params.encodingType, 'PCM') params.quantBits = 8; end if ~isfield(params, 'stepSize') && contains(params.encodingType, {'DPCM', 'DM'}) params.stepSize = 0.05; end % 归一化优先级权重 params.priorities = params.priorities / sum(params.priorities); obj.params = params; % 计算关键参数 totalSamples = params.fs * params.duration; obj.params.slotSamples = floor(totalSamples / params.totalSlots); % 初始化性能指标 obj.performance = struct(); obj.quantizationError = zeros(params.numSignals, 1); obj.crcErrors = struct('total', 0, 'perSignal', zeros(1, params.numSignals)); obj.paddingInfo = struct('encoded', zeros(1, params.numSignals)); obj.debugInfo = struct('signalLengths', []); % 初始化编码参数 obj.encodingParams = struct(... 'type', params.encodingType, ... 'quantBits', ifelse(isfield(params, 'quantBits'), params.quantBits, 8), ... 'step', ifelse(isfield(params, 'stepSize'), params.stepSize, 0.05)); % 初始化调制参数 obj.modulationParams = struct(... 'type', ifelse(isfield(params, 'modulationType'), params.modulationType, 'BPSK'), ... 'signalModulations', {params.signalModulations}); % 初始化帧配置 obj.frameConfig = struct(... 'header', params.frameHeader, ... 'useCRC', params.useCRC); end function obj = runSimulation(obj) fprintf('开始TDM系统仿真...\n'); fprintf('信号数量: %d, 总时隙数: %d, 策略: %s, 编码: %s, 调制: %s\n', ... obj.params.numSignals, obj.params.totalSlots, obj.params.strategy, ... obj.encodingParams.type, obj.modulationParams.type); try % 检查原始信号是否提供 if isempty(obj.originalSignals) || all(cellfun(@isempty, obj.signalInfo)) error('原始信号未提供'); else fprintf('使用外部提供的原始信号...\n'); end % 记录原始信号长度 obj.debugInfo.signalLengths = size(obj.originalSignals, 2); % 处理流程 fprintf('编码信号 (%s)...\n', obj.encodingParams.type); obj = obj.encodeSignals(); fprintf('调制信号...\n'); obj = obj.modulateSignals(); fprintf('分配时隙...\n'); obj = obj.allocateSlots(); fprintf('TDM复用 (包含帧头)...\n'); obj = obj.multiplex(); fprintf('信道传输 (SNR: %.1f dB)...\n', obj.params.snrDb); obj = obj.transmit(); fprintf('帧同步...\n'); obj = obj.frameSynchronization(); fprintf('解复用...\n'); obj = obj.demultiplex(); fprintf('解调信号...\n'); obj = obj.demodulateSignals(); fprintf('解码信号 (%s)...\n', obj.encodingParams.type); obj = obj.decodeSignals(); fprintf('信号同步...\n'); obj = obj.synchronize(); fprintf('性能评估...\n'); obj = obj.evaluatePerformance(); fprintf('仿真成功完成!\n'); catch ME fprintf('仿真过程中发生错误: %s\n', ME.message); rethrow(ME); end end function obj = encodeSignals(obj) obj.encodedSignals = cell(1, obj.params.numSignals); for i = 1:obj.params.numSignals signal = obj.originalSignals(i, :); switch obj.encodingParams.type case 'PCM' [quantized, quantErr] = obj.pcm_encode(signal, obj.encodingParams.quantBits); [binStream, ~] = obj.int_to_bin(quantized, obj.encodingParams.quantBits); obj.quantizationError(i) = mean(quantErr.^2); case 'DPCM' [quantized, quantErr] = obj.dpcm_encode(signal, obj.encodingParams.quantBits, obj.encodingParams.step); [binStream, ~] = obj.int_to_bin(quantized, obj.encodingParams.quantBits); obj.quantizationError(i) = mean(quantErr.^2); case 'DM' binStream = obj.dm_encode(signal, obj.encodingParams.step); otherwise error('未知编码类型: %s', obj.encodingParams.type); end % 根据调制方式预填充位流 modType = obj.modulationParams.signalModulations{i}; bitsPerSymbol = obj.getBitsPerSymbol(modType); % 计算填充位数 paddingBits = mod(length(binStream), bitsPerSymbol); if paddingBits > 0 padding = bitsPerSymbol - paddingBits; binStream = [binStream, false(1, padding)]; % 填充0 else padding = 0; end obj.paddingInfo.encoded(i) = padding; % 统一转换为逻辑数组 if ~islogical(binStream) binStream = logical(binStream); end obj.encodedSignals{i} = binStream; fprintf('信号%d: 编码后长度=%d, 填充位=%d\n', i, length(binStream), padding); end end function [binStream, padding] = int_to_bin(~, values, numBits) % 将整数数组转换为二进制位流 numValues = numel(values); totalBits = numValues * numBits; binStream = false(1, totalBits); for i = 1:numValues val = uint32(values(i)); startIdx = (i-1)*numBits + 1; for bitPos = 1:numBits bit = bitget(val, bitPos, 'uint32'); binStream(startIdx + numBits - bitPos) = (bit == 1); end end padding = 0; end function values = bin_to_int(~, binStream, numBits) % 将二进制位流转换回整数数组 numValues = floor(length(binStream) / numBits); padding = length(binStream) - numValues * numBits; if padding > 0 binStream = binStream(1:end-padding); end values = zeros(1, numValues); for i = 1:numValues startIdx = (i-1)*numBits + 1; endIdx = startIdx + numBits - 1; segment = binStream(startIdx:endIdx); % 将二进制段转换为整数 val = 0; for j = 1:numBits val = val * 2 + segment(j); end values(i) = val; end end function obj = decodeSignals(obj) totalSamples = size(obj.demodulatedSignals, 2); obj.decodedSignals = zeros(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals binStream = obj.demodulatedSignals(i, :); switch obj.encodingParams.type case 'PCM' quantized = obj.bin_to_int(binStream, obj.encodingParams.quantBits); decoded = obj.pcm_decode(quantized, obj.encodingParams.quantBits); obj.decodedSignals(i, 1:length(decoded)) = decoded; case 'DPCM' quantized = obj.bin_to_int(binStream, obj.encodingParams.quantBits); decoded = obj.dpcm_decode(quantized, obj.encodingParams.quantBits, obj.encodingParams.step); obj.decodedSignals(i, 1:length(decoded)) = decoded; case 'DM' decoded = obj.dm_decode(binStream, obj.encodingParams.step); obj.decodedSignals(i, 1:length(decoded)) = decoded; orig = obj.originalSignals(i, 1:size(obj.decodedSignals, 2)); obj.quantizationError(i) = mean((orig - decoded).^2); end % 长度对齐 decodedLength = length(decoded); if decodedLength < totalSamples obj.decodedSignals(i, decodedLength+1:end) = 0; end end end function obj = modulateSignals(obj) obj.modulatedSignals = cell(obj.params.numSignals, 1); for i = 1:obj.params.numSignals binStream = obj.encodedSignals{i}; modulationType = obj.modulationParams.signalModulations{i}; switch modulationType case 'None' obj.modulatedSignals{i} = binStream; case 'BPSK' obj.modulatedSignals{i} = 2*double(binStream) - 1; case 'QPSK' % 重组为复数符号 symbols = reshape(binStream, 2, [])'; I = 2*double(symbols(:,1)) - 1; Q = 2*double(symbols(:,2)) - 1; obj.modulatedSignals{i} = (I + 1i*Q)/sqrt(2); case '16QAM' symbols = reshape(binStream, 4, [])'; I = 2*double(symbols(:,1)) + double(symbols(:,2)); Q = 2*double(symbols(:,3)) + double(symbols(:,4)); % 映射到星座点 I(I==0) = -3; I(I==1) = -1; I(I==2) = 1; I(I==3) = 3; Q(Q==0) = -3; Q(Q==1) = -1; Q(Q==2) = 1; Q(Q==3) = 3; obj.modulatedSignals{i} = (I + 1i*Q)/sqrt(10); otherwise error('未知的调制方式: %s', modulationType); end % 存储星座图数据 if any(strcmp(modulationType, {'BPSK', 'QPSK', '16QAM'})) points = obj.modulatedSignals{i}; obj.constellationPoints{i} = points(1:min(1000, end)); end end end function obj = demodulateSignals(obj) totalSamples = size(obj.demuxSignals{1}, 2); obj.demodulatedSignals = false(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals modSignal = obj.demuxSignals{i}; modulationType = obj.modulationParams.signalModulations{i}; switch modulationType case 'None' bits = real(modSignal) > 0.5; case 'BPSK' bits = real(modSignal) > 0; case 'QPSK' I = real(modSignal) > 0; Q = imag(modSignal) > 0; bits = [I, Q]'; bits = bits(:)'; case '16QAM' symbols = modSignal * sqrt(10); I = real(symbols); Q = imag(symbols); % 解调I通道 bitsI1 = I > 0; bitsI2 = abs(I) > 2; % 解调Q通道 bitsQ1 = Q > 0; bitsQ2 = abs(Q) > 2; bits = [bitsI1, bitsI2, bitsQ1, bitsQ2]'; bits = bits(:)'; end % 移除填充位 padding = obj.paddingInfo.encoded(i); if padding > 0 bits = bits(1:end-padding); end % 确保输出长度匹配 endIdx = min(length(bits), totalSamples); obj.demodulatedSignals(i, 1:endIdx) = bits(1:endIdx); % 长度对齐 if endIdx < totalSamples obj.demodulatedSignals(i, endIdx+1:end) = false; end end end function obj = allocateSlots(obj) if obj.params.totalSlots < obj.params.numSignals error('总时隙数(%d)小于信号数(%d)', ... obj.params.totalSlots, obj.params.numSignals); end obj.allocatedSlots = zeros(1, obj.params.numSignals); obj.slotAssignment = zeros(obj.params.numSignals, obj.params.totalSlots); switch obj.params.strategy case 'fixed' baseSlots = floor(obj.params.totalSlots / obj.params.numSignals); obj.allocatedSlots = baseSlots * ones(1, obj.params.numSignals); remainder = obj.params.totalSlots - sum(obj.allocatedSlots); [~, sortedIdx] = sort(obj.params.priorities, 'descend'); for i = 1:remainder if i <= obj.params.numSignals obj.allocatedSlots(sortedIdx(i)) = obj.allocatedSlots(sortedIdx(i)) + 1; end end case 'priority' minSlots = ones(1, obj.params.numSignals); availableSlots = obj.params.totalSlots - sum(minSlots); if availableSlots < 0 error('总时隙数(%d)不足以分配', obj.params.totalSlots); end weights = obj.params.priorities / sum(obj.params.priorities); extraSlots = floor(availableSlots * weights); obj.allocatedSlots = minSlots + extraSlots; remainder = availableSlots - sum(extraSlots); [~, idx] = sort(obj.params.priorities, 'descend'); for i = 1:remainder obj.allocatedSlots(idx(i)) = obj.allocatedSlots(idx(i)) + 1; end otherwise error('未知策略: %s', obj.params.strategy); end % 验证分配 if sum(obj.allocatedSlots) ~= obj.params.totalSlots error('时隙分配错误: 分配数(%d) != 总数(%d)', ... sum(obj.allocatedSlots), obj.params.totalSlots); end % 构建分配矩阵 current_slot = 1; for i = 1:obj.params.numSignals slotsToAssign = obj.allocatedSlots(i); for j = 1:slotsToAssign if current_slot > obj.params.totalSlots break; end obj.slotAssignment(i, current_slot) = 1; current_slot = current_slot + 1; end end % 打印分配结果 fprintf('时隙分配结果:\n'); for i = 1:obj.params.numSignals fprintf(' 信号 %d (%s): %d 个时隙 (优先级: %.2f, 调制: %s)\n', ... i, obj.signalInfo{i}, obj.allocatedSlots(i), ... obj.params.priorities(i), obj.modulationParams.signalModulations{i}); end end function obj = multiplex(obj) totalSamples = obj.params.fs * obj.params.duration; headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; frameSizeTotal = dataSizePerFrame + headerLen; numFrames = ceil(totalSamples / dataSizePerFrame); % 初始化复数数组 obj.tdmSignal = complex(zeros(1, numFrames * frameSizeTotal)); obj.frameHeaders = zeros(1, numFrames); for frameIdx = 1:numFrames frameStartTotal = (frameIdx-1) * frameSizeTotal + 1; headerEnd = frameStartTotal + headerLen - 1; % 帧头转换为复数存储 obj.tdmSignal(frameStartTotal:headerEnd) = complex(headerBin, 0); obj.frameHeaders(frameIdx) = frameStartTotal; dataStart = headerEnd + 1; for slot = 1:obj.params.totalSlots slotStart = dataStart + (slot-1) * slotSamples; slotEnd = slotStart + slotSamples - 1; if slotEnd > length(obj.tdmSignal) break; end signalIdx = find(obj.slotAssignment(:, slot) == 1, 1); if ~isempty(signalIdx) % 计算信号位置 signalStart = (frameIdx-1) * dataSizePerFrame + (slot-1) * slotSamples + 1; signalEnd = min(signalStart + slotSamples - 1, length(obj.modulatedSignals{signalIdx})); % 获取信号片段 signalSegment = obj.modulatedSignals{signalIdx}(signalStart:signalEnd); % 处理CRC if obj.frameConfig.useCRC crcLen = 16; if length(signalSegment) > crcLen dataPart = signalSegment(1:end-crcLen); crc = obj.calculateCRC(dataPart); if isreal(crc) crc = complex(crc, 0); end signalSegment = [dataPart, crc]; end end % 长度匹配处理 if length(signalSegment) < slotSamples padding = complex(zeros(1, slotSamples - length(signalSegment))); signalSegment = [signalSegment, padding]; elseif length(signalSegment) > slotSamples signalSegment = signalSegment(1:slotSamples); end % 插入时隙 obj.tdmSignal(slotStart:slotEnd) = signalSegment; else obj.tdmSignal(slotStart:slotEnd) = complex(zeros(1, slotSamples)); end end end % 裁剪多余部分 obj.tdmSignal = obj.tdmSignal(1:min(numFrames * frameSizeTotal, totalSamples)); end function obj = transmit(obj) signal_power = mean(abs(obj.tdmSignal).^2); if signal_power == 0 signal_power = 1e-10; end linear_snr = 10^(obj.params.snrDb/10); noise_power = signal_power / linear_snr; % 根据信号类型添加噪声 if ~isreal(obj.tdmSignal) noise = sqrt(noise_power/2) * (randn(size(obj.tdmSignal)) + 1i*randn(size(obj.tdmSignal))); else noise = sqrt(noise_power) * randn(size(obj.tdmSignal)); end obj.receivedSignal = obj.tdmSignal + noise; end function obj = frameSynchronization(obj) headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; frameSizeTotal = dataSizePerFrame + headerLen; % 创建复数参考帧头 if isreal(obj.receivedSignal) headerRef = complex(headerBin, 0); else headerRef = complex(headerBin, zeros(size(headerBin))); end % 复数互相关计算 correlation = conv(obj.receivedSignal, conj(fliplr(headerRef)), 'same'); correlationMag = abs(correlation); % 使用稳健的峰值检测 [~, locs] = findpeaks(correlationMag, 'MinPeakHeight', 0.7*max(correlationMag), ... 'MinPeakDistance', round(frameSizeTotal*0.8)); % 验证峰值间距 detectedHeaders = []; for i = 1:length(locs) if i == 1 || (locs(i) - locs(i-1)) > 0.8 * frameSizeTotal detectedHeaders = [detectedHeaders, locs(i)]; end end obj.frameHeaders = detectedHeaders; fprintf('检测到 %d 个有效帧头\n', length(detectedHeaders)); end function obj = demultiplex(obj) totalSamples = obj.params.fs * obj.params.duration; headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; obj.demuxSignals = cell(1, obj.params.numSignals); for i = 1:obj.params.numSignals obj.demuxSignals{i} = complex(zeros(1, totalSamples)); end obj.crcErrors.total = 0; obj.crcErrors.perSignal = zeros(1, obj.params.numSignals); for frameIdx = 1:length(obj.frameHeaders) headerStart = obj.frameHeaders(frameIdx); if headerStart + headerLen + dataSizePerFrame - 1 > length(obj.receivedSignal) continue; end frameData = obj.receivedSignal(headerStart+headerLen:headerStart+headerLen+dataSizePerFrame-1); for slot = 1:obj.params.totalSlots slotStart = (slot-1)*slotSamples + 1; slotEnd = slotStart + slotSamples - 1; if slotEnd > length(frameData) continue; end slotData = frameData(slotStart:slotEnd); signalIdx = find(obj.slotAssignment(:, slot) == 1, 1); if ~isempty(signalIdx) % CRC处理 if obj.frameConfig.useCRC crcLen = 16; if length(slotData) > crcLen data = slotData(1:end-crcLen); receivedCRC = slotData(end-crcLen+1:end); calculatedCRC = obj.calculateCRC(data); if ~isequal(real(receivedCRC), real(calculatedCRC)) obj.crcErrors.total = obj.crcErrors.total + 1; obj.crcErrors.perSignal(signalIdx) = obj.crcErrors.perSignal(signalIdx) + 1; end end else data = slotData; end % 计算信号位置 signalStart = (frameIdx-1)*dataSizePerFrame + (slot-1)*slotSamples + 1; signalEnd = signalStart + length(data) - 1; % 确保不越界 if signalEnd > totalSamples signalEnd = totalSamples; data = data(1:(signalEnd - signalStart + 1)); end % 存储解复用数据 obj.demuxSignals{signalIdx}(signalStart:signalEnd) = data; end end end end function obj = synchronize(obj) totalSamples = obj.params.fs * obj.params.duration; t = linspace(0, obj.params.duration, totalSamples); obj.syncedSignals = zeros(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals decodedSignal = obj.decodedSignals(i, :); validIdx = find(~isnan(decodedSignal) & ~isinf(decodedSignal)); if isempty(validIdx) obj.syncedSignals(i, :) = 0; continue; end drift = obj.params.clockDrift(i); shifted_t = t * (1 + drift); % 确保时间向量不超出范围 max_time = max(shifted_t); if max_time > obj.params.duration shifted_t = shifted_t(shifted_t <= obj.params.duration); if numel(shifted_t) < totalSamples shifted_t = [shifted_t, linspace(shifted_t(end), obj.params.duration, ... totalSamples - numel(shifted_t))]; end end if numel(validIdx) > 10 obj.syncedSignals(i, :) = interp1(... t(validIdx), decodedSignal(validIdx), shifted_t, 'pchip', 0); else obj.syncedSignals(i, :) = interp1(... t(validIdx), decodedSignal(validIdx), shifted_t, 'nearest', 0); end end end function obj = evaluatePerformance(obj) obj.performance = struct(... 'snr', zeros(1, obj.params.numSignals), ... 'sdr', zeros(1, obj.params.numSignals), ... 'corr', zeros(1, obj.params.numSignals), ... 'ber', zeros(1, obj.params.numSignals), ... 'mse', zeros(1, obj.params.numSignals)); for i = 1:obj.params.numSignals % 安全长度处理 orig_signal = obj.originalSignals(i, :); synced_signal = obj.syncedSignals(i, :); % 获取最小公共长度 minLen = min(length(orig_signal), length(synced_signal)); if minLen == 0 fprintf('信号 %d: 无有效数据\n', i); continue; end % 截取公共长度段 orig_segment = orig_signal(1:minLen); synced_segment = synced_signal(1:minLen); % 计算MSE mse = mean((orig_segment - synced_segment).^2); obj.performance.mse(i) = mse; % 计算SNR signal_power = mean(orig_segment.^2); if mse > 0 obj.performance.snr(i) = 10 * log10(signal_power / mse); else obj.performance.snr(i) = Inf; end % 计算SDR distortion = obj.quantizationError(i); if distortion > 0 obj.performance.sdr(i) = 10 * log10(signal_power / distortion); else obj.performance.sdr(i) = Inf; end % 计算相关系数 if minLen > 1 obj.performance.corr(i) = corr(orig_segment(:), synced_segment(:)); else obj.performance.corr(i) = NaN; end % BER计算 modType = obj.modulationParams.signalModulations{i}; if any(strcmp(modType, {'BPSK', 'QPSK', '16QAM'})) orig_bits = obj.encodedSignals{i}; demod_bits = obj.demodulatedSignals(i, :); % 确保长度一致 minLenBits = min(length(orig_bits), length(demod_bits)); if minLenBits == 0 obj.performance.ber(i) = NaN; else orig_seg = orig_bits(1:minLenBits); demod_seg = demod_bits(1:minLenBits); bit_errors = sum(orig_seg ~= demod_seg); obj.performance.ber(i) = bit_errors / minLenBits; end else obj.performance.ber(i) = NaN; end fprintf('信号 %d (%s): MSE=%.4f, SNR=%.2f dB, SDR=%.2f dB, BER=%.4f, Corr=%.4f\n', ... i, obj.signalInfo{i}, mse, obj.performance.snr(i), ... obj.performance.sdr(i), obj.performance.ber(i), obj.performance.corr(i)); end end function bin = str2bin(~, str) % 将字符串转换为二进制数组 dec = uint8(str); binStr = dec2bin(dec, 8)'; bin = double(binStr(:)') - 48; end function crc = calculateCRC(~, data) % 支持复数数据 if ~isreal(data) realData = [real(data); imag(data)]; data = realData(:)'; end % 简化的16位CRC计算 poly = [1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1]; crc = zeros(1, 16); for i = 1:length(data) bit = data(i) > 0; msb = crc(1); crc(1:end-1) = crc(2:end); crc(end) = 0; if xor(msb, bit) crc = xor(crc, poly(2:end)); end end crc = complex(crc, 0); end % ================== 编码核心方法 ================== function [quantized, quantErr] = pcm_encode(~, signal, quantBits) maxVal = max(abs(signal)); quantLevels = 2^quantBits; quantStep = 2*maxVal/(quantLevels-1); minVal = -maxVal; quantized = round((signal - minVal)/quantStep); quantized = max(0, min(quantized, quantLevels-1)); quantErr = signal - (quantized*quantStep + minVal); end function decoded = pcm_decode(~, quantized, quantBits) maxVal = max(quantized) * (2^quantBits-1)/2^quantBits; minVal = -maxVal; quantStep = 2*maxVal/(2^quantBits-1); decoded = quantized*quantStep + minVal; end function [encoded, quantErr] = dpcm_encode(obj, signal, quantBits, stepSize) n = length(signal); encoded = zeros(1, n); quantErr = zeros(1, n); predictor = 0; for i = 1:n error = signal(i) - predictor; quantizedError = obj.quantize(error, quantBits, stepSize); encoded(i) = quantizedError; predictor = predictor + quantizedError; quantErr(i) = error - quantizedError; end end function decoded = dpcm_decode(~, encoded, ~, ~) n = length(encoded); decoded = zeros(1, n); predictor = 0; for i = 1:n decoded(i) = predictor + encoded(i); predictor = decoded(i); end end function encoded = dm_encode(~, signal, stepSize) n = length(signal); encoded = false(1, n); integrator = 0; for i = 1:n if signal(i) > integrator encoded(i) = true; integrator = integrator + stepSize; else encoded(i) = false; integrator = integrator - stepSize; end end end function decoded = dm_decode(~, encoded, stepSize) n = length(encoded); decoded = zeros(1, n); integrator = 0; for i = 1:n if encoded(i) integrator = integrator + stepSize; else integrator = integrator - stepSize; end decoded(i) = integrator; end end function quantized = quantize(~, value, quantBits, stepSize) levels = 2^quantBits; maxVal = (levels-1) * stepSize / 2; clipped = max(min(value, maxVal), -maxVal); quantized = round(clipped/stepSize) * stepSize; end % ==== 辅助方法:获取调制方式对应的符号位数 ==== function bits = getBitsPerSymbol(~, modType) switch modType case {'BPSK', 'None'} bits = 1; case 'QPSK' bits = 2; case '16QAM' bits = 4; otherwise bits = 1; end end end
end
% 辅助函数
function out = ifelse(condition, true_val, false_val)
if condition
out = true_val;
else
out = false_val;
end
end