Initial ARSS. Need to improve and add functions.

This commit is contained in:
2026-03-02 14:48:21 +09:00
commit 775668afdb
20 changed files with 1610 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
% chirpIdx , t와 fs
function tx_matrix = apply_mimo_mode(x_amp, t, Timing, NumTx, mimoMode, fs)
N_samples = length(x_amp);
tx_matrix = zeros(NumTx, N_samples);
T_chirp = Timing.IdleTime + Timing.RampEndTime;
SamplesPerChirp = round(T_chirp * fs);
% []: (1, 2, 3...)
chirp_indices = floor((0:N_samples-1) / SamplesPerChirp) + 1;
switch upper(mimoMode)
case 'TDM'
% 1,2,3,1,2,3
active_tx_seq = mod(chirp_indices - 1, NumTx) + 1;
for tx = 1:NumTx
%
tx_matrix(tx, :) = x_amp .* (active_tx_seq == tx);
end
case 'DDMA'
%
for tx = 1:NumTx
phase_shift_seq = 2 * pi * (tx - 1) * (chirp_indices - 1) / NumTx;
tx_matrix(tx, :) = x_amp .* exp(1j * phase_shift_seq);
end
otherwise
error(' MIMO . TDM DDMA를 .');
end
end
+26
View File
@@ -0,0 +1,26 @@
function [t, tx_mask] = generate_waveform_timing(RadarParams)
% RadarParams TX
% TX .
%
% :
% - RadarParams:
%
% :
% - t: ()
% - tx_mask: TX (0 1)
Timing = RadarParams.Waveform.Timing;
NumChirps = RadarParams.Waveform.NumChirps;
T_chirp = Timing.IdleTime + Timing.RampEndTime;
T_frame = T_chirp * NumChirps; %
fs = RadarParams.Waveform.fs_waveform;
N_samples = round(T_frame * fs);
% ( )
t = linspace(0, T_frame, N_samples);
% (t_mod) ( )
t_mod = mod(t, T_chirp);
% TX
tx_mask = zeros(1, N_samples);
tx_start_abs = Timing.IdleTime + Timing.TxStartTime;
tx_mask(t_mod >= tx_start_abs) = 1;
end
+25
View File
@@ -0,0 +1,25 @@
function TxOut = radiate_antenna(Target, TxPatternArray)
% : , TX
% : TxOut.G_tx_amp (, TX별 [NumTargets x NumTx])
NumTx = length(TxPatternArray);
NumTargets = Target.NumTargets;
TxOut.G_tx_amp = zeros(NumTargets, NumTx);
for k = 1:NumTargets
for tx = 1:NumTx
pat = TxPatternArray(tx);
%
if strcmpi(pat.Type, '2D')
g_dBi = interp2(pat.az_angles, pat.el_angles, pat.gain_dBi, Target.az(k), Target.el(k), 'linear', -20);
else
g_az = interp1(pat.az_angles, pat.gain_az_dBi, Target.az(k), 'linear', -20);
g_el = interp1(pat.el_angles, pat.gain_el_dBi, Target.el(k), 'linear', -20);
g_dBi = g_az + g_el - pat.max_gain_dBi;
end
% (sqrt(10^(G_dBi/10)))
TxOut.G_tx_amp(k, tx) = sqrt(10^(g_dBi/10));
end
end
end
+145
View File
@@ -0,0 +1,145 @@
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
+78
View File
@@ -0,0 +1,78 @@
function fig = visualize_tx_waveform(t, Timing, fc, f_start, Slope, tx_mask, peak_phase_error, f_ripple)
fig = figure('Name', 'FMCW Radar Timing & True RF Frequency', 'Position', [100, 100, 1100, 700]);
t_ramp = t - Timing.IdleTime;
%
inst_freq_theoretical = f_start + Slope * t_ramp;
freq_nonlin = peak_phase_error * f_ripple * cos(2 * pi * f_ripple * t_ramp);
inst_freq_theoretical = inst_freq_theoretical + freq_nonlin;
inst_freq_masked = inst_freq_theoretical;
inst_freq_masked(tx_mask == 0) = NaN;
% Y축
y_min = (f_start / 1e9) - 0.2;
y_max = (f_start / 1e9) + (Slope * Timing.RampEndTime / 1e9) + 0.1;
% --- [ ] ---
plot(t * 1e6, inst_freq_masked / 1e9, 'b', 'LineWidth', 2.5);
title(sprintf('Mathematical Instantaneous RF Frequency & HW Timing (Center fc = %.2f GHz)', fc/1e9), 'FontSize', 12);
xlabel('Time (\mus)', 'FontSize', 11); ylabel('Absolute Frequency (GHz)', 'FontSize', 11);
ylim([y_min, y_max]);
grid on; hold on;
% --- [ : ] ---
% ADC /
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(' Valid Bandwidth : %.4f GHz', valid_bandwidth / 1e9) %
};
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);
% --- [ ] ---
y_lims = ylim;
guide_line_args = {'Color', [0 0 0.5], 'LineStyle', '--', 'LineWidth', 1};
x_coords = [0, Timing.IdleTime, ...
(Timing.IdleTime + Timing.TxStartTime), ...
(Timing.IdleTime + Timing.AdcStartTime), ...
(Timing.IdleTime + Timing.AdcStartTime + Timing.AdcSampTime), ...
(Timing.IdleTime + Timing.RampEndTime)];
x_coords_us = x_coords * 1e6;
for i = 1:length(x_coords_us)
plot([x_coords_us(i), x_coords_us(i)], y_lims, guide_line_args{:});
end
% --- [ ] ---
draw_dim_arrow = @(x1, x2, y, name, val_us) ...
[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, sprintf('%s\n(%.1f \\mus)', name, val_us), 'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom', 'FontSize', 9, 'FontWeight', 'bold', 'BackgroundColor', 'w', 'EdgeColor', 'k')];
%
y1 = y_min + 0.05;
y2 = y_min + 0.18;
y3 = y_min + 0.31;
draw_dim_arrow(x_coords_us(1), x_coords_us(2), y1, 'Idle Time', Timing.IdleTime * 1e6);
draw_dim_arrow(x_coords_us(2), x_coords_us(3), y2, 'TX Start', Timing.TxStartTime * 1e6);
draw_dim_arrow(x_coords_us(2), x_coords_us(4), y3, 'ADC Delay', Timing.AdcStartTime * 1e6);
draw_dim_arrow(x_coords_us(4), x_coords_us(5), y2, 'ADC Sampling (Valid)', Timing.AdcSampTime * 1e6);
draw_dim_arrow(x_coords_us(5), x_coords_us(6), y1, 'Excess', Timing.ExcessTime * 1e6);
hold off;
end