diff --git a/main.c b/main.c index 89a479f..d8b9ac3 100644 --- a/main.c +++ b/main.c @@ -2431,6 +2431,8 @@ static const VNAShellCommand commands[] = { "if", cmd_if, 0 }, #ifdef TINYSA4 { "if1", cmd_if1, 0 }, + { "lna2", cmd_lna2, 0 }, + { "agc", cmd_agc, 0 }, #endif { "attenuate", cmd_attenuate, 0 }, { "level", cmd_level, 0 }, @@ -2454,6 +2456,7 @@ static const VNAShellCommand commands[] = { "deviceid", cmd_deviceid, 0 }, { "selftest", cmd_selftest, 0 }, { "correction", cmd_correction, 0 }, + { "calc", cmd_calc, 0}, #ifdef ENABLE_THREADS_COMMAND {"threads" , cmd_threads , 0}, #endif diff --git a/sa_cmd.c b/sa_cmd.c index 547113e..38239ba 100644 --- a/sa_cmd.c +++ b/sa_cmd.c @@ -77,6 +77,20 @@ VNA_SHELL_FUNCTION(cmd_modulation ) } } +VNA_SHELL_FUNCTION(cmd_calc ) +{ + static const char cmd_cal[] = "off|minh|maxh|maxd|aver4|aver16|quasip"; + if (argc < 1) { + usage: + shell_printf("usage: calc %s\r\n", cmd_cal); + return; + } + int m = get_str_index(argv[0], cmd_cal); + if (m<0) + goto usage; + set_average(m); +} + int generic_option_cmd( const char *cmd, const char *cmd_list, int argc, char *argv) { if (argc != 1) { @@ -165,6 +179,49 @@ usage: shell_printf("usage: load 0..4\r\n"); } +#ifdef TINYSA4 + +static uint8_t reg_agc_lna = 0; + +VNA_SHELL_FUNCTION(cmd_lna2) +{ + int a; + if (argc != 1) { +// usage: + shell_printf("usage: lna2 0..7|auto\r\n"); + return; + } + if (get_str_index(argv[0],"auto") == 0) { + reg_agc_lna &= 0xf0; + } else { + a = my_atoi(argv[0]); + reg_agc_lna &= 0xf0; + reg_agc_lna |= 0x08 | a; + } + SI446x_set_AGC_LNA(reg_agc_lna); +} + +VNA_SHELL_FUNCTION(cmd_agc) +{ + int a; + if (argc != 1) { +// usage: + shell_printf("usage: agc 0..7|auto\r\n"); + return; + } + if (get_str_index(argv[0],"auto") == 0) { + reg_agc_lna &= 0x0f; + } else { + a = my_atoi(argv[0]); + reg_agc_lna &= 0x0f; + reg_agc_lna |= 0x80 | (a << 4); + } + SI446x_set_AGC_LNA(reg_agc_lna); +} + +#endif + + VNA_SHELL_FUNCTION(cmd_attenuate) { if (argc != 1) { diff --git a/sa_core.c b/sa_core.c index 9ae1e12..f5de274 100644 --- a/sa_core.c +++ b/sa_core.c @@ -1042,7 +1042,7 @@ void set_AGC_LNA(void) { uint8_t v = 0; if (!S_STATE(setting.agc)) v |= 0x80 + 0x20; // Inverse!!!! - if (!S_STATE(setting.lna)) + if (S_STATE(setting.lna)) v |= 0x08; // Inverse!!!! SI446x_set_AGC_LNA(v); SI4432_old_v[0] = v; @@ -1069,18 +1069,22 @@ void set_unit(int u) r = REFLEVEL_MAX; // Maximum value set_scale(r/NGRIDY); set_reflevel(setting.scale*NGRIDY); +#ifdef __SI4432__ if (S_IS_AUTO(setting.agc)) setting.agc = S_AUTO_ON; if (S_IS_AUTO(setting.lna)) setting.lna = S_AUTO_OFF; +#endif } else { r = 10 * roundf((r*1.2)/10.0); set_reflevel(r); set_scale(10); +#ifdef __SI4432__ if (S_IS_AUTO(setting.agc)) setting.agc = S_AUTO_ON; if (S_IS_AUTO(setting.lna)) setting.lna = S_AUTO_OFF; +#endif } plot_into_index(measured); redraw_request|=REDRAW_AREA; @@ -1281,8 +1285,8 @@ static const struct { } step_delay_table[]={ // RBWx10 step_delay offset_delay spur_gate (value divided by 1000) { 6000, 80, 50, 400}, - { 3000, 80, 50, 200}, - { 1000, 100, 100, 100}, + { 3000, 400, 50, 200}, + { 1000, 400, 100, 100}, { 300, 400, 120, 100}, { 100, 400, 120, 100}, { 30, 900, 300, 100}, @@ -2235,10 +2239,22 @@ void clock_below_48MHz(void) } } +void clock_at_48MHz(void) +{ + if (hsical == -1) + hsical = ( (RCC->CR & 0xff00) >> 8 ); + if (hsical != -1) { + RCC->CR &= RCC_CR_HSICAL; + RCC->CR |= ( (hsical) << 8 ); + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + } +} + pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) // Measure the RSSI for one frequency, used from sweep and other measurement routines. Must do all HW setup { int modulation_delay = 0; int modulation_index = 0; + int modulation_count_iter = 0; int spur_second_pass = false; if (i == 0 && dirty ) { // if first point in scan and dirty #ifdef __ADF4351__ @@ -2276,7 +2292,9 @@ pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) / calculate_static_correction(); if (!in_selftest) clock_above_48MHz(); is_below = false; - } + correct_RSSI_freq = get_frequency_correction(f); // for i == 0 and freq_step == 0; + } else + clock_at_48MHz(); // if (MODE_OUTPUT(setting.mode) && setting.additional_step_delay_us < 500) // Minimum wait time to prevent LO from lockup during output frequency sweep // setting.additional_step_delay_us = 500; // Update grid and status after @@ -2408,7 +2426,7 @@ pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) / #endif // Calculate the RSSI correction for later use if (MODE_INPUT(setting.mode)){ // only cases where the value can change on 0 point of sweep - if (i == 0 || setting.frequency_step != 0) + if (setting.frequency_step != 0) correct_RSSI_freq = get_frequency_correction(f); } int *current_fm_modulation = 0; @@ -2662,13 +2680,13 @@ modulation_again: if (setting.R == 0) { if (lf < LOW_MAX_FREQ && lf >= TXCO_DIV3 && MODE_INPUT(setting.mode)) { - freq_t tf = ((lf + actual_rbw_x10*100) / TCXO) * TCXO; - if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) { + freq_t tf = ((lf + actual_rbw_x10*1000) / TCXO) * TCXO; + if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) { // 30MHz ADF4351_R_counter(6); } else { if (setting.frequency_step < 100000) { - freq_t tf = ((lf + actual_rbw_x10*100) / TXCO_DIV3) * TXCO_DIV3; - if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) + freq_t tf = ((lf + actual_rbw_x10*1000) / TXCO_DIV3) * TXCO_DIV3; + if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) // 10MHz ADF4351_R_counter(4); else ADF4351_R_counter(3); @@ -2844,6 +2862,11 @@ modulation_again: return(0); // abort if ( i==1 && MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE && setting.modulation != MO_EXTERNAL) { // if in output mode with modulation and LO setup done // i = 1; // Everything set so skip LO setting +#define MODULATION_CYCLES_TEST 10000 + if (in_selftest && modulation_count_iter++ >= 10000) { + start_of_sweep_timestamp = (chVTGetSystemTimeX() - start_of_sweep_timestamp)*MODULATION_STEPS*100/MODULATION_CYCLES_TEST; // uS per cycle + return 0; + } goto modulation_again; // Keep repeating sweep loop till user aborts by input } return(0); @@ -2861,7 +2884,7 @@ modulation_again: #endif #ifdef __SI4463__ if (i == 0 && setting.frequency_step == 0 && setting.trigger == T_AUTO && S_STATE(setting.spur_removal) == 0 && SI4432_step_delay == 0 && setting.repeat == 1 && setting.sweep_time_us < 100*ONE_MS_TIME) { - SI446x_Fill(MODE_SELECT(setting.mode), 0); + SI446x_Fill(MODE_SELECT(setting.mode), -1); // First get_RSSI will fail } #endif #endif @@ -2953,6 +2976,10 @@ modulation_again: #endif #endif } +// if (pureRSSI < 400) { +// volatile int i = 0; +// i = i + 1; +// } #ifdef __SPUR__ static pureRSSI_t spur_RSSI = -1; // Initialization only to avoid warning. if (setting.mode == M_LOW && S_STATE(setting.spur_removal)) { @@ -3242,9 +3269,10 @@ sweep_again: // stay in sweep loop when output mo } // end of input specific processing } // ---------------------- end of sweep loop ----------------------------- - if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE ) // if in output mode with modulation - goto sweep_again; // Keep repeating sweep loop till user aborts by input - + if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE) { // if in output mode with modulation + if (!in_selftest) + goto sweep_again; // Keep repeating sweep loop till user aborts by input + } // --------------- check if maximum is above trigger level ----------------- if (setting.trigger != T_AUTO && setting.frequency_step > 0) { // Trigger active @@ -3345,7 +3373,7 @@ sweep_again: // stay in sweep loop when output mo #endif // -------------------------- auto attenuate ---------------------------------- #ifdef TINYSA4 -#define AUTO_TARGET_LEVEL -35 +#define AUTO_TARGET_LEVEL -30 #else #define AUTO_TARGET_LEVEL -25 #endif @@ -3534,6 +3562,21 @@ sweep_again: // stay in sweep loop when output mo markers[1].enabled = search_maximum(1, frequencies[markers[0].index]*2, 8); markers[2].enabled = search_maximum(2, frequencies[markers[0].index]*3, 12); markers[3].enabled = search_maximum(3, frequencies[markers[0].index]*4, 16); +#ifdef TINYSA4 + } else if (setting.measurement == M_AM && markers[0].index > 10) { // ----------IOP measurement + int l = markers[1].index; + int r = markers[2].index; + if (r < l) { + l = markers[2].index; + r = markers[1].index; + markers[1].index = l; + markers[2].index = r; + } + freq_t lf = frequencies[l]; + freq_t rf = frequencies[r]; + markers[1].frequency = lf; + markers[2].frequency = rf; +#endif } else if (setting.measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) { // ----------IOP measurement int l = markers[0].index; int r = markers[1].index; @@ -3578,6 +3621,7 @@ sweep_again: // stay in sweep loop when output mo } } else if (setting.measurement == M_AM) { // ----------------AM measurement if (S_IS_AUTO(setting.agc )) { +#ifdef __SI4432__ int actual_level = actual_t[max_index[0]] - get_attenuation(); // no need for float if (actual_level > -20 ) { setting.agc = S_AUTO_OFF; @@ -3590,6 +3634,7 @@ sweep_again: // stay in sweep loop when output mo setting.lna = S_AUTO_ON; } set_AGC_LNA(); +#endif } } @@ -4529,6 +4574,37 @@ void self_test(int test) reset_settings(M_LOW); setting.step_delay_mode = SD_NORMAL; setting.step_delay = 0; + } else if (test == 4) { + reset_settings(M_LOW); + set_mode(M_GENLOW); + set_sweep_frequency(ST_CENTER, (freq_t)30000000); + set_sweep_frequency(ST_SPAN, (freq_t)0); + setting.modulation = MO_AM; + setting.modulation_frequency = 5000; + in_selftest = true; + config.cor_am = 0; + perform(false,0, 30000000, false); + perform(false,1, 30000000, false); + config.cor_am = -(start_of_sweep_timestamp - (ONE_SECOND_TIME / setting.modulation_frequency))/8; + + setting.modulation = MO_NFM; + setting.modulation_frequency = 5000; + in_selftest = true; + config.cor_nfm = 0; + perform(false,0, 30000000, false); + perform(false,1, 30000000, false); + config.cor_nfm = -(start_of_sweep_timestamp - (ONE_SECOND_TIME / setting.modulation_frequency))/8; + + setting.modulation = MO_WFM; + setting.modulation_frequency = 5000; + in_selftest = true; + config.cor_wfm = 0; + perform(false,0, 30000000, false); + perform(false,1, 30000000, false); + config.cor_wfm = -(start_of_sweep_timestamp - (ONE_SECOND_TIME / setting.modulation_frequency))/8; + + // shell_printf("\n\rCycle time = %d\n\r", start_of_sweep_timestamp); + reset_settings(M_LOW); } else if (test == 5) { // reset_settings(M_LOW); // Make sure we are in a defined state in_selftest = true; @@ -4616,7 +4692,7 @@ void calibrate(void) test_prepare(TEST_POWER); setting.step_delay_mode = SD_PRECISE; #ifndef TINYSA4 - setting.agc = S_OFF; + setting.agc = S_ON; setting.lna = S_OFF; #endif test_acquire(TEST_POWER); // Acquire test diff --git a/si4468.c b/si4468.c index 58aed4c..ca19688 100644 --- a/si4468.c +++ b/si4468.c @@ -1897,7 +1897,8 @@ again: SI4463_do_api(data, 1, data, 3); // TODO no clear of interrups if (data[2] == 0) goto again; if (data[2] == 255) goto again; - age[i]=(char)data[2]; + if (i >= 0) + age[i]=(char)data[2]; // Skip first RSSI if (++i >= sweep_points) break; if (t) my_microsecond_delay(t); @@ -1908,7 +1909,7 @@ again: __enable_irq(); setting.measure_sweep_time_us = (chVTGetSystemTimeX() - measure)*100; - buf_index = start; // Is used to skip 1st entry during level triggering + buf_index = (start<=0 ? 0 : start); // Is used to skip 1st entry during level triggering buf_read = true; } #endif @@ -2484,6 +2485,7 @@ freq_t SI4463_set_freq(freq_t freq) 0x10 + (uint8_t)(SI4463_band + (Npresc ? 0x08 : 0)) // 0x08 for high performance mode, 0x10 to skip recal }; SI4463_do_api(data2, sizeof(data2), NULL, 0); + SI4463_frequency_changed = true; // my_microsecond_delay(30000); } diff --git a/ui_sa.c b/ui_sa.c index 7a06b1a..e8a15c9 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -965,10 +965,18 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) reset_settings(setting.mode); for (int i = 0; i< 3; i++) { markers[i].enabled = M_ENABLED; +#ifdef TINYSA4 + markers[i].mtype = M_DELTA| M_TRACKING; +#else markers[i].mtype = M_DELTA;// | M_TRACKING; +#endif } freq_t center, span; +#ifdef TINYSA4 + markers[0].mtype = M_REFERENCE | M_TRACKING; +#else markers[0].mtype = M_REFERENCE;// | M_TRACKING; +#endif kp_help_text = "Frequency of signal"; ui_mode_keypad(KM_CENTER); center = uistat.value; @@ -977,12 +985,17 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) // if (uistat.value < 3000) // break; span = uistat.value; +#ifdef TINYSA4 + set_RBW(span/300); +#endif set_sweep_frequency(ST_SPAN, span * 10); // update_frequencies(); // To ensure markers are positioned right!!!!!! set_measurement(M_AM); +#ifndef TINYSA4 set_marker_frequency(0, center); set_marker_frequency(1, center-span); set_marker_frequency(2, center+span); +#endif set_average(4); break; case M_FM: // FM @@ -999,7 +1012,11 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) ui_mode_keypad(KM_SPAN); if (uistat.value < 1000 || uistat.value > 2500) break; +#ifdef TINYSA4 + set_RBW(uistat.value/300); +#else set_RBW(uistat.value/100); +#endif // actual_rbw_x10 kp_help_text = "Frequency deviation: 3 .. 500kHz"; ui_mode_keypad(KM_SPAN);