diff --git a/nanovna.h b/nanovna.h index 22d073e..6b3ea05 100644 --- a/nanovna.h +++ b/nanovna.h @@ -18,7 +18,7 @@ */ #include "ch.h" -#ifdef TINYSA_F303 +//#ifdef TINYSA_F303 #include "adc_F303.h" #ifdef TINYSA_F072 #error "Remove comment for #ifdef TINYSA_F303" @@ -27,7 +27,7 @@ #define TINYSA4 #endif #define TINYSA4_PROTO -#endif +//#endif #ifdef TINYSA_F072 #ifdef TINYSA_F303 @@ -124,7 +124,11 @@ #else #define POINTS_COUNT 290 #endif +#ifdef TINYSA4 +#define MARKER_COUNT 8 +#else #define MARKER_COUNT 4 +#endif #define TRACES_MAX 3 #define TRACE_ACTUAL 0 // order linked to redraw_request flags!!!!! @@ -254,7 +258,7 @@ void toggle_pulse(void); void load_default_properties(void); enum { - AV_OFF, AV_MIN, AV_MAX_HOLD, AV_MAX_DECAY, AV_4, AV_16, AV_QUASI + AV_OFF, AV_MIN, AV_MAX_HOLD, AV_MAX_DECAY, AV_4, AV_16, AV_QUASI, AV_DECONV }; enum { M_LOW, M_HIGH, M_GENLOW, M_GENHIGH, M_ULTRA @@ -769,7 +773,7 @@ extern uint8_t active_limit; extern void limits_update(void); #endif -#define MARKERS_MAX 4 +#define MARKERS_MAX MARKER_COUNT #define MARKER_INVALID -1 extern int8_t previous_marker; @@ -1432,7 +1436,7 @@ void interpolate_maximum(int m); void calibrate_modulation(int modulation, int8_t *correction); enum { - M_OFF, M_IMD, M_OIP3, M_PHASE_NOISE, M_STOP_BAND, M_PASS_BAND, M_LINEARITY, M_AM, M_FM, M_THD, M_CP, + M_OFF, M_IMD, M_OIP3, M_PHASE_NOISE, M_STOP_BAND, M_PASS_BAND, M_LINEARITY, M_AM, M_FM, M_THD, M_CP, M_DECONV }; enum { diff --git a/plot.c b/plot.c index 05844b4..9af3490 100644 --- a/plot.c +++ b/plot.c @@ -511,7 +511,11 @@ static inline void markmap_upperarea(void) { // Hardcoded, Text info from upper area +#if MARKER_COUNT == 4 invalidate_rect(0, 0, AREA_WIDTH_NORMAL, 31); +#else + invalidate_rect(0, 0, AREA_WIDTH_NORMAL, 63); +#endif } static uint16_t get_trigger_level(void){ @@ -627,7 +631,8 @@ static const uint8_t reference_bitmap[]={ #define X_MARKER_OFFSET 3 #define Y_MARKER_OFFSET 10 #define MARKER_BITMAP(i) (&marker_bitmap[(i)*MARKER_HEIGHT]) -static const uint8_t marker_bitmap[]={ +static const uint8_t marker_bitmap[]= +{ // Marker Back plate _BMP8(0b11111110), _BMP8(0b11111110), @@ -683,6 +688,53 @@ static const uint8_t marker_bitmap[]={ _BMP8(0b00001000), _BMP8(0b00000000), _BMP8(0b00000000), +#if MARKER_COUNT > 4 + // Marker 5 + _BMP8(0b00000000), + _BMP8(0b11110000), + _BMP8(0b10000000), + _BMP8(0b11100000), + _BMP8(0b00010000), + _BMP8(0b00010000), + _BMP8(0b10010000), + _BMP8(0b01100000), + _BMP8(0b00000000), + _BMP8(0b00000000), + // Marker 6 + _BMP8(0b00000000), + _BMP8(0b01100000), + _BMP8(0b10010000), + _BMP8(0b10000000), + _BMP8(0b11100000), + _BMP8(0b10010000), + _BMP8(0b10010000), + _BMP8(0b01100000), + _BMP8(0b00000000), + _BMP8(0b00000000), + // Marker 7 + _BMP8(0b00000000), + _BMP8(0b11110000), + _BMP8(0b00010000), + _BMP8(0b00100000), + _BMP8(0b00100000), + _BMP8(0b01000000), + _BMP8(0b01000000), + _BMP8(0b01000000), + _BMP8(0b00000000), + _BMP8(0b00000000), + // Marker 8 + _BMP8(0b00000000), + _BMP8(0b01100000), + _BMP8(0b10010000), + _BMP8(0b10010000), + _BMP8(0b01100000), + _BMP8(0b10010000), + _BMP8(0b10010000), + _BMP8(0b01100000), + _BMP8(0b00000000), + _BMP8(0b00000000), + +#endif }; #elif _MARKER_SIZE_ == 1 @@ -691,7 +743,8 @@ static const uint8_t marker_bitmap[]={ #define X_MARKER_OFFSET 4 #define Y_MARKER_OFFSET 13 #define MARKER_BITMAP(i) (&marker_bitmap[(i)*2*MARKER_HEIGHT]) -static const uint8_t marker_bitmap[]={ +static const uint8_t marker_bitmap[]= +{ // Marker Back plate _BMP16(0b1111111110000000), _BMP16(0b1111111110000000), @@ -762,6 +815,64 @@ static const uint8_t marker_bitmap[]={ _BMP16(0b0000000000000000), _BMP16(0b0000000000000000), _BMP16(0b0000000000000000), +#if MARKER_COUNT>4 + // Marker 5 + _BMP16(0b0000000000000000), + _BMP16(0b11111100<<6), + _BMP16(0b11000000<<6), + _BMP16(0b11000000<<6), + _BMP16(0b11111000<<6), + _BMP16(0b11001100<<6), + _BMP16(0b00001100<<6), + _BMP16(0b00001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b01111000<<6), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + // Marker 6 + _BMP16(0b0000000000000000), + _BMP16(0b01111000<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11000000<<6), + _BMP16(0b11000000<<6), + _BMP16(0b11111000<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b01111000<<6), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + // Marker 7 + _BMP16(0b0000000000000000), + _BMP16(0b11111100<<6), + _BMP16(0b00001100<<6), + _BMP16(0b00001100<<6), + _BMP16(0b00011000<<6), + _BMP16(0b00011000<<6), + _BMP16(0b00110000<<6), + _BMP16(0b00110000<<6), + _BMP16(0b01100000<<6), + _BMP16(0b01100000<<6), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + // Marker 8 + _BMP16(0b0000000000000000), + _BMP16(0b01111000<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b01111000<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b11001100<<6), + _BMP16(0b01111000<<6), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), +#endif }; #endif @@ -994,7 +1105,7 @@ draw_cell(int m, int n) #endif // Draw trace and marker info on the top (50 system ticks for all screen calls) #if 1 - if (n == 0) + if (n <= (MARKERS_MAX > 4 ? 1 : 0)) cell_draw_marker_info(x0, y0); #endif #ifdef __SELFTEST__ diff --git a/sa_core.c b/sa_core.c index 17f99c7..5f79b10 100644 --- a/sa_core.c +++ b/sa_core.c @@ -2137,7 +2137,7 @@ int index_of_frequency(freq_t f) // Search which index in the frequency tab return -1; if (f > frequencies[sweep_points-1]) return -1; - int i = (f + (f_step >> 1))* sweep_points / (frequencies[sweep_points-1] - frequencies[0]); + int i = (f + (f_step >> 1)) / f_step; return i; #if 0 // int R = (sizeof frequencies)/sizeof(int) - 1; @@ -2180,18 +2180,22 @@ void interpolate_maximum(int m) } } -#define MAX_MAX 4 +#define MAX_MAX MARKER_COUNT int search_maximum(int m, freq_t center, int span) { +#ifdef TINYSA4 int center_index = index_of_frequency(center); +#else + int center_index = binary_search_frequency(center); +#endif if (center_index < 0) return false; int from = center_index - span/2; int found = false; int to = center_index + span/2; int cur_max = 0; // Always at least one maximum - int max_index[4]; + int max_index[MAX_MAX]; if (from<0) from = 0; if (to > setting._sweep_points-1) @@ -3608,7 +3612,6 @@ again: // Spur redu } -#define MAX_MAX 4 static uint16_t max_index[MAX_MAX]; static uint16_t cur_max = 0; @@ -3815,6 +3818,13 @@ static bool sweep(bool break_on_operation) } #endif +#ifdef TINYSA4 + int d_half_width = 0; + if (setting.average == AV_DECONV && setting.frequency_step != 0) { + d_half_width = (frequencies[sweep_points-1] - frequencies[0]) / (actual_rbw_x10 * 100); + } +#endif + for (int i = 0; i < sweep_points; i++) { #if 0 @@ -3884,6 +3894,16 @@ static bool sweep(bool break_on_operation) actual_t[i] = old_RSSI; } break; +#endif +#ifdef TINYSA4 + case AV_DECONV: + actual_t[i] = temp_t[i]; + int f_start = sweep_points/2 - d_half_width; + int lower = ( i - d_half_width*2 + 1 < 0 ? 0 : i - d_half_width*2 + 1); + for (int k = lower; k < i; k++) + actual_t[i] -= actual_t[k] * stored_t[f_start + i - k]; + actual_t[i] /= stored_t[0]; + break; #endif } } @@ -3943,7 +3963,15 @@ static bool sweep(bool break_on_operation) } } // end of peak finding } - } // ---------------------- end of postprocessing ----------------------------- + if (setting.average == AV_DECONV && setting.frequency_step != 0) { + for (int i = sweep_points - 1 - d_half_width*2; i>0; i--) { + actual_t[i+d_half_width] = actual_t[i]; + } + } + } + + + // ---------------------- end of postprocessing ----------------------------- if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE) { // if in output mode with modulation if (!in_selftest) @@ -4231,9 +4259,8 @@ static bool sweep(bool break_on_operation) #else #define H_SPACING 4 #endif - markers[1].enabled = search_maximum(1, frequencies[markers[0].index]*2, 2*H_SPACING); - markers[2].enabled = search_maximum(2, frequencies[markers[0].index]*3, 3*H_SPACING); - markers[3].enabled = search_maximum(3, frequencies[markers[0].index]*4, 4*H_SPACING); + for (int i=1; i < MARKER_COUNT;i++) + markers[i].enabled = search_maximum(i, frequencies[markers[0].index]*(i+1), (i+1)*H_SPACING); #ifdef TINYSA4 } else if (setting.measurement == M_AM && markers[0].index > 10) { // ----------AM measurement int l = markers[1].index; @@ -4266,7 +4293,7 @@ static bool sweep(bool break_on_operation) markers[2].enabled = search_maximum(2, lf - (rf - lf), 12); markers[3].enabled = search_maximum(3, rf + (rf - lf), 12); } else if (setting.measurement == M_PHASE_NOISE && markers[0].index > 10) { // ------------Phase noise measurement - markers[1].index = markers[0].index + (setting.mode == M_LOW ? 290/4 : -290/4); // Position phase noise marker at requested offset + markers[1].index = markers[0].index + (setting.mode == M_LOW ? WIDTH/4 : -WIDTH/4); // Position phase noise marker at requested offset markers[1].frequency = frequencies[markers[1].index]; } else if (setting.measurement == M_STOP_BAND && markers[0].index > 10) { // -------------Stop band measurement markers[1].index = marker_search_left_min(markers[0].index); diff --git a/ui_sa.c b/ui_sa.c index 189a74a..0415529 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -1137,6 +1137,10 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) return; } menu_move_back(false); + for (int i = 0; i< MARKERS_MAX; i++) { + markers[i].enabled = M_DISABLED; + markers[i].mtype = M_NORMAL; + } #ifdef __MEASURE__ if ((data != M_OFF && setting.measurement != M_OFF) || data == M_OFF ) @@ -1149,10 +1153,6 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) if (setting.measurement == M_LINEARITY) { TRACE_DISABLE(TRACE_STORED_FLAG); } - for (int i = 0; i< MARKERS_MAX; i++) { - markers[i].enabled = M_DISABLED; - markers[i].mtype = M_NORMAL; - } markers[0].enabled = M_ENABLED; markers[0].mtype = M_REFERENCE | M_TRACKING; set_average(AV_OFF); @@ -1171,18 +1171,13 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) kp_help_text = "Frequency of fundamental"; ui_mode_keypad(KM_CENTER); set_sweep_frequency(ST_START, 0); -#ifdef TINYSA4 -#define IMD_RANGE 10 -#else -#define IMD_RANGE 5 -#endif - set_sweep_frequency(ST_STOP, uistat.value*IMD_RANGE); + set_sweep_frequency(ST_STOP, uistat.value*(MARKERS_MAX+1)); set_average(AV_4); // set_measurement(M_IMD); break; case M_OIP3: // OIP3 reset_settings(setting.mode); - for (int i = 0; i< MARKERS_MAX; i++) { + for (int i = 0; i< 4; i++) { markers[i].enabled = M_ENABLED; markers[i].mtype = M_DELTA; } @@ -1201,10 +1196,6 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) break; case M_PHASE_NOISE: // Phase noise reset_settings(setting.mode); - for (int i = 0; i< MARKERS_MAX; i++) { - markers[i].enabled = M_DISABLED; - markers[i].mtype = M_NORMAL; - } markers[0].enabled = M_ENABLED; markers[0].mtype = M_REFERENCE | M_TRACKING; markers[1].enabled = M_ENABLED; @@ -1342,6 +1333,9 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) set_sweep_frequency(ST_SPAN, uistat.value*3); // set_measurement(M_CP); break; + case M_DECONV: + set_average(AV_DECONV); + break; #endif } set_measurement(data); @@ -2275,6 +2269,18 @@ const menuitem_t menu_marker_select[] = { { MT_ADV_CALLBACK, 2, "MARKER %d", menu_marker_select_acb }, { MT_ADV_CALLBACK, 3, "MARKER %d", menu_marker_select_acb }, { MT_ADV_CALLBACK, 4, "MARKER %d", menu_marker_select_acb }, +#if MARKER_COUNT >= 5 + { MT_ADV_CALLBACK, 5, "MARKER %d", menu_marker_select_acb }, +#endif +#if MARKER_COUNT >= 6 + { MT_ADV_CALLBACK, 6, "MARKER %d", menu_marker_select_acb }, +#endif +#if MARKER_COUNT >= 7 + { MT_ADV_CALLBACK, 7, "MARKER %d", menu_marker_select_acb }, +#endif +#if MARKER_COUNT >= 8 + { MT_ADV_CALLBACK, 8, "MARKER %d", menu_marker_select_acb }, +#endif { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel }; @@ -2542,8 +2548,11 @@ static const menuitem_t menu_measure2[] = { #ifdef __CHANNEL_POWER__ { MT_ADV_CALLBACK, M_CP, "CHANNEL\nPOWER",menu_measure_acb}, #endif - #ifdef __LINEARITY__ - { MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, +#ifdef __LINEARITY__ +{ MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, +#endif +#ifdef TINYSA4 + { MT_ADV_CALLBACK, M_DECONV, "DECONV", menu_measure_acb}, #endif { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel