function trackingPlotResults( pathName, fileName, settings, trackResults )

%==============================================================================%
%                                                                              %
%   plotTrackingResults( pathName, fileName, settings, trackResults )          %
%                                                                              %
%   Plot tracking results                                                      %
%   David S. De Lorenzo                                                        %
%   17 November 2005                                                           %
%                                                                              %
%==============================================================================%
%                       GPS Software Receiver in Matlab                        %
%     Copyright (c) 2003-2017 David S. De Lorenzo / 2018-2023 Trimble Inc.     %
%==============================================================================%

%--- This is a value to determine x-axis scaling (seconds or milliseconds) -----
plotScalingThreshold = 5000;

%--- Plot with milliseconds for shorter data records ---------------------------
%    but with seconds (ms/1000) for longer records.
if (settings.trk.msToProcess <= plotScalingThreshold)
    xlabelString = 'Time (ms)';
    xValues     = 1:settings.trk.msToProcess;
    line1 = [1 1] * settings.trk.fllTimeMs;
    line2 = [1 1] * settings.trk.pullInTimeMs;
    line3 = [1 1] * settings.trk.transitionTimeMs;
else
    xlabelString = 'Time (s)';
    xValues    = (1:settings.trk.msToProcess)     / 1000;
    line1 = [1 1] * settings.trk.fllTimeMs        / 1000;
    line2 = [1 1] * settings.trk.pullInTimeMs     / 1000;
    line3 = [1 1] * settings.trk.transitionTimeMs / 1000;
end

