First experiment with span in output mode

tinySA
erikkaashoek 6 years ago
parent 01a665f306
commit 495063f5bf

@ -1,5 +1,4 @@
/* /*
* Copyright (c) 2016-2017, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
* All rights reserved. * All rights reserved.
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
@ -116,7 +115,7 @@ const char *info_about[]={
"Platform: " PLATFORM_NAME, "Platform: " PLATFORM_NAME,
0 // sentinel 0 // sentinel
}; };
extern int dirty;
static THD_WORKING_AREA(waThread1, 900); static THD_WORKING_AREA(waThread1, 900);
static THD_FUNCTION(Thread1, arg) static THD_FUNCTION(Thread1, arg)
{ {
@ -126,7 +125,8 @@ static THD_FUNCTION(Thread1, arg)
while (1) { while (1) {
bool completed = false; bool completed = false;
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) { if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
completed = sweep(true); if (dirty)
completed = sweep(true);
sweep_mode&=~SWEEP_ONCE; sweep_mode&=~SWEEP_ONCE;
} else if (sweep_mode & SWEEP_SELFTEST) { } else if (sweep_mode & SWEEP_SELFTEST) {
self_test(); // call from lowest level to save stack space self_test(); // call from lowest level to save stack space

@ -444,6 +444,10 @@ void setFreq(int V, unsigned long freq)
{ {
SI4432_Sel = V; SI4432_Sel = V;
if (old_freq[V] != freq) { if (old_freq[V] != freq) {
if (V == 0) {
V = -V;
V = -V;
}
SI4432_Set_Frequency(freq); SI4432_Set_Frequency(freq);
old_freq[V] = freq; old_freq[V] = freq;
} }
@ -685,7 +689,7 @@ float perform(bool break_on_operation, int i, int32_t f, int tracking)
long local_IF; long local_IF;
if (MODE_HIGH(setting_mode)) if (MODE_HIGH(setting_mode))
local_IF = 0; local_IF = 0;
else if (avoid_spur(f)) else if (setting_mode == M_LOW && avoid_spur(f))
local_IF = spur_alternate_IF; local_IF = spur_alternate_IF;
else else
local_IF = frequency_IF; local_IF = frequency_IF;
@ -698,7 +702,7 @@ float perform(bool break_on_operation, int i, int32_t f, int tracking)
if (local_IF) { if (local_IF) {
setFreq (0, local_IF); setFreq (0, local_IF);
} }
if (setting_modulation == MO_AM) { if (MODE_OUTPUT(setting_mode) && setting_modulation == MO_AM) {
int p = setting_attenuate * 2 + modulation_counter; int p = setting_attenuate * 2 + modulation_counter;
PE4302_Write_Byte(p); PE4302_Write_Byte(p);
if (modulation_counter == 3) if (modulation_counter == 3)
@ -706,7 +710,7 @@ float perform(bool break_on_operation, int i, int32_t f, int tracking)
else else
modulation_counter++; modulation_counter++;
chThdSleepMicroseconds(250); chThdSleepMicroseconds(250);
} else if (setting_modulation == MO_NFM || setting_modulation == MO_WFM ) { } else if (MODE_OUTPUT(setting_mode) && (setting_modulation == MO_NFM || setting_modulation == MO_WFM )) {
SI4432_Sel = 1; SI4432_Sel = 1;
SI4432_Write_Byte(0x79, modulation_counter); // Use frequency hopping channel for FM modulation SI4432_Write_Byte(0x79, modulation_counter); // Use frequency hopping channel for FM modulation
if (modulation_counter == 3) if (modulation_counter == 3)
@ -719,16 +723,22 @@ float perform(bool break_on_operation, int i, int32_t f, int tracking)
int t = 0; int t = 0;
do { do {
int lf = (uint32_t)(f + (int)(t * 500 * actual_rbw)); int lf = (uint32_t)(f + (int)(t * 500 * actual_rbw));
if (tracking) if (MODE_INPUT(setting_mode) && tracking)
setFreq (0, local_IF + lf - reffer_freq[setting_refer]); // Offset so fundamental of reffer is visible setFreq (0, local_IF + lf - reffer_freq[setting_refer]); // Offset so fundamental of reffer is visible
#if 0
if (lf >11000000 || lf < 9000000) {
lf = lf;
break;
}
#endif
setFreq (1, local_IF + lf); setFreq (1, local_IF + lf);
if (MODE_OUTPUT(setting_mode)) if (MODE_OUTPUT(setting_mode)) // No substepping in output mode
return(0); return(0);
float subRSSI = SI4432_RSSI(lf, MODE_SELECT(setting_mode))+settingLevelOffset()+setting_attenuate; float subRSSI = SI4432_RSSI(lf, MODE_SELECT(setting_mode))+settingLevelOffset()+setting_attenuate;
if (RSSI < subRSSI) if (RSSI < subRSSI)
RSSI = subRSSI; RSSI = subRSSI;
t++; t++;
if ((operation_requested && break_on_operation ) || (MODE_OUTPUT(setting_mode))) // output modes do not step. if (operation_requested && break_on_operation) // output modes do not step.
break; // abort break; // abort
} while (t < vbwSteps); } while (t < vbwSteps);
return(RSSI); return(RSSI);
@ -747,70 +757,70 @@ static bool sweep(bool break_on_operation)
temppeakLevel = -150; temppeakLevel = -150;
float temp_min_level = 100; float temp_min_level = 100;
// spur_old_stepdelay = 0; // spur_old_stepdelay = 0;
//again: //again:
for (int i = 0; i < sweep_points; i++) { for (int i = 0; i < sweep_points; i++) {
RSSI = perform(break_on_operation, i, frequencies[i], setting_tracking); RSSI = perform(break_on_operation, i, frequencies[i], setting_tracking);
// back to toplevel to handle ui operation // back to toplevel to handle ui operation
if (operation_requested && break_on_operation) if (operation_requested && break_on_operation)
return false; return false;
if (MODE_INPUT(setting_mode)) {
// if (setting_spur == 1) { // First pass // if (setting_spur == 1) { // First pass
// temp_t[i] = RSSI; // temp_t[i] = RSSI;
// continue; // Skip all other processing // continue; // Skip all other processing
// } // }
// if (setting_spur == -1) // Second pass // if (setting_spur == -1) // Second pass
// RSSI = ( RSSI < temp_t[i] ? RSSI : temp_t[i]); // Minimum of two passes // RSSI = ( RSSI < temp_t[i] ? RSSI : temp_t[i]); // Minimum of two passes
temp_t[i] = RSSI; temp_t[i] = RSSI;
if (setting_subtract_stored) { if (setting_subtract_stored) {
RSSI = RSSI - stored_t[i] ; RSSI = RSSI - stored_t[i] ;
} }
// stored_t[i] = (SI4432_Read_Byte(0x69) & 0x0f) * 3.0 - 90.0; // Display the AGC value in thestored trace // stored_t[i] = (SI4432_Read_Byte(0x69) & 0x0f) * 3.0 - 90.0; // Display the AGC value in thestored trace
if (scandirty || setting_average == AV_OFF) { if (scandirty || setting_average == AV_OFF) {
actual_t[i] = RSSI; actual_t[i] = RSSI;
age[i] = 0; age[i] = 0;
} else { } else {
switch(setting_average) { switch(setting_average) {
case AV_MIN: if (actual_t[i] > RSSI) actual_t[i] = RSSI; break; case AV_MIN: if (actual_t[i] > RSSI) actual_t[i] = RSSI; break;
case AV_MAX_HOLD: if (actual_t[i] < RSSI) actual_t[i] = RSSI; break; case AV_MAX_HOLD: if (actual_t[i] < RSSI) actual_t[i] = RSSI; break;
case AV_MAX_DECAY: case AV_MAX_DECAY:
if (actual_t[i] < RSSI) { if (actual_t[i] < RSSI) {
actual_t[i] = RSSI; actual_t[i] = RSSI;
age[i] = 0; age[i] = 0;
} else { } else {
if (age[i] > setting_decay) if (age[i] > setting_decay)
actual_t[i] -= 0.5; actual_t[i] -= 0.5;
else else
age[i] += 1; age[i] += 1;
}
break;
case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break;
case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break;
} }
break;
case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break;
case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break;
} }
}
#if 1 #if 1
// START_PROFILE // START_PROFILE
if (i == 0) { if (i == 0) {
cur_max = 0; // Always at least one maximum cur_max = 0; // Always at least one maximum
temppeakIndex = 0; temppeakIndex = 0;
temppeakLevel = actual_t[i];
max_index[0] = 0;
downslope = true;
}
if (downslope) {
if (temppeakLevel > actual_t[i]) { // Follow down
temppeakIndex = i; // Latest minimum
temppeakLevel = actual_t[i]; temppeakLevel = actual_t[i];
} else if (temppeakLevel + setting_noise < actual_t[i]) { // Local minimum found max_index[0] = 0;
temppeakIndex = i; // This is now the latest maximum downslope = true;
temppeakLevel = actual_t[i];
downslope = false;
} }
} else { if (downslope) {
if (temppeakLevel < actual_t[i]) { // Follow up if (temppeakLevel > actual_t[i]) { // Follow down
temppeakIndex = i; temppeakIndex = i; // Latest minimum
temppeakLevel = actual_t[i]; temppeakLevel = actual_t[i];
} else if (temppeakLevel - setting_noise > actual_t[i]) { // Local max found } else if (temppeakLevel + setting_noise < actual_t[i]) { // Local minimum found
temppeakIndex = i; // This is now the latest maximum
temppeakLevel = actual_t[i];
downslope = false;
}
} else {
if (temppeakLevel < actual_t[i]) { // Follow up
temppeakIndex = i;
temppeakLevel = actual_t[i];
} else if (temppeakLevel - setting_noise > actual_t[i]) { // Local max found
int j = 0; // Insertion index int j = 0; // Insertion index
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
@ -819,20 +829,21 @@ static bool sweep(bool break_on_operation)
int k = MAX_MAX-1; int k = MAX_MAX-1;
while (k > j) { // Shift to make room for max while (k > j) { // Shift to make room for max
max_index[k] = max_index[k-1]; max_index[k] = max_index[k-1];
// maxlevel_index[k] = maxlevel_index[k-1]; // Only for debugging // maxlevel_index[k] = maxlevel_index[k-1]; // Only for debugging
k--; k--;
} }
max_index[j] = temppeakIndex; max_index[j] = temppeakIndex;
// maxlevel_index[j] = actual_t[temppeakIndex]; // Only for debugging // maxlevel_index[j] = actual_t[temppeakIndex]; // Only for debugging
if (cur_max < MAX_MAX) { if (cur_max < MAX_MAX) {
cur_max++; cur_max++;
} }
//STOP_PROFILE //STOP_PROFILE
} }
temppeakIndex = i; // Latest minimum temppeakIndex = i; // Latest minimum
temppeakLevel = actual_t[i]; temppeakLevel = actual_t[i];
downslope = true; downslope = true;
}
} }
} }
#else #else
@ -846,75 +857,77 @@ static bool sweep(bool break_on_operation)
temp_min_level = actual_t[i]; temp_min_level = actual_t[i];
#endif #endif
} }
// if (setting_spur == 1) { // if (setting_spur == 1) {
// setting_spur = -1; // setting_spur = -1;
// goto again; // goto again;
// } else if (setting_spur == -1) // } else if (setting_spur == -1)
// setting_spur = 1; // setting_spur = 1;
if (scandirty) { if (scandirty) {
scandirty = false; scandirty = false;
draw_cal_status(); draw_cal_status();
} }
#if 1 #if 1
int i = 0; if (MODE_INPUT(setting_mode)) {
int m = 0; int i = 0;
while (i < cur_max) { // For all maxima found int m = 0;
while (i < cur_max) { // For all maxima found
while (m < MARKERS_MAX) {
if (markers[m].enabled == M_TRACKING_ENABLED) { // Available marker found
markers[m].index = max_index[i];
markers[m].frequency = frequencies[markers[m].index];
m++;
break; // Next maximum
}
m++; // Try next marker
}
i++;
}
while (m < MARKERS_MAX) { while (m < MARKERS_MAX) {
if (markers[m].enabled == M_TRACKING_ENABLED) { // Available marker found if (markers[m].enabled == M_TRACKING_ENABLED ) { // More available markers found
markers[m].index = max_index[i]; markers[m].index = 0; // Enabled but no max
markers[m].frequency = frequencies[markers[m].index]; markers[m].frequency = frequencies[markers[m].index];
m++;
break; // Next maximum
} }
m++; // Try next marker m++; // Try next marker
} }
i++; if (setting_measurement == M_IMD && markers[0].index > 10) {
} markers[1].enabled = search_maximum(1, markers[0].index*2, 8);
while (m < MARKERS_MAX) { markers[2].enabled = search_maximum(2, markers[0].index*3, 12);
if (markers[m].enabled == M_TRACKING_ENABLED ) { // More available markers found markers[3].enabled = search_maximum(3, markers[0].index*4, 16);
markers[m].index = 0; // Enabled but no max } else if (setting_measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) {
markers[m].frequency = frequencies[markers[m].index]; int l = markers[0].index;
} int r = markers[1].index;
m++; // Try next marker if (r < l) {
} l = markers[1].index;
if (setting_measurement == M_IMD && markers[0].index > 10) { r = markers[0].index;
markers[1].enabled = search_maximum(1, markers[0].index*2, 8); }
markers[2].enabled = search_maximum(2, markers[0].index*3, 12); markers[2].enabled = search_maximum(2, l - (r-l), 10);
markers[3].enabled = search_maximum(3, markers[0].index*4, 16); markers[3].enabled = search_maximum(3, r + (r-l), 10);
} else if (setting_measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) {
int l = markers[0].index;
int r = markers[1].index;
if (r < l) {
l = markers[1].index;
r = markers[0].index;
} }
markers[2].enabled = search_maximum(2, l - (r-l), 10); peakIndex = max_index[0];
markers[3].enabled = search_maximum(3, r + (r-l), 10); peakLevel = actual_t[peakIndex];
} peakFreq = frequencies[peakIndex];
peakIndex = max_index[0];
peakLevel = actual_t[peakIndex];
peakFreq = frequencies[peakIndex];
#else #else
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;
markers[peak_marker].frequency = frequencies[markers[peak_marker].index]; markers[peak_marker].frequency = frequencies[markers[peak_marker].index];
#endif #endif
min_level = temp_min_level; min_level = temp_min_level;
#if 0 // Auto ref level setting #if 0 // Auto ref level setting
int scale = get_trace_scale(2); int scale = get_trace_scale(2);
int rp = (NGRIDY - get_trace_refpos(2)) * scale; int rp = (NGRIDY - get_trace_refpos(2)) * scale;
if (scale > 0 && peakLevel > rp && peakLevel - min_level < 8 * scale ) { if (scale > 0 && peakLevel > rp && peakLevel - min_level < 8 * scale ) {
SetRefpos((((int)(peakLevel/scale)) + 1) * scale); SetRefpos((((int)(peakLevel/scale)) + 1) * scale);
} }
if (scale > 0 && min_level < rp - 9*scale && peakLevel - min_level < 8 * scale ) { if (scale > 0 && min_level < rp - 9*scale && peakLevel - min_level < 8 * scale ) {
int new_rp = (((int)((min_level + 9*scale)/scale)) - 1) * scale; int new_rp = (((int)((min_level + 9*scale)/scale)) - 1) * scale;
if (new_rp < rp) if (new_rp < rp)
SetRefpos(new_rp); SetRefpos(new_rp);
} }
#endif #endif
}
// redraw_marker(peak_marker, FALSE); // redraw_marker(peak_marker, FALSE);
palSetPad(GPIOC, GPIOC_LED); palSetPad(GPIOC, GPIOC_LED);
return true; return true;

@ -131,6 +131,8 @@ byte SI4432_Read_Byte( byte ADR )
void SI4432_Reset(void) void SI4432_Reset(void)
{ {
int count = 0; int count = 0;
SI4432_Read_Byte ( 0x03 ); // Clear pending interrupts
SI4432_Read_Byte ( 0x04 );
// always perform a system reset (don't send 0x87) // always perform a system reset (don't send 0x87)
SI4432_Write_Byte( 0x07, 0x80); SI4432_Write_Byte( 0x07, 0x80);
chThdSleepMilliseconds(50); chThdSleepMilliseconds(50);
@ -225,7 +227,7 @@ void SI4432_Set_Frequency ( long Freq ) {
int N = Freq / 10000000; int N = Freq / 10000000;
Carrier = ( 4 * ( Freq - N * 10000000 )) / 625; Carrier = ( 4 * ( Freq - N * 10000000 )) / 625;
int Freq_Band = ( N - 24 ) | ( hbsel << 5 ) | ( sbsel << 6 ); int Freq_Band = ( N - 24 ) | ( hbsel << 5 ) | ( sbsel << 6 );
#if 0 #if 1
SI4432_Write_Byte ( 0x75, Freq_Band ); SI4432_Write_Byte ( 0x75, Freq_Band );
SI4432_Write_Byte ( 0x76, (Carrier>>8) & 0xFF ); SI4432_Write_Byte ( 0x76, (Carrier>>8) & 0xFF );
SI4432_Write_Byte ( 0x77, Carrier & 0xFF ); SI4432_Write_Byte ( 0x77, Carrier & 0xFF );
@ -266,6 +268,20 @@ float SI4432_RSSI(uint32_t i, int s)
void SI4432_Sub_Init(void) void SI4432_Sub_Init(void)
{ {
SI4432_Reset(); SI4432_Reset();
//set VCO and PLL Only for SI4432 V2
SI4432_Write_Byte(0x72, 0x1F); //write 0x1F to the Frequency Deviation register
SI4432_Write_Byte(0x5A, 0x7F); //write 0x7F to the VCO Current Trimming register
SI4432_Write_Byte(0x58, 0x80); //write 0xD7 to the ChargepumpCurrentTrimmingOverride register
SI4432_Write_Byte(0x59, 0x40); //write 0x40 to the Divider Current Trimming register
//set the AGC
SI4432_Write_Byte(0x6A, 0x0B); //write 0x0B to the AGC Override 2 register
//set ADC reference voltage to 0.9V
SI4432_Write_Byte(0x68, 0x04); //write 0x04 to the Deltasigma ADC Tuning 2 register
SI4432_Write_Byte(0x1F, 0x03); //write 0x03 to the Clock Recovery Gearshift Override register
SI4432_Write_Byte(0x05, 0x0); SI4432_Write_Byte(0x05, 0x0);
SI4432_Write_Byte(0x06, 0x0); SI4432_Write_Byte(0x06, 0x0);
// Enable receiver chain // Enable receiver chain

@ -570,6 +570,7 @@ const menuitem_t menu_lowoutputmode[] = {
{ MT_FORM | MT_KEYPAD, KM_CENTER, "FREQ: %s", NULL}, { MT_FORM | MT_KEYPAD, KM_CENTER, "FREQ: %s", NULL},
{ MT_FORM | MT_KEYPAD, KM_LOWOUTLEVEL, "LEVEL: %s", NULL}, { MT_FORM | MT_KEYPAD, KM_LOWOUTLEVEL, "LEVEL: %s", NULL},
{ MT_FORM | MT_SUBMENU, 0, "MODULATION: %s", menu_modulation}, { MT_FORM | MT_SUBMENU, 0, "MODULATION: %s", menu_modulation},
{ MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", NULL},
{ MT_FORM | MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_FORM | MT_CANCEL, 0, S_LARROW" BACK", NULL },
{ MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel
}; };
@ -579,6 +580,7 @@ const menuitem_t menu_highoutputmode[] = {
{ MT_FORM | MT_KEYPAD, KM_CENTER, "FREQ: %s", NULL}, { MT_FORM | MT_KEYPAD, KM_CENTER, "FREQ: %s", NULL},
{ MT_FORM | MT_SUBMENU, 0, "LEVEL: %s", menu_drive_wide}, { MT_FORM | MT_SUBMENU, 0, "LEVEL: %s", menu_drive_wide},
{ MT_FORM | MT_SUBMENU, 0, "MODULATION: %s", menu_modulation}, { MT_FORM | MT_SUBMENU, 0, "MODULATION: %s", menu_modulation},
{ MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", NULL},
{ MT_FORM | MT_CANCEL, 0, S_LARROW" BACK",NULL }, { MT_FORM | MT_CANCEL, 0, S_LARROW" BACK",NULL },
{ MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel
}; };

Loading…
Cancel
Save

Powered by TurnKey Linux.