diff --git a/main.c b/main.c index 95fe5b6..a874c86 100644 --- a/main.c +++ b/main.c @@ -989,6 +989,7 @@ config_t config = { .cor_wfm = -55, .cor_nfm = -55, .ultra = false, + .high_out_adf4350 = true, #endif .sweep_voltage = 3.3, }; diff --git a/nanovna.h b/nanovna.h index a5a6bca..1868b99 100644 --- a/nanovna.h +++ b/nanovna.h @@ -621,6 +621,7 @@ typedef struct config { int8_t cor_am; int8_t cor_wfm; int8_t cor_nfm; + uint8_t high_out_adf4350; float sweep_voltage; uint32_t dummy; // uint8_t _reserved[22]; diff --git a/sa_core.c b/sa_core.c index 441f9d3..494f3ac 100644 --- a/sa_core.c +++ b/sa_core.c @@ -48,7 +48,6 @@ freq_t maxFreq = 520000000; int spur_gate = 100; uint32_t old_CFGR; uint32_t orig_CFGR; -int high_out_adf4350 = false; int debug_frequencies = false; @@ -74,18 +73,18 @@ const float si_drive_dBm [] = {-41, -30, -21, -17, -12, -11, -10, -8.5, -7.5 const float adf_drive_dBm[] = {-15,-12,-9,-6}; const uint8_t drive_register[] = {0, 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; -float *drive_dBm = (float *) si_drive_dBm; +float *drive_dBm = (float *) adf_drive_dBm; #else const int8_t drive_dBm [16] = {-38, -32, -30, -27, -24, -19, -15, -12, -5, -2, 0, 3, 6, 9, 12, 16}; #endif #ifdef TINYSA4 -#define SWITCH_ATTENUATION (high_out_adf4350 ? 0 : 37) +#define SWITCH_ATTENUATION (setting.mode == M_GENHIGH && config.high_out_adf4350 ? 0 : 37) //#define POWER_OFFSET -18 // Max level with all enabled //#define POWER_RANGE 70 -#define MAX_DRIVE (high_out_adf4350 ? 3 : 18) -#define MIN_DRIVE (high_out_adf4350 ? 0: 2) +#define MAX_DRIVE (setting.mode == M_GENHIGH && config.high_out_adf4350 ? 3 : 18) +#define MIN_DRIVE (setting.mode == M_GENHIGH && config.high_out_adf4350 ? 0: 2) //#define SL_GENHIGH_LEVEL_MIN -15 //#define SL_GENHIGH_LEVEL_RANGE 9 @@ -146,7 +145,7 @@ void update_min_max_freq(void) break; case M_GENHIGH: #ifdef TINYSA4 - if (high_out_adf4350) { + if (config.high_out_adf4350) { minFreq = 136000000; maxFreq = MAX_LO_FREQ; } else { @@ -166,8 +165,7 @@ void reset_settings(int m) // strcpy((char *)spi_buffer, dummy); setting.mode = m; #ifdef TINYSA4 - high_out_adf4350 = false; // Must be false in the low modes - drive_dBm = (float *) si_drive_dBm; + drive_dBm = (float *) (setting.mode == M_GENHIGH && config.high_out_adf4350 ? adf_drive_dBm : si_drive_dBm); #endif update_min_max_freq(); sweep_mode |= SWEEP_ENABLE; @@ -176,8 +174,8 @@ void reset_settings(int m) setting.unit = U_DBM; set_scale(10); set_reflevel(-10); + setting.level_sweep = 0.0; setting.attenuate_x2 = 0; // These should be initialized consistently - setting.level_sweep = 0.0; // And this setting.rx_drive=MAX_DRIVE; // And this setting.atten_step = 0; // And this, only used in low output mode setting.level = level_max(); // This is the level with above settings. @@ -300,7 +298,8 @@ void reset_settings(int m) break; case M_GENHIGH: #ifdef TINYSA4 - setting.lo_drive=MIN_DRIVE; + setting.lo_drive = MIN_DRIVE; + setting.level = drive_dBm[setting.lo_drive]+ config.high_level_output_offset; set_sweep_frequency(ST_CENTER, (minFreq + maxFreq)/2 ); setting.extra_lna = false; #else @@ -487,8 +486,9 @@ void toggle_tracking_output(void) #ifdef TINYSA4 void toggle_high_out_adf4350(void) { - high_out_adf4350 = !high_out_adf4350; - drive_dBm = (float *) (high_out_adf4350 ? adf_drive_dBm : si_drive_dBm); + config.high_out_adf4350 = !config.high_out_adf4350; + drive_dBm = (float *) (config.high_out_adf4350 ? adf_drive_dBm : si_drive_dBm); + config_save(); dirty = true; } @@ -662,32 +662,42 @@ static pureRSSI_t get_signal_path_loss(void){ void set_level(float v) // Set the output level in dB in high/low output { if (setting.mode == M_GENHIGH) { - unsigned int d = 0; + if (v < SL_GENHIGH_LEVEL_MIN) + v = SL_GENHIGH_LEVEL_MIN; + if (v > SL_GENHIGH_LEVEL_MIN + SL_GENHIGH_LEVEL_RANGE) + v = SL_GENHIGH_LEVEL_MIN + SL_GENHIGH_LEVEL_RANGE; +#if 0 + unsigned int d = MIN_DRIVE; v = v - config.high_level_output_offset; while (drive_dBm[d] < v && d < MAX_DRIVE) // Find level equal or above requested level d++; // if (d == 8 && v < -12) // Round towards closest level // d = 7; + v = drive_dBm[d] + config.high_level_output_offset; set_lo_drive(d); - } else { +#endif + } else { // This MUST be low output level if (v < SL_GENLOW_LEVEL_MIN) v = SL_GENLOW_LEVEL_MIN; if (v > SL_GENLOW_LEVEL_MIN + SL_GENLOW_LEVEL_RANGE) v = SL_GENLOW_LEVEL_MIN + SL_GENLOW_LEVEL_RANGE; - setting.level = v; // set_attenuation(setting.level - config.low_level_output_offset); } + setting.level = v; dirty = true; } float get_level(void) { +#if 0 if (setting.mode == M_GENHIGH) { - return drive_dBm[setting.lo_drive] + config.high_level_output_offset; + return v; // drive_dBm[setting.lo_drive] + config.high_level_output_offset; } else { // setting.level = get_attenuation() + config.low_level_output_offset; return setting.level; } +#endif + return setting.level; } @@ -1720,7 +1730,7 @@ case M_GENHIGH: // Direct output from 1 SI4432_Transmit(setting.lo_drive); #endif #ifdef TINYSA4 - if (high_out_adf4350) { + if (config.high_out_adf4350) { #ifdef __SI4468__ SI4463_init_rx(); enable_rx_output(true); // to protect the SI @@ -2238,54 +2248,66 @@ pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) / } } #endif - if (setting.mode == M_GENLOW && ( setting.frequency_step != 0 || setting.level_sweep != 0.0 || i == 0)) {// if in low output mode and level sweep or frequency weep is active or at start of sweep - float ls=setting.level_sweep; // calculate and set the output level - if (ls > 0) - ls += 0.5; - else - ls -= 0.5; - float a = ((int)((setting.level + ((float)i / sweep_points) * ls)*2.0)) / 2.0; - a += PURE_TO_float(get_frequency_correction(f)) - config.low_level_output_offset; - if (a != old_a) { - old_a = a; - a = a - level_max(); // convert to all settings maximum power output equals a = zero - if (a < -SWITCH_ATTENUATION) { - a = a + SWITCH_ATTENUATION; + if (( setting.frequency_step != 0 || setting.level_sweep != 0.0 || i == 0)) { // Initialize or adapt output levels + if (setting.mode == M_GENLOW) {// if in low output mode and level sweep or frequency weep is active or at start of sweep + float ls=setting.level_sweep; // calculate and set the output level + if (ls > 0) + ls += 0.5; + else + ls -= 0.5; + float a = ((int)((setting.level + ((float)i / sweep_points) * ls)*2.0)) / 2.0; + a += PURE_TO_float(get_frequency_correction(f)) - config.low_level_output_offset; + if (a != old_a) { + old_a = a; + a = a - level_max(); // convert to all settings maximum power output equals a = zero + if (a < -SWITCH_ATTENUATION) { + a = a + SWITCH_ATTENUATION; #ifdef TINYSA3 - SI4432_Sel = SI4432_RX ; - set_switch_receive(); + SI4432_Sel = SI4432_RX ; + set_switch_receive(); #else - enable_rx_output(false); + enable_rx_output(false); #endif - } else { + } else { #ifdef TINYSA3 - SI4432_Sel = SI4432_RX ; - set_switch_transmit(); + SI4432_Sel = SI4432_RX ; + set_switch_transmit(); #else - enable_rx_output(true); + enable_rx_output(true); #endif - } + } - int d = MAX_DRIVE; // Reduce level till it fits in attenuator range - while (a - BELOW_MAX_DRIVE(d) < - 31 && d > MIN_DRIVE) { - d--; - } - a -= BELOW_MAX_DRIVE(d); + int d = MAX_DRIVE; // Reduce level till it fits in attenuator range + while (a - BELOW_MAX_DRIVE(d) < - 31 && d > MIN_DRIVE) { + d--; + } + a -= BELOW_MAX_DRIVE(d); #ifdef __SI4432__ - SI4432_Sel = SI4432_RX ; - SI4432_Drive(d); + SI4432_Sel = SI4432_RX ; + SI4432_Drive(d); #endif #ifdef __SI4463__ - SI4463_set_output_level(d); + SI4463_set_output_level(d); #endif - if (a > 0) - a = 0; - if (a < -31.5) - a = -31.5; - a = -a; + if (a > 0) + a = 0; + if (a < -31.5) + a = -31.5; + a = -a; #ifdef __PE4302__ - PE4302_Write_Byte((int)(a * 2) ); + PE4302_Write_Byte((int)(a * 2) ); #endif + } + } + else if (setting.mode == M_GENHIGH) { + unsigned int d = MIN_DRIVE; + float v = setting.level - config.high_level_output_offset; + while (drive_dBm[d] < v && d < MAX_DRIVE) // Find level equal or above requested level + d++; + // if (d == 8 && v < -12) // Round towards closest level + // d = 7; + setting.level = drive_dBm[d] + config.high_level_output_offset; + set_lo_drive(d); } } #ifdef __SI4432__ @@ -2613,7 +2635,7 @@ modulation_again: } else if (setting.mode == M_HIGH) { set_freq (SI4463_RX, lf); // sweep RX, local_IF = 0 in high mode } else if (setting.mode == M_GENHIGH) { - if (high_out_adf4350) { + if (config.high_out_adf4350) { set_freq (ADF4351_LO, lf); // sweep LO, local_IF = 0 in high mode local_IF = 0; } else { diff --git a/ui_sa.c b/ui_sa.c index ecac7f3..112e504 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -403,22 +403,29 @@ static const keypads_t keypads_time[] = { enum { KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, // These must be first to share common help text - KM_REFLEVEL, KM_SCALE, KM_ATTENUATION, - KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE, + //#5 + KM_REFLEVEL, KM_SCALE, KM_ATTENUATION, KM_ACTUALPOWER, KM_IF, + // #10 + KM_SAMPLETIME, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE, #ifdef TINYSA4 KM_30MHZ, #else KM_10MHZ, #endif - KM_REPEAT, KM_OFFSET, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME, KM_OFFSET_DELAY, - KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, KM_HIGHOUTLEVEL, + // #15 + KM_REPEAT, KM_OFFSET, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME, + // #20 + KM_OFFSET_DELAY, KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, + // #25 + KM_HIGHOUTLEVEL, #ifdef TINYSA4 + KM_COR_AM, KM_COR_WFM, KM_COR_NFM, + KM_IF2, + // #30 KM_R,KM_MOD,KM_CP, - KM_COR_AM,KM_COR_WFM, KM_COR_NFM, #endif KM_ATTACK, #ifdef TINYSA4 - KM_IF2, KM_LPF, #endif KM_NONE // always at enum end @@ -433,39 +440,39 @@ static const struct { {keypads_freq , "CENTER"}, // center {keypads_freq , "SPAN"}, // span {keypads_freq , "FREQ"}, // cw freq - {keypads_plusmin_unit, "REF\nLEVEL"}, // reflevel + {keypads_plusmin_unit, "REF\nLEVEL"}, // reflevel #5 {keypads_pos_unit , "SCALE"}, // scale {keypads_positive , "ATTENUATE"}, // attenuation {keypads_plusmin_unit, "ACTUAL\nPOWER"}, // actual power {keypads_freq , "IF"}, // IF - {keypads_positive , "SAMPLE\nDELAY"}, // sample delay + {keypads_positive , "SAMPLE\nDELAY"}, // sample delay #10 {keypads_plusmin , "LEVEL"}, // KM_LOWOUTLEVEL {keypads_positive , "DECAY"}, // KM_DECAY {keypads_positive , "NOISE\nLEVEL"}, // KM_NOISE {keypads_freq , "FREQ"}, // KM_30MHz | KM_10MHz - {keypads_positive , "SAMPLE\nREPEAT"}, // KM_REPEA + {keypads_positive , "SAMPLE\nREPEAT"}, // KM_REPEA #15 {keypads_plusmin , "OFFSET"}, // KM_OFFSET {keypads_plusmin_unit, "TRIGGER\nLEVEL"}, // KM_TRIGGER {keypads_plusmin , "LEVEL\nSWEEP"}, // KM_LEVELSWEEP {keypads_time , "SWEEP\nSECONDS"}, // KM_SWEEP_TIME - {keypads_positive , "OFFSET\nDELAY"}, // KM_OFFSET_DELAY + {keypads_positive , "OFFSET\nDELAY"}, // KM_OFFSET_DELAY #20 {keypads_positive , "FAST\nSPEEDUP"}, // KM_FAST_SPEEDUP {keypads_positive , "MINIMUM\nGRIDLINES"}, // KM_GRIDLINES {keypads_freq , "MARKER\nFREQ"}, // KM_MARKER {keypads_freq , "MODULATION\nFREQ"}, // KM_MODULATION - {keypads_plusmin , "LEVEL"}, // KM_HIGHOUTLEVEL -#ifdef TINYSA + {keypads_plusmin , "LEVEL"}, // KM_HIGHOUTLEVEL #25 +#ifdef TINYSA4 {keypads_plusmin , "COR\nAM"}, // KM_COR_AM {keypads_plusmin , "COR\nWFM"}, // KM_COR_WFM {keypads_plusmin , "COR\nNFM"}, // KM_COR_NFM {keypads_freq , "IF2"}, // KM_IF2 - {keypads_positive , "R"}, // KM_R + {keypads_positive , "R"}, // KM_R #30 {keypads_positive , "MODULO"}, // KM_MOD {keypads_positive , "CP"}, // KM_CP #endif {keypads_positive , "ATTACK"}, // KM_ATTACK #ifdef TINYSA4 - {keypads_freq , "ULTRA\nSTART"}, // KM_LPF + {keypads_freq , "ULTRA\nSTART"}, // KM_LPF #34 #endif }; #if 0 // Not used @@ -833,7 +840,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_adf_out_acb) (void)data; (void)item; if (b){ - b->icon = high_out_adf4350 == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + b->icon = config.high_out_adf4350 == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; return; } toggle_high_out_adf4350(); @@ -2232,7 +2239,7 @@ static void fetch_numeric_target(void) break; case KM_LOWOUTLEVEL: uistat.value = get_level(); // compensation for dB offset during low output mode - int end_level = ((int32_t)uistat.value)+setting.level_sweep; + float end_level = ((int32_t)uistat.value)+setting.level_sweep; if (end_level < level_min()) end_level = level_min(); if (end_level > level_max()) @@ -2240,14 +2247,14 @@ static void fetch_numeric_target(void) 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); + plot_printf(uistat.text, sizeof uistat.text, "%.1f to %.1fdBm", uistat.value, end_level); else - plot_printf(uistat.text, sizeof uistat.text, "%ddBm", ((int32_t)uistat.value)); + plot_printf(uistat.text, sizeof uistat.text, "%.1fdBm", 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)); + plot_printf(uistat.text, sizeof uistat.text, "%.1fdBm", uistat.value); break; case KM_DECAY: uistat.value = setting.decay;