From 1a15e6e64b8c63aad2be70f15bfcc42e44bd0197 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 18fd053..0fa6496 100644 --- a/nanovna.h +++ b/nanovna.h @@ -984,6 +984,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 8ffe9fe..1615017 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 85013ab..6389f5f 100644 --- a/sa_core.c +++ b/sa_core.c @@ -5696,6 +5696,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!!