Merge branch 'master' of https://github.com/erikkaashoek/tinySA into DiSlord_test_branch

pull/4/head
DiSlord 6 years ago
commit e365edb083

@ -156,7 +156,7 @@ void reset_settings(int m)
dirty = true; dirty = true;
} }
uint32_t calc_min_sweep_time_us(void) // Calculate minimum sweep time in uS uint32_t calc_min_sweep_time_us(void) // Calculate minimum sweep time in uS needed just because of the delays for the RSSI to become stable
{ {
float t; float t;
float a = (actualStepDelay + MEASURE_TIME); // in uS float a = (actualStepDelay + MEASURE_TIME); // in uS
@ -221,14 +221,14 @@ void set_level_sweep(float l)
dirty = true; dirty = true;
} }
void set_sweep_time_us(uint32_t t) void set_sweep_time_us(uint32_t t) // Set the sweep time as the user wants it to be.
{ {
if (t < MINIMUM_SWEEP_TIME) if (t < MINIMUM_SWEEP_TIME)
t = MINIMUM_SWEEP_TIME; t = MINIMUM_SWEEP_TIME;
if (t > MAXIMUM_SWEEP_TIME) if (t > MAXIMUM_SWEEP_TIME)
t = MAXIMUM_SWEEP_TIME; t = MAXIMUM_SWEEP_TIME;
setting.sweep_time_us = t; setting.sweep_time_us = t;
uint32_t ta = calc_min_sweep_time_us(); uint32_t ta = calc_min_sweep_time_us(); // Can not be faster than minimum sweep time
if (ta < t) if (ta < t)
ta = t; ta = t;
setting.actual_sweep_time_us = ta; setting.actual_sweep_time_us = ta;
@ -330,7 +330,7 @@ float get_attenuation(void)
static const int drive_dBm [16] = {-38,-35,-33,-30,-27,-24,-21,-19,-7,-4,-2, 1, 4, 7, 10, 13}; static const int drive_dBm [16] = {-38,-35,-33,-30,-27,-24,-21,-19,-7,-4,-2, 1, 4, 7, 10, 13};
void set_level(float v) void set_level(float v) // Set the drive level of the LO
{ {
if (setting.mode == M_GENHIGH) { if (setting.mode == M_GENHIGH) {
int d = 0; int d = 0;
@ -346,7 +346,7 @@ void set_level(float v)
dirty = true; dirty = true;
} }
void set_attenuation(float a) void set_attenuation(float a) // Is used both in output mode and input mode
{ {
if (setting.mode == M_GENLOW) { if (setting.mode == M_GENLOW) {
a = a + POWER_OFFSET; a = a + POWER_OFFSET;
@ -439,9 +439,9 @@ void toggle_normalize(void)
extern float peakLevel; extern float peakLevel;
void set_actual_power(float o) void set_actual_power(float o) // Set peak level to known value
{ {
float new_offset = o - peakLevel + get_level_offset(); float new_offset = o - peakLevel + get_level_offset(); // calculate offset based on difference between measured peak level and known peak level
if (o == 100) new_offset = 0; if (o == 100) new_offset = 0;
if (setting.mode == M_HIGH) { if (setting.mode == M_HIGH) {
config.high_level_offset = new_offset; config.high_level_offset = new_offset;
@ -458,7 +458,7 @@ void set_actual_power(float o)
int get_level_offset(void) int get_level_offset(void)
{ {
if (setting.mode == M_HIGH) { if (setting.mode == M_HIGH) {
if (config.high_level_offset == 100) if (config.high_level_offset == 100) // Offset of 100 means not calibrated
return 0; return 0;
return(config.high_level_offset); return(config.high_level_offset);
} }
@ -513,10 +513,10 @@ void set_harmonic(int h)
} }
#endif #endif
void set_step_delay(int d) void set_step_delay(int d) // override RSSI measurement delay or set to one of three auto modes
{ {
if ((3 <= d && d < 300) || d > 30000) if ((3 <= d && d < 300) || d > 30000) // values 0 (fast scan), 1 (precise scan) and 2(extra fast scan) have special meaning and are auto calculated
return; return;
setting.step_delay = d; setting.step_delay = d;
dirty = true; dirty = true;
@ -755,7 +755,7 @@ void set_mode(int m)
// dirty = true; // dirty = true;
} }
void apply_settings(void) void apply_settings(void) // Ensure all settings in the setting structure are translated to the right HW setup
{ {
set_switches(setting.mode); set_switches(setting.mode);
if (setting.mode == M_HIGH) if (setting.mode == M_HIGH)
@ -767,12 +767,12 @@ void apply_settings(void)
} }
SI4432_SetReference(setting.refer); SI4432_SetReference(setting.refer);
update_rbw(); update_rbw();
if (setting.frequency_step == 0.0) { if (setting.frequency_step == 0.0) { // zero span mode, not dependend on selected RBW
if (setting.step_delay <= 2) if (setting.step_delay <= 2)
actualStepDelay = 0; actualStepDelay = 0;
else else
actualStepDelay = setting.step_delay; actualStepDelay = setting.step_delay;
} else if (setting.step_delay <= 2){ } else if (setting.step_delay <= 2){ // Frequency sweep so use RBW to calculate minimum delay when changing frequency
if (actual_rbw >= 191.0) actualStepDelay = 280; if (actual_rbw >= 191.0) actualStepDelay = 280;
else if (actual_rbw >= 142.0) actualStepDelay = 350; else if (actual_rbw >= 142.0) actualStepDelay = 350;
else if (actual_rbw >= 75.0) actualStepDelay = 450; else if (actual_rbw >= 75.0) actualStepDelay = 450;
@ -782,7 +782,7 @@ void apply_settings(void)
else if (actual_rbw >= 9.0) actualStepDelay = 1700; else if (actual_rbw >= 9.0) actualStepDelay = 1700;
else if (actual_rbw >= 5.0) actualStepDelay = 3300; else if (actual_rbw >= 5.0) actualStepDelay = 3300;
else actualStepDelay = 6400; else actualStepDelay = 6400;
if (setting.step_delay == 1) if (setting.step_delay == 1) // In precise mode wait twice as long for RSSI to stabalize
actualStepDelay *= 2; actualStepDelay *= 2;
} else } else
actualStepDelay = setting.step_delay; actualStepDelay = setting.step_delay;
@ -799,7 +799,7 @@ static const float correction_value[CORRECTION_POINTS] =
{ +4.0, +2.0, +1.5, +0.5, 0.0, 0.0, +1.0, +1.0, +2.5, +5.0 }; { +4.0, +2.0, +1.5, +0.5, 0.0, 0.0, +1.0, +1.0, +2.5, +5.0 };
#endif #endif
float get_frequency_correction(uint32_t f) float get_frequency_correction(uint32_t f) // Frequency dependent RSSI correction to compensate for imperfect LPF
{ {
if (!(setting.mode == M_LOW)) if (!(setting.mode == M_LOW))
return(0.0); return(0.0);
@ -846,41 +846,42 @@ extern int SI4432_frequency_changed;
extern int SI4432_offset_changed; extern int SI4432_offset_changed;
static systime_t set_freq_time; static systime_t set_freq_time;
void set_freq(int V, unsigned long freq) void set_freq(int V, unsigned long freq) // translate the requested frequency into a setting of the SI4432
{ {
if (old_freq[V] != freq) { if (old_freq[V] != freq) { // Do not change HW if not needed
if (V <= 1) { if (V <= 1) {
SI4432_Sel = V; SI4432_Sel = V;
if (freq < 240000000 || freq > 960000000) { if (freq < 240000000 || freq > 960000000) { // Impossible frequency, simply ignore, should never happen.
real_old_freq[V] = freq + 1; real_old_freq[V] = freq + 1; // No idea why this is done........
return; return;
} }
#if 1 #if 1
if (setting.step_delay == 2) { if (setting.step_delay == 2) { // If in extra fast scanning mode
int delta = freq - real_old_freq[V]; int delta = freq - real_old_freq[V];
if (real_old_freq[V] >= 480000000) // 480MHz, high band if (real_old_freq[V] >= 480000000) // 480MHz, high band
delta = delta >> 1; delta = delta >> 1;
if (delta > 0 && delta < 80000) { // use frequency deviation registers if (delta > 0 && delta < 80000) { // and requested frequency can be reached by using the offset registers
#if 0
if (0) { if (0) {
if (real_old_freq[V] >= 480000000) if (real_old_freq[V] >= 480000000)
shell_printf("%d: Offs %q HW %d\r\n", SI4432_Sel, (uint32_t)(real_old_freq[V]+delta*2), real_old_freq[V]); shell_printf("%d: Offs %q HW %d\r\n", SI4432_Sel, (uint32_t)(real_old_freq[V]+delta*2), real_old_freq[V]);
else else
shell_printf("%d: Offs %q HW %d\r\n", SI4432_Sel, (uint32_t)(real_old_freq[V]+delta*1), real_old_freq[V]); shell_printf("%d: Offs %q HW %d\r\n", SI4432_Sel, (uint32_t)(real_old_freq[V]+delta*1), real_old_freq[V]);
} }
#endif
delta = delta * 4 / 625; // = 156.25; delta = delta * 4 / 625; // = 156.25; // Calculate and set the offset register i.s.o programming a new frequency
SI4432_Write_Byte(0x73, (uint8_t)(delta & 0xff)); SI4432_Write_Byte(0x73, (uint8_t)(delta & 0xff));
SI4432_Write_Byte(0x74, (uint8_t)((delta >> 8) & 0x03)); SI4432_Write_Byte(0x74, (uint8_t)((delta >> 8) & 0x03));
SI4432_offset_changed = true; SI4432_offset_changed = true; // Signal offset changed so RSSI retrieval is delayed for frequency settling
old_freq[V] = freq; old_freq[V] = freq;
return; return;
} }
} }
#endif #endif
set_freq_time = chVTGetSystemTimeX(); set_freq_time = chVTGetSystemTimeX();
SI4432_Set_Frequency(freq); SI4432_Set_Frequency(freq); // Impossible to use offset so set SI4432 to new frequency
SI4432_Write_Byte(0x73, 0); SI4432_Write_Byte(0x73, 0); // set offset to zero
SI4432_Write_Byte(0x74, 0); SI4432_Write_Byte(0x74, 0);
#ifdef __ULTRA_SA__ #ifdef __ULTRA_SA__
} else { } else {
@ -928,7 +929,7 @@ case M_ULTRA:
#endif #endif
SI4432_Sel = 0; SI4432_Sel = 0;
SI4432_Receive(); SI4432_Receive();
if (setting.atten_step) { if (setting.atten_step) { // use switch as attenuator
set_switch_transmit(); set_switch_transmit();
} else { } else {
set_switch_receive(); set_switch_receive();
@ -953,7 +954,7 @@ mute:
SI4432_Sel = 1; SI4432_Sel = 1;
SI4432_Receive(); SI4432_Receive();
if (setting.atten_step) { if (setting.atten_step) {// use switch as attenuator
set_switch_transmit(); set_switch_transmit();
} else { } else {
set_switch_receive(); set_switch_receive();
@ -965,7 +966,7 @@ case M_GENLOW: // Mixed output from 0
if (setting.mute) if (setting.mute)
goto mute; goto mute;
SI4432_Sel = 0; SI4432_Sel = 0;
if (setting.atten_step) { if (setting.atten_step) { // use switch as attenuator
set_switch_off(); set_switch_off();
} else { } else {
set_switch_transmit(); set_switch_transmit();
@ -990,7 +991,7 @@ case M_GENHIGH: // Direct output from 1
SI4432_Sel = 1; SI4432_Sel = 1;
if (setting.drive < 8) { if (setting.drive < 8) {
set_switch_off(); set_switch_off(); // use switch as attenuator
} else { } else {
set_switch_transmit(); set_switch_transmit();
} }
@ -1004,16 +1005,16 @@ case M_GENHIGH: // Direct output from 1
} }
void update_rbw(void) void update_rbw(void) // calculate the actual_rbw and the vbwSteps (# steps in between needed if frequency step is largen than maximum rbw)
{ {
if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) { if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) {
setting.vbw = (setting.frequency_step)/1000.0; setting.vbw = (setting.frequency_step)/1000.0;
} else { } else {
setting.vbw = 300; // trick to get right default rbw in zero span mode setting.vbw = 300; // trick to get right default rbw in zero span mode
} }
actual_rbw = setting.rbw; actual_rbw = setting.rbw; // requested rbw
if (actual_rbw == 0) { if (actual_rbw == 0) { // if auto rbw
actual_rbw = 2*setting.vbw; actual_rbw = 2*setting.vbw; // rbw is twice the frequency step to ensure no gaps in coverage
} }
if (actual_rbw < 2.6) if (actual_rbw < 2.6)
actual_rbw = 2.6; actual_rbw = 2.6;
@ -1021,27 +1022,25 @@ void update_rbw(void)
actual_rbw = 600; actual_rbw = 600;
if (setting.spur && actual_rbw > 300) if (setting.spur && actual_rbw > 300)
actual_rbw = 250; actual_rbw = 250; // if spur suppression reduce max rbw to fit within BPF
SI4432_Sel = MODE_SELECT(setting.mode); SI4432_Sel = MODE_SELECT(setting.mode);
actual_rbw = SI4432_SET_RBW(actual_rbw); actual_rbw = SI4432_SET_RBW(actual_rbw); // see what rbw the SI4432 can realize
if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) { if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) { // When doing frequency scanning in input mode
if (setting.step_delay==1) // Precise vbwSteps = ((int)(2 * (setting.vbw + (actual_rbw/2)) / actual_rbw)); // calculate # steps in between each frequency step due to rbw being less than frequency step
vbwSteps = ((int)(2 * (setting.vbw + (actual_rbw/2)) / (actual_rbw / 2))); if (setting.step_delay==1) // if in Precise scanning
else vbwSteps *= 2; // use twice as many steps
vbwSteps = ((int)(2 * (setting.vbw + (actual_rbw/2)) / actual_rbw)); if (vbwSteps < 1) // at least one step
if (vbwSteps < 1)
vbwSteps = 1; vbwSteps = 1;
} else { } else { // in all other modes
setting.vbw = actual_rbw; setting.vbw = actual_rbw;
vbwSteps = 1; vbwSteps = 1; // only one vbwSteps
} }
dirty = true; dirty = true;
} }
int binary_search_frequency(int f) int binary_search_frequency(int f) // Search which index in the frequency tabled matches with frequency f using actual_rbw
{ {
int L = 0; int L = 0;
int R = (sizeof frequencies)/sizeof(int) - 1; int R = (sizeof frequencies)/sizeof(int) - 1;
@ -1127,9 +1126,9 @@ search_maximum(int m, int center, int span)
} }
//static int spur_old_stepdelay = 0; //static int spur_old_stepdelay = 0;
static const unsigned int spur_IF = 433800000; static const unsigned int spur_IF = 433800000; // The IF frequency for which the spur table is value
static const unsigned int spur_alternate_IF = 433900000; static const unsigned int spur_alternate_IF = 433900000; // if the frequency is found in the spur table use this IF frequency
static const int spur_table[] = static const int spur_table[] = // Frequencies to avoid
{ {
580000, // 433.8 MHz table 580000, // 433.8 MHz table
961000, 961000,
@ -1204,7 +1203,7 @@ int binary_search(int f)
} }
int avoid_spur(int f) int avoid_spur(int f) // find if this frequency should be avoided
{ {
// int window = ((int)actual_rbw ) * 1000*2; // int window = ((int)actual_rbw ) * 1000*2;
// if (window < 50000) // if (window < 50000)
@ -1216,26 +1215,26 @@ int avoid_spur(int f)
static int modulation_counter = 0; static int modulation_counter = 0;
static const int am_modulation[5] = { 4,0,1,5,7 }; static const int am_modulation[5] = { 4,0,1,5,7 }; // 5 step AM modulation
static const int nfm_modulation[5] = { 0, 2, 1, -1, -2}; static const int nfm_modulation[5] = { 0, 2, 1, -1, -2}; // 5 step narrow FM modulation
static const int wfm_modulation[5] = { 0, 190, 118, -118, -190 }; static const int wfm_modulation[5] = { 0, 190, 118, -118, -190 }; // 5 step wide FM modulation
char age[POINTS_COUNT]; char age[POINTS_COUNT];
static float old_a = -150; static float old_a = -150;
float perform(bool break_on_operation, int i, uint32_t f, int tracking) float perform(bool break_on_operation, int i, uint32_t f, int tracking) // Measure the RSSI for one frequency, used from sweep and other measurement routines. Must do all HW setup
{ {
if (i == 0 && dirty ) { // SCan initiation if (i == 0 && dirty ) { // if first point in scan and dirty
apply_settings(); apply_settings(); // Initialize HW
scandirty = true; scandirty = true; // This is the first pass with new settings
dirty = false; dirty = false;
if (setting.spur) if (setting.spur) // if in spur avoidance mode
setting.spur = 1; // resync spur in case of previous abort setting.spur = 1; // resync spur in case of previous abort
} }
if (setting.mode == M_GENLOW && setting.level_sweep != 0.0) { if (setting.mode == M_GENLOW && setting.level_sweep != 0.0) { // if in low output mode and level sweep is active
float ls=setting.level_sweep; float ls=setting.level_sweep; // calculate and set the output level
if (ls > 0) if (ls > 0)
ls += 0.5; ls += 0.5;
else else
@ -1275,8 +1274,8 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
} }
} }
if (setting.mode == M_LOW && S_IS_AUTO(setting.agc) && UNIT_IS_LOG(setting.unit)) { if (setting.mode == M_LOW && S_IS_AUTO(setting.agc) && UNIT_IS_LOG(setting.unit)) { // If in low input mode with auto AGC and log unit
unsigned char v; unsigned char v; // Adapt the AGC setting if needed
static unsigned char old_v; static unsigned char old_v;
if (f < 500000) if (f < 500000)
v = 0x50; // Disable AGC and enable LNA v = 0x50; // Disable AGC and enable LNA
@ -1287,6 +1286,9 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
old_v = v; old_v = v;
} }
} }
// ----------------------------------------------------- modulation for output modes ---------------------------------------
if (MODE_OUTPUT(setting.mode) && (setting.modulation == MO_AM_1kHz||setting.modulation == MO_AM_10Hz)) { // AM modulation if (MODE_OUTPUT(setting.mode) && (setting.modulation == MO_AM_1kHz||setting.modulation == MO_AM_10Hz)) { // AM modulation
int p = setting.attenuate * 2 + am_modulation[modulation_counter]; int p = setting.attenuate * 2 + am_modulation[modulation_counter];
if (p>63) if (p>63)
@ -1325,10 +1327,10 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
my_microsecond_delay(200); my_microsecond_delay(200);
// chThdSleepMicroseconds(200); // chThdSleepMicroseconds(200);
} }
// -------------------------------- Acquisition loop for one requested frequency covering spur avoidance and vbwsteps ------------------------
float RSSI = -150.0; float RSSI = -150.0;
int t = 0; int t = 0;
do { // ------------- Acquisition loop ---------- do {
int offs = 0,sm; int offs = 0,sm;
uint32_t lf = (uint32_t)f; uint32_t lf = (uint32_t)f;
if (vbwSteps > 1) { // Calculate sub steps if (vbwSteps > 1) { // Calculate sub steps
@ -1351,13 +1353,13 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
#ifdef __SPUR__ #ifdef __SPUR__
float spur_RSSI = 0; float spur_RSSI = 0;
#endif #endif
if (MODE_INPUT(setting.mode) && i > 0 && FREQ_IS_CW()) // In input mode in zero span mode after first setting of the LO's
goto skip_LO_setting; // No more LO changes required, save some time and jump over the code
long local_IF;
if (MODE_INPUT(setting.mode) && i > 0 && FREQ_IS_CW()) again: // Spur reduction jumps to here for second measurement
goto skip_LO_setting; // No LO changes during CW loop
long local_IF;
again:
if (MODE_HIGH(setting.mode)) if (MODE_HIGH(setting.mode))
local_IF = 0; local_IF = 0;
else { else {
@ -1370,33 +1372,35 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
else else
local_IF = setting.frequency_IF; local_IF = setting.frequency_IF;
} }
if (setting.mode == M_LOW && tracking) { // Measure BPF if (setting.mode == M_LOW && tracking) { // VERY SPECIAL CASE!!!!! Measure BPF
set_freq (0, local_IF + lf - reffer_freq[setting.refer]); // Offset so fundamental of reffer is visible set_freq (0, local_IF + lf - reffer_freq[setting.refer]); // Offset so fundamental of reffer is visible
} else if (MODE_LOW(setting.mode)) { } else if (MODE_LOW(setting.mode)) {
if (setting.mode == M_LOW && !in_selftest && avoid_spur(f)) { if (setting.mode == M_LOW && !in_selftest && avoid_spur(f)) { // check is alternate IF is needed to avoid spur.
local_IF = spur_alternate_IF; local_IF = spur_alternate_IF;
#ifdef __SPUR__ #ifdef __SPUR__
} else if (setting.mode== M_LOW && setting.spur){ } else if (setting.mode== M_LOW && setting.spur){ // If in low input mode and spur reduction is on
if (S_IS_AUTO(setting.below_IF) && lf < 150000000) // if below 150MHz and auto_below_IF swap IF if (S_IS_AUTO(setting.below_IF) && lf < 150000000) // if below 150MHz and auto_below_IF
{ // else low/above IF { // else low/above IF
if (setting.spur == 1) if (setting.spur == 1)
setting.below_IF = S_AUTO_ON; setting.below_IF = S_AUTO_ON; // use below IF in first pass
else else
setting.below_IF = S_AUTO_OFF; setting.below_IF = S_AUTO_OFF; // and above IF in second pass
} }
else { else {
int32_t spur_offset = actual_rbw * 1000; int32_t spur_offset = actual_rbw * 1000; // Can not use below IF so calculate IF shift that hopefully will kill the spur.
if (setting.spur == -1) if (setting.spur == -1) // If second spur pass
spur_offset = - spur_offset; spur_offset = - spur_offset; // IF shift in the other direction
local_IF = local_IF + spur_offset; local_IF = local_IF + spur_offset; // apply IF spur shift
} }
#endif #endif
} else {
// local_IF = setting.frequency_IF ;
} }
if (setting.mode == M_GENLOW && setting.modulation == MO_EXTERNAL) // LO input via high port if (setting.mode == M_GENLOW && setting.modulation == MO_EXTERNAL) // VERY SPECIAL CASE !!!!!! LO input via high port
local_IF += lf; local_IF += lf;
// --------------------- IF know, set the RX SI4432 frequency ------------------------
set_freq (0, local_IF); set_freq (0, local_IF);
#ifdef __ULTRA__ #ifdef __ULTRA__
} else if (setting.mode == M_ULTRA) { // No above/below IF mode in Ultra } else if (setting.mode == M_ULTRA) { // No above/below IF mode in Ultra
local_IF = setting.frequency_IF + (int)(actual_rbw < 350.0 ? setting.spur*300000 : 0 ); local_IF = setting.frequency_IF + (int)(actual_rbw < 350.0 ? setting.spur*300000 : 0 );
@ -1435,12 +1439,15 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
set_freq (3, IF_2 - 433800000); // Down from IF2 to fixed second IF in Ultra SA mode set_freq (3, IF_2 - 433800000); // Down from IF2 to fixed second IF in Ultra SA mode
set_freq (1, 433800000); // Second IF fixe in Ultra SA mode set_freq (1, 433800000); // Second IF fixe in Ultra SA mode
#else #else
if (setting.mode == M_LOW && !setting.tracking && S_STATE(setting.below_IF)) if (setting.mode == M_LOW && !setting.tracking && S_STATE(setting.below_IF)) // if in low input mode and below IF
set_freq (1, local_IF-lf); set_freq (1, local_IF-lf); // set LO SI4432 to below IF frequency
else else
set_freq (1, local_IF+lf); set_freq (1, local_IF+lf); // otherwise to above IF
#endif #endif
} }
// ------------------------- end of processing when in output mode ------------------------------------------------
if (MODE_OUTPUT(setting.mode)) // No substepping and no RSSI in output mode if (MODE_OUTPUT(setting.mode)) // No substepping and no RSSI in output mode
return(0); return(0);
@ -1448,9 +1455,11 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
float signal_path_loss; float signal_path_loss;
skip_LO_setting: skip_LO_setting: // jump here if in zero span mode and all HW frequency setup is done.
#ifdef __FAST_SWEEP__ #ifdef __FAST_SWEEP__
if (i == 0 && setting.frequency_step == 0 && setting.trigger == T_AUTO && setting.spur == 0 && actualStepDelay == 0 && setting.repeat == 1 && setting.sweep_time_us < ONE_SECOND_TIME) { if (i == 0 && setting.frequency_step == 0 && setting.trigger == T_AUTO && setting.spur == 0 && actualStepDelay == 0 && setting.repeat == 1 && setting.sweep_time_us < ONE_SECOND_TIME) {
// if ultra fast scanning is needed prefill the SI4432 RSSI read buffer
SI4432_Fill(MODE_SELECT(setting.mode), 0); SI4432_Fill(MODE_SELECT(setting.mode), 0);
} }
#endif #endif
@ -1467,28 +1476,30 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
int wait_for_trigger = false; int wait_for_trigger = false;
int old_actual_step_delay = actualStepDelay; int old_actual_step_delay = actualStepDelay;
if (i == 0 && setting.frequency_step == 0 && setting.trigger != T_AUTO) { // prepare for wait for trigger to happen if (i == 0 && setting.frequency_step == 0 && setting.trigger != T_AUTO) { // if in zero span mode and wait for trigger to happen and NOT in trigger mode
wait_for_trigger = true; wait_for_trigger = true; // signal the wait for trigger
actualStepDelay = 0; // fastest possible in zero span trigger mode actualStepDelay = 0; // and ignore requested sweep time to be as fast as possible
} }
float subRSSI; float subRSSI;
static float correct_RSSI; static float correct_RSSI; // This is re-used between calls
if (i == 0 || setting.frequency_step != 0 ) // only cases where the value can change if (i == 0 || setting.frequency_step != 0 ) // only cases where the value can change
correct_RSSI = get_level_offset()+ get_attenuation() - signal_path_loss - setting.offset + get_frequency_correction(f); correct_RSSI = get_level_offset()+ get_attenuation() - signal_path_loss - setting.offset + get_frequency_correction(f); // calcuate the RSSI correction for later use
wait:
subRSSI = SI4432_RSSI(lf, MODE_SELECT(setting.mode)) + correct_RSSI ; wait:
subRSSI = SI4432_RSSI(lf, MODE_SELECT(setting.mode)) + correct_RSSI ; // Get RSSI, either from pre-filled buffer or by reading SI4432 RSSI
// if ( i < 3) // if ( i < 3)
// shell_printf("%d %.3f %.3f %.1f\r\n", i, local_IF/1000000.0, lf/1000000.0, subRSSI); // shell_printf("%d %.3f %.3f %.1f\r\n", i, local_IF/1000000.0, lf/1000000.0, subRSSI);
if (wait_for_trigger) { // wait for trigger to happen if (wait_for_trigger) { // wait for trigger to happen
if ((operation_requested || shell_function) && break_on_operation) if ((operation_requested || shell_function) && break_on_operation) // allow aborting a wait for trigger
break; // abort break; // abort
if (subRSSI < setting.trigger_level) if (subRSSI < setting.trigger_level) // trigger level not yet reached
goto wait; goto wait; // get next rssi
#ifdef __FAST_SWEEP__ #ifdef __FAST_SWEEP__
if (i == 0 && setting.frequency_step == 0 /* && setting.trigger == T_AUTO */&& setting.spur == 0 && old_actual_step_delay == 0 && setting.repeat == 1 && setting.sweep_time_us < ONE_SECOND_TIME) { if (i == 0 && setting.frequency_step == 0 /* && setting.trigger == T_AUTO */&& setting.spur == 0 && old_actual_step_delay == 0 && setting.repeat == 1 && setting.sweep_time_us < ONE_SECOND_TIME) {
SI4432_Fill(MODE_SELECT(setting.mode), 1); SI4432_Fill(MODE_SELECT(setting.mode), 1); // fast mode possible to pre-fill RSSI buffer
} }
#endif #endif
actualStepDelay = old_actual_step_delay; // Trigger happened, restore step delay actualStepDelay = old_actual_step_delay; // Trigger happened, restore step delay
@ -1498,21 +1509,21 @@ float perform(bool break_on_operation, int i, uint32_t f, int tracking)
#ifdef __SPUR__ #ifdef __SPUR__
if (setting.spur == 1) { // If first spur pass if (setting.spur == 1) { // If first spur pass
spur_RSSI = subRSSI; spur_RSSI = subRSSI; // remember measure RSSI
setting.spur = -1; setting.spur = -1; // and prepare for second pass
goto again; // Skip all other processing goto again; // Skip all other processing
} else if (setting.spur == -1) { // If second spur pass } else if (setting.spur == -1) { // If second spur pass
subRSSI = ( subRSSI < spur_RSSI ? subRSSI : spur_RSSI); // Take minimum of two subRSSI = ( subRSSI < spur_RSSI ? subRSSI : spur_RSSI); // Take minimum of two
setting.spur = 1; setting.spur = 1; // and prepare for next call of perform.
} }
#endif #endif
if (RSSI < subRSSI) // Take max during subscanning if (RSSI < subRSSI) // Take max during subscanning
RSSI = subRSSI; RSSI = subRSSI;
t++; t++; // one subscan done
if ((operation_requested || shell_function ) && break_on_operation) // break subscanning if requested if ((operation_requested || shell_function ) && break_on_operation) // break subscanning if requested
break; // abort break; // abort
} while (t < vbwSteps); } while (t < vbwSteps); // till all sub steps done
return(RSSI); return(RSSI);
} }
@ -1534,18 +1545,21 @@ static bool sweep(bool break_on_operation)
// if (setting.mode== -1) // if (setting.mode== -1)
// return; // return;
// START_PROFILE; // START_PROFILE;
again: again: // Waiting for a trigger jumps back to here
downslope = true;
palClearPad(GPIOB, GPIOB_LED); palClearPad(GPIOB, GPIOB_LED);
downslope = true; // Initialize the peak search algoritm
temppeakLevel = -150; temppeakLevel = -150;
float temp_min_level = 100; float temp_min_level = 100;
// spur_old_stepdelay = 0; // spur_old_stepdelay = 0;
int repeats = 1; int repeats = 1;
// shell_printf("\r\n"); // shell_printf("\r\n");
if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE) { if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE) { // If in output mode
repeats = 1000; // to avoid interrupting the tone during UI processing repeats = 1000; // stay as long as possible in the sweep loop to avoid interrupting the tone during by UI processing
modulation_counter = 0; modulation_counter = 0; // init modulation counter
} }
uint32_t t = calc_min_sweep_time_us(); // Time to delay in uS uint32_t t = calc_min_sweep_time_us(); // Time to delay in uS
if (t < setting.sweep_time_us){ if (t < setting.sweep_time_us){
t = setting.sweep_time_us - t; t = setting.sweep_time_us - t;
@ -1553,23 +1567,34 @@ again:
} }
else else
t = 0; t = 0;
if (MODE_OUTPUT(setting.mode) && t < 500) // Minimum wait time to prevent LO from lockup if (MODE_OUTPUT(setting.mode) && t < 500) // Minimum wait time to prevent LO from lockup
t = 500; t = 500;
set_freq_time = 0;
set_freq_time = 0; // for predicting the weep time
while (repeats--) { while (repeats--) {
for (int i = 0; i < sweep_points; i++) {
if (start_index == -1 && start_time == 0 && set_freq_time != 0) { // ------------------------- sweep loop -----------------------------------
for (int i = 0; i < sweep_points; i++) {
if (start_index == -1 && start_time == 0 && set_freq_time != 0) { // Sweep time prediction: first real set SI4432 freq
start_index = i; start_index = i;
start_time = set_freq_time; start_time = set_freq_time; // remember time
set_freq_time = 0;
} else if (start_index != -1 && start_time != 0 && set_freq_time != 0 ) {
uint32_t total_time = 290*(set_freq_time - start_time)*100/(i - start_index);
if (1) shell_printf("%d T:%f\r\n", i, total_time / 1000000.0);
set_freq_time = 0; set_freq_time = 0;
} else if (start_index != -1 && start_time != 0 && set_freq_time != 0 ) { // next real set si4432 freq
uint32_t total_time = 290*(set_freq_time - start_time)*100/(i - start_index); // use in between time to predict total sweep time
// shell_printf("%d T:%f\r\n", i, total_time / 1000000.0);
set_freq_time = 0; // retrigger detection of si4432 set freq
} }
RSSI = perform(break_on_operation, i, frequencies[i], setting.tracking); // --------------------- measure -------------------------
RSSI = perform(break_on_operation, i, frequencies[i], setting.tracking); // Measure RSSI for one of the frequencies
// ----------------- delay between points if needed ----------------
if (t && (MODE_INPUT(setting.mode) || setting.modulation == MO_NONE)) { if (t && (MODE_INPUT(setting.mode) || setting.modulation == MO_NONE)) {
if (t < 30*ONE_MS_TIME) if (t < 30*ONE_MS_TIME)
my_microsecond_delay(t); my_microsecond_delay(t);
@ -1578,23 +1603,26 @@ again:
} }
// back to toplevel to handle ui operation // back to toplevel to handle ui operation
if ((operation_requested || shell_function) && break_on_operation) { if ((operation_requested || shell_function) && break_on_operation) { // break loop if needed
if (setting.actual_sweep_time_us > ONE_SECOND_TIME) { if (setting.actual_sweep_time_us > ONE_SECOND_TIME) {
ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, WIDTH, 1, 0); ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, WIDTH, 1, 0);
} }
return false; return false;
} }
if (MODE_OUTPUT(setting.mode)) {
continue; // Skip all other processing if (MODE_OUTPUT(setting.mode)) { // if in output mode
continue; // Skip all other processing in sweep loop
} }
if (MODE_INPUT(setting.mode)) { if (MODE_INPUT(setting.mode)) { // this is always true I guess......
if (setting.actual_sweep_time_us > ONE_SECOND_TIME && (i & 0x07) == 0) {
ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, i, 1, BRIGHT_COLOR_GREEN); if (setting.actual_sweep_time_us > ONE_SECOND_TIME && (i & 0x07) == 0) { // if required
ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, i, 1, BRIGHT_COLOR_GREEN); // update sweep progress bar
ili9341_fill(OFFSETX+i, HEIGHT_NOSCROLL+1, WIDTH-i, 1, 0); ili9341_fill(OFFSETX+i, HEIGHT_NOSCROLL+1, WIDTH-i, 1, 0);
} }
// ------------------------ do all RSSI calculations frm CALC menu -------------------
if (setting.average != AV_OFF) if (setting.average != AV_OFF)
temp_t[i] = RSSI; temp_t[i] = RSSI;
if (setting.subtract_stored) { if (setting.subtract_stored) {
@ -1623,7 +1651,9 @@ again:
case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break; case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break;
} }
} }
#if 1
// --------------------------- find peak and add to peak table if found ------------------------
// START_PROFILE // START_PROFILE
if (i == 0) { // Prepare peak finding if (i == 0) { // Prepare peak finding
@ -1648,7 +1678,7 @@ again:
temppeakLevel = actual_t[i]; temppeakLevel = actual_t[i];
} else if (actual_t[i] < temppeakLevel - setting.noise) { // Local max found } else if (actual_t[i] < temppeakLevel - setting.noise) { // Local max found
// maintain sorted peak table
int j = 0; // Insert max in sorted table int j = 0; // Insert max in sorted table
while (j<cur_max && actual_t[max_index[j]] >= temppeakLevel) // Find where to insert while (j<cur_max && actual_t[max_index[j]] >= temppeakLevel) // Find where to insert
j++; j++;
@ -1674,22 +1704,18 @@ again:
} }
} }
} // end of peak finding } // end of peak finding
#else
if (frequencies[i] > 1000000) {
if (temppeakLevel < actual_t[i]) {
temppeakIndex = i;
temppeakLevel = actual_t[i];
}
}
#endif
if (temp_min_level > actual_t[i]) // Remember minimum if (temp_min_level > actual_t[i]) // Remember minimum
temp_min_level = actual_t[i]; temp_min_level = actual_t[i];
} }
// --------------- check if maximum is above trigger level -----------------
if (setting.trigger != T_AUTO && setting.frequency_step > 0) { // Trigger active if (setting.trigger != T_AUTO && setting.frequency_step > 0) { // Trigger active
if (actual_t[max_index[0]] < setting.trigger_level) { if (actual_t[max_index[0]] < setting.trigger_level) {
goto again; goto again; // not yet, sweep again
} else { } else {
if (setting.trigger == T_SINGLE) if (setting.trigger == T_SINGLE)
pause_sweep(); // Stop scanning after completing this sweep if above trigger pause_sweep(); // Stop scanning after completing this sweep if above trigger
@ -1697,12 +1723,16 @@ again:
scandirty = true; // To show trigger happened scandirty = true; // To show trigger happened
} }
// ---------------------- sweep finished, do all postprocessing ---------------------
if (scandirty) { if (scandirty) {
scandirty = false; scandirty = false;
redraw_request |= REDRAW_CAL_STATUS; redraw_request |= REDRAW_CAL_STATUS;
} }
if (!in_selftest && setting.mode == M_LOW && setting.auto_attenuation && max_index[0] > 0) { // Auto attenuate // -------------------------- auto attenuate ----------------------------------
if (!in_selftest && setting.mode == M_LOW && setting.auto_attenuation && max_index[0] > 0) { // calculate and apply auto attenuate
setting.atten_step = false; // No step attenuate in low mode auto attenuate setting.atten_step = false; // No step attenuate in low mode auto attenuate
float old_attenuate = get_attenuation(); float old_attenuate = get_attenuation();
float actual_max_level = actual_t[max_index[0]] - old_attenuate; float actual_max_level = actual_t[max_index[0]] - old_attenuate;
@ -1725,6 +1755,9 @@ again:
// dirty = true; // Must be above if(scandirty!!!!!) // dirty = true; // Must be above if(scandirty!!!!!)
} }
} }
// ---------------------------------- auto AGC ----------------------------------
if (!in_selftest && MODE_INPUT(setting.mode) && S_IS_AUTO(setting.agc) && UNIT_IS_LINEAR(setting.unit)) { // Auto AGC in linear mode if (!in_selftest && MODE_INPUT(setting.mode) && S_IS_AUTO(setting.agc) && UNIT_IS_LINEAR(setting.unit)) { // Auto AGC in linear mode
unsigned char v; unsigned char v;
static unsigned char old_v; static unsigned char old_v;
@ -1739,6 +1772,9 @@ again:
} }
} }
// -------------------------- auto reflevel ---------------------------------
if (max_index[0] > 0) if (max_index[0] > 0)
temppeakLevel = actual_t[max_index[0]]; temppeakLevel = actual_t[max_index[0]];
@ -1787,7 +1823,9 @@ again:
// dirty = false; // Prevent reset of SI4432 // dirty = false; // Prevent reset of SI4432
} }
} }
#if 1
// --------------------- set tracking markers from maximum table -----------------
if (MODE_INPUT(setting.mode)) { // Assign maxima found to tracking markers if (MODE_INPUT(setting.mode)) { // Assign maxima found to tracking markers
int i = 0; int i = 0;
int m = 0; int m = 0;
@ -1810,12 +1848,16 @@ again:
} }
m++; // Try next marker m++; // Try next marker
} }
// ----------------------- now follow all the special marker calculations for the measurement modes ----------------------------
#ifdef __MEASURE__ #ifdef __MEASURE__
if (setting.measurement == M_IMD && markers[0].index > 10) { // IMD measurement if (setting.measurement == M_IMD && markers[0].index > 10) { // ----- IMD measurement
markers[1].enabled = search_maximum(1, frequencies[markers[0].index]*2, 8); 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[2].enabled = search_maximum(2, frequencies[markers[0].index]*3, 12);
markers[3].enabled = search_maximum(3, frequencies[markers[0].index]*4, 16); markers[3].enabled = search_maximum(3, frequencies[markers[0].index]*4, 16);
} else if (setting.measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) { // IOP measurement } else if (setting.measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) { // ----------IOP measurement
int l = markers[0].index; int l = markers[0].index;
int r = markers[1].index; int r = markers[1].index;
if (r < l) { if (r < l) {
@ -1828,14 +1870,14 @@ again:
uint32_t rf = frequencies[r]; uint32_t rf = frequencies[r];
markers[2].enabled = search_maximum(2, lf - (rf - lf), 12); markers[2].enabled = search_maximum(2, lf - (rf - lf), 12);
markers[3].enabled = search_maximum(3, rf + (rf - lf), 12); markers[3].enabled = search_maximum(3, rf + (rf - lf), 12);
} else if (setting.measurement == M_PHASE_NOISE && markers[0].index > 10) { // Phase noise measurement } else if (setting.measurement == M_PHASE_NOISE && markers[0].index > 10) { // ------------Phase noise measurement
markers[1].index = markers[0].index + (setting.mode == M_LOW ? 290/4 : -290/4); // Position phase noise marker at requested offset markers[1].index = markers[0].index + (setting.mode == M_LOW ? 290/4 : -290/4); // Position phase noise marker at requested offset
} else if (setting.measurement == M_STOP_BAND && markers[0].index > 10) { // Stop band measurement } else if (setting.measurement == M_STOP_BAND && markers[0].index > 10) { // -------------Stop band measurement
markers[1].index = marker_search_left_min(markers[0].index); markers[1].index = marker_search_left_min(markers[0].index);
if (markers[1].index < 0) markers[1].index = 0; if (markers[1].index < 0) markers[1].index = 0;
markers[2].index = marker_search_right_min(markers[0].index); markers[2].index = marker_search_right_min(markers[0].index);
if (markers[2].index < 0) markers[1].index = setting._sweep_points - 1; if (markers[2].index < 0) markers[1].index = setting._sweep_points - 1;
} else if (setting.measurement == M_PASS_BAND && markers[0].index > 10) { // Pass band measurement } else if (setting.measurement == M_PASS_BAND && markers[0].index > 10) { // ----------------Pass band measurement
int t = markers[0].index; int t = markers[0].index;
float v = actual_t[t]; float v = actual_t[t];
while (t > 0 && actual_t[t] > v - 3.0) // Find left -3dB point while (t > 0 && actual_t[t] > v - 3.0) // Find left -3dB point
@ -1848,11 +1890,12 @@ again:
if (t < setting._sweep_points - 1 ) if (t < setting._sweep_points - 1 )
markers[2].index = t; markers[2].index = t;
} }
#endif #endif
peakIndex = max_index[0]; peakIndex = max_index[0];
peakLevel = actual_t[peakIndex]; peakLevel = actual_t[peakIndex];
peakFreq = frequencies[peakIndex]; peakFreq = frequencies[peakIndex];
#else #if 0
int peak_marker = 0; int peak_marker = 0;
markers[peak_marker].enabled = true; markers[peak_marker].enabled = true;
markers[peak_marker].index = peakIndex; markers[peak_marker].index = peakIndex;
@ -1861,6 +1904,11 @@ again:
min_level = temp_min_level; min_level = temp_min_level;
} }
} }
//---------------- in Linearity measurement the attenuation has to be adapted ------------------
if (setting.measurement == M_LINEARITY && setting.linearity_step < setting._sweep_points) { if (setting.measurement == M_LINEARITY && setting.linearity_step < setting._sweep_points) {
setting.attenuate = 29.0 - setting.linearity_step * 30.0 / 290.0; setting.attenuate = 29.0 - setting.linearity_step * 30.0 / 290.0;
dirty = true; dirty = true;
@ -1870,7 +1918,7 @@ again:
// redraw_marker(peak_marker, FALSE); // redraw_marker(peak_marker, FALSE);
// STOP_PROFILE; // STOP_PROFILE;
if (setting.actual_sweep_time_us > ONE_SECOND_TIME) { if (setting.actual_sweep_time_us > ONE_SECOND_TIME) { // Clear sweep progress bar at end of sweep
ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, WIDTH, 1, 0); ili9341_fill(OFFSETX, HEIGHT_NOSCROLL+1, WIDTH, 1, 0);
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.