diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 54c247b..c65f2cb 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -17,7 +17,7 @@
-
+
diff --git a/main.c b/main.c
index c5975a4..3903302 100644
--- a/main.c
+++ b/main.c
@@ -978,8 +978,10 @@ config_t config = {
.lna_level_offset = 100,
.low_level_output_offset = 100.0, // Uncalibrated
.high_level_output_offset = 0, // Uncalibrated, but checking code is not yet present
- .harmonic_level_offset = -11.5,
- .shift_level_offset = -1.5,
+ .harmonic_level_offset = 7,
+ .shift_level_offset = -0.5,
+ .drive1_level_offset = -1,
+ .drive2_level_offset = -1.5,
.correction_frequency =
{
{ 10000, 100000, 1000000, 5000000, 15000000, 30000000, 145000000, 400000000, 720000000, 800000000, 800000001, 1519000000, 1527000000, 3000000000, 3500000000, 4000000000, 4500000000, 5000000000, 5500000000, 6000000000 }, // low in
diff --git a/nanovna.h b/nanovna.h
index f34ca55..afd3384 100644
--- a/nanovna.h
+++ b/nanovna.h
@@ -139,6 +139,8 @@
#define ULTRA_AUTO 10000000000ULL // 10GHz
//#define ULTRA_MAX_FREQ 2900000000ULL
#define MAX_LO_FREQ 4350000000ULL
+#define MAX_ABOVE_IF_FREQ 3350000000ULL
+#define MIN_BELOW_IF_FREQ 2300000000ULL
//#define LOW_MAX_FREQ 800000000ULL
#define MIN_BELOW_LO 550000000ULL
#ifdef __NEW_SWITCHES__
@@ -707,6 +709,8 @@ typedef struct config {
float lna_level_offset;
float harmonic_level_offset;
float shift_level_offset;
+ float drive1_level_offset;
+ float drive2_level_offset;
#endif
#ifdef __NOISE_FIGURE__
float noise_figure;
diff --git a/sa_cmd.c b/sa_cmd.c
index 31eec74..800c516 100644
--- a/sa_cmd.c
+++ b/sa_cmd.c
@@ -338,7 +338,7 @@ VNA_SHELL_FUNCTION(cmd_leveloffset)
{
// 0 1 2
#ifdef TINYSA4
- static const char cmd_mode_list[] = "low|high|switch|receive_switch|lna|harmonic|shift";
+ static const char cmd_mode_list[] = "low|high|switch|receive_switch|lna|harmonic|shift|drive1|drive2";
#else
static const char cmd_mode_list[] = "low|high|switch|receive_switch";
#endif
@@ -354,6 +354,8 @@ VNA_SHELL_FUNCTION(cmd_leveloffset)
shell_printf(p, "lna", config.lna_level_offset);
shell_printf(p, "harmonic", config.harmonic_level_offset);
shell_printf(p, "shift", config.shift_level_offset);
+ shell_printf(p, "drive1", config.drive1_level_offset);
+ shell_printf(p, "drive2", config.drive2_level_offset);
#endif
return;
}
@@ -374,6 +376,8 @@ VNA_SHELL_FUNCTION(cmd_leveloffset)
case 4: config.lna_level_offset = v; break;
case 5: config.harmonic_level_offset = v; break;
case 6: config.shift_level_offset = v; break;
+ case 7: config.drive1_level_offset = v; break;
+ case 8: config.drive2_level_offset = v; break;
#endif
default: goto usage;
}
@@ -684,7 +688,7 @@ VNA_SHELL_FUNCTION(cmd_d)
(void) argc;
(void) argv;
int32_t a = my_atoi(argv[0]);
-#ifdef TINYSA4
+#if false
int32_t d;
if (argc == 2)
d = my_atoi(argv[1]);
diff --git a/sa_core.c b/sa_core.c
index bcb4bee..519995b 100644
--- a/sa_core.c
+++ b/sa_core.c
@@ -70,6 +70,7 @@ int spur_gate = 100;
#define DEFAULT_ULTRA_THRESHOLD 800000000ULL
freq_t ultra_threshold;
bool ultra;
+static int LO_harmonic;
#endif
#ifdef TINYSA4
int noise_level;
@@ -83,9 +84,11 @@ int linear_averaging = true;
static freq_t old_freq[5] = { 0, 0, 0, 0,0};
static freq_t real_old_freq[5] = { 0, 0, 0, 0,0};
static long real_offset = 0;
-#ifdef __ULTRA__
-static int LO_harmonic;
-#endif
+
+
+static int LO_spur_shifted;
+static int LO_mirrored;
+static volatile int LO_shifting;
void clear_frequency_cache(void)
{
@@ -109,6 +112,11 @@ float *drive_dBm = (float *) adf_drive_dBm;
const int8_t drive_dBm [16] = {-38, -32, -30, -27, -24, -19, -15, -12, -5, -2, 0, 3, 6, 9, 12, 16};
#endif
+#ifdef __ULTRA__
+int old_drive = -1;
+int actual_drive = -1;
+#endif
+
#ifdef TINYSA4
#define SWITCH_ATTENUATION ((setting.mode == M_GENHIGH && config.high_out_adf4350) ? 40 : 25.0)
#define RECEIVE_SWITCH_ATTENUATION (29 - config.receive_switch_offset)
@@ -875,6 +883,33 @@ static pureRSSI_t get_signal_path_loss(void){ // loss as positive number
#endif
}
+void correct_high_output_level(void)
+{
+ float a = setting.level - level_max();
+#ifdef TINYSA4
+ if (!config.high_out_adf4350) {
+ float dt = Si446x_get_temp() - CENTER_TEMPERATURE;
+ if (dt > 0)
+ a += dt * DB_PER_DEGREE_ABOVE; // Temperature correction
+ else
+ a += dt * DB_PER_DEGREE_BELOW; // Temperature correction
+ }
+#endif
+ if (a <= -SWITCH_ATTENUATION) {
+ setting.atten_step = true;
+ a = a + SWITCH_ATTENUATION;
+ } else {
+ setting.atten_step = false;
+ }
+
+ unsigned int d = MIN_DRIVE;
+ while (drive_dBm[d] - level_max() < a && 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 - (setting.atten_step ? SWITCH_ATTENUATION : 0);
+}
+
void set_level(float v) // Set the output level in dB in high/low output
{
if (setting.mode == M_GENHIGH) {
@@ -904,6 +939,7 @@ void set_level(float v) // Set the output level in dB in high/low output
// set_attenuation(setting.level - LOW_OUT_OFFSET);
}
setting.level = v;
+ if (setting.mode == M_GENHIGH) correct_high_output_level();
dirty = true;
}
@@ -1751,7 +1787,7 @@ static void calculate_correction(void)
#pragma GCC push_options
#pragma GCC optimize ("Og") // "Os" causes problem
-pureRSSI_t get_frequency_correction(freq_t f) // Frequency dependent RSSI correction to compensate for imperfect LPF
+pureRSSI_t get_frequency_correction(freq_t f) // Frequency dependent RSSI correction to subtract for imperfect LPF
{
pureRSSI_t cv = 0;
int c=CORRECTION_LOW;
@@ -1762,13 +1798,29 @@ pureRSSI_t get_frequency_correction(freq_t f) // Frequency dependent RSSI c
#ifdef TINYSA4
if (setting.extra_lna)
c += 1;
- if (setting.mode == M_LOW && ultra && f > ultra_threshold) {
- c = CORRECTION_LOW_ULTRA;
- if ( f > ULTRA_MAX_FREQ) {
- cv -= float_TO_PURE_RSSI(config.harmonic_level_offset); // +10.5dB correction.
+ if (setting.mode == M_LOW) {
+ switch(actual_drive) {
+ case 1:
+ cv += float_TO_PURE_RSSI(-1);
+ break;
+ case 2:
+ cv += float_TO_PURE_RSSI(-1.5);
+ break;
+ case 3:
+ cv += float_TO_PURE_RSSI(-2);
+ break;
}
- if (setting.extra_lna)
- c += 1;
+ if (ultra && f > ultra_threshold) {
+ c = CORRECTION_LOW_ULTRA;
+ if (LO_harmonic) {
+ cv += float_TO_PURE_RSSI(config.harmonic_level_offset); // +10.5dB correction.
+ }
+ if (setting.extra_lna)
+ c += 1;
+ }
+// if (LO_shifting)
+// cv += float_TO_PURE_RSSI(config.shift_level_offset);
+
} else if (setting.mode == M_GENLOW){
c = CORRECTION_LOW_OUT;
}
@@ -1901,9 +1953,6 @@ void setup_sa(void)
#ifdef TINYSA4
static int fast_counter = 0;
#endif
-#ifdef __ULTRA__
-int old_drive = -1;
-#endif
void set_freq(int V, freq_t freq) // translate the requested frequency into a setting of the SI4432
{
@@ -1988,25 +2037,26 @@ void set_freq(int V, freq_t freq) // translate the requested frequency into a
}
#endif
if (freq) {
+#if 0 // moved
// ----------------------------- set mixer drive --------------------------------------------
int target_drive = setting.lo_drive;
if (target_drive & 0x04){ // Automatic mixer drive
if (LO_harmonic)
target_drive = 3;
- else if (freq-970000000 < 600000000ULL) // below 100MHz
+ else if (freq-970000000 < 600000000ULL) // below 600MHz
target_drive = 0;
else if (freq-970000000 < 1200000000ULL) // below 1.2GHz
target_drive = 1;
- else if (freq-970000000 < 2000000000ULL) // below 3GHz
- target_drive = 2;
+// else if (freq-970000000 < 2000000000ULL) // below 2GHz
+// target_drive = 2;
else
- target_drive = 3;
+ target_drive = 2;
}
if (old_drive != target_drive) {
ADF4351_drive(target_drive); // Max drive
old_drive = target_drive;
}
-
+#endif
real_old_freq[V] = ADF4351_set_frequency(V-ADF4351_LO,freq);
}
} else if (V==ADF4351_LO2) {
@@ -2851,11 +2901,7 @@ static systime_t sweep_elapsed = 0; // Time since fi
uint8_t signal_is_AM = false;
static uint8_t check_for_AM = false;
static int is_below = false;
-#ifdef TINYSA4
-static int LO_shifted;
-static int LO_mirrored;
-static int LO_shifting;
-#endif
+
static void calculate_static_correction(void) // Calculate the static part of the RSSI correction
{
@@ -3243,19 +3289,6 @@ pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) /
auto_set_AGC_LNA(true, 0);
}
#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 (setting.frequency_step != 0) {
- correct_RSSI_freq = get_frequency_correction(f);
- }
- }
-// #define DEBUG_CORRECTION
-#ifdef DEBUG_CORRECTION
- if (SDU1.config->usbp->state == USB_ACTIVE) {
- shell_printf ("%d:%Q %f\r\n", i, f, PURE_TO_float(correct_RSSI_freq));
- osalThreadSleepMilliseconds(2);
-}
-#endif
// ----------------------------- Initiate modulation ---------------------------
@@ -3360,12 +3393,14 @@ modulation_again:
freq_t local_IF;
#ifdef TINYSA4
local_IF = config.frequency_IF1;
+#if 0
if (setting.mode == M_LOW && setting.frequency_step > 0 && ultra &&
((f < ULTRA_MAX_FREQ && f > MAX_LO_FREQ - local_IF) ||
( f > ultra_threshold && f < MIN_BELOW_LO + local_IF))
) {
local_vbw_steps *= 2;
}
+#endif
#endif
// -----------------------------------START vbwsteps loop ------------------------------------
@@ -3410,7 +3445,7 @@ again: // Spur redu
local_IF=0; // For all high modes
#ifdef TINYSA4
- LO_shifted = false;
+ LO_spur_shifted = false;
LO_mirrored = false;
LO_shifting = false;
#endif
@@ -3460,7 +3495,7 @@ again: // Spur redu
#endif
#ifdef __ULTRA__
if (S_IS_AUTO(setting.below_IF)) {
- if ((freq_t)lf + (freq_t)local_IF> MAX_LO_FREQ && lf <= ULTRA_MAX_FREQ)
+ if ((freq_t)lf > MAX_ABOVE_IF_FREQ /* && lf <= ULTRA_MAX_FREQ */ )
setting.below_IF = S_AUTO_ON; // Only way to reach this range.
else
setting.below_IF = S_AUTO_OFF; // default is above IF
@@ -3471,7 +3506,7 @@ again: // Spur redu
#ifdef TINYSA4
( lf > ULTRA_MAX_FREQ || // Harmonic mode
lf < 400000000 || // below 400MHz use below IF
- ( lf + (uint64_t)local_IF< MAX_LO_FREQ && lf > 2 * local_IF + 10000000) )
+ ( lf < MAX_ABOVE_IF_FREQ && lf > MIN_BELOW_IF_FREQ) ) // From 2.1GHz to 3.35GHz use below IF
#else
#ifdef __ULTRA__
( (lf > ULTRA_MAX_FREQ && (lf + local_IF) / setting.harmonic < MAX_LO_FREQ) || lf < local_IF - MIN_LO_FREQ || ( lf + (uint32_t)local_IF< MAX_LO_FREQ && lf > MIN_BELOW_LO + local_IF) )
@@ -3489,13 +3524,14 @@ again: // Spur redu
}
else // if (setting.auto_IF)
{
-#ifdef TINYSA4
- LO_shifting = true;
-#endif
if ((debug_avoid && debug_avoid_second) || spur_second_pass) {
#ifdef TINYSA4
local_IF = local_IF + DEFAULT_SPUR_OFFSET-(actual_rbw_x10 > 1000 ? 200000 : 0); // apply IF spur shift
- LO_shifted = true;
+ LO_spur_shifted = true;
+#ifdef TINYSA4
+ LO_shifting = true;
+#endif
+
} else {
local_IF = local_IF; // - (actual_rbw_x10 > 5000 ? 200000 : 0);// - DEFAULT_SPUR_OFFSET/2; // apply IF spur shift
}
@@ -3523,7 +3559,7 @@ again: // Spur redu
local_IF = local_IF + DEFAULT_SPUR_OFFSET/2;
// if (actual_rbw_x10 == 6000 )
// local_IF = local_IF + 50000;
- LO_shifted = true;
+ LO_spur_shifted = true;
}
}
} else {
@@ -3548,7 +3584,7 @@ again: // Spur redu
local_IF = local_IF + (actual_rbw_x10 > 2000 ? DEFAULT_SPUR_OFFSET : DEFAULT_SPUR_OFFSET/2); // TODO find better way to shift spur away at large RBW/2;
// if (actual_rbw_x10 == 6000 )
// local_IF = local_IF + 50000;
- LO_shifted = true;
+ LO_spur_shifted = true;
}
} else
{
@@ -3763,6 +3799,26 @@ again: // Spur redu
target_f /= setting.harmonic;
LO_harmonic = true;
}
+ // ----------------------------- set mixer drive --------------------------------------------
+ if (setting.mode == M_LOW) {
+ actual_drive = setting.lo_drive;
+ if (actual_drive & 0x04){ // Automatic mixer drive
+ if (LO_harmonic)
+ actual_drive = 3;
+ else if (lf < 600000000ULL) // below 600MHz
+ actual_drive = 0;
+ else if (lf < 1200000000ULL) // below 1.2GHz
+ actual_drive = 1;
+ else if (lf < 2000000000ULL) // below 2GHz
+ actual_drive = 2;
+ else
+ actual_drive = 3;
+ }
+ if (old_drive != actual_drive) {
+ ADF4351_drive(actual_drive); // Max drive
+ old_drive = actual_drive;
+ }
+ }
set_freq(ADF4351_LO, target_f);
#if 1 // Compensate frequency ADF4350 error with SI4468
if (actual_rbw_x10 < 10000 || setting.frequency_step < 100000) { //TODO always compensate for the moment as this eliminates artifacts at larger RBW
@@ -3775,10 +3831,9 @@ again: // Spur redu
goto correct_min;
}
correct_plus:
- if (setting.harmonic && lf > ULTRA_MAX_FREQ) {
+ if (LO_harmonic)
error_f *= setting.harmonic;
- }
- if (error_f > actual_rbw_x10 * 5) //RBW / 4
+ if (error_f > actual_rbw_x10 * 5 || LO_harmonic) //RBW / 4
local_IF += error_f;
} else if ( real_old_freq[ADF4351_LO] < target_f) {
error_f = real_old_freq[ADF4351_LO] - target_f;
@@ -3787,10 +3842,10 @@ again: // Spur redu
goto correct_plus;
}
correct_min:
- if (setting.harmonic && lf > ULTRA_MAX_FREQ) {
+ if (LO_harmonic) {
error_f *= setting.harmonic;
}
- if ( error_f < - actual_rbw_x10 * 5) //RBW / 4
+ if ( error_f < - actual_rbw_x10 * 5 || LO_harmonic) //RBW / 4
local_IF += error_f;
}
}
@@ -3897,7 +3952,7 @@ again: // Spur redu
if (delta < actual_rbw_x10*100)
spur = '!';
}
- char shifted = ( LO_shifted ? '>' : ' ');
+ char shifted = ( LO_spur_shifted ? '>' : ' ');
if (SDU1.config->usbp->state == USB_ACTIVE)
shell_printf ("%d:%c%c%c%cLO=%11.6Lq:%11.6Lq\tIF=%11.6Lq:%11.6Lq\tOF=%11.6d\tF=%11.6Lq:%11.6Lq\tD=%.2f:%.2f %c%c%c\r\n",
i, spur, shifted,(LO_mirrored ? 'm' : ' '), (LO_harmonic ? 'h':' ' ),
@@ -3912,6 +3967,22 @@ again: // Spur redu
#endif
// ------------------------- end of processing when in output mode ------------------------------------------------
+
+ // 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 (setting.frequency_step != 0 || (i==0 && scandirty)) {
+ correct_RSSI_freq = get_frequency_correction(f);
+ }
+ }
+ // #define DEBUG_CORRECTION
+ #ifdef DEBUG_CORRECTION
+ if (SDU1.config->usbp->state == USB_ACTIVE) {
+ shell_printf ("%d:%Q %f\r\n", i, f, PURE_TO_float(correct_RSSI_freq));
+ osalThreadSleepMilliseconds(2);
+ }
+ #endif
+
+
skip_LO_setting:
if (i == 0 && t == 0) // if first point in scan (here is get 1 point data)
start_of_sweep_timestamp = chVTGetSystemTimeX(); // initialize start sweep time
@@ -4005,6 +4076,9 @@ again: // Spur redu
#endif
#ifdef __SI4463__
pureRSSI = Si446x_RSSI();
+ if (LO_shifting)
+ pureRSSI -= float_TO_PURE_RSSI(config.shift_level_offset);
+
#endif
if (break_on_operation && operation_requested) // allow aborting a wait for trigger
goto abort; //return 0; // abort
@@ -4043,7 +4117,7 @@ again: // Spur redu
int my_step_delay = SI4432_step_delay;
if (f < 2000000 && actual_rbw_x10 == 3 && !in_step_test)
my_step_delay = my_step_delay * 2;
-// if (LO_shifted) // || SI4463_offset_changed)
+// if (LO_spur_shifted) // || SI4463_offset_changed)
// my_step_delay = my_step_delay * 2;
#if 0 // Always have some delay before measuring RSSI
if (old_R < 4 && actual_rbw_x10 >= 1000 && SI4463_frequency_changed && ADF4351_frequency_changed) {
@@ -4099,8 +4173,11 @@ again: // Spur redu
#ifdef __SI4463__
if (real_old_freq[SI4463_RX] == 0)
pureRSSI = 0;
- else
+ else {
pureRSSI = Si446x_RSSI();
+ if (LO_shifting)
+ pureRSSI -= float_TO_PURE_RSSI(config.shift_level_offset);
+ }
//#define __DEBUG_FREQUENCY_SETTING__
#ifdef __DEBUG_FREQUENCY_SETTING__ // For debugging the frequency calculation
stored_t[i] = -60.0 + (real_old_freq[ADF4351_LO] - f - old_freq[2])/10;
@@ -4145,13 +4222,6 @@ again: // Spur redu
}
#endif
-#ifdef TINYSA4
- if (LO_shifting)
- pureRSSI -= float_TO_PURE_RSSI(config.shift_level_offset);
-// if (LO_harmonic)
-// pureRSSI -= float_TO_PURE_RSSI(config.harmonic_level_offset);
-#endif
-
if (RSSI < pureRSSI) // Take max during subscanning
RSSI = pureRSSI;
t++; // one subscan done
diff --git a/ui_sa.c b/ui_sa.c
index 25c2fe4..6fd5aae 100644
--- a/ui_sa.c
+++ b/ui_sa.c
@@ -3296,7 +3296,10 @@ static void fetch_numeric_target(uint8_t mode)
#ifdef __ULTRA__
case KM_ULTRA_START:
uistat.freq_value = config.ultra_threshold;
- plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value );
+ if (config.ultra_threshold == ULTRA_AUTO)
+ plot_printf(uistat.text, sizeof uistat.text, "AUTO");
+ else
+ plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value );
break;
case KM_DIRECT_START:
uistat.freq_value = config.direct_start;