3 changed files with 68 additions and 21 deletions
+8 -5
View File
@@ -22,8 +22,10 @@ function [adc_raw_data, adc_combined] = apply_lna_and_mixer(RxOut, TxOut, RadarP
phase_noise_cfg = struct();
if isfield(RadarParams.Waveform.nonideal, 'phaseNoise')
phase_noise_cfg = RadarParams.Waveform.nonideal.phaseNoise;
if isfield(phase_noise_cfg,'enabled') && phase_noise_cfg.enabled && ...
isfield(phase_noise_cfg,'offset_Hz') && isfield(phase_noise_cfg,'level_dBc_Hz')
has_offset = isfield(phase_noise_cfg,'offset_Hz') && ~isempty(phase_noise_cfg.offset_Hz);
has_level = isfield(phase_noise_cfg,'level_dBc_Hz') && ~isempty(phase_noise_cfg.level_dBc_Hz);
same_length = has_offset && has_level && (numel(phase_noise_cfg.offset_Hz) == numel(phase_noise_cfg.level_dBc_Hz));
if same_length
use_datasheet_phase_noise = true;
end
end
@@ -31,6 +33,7 @@ function [adc_raw_data, adc_combined] = apply_lna_and_mixer(RxOut, TxOut, RadarP
NumTx = RadarParams.Antenna.NumTx;
rxPathGain_dB = RadarParams.Rxpath.rxPathGain_dB;
system_NF_dB = RadarParams.Rxpath.system_NF_dB;
impedance_ohm = 50; % ( 50)
PA_Profile = RadarParams.RFOutput.PA_Profile;
SpurParams = RadarParams.SpurParams;
enable_spur = true;
@@ -57,8 +60,8 @@ function [adc_raw_data, adc_combined] = apply_lna_and_mixer(RxOut, TxOut, RadarP
P_inst_dBm = interp1(PA_Profile(:,1), PA_Profile(:,2), f_inst, 'linear', 'extrap');
end
% dBm -> Watt -> (V) (50 )
Vtx_inst = sqrt(10.^((P_inst_dBm - 30) / 10) * 50);
% dBm -> Watt -> (V) ( )
Vtx_inst = sqrt(10.^((P_inst_dBm - 30) / 10) * impedance_ohm);
% --- 2. ---
T_ref = RadarParams.Basic.T0;
@@ -69,7 +72,7 @@ function [adc_raw_data, adc_combined] = apply_lna_and_mixer(RxOut, TxOut, RadarP
% ADC
P_noise_total_W = P_noise_floor_W * system_NF_lin * rxPathGain_lin;
sigma_n = sqrt(P_noise_total_W * 50);
sigma_n = sqrt(P_noise_total_W * impedance_ohm);
% --- MIMO TX ---
% TDM: TX만
@@ -13,13 +13,34 @@ function fig = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target
% :
% - fig: figure
if ~isfield(RadarParams, 'SP') || ~isfield(RadarParams.SP, 'RDM') || ...
~isfield(RadarParams.SP.RDM, 'window_range') || ~isfield(RadarParams.SP.RDM, 'window_doppler')
error('RadarParams.SP.RDM.window_range / window_doppler .');
end
win_r = RadarParams.SP.RDM.window_range;
win_d = RadarParams.SP.RDM.window_doppler;
normal_factor = RadarParams.Rxpath.fc_lpf * RadarParams.Waveform.PRF * sum(win_r.^2) * sum(win_d.^2);
if ~isfield(RadarParams, 'Rxpath') || ~isfield(RadarParams.Rxpath, 'load_impedance_ohm')
error('RadarParams.Rxpath.load_impedance_ohm .');
end
load_impedance_ohm = RadarParams.Rxpath.load_impedance_ohm;
psd2d_w_hz2 = (abs(target_rd_map).^2) / (load_impedance_ohm * max(normal_factor, eps));
rbw_range_hz = RadarParams.Waveform.fs_adc * sum(win_r.^2) / max(eps, (sum(win_r)^2));
rbw_doppler_hz = RadarParams.Waveform.PRF * sum(win_d.^2) / max(eps, (sum(win_d)^2));
rd_map_dbm_bin = 10*log10(max(psd2d_w_hz2, realmin) / 1e-3) + 10*log10(max(rbw_range_hz * rbw_doppler_hz, eps));
fig = figure('Name', '2D Range-Doppler Map');
imagesc(r_axis, v_axis, 20*log10(abs(target_rd_map)));
imagesc(r_axis, v_axis, rd_map_dbm_bin);
axis xy; % y축 ()
colorbar;
cb = colorbar;
cb.Label.String = 'Power (dBm/bin)';
xlabel('Range (m)');
ylabel('Velocity (m/s)');
title('Range-Doppler Map (Single Channel)');
title('Range-Doppler Map (dBm/bin)');
colormap(jet);
%
@@ -61,7 +82,6 @@ function fig = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target
ni = RadarParams.Waveform.nonideal;
enable_phase_noise = false;
enable_nonlinearity = false;
enable_datasheet_phase_noise = false;
if isfield(ni,'enable_phase_noise')
enable_phase_noise = logical(ni.enable_phase_noise);
@@ -69,12 +89,8 @@ function fig = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target
if isfield(ni,'enable_nonlinearity')
enable_nonlinearity = logical(ni.enable_nonlinearity);
end
if isfield(ni,'phaseNoise') && isstruct(ni.phaseNoise) && isfield(ni.phaseNoise,'enabled')
enable_datasheet_phase_noise = logical(ni.phaseNoise.enabled);
end
show_nonideal_overlay = show_nonideal_overlay && ...
(enable_phase_noise || enable_nonlinearity || enable_datasheet_phase_noise);
(enable_phase_noise || enable_nonlinearity);
end
% --- 2. LO/ADC ---
+35 -7
View File
@@ -42,12 +42,11 @@ RadarParams.Waveform.nonideal.pn_level = 0.05; % 위상노이즈
RadarParams.Waveform.nonideal.f_ripple = 300e3; %
RadarParams.Waveform.nonideal.peak_phase_error = 0.1; %
RadarParams.Waveform.nonideal.power_drop_edge = 0.8; %
RadarParams.Waveform.nonideal.enable_phase_noise = false; % phase noise on/off
RadarParams.Waveform.nonideal.enable_phase_noise = true; % phase noise on/off
RadarParams.Waveform.nonideal.enable_nonlinearity = false; % nonlinearity on/off
% Datasheet phase noise (: -89 dBc/Hz @ 1 MHz)
RadarParams.Waveform.nonideal.phaseNoise.offset_Hz = [1e6];
RadarParams.Waveform.nonideal.phaseNoise.level_dBc_Hz = [-89];
RadarParams.Waveform.nonideal.phaseNoise.enabled = false;
% 2-3) MIMO
RadarParams.Waveform.mimoMode = 'TDM'; % 'TDM' 'DDMA'
@@ -71,11 +70,11 @@ RadarParams.Antenna.TxPattern = build_antenna_patterns(RadarParams.Antenna.NumTx
RadarParams.Antenna.RxPattern = build_antenna_patterns(RadarParams.Antenna.NumRx, '2D', 14, 2, 40, 15, RadarParams.Antenna.rx_files);
% 5)
RadarParams.Target.R = [12, 80, 120]; % (m)
RadarParams.Target.v = [7, -5, 0]; % (m/s)
RadarParams.Target.rcs = [10, 5, 20]; % RCS (dBsm)
RadarParams.Target.az = [10, -10, 0]; % (deg)
RadarParams.Target.el = [0, 0, 5]; % (deg)
RadarParams.Target.R = [12]; % (m)
RadarParams.Target.v = [7]; % (m/s)
RadarParams.Target.rcs = [-10000]; % RCS (dBsm)
RadarParams.Target.az = [10]; % (deg)
RadarParams.Target.el = [0]; % (deg)
RadarParams.Target.NumTargets = length(RadarParams.Target.R);
% 6)
@@ -84,6 +83,7 @@ RadarParams.Rxpath.fc_lpf = 0.8*RadarParams.Waveform.fs_adc/2; % L
RadarParams.Rxpath.adc_bits = 12; % ADC
RadarParams.Rxpath.adc_v_full_scale = 2.0; % full-scale (Vp-p)
RadarParams.Rxpath.receiver_mode = 'Real'; % 'IQ' 'Real'
RadarParams.Rxpath.load_impedance_ohm = 50; % (Ohm)
RadarParams.Rxpath.rxPathGain_dB = 50; % RX (dB)
RadarParams.Rxpath.system_NF_dB = 15; % (dB)
@@ -104,6 +104,34 @@ RadarParams.SpurParams.enabled = false; % spur on/of
% 7)
RadarParams.SP.RDM.window_type_range = 'hann'; % Range FFT용
RadarParams.SP.RDM.window_type_doppler = 'chebwin'; % Doppler FFT용
num_samples_range = round(RadarParams.Waveform.fs_adc * RadarParams.Waveform.Timing.AdcSampTime);
num_chirps_doppler = RadarParams.Waveform.NumChirps;
if strcmpi(RadarParams.SP.RDM.window_type_range, 'none')
RadarParams.SP.RDM.window_range = ones(1, num_samples_range);
elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'hamming')
RadarParams.SP.RDM.window_range = hamming(num_samples_range)';
elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'blackman')
RadarParams.SP.RDM.window_range = blackman(num_samples_range)';
elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'chebwin')
RadarParams.SP.RDM.window_range = chebwin(num_samples_range, 60)';
else
RadarParams.SP.RDM.window_range = hann(num_samples_range)';
end
if strcmpi(RadarParams.SP.RDM.window_type_doppler, 'none')
RadarParams.SP.RDM.window_doppler = ones(1, num_chirps_doppler);
elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'hamming')
RadarParams.SP.RDM.window_doppler = hamming(num_chirps_doppler)';
elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'blackman')
RadarParams.SP.RDM.window_doppler = blackman(num_chirps_doppler)';
elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'hann')
RadarParams.SP.RDM.window_doppler = hann(num_chirps_doppler)';
else
RadarParams.SP.RDM.window_doppler = chebwin(num_chirps_doppler, 60)';
end
RadarParams.SP.CFAR.method = 'OS'; % 'CA' 'OS'
RadarParams.SP.CFAR.dimension = '2D'; % '1D' '2D'
RadarParams.SP.CFAR.axis = 'doppler'; % 1D일 : 'range' 'doppler'