From 516319b354b49973cd938539cef3247321558649 Mon Sep 17 00:00:00 2001 From: TT Date: Wed, 25 Sep 2019 02:40:00 +0900 Subject: [PATCH 1/6] fix: plot only if sweep completed --- main.c | 130 +++++++++++++++++++++--------------------------------- nanovna.h | 2 +- plot.c | 20 +++++---- 3 files changed, 63 insertions(+), 89 deletions(-) diff --git a/main.c b/main.c index d7ee8f3..09b6296 100644 --- a/main.c +++ b/main.c @@ -38,7 +38,7 @@ static void apply_error_term(void); static void apply_error_term_at(int i); static void cal_interpolate(int s); -void sweep(void); +bool sweep(bool break_on_operation); static MUTEX_DECL(mutex); @@ -48,11 +48,9 @@ static MUTEX_DECL(mutex); int32_t frequency_offset = 5000; int32_t frequency = 10000000; int8_t drive_strength = DRIVE_STRENGTH_AUTO; -int8_t frequency_updated = FALSE; int8_t sweep_enabled = TRUE; int8_t cal_auto_interpolate = TRUE; uint16_t redraw_request = 0; // contains REDRAW_XXX flags -int8_t stop_the_world = FALSE; int16_t vbat = 0; @@ -63,32 +61,37 @@ static THD_FUNCTION(Thread1, arg) chRegSetThreadName("sweep"); while (1) { - if (stop_the_world) { - __WFI(); - continue; - } - + bool completed = false; if (sweep_enabled) { chMtxLock(&mutex); - sweep(); + completed = sweep(true); chMtxUnlock(&mutex); } else { __WFI(); - ui_process(); } - if (vbat != -1) { + { + chMtxLock(&mutex); + ui_process(); + + if (vbat != -1) { adc_stop(ADC1); vbat = adc_vbat_read(ADC1); touch_start_watchdog(); draw_battery_status(); - } + } + + /* calculate trace coordinates and plot only if scan completed */ + if (completed) { + plot_into_index(measured); + redraw_request |= REDRAW_CELLS; + } - /* calculate trace coordinates */ - plot_into_index(measured); + /* plot trace and other indications as raster */ + draw_all(completed); // flush markmap only if scan completed to prevent remaining traces - /* plot trace as raster */ - draw_all(); + chMtxUnlock(&mutex); + } } } @@ -220,6 +223,7 @@ static void cmd_resume(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; resume_sweep(); + update_frequencies(); } static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[]) @@ -461,13 +465,15 @@ static void cmd_data(BaseSequentialStream *chp, int argc, char *argv[]) if (sel == 0 || sel == 1) { chMtxLock(&mutex); for (i = 0; i < sweep_points; i++) { - chprintf(chp, "%f %f\r\n", measured[sel][i][0], measured[sel][i][1]); + if (frequencies[i] != 0) + chprintf(chp, "%f %f\r\n", measured[sel][i][0], measured[sel][i][1]); } chMtxUnlock(&mutex); } else if (sel >= 2 && sel < 7) { chMtxLock(&mutex); for (i = 0; i < sweep_points; i++) { - chprintf(chp, "%f %f\r\n", cal_data[sel-2][i][0], cal_data[sel-2][i][1]); + if (frequencies[i] != 0) + chprintf(chp, "%f %f\r\n", cal_data[sel-2][i][0], cal_data[sel-2][i][1]); } chMtxUnlock(&mutex); } else { @@ -505,10 +511,7 @@ static void cmd_capture(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; - // pause sweep - stop_the_world = TRUE; - - chThdSleepMilliseconds(1000); + chMtxLock(&mutex); // use uint16_t spi_buffer[1024] (defined in ili9341) for read buffer uint16_t *buf = &spi_buffer[0]; @@ -531,7 +534,7 @@ static void cmd_capture(BaseSequentialStream *chp, int argc, char *argv[]) } //*/ - stop_the_world = FALSE; + chMtxUnlock(&mutex); } #if 0 @@ -632,48 +635,13 @@ ensure_edit_config(void) cal_status = 0; } -#if 0 -static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) -{ - float gamma[2]; - int i; - int32_t freq, step; - int delay; - (void)argc; - (void)argv; - - pause_sweep(); - chMtxLock(&mutex); - - freq = frequency0; - step = (frequency1 - frequency0) / (sweep_points-1); - set_frequency(freq); - delay = 4; - for (i = 0; i < sweep_points; i++) { - freq = freq + step; - wait_dsp(delay); - delay = set_frequency(freq); - palClearPad(GPIOC, GPIOC_LED); - calculate_gamma(gamma); - palSetPad(GPIOC, GPIOC_LED); - chprintf(chp, "%d %d\r\n", gamma[0], gamma[1]); - } - chMtxUnlock(&mutex); -} -#endif - // main loop for measurement -void sweep(void) +bool sweep(bool break_on_operation) { int i; - int delay; - - rewind: - frequency_updated = FALSE; - //delay = 3; for (i = 0; i < sweep_points; i++) { - delay = set_frequency(frequencies[i]); + int delay = set_frequency(frequencies[i]); tlv320aic3204_select_in3(); // CH0:REFLECT wait_dsp(delay); @@ -698,15 +666,13 @@ void sweep(void) if (electrical_delay != 0) apply_edelay_at(i); - ui_process(); - if (redraw_request) - break; // return to redraw screen asap. - - if (frequency_updated) - goto rewind; + // back to toplevel to handle ui operation + if (operation_requested && break_on_operation) + return false; } transform_domain(); + return true; } static void @@ -741,32 +707,37 @@ update_marker_index(void) } void -update_frequencies(void) +set_frequencies(uint32_t start, uint32_t stop, int16_t points) { int i; - int32_t span; - int32_t start; + uint32_t span = (stop - start) / 1000; /* prevents overflow because of maximum of int32_t(2.147e+9) */ + for (i = 0; i < points; i++) + frequencies[i] = start + span * i / (points - 1) * 1000; + for (; i < sweep_points; i++) + frequencies[i] = 0; +} + +void +update_frequencies(void) +{ + uint32_t start, stop; if (frequency1 > 0) { start = frequency0; - span = (frequency1 - frequency0)/100; + stop = frequency1; } else { - int center = frequency0; - span = -frequency1; + int32_t center = frequency0; + int32_t span = -frequency1; start = center - span/2; - span /= 100; + stop = center + span/2; } - for (i = 0; i < sweep_points; i++) - frequencies[i] = start + span * i / (sweep_points - 1) * 100; - + set_frequencies(start, stop, sweep_points); update_marker_index(); - frequency_updated = TRUE; // set grid layout update_grid(); } - void freq_mode_startstop(void) { @@ -1722,7 +1693,8 @@ static void cmd_frequencies(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; for (i = 0; i < sweep_points; i++) { - chprintf(chp, "%d\r\n", frequencies[i]); + if (frequencies[i] != 0) + chprintf(chp, "%d\r\n", frequencies[i]); } } diff --git a/nanovna.h b/nanovna.h index 6a14fe1..ef4425c 100644 --- a/nanovna.h +++ b/nanovna.h @@ -236,7 +236,7 @@ void redraw_marker(int marker, int update_info); void trace_get_info(int t, char *buf, int len); void plot_into_index(float measured[2][101][2]); void force_set_markmap(void); -void draw_all(void); +void draw_all(bool flush); void draw_cal_status(void); diff --git a/plot.c b/plot.c index a7167ed..18f4dbb 100644 --- a/plot.c +++ b/plot.c @@ -1248,7 +1248,7 @@ draw_cell(int m, int n) } void -draw_all_cells(void) +draw_all_cells(bool flush_markmap) { int m, n; for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++) @@ -1257,17 +1257,19 @@ draw_all_cells(void) draw_cell(m, n); } - // keep current map for update - swap_markmap(); - // clear map for next plotting - clear_markmap(); + if (flush_markmap) { + // keep current map for update + swap_markmap(); + // clear map for next plotting + clear_markmap(); + } } void -draw_all(void) +draw_all(bool flush) { - draw_all_cells(); - + if (redraw_request & REDRAW_CELLS) + draw_all_cells(flush); if (redraw_request & REDRAW_FREQUENCY) draw_frequencies(); if (redraw_request & REDRAW_CAL_STATUS) @@ -1285,7 +1287,7 @@ redraw_marker(int marker, int update_info) if (update_info) markmap[current_mappage][0] = 0xffff; - draw_all_cells(); + draw_all_cells(TRUE); } void From 571e45d50bf0fee2902da05408574005b5dce0d7 Mon Sep 17 00:00:00 2001 From: TT Date: Wed, 25 Sep 2019 02:43:02 +0900 Subject: [PATCH 2/6] feat: add scan command --- main.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 09b6296..d6797ec 100644 --- a/main.c +++ b/main.c @@ -675,6 +675,37 @@ bool sweep(bool break_on_operation) return true; } +static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) +{ + int32_t start, stop; + int16_t points = sweep_points; + + if (argc != 2 && argc != 3) { + chprintf(chp, "usage: sweep {start(Hz)} {stop(Hz)} [points]\r\n"); + return; + } + + start = atoi(argv[0]); + stop = atoi(argv[1]); + if (start == 0 || stop == 0 || start > stop) { + chprintf(chp, "frequency range is invalid\r\n"); + return; + } + if (argc == 3) { + points = atoi(argv[2]); + if (points <= 0 || points > sweep_points) { + chprintf(chp, "sweep points exceeds range\r\n"); + return; + } + } + + pause_sweep(); + chMtxLock(&mutex); + set_frequencies(start, stop, points); + sweep(false); + chMtxUnlock(&mutex); +} + static void update_marker_index(void) { @@ -1841,7 +1872,7 @@ static void cmd_vbat(BaseSequentialStream *chp, int argc, char *argv[]) chprintf(chp, "%d mV\r\n", vbat); } -static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); +static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */640); static const ShellCommand commands[] = { @@ -1864,7 +1895,7 @@ static const ShellCommand commands[] = { "power", cmd_power }, { "sample", cmd_sample }, //{ "gamma", cmd_gamma }, - //{ "scan", cmd_scan }, + { "scan", cmd_scan }, { "sweep", cmd_sweep }, { "test", cmd_test }, { "touchcal", cmd_touchcal }, From 5fea75f92f270d4b980d47ab5e125884994ef901 Mon Sep 17 00:00:00 2001 From: TT Date: Thu, 26 Sep 2019 09:22:00 +0900 Subject: [PATCH 3/6] chore: move loop of scan command into sweep thread --- main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index d6797ec..5475be0 100644 --- a/main.c +++ b/main.c @@ -49,6 +49,7 @@ int32_t frequency_offset = 5000; int32_t frequency = 10000000; int8_t drive_strength = DRIVE_STRENGTH_AUTO; int8_t sweep_enabled = TRUE; +int8_t sweep_once = FALSE; int8_t cal_auto_interpolate = TRUE; uint16_t redraw_request = 0; // contains REDRAW_XXX flags int16_t vbat = 0; @@ -62,15 +63,16 @@ static THD_FUNCTION(Thread1, arg) while (1) { bool completed = false; - if (sweep_enabled) { + if (sweep_enabled || sweep_once) { chMtxLock(&mutex); completed = sweep(true); + sweep_once = FALSE; chMtxUnlock(&mutex); } else { __WFI(); } - { + if (sweep_enabled) { chMtxLock(&mutex); ui_process(); @@ -702,8 +704,12 @@ static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) pause_sweep(); chMtxLock(&mutex); set_frequencies(start, stop, points); - sweep(false); + sweep_once = TRUE; chMtxUnlock(&mutex); + + // wait finishing sweep + while (sweep_once) + chThdSleepMilliseconds(10); } static void @@ -1872,7 +1878,7 @@ static void cmd_vbat(BaseSequentialStream *chp, int argc, char *argv[]) chprintf(chp, "%d mV\r\n", vbat); } -static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */640); +static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); static const ShellCommand commands[] = { From b552d04f96b7448302fa4cce2b64fec79792a606 Mon Sep 17 00:00:00 2001 From: TT Date: Sat, 28 Sep 2019 10:01:19 +0900 Subject: [PATCH 4/6] fix: apply cal on scan --- main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 5475be0..0ca6be8 100644 --- a/main.c +++ b/main.c @@ -224,8 +224,13 @@ static void cmd_resume(BaseSequentialStream *chp, int argc, char *argv[]) (void)chp; (void)argc; (void)argv; - resume_sweep(); + + // restore frequencies array and cal update_frequencies(); + if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) + cal_interpolate(lastsaveid); + + resume_sweep(); } static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[]) @@ -704,6 +709,9 @@ static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) pause_sweep(); chMtxLock(&mutex); set_frequencies(start, stop, points); + if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) + cal_interpolate(lastsaveid); + sweep_once = TRUE; chMtxUnlock(&mutex); @@ -808,7 +816,6 @@ void set_sweep_frequency(int type, float frequency) { int32_t freq = frequency; - bool cal_applied = cal_status & CALSTAT_APPLY; switch (type) { case ST_START: freq_mode_startstop(); @@ -888,7 +895,7 @@ set_sweep_frequency(int type, float frequency) break; } - if (cal_auto_interpolate && cal_applied) + if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) cal_interpolate(lastsaveid); } From dbfdad4fd91d99bf6c5f6b130a8d56815c8f8182 Mon Sep 17 00:00:00 2001 From: TT Date: Sat, 28 Sep 2019 10:01:54 +0900 Subject: [PATCH 5/6] WIP: add multisegment scan --- python/nanovna.py | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/python/nanovna.py b/python/nanovna.py index 8edda94..f448cac 100755 --- a/python/nanovna.py +++ b/python/nanovna.py @@ -141,19 +141,6 @@ class NanoVNA: d = data.strip().split(' ') return (int(d[0])+int(d[1])*1.j)/REF_LEVEL - def fetch_scan(self, port = None): - self.set_port(port) - self.send_command("scan\r") - data = self.fetch_data() - x = [] - for line in data.split('\n'): - if line: - x.append([int(d) for d in line.strip().split(' ')]) - x = np.array(x) - freqs = x[:,0] - gammas = x[:,1]+x[:,2]*1j - return gammas / REF_LEVEL, freqs - def reflect_coeff_from_rawwave(self, freq = None): ref, samp = self.fetch_rawwave(freq) if self.filter: @@ -202,6 +189,30 @@ class NanoVNA: x.append(float(line)) self._frequencies = np.array(x) + def send_scan(self, start = 1e6, stop = 900e6, points = None): + if points: + self.send_command("scan %d %d %d\r"%(start, stop, points)) + else: + self.send_command("scan %d %d\r"%(start, stop)) + + def scan_multisegment(self, start = 1e6, stop = 900e6, points = 201): + segment_length = 101 + array0 = [] + array1 = [] + freqs = np.linspace(start, stop, points) + self._frequencies = freqs + while len(freqs) > 1: + seg_start = freqs[0] + seg_stop = freqs[segment_length-1] if len(freqs) >= segment_length else freqs[-1] + length = segment_length if len(freqs) >= segment_length else len(freqs) + #print((seg_start, seg_stop, length)) + self.send_scan(seg_start, seg_stop, length) + array0.extend(self.data(0)) + array1.extend(self.data(1)) + freqs = freqs[segment_length:] + self.resume() + return (array0, array1) + def capture(self): from PIL import Image self.send_command("capture\r") @@ -395,7 +406,9 @@ if __name__ == '__main__': plot = opt.phase or opt.plot or opt.vswr or opt.delay or opt.groupdelay or opt.smith or opt.unwrapphase or opt.polar or opt.tdr if plot: if opt.scan: - s = nv.scan() + #s = nv.scan() + s = nv.scan_multisegment() + s = s[0] else: p = 0 if opt.port: From 115047045c5caa57c05e006951aa5ba32a90e25d Mon Sep 17 00:00:00 2001 From: TT Date: Sat, 28 Sep 2019 13:03:08 +0900 Subject: [PATCH 6/6] feat: multisegment scan support in python script --- python/nanovna.py | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/python/nanovna.py b/python/nanovna.py index f448cac..8ec3526 100755 --- a/python/nanovna.py +++ b/python/nanovna.py @@ -3,9 +3,7 @@ import serial import numpy as np import pylab as pl import scipy.signal as signal -import time import struct -import os from serial.tools import list_ports VID = 0x0483 #1155 @@ -44,7 +42,7 @@ class NanoVNA: def frequencies(self): return self._frequencies - def set_sweep(self, start = 1e6, stop = 900e6, points = None): + def set_frequencies(self, start = 1e6, stop = 900e6, points = None): if points: self.points = points self._frequencies = np.linspace(start, stop, self.points) @@ -63,6 +61,12 @@ class NanoVNA: self.serial.write(cmd.encode()) self.serial.readline() # discard empty line + def set_sweep(self, start, stop): + if start is not None: + self.send_command("sweep start %d\r" % start) + if stop is not None: + self.send_command("sweep stop %d\r" % stop) + def set_frequency(self, freq): if freq is not None: self.send_command("freq %d\r" % freq) @@ -162,7 +166,7 @@ class NanoVNA: def pause(self): self.send_command("pause\r") - def scan(self, port = None): + def scan_gamma0(self, port = None): self.set_port(port) return np.vectorize(self.gamma)(self.frequencies) @@ -195,13 +199,12 @@ class NanoVNA: else: self.send_command("scan %d %d\r"%(start, stop)) - def scan_multisegment(self, start = 1e6, stop = 900e6, points = 201): + def scan(self): segment_length = 101 array0 = [] array1 = [] - freqs = np.linspace(start, stop, points) - self._frequencies = freqs - while len(freqs) > 1: + freqs = self._frequencies + while len(freqs) > 0: seg_start = freqs[0] seg_stop = freqs[segment_length-1] if len(freqs) >= segment_length else freqs[-1] length = segment_length if len(freqs) >= segment_length else len(freqs) @@ -212,7 +215,7 @@ class NanoVNA: freqs = freqs[segment_length:] self.resume() return (array0, array1) - + def capture(self): from PIL import Image self.send_command("capture\r") @@ -355,6 +358,15 @@ if __name__ == '__main__': parser.add_option("-c", "--scan", dest="scan", action="store_true", default=False, help="scan by script", metavar="SCAN") + parser.add_option("-S", "--start", dest="start", + type="float", default=1e6, + help="start frequency", metavar="START") + parser.add_option("-E", "--stop", dest="stop", + type="float", default=900e6, + help="stop frequency", metavar="STOP") + parser.add_option("-N", "--points", dest="points", + type="int", default=101, + help="scan points", metavar="POINTS") parser.add_option("-P", "--port", type="int", dest="port", help="port", metavar="PORT") parser.add_option("-d", "--dev", dest="device", @@ -365,7 +377,7 @@ if __name__ == '__main__': help="gain (0-95)", metavar="GAIN") parser.add_option("-O", "--offset", type="int", dest="offset", help="offset frequency", metavar="OFFSET") - parser.add_option("-S", "--strength", type="int", dest="strength", + parser.add_option("--strength", type="int", dest="strength", help="drive strength(0-3)", metavar="STRENGTH") parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, @@ -403,16 +415,17 @@ if __name__ == '__main__': print(np.average(samp[0::2] * samp[1::2])) pl.show() exit(0) + if opt.start or opt.stop or opt.points: + nv.set_frequencies(opt.start, opt.stop, opt.points) plot = opt.phase or opt.plot or opt.vswr or opt.delay or opt.groupdelay or opt.smith or opt.unwrapphase or opt.polar or opt.tdr if plot: - if opt.scan: - #s = nv.scan() - s = nv.scan_multisegment() - s = s[0] + p = int(opt.port) if opt.port else 0 + if opt.scan or opt.points > 101: + s = nv.scan() + s = s[p] else: - p = 0 - if opt.port: - p = int(opt.port) + if opt.start or opt.stop: + nv.set_sweep(opt.start, opt.stop) s = nv.data(p) if opt.smith: nv.smith(s)