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