diff --git a/nanovna.h b/nanovna.h index 524b2aa..ba14262 100644 --- a/nanovna.h +++ b/nanovna.h @@ -287,6 +287,7 @@ void request_to_draw_cells_behind_menu(void); void request_to_draw_cells_behind_numeric_input(void); void redraw_marker(int marker, int update_info); void plot_into_index(float measured[2][POINTS_COUNT][2]); +void get_trace_autoscale(int t, float *scale, float *refpos, const float array[101][2]); void force_set_markmap(void); void draw_frequencies(void); void draw_all(bool flush); diff --git a/plot.c b/plot.c index 70f5e31..5a42058 100644 --- a/plot.c +++ b/plot.c @@ -436,7 +436,7 @@ groupdelay(const float *v, const float *w, float deltaf) static float linear(const float *v) { - return - sqrtf(v[0]*v[0] + v[1]*v[1]); + return sqrtf(v[0]*v[0] + v[1]*v[1]); } /* @@ -451,6 +451,16 @@ swr(const float *v) return (1 + x)/(1 - x); } +float real(const float *v) +{ + return v[0]; +} + +float imag(const float *v) +{ + return v[1]; +} + static float resitance(const float *v) { float z0 = 50; @@ -549,14 +559,112 @@ trace_into_index(int t, int i, float array[POINTS_COUNT][2]) cartesian_scale(coeff[0], coeff[1], &x, &y, scale); goto set_index; } - if (v < 0) v = 0; - if (v > NGRIDY) v = NGRIDY; + if (v < 0) v = 0; + if (v > 8) v = 8; x = (i * (WIDTH) + (sweep_points-1)/2) / (sweep_points-1) + CELLOFFSETX; y = floatToInt(v * GRIDY); set_index: return INDEX(x, y); } + +/** find minimum-max range of the data array using a specific function to evaluate the single point + * @param array[in] is the data array + * @param fmetric[in] is the function to be used for point evaluation + * @param min[out] is te minimum found value + * @param max[out] is the maximum found value + */ + +static void find_min_max(const float array[101][2], float(*const fmetric)(const float *), float *min, float *max) +{ + float v, m, M; + m = M = fmetric(array[0]); + for (int i = 1; i<101; i++) { + v = fmetric(array[i]); + if (v > M) + M = v; + else if (v < m) + m = v; + } + *min = m; + *max = M; +} + +/** Get the autoscale values for the given trace + * @param t[in] the trace to be autoscaled + * @param scale[inout] the scale value to be calculated (initialized with the current value) + * @param refpos[inout] the reference position to be calculated (initialized with the current value) + * @param array[in] data point set + */ + +void +get_trace_autoscale(int t, float *scale, float *refpos, const float array[101][2]) +{ + float min, max, sc = *scale, rp = *refpos; + switch (trace[t].type) { + case TRC_LOGMAG: + find_min_max(array, logmag, &min, &max); + sc = (max-min)/7; + if (sc < 1) sc = ceil(sc*10)/10; + else if (sc < 10) sc = ceil(sc); + else sc = ceil(sc/10)*10; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_PHASE: + find_min_max(array, phase, &min, &max); + sc = (max-min)/7; + if (sc < 10) sc = ceil(sc); + else sc = ceil(sc/5)*5; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_DELAY: + case TRC_LINEAR: + find_min_max(array, linear, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_SWR: + find_min_max(array, swr, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + else if (sc > 30) sc = 30; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_REAL: + find_min_max(array, real, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_IMAG: + find_min_max(array, imag, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_R: + find_min_max(array, resitance, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_X: + find_min_max(array, reactance, &min, &max); + sc = (max-min)/7; + if (sc < 1e-12) sc = 1e-12; + rp = 4 - (min+max) / 2 / sc; + break; + case TRC_SMITH: + //case TRC_ADMIT: + case TRC_POLAR: + break; + } + *scale = sc; + *refpos = rp; + return; +} + static void format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) { diff --git a/ui.c b/ui.c index 681c8bb..d9777b9 100644 --- a/ui.c +++ b/ui.c @@ -119,6 +119,7 @@ static void leave_ui_mode(void); static void erase_menu_buttons(void); static void ui_process_keypad(void); static void ui_process_numeric(void); +static void ui_process_autoscale(void); static void menu_move_back(void); static void menu_push_submenu(const menuitem_t *submenu); @@ -660,7 +661,9 @@ menu_scale_cb(int item, uint8_t data) if (data == KM_SCALE && trace[uistat.current_trace].type == TRC_DELAY) { data = KM_SCALEDELAY; } - if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) { + if (item == 3){ + ui_process_autoscale(); + } else if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) { ui_mode_numeric(data); ui_process_numeric(); } else { @@ -908,6 +911,7 @@ const menuitem_t menu_scale[] = { { MT_CALLBACK, KM_SCALE, "SCALE/DIV", menu_scale_cb }, { MT_CALLBACK, KM_REFPOS, "\2REFERENCE\0POSITION", menu_scale_cb }, { MT_CALLBACK, KM_EDELAY, "\2ELECTRICAL\0DELAY", menu_scale_cb }, + { MT_CALLBACK, 0, "AUTO", menu_scale_cb }, { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel }; @@ -1947,6 +1951,17 @@ numeric_apply_touch(void) return; } +static void +ui_process_autoscale(void) +{ + float refpos = get_trace_refpos(uistat.current_trace); + float scale = get_trace_scale(uistat.current_trace); + get_trace_autoscale(uistat.current_trace, &scale, &refpos, measured[trace[uistat.current_trace].channel]); + set_trace_refpos(uistat.current_trace, refpos); + set_trace_scale(uistat.current_trace, scale); + ui_mode_normal(); +} + static void ui_process_numeric(void) {