From 62e0120f221f21f8dfe6c656a61e93b3774723e5 Mon Sep 17 00:00:00 2001 From: erikkaashoek Date: Thu, 2 Apr 2020 13:34:10 +0200 Subject: [PATCH] Measurements working --- nanovna.h | 6 +++ plot.c | 32 +++++++++++++-- sa_core.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++----- ui.c | 13 +++++- ui_sa.c | 91 ++++++++++++++++++++++++++---------------- 5 files changed, 208 insertions(+), 50 deletions(-) diff --git a/nanovna.h b/nanovna.h index a299dd5..c8f8da2 100644 --- a/nanovna.h +++ b/nanovna.h @@ -638,4 +638,10 @@ void SetRefpos(int); void SetScale(int); void SetRBW(int); void SetRX(int); +extern int setting_measurement; + +enum { + M_OFF, M_IMD, M_OIP3 +}; + /*EOF*/ diff --git a/plot.c b/plot.c index a6e4bad..1a8ef2b 100644 --- a/plot.c +++ b/plot.c @@ -1,5 +1,4 @@ -/* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com - * All rights reserved. +/* All rights reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1100,7 +1099,7 @@ markmap_marker(int marker) int t; if (!markers[marker].enabled) return; - for (t = TRACE_ACTUAL; t < TRACE_ACTUAL; t++) { + for (t = TRACE_ACTUAL; t <= TRACE_ACTUAL; t++) { if (!trace[t].enabled) continue; index_t index = trace_index[t][markers[marker].index]; @@ -1398,10 +1397,18 @@ draw_cell(int m, int n) int x = CELL_X(index) - x0 - X_MARKER_OFFSET; int y = CELL_Y(index) - y0 - Y_MARKER_OFFSET; // Check marker icon on cell +#if 1 + + if (x + MARKER_WIDTH >= 0 && x < CELLWIDTH && + y + MARKER_HEIGHT >= 0 && y < CELLHEIGHT) + draw_marker(x, y, marker_color[markers[i].mtype], i); +#else + if (x + MARKER_WIDTH >= 0 && x - MARKER_WIDTH < CELLWIDTH && y + MARKER_HEIGHT >= 0 && y - MARKER_HEIGHT < CELLHEIGHT) draw_marker(x, y, marker_color[markers[i].mtype], i); -// draw_marker(x, y, config.trace_color[t], i); +#endif + // draw_marker(x, y, config.trace_color[t], i); // } } #endif @@ -1814,6 +1821,23 @@ static void cell_draw_marker_info(int x0, int y0) } } for (int i = 0; i < MARKER_COUNT; i++) { + if (i >= 2 && setting_measurement == M_OIP3 && markers[2].enabled && markers[3].enabled) { + float il = logmag(&(actual_t[markers[2].index])); + float ir = logmag(&(actual_t[markers[3].index])); + float sl = logmag(&(actual_t[markers[0].index])); + float sr = logmag(&(actual_t[markers[1].index])); + sl = (sl + sr)/2; + il = (il + ir)/2; + + il = sl+ (sl - il)/2; + plot_printf(buf, sizeof buf, "OIP3: %4.1fdB", il); + j = 2; + int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(16) - y0; + + cell_drawstring_7x13(buf, xpos, ypos); + break; + } if (!markers[i].enabled) continue; int idx = markers[i].index; diff --git a/sa_core.c b/sa_core.c index 2396f5c..08c945e 100644 --- a/sa_core.c +++ b/sa_core.c @@ -19,8 +19,11 @@ int setting_tracking = false; int setting_modulation = MO_NONE; int setting_step_delay = 0; int setting_frequency_step; +int setting_decay; +int setting_noise; float actual_rbw = 0; float setting_vbw = 0; +int setting_measurement; int vbwSteps = 1; @@ -48,6 +51,9 @@ void reset_settings(int m) setting_modulation = MO_NONE; setting_step_delay = 0; setting_vbw = 0; + setting_decay=20; + setting_noise=20; + setting_measurement = M_OFF; // setting_spur = 0; switch(m) { case M_LOW: @@ -92,6 +98,27 @@ int get_refer_output(void) return(setting_refer); } +void set_decay(int d) +{ + if (d < 0 || d > 200) + return; + setting_decay = d; + dirty = true; +} + +void set_noise(int d) +{ + if (d < 5 || d > 200) + return; + setting_noise = d; + dirty = true; +} + +void set_measurement(int m) +{ + setting_measurement = m; + dirty = true; +} void SetDrive(int d) { setting_drive = d; @@ -455,6 +482,64 @@ void update_rbw(void) vbwSteps = 1; dirty = true; } +#define MAX_MAX 4 +int +search_maximum(int m, int center, int span) +{ + int from = center - span/2; + int found = false; + int to = center + span/2; + int cur_max = 0; // Always at least one maximum + int max_index[4]; + temppeakIndex = 0; + temppeakLevel = actual_t[from]; + max_index[cur_max] = from; + int downslope = true; + + for (int i = from; i <= to; i++) { + if (downslope) { + if (temppeakLevel > actual_t[i]) { // Follow down + temppeakIndex = i; // Latest minimum + temppeakLevel = actual_t[i]; + } else if (temppeakLevel + setting_noise < actual_t[i]) { // Local minimum found + temppeakIndex = i; // This is now the latest maximum + temppeakLevel = actual_t[i]; + downslope = false; + } + } else { + if (temppeakLevel < actual_t[i]) { // Follow up + temppeakIndex = i; + temppeakLevel = actual_t[i]; + } else if (temppeakLevel - setting_noise > actual_t[i]) { // Local max found + + found = true; + int j = 0; // Insertion index + while (j= temppeakLevel) // Find where to insert + j++; + if (j < MAX_MAX) { // Larger then one of the previous found + int k = MAX_MAX-1; + while (k > j) { // Shift to make room for max + max_index[k] = max_index[k-1]; + // maxlevel_index[k] = maxlevel_index[k-1]; // Only for debugging + k--; + } + max_index[j] = temppeakIndex; + // maxlevel_index[j] = actual_t[temppeakIndex]; // Only for debugging + if (cur_max < MAX_MAX) { + cur_max++; + } + //STOP_PROFILE + } + temppeakIndex = i; // Latest minimum + temppeakLevel = actual_t[i]; + + downslope = true; + } + } + } + markers[m].index = max_index[0]; + return found; +} //static int spur_old_stepdelay = 0; static const unsigned int spur_IF = 433900000; @@ -569,7 +654,6 @@ float perform(bool break_on_operation, int i, int32_t f, int tracking) } #define MAX_MAX 4 -#define MAX_NOISE 10 // 10dB int16_t max_index[MAX_MAX]; int16_t cur_max = 0; @@ -613,14 +697,14 @@ static bool sweep(bool break_on_operation) actual_t[i] = RSSI; age[i] = 0; } else { - if (age[i] > 20) + if (age[i] > setting_decay) actual_t[i] -= 0.5; else age[i] += 1; } break; - case AV_4: actual_t[i] = (actual_t[i] + RSSI) / 4.0; break; - case AV_16: actual_t[i] = (actual_t[i]*3 + RSSI) / 16.0; break; + case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break; + case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break; } } #if 1 @@ -629,14 +713,14 @@ static bool sweep(bool break_on_operation) cur_max = 0; // Always at least one maximum temppeakIndex = 0; temppeakLevel = actual_t[i]; - max_index[i] = 0; + max_index[0] = 0; downslope = true; } if (downslope) { if (temppeakLevel > actual_t[i]) { // Follow down temppeakIndex = i; // Latest minimum temppeakLevel = actual_t[i]; - } else if (temppeakLevel + MAX_NOISE < actual_t[i]) { // Local minimum found + } else if (temppeakLevel + setting_noise < actual_t[i]) { // Local minimum found temppeakIndex = i; // This is now the latest maximum temppeakLevel = actual_t[i]; downslope = false; @@ -645,7 +729,7 @@ static bool sweep(bool break_on_operation) if (temppeakLevel < actual_t[i]) { // Follow up temppeakIndex = i; temppeakLevel = actual_t[i]; - } else if (temppeakLevel - MAX_NOISE > actual_t[i]) { // Local max found + } else if (temppeakLevel - setting_noise > actual_t[i]) { // Local max found int j = 0; // Insertion index while (j= temppeakLevel) // Find where to insert @@ -713,6 +797,20 @@ static bool sweep(bool break_on_operation) } m++; // Try next marker } + if (setting_measurement == M_IMD && markers[0].index > 10) { + markers[1].enabled = search_maximum(1, markers[0].index*2, 8); + markers[2].enabled = search_maximum(2, markers[0].index*3, 12); + markers[3].enabled = search_maximum(3, markers[0].index*4, 16); + } else if (setting_measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) { + int l = markers[0].index; + int r = markers[1].index; + if (r < l) { + l = markers[1].index; + r = markers[0].index; + } + markers[2].enabled = search_maximum(2, l - (r-l), 10); + markers[3].enabled = search_maximum(3, r + (r-l), 10); + } peakIndex = max_index[0]; peakLevel = actual_t[peakIndex]; peakFreq = frequencies[peakIndex]; @@ -742,7 +840,7 @@ static bool sweep(bool break_on_operation) } -const char *averageText[] = { "OFF", "MIN", "MAX", "MAXD", "4", "16"}; +const char *averageText[] = { "OFF", "MIN", "MAX", "MAXD", " A 4", "A 16"}; const char *dBText[] = { "1dB/", "2dB/", "5dB/", "10dB/", "20dB/"}; const int refMHz[] = { 30, 15, 10, 4, 3, 2, 1 }; @@ -794,7 +892,7 @@ void draw_cal_status(void) if (setting_average>0) { ili9341_set_foreground(BRIGHT_COLOR_BLUE); y += YSTEP*2; - ili9341_drawstring("Aver:", x, y); + ili9341_drawstring("Calc:", x, y); y += YSTEP; plot_printf(buf, BLEN, "%s",averageText[setting_average]); diff --git a/ui.c b/ui.c index 2542794..a7822e3 100644 --- a/ui.c +++ b/ui.c @@ -1108,6 +1108,8 @@ menu_move_back(void) return; erase_menu_buttons(); menu_current_level--; + if (selection >= 0) + selection = 0; ensure_selection(); draw_menu(); } @@ -1119,6 +1121,8 @@ menu_push_submenu(const menuitem_t *submenu) if (menu_current_level < MENU_STACK_DEPTH_MAX-1) menu_current_level++; menu_stack[menu_current_level] = submenu; + if (selection >= 0) + selection = 0; ensure_selection(); if (menu_is_form(submenu)) { redraw_frame(); @@ -1940,6 +1944,10 @@ ui_process_menu(void) int status = btn_check(); if (status != 0) { if (status & EVT_BUTTON_SINGLE_CLICK) { + if (selection == -1) { + selection = 0; + goto activate; + } menu_invoke(selection); } else { do { @@ -1947,13 +1955,14 @@ ui_process_menu(void) // close menu if next item is sentinel if (menu_stack[menu_current_level][selection+1].type == MT_NONE) goto menuclose; - if (!(menu_stack[menu_current_level][selection+1].type == MT_FORM | MT_NONE)) + if (!(menu_stack[menu_current_level][selection+1].type == (MT_FORM | MT_NONE))) selection++; } if (status & EVT_DOWN) { if (! ( selection == 0 && menu_stack[menu_current_level][0].type & MT_FORM)) selection--; } +activate: ensure_selection(); draw_menu(); status = btn_wait_release(); @@ -2210,7 +2219,7 @@ ui_process_keypad(void) redraw_frame(); if (menu_is_form(menu_stack[menu_current_level])) { ui_mode_menu(); //Reactivate menu after keypad - selection = 0; + selection = -1; ensure_selection(); } else { ui_mode_normal(); diff --git a/ui_sa.c b/ui_sa.c index b67489e..6c66358 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -5,6 +5,7 @@ static void menu_marker_type_cb(int item, uint8_t data); void set_sweep_frequency(int type, uint32_t frequency); uint32_t get_sweep_frequency(int type); void clearDisplay(void); +void reset_settings(int); //void ui_process_touch(void); void SetPowerGrid(int); void SetRefLevel(int); @@ -37,13 +38,18 @@ void ToggleLNA(void); void ToggleAGC(void); void redrawHisto(void); void self_test(void); +void set_decay(int); +void set_noise(int); extern int32_t frequencyExtra; extern int setting_tracking; extern int setting_drive; extern int setting_lna; extern int setting_agc; +extern int setting_decay; +extern int setting_noise; void SetModulation(int); extern int setting_modulation; +void set_measurement(int); // extern int settingSpeed; extern int setting_step_delay; @@ -51,7 +57,7 @@ extern int setting_step_delay; enum { KM_START=1, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_REFPOS, KM_SCALE, KM_ATTENUATION, - KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_DRIVE, KM_LOWOUTLEVEL, KM_HIGHOUTLEVEL + KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_DRIVE, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE }; @@ -157,7 +163,8 @@ static const keypads_t * const keypads_mode_tbl[] = { keypads_level, // sample time keypads_scale, // drive keypads_level, // KM_LOWOUTLEVEL - keypads_level, // KM_HIGHOUTLEVEL + keypads_level, // KM_DECAY + keypads_level, // KM_NOISE }; #ifdef __VNA__ @@ -167,7 +174,7 @@ static const char * const keypad_mode_label[] = { #endif #ifdef __SA__ static const char * const keypad_mode_label[] = { - "error", "START", "STOP", "CENTER", "SPAN", "CW FREQ", "REFPOS", "SCALE", "\2ATTENUATE\0 0-31dB", "ACTUALPOWER", "IF", "SAMPLE TIME", "DRIVE", "LEVEL", "LEVEL" + "error", "START", "STOP", "CENTER", "SPAN", "CW FREQ", "REFPOS", "SCALE", "\2ATTENUATE\0 0-31dB", "ACTUALPOWER", "IF", "SAMPLE TIME", "DRIVE", "LEVEL", "LEVEL", "LEVEL" }; #endif @@ -210,9 +217,7 @@ void menu_autosettings_cb(int item, uint8_t data) { (void)item; (void)data; - int current_mode = GetMode(); - SetMode(-1); // Force setmode to do something - SetMode(current_mode); + reset_settings(GetMode()); active_marker = 0; for (int i = 1; i