From 211cb2f7eca25069a36e49e02843e76f107b9a0b Mon Sep 17 00:00:00 2001 From: PhysicistJohn <54456354+PhysicistJohn@users.noreply.github.com> Date: Tue, 14 Jul 2026 22:03:59 -0700 Subject: [PATCH] fix: refresh zero-span grid from completed sweep The zero-span time grid can be calculated before actual_sweep_time_us is updated, leaving the display aligned to the previous sweep duration. Calculate grid geometry without mutating global state, recompute it after the measured sweep time is stored, and redraw only when the resulting tuple changes. Use 64-bit arithmetic through the final time-domain division so short sweeps retain exact pixel geometry. --- nanovna.h | 1 + plot.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++--------- sa_core.c | 5 +++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/nanovna.h b/nanovna.h index f323edd..88a2b26 100644 --- a/nanovna.h +++ b/nanovna.h @@ -986,6 +986,7 @@ extern int8_t marker_tracking; void plot_init(void); void update_grid(void); +void update_grid_if_changed(void); void request_to_redraw_grid(void); void redraw_frame(void); //void redraw_all(void); diff --git a/plot.c b/plot.c index 9bbf119..4335a55 100644 --- a/plot.c +++ b/plot.c @@ -110,19 +110,24 @@ float2int(float v) } #endif -void update_grid(void) +static void calculate_grid(int16_t *offset, int16_t *width, freq_t *span) { freq_t gdigit = 1000000000; freq_t fstart = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT); freq_t fspan = get_sweep_frequency(ST_SPAN); freq_t grid; + bool time_domain = fspan == 0; - if (fspan == 0) { + if (time_domain) { fspan = setting.actual_sweep_time_us; // Time in uS fstart = 0; } + if (fspan == 0) + fspan = 1; if (config.gridlines == 0) { grid = fspan/10; + if (grid == 0) + grid = 1; } else { if (config.gridlines < 3) config.gridlines = 6; @@ -139,21 +144,54 @@ void update_grid(void) gdigit /= 10; } } - grid_span = grid; - if (grid > 1000) { - grid_offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100); - grid_width = (WIDTH) * (grid / 100) / (fspan / 1000); + *span = grid; + if (time_domain) { + // The zero-span x axis is measured in microseconds. Keep the full ratio + // until the final division so 5-20 ms sweeps do not shift by whole pixels. + *offset = (int16_t)((uint64_t)WIDTH * (fstart % grid) / fspan); + *width = (int16_t)((uint64_t)WIDTH * 10U * grid / fspan); + } else if (grid > 1000) { + *offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100); + *width = (WIDTH) * (grid / 100) / (fspan / 1000); } else { - grid_offset = (WIDTH) * ((fstart % grid)) / (fspan); - grid_width = (WIDTH) * (grid) / (fspan/10); + *offset = (WIDTH) * ((fstart % grid)) / (fspan); + *width = (WIDTH) * (grid) / (fspan/10); } + if (*width < 1) + *width = 1; if (config.gridlines == 0) - grid_offset = 0; + *offset = 0; +} + +static void apply_grid(int16_t offset, int16_t width, freq_t span) +{ + grid_offset = offset; + grid_width = width; + grid_span = span; // if (setting.waterfall) set_level_meter_or_waterfall(); redraw_request |= REDRAW_FREQUENCY | REDRAW_AREA; } +void update_grid(void) +{ + int16_t offset; + int16_t width; + freq_t span; + calculate_grid(&offset, &width, &span); + apply_grid(offset, width, span); +} + +void update_grid_if_changed(void) +{ + int16_t offset; + int16_t width; + freq_t span; + calculate_grid(&offset, &width, &span); + if (offset != grid_offset || width != grid_width || span != grid_span) + apply_grid(offset, width, span); +} + #if 0 static int rectangular_grid(int x, int y) diff --git a/sa_core.c b/sa_core.c index 4046a20..2ff36a9 100644 --- a/sa_core.c +++ b/sa_core.c @@ -5698,6 +5698,11 @@ static volatile int dummy; redraw_request|=REDRAW_CAL_STATUS | REDRAW_FREQUENCY; } setting.actual_sweep_time_us = setting.measure_sweep_time_us; + // The zero-span x axis represents the sweep that just completed. Recompute + // its tuple every time; update_grid_if_changed() suppresses redraws while + // the exact grid geometry remains unchanged. + if (FREQ_IS_CW()) + update_grid_if_changed(); // Not possible reduce sweep time, it minimum! if (setting.sweep_time_us < setting.actual_sweep_time_us && setting.additional_step_delay_us == 0){ // Warning!! not correct set sweep time here, you get error!!