diff --git a/nanovna.h b/nanovna.h index ad998a5..9bbe4b8 100644 --- a/nanovna.h +++ b/nanovna.h @@ -83,7 +83,7 @@ #define MARKER_COUNT 4 #define TRACES_MAX 3 -#define TRACE_AGE 3 +//#define TRACE_AGE 3 #define TRACE_ACTUAL 2 #define TRACE_STORED 1 #define TRACE_TEMP 0 @@ -246,6 +246,7 @@ void toggle_ultra(void); int get_refer_output(void); void set_attenuation(float); float get_attenuation(void); +float get_level(void); void set_harmonic(int); //extern int setting.harmonic; int search_is_greater(void); @@ -581,6 +582,7 @@ float get_trace_scale(int t); float get_trace_refpos(int t); const char *get_trace_typename(int t); extern int in_selftest; +extern int display_test(void); // // Shell config functions and macros diff --git a/plot.c b/plot.c index 44f3b1c..9fdfe48 100644 --- a/plot.c +++ b/plot.c @@ -2386,6 +2386,27 @@ redraw_frame(void) draw_cal_status(); } +int display_test(void) +{ +// return true; + // write and read display, return false on fail. + for (int h = 0; h < LCD_HEIGHT; h++) { + for (int w = 0; w < LCD_WIDTH; w++) { + spi_buffer[w] = ((w*h) & 0xfff); + } + ili9341_bulk(0, h, LCD_WIDTH, 1); + for (int w = 0; w < LCD_WIDTH; w++) { + spi_buffer[w] = 0; + } + ili9341_read_memory(0, h, LCD_WIDTH, 1, LCD_WIDTH, spi_buffer); + for (int volatile w = 0; w < LCD_WIDTH; w++) { + if (spi_buffer[w] != ((w*h) & 0xfff)) + return false; + } + } + return true; +} + //#define _USE_WATERFALL_PALETTE #ifdef _USE_WATERFALL_PALETTE #include "waterfall.c" diff --git a/sa_core.c b/sa_core.c index 3718563..f892979 100644 --- a/sa_core.c +++ b/sa_core.c @@ -1,4 +1,5 @@ -/* This is free software; you can redistribute it and/or modify +/* + * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. @@ -144,7 +145,8 @@ void reset_settings(int m) setting.measurement = M_OFF; setting.frequency_IF = config.frequency_IF1; setting.auto_IF = true; - setting.offset = 0.0; + set_offset(0.0); // This also updates the help text!!!!! + //setting.offset = 0.0; setting.trigger = T_AUTO; setting.trigger_direction = T_UP; setting.trigger_mode = T_MID; @@ -559,6 +561,14 @@ void set_level(float v) // Set the output level in dB in high/low output dirty = true; } +float get_level(void) +{ + if (setting.mode == M_GENHIGH) { + return drive_dBm[setting.lo_drive]; + } else { + return get_attenuation(); + } +} void set_attenuation(float a) // Is used both in low output mode and high/low input mode { if (setting.mode == M_GENLOW) { @@ -999,7 +1009,13 @@ extern char low_level_help_text[12]; void set_offset(float offset) { setting.offset = offset; - plot_printf(low_level_help_text, sizeof low_level_help_text, "%+d..%+d", POWER_OFFSET - 70 + (int)offset, POWER_OFFSET + (int)offset); + int min,max; + if (setting.mode == M_GENLOW) { + min = -76; max = -6; + } else { + min = -38; max = +13; + } + plot_printf(low_level_help_text, sizeof low_level_help_text, "%+d..%+d", min + (int)offset, max + (int)offset); force_set_markmap(); dirty = true; // No HW update required, only status panel refresh but need to ensure the cached value is updated in the calculation of the RSSI } @@ -1847,13 +1863,19 @@ static const int am_modulation[MODULATION_STEPS] = { 5, 1, 0, 1, 5, 9, 11, 9 }; #define HWD 48 static const int fm_modulation[4][MODULATION_STEPS] = // Avoid sign changes in NFM { - { 2*LND,(int)( 3.5*LND ), 4*LND, (int)(3.5*LND), 2*LND, (int)(0.5*LND), 0, (int)(0.5*LND)}, - { 0*LWD,(int)( 1.5*LWD ), 2*LWD, (int)(1.5*LWD), 0*LWD, (int)(-1.5*LWD), (int)-2*LWD, (int)(-1.5*LWD)}, - { 2*HND,(int)( 3.5*HND ), 4*HND, (int)(3.5*HND), 2*HND, (int)(0.5*HND), 0, (int)(0.5*HND)}, - { 0*HWD,(int)( 1.5*HWD ), 2*HWD, (int)(1.5*HWD), 0*HWD, (int)(-1.5*HWD), (int)-2*HWD, (int)(-1.5*HWD)}, + { 2*LND,(int)( 3.5*LND ), 4*LND, (int)(3.5*LND), 2*LND, (int)(0.5*LND), 0, (int)(0.5*LND)}, // Low range, NFM + { 0*LWD,(int)( 1.5*LWD ), 2*LWD, (int)(1.5*LWD), 0*LWD, (int)(-1.5*LWD), (int)-2*LWD, (int)(-1.5*LWD)}, // Low range, WFM + { 2*HND,(int)( 3.5*HND ), 4*HND, (int)(3.5*HND), 2*HND, (int)(0.5*HND), 0, (int)(0.5*HND)}, // High range, NFM + { 0*HWD,(int)( 1.5*HWD ), 2*HWD, (int)(1.5*HWD), 0*HWD, (int)(-1.5*HWD), (int)-2*HWD, (int)(-1.5*HWD)}, // HIgh range, WFM }; // narrow FM modulation avoid sign changes -static const int fm_modulation_offset[4] = { LND*625/2, 0, LND*625/2, 0}; +static const int fm_modulation_offset[4] = +{ + 85000, + 80000, + 165000, + 160000 +}; deviceRSSI_t age[POINTS_COUNT]; // Array used for 1: calculating the age of any max and 2: buffer for fast sweep RSSI values; @@ -3306,7 +3328,7 @@ marker_search_right_min(int from) // -------------------- Self testing ------------------------------------------------- enum { - TC_SIGNAL, TC_BELOW, TC_ABOVE, TC_FLAT, TC_MEASURE, TC_SET, TC_END, TC_ATTEN, + TC_SIGNAL, TC_BELOW, TC_ABOVE, TC_FLAT, TC_MEASURE, TC_SET, TC_END, TC_ATTEN, TC_DISPLAY, }; enum { @@ -3346,20 +3368,21 @@ const test_case_t test_case [] = {TC_FLAT, TP_10MHZEXTRA, 10, 8, -18, 9, -60}, // 8 BPF pass band flatness {TC_BELOW, TP_30MHZ, 400, 60, -75, 0, -75}, // 9 LPF cutoff {TC_SIGNAL, TP_10MHZ_SWITCH,20, 7, -39, 10, -60 }, // 10 Switch isolation using high attenuation - {TC_ATTEN, TP_30MHZ, 30, 0, CAL_LEVEL, 145, -60 }, // 11 Measure atten step accuracy -#define TEST_END 11 + {TC_DISPLAY, TP_30MHZ, 30, 0, -25, 145, -60 }, // 11 Measure atten step accuracy + {TC_ATTEN, TP_30MHZ, 30, 0, CAL_LEVEL, 145, -60 }, // 12 Measure atten step accuracy +#define TEST_END 12 {TC_END, 0, 0, 0, 0, 0, 0}, -#define TEST_POWER 12 +#define TEST_POWER 13 {TC_MEASURE, TP_30MHZ, 30, 7, CAL_LEVEL, 10, -55 }, // 12 Measure power level and noise {TC_MEASURE, TP_30MHZ, 270, 4, -50, 10, -75 }, // 13 Measure powerlevel and noise {TC_MEASURE, TPH_30MHZ, 270, 4, -40, 10, -65 }, // 14 Calibrate power high mode {TC_END, 0, 0, 0, 0, 0, 0}, -#define TEST_RBW 16 +#define TEST_RBW 17 {TC_MEASURE, TP_30MHZ, 30, 1, CAL_LEVEL, 10, -60 }, // 16 Measure RBW step time {TC_END, 0, 0, 0, 0, 0, 0}, {TC_MEASURE, TPH_30MHZ, 300, 4, -48, 10, -65 }, // 14 Calibrate power high mode {TC_MEASURE, TPH_30MHZ_SWITCH,300, 4, -40, 10, -65 }, // 14 Calibrate power high mode -#define TEST_ATTEN 20 +#define TEST_ATTEN 21 {TC_ATTEN, TP_30MHZ, 30, 0, -25, 145, -60 } // 20 Measure atten step accuracy }; @@ -3528,6 +3551,16 @@ int validate_atten(int i) { return(TS_PASS); } +int validate_display(int tc) +{ + test_fail_cause[tc] = "Display "; + if (!display_test()) { + return(TS_FAIL); + } + test_fail_cause[tc] = ""; + return(TS_PASS); +} + int validate_above(int tc) { int status = TS_PASS; for (int j = 0; j < setting._sweep_points; j++) { @@ -3584,6 +3617,9 @@ int test_validate(int i) case TC_ATTEN: current_test_status = validate_atten(i); break; + case TC_DISPLAY: + current_test_status = validate_display(i); + break; } // Report status diff --git a/ui.c b/ui.c index 3a879b4..56cda6e 100644 --- a/ui.c +++ b/ui.c @@ -90,7 +90,6 @@ static int selection = 0; static const uint8_t slider_bitmap[]= { - _BMP8(0b11111110), _BMP8(0b11111110), _BMP8(0b11111110), _BMP8(0b01111100), @@ -1798,6 +1797,8 @@ static const uint8_t check_box[] = { _BMP16(0b0000100001000000), _BMP16(0b0000011110000000), }; +static const char *step_text[5] = {"-10dB", "-1dB", "set", "+1dB", "+10dB"}; +static char step_text_freq[5][10] = { "-100MHz", "-10MHz", "set", "+10MHz", "+100MHz" }; static void draw_menu_buttons(const menuitem_t *menu) @@ -1862,7 +1863,7 @@ draw_menu_buttons(const menuitem_t *menu) text_offs = button_start+6+ICON_WIDTH+1; } // ili9341_drawstring_size(button.text, text_offs, y+(button_height-2*FONT_GET_HEIGHT)/2, 2); - ili9341_drawstring_10x14(button.text, text_offs, y+(button_height-wFONT_GET_HEIGHT)/2); + ili9341_drawstring_10x14(button.text, text_offs, y+(button_height-wFONT_GET_HEIGHT)/2 - 2); #ifdef __ICONS__ if (menu[i].type & MT_ICON) { blit8BitWidthBitmap(button_start+MENU_FORM_WIDTH-2*FORM_ICON_WIDTH-8,y+(button_height-FORM_ICON_HEIGHT)/2,FORM_ICON_WIDTH,FORM_ICON_HEIGHT,& left_icons[((menu[i].data >>4)&0xf)*2*FORM_ICON_HEIGHT]); @@ -1873,17 +1874,36 @@ draw_menu_buttons(const menuitem_t *menu) if (MT_MASK(menu[i].type) == MT_KEYPAD) { if (menu[i].data == KM_CENTER) { local_slider_positions = LCD_WIDTH/2+setting.slider_position; - goto draw_slider; + plot_printf(step_text_freq[0], sizeof step_text_freq[0], "-%3.1qHz", setting.slider_span); + plot_printf(step_text_freq[1], sizeof step_text_freq[1], "-%3.1qHz", setting.slider_span/10); + plot_printf(step_text_freq[3], sizeof step_text_freq[3], "+%3.1qHz", setting.slider_span/10); + plot_printf(step_text_freq[4], sizeof step_text_freq[4], "+%3.1qHz", setting.slider_span); + for (int i=0; i <= 4; i++) { + ili9341_drawstring(step_text_freq[i], button_start+12 + i * MENU_FORM_WIDTH/5, y+button_height-9); + } + goto draw_divider; } else if (menu[i].data == KM_LOWOUTLEVEL) { - local_slider_positions = (get_attenuation() - POWER_OFFSET + 70 ) * MENU_FORM_WIDTH / 70 + OFFSETX; + local_slider_positions = ((get_attenuation() + 76 ) * (MENU_FORM_WIDTH-8)) / 70 + OFFSETX+4; + for (int i=0; i <= 4; i++) { + ili9341_drawstring(step_text[i], button_start+12 + i * MENU_FORM_WIDTH/5, y+button_height-9); + } + draw_divider: + for (int i = 1; i <= 4; i++) { + ili9341_line(button_start + i * MENU_FORM_WIDTH/5, y+button_height-9, button_start + i * MENU_FORM_WIDTH/5, y+button_height); + } + draw_slider: + blit8BitWidthBitmap(local_slider_positions - 4, y, 7, 5, slider_bitmap); + } else if (menu[i].data == KM_HIGHOUTLEVEL) { + local_slider_positions = ((menu_drive_value[setting.lo_drive] + 38 ) * (MENU_FORM_WIDTH-8)) / 51 + OFFSETX+4; goto draw_slider; } } +#if 0 if (MT_MASK(menu[i].type) == MT_ADV_CALLBACK && menu[i].reference == menu_sdrive_acb) { - local_slider_positions = (menu_drive_value[setting.lo_drive] + 38 ) * MENU_FORM_WIDTH / 51 + OFFSETX; - draw_slider: - blit8BitWidthBitmap(local_slider_positions - 4, y, 7, 6, slider_bitmap); + local_slider_positions = ((menu_drive_value[setting.lo_drive] + 38 ) * (MENU_FORM_WIDTH-8)) / 51 + OFFSETX+4; + goto draw_slider; } +#endif } else { int button_width = MENU_BUTTON_WIDTH; int button_start = LCD_WIDTH - MENU_BUTTON_WIDTH; @@ -1931,20 +1951,23 @@ void check_frequency_slider(uint32_t slider_freq) } uint32_t half_span = setting.slider_span >> 1; if (minFreq + (uint32_t)half_span > slider_freq) { - setting.slider_position -= (minFreq + half_span - slider_freq) / (setting.slider_span /MENU_FORM_WIDTH); // reposition if needed + setting.slider_position -= (minFreq + half_span - slider_freq) / (setting.slider_span / (MENU_FORM_WIDTH-8)); // reposition if needed } if (maxFreq < slider_freq + (uint32_t)half_span) { - setting.slider_position += (slider_freq + half_span - maxFreq) / (setting.slider_span /MENU_FORM_WIDTH); // reposition if needed + setting.slider_position += (slider_freq + half_span - maxFreq) / (setting.slider_span /(MENU_FORM_WIDTH-8)); // reposition if needed } } static void -menu_select_touch(int i) +menu_select_touch(int i, int pos) { + int32_t step = 0; + int do_exit = false; selection = i; draw_menu(); #if 1 // drag values const menuitem_t *menu = menu_stack[menu_current_level]; + int old_keypad_mode = keypad_mode; int keypad = menu[i].data; prev_touch_time = chVTGetSystemTimeX(); @@ -1960,14 +1983,13 @@ menu_select_touch(int i) if (dt > BUTTON_DOWN_LONG_TICKS) { touch_position(&touch_x, &touch_y); if (touch_x != prev_touch_x /* - 1 || prev_touch_x + 1 < touch_x */ ) { - int old_keypad_mode = keypad_mode; keypad_mode = keypad; fetch_numeric_target(); int new_slider = touch_x - LCD_WIDTH/2; - if (new_slider < -MENU_FORM_WIDTH/2) - new_slider = -MENU_FORM_WIDTH/2; - if (new_slider > MENU_FORM_WIDTH/2) - new_slider = MENU_FORM_WIDTH/2; + if (new_slider < - (MENU_FORM_WIDTH-8)/2) + new_slider = -(MENU_FORM_WIDTH-8)/2; + if (new_slider > (MENU_FORM_WIDTH-8)/2) + new_slider = (MENU_FORM_WIDTH-8)/2; if (menu_is_form(menu) && MT_MASK(menu[i].type) == MT_KEYPAD && keypad == KM_CENTER){ #define TOUCH_DEAD_ZONE 40 if (mode == SL_UNKNOWN ) { @@ -1979,7 +2001,7 @@ menu_select_touch(int i) } } if (mode == SL_MOVE ) { - uistat.value = uistat.value - setting.slider_position * (setting.slider_span/MENU_FORM_WIDTH) + new_slider * (setting.slider_span/MENU_FORM_WIDTH); + uistat.value = uistat.value - setting.slider_position * (setting.slider_span/(MENU_FORM_WIDTH-8)) + new_slider * (setting.slider_span/(MENU_FORM_WIDTH-8)); if (uistat.value < minFreq) uistat.value = minFreq; if (uistat.value > maxFreq) @@ -2014,30 +2036,40 @@ menu_select_touch(int i) minFreq = 0; // And set minFreq to 0 for span display uistat.value = setting.slider_span; set_keypad_value(keypad); +#if 1 + plot_printf(center_text, sizeof center_text, "WIDTH: %%s"); +#else center_text[0] = 'S'; center_text[1] = 'P'; center_text[2] = 'A'; center_text[3] = 'N'; +#endif draw_menu(); // Show slider span minFreq = old_minFreq; // and restore minFreq uistat.value = (float) slider_freq; // and restore current slider freq set_keypad_value(keypad); +#if 1 + plot_printf(center_text, sizeof center_text, "FREQ: %%s"); +#else center_text[0] = 'F'; center_text[1] = 'R'; center_text[2] = 'E'; center_text[3] = 'Q'; +#endif setting.slider_position = 0; // reset slider after span change check_frequency_slider(slider_freq); } } else if (menu_is_form(menu) && MT_MASK(menu[i].type) == MT_KEYPAD && keypad == KM_LOWOUTLEVEL) { - uistat.value = setting.offset + (POWER_OFFSET-70) + (touch_x - OFFSETX) * 70 / MENU_FORM_WIDTH ; + uistat.value = setting.offset + (touch_x - OFFSETX+4) *( -6 - -76) / (MENU_FORM_WIDTH-8) + -76; + apply_step: set_keypad_value(keypad); apply: perform(false, 0, get_sweep_frequency(ST_CENTER), false); draw_menu(); // } - } else if (MT_MASK(menu[i].type) == MT_ADV_CALLBACK && menu[i].reference == menu_sdrive_acb) { - set_level( (touch_x - OFFSETX) *( 13 - -38) / MENU_FORM_WIDTH + -38 ); +// } else if (MT_MASK(menu[i].type) == MT_ADV_CALLBACK && menu[i].reference == menu_sdrive_acb) { + } else if (menu_is_form(menu) && MT_MASK(menu[i].type) == MT_KEYPAD && keypad == KM_HIGHOUTLEVEL) { + set_level( (touch_x - OFFSETX+4) *( 13 - -38) / (MENU_FORM_WIDTH-8) + -38 ); goto apply; } keypad_mode = old_keypad_mode; @@ -2045,11 +2077,54 @@ menu_select_touch(int i) } prev_touch_x = touch_x; } - if (dt > BUTTON_DOWN_LONG_TICKS) { + if (dt > BUTTON_DOWN_LONG_TICKS || do_exit) { selection = -1; draw_menu(); return; } + if (menu_is_form(menu) && MT_MASK(menu[i].type) == MT_KEYPAD && keypad == KM_LOWOUTLEVEL) { + switch (pos) { + case 0: + step = -10; + break; + case 1: + step = -1; + break; + case 2: + goto nogo; + case 3: + step = +1; + break; + case 4: + step = +10; + break; + } + uistat.value = get_level() + step; + do_exit = true; + goto apply_step; + } else if (menu_is_form(menu) && MT_MASK(menu[i].type) == MT_KEYPAD && keypad == KM_CENTER) { + switch (pos) { + case 0: + step = -setting.slider_span; + break; + case 1: + step = -setting.slider_span/10; + break; + case 2: + goto nogo; + case 3: + step = setting.slider_span/10; + break; + case 4: + step = setting.slider_span; + break; + } + uistat.value = get_sweep_frequency(ST_CENTER) + step; + do_exit = true; + goto apply_step; + } + +nogo: setting.slider_position = 0; // Reset slider when entering frequency prev_touch_button = -1; #endif @@ -2088,7 +2163,7 @@ menu_apply_touch(void) } if (y < touch_y && touch_y < y+MENU_BUTTON_HEIGHT) { if (touch_x > active_button_start) { - menu_select_touch(i); + menu_select_touch(i, (( touch_x - active_button_start) * 5 ) / MENU_FORM_WIDTH); return; } } diff --git a/ui_sa.c b/ui_sa.c index 0919043..4d06e75 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -406,7 +406,7 @@ enum { KM_REFLEVEL, KM_SCALE, KM_ATTENUATION, KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_DRIVE, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE, KM_30MHZ, KM_REPEAT, KM_OFFSET, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME, KM_OFFSET_DELAY, - KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, + KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, KM_HIGHOUTLEVEL, KM_R,KM_MOD,KM_CP, #if 0 KM_COR_AM,KM_COR_WFM, KM_COR_NFM, @@ -447,6 +447,7 @@ static const struct { {keypads_positive , "MINIMUM\nGRIDLINES"}, // KM_GRIDLINES {keypads_freq , "MARKER\nFREQ"}, // KM_MARKER {keypads_freq , "MODULATION\nFREQ"}, // KM_MODULATION + {keypads_plusmin , "LEVEL"}, // KM_HIGHOUTLEVEL #if 0 {keypads_plusmin , "COR\nAM"}, // KM_COR_AM {keypads_plusmin , "COR\nWFM"}, // KM_COR_WFM @@ -464,7 +465,8 @@ ui_slider_t ui_sliders [] = { { KM_CENTER, true, 0, 1000000, 0, 350000000, M_GENLOW}, { KM_CENTER, true, 0, 1000000, 240000000, 960000000, M_GENHIGH}, - { KM_LOWOUTLEVEL, false,0, 1, POWER_OFFSET - 70, POWER_OFFSET, M_GENLOW}, + { KM_LOWOUTLEVEL, false,0, 1, -76, -6, M_GENLOW}, + { KM_HIGHOUTLEVEL, false,0, 1, -38, +6, M_GENHIGH}, }; #endif @@ -784,6 +786,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_mixer_drive_acb) // draw_cal_status(); } +#if 0 static UI_FUNCTION_ADV_CALLBACK(menu_sdrive_acb){ (void)item; (void)data; @@ -797,6 +800,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_sdrive_acb){ } menu_push_submenu(menu_drive_wide); } +#endif @@ -1554,6 +1558,7 @@ static const menuitem_t menu_mixer_drive[] = { { MT_NONE, 0, NULL, NULL } // sentinel }; +#if 0 static const menuitem_t menu_drive_wide3[] = { { MT_FORM | MT_ADV_CALLBACK, 5, "%+ddBm", menu_lo_drive_acb}, { MT_FORM | MT_ADV_CALLBACK, 4, "%+ddBm", menu_lo_drive_acb}, @@ -1586,6 +1591,7 @@ static const menuitem_t menu_drive_wide[] = { { MT_FORM | MT_CANCEL, 255, S_LARROW" BACK", NULL }, { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel }; +#endif static const menuitem_t menu_modulation[] = { { MT_FORM | MT_TITLE, 0, "MODULATION",NULL}, @@ -1607,8 +1613,8 @@ static const menuitem_t menu_sweep[] = { { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel }; -char low_level_help_text[12] = "-88..-18"; -char center_text[10] = "FREQ: %s"; +char low_level_help_text[12] = "-76..-6"; +char center_text[18] = "FREQ: %s"; static const menuitem_t menu_lowoutputmode[] = { { MT_FORM | MT_ADV_CALLBACK, 0, "LOW OUTPUT %s", menu_outputmode_acb}, @@ -1630,14 +1636,10 @@ static const menuitem_t menu_highoutputmode[] = { { MT_FORM | MT_ADV_CALLBACK, 0, "HIGH OUTPUT %s", menu_outputmode_acb}, { MT_FORM | MT_SUBMENU, 255, S_RARROW" Settings", menu_settings3}, { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, "240MHz..960MHz"}, - { MT_FORM | MT_ADV_CALLBACK, 0, "LEVEL: %+ddBm", menu_sdrive_acb}, -#if 0 +// { MT_FORM | MT_ADV_CALLBACK, 0, "LEVEL: %+ddBm", menu_sdrive_acb}, + { MT_FORM | MT_KEYPAD, KM_HIGHOUTLEVEL, "LEVEL: %s", low_level_help_text /* "-76..-6" */}, { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, - { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", NULL}, - { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME,"SWEEP TIME: %s", "0..600 seconds"}, -#else { MT_FORM | MT_ADV_CALLBACK, 0, "%s", menu_sweep_acb}, -#endif { MT_FORM | MT_KEYPAD, KM_OFFSET, "EXTERNAL AMP: %s", "-100..+100"}, { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel @@ -1921,12 +1923,12 @@ static const menuitem_t menu_settings[] = }; static const menuitem_t menu_measure2[] = { -#ifdef __LINEARITY__ - { MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, -#endif { MT_ADV_CALLBACK, M_AM, "AM", menu_measure_acb}, { MT_ADV_CALLBACK, M_FM, "FM", menu_measure_acb}, { MT_ADV_CALLBACK, M_THD, "THD", menu_measure_acb}, +#ifdef __LINEARITY__ + { MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, +#endif { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel }; @@ -2239,7 +2241,7 @@ static void fetch_numeric_target(void) plot_printf(uistat.text, sizeof uistat.text, "%3ddB", ((int32_t)uistat.value)); break; case KM_LOWOUTLEVEL: - uistat.value = get_attenuation(); // compensation for dB offset during low output mode + uistat.value = get_level(); // compensation for dB offset during low output mode int end_level = ((int32_t)uistat.value)+setting.level_sweep; if (end_level < POWER_OFFSET - 70) end_level = POWER_OFFSET - 70; @@ -2252,6 +2254,11 @@ static void fetch_numeric_target(void) else plot_printf(uistat.text, sizeof uistat.text, "%ddBm", ((int32_t)uistat.value)); break; + case KM_HIGHOUTLEVEL: + uistat.value = get_level(); // compensation for dB offset during low output mode + uistat.value += setting.offset; + plot_printf(uistat.text, sizeof uistat.text, "%ddBm", ((int32_t)uistat.value)); + break; case KM_DECAY: uistat.value = setting.decay; plot_printf(uistat.text, sizeof uistat.text, "%5d", ((int32_t)uistat.value)); @@ -2390,6 +2397,9 @@ set_numeric_value(void) case KM_LOWOUTLEVEL: set_level(uistat.value - setting.offset); break; + case KM_HIGHOUTLEVEL: + set_level(uistat.value - setting.offset); + break; case KM_DECAY: set_decay(uistat.value); break;