Files
gnss-sdr/utils/matlab/libs/load_f_error_dump.m
T
joebre 5c24058459 Add Octave tooling to load, plot and simulate f_error dump scans
load_f_error_dump/find_f_error_scans/plot_f_error_scan (utils/matlab/libs)
read and visualize the per-bin CSV written by the tracking f_error_dump
diagnostic, and plot_all_f_error_scans (utils/matlab) batches
plot_f_error_scan over every scan in a dump, optionally saving PNGs.
f_error_sim (utils/matlab/libs) is a self-contained Monte Carlo
simulation of the same bin-scan/CN0-estimator logic, useful for sizing
f_error_step_num/f_error_accumulation/f_error_doppler_step without a
live capture.
2026-09-30 07:42:39 +02:00

79 lines
3.2 KiB
Matlab

% load_f_error_dump.m
%
% Loads the CSV written by dll_pll_veml_tracking's state-5 (frequency error
% reduction) diagnostic -- see Dll_Pll_Conf::f_error_dump_filename -- into an
% Octave struct array, one element per scan (one satellite's pass through
% state 5). Each row of the CSV is one Doppler bin; this groups rows by
% scan_id.
%
% CSV columns (header row is skipped):
% scan_id, prn, system_char, channel, cn0_dBHz, selected_doppler_hz,
% selected_bin, bin_index, doppler_hz, power
%
% Usage:
% scans = load_f_error_dump(); % default: ./f_error_dump.csv
% scans = load_f_error_dump('/path/to/dump.csv');
% load_f_error_dump(); % no output arg: also prints a summary table
%
% Each scans(i) has fields:
% scan_id, prn, system_char, channel, cn0_dBHz, selected_doppler_hz, selected_bin,
% doppler_hz (row vector, increasing Doppler order), power (row vector, same order)
%
% See also: find_f_error_scans, plot_f_error_scan
% -------------------------------------------------------------------------
%
% GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
% This file is part of GNSS-SDR.
%
% SPDX-FileCopyrightText: Joel Brenner, 2026. joel.brenner(at)saphyrion.ch
% SPDX-License-Identifier: GPL-3.0-or-later
%
% -------------------------------------------------------------------------
function scans = load_f_error_dump(filename)
if nargin < 1 || isempty(filename)
filename = 'f_error_dump.csv';
end
raw = csvread(filename, 1, 0); % skip header row
if isempty(raw)
error('load_f_error_dump: no data rows found in %s', filename);
end
scan_id_col = raw(:, 1);
unique_ids = unique(scan_id_col);
n = numel(unique_ids);
scans = struct('scan_id', {}, 'prn', {}, 'system_char', {}, 'channel', {}, 'cn0_dBHz', {}, ...
'selected_doppler_hz', {}, 'selected_bin', {}, ...
'doppler_hz', {}, 'power', {});
for i = 1:n
rows = raw(scan_id_col == unique_ids(i), :);
[~, order] = sort(rows(:, 8)); % bin_index, defensive (writer already emits increasing Doppler order)
rows = rows(order, :);
scans(i).scan_id = rows(1, 1);
scans(i).prn = rows(1, 2);
scans(i).system_char = rows(1, 3);
scans(i).channel = rows(1, 4);
scans(i).cn0_dBHz = rows(1, 5);
scans(i).selected_doppler_hz = rows(1, 6);
scans(i).selected_bin = rows(1, 7);
scans(i).doppler_hz = rows(:, 9)';
scans(i).power = rows(:, 10)';
end
if nargout == 0
printf('%6s %5s %4s %9s %14s %8s %6s\n', 'scan', 'PRN', 'ch', 'CN0[dBHz]', 'selDoppler[Hz]', 'nBins', '');
for i = 1:n
printf('%6d %5d %4d %9.2f %14.2f %8d\n', scans(i).scan_id, scans(i).prn, scans(i).channel, ...
scans(i).cn0_dBHz, scans(i).selected_doppler_hz, numel(scans(i).doppler_hz));
end
printf('\n%d scans loaded from %s\n', n, filename);
printf('PRNs present: %s\n', mat2str(unique([scans.prn])));
clear scans; % avoid echoing the struct array to the console when called as a script
end
end