diff --git a/nanovna.h b/nanovna.h index 913bdb2..48648ac 100644 --- a/nanovna.h +++ b/nanovna.h @@ -382,7 +382,7 @@ extern uint16_t graph_bottom; #define FORM_BUTTON_BORDER 2 // Form button (at center screen better be less LCD_WIDTH - 2*OFFSETX) -#define MENU_FORM_WIDTH 256 +#define MENU_FORM_WIDTH (LCD_WIDTH - 2*OFFSETX) // Num Input height at bottom #define NUM_INPUT_HEIGHT 32 @@ -819,6 +819,7 @@ typedef struct setting int fast_speedup; float normalize_level; // Level to set normalize to, zero if not doing anything int modulation_frequency; + int trigger_mode; uint32_t checksum; int extra_lna; int ultra; @@ -1006,7 +1007,7 @@ typedef struct uistat { uint8_t marker_noise; uint8_t marker_tracking; uint8_t auto_center_marker; - char text[20]; + char text[28]; } uistat_t; typedef struct ui_button { @@ -1080,6 +1081,7 @@ typedef int16_t pureRSSI_t; // External programm zero level settings (need decrease on this value -) #define EXT_ZERO_LEVEL (128) #define DEVICE_TO_PURE_RSSI(rssi) ((rssi)<<4) +#define PURE_TO_DEVICE_RSSI(rssi) ((rssi)>>4) #define float_TO_PURE_RSSI(rssi) ((rssi)*32) #define PURE_TO_float(rssi) ((rssi)/32.0) @@ -1113,35 +1115,7 @@ enum { }; enum { - T_AUTO, T_NORMAL, T_SINGLE, T_DONE, T_UP, T_DOWN + T_AUTO, T_NORMAL, T_SINGLE, T_DONE, T_UP, T_DOWN, T_MODE, T_PRE, T_POST, T_MID }; - -// -------------------- Si4432.c --------------- - -void set_calibration_freq(int ref); -uint16_t set_rbw(uint16_t WISH); -uint16_t force_rbw(int f); - -#ifdef __SI4463__ -extern int SI4463_R; -void SI4463_set_freq(uint32_t freq); -void SI446x_set_AGC_LNA(uint8_t v); -void SI4463_set_gpio(int i, int s); -void SI4463_set_output_level(int t); -#define GPIO_HIGH 3 -#define GPIO_LOW 2 -void SI4463_start_tx(uint8_t CHANNEL); -void SI4463_init_rx(void); -void SI4463_init_tx(void); -#endif - -void set_R(int f); -void set_modulo(uint32_t f); -#ifdef __ADF4351__ -extern volatile int64_t ADF4350_modulo; -void ADF4351_Set(int channel); -void ADF4351_force_refresh(void); -void ADF4351_mux(int R); -#endif /*EOF*/ diff --git a/plot.c b/plot.c index 8890943..1c649cf 100644 --- a/plot.c +++ b/plot.c @@ -2133,33 +2133,29 @@ static void cell_draw_marker_info(int x0, int y0) break; plot_printf(buf, sizeof buf, "DEVIATION:%6.1qHz", dev); goto show_computed; - } - } - if (i >= 2 && setting.measurement == M_THD) { - if (i == 2 && (markers[0].index << 5) > sweep_points ) { + } else if (setting.measurement == M_THD && markers[0].enabled && (markers[0].index << 5) > sweep_points ) { int old_unit = setting.unit; setting.unit = U_WATT; float p = index_to_value(markers[0].index); - int j = 2; + int h_i = 2; uint32_t f = markers[0].frequency; float h = 0.0; - while (f * j < frequencies[sweep_points-1]) { - if (search_maximum(1, f*j, 4*j) ) // use marker 1 for searching harmonics + while (f * h_i < frequencies[sweep_points-1]) { + if (search_maximum(1, f*h_i, 4*h_i) ) // use marker 1 for searching harmonics h += index_to_value(markers[1].index); - j++; + h_i++; } float thd = 100.0 * sqrt(h/p); setting.unit = old_unit; - + ili9341_set_foreground(marker_color(markers[0].mtype)); plot_printf(buf, sizeof buf, "THD: %4.1f%%", thd); - j = 1; +// j = 1; int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; int ypos = 1 + (j/2)*(16) - y0; cell_drawstring_7x13(buf, xpos, ypos); // cell_drawstring(buf, xpos, ypos); break; } - break; } else if (i >= 2 && setting.measurement == M_OIP3 && markers[2].enabled && markers[3].enabled) { float il = index_to_value(markers[2].index); @@ -2202,14 +2198,6 @@ static void cell_draw_marker_info(int x0, int y0) for (t = TRACE_ACTUAL; t <= TRACE_ACTUAL; t++) { // Only show info on actual trace if (!trace[t].enabled) continue; -#if 1 - int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; -// int ypos = 1 + (j/2)*(13) - y0; - int ypos = 1 + (j/2)*(16) - y0; -#else - int xpos = 1 + CELLOFFSETX - x0; - int ypos = 1 + j*(FONT_GET_HEIGHT*2+1) - y0; -#endif int k = 0; if (i == active_marker) { // ili9341_set_foreground(LCD_BG_COLOR); @@ -2248,6 +2236,14 @@ static void cell_draw_marker_info(int x0, int y0) trace_get_value_string( t, &buf[k], (sizeof buf) - k, idx, measured[trace[t].channel], ridx, markers[i].mtype,markers[i].frequency, markers[ref_marker].frequency); +#if 1 + int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; +// int ypos = 1 + (j/2)*(13) - y0; + int ypos = 1 + (j/2)*(16) - y0; +#else + int xpos = 1 + CELLOFFSETX - x0; + int ypos = 1 + j*(FONT_GET_HEIGHT*2+1) - y0; +#endif if (/* strlen(buf)*7> WIDTH/2 && */active > 1) cell_drawstring(buf, xpos, ypos); else diff --git a/sa_core.c b/sa_core.c index c8c041c..00bc6ba 100644 --- a/sa_core.c +++ b/sa_core.c @@ -127,6 +127,7 @@ void reset_settings(int m) setting.offset = 0.0; setting.trigger = T_AUTO; setting.trigger_direction = T_UP; + setting.trigger_mode = T_MID; setting.fast_speedup = 0; setting.level_sweep = 0.0; setting.level = -15.0; @@ -323,8 +324,8 @@ void set_sweep_time_us(uint32_t t) // Set the sweep time as the user wa if (t > MAXIMUM_SWEEP_TIME) t = MAXIMUM_SWEEP_TIME; setting.sweep_time_us = t; - if (MODE_OUTPUT(setting.mode)) - setting.actual_sweep_time_us = t; // To ensure time displayed is correct before first sweep is completed +// if (MODE_OUTPUT(setting.mode)) +// setting.actual_sweep_time_us = t; // To ensure time displayed is correct before first sweep is completed #if 0 uint32_t ta = calc_min_sweep_time_us(); // Can not be faster than minimum sweep time if (ta < t) @@ -980,7 +981,9 @@ void set_trigger_level(float trigger_level) void set_trigger(int trigger) { - if (trigger == T_UP || trigger == T_DOWN){ + if (trigger == T_PRE || trigger == T_POST || trigger == T_MID) { + setting.trigger_mode = trigger; + } else if (trigger == T_UP || trigger == T_DOWN){ setting.trigger_direction = trigger; } else if (trigger == T_DONE) { pause_sweep(); // Trigger once so pause after this sweep has completed!!!!!!! @@ -2178,6 +2181,11 @@ modulation_again: #define T_LEVEL_CLEAN ~(1< 0; j--) { - if (actual_t[j] < peakLevel - 15) // Search left -3dB + for (k = peakIndex; k > 0; k--) { + if (actual_t[k] < peakLevel - 15) // Search left -3dB break; } - //shell_printf("Left width %d\n\r", j - peakIndex ); - if (peakIndex - j < W2P(test_case[i].width)) - return(TS_FAIL); +// shell_printf("Width %d between %d and %d\n\r", j - k, 2* W2P(test_case[i].width), 3* W2P(test_case[i].width) ); + if (j - k < 2* W2P(test_case[i].width)) + return(TS_FAIL); + if (j - k > 3* W2P(test_case[i].width)) + return(TS_FAIL); test_fail_cause[i] = ""; return(TS_PASS); } diff --git a/si4432.c b/si4432.c index 2f4669f..3309f25 100644 --- a/si4432.c +++ b/si4432.c @@ -498,6 +498,7 @@ void SI4432_Set_Frequency ( uint32_t Freq ) { #ifdef __FAST_SWEEP__ extern deviceRSSI_t age[POINTS_COUNT]; static int buf_index = 0; +static int buf_end = 0; static bool buf_read = false; #if 0 @@ -507,6 +508,102 @@ int SI4432_is_fast_mode(void) } #endif + +//--------------------------- Trigger ------------------- +// ************** trigger mode if need +// trigger on measure 4 point +#define T_POINTS 4 +#define T_LEVEL_UNDEF (1<<(16-T_POINTS)) // should drop after 4 shifts left +#define T_LEVEL_BELOW 1 +#define T_LEVEL_ABOVE 0 +// Trigger mask, should have width T_POINTS bit +#define T_DOWN_MASK (0b0011) // 2 from up 2 to bottom +#define T_UP_MASK (0b1100) // 2 from bottom 2 to up +#define T_LEVEL_CLEAN ~(1<= sweep_points) + i = 0; + switch (waiting) { + case ST_ARMING: + if (i == sweep_points-1) { + waiting = ST_WAITING; + setting.measure_sweep_time_us = (chVTGetSystemTimeX() - measure)*100; + } + break; + case ST_WAITING: +#if 1 + if (rssi < trigger_lvl) { + data_level = ((data_level<<1) | (T_LEVEL_BELOW))&(T_LEVEL_CLEAN); + } else { + data_level = ((data_level<<1) | (T_LEVEL_ABOVE))&(T_LEVEL_CLEAN); + } +#else + data_level = ((data_level<<1) | (rssi < trigger_lvl ? T_LEVEL_BELOW : T_LEVEL_ABOVE))&(T_LEVEL_CLEAN); +#endif + if (data_level == t_mode) { // wait trigger + // if (i == 128) { // wait trigger + waiting = ST_FILLING; + switch (trigger_mode) { + case T_PRE: // Trigger at the begin of the scan + buf_index = i; + goto fill_rest; + break; + case T_POST: // Trigger at the end of the scan + buf_index = i; + goto done; + break; + case T_MID: // Trigger in the middle of the scan + buf_index = i + sweep_points/2; + if (buf_index >= sweep_points) + buf_index -= sweep_points; + break; + } + } + break; + case ST_FILLING: + if (i == buf_index) + goto done; + } +fill_rest: + if (t) + my_microsecond_delay(t); + }while(1); +done: + buf_end = buf_index; + buf_read = true; +} + void SI4432_Fill(int s, int start) { set_SPI_mode(SPI_MODE_SI); @@ -524,8 +621,8 @@ void SI4432_Fill(int s, int start) uint32_t t = setting.additional_step_delay_us; systime_t measure = chVTGetSystemTimeX(); // __disable_irq(); -#if 0 - SPI1_CLK_LOW; +#if 1 + SPI2_CLK_LOW; int i = start; do { palClearPad(GPIOC, sel); @@ -542,6 +639,7 @@ void SI4432_Fill(int s, int start) // __enable_irq(); setting.measure_sweep_time_us = (chVTGetSystemTimeX() - measure)*100; buf_index = start; // Is used to skip 1st entry during level triggering + buf_end = sweep_points - 1; buf_read = true; } #endif @@ -565,9 +663,12 @@ pureRSSI_t SI4432_RSSI(uint32_t i, int s) //START_PROFILE #ifdef __FAST_SWEEP__ if (buf_read) { - if (buf_index == sweep_points-1) + pureRSSI_t val = DEVICE_TO_PURE_RSSI(age[buf_index++]); + if (buf_index >= sweep_points) + buf_index = 0; + if (buf_index == buf_end) buf_read = false; - return DEVICE_TO_PURE_RSSI(age[buf_index++]); + return val; } #endif SI4432_Sel = s; diff --git a/si4432.h b/si4432.h index ad541f0..37ef66b 100644 --- a/si4432.h +++ b/si4432.h @@ -142,6 +142,7 @@ extern const int SI4432_RBW_count; void set_calibration_freq(int freq); #ifdef __FAST_SWEEP__ void SI4432_Fill(int s, int start); +void SI4432_trigger_fill(int s, uint8_t trigger_lvl, int up_direction, int trigger_mode); #if 0 int SI4432_is_fast_mode(void); #endif diff --git a/ui.c b/ui.c index 78e4c76..125ed1f 100644 --- a/ui.c +++ b/ui.c @@ -522,8 +522,8 @@ enum { MT_LOW = 0x40, // Only applicable to low mode MT_FORM = 0x80, // Large button menu }; -#define MT_BACK 0x40 -#define MT_LEAVE 0x20 +//#define MT_BACK 0x40 +//#define MT_LEAVE 0x20 #define MT_MASK(x) (0xF & (x)) // Call back functions for MT_CALLBACK type @@ -2618,6 +2618,7 @@ touch_lever_mode_select(void) else ui_mode_keypad(KM_START); ui_process_keypad(); + return TRUE; } if (touch_x > FREQUENCIES_XPOS2 - 50 && touch_x < FREQUENCIES_XPOS2 +50) { touch_wait_release(); @@ -2635,8 +2636,10 @@ touch_lever_mode_select(void) else ui_mode_keypad(KM_STOP); ui_process_keypad(); + return TRUE; } select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN); + touch_wait_release(); return TRUE; } if (touch_x =2?BUTTON_ICON_CHECK_AUTO:S) // Depends on order of ICONs!!!!! +static UI_FUNCTION_ADV_CALLBACK(menu_sweep_acb) +{ + (void)data; + if (b){ + if (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0) { + plot_printf(uistat.text, sizeof uistat.text, "SW:%3.2fMHz %+ddB %.3Fs", + get_sweep_frequency(ST_SPAN) / 1000000.0, + (int)setting.level_sweep, + setting.sweep_time_us/(float)ONE_SECOND_TIME); + b->param_1.text = uistat.text; + } + else + b->param_1.text = "SWEEP: OFF"; + return; + } + menu_push_submenu(menu_sweep); +} + + static UI_FUNCTION_ADV_CALLBACK(menu_mode_acb) { (void)data; @@ -707,24 +727,8 @@ static UI_FUNCTION_ADV_CALLBACK(menu_drive_acb) { (void)item; if(b){ - b->param_1.i = menu_drive_value[data]; - b->icon = data == setting.rx_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } -//Serial.println(item); - set_rx_drive(data); - menu_move_back(); -// ui_mode_normal(); -// draw_cal_status(); -} - -const int8_t menu_lo_drive_value[]={4,7,10,13}; -static UI_FUNCTION_ADV_CALLBACK(menu_lo_drive_acb) -{ - (void)item; - if(b){ - b->param_1.i = menu_lo_drive_value[data]; - b->icon = data == setting.lo_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->param_1.i = menu_drive_value[data] + (setting.mode==M_GENHIGH ? setting.offset : 0); + b->icon = data == setting.drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; return; } //Serial.println(item); @@ -738,7 +742,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_sdrive_acb){ (void)item; (void)data; if(b){ - b->param_1.i = menu_drive_value[setting.lo_drive]; + b->param_1.i = menu_drive_value[setting.drive] + (setting.mode==M_GENHIGH ? setting.offset : 0); return; } menu_push_submenu(menu_drive_wide); @@ -1162,22 +1166,32 @@ static UI_FUNCTION_ADV_CALLBACK(menu_scale_per_acb) } #endif +const char *mode_text[] = {"PRE","POST","MID"}; + static UI_FUNCTION_ADV_CALLBACK(menu_trigger_acb) { (void)item; if(b){ - if (data == T_UP || data == T_DOWN) + if (data == T_MODE) { + b->param_1.text = mode_text[setting.trigger_mode - T_PRE]; + } else if (data == T_UP || data == T_DOWN) b->icon = setting.trigger_direction == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; else b->icon = setting.trigger == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; return; } - if (data != T_DONE) { + if (data == T_MODE) { + setting.trigger_mode += 1; + if (setting.trigger_mode > T_MID) + setting.trigger_mode = T_PRE; + set_trigger(setting.trigger_mode); + } else if (data != T_DONE) { set_trigger(data); // menu_move_back(); ui_mode_normal(); - completed = true; } + draw_menu(); + completed = true; } #if 0 @@ -1489,16 +1503,27 @@ static const menuitem_t menu_modulation[] = { { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel }; +static const menuitem_t menu_sweep[] = { + { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", "0..350MHz"}, + { MT_FORM | MT_KEYPAD | MT_LOW, KM_LEVELSWEEP,"LEVEL CHANGE: %s", "-70..70"}, + { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME, "SWEEP TIME: %s", "0..600 seconds"}, + { MT_FORM | MT_CANCEL, 0, S_LARROW" BACK",NULL }, + { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel +}; + + static const menuitem_t menu_lowoutputmode[] = { { MT_FORM | MT_ADV_CALLBACK, 0, "LOW OUTPUT %s", menu_outputmode_acb}, { MT_FORM | MT_KEYPAD, KM_CENTER, "FREQ: %s", "10kHz..350MHz"}, { MT_FORM | MT_KEYPAD, KM_LOWOUTLEVEL, "LEVEL: %s", "-76..-6"}, // { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, { MT_FORM | MT_SUBMENU, 255, S_RARROW" Settings", menu_settings3}, - - { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", "0..350MHz"}, - { MT_FORM | MT_KEYPAD | MT_LOW, KM_LEVELSWEEP,"LEVEL CHANGE: %s", "-70..70"}, - { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME, "SWEEP TIME: %s", "0..600 seconds"}, + { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, + { MT_FORM | MT_ADV_CALLBACK, 0, "%s", menu_sweep_acb}, +// { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", "0..350MHz"}, +// { MT_FORM | MT_KEYPAD | MT_LOW, KM_LEVELSWEEP,"LEVEL CHANGE: %s", "-70..70"}, +// { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME, "SWEEP TIME: %s", "0..600 seconds"}, + { MT_FORM | MT_KEYPAD, KM_OFFSET, "AMP: %s", "-100..+100"}, { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel }; @@ -1510,6 +1535,7 @@ static const menuitem_t menu_highoutputmode[] = { { 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"}, + { MT_FORM | MT_KEYPAD, KM_OFFSET, "AMP: %s", "-100..+100"}, { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel }; @@ -1916,6 +1942,7 @@ static const menuitem_t menu_trigger[] = { { MT_KEYPAD, KM_TRIGGER, "TRIGGER\nLEVEL", NULL}, { MT_ADV_CALLBACK, T_UP, "UP\nEDGE", menu_trigger_acb}, { MT_ADV_CALLBACK, T_DOWN, "DOWN\nEDGE", menu_trigger_acb}, + { MT_ADV_CALLBACK, T_MODE, "%s\nTRIGGER", menu_trigger_acb}, { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel }; @@ -2104,6 +2131,8 @@ static void fetch_numeric_target(void) end_level = -76; if (end_level > -6) end_level = -6; + uistat.value += setting.offset; + end_level += setting.offset; if (setting.level_sweep != 0) plot_printf(uistat.text, sizeof uistat.text, "%d to %ddBm", ((int32_t)uistat.value), end_level); else @@ -2241,7 +2270,7 @@ set_numeric_value(void) set_rx_drive(uistat.value); break; case KM_LOWOUTLEVEL: - set_level(uistat.value); + set_level(uistat.value - setting.offset); break; case KM_DECAY: set_decay(uistat.value);