145 lines
6.7 KiB
Matlab
145 lines
6.7 KiB
Matlab
function fig = visualize_multi_tx_waveform(t, Timing, fc, f_start, Slope, tx_mask, TotalNumChirps, mimoMode, NumTx)
|
|
fig = figure('Name', 'Multi-Chirp & MIMO Modulation', 'Position', [150, 150, 1100, 750]);
|
|
|
|
T_chirp = Timing.IdleTime + Timing.RampEndTime;
|
|
NumChirpsToPlot = min(TotalNumChirps, 4);
|
|
|
|
plot_idx = (t <= NumChirpsToPlot * T_chirp);
|
|
t_plot = t(plot_idx);
|
|
tx_mask_plot = tx_mask(plot_idx);
|
|
|
|
t_mod = mod(t_plot, T_chirp);
|
|
t_ramp = t_mod - Timing.IdleTime;
|
|
|
|
inst_freq_theoretical = f_start + Slope * t_ramp;
|
|
inst_freq_masked = inst_freq_theoretical;
|
|
inst_freq_masked(tx_mask_plot == 0) = NaN;
|
|
|
|
% =========================================================
|
|
% [Subplot 1] 상단: 시간에 따른 주파수 파형
|
|
% =========================================================
|
|
subplot(2, 1, 1);
|
|
|
|
y_min = (f_start / 1e9) - 0.25;
|
|
y_max = (f_start / 1e9) + (Slope * Timing.RampEndTime / 1e9) + 0.1;
|
|
|
|
plot(t_plot * 1e6, inst_freq_masked / 1e9, 'b', 'LineWidth', 2);
|
|
grid on; hold on;
|
|
|
|
title(sprintf('Continuous Multi-Chirp Sequence (Showing %d of %d Chirps)', NumChirpsToPlot, TotalNumChirps), 'FontSize', 12);
|
|
ylabel('Absolute Frequency (GHz)', 'FontSize', 11);
|
|
|
|
ylim([y_min, y_max]);
|
|
if ~isempty(t_plot)
|
|
xlim([0, max(t_plot)*1e6]);
|
|
else
|
|
xlim([0, 1]); % fallback range when no data
|
|
end
|
|
|
|
f_valid_start = f_start + (Slope * Timing.AdcStartTime);
|
|
f_valid_end = f_start + (Slope * (Timing.AdcStartTime + Timing.AdcSampTime));
|
|
valid_bandwidth = f_valid_end - f_valid_start;
|
|
|
|
info_str = {
|
|
sprintf('▶ Valid Start Freq : %.4f GHz', f_valid_start / 1e9), ...
|
|
sprintf('▶ Center Freq : %.4f GHz', fc / 1e9), ...
|
|
sprintf('▶ Valid End Freq : %.4f GHz', f_valid_end / 1e9), ...
|
|
sprintf('▶ Transmit Bandwidth : %.4f GHz', valid_bandwidth / 1e9), ...
|
|
sprintf('▶ Total Gen Chirps : %d', TotalNumChirps)
|
|
};
|
|
text(0.02, 0.96, info_str, 'Units', 'normalized', 'FontSize', 10, 'FontWeight', 'bold', 'BackgroundColor', [1 1 1 0.85], 'EdgeColor', 'k', 'VerticalAlignment', 'top', 'Margin', 5);
|
|
|
|
guide_line_args = {'Color', [0 0 0.5], 'LineStyle', '--', 'LineWidth', 1};
|
|
for i = 0:NumChirpsToPlot
|
|
plot([i * T_chirp * 1e6, i * T_chirp * 1e6], [y_min, y_max], guide_line_args{:});
|
|
end
|
|
|
|
draw_dim_arrow = @(x1, x2, y, label_str) ...
|
|
[plot([x1, x2], [y, y], 'k-', 'LineWidth', 1.2), ...
|
|
fill([x1, x1 + min(0.6, (x2-x1)*0.35), x1 + min(0.6, (x2-x1)*0.35)], [y, y + 0.015, y - 0.015], 'k', 'EdgeColor', 'none'), ...
|
|
fill([x2, x2 - min(0.6, (x2-x1)*0.35), x2 - min(0.6, (x2-x1)*0.35)], [y, y + 0.015, y - 0.015], 'k', 'EdgeColor', 'none'), ...
|
|
text((x1+x2)/2, y + 0.03, label_str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom', 'FontSize', 9, 'FontWeight', 'bold', 'BackgroundColor', 'w', 'EdgeColor', 'k')];
|
|
|
|
y_pri = y_min + 0.08;
|
|
pri_us = T_chirp * 1e6;
|
|
prf_khz = (1 / T_chirp) / 1e3;
|
|
pri_prf_label = sprintf('PRI: %.1f \\mus\nPRF: %.1f kHz', pri_us, prf_khz);
|
|
draw_dim_arrow(0, pri_us, y_pri, pri_prf_label);
|
|
hold off;
|
|
|
|
% =========================================================
|
|
% [Subplot 2] 하단: MIMO 방식 통합형 Active TX & Phase 맵
|
|
% =========================================================
|
|
subplot(2, 1, 2);
|
|
hold on; grid on;
|
|
|
|
% --- [핵심 추가]: TX 개수에 맞춘 고유 색상 팔레트 생성 ---
|
|
% lines() 함수는 구분이 명확하고 세련된 색상 배열을 반환합니다.
|
|
tx_colors = lines(NumTx);
|
|
|
|
for tx = 1:NumTx
|
|
plot([0, NumChirpsToPlot * T_chirp * 1e6], [tx, tx], ':', 'Color', [0.8 0.8 0.8], 'HandleVisibility', 'off');
|
|
end
|
|
|
|
for i = 0 : NumChirpsToPlot - 1
|
|
t_center_us = (i + 0.5) * T_chirp * 1e6;
|
|
|
|
if strcmpi(mimoMode, 'TDM')
|
|
active_tx_list = mod(i, NumTx) + 1;
|
|
elseif strcmpi(mimoMode, 'DDMA')
|
|
active_tx_list = 1:NumTx;
|
|
else
|
|
active_tx_list = 1;
|
|
end
|
|
|
|
for tx = 1:NumTx
|
|
% 현재 처리 중인 TX 안테나의 고유 색상 추출
|
|
current_color = tx_colors(tx, :);
|
|
|
|
if ismember(tx, active_tx_list)
|
|
if strcmpi(mimoMode, 'DDMA')
|
|
phase_rad = 2 * pi * (tx - 1) * i / NumTx;
|
|
phase_deg = mod(rad2deg(phase_rad), 360);
|
|
else
|
|
phase_deg = 0;
|
|
end
|
|
|
|
% 활성화: 해당 안테나의 색상으로 꽉 채워진 원
|
|
plot(t_center_us, tx, 'o', 'MarkerSize', 12, 'MarkerFaceColor', current_color, 'MarkerEdgeColor', current_color, 'HandleVisibility', 'off');
|
|
|
|
text_offset_us = T_chirp * 1e6 * 0.08;
|
|
text(t_center_us + text_offset_us, tx, sprintf('%d^\\circ', round(phase_deg)), ...
|
|
'VerticalAlignment', 'middle', 'HorizontalAlignment', 'left', ...
|
|
'FontSize', 9, 'FontWeight', 'bold', 'Color', current_color);
|
|
else
|
|
% 비활성화: 해당 안테나의 색상 테두리를 가진 비워진 원
|
|
plot(t_center_us, tx, 'o', 'MarkerSize', 12, 'MarkerFaceColor', 'w', 'MarkerEdgeColor', current_color, 'HandleVisibility', 'off');
|
|
end
|
|
end
|
|
end
|
|
|
|
title(sprintf('%s Active TX Antenna & Phase Map', upper(mimoMode)), 'FontSize', 12);
|
|
ylabel('TX Antenna', 'FontSize', 11);
|
|
|
|
yticks(1:NumTx);
|
|
% Y축 라벨에도 텍스트 색상을 입혀 직관성 극대화 (선택 사항)
|
|
% yticklabels(arrayfun(@(x) sprintf('\\color[rgb]{%f,%f,%f}TX %d', tx_colors(x,1), tx_colors(x,2), tx_colors(x,3), x), 1:NumTx, 'UniformOutput', false));
|
|
yticklabels(arrayfun(@(x) sprintf('TX %d', x), 1:NumTx, 'UniformOutput', false));
|
|
ylim([0.5, NumTx + 0.5]);
|
|
|
|
% --- [범례 수정]: 중립적인 색상(다크 그레이)으로 상태의 개념만 표시 ---
|
|
neutral_color = [0.3 0.3 0.3];
|
|
h_on = plot(NaN, NaN, 'o', 'MarkerSize', 10, 'MarkerFaceColor', neutral_color, 'MarkerEdgeColor', neutral_color, 'DisplayName', 'Active');
|
|
h_off = plot(NaN, NaN, 'o', 'MarkerSize', 10, 'MarkerFaceColor', 'w', 'MarkerEdgeColor', neutral_color, 'DisplayName', 'Inactive');
|
|
legend([h_on, h_off], 'Location', 'best', 'FontSize', 10, 'Box', 'on');
|
|
|
|
xlabel('Time (\mus)', 'FontSize', 11);
|
|
xlim([0, max(t_plot)*1e6]);
|
|
|
|
y_lims_bottom = ylim;
|
|
for i = 0:NumChirpsToPlot
|
|
plot([i * T_chirp * 1e6, i * T_chirp * 1e6], y_lims_bottom, guide_line_args{:}, 'HandleVisibility', 'off');
|
|
end
|
|
|
|
hold off;
|
|
end |