%--- Loop over channel list ----------------------------------------------------
for channelNr = 1:numel(trackResults)
    
    prn = trackResults(channelNr).prn;
    
    %=== Make large (complicated) version of the plot ==========================
    if strcmp(settings.trk.plotSwitch, 'large')
        
        %=== Select (or create) and clear the figure ===========================
        %    The offset is added just for more convenient handling of the
        %    open figure windows, when many figures are closed and reopened.
        figNum = figure(channelNr + 100);
        clf(figNum);
        set(gcf, 'Name', sprintf('Tracking Channel #%d --> PRN %d', ...
                                 channelNr, prn));
        
        %--- Nav Data Message --------------------------------------------------
        subplot(3, 3, [1 2]);
        
        plot(xValues, trackResults(channelNr).I_prompt ...
                      ./ hypot(trackResults(channelNr).I_prompt, ...
                               trackResults(channelNr).Q_prompt), 'r', ...
             xValues, trackResults(channelNr).navDataBits, 'b');
        
        axis([0 xValues(end) -1.4 1.4]);
        title(sprintf('Navigation Data Message - PRN %d', prn));
        xlabel(xlabelString);
        
        %--- Discrete-Time Scatter Plot ----------------------------------------
        subplot(3, 3, 3);
        
        p = 1: ...
            min([settings.trk.pullInTimeMs ...
                 settings.trk.msToProcess]);
        x = (settings.trk.pullInTimeMs+1): ...
            min([settings.trk.pullInTimeMs+settings.trk.transitionTimeMs ...
                 settings.trk.msToProcess]);
        f = (settings.trk.pullInTimeMs+ ...
             settings.trk.transitionTimeMs+1):settings.trk.msToProcess;
        
        hold('on');
        plot(trackResults(channelNr).I_prompt(p), ...
             trackResults(channelNr).Q_prompt(p), ...
             'Marker', '.', 'LineStyle', 'none',  ...
             'Color', [0.803921568627451 0.87843137254902 0.968627450980392]);
        plot(trackResults(channelNr).I_prompt(x), ...
             trackResults(channelNr).Q_prompt(x), ...
             'Marker', '.', 'LineStyle', 'none',  ...
             'Color', [0.701960784313725 0.780392156862745 1]);
        plot(trackResults(channelNr).I_prompt(f), ...
             trackResults(channelNr).Q_prompt(f), ...
             'Marker', '.', 'LineStyle', 'none',  ...
             'Color', [0 0 1]);
        hold('off');
        
        grid('on');
        axis('equal');
        title('Discrete-Time Scatter Plot');
        xlabel('I prompt');
        ylabel('Q prompt');
        
        %--- PLL Discriminator -------------------------------------------------
        handle = subplot(3, 3, 4);
        
        plot(xValues, (trackResults(channelNr).PLL_discr * 360));
        
        axis([0 xValues(end) -90 90]);
        v = axis;
        title('PLL Discriminator');
        xlabel(xlabelString);
        ylabel('Phase offset (degrees)');
        set(handle, 'YLim', [-90 90]);
        set(handle, 'YTick', -90:45:90);
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- DLL Discriminator -------------------------------------------------
        subplot(3, 3, 5);
        
        plot(xValues, ...
             (trackResults(channelNr).DLL_discr * 299792458) ...
             / settings.codeFreq);
        
        v = axis;
        axis([0 xValues(end) max([50 abs(v(3:4))]) * [-1 1]]);
        v = axis;
        title('DLL Discriminator');
        xlabel(xlabelString);
        ylabel('Code offset (m)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Correlator Output Power -------------------------------------------
        subplot(3, 3, 6);
        
        hold('on');
        plot(xValues, hypot(trackResults(channelNr).I_early, ...
                            trackResults(channelNr).Q_early), ...
             '.', 'Color', [0.8 0.7 1]);
        plot(xValues, hypot(trackResults(channelNr).I_late,  ...
                            trackResults(channelNr).Q_late), ...
             '.', 'Color', [0.8 0.8 1]);
        plot(xValues, hypot(trackResults(channelNr).I_prompt,  ...
                            trackResults(channelNr).Q_prompt), ...
             '.', 'Color', [0 0 1]);
        hold('off');
        
        v = axis;
        axis([0 xValues(end) 0 v(4)]);
        v = axis;
        title('Correlator Output Power');
        xlabel(xlabelString);
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Doppler Frequency -------------------------------------------------
        subplot(3, 3, 7);
        
        plot(xValues, trackResults(channelNr).dopplerFreq);
        
        v = axis;
        axis([0 xValues(end) ...
              min([v(3) mean(v(3:4))-75]) max([v(4) mean(v(3:4))+75])]);
        v = axis;
        title('Doppler Frequency');
        xlabel(xlabelString);
        ylabel('Doppler frequency (Hz)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Code-Phase --------------------------------------------------------
        subplot(3, 3, 8);
        
        plot(xValues, trackResults(channelNr).codePhase);
        
        v = axis;
        axis([0 xValues(end) v(3:4)+[-1 1]]);
        v = axis;
        title('Position of the Code Start');
        xlabel(xlabelString);
        ylabel('Code start (chips)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Filtered C/No -----------------------------------------------------
        subplot(3, 3, 9);
        
        plot(xValues, trackResults(channelNr).CNo);
        
        v = axis;
        axis([0 xValues(end) min([v(3) 30]) max([v(4) 60])]);
        v = axis;
        title('Filtered C/N_0');
        xlabel(xlabelString);
        ylabel('C/No (dB-Hz)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        drawnow();
        
    %=== Make medium version of the plot =======================================
    elseif strcmp(settings.trk.plotSwitch, 'med')
        
        %=== Select (or create) and clear the figure ===========================
        %    The offset is added just for more convenient handling of the
        %    open figure windows, when many figures are closed and reopened.
        figure(channelNr + 100);
        clf(gcf);
        set(gcf, 'Name', sprintf('Tracking Channel #%d --> PRN %d', ...
                                 channelNr, prn));
        
        %--- PLL Discriminator -------------------------------------------------
        handle = subplot(3, 2, 1);
        
        plot(xValues, (trackResults(channelNr).PLL_discr * 360));
        
        axis([0 xValues(end) -90 90]);
        v = axis;
        title('PLL Discriminator');
        xlabel(xlabelString);
        ylabel('Phase offset (degrees)');
        set(handle, 'YLim', [-90 90]);
        set(handle, 'YTick', -90:45:90);
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- DLL Discriminator -------------------------------------------------
        subplot(3, 2, 2);
        
        plot(xValues, ...
             (trackResults(channelNr).DLL_discr * 299792458) ...
             / settings.codeFreq);
        
        v = axis;
        axis([0 xValues(end) max([50 abs(v(3:4))]) * [-1 1]]);
        v = axis;
        title('DLL Discriminator');
        xlabel(xlabelString);
        ylabel('Code offset (m)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Doppler Frequency -------------------------------------------------
        subplot(3, 2, 3);
        
        plot(xValues, trackResults(channelNr).dopplerFreq);
        
        v = axis;
        axis([0 xValues(end) ...
              min([v(3) mean(v(3:4))-75]) max([v(4) mean(v(3:4))+75])]);
        v = axis;
        title('Doppler Frequency');
        xlabel(xlabelString);
        ylabel('Doppler frequency (Hz)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Code-Phase --------------------------------------------------------
        subplot(3, 2, 4);
        
        plot(xValues, trackResults(channelNr).codePhase);
        
        v = axis;
        axis([0 xValues(end) v(3:4)+[-1 1]]);
        v = axis;
        title('Position of the Code Start');
        xlabel(xlabelString);
        ylabel('Code start (chips)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        %--- Filtered C/No -----------------------------------------------------
        subplot(3, 2, [5 6]);
        
        plot(xValues, trackResults(channelNr).CNo);
        
        v = axis;
        axis([0 xValues(end) min([v(3) 30]) max([v(4) 60])]);
        v = axis;
        title('Filtered C/N_0');
        xlabel(xlabelString);
        ylabel('C/No (dB-Hz)');
        line(line1, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line2, v(3:4), 'Color', 'k', 'LineStyle', '--');
        line(line3, v(3:4), 'Color', 'k', 'LineStyle', '--');
        
        drawnow();
        
    %=== Make small (simple) version of the plot ===============================
    elseif strcmp(settings.trk.plotSwitch, 'small')
        
        %=== Select (or create) and clear the figure ===========================
        %    The offset is added just for more convenient handling of the
        %    open figure windows, when many figures are closed and reopened.
        figure(channelNr + 100);
        clf(gcf);
        set(gcf, 'Name', sprintf('Tracking Channel #%d --> PRN %d', ...
                                 channelNr, prn));
        
        %--- Correlator Output -------------------------------------------------
        subplot(2, 1, 1);
        
        plot(xValues, trackResults(channelNr).I_prompt);
        
        v = axis;
        axis([0 xValues(end) v(3:4)]);
        title('In-phase Prompt Correlator Output');
        xlabel(xlabelString);
        
        %--- Code-Phase --------------------------------------------------------
        subplot(2, 1, 2);
        
        plot(xValues, trackResults(channelNr).codePhase);
        
        v = axis;
        axis([0 xValues(end) v(3:4)+[-1 1]])
        title('Position of the Code Start');
        xlabel(xlabelString);
        ylabel('Code start (chips)');
        
        drawnow();
        
    %=== Do not plot tracking results ==========================================
    else
        
        %--- Fall through w/ no plotting ---------------------------------------
        continue
        
    end % if... on settings.trk.plotSwitch
    
    %--- Save plots to JPEG ----------------------------------------------------
    if ~(exist('OCTAVE_VERSION','builtin') > 0)
        if (settings.trk.plotToJPEG == true)
            print('-djpeg', sprintf('-f%d', 100+channelNr), ...
                  fullfile(pathName, ...
                           [fileName '__trk_' sprintf('PRN%02d', prn)]));
        end
    end
    
end % loop over channel number

return
%===============================================================================