diff --git a/main.c b/main.c index 2e4a0ca..c1d834b 100644 --- a/main.c +++ b/main.c @@ -1333,6 +1333,9 @@ set_frequencies(freq_t start, freq_t stop, uint16_t points) freq_t getFrequency(uint16_t idx) {return frequencies[idx];} #endif #else +#ifdef __BANDS__ +static uint8_t _f_band_index[POINTS_COUNT]; +#endif static freq_t _f_start; static freq_t _f_delta; static freq_t _f_error; @@ -1341,6 +1344,40 @@ static uint16_t _f_count; static void set_frequencies(freq_t start, freq_t stop, uint16_t points) { +#ifdef __BANDS__ + if (setting.multi_band && !setting.multi_trace) { + + freq_t span = 0; + for (int i=0; i= points) + return; + } + else { + b++; + break; + } + } + } while (b < BANDS_MAX); + return; + } +#endif freq_t span = stop - start; _f_start = start; _f_count = (points - 1); @@ -1349,7 +1386,26 @@ set_frequencies(freq_t start, freq_t stop, uint16_t points) setting.frequency_step = _f_delta; dirty = true; } -freq_t getFrequency(uint16_t idx) {return _f_start + _f_delta * idx + (_f_count / 2 + _f_error * idx) / _f_count;} +freq_t getFrequency(uint16_t idx) { +#ifdef __BANDS__ + if (setting.multi_band && !setting.multi_trace) { + if (idx >= POINTS_COUNT) + idx = POINTS_COUNT-1; + int b = _f_band_index[idx]; + band_t *bp = &setting.bands[b]; + freq_t f = bp->start + ((bp->end- bp->start) * (idx - bp->start_index)) / (bp->stop_index - bp->start_index) ; + return f; + } else +#endif + return _f_start + _f_delta * idx + (_f_count / 2 + _f_error * idx) / _f_count;} +#endif + +#ifdef __BANDS__ +int getBand(uint16_t idx) { + if (setting.multi_band && !setting.multi_trace) + return _f_band_index[idx]; + return 0; +} #endif @@ -1438,6 +1494,26 @@ set_sweep_frequency(int type, freq_t freq) freq_t get_sweep_frequency(int type) { +#ifdef __BANDS__ + if (setting.multi_band && !setting.multi_trace) { + switch (type) { + case ST_START: return getFrequency(0); + case ST_STOP: return getFrequency(sweep_points); + case ST_CENTER: return (getFrequency(sweep_points) + getFrequency(0))/2; + case ST_SPAN: + { + freq_t span = 0; + for (int i=0; i setting.frequency1) { freq_t t = setting.frequency0; diff --git a/nanovna.h b/nanovna.h index 30bd4e7..afa2924 100644 --- a/nanovna.h +++ b/nanovna.h @@ -1162,10 +1162,12 @@ void spi_init(void); #ifdef __BANDS__ #define BANDS_MAX 8 typedef struct { - bool enabled; - freq_t start; - freq_t end; - float level; + bool enabled; + freq_t start; + freq_t end; + float level; + int start_index; + int stop_index; } band_t; #endif @@ -1227,6 +1229,10 @@ typedef struct setting uint8_t draw_line; // uses the trigger level setting #ifdef TINYSA4 uint8_t lock_display; +#endif +#ifdef __BANDS__ + uint8_t multi_band; + uint8_t multi_trace; #endif uint16_t repeat; // 1...100 uint16_t linearity_step; // range equal POINTS_COUNT @@ -1434,7 +1440,7 @@ typedef struct properties { //sizeof(properties_t) == 0x1200 #define CONFIG_MAGIC 0x434f4e60 /* 'CONF' */ -#define SETTING_MAGIC 0x434f4e61 +#define SETTING_MAGIC 0x434f4e62 extern int16_t lastsaveid; //extern properties_t *active_props; @@ -1449,6 +1455,10 @@ freq_t getFrequency(uint16_t idx); #else freq_t getFrequency(uint16_t idx); #endif +#ifdef __BANDS__ +int getBand(uint16_t idx); +#endif + //#define frequency0 current_props._frequency0 //#define frequency1 current_props._frequency1 #define sweep_points setting._sweep_points @@ -1767,9 +1777,9 @@ void interpolate_maximum(int m); void calibrate_modulation(int modulation, int8_t *correction); enum { - M_OFF, M_IMD, M_OIP3, M_PHASE_NOISE, M_SNR, M_PASS_BAND, M_LINEARITY, M_AM, M_FM, M_THD, M_CP, M_NF_TINYSA, M_NF_STORE, M_NF_VALIDATE, M_NF_AMPLIFIER, M_BANDS, M_DECONV,M_MAX + M_OFF, M_IMD, M_OIP3, M_PHASE_NOISE, M_SNR, M_PASS_BAND, M_LINEARITY, M_AM, M_FM, M_THD, M_CP, M_NF_TINYSA, M_NF_STORE, M_NF_VALIDATE, M_NF_AMPLIFIER, M_DECONV,M_MAX }; -#define MEASUREMENT_TEXT "OFF","IMD","OIP3","PN","SNR","PASS","LIN","AM","FM","THD","CP","NF T","NF S","NF V","NF A","MULTI","DECONF" +#define MEASUREMENT_TEXT "OFF","IMD","OIP3","PN","SNR","PASS","LIN","AM","FM","THD","CP","NF T","NF S","NF V","NF A", "DECONF" enum { T_AUTO, T_NORMAL, T_SINGLE, T_DONE, T_UP, T_DOWN, T_MODE, T_PRE, T_POST, T_MID, T_BEEP, diff --git a/plot.c b/plot.c index 8ec445f..36a8260 100644 --- a/plot.c +++ b/plot.c @@ -1101,6 +1101,18 @@ draw_cell(int m, int n) } } #endif +#ifdef __BANDS__ + if (setting.multi_band && !setting.multi_trace) { + c = GET_PALTETTE_COLOR(LCD_TRIGGER_COLOR); + for (x = 0; x < w; x++) { + int idx1 = ((x+x0) * sweep_points) / WIDTH; + int idx2 = ((x+x0+1) * sweep_points) / WIDTH; + if (getBand(idx1) != getBand(idx2) && idx2 < WIDTH-2) { + for (y = 0; y < h; y++) cell_buffer[y * CELLWIDTH + x] = c; + } + } + } +#endif // PULSE; #endif // Draw trigger line @@ -1823,7 +1835,22 @@ draw_frequencies(void) return; if (current_menu_is_form() && !in_selftest) return; - +#ifdef __BANDS__ + if (setting.multi_band && !setting.multi_trace) { + ili9341_set_foreground(LCD_FG_COLOR); + ili9341_set_background(LCD_BG_COLOR); + ili9341_fill(FREQUENCIES_XPOS1, CHART_BOTTOM + 1, LCD_WIDTH - FREQUENCIES_XPOS1, LCD_HEIGHT - CHART_BOTTOM - 1); + int idx=0; + do { + int b = getBand(idx); +// plot_printf(buf1, sizeof(buf1), "%.3QHz-%.3QHz %5.1QHz/", setting.bands[b].start + (setting.frequency_offset - FREQUENCY_SHIFT), setting.bands[b].end + (setting.frequency_offset - FREQUENCY_SHIFT), grid_span); + plot_printf(buf1, sizeof(buf1), "%.3QHz %5.1QHz/", setting.bands[b].start + (setting.frequency_offset - FREQUENCY_SHIFT), grid_span); + ili9341_drawstring(buf1, FREQUENCIES_XPOS1+idx, FREQUENCIES_YPOS); + while (b == getBand(++idx)); + } while (idx < sweep_points - 10); + return; + } +#endif char *shift = (setting.frequency_offset == FREQUENCY_SHIFT ? "" : "shifted"); if (FREQ_IS_CW()) { plot_printf(buf1, sizeof(buf1), " CW %QHz", get_sweep_frequency(ST_CW) + (setting.frequency_offset - FREQUENCY_SHIFT)); diff --git a/sa_core.c b/sa_core.c index 017e4a5..abf8182 100644 --- a/sa_core.c +++ b/sa_core.c @@ -4847,6 +4847,12 @@ static bool sweep(bool break_on_operation) #endif if (dirty) { // Calculate new scanning solution +#ifdef __BANDS__ + if (setting.multi_band && ! setting.multi_trace) { + set_frequencies(0,0,sweep_points); + update_rbw(); + } +#endif sweep_counter = 0; if (get_sweep_frequency(ST_SPAN) < 300000) // Check if AM signal check_for_AM = true; @@ -4880,7 +4886,7 @@ static bool sweep(bool break_on_operation) again: // Waiting for a trigger jumps back to here #ifdef __BANDS__ - if (setting.measurement == M_BANDS) { + if (setting.multi_band && setting.multi_trace) { do { current_band++; if (current_band > BANDS_MAX) @@ -4891,17 +4897,14 @@ static bool sweep(bool break_on_operation) last_band = current_band; set_sweep_frequency(ST_START, setting.bands[current_band].start); set_sweep_frequency(ST_STOP, setting.bands[current_band].end); - set_step_delay(SD_FAST); - set_rbw(8000); - set_sweep_points((setting.bands[current_band].end - setting.bands[current_band].start) / 800000); +// set_step_delay(SD_FAST); +// set_rbw(8000); +// set_sweep_points((setting.bands[current_band].end - setting.bands[current_band].start) / 800000); setting.trigger_level = setting.bands[current_band].level; setting.auto_attenuation = false; } - set_audio_mode(A_PWM); - pwm_stop(); } else { last_band = -1; - set_audio_mode(A_DAC); } #endif #ifdef __BEEP__ diff --git a/ui.c b/ui.c index 2213175..4a929f3 100644 --- a/ui.c +++ b/ui.c @@ -1468,8 +1468,8 @@ static const menuitem_t menu_limit_modify[]; static const menuitem_t menu_limit_select[]; #endif #ifdef __BANDS__ -static const menuitem_t menu_BAND_modify[]; -static const menuitem_t menu_BAND_select[]; +static const menuitem_t menu_band_modify[]; +static const menuitem_t menu_band_select[]; #endif static const menuitem_t menu_average[]; static const menuitem_t menu_reffer[]; @@ -2874,9 +2874,9 @@ validate: } break; #endif -#ifdef __BANDS__ +#ifdef __BANDS__xx case M_BANDS: - menu_push_submenu(menu_BAND_select); + menu_push_submenu(menu_band_select); goto leave; break; #endif @@ -3200,10 +3200,39 @@ static UI_FUNCTION_ADV_CALLBACK(menu_band_select_acb) setting.bands[active_band].enabled = true; dirty = true; update_frequencies(); + update_grid(); // BANDs_update(); - menu_push_submenu(menu_BAND_modify); + menu_push_submenu(menu_band_modify); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_multi_band_acb) +{ + (void)item; + (void)data; + if(b){ + b->icon = (setting.multi_band?BUTTON_ICON_CHECK:BUTTON_ICON_NOCHECK) ; + return; + } + dirty = true; + setting.multi_band = ! setting.multi_band; + redraw_request|= REDRAW_AREA | REDRAW_FREQUENCY | REDRAW_CAL_STATUS; + if (setting.multi_band) menu_push_submenu(menu_band_select); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_multi_trace_acb) +{ + (void)item; + (void)data; + if(b){ + b->icon = (setting.multi_trace?BUTTON_ICON_CHECK:BUTTON_ICON_NOCHECK) ; + return; + } + dirty = true; + setting.multi_trace = ! setting.multi_trace; + redraw_request|= REDRAW_AREA | REDRAW_FREQUENCY | REDRAW_CAL_STATUS; } +# #endif extern const menuitem_t menu_marker_select[]; @@ -3345,6 +3374,7 @@ static UI_FUNCTION_CALLBACK(menu_BAND_disable_cb) setting.bands[active_band].enabled = false; dirty = true; update_frequencies(); + update_grid(); // BANDs_update(); menu_move_back(false); } @@ -3770,7 +3800,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_enter_marker_acb) } #ifdef TINYSA4 -static const uint16_t points_setting[] = {51, 101, 201, 256, 290, 450}; +static const uint16_t points_setting[] = {25, 50, 100, 200, 290, 450}; #else static const uint16_t points_setting[] = {51, 101, 145, 290}; #endif @@ -4160,17 +4190,18 @@ static const menuitem_t menu_limit_select[] = { #endif #ifdef __BANDS__ -static const menuitem_t menu_BAND_modify[] = +static const menuitem_t menu_band_modify[] = { { MT_KEYPAD, KM_BAND_START, "START\n\b%s", "Start"}, { MT_KEYPAD, KM_BAND_END, "STOP\n\b%s", "Stop"}, - { MT_KEYPAD, KM_BAND_LEVEL, "LEVEL\n\b%s", "Level"}, - { MT_CALLBACK,0, "DISABLE", menu_BAND_disable_cb}, + { MT_KEYPAD, KM_BAND_LEVEL, "LEVEL\n\b%s", "Level"}, + { MT_CALLBACK,0, "DISABLE", menu_BAND_disable_cb}, { MT_NONE, 0, NULL, menu_back} // next-> menu_back }; -static const menuitem_t menu_BAND_select[] = { - { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,BANDS_MAX), MT_CUSTOM_LABEL, menu_band_select_acb }, +static const menuitem_t menu_band_select[] = { + { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,BANDS_MAX), MT_CUSTOM_LABEL, menu_band_select_acb }, + { MT_ADV_CALLBACK, 0 , "MULTI\nTRACE", menu_multi_trace_acb }, #ifdef __USE_SD_CARD__ { MT_CALLBACK, FMT_BND_FILE, "BANDS"S_RARROW"\nSD", menu_sdcard_cb}, #ifdef __SD_FILE_BROWSER__ @@ -4511,9 +4542,9 @@ static const menuitem_t menu_measure2[] = { #ifdef __NOISE_FIGURE__ { MT_SUBMENU | MT_LOW, 0, "NOISE\nFIGURE", menu_measure_noise_figure}, #endif -#ifdef __BANDS__ -{ MT_ADV_CALLBACK, M_BANDS, "MULTI\nBAND", menu_measure_acb}, -#endif +//#ifdef __BANDS__ +//{ MT_ADV_CALLBACK, M_BANDS, "MULTI\nBAND", menu_measure_acb}, +//#endif #ifdef __FFT_DECONV__ { MT_ADV_CALLBACK, M_DECONV, "DECONV", menu_measure_acb}, #endif @@ -4775,6 +4806,9 @@ static const menuitem_t menu_stimulus[] = { { MT_KEYPAD, KM_CENTER, "CENTER\n\b%s", NULL}, { MT_KEYPAD, KM_SPAN, "SPAN\n\b%s", NULL}, { MT_KEYPAD, KM_CW, "ZERO SPAN", NULL}, +#ifdef __BANDS__ + { MT_ADV_CALLBACK, 0, "MULTI\nBAND", menu_multi_band_acb}, +#endif { MT_SUBMENU,0, "RBW", menu_rbw}, #ifdef __VBW__ { MT_SUBMENU, 0, "VBW", menu_vbw}, @@ -5258,18 +5292,21 @@ set_numeric_value(void) setting.bands[active_band].start = uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT); update_frequencies(); dirty = true; + update_grid(); // BANDs_update(); break; case KM_BAND_END: setting.bands[active_band].end = uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT); update_frequencies(); dirty = true; + update_grid(); // BANDs_update(); break; case KM_BAND_LEVEL: setting.bands[active_band].level = to_dBm(uistat.value); update_frequencies(); dirty = true; + update_grid(); // BANDs_update(); break; #endif @@ -5572,7 +5609,13 @@ redraw_cal_status: } quick_menu_y[max_quick_menu] = y; quick_menu[max_quick_menu++] = (menuitem_t *)NULL; - +#ifdef __BANDS__ + if (setting.multi_band){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "MULTI"); + y += 2*YSTEP + YSTEP/2; + } +#endif #ifdef TINYSA4 if (setting.measurement != M_OFF){ ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN);