RXSweep mode added
Also scale for bandscope
This commit is contained in:
parent
76d7cd9aee
commit
6479c6050b
@ -54,7 +54,7 @@ void initBandscope()
|
||||
/*
|
||||
* Create and draw the sprite for the gain scale
|
||||
*/
|
||||
CreateGainScale ();
|
||||
CreateGridScale ();
|
||||
|
||||
// Make sure everything will be reset
|
||||
old_settingAttenuate = -1000;
|
||||
@ -457,10 +457,10 @@ static uint16_t chunkIndex;
|
||||
if ( setting.ShowStorage )
|
||||
DisplayPoint ( myStorage, tmp, STORAGE_COLOR );
|
||||
|
||||
// If in the last few points and gain trace is displayed show the gain scale
|
||||
if ( setting.ShowGain && (oldSweepStep > setting.BandscopePoints - 2 * CHAR_WIDTH) )
|
||||
// If in the first few points show the scale
|
||||
if ( ( tmp < 4 * CHAR_WIDTH ) && (tmp > 0) )
|
||||
{
|
||||
int16_t scaleX = setting.BandscopePoints - 2 * CHAR_WIDTH - tmp + 1; // relative to the img sprite
|
||||
int16_t scaleX = -tmp + 1; // relative to the img sprite
|
||||
img.setPivot( scaleX, 0);
|
||||
gainScaleSprite.pushRotated ( &img, 0, TFT_BLACK ); // Send the sprite to the target sprite, with transparent colour
|
||||
}
|
||||
|
508
RXsweep.ino
Normal file
508
RXsweep.ino
Normal file
@ -0,0 +1,508 @@
|
||||
|
||||
/*
|
||||
* RX sweep fixes the LO and sweeps the receiver from a start value to an stop value to
|
||||
* measure the RX FIR bandpass pass filter response. This eleimates any effect from the SAW
|
||||
* and low pass filters before the receiver.
|
||||
* It requires a fixed strength and frequency signal, and this is provided
|
||||
* by setting the reference output to say 15MHz. Avoid 30Mhz due to some stray clock signal
|
||||
* The input should be connected to the reference signal output with an external cable
|
||||
*/
|
||||
void initRX_Sweep()
|
||||
{
|
||||
// set up checkerboard sizes
|
||||
gridHeight = GRID_HEIGHT;
|
||||
gridWidth = DISPLAY_POINTS;
|
||||
yGrid = Y_GRID; // no of grid divisions
|
||||
yDelta = gridHeight / yGrid; // no of points/division
|
||||
xGrid = X_GRID;
|
||||
xOrigin = X_ORIGIN;
|
||||
yOrigin = Y_ORIGIN;
|
||||
displayPoints = DISPLAY_POINTS;
|
||||
xDelta = displayPoints / xGrid;
|
||||
|
||||
init_sweep();
|
||||
|
||||
tinySA_mode = RX_SWEEP;
|
||||
setting.Mode = tinySA_mode;
|
||||
|
||||
ResetRXsweepMenuStack(); // Put menu stack back to root level
|
||||
|
||||
}
|
||||
|
||||
|
||||
void doRX_Sweep()
|
||||
{
|
||||
static uint32_t autoSweepStep = 0;
|
||||
static uint32_t autoSweepFreq = 0;
|
||||
static uint32_t autoSweepFreqStep = 0;
|
||||
static uint32_t nextPointFreq = 0; // Frequency for the next display point. Used for substeps
|
||||
static unsigned long setFreqMicros;
|
||||
static unsigned long nowMicros;
|
||||
|
||||
static uint32_t sweepStep; // Step count
|
||||
static uint32_t sweepFreqStep;
|
||||
|
||||
static int16_t pointMinGain; // to record minimum gain for the current display point
|
||||
static int16_t pointMaxRSSI; // to record max RSSI of the samples in the current display point
|
||||
static uint32_t pointMaxFreq; // record frequency where maximum occurred
|
||||
|
||||
static int16_t lastMode; // Record last operating mode (sig gen, normal)
|
||||
|
||||
static uint16_t currentPointRSSI;
|
||||
static uint16_t peakRSSI;
|
||||
static uint16_t prevPointRSSI;
|
||||
static uint32_t peakFreq;
|
||||
static uint16_t peakIndex;
|
||||
static uint16_t pointsPastPeak;
|
||||
static uint16_t pointsPastDip;
|
||||
static uint16_t minRSSI; // Minimum level for the sweep
|
||||
static uint16_t lastMinRSSI; // Minimum level for the previous sweep
|
||||
|
||||
static bool jsonDocInitialised = false;
|
||||
static uint16_t chunkIndex;
|
||||
|
||||
/*
|
||||
* If paused and at the start of a sweep then do nothing
|
||||
*/
|
||||
if (!sweepStartDone && paused)
|
||||
return;
|
||||
|
||||
|
||||
if (( !sweepStartDone || initSweep || changedSetting ) )
|
||||
{
|
||||
if ( initSweep || changedSetting ) // Something has changed, or a first start, so need to work out some basic things
|
||||
{
|
||||
Serial.println("Init RXSweep or changedSetting");
|
||||
autoSweepFreqStep = ( stopFreq_RX - startFreq_RX ) / displayPoints;
|
||||
|
||||
vbw = autoSweepFreqStep / 1000.0; // Set the video resolution
|
||||
|
||||
/*
|
||||
* Use the RBW setting. If zero then it is meaningless, use smallest instead
|
||||
*/
|
||||
bandwidth = rcvr.SetRBW ( setting.Bandwidth10, &delaytime ); // Set it in the receiver Si4432. delaytime is returned
|
||||
|
||||
sweepPoints = displayPoints;
|
||||
|
||||
sweepFreqStep = ( stopFreq_RX - startFreq_RX ) / sweepPoints; // Step for each reading
|
||||
|
||||
att.SetAtten ( 0 ); // Set the internal attenuator
|
||||
|
||||
xmit.SetPowerReference ( setting.ReferenceOut ); // Set the GPIO reference output
|
||||
|
||||
maxGrid = setting.MaxGrid;
|
||||
minGrid = setting.MinGrid;
|
||||
|
||||
#ifdef USE_WIFI
|
||||
// Vary number of points to send in each chunk depending on delaytime
|
||||
// A chunk is sent at the end of each sweep regardless
|
||||
wiFiPoints = wiFiTargetTime / delaytime;
|
||||
if (wiFiPoints > MAX_WIFI_POINTS)
|
||||
wiFiPoints = MAX_WIFI_POINTS;
|
||||
if (wiFiPoints > displayPoints*OVERLAP)
|
||||
wiFiPoints = displayPoints*OVERLAP;
|
||||
// Serial.printf("No of wifiPoints set to %i\n", wiFiPoints);
|
||||
|
||||
pushIFSweepSettings();
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
|
||||
} // initSweep || changedSetting
|
||||
|
||||
autoSweepStep = 0; // Set the step counter to zero
|
||||
autoSweepFreq = startFreq_RX; // Set the start frequency.
|
||||
|
||||
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
||||
|
||||
|
||||
while (( micros() - setFreqMicros ) < delaytime ) // Make sure enough time has elasped since previous frequency write
|
||||
{
|
||||
}
|
||||
|
||||
//Serial.printf("set rcvr Freq get:%u, tempIF:%u\n", rcvr.GetFrequency(), tempIF);
|
||||
rcvr.SetFrequency ( autoSweepFreq ); // Set the RX Si4432 to the start of the sweep
|
||||
|
||||
setFreqMicros = micros(); // Store the time the frequency was changed
|
||||
xmit.SetFrequency ( sigFreq_RX + setting.IF_Freq ); // set the LO frequency to the IF plus reference
|
||||
|
||||
// Serial.printf("autoSweepFreq init: %u\n", autoSweepFreq);
|
||||
|
||||
|
||||
#ifdef USE_WIFI
|
||||
|
||||
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
||||
{
|
||||
jsonDocument.clear ();
|
||||
chunkIndex = 0;
|
||||
|
||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
||||
jsonDocument["mType"] = "chunkSweep";
|
||||
jsonDocument["StartIndex"] = 0;
|
||||
jsonDocument["sweepPoints"] = sweepPoints;
|
||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
||||
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||
jsonDocInitialised = true;
|
||||
}
|
||||
|
||||
else
|
||||
jsonDocInitialised = false;
|
||||
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
sweepStep = 0;
|
||||
startFreq = startFreq_RX; // Start freq for the RX
|
||||
stopFreq = stopFreq_RX; // Stop freq for the RX
|
||||
|
||||
pointMinGain = 100; // Reset min/max values
|
||||
pointMaxRSSI = 0;
|
||||
|
||||
DisplayInfo (); // Display axis, top and side bar text
|
||||
|
||||
peakLevel = 0; // Reset the peak values for the sweep
|
||||
peakFreq = 0.0;
|
||||
peakGain = 100; // Set to higher than gain can ever be
|
||||
|
||||
lastMinRSSI = minRSSI;
|
||||
minRSSI = 300; // Higher than it can be
|
||||
|
||||
|
||||
/*
|
||||
* Copy the values for the peaks (marker positions) to the old versions. No need to
|
||||
* reset the indicies or frequencies; just the "Level".
|
||||
*/
|
||||
|
||||
for ( int i = 0; i < MARKER_COUNT; i++ )
|
||||
{
|
||||
oldPeaks[i].Level = peaks[i].Level;
|
||||
oldPeaks[i].Index = peaks[i].Index;
|
||||
oldPeaks[i].Freq = peaks[i].Freq;
|
||||
peaks[i].Level = 0;
|
||||
}
|
||||
|
||||
pointsPastPeak = 0; // Avoid possible peak detection at start of sweep
|
||||
peakRSSI = 0;
|
||||
|
||||
sweepStartDone = true; // Make sure this initialize is only done once per sweep
|
||||
initSweep = false;
|
||||
changedSetting = false;
|
||||
|
||||
lastSweepStartMicros = sweepStartMicros; // Set last time we got here
|
||||
sweepStartMicros = micros(); // Current time
|
||||
sweepMicros = sweepStartMicros - lastSweepStartMicros; // Calculate sweep time (no rollover handling)
|
||||
|
||||
} // End of "if ( !sweepStartDone ) || initSweep || changedSetting )"
|
||||
|
||||
|
||||
/*
|
||||
* Here we do the actual sweep. Save the current step and frequencies for the next time
|
||||
* through, then wait the required amount of time based on the RBW before taking the
|
||||
* signal strength reading and changing the transmitter (LO) frequency.
|
||||
*/
|
||||
|
||||
uint16_t oldSweepStep = autoSweepStep;
|
||||
uint32_t oldSweepFreq = autoSweepFreq;
|
||||
|
||||
/*
|
||||
* Wait until time to take the next reading. If a long wait then check the touchscreen
|
||||
* and Websockets while we are waiting to improve response
|
||||
*/
|
||||
nowMicros = micros();
|
||||
|
||||
while (( nowMicros - setFreqMicros ) < delaytime )
|
||||
{
|
||||
|
||||
if ( ( nowMicros - setFreqMicros + delaytime > 200 ) &&
|
||||
( (nowMicros - lastWebsocketMicros > websocketInterval) || (numberOfWebsocketClients > 0) ) )
|
||||
{
|
||||
// Serial.print("W");
|
||||
webSocket.loop (); // Check websockets - includes Yield() to allow other events to run
|
||||
// Serial.println("w");
|
||||
lastWebsocketMicros = nowMicros;
|
||||
}
|
||||
if ( nowMicros - setFreqMicros > 100 ) // Wait some time to allow DMA sprite write to finish!
|
||||
UiProcessTouch (); // Check the touch screen
|
||||
// Serial.println("w");
|
||||
nowMicros = micros();
|
||||
}
|
||||
|
||||
int rxRSSI = rcvr.GetRSSI (); // Read the RSSI from the RX SI4432
|
||||
|
||||
/*
|
||||
* Note that there are two different versions of the print statement to send the
|
||||
* RSSI readings to the serial output. You can change which one is commented out.
|
||||
*
|
||||
* The first one produces a tab separated list of just the frequency and RSSI
|
||||
* reading. That format can be easily read inte something like Excel.
|
||||
*
|
||||
* The second one produces a listing more fit for human consumption!
|
||||
*/
|
||||
|
||||
if ( showRSSI ) // Displaying RSSI?
|
||||
{
|
||||
// Serial.printf ( "%s\t%03d\n",
|
||||
// FormatFrequency ( autoSweepFreq) , rxRSSI ); // Send it to the serial output
|
||||
Serial.printf ( "Freq: %s - RSSI: %03d\n",
|
||||
FormatFrequency ( autoSweepFreq) , rxRSSI ); // Send it to the serial output
|
||||
}
|
||||
|
||||
if ( (numberOfWebsocketClients > 0) || (setting.ShowGain) )
|
||||
gainReading = GetPreampGain ( &AGC_On, &AGC_Reg ); // Record the preamp/lna gains
|
||||
|
||||
autoSweepFreq += sweepFreqStep; // Increment the frequency
|
||||
sweepStep++; // and increment the step count
|
||||
|
||||
// Serial.printf("autoSweepFreq: %u Step: %u\n", autoSweepFreq, sweepStep);
|
||||
|
||||
|
||||
/*
|
||||
* Change the transmitter frequency for the next reading and record the time for
|
||||
* the RBW required settling delay.
|
||||
*
|
||||
* Not we also set the lo here to simulate the effect on the filters in a real sweep
|
||||
*/
|
||||
|
||||
setFreqMicros = micros(); // Store the time the LO frequency was changed
|
||||
xmit.SetFrequency ( sigFreq_RX + setting.IF_Freq ); // set the LO frequency to the IF plus reference
|
||||
rcvr.SetFrequency ( autoSweepFreq ); // Set the RX Si4432 to the IF frequency
|
||||
|
||||
// Serial.printf("Step: %i Required: %i Actual %i\n", sweepStep, autoSweepFreq, rcvr.GetFrequency());
|
||||
|
||||
#ifdef USE_WIFI
|
||||
|
||||
if ( numberOfWebsocketClients > 0 )
|
||||
{
|
||||
if ( jsonDocInitialised )
|
||||
{
|
||||
JsonObject dataPoint = Points.createNestedObject (); // Add an object to the Json array to be pushed to the client
|
||||
dataPoint["x"] = oldSweepFreq/1000000.0; // Set the x(frequency) value
|
||||
dataPoint["y"] = rxRSSI; // Set the y (RSSI) value
|
||||
// Serial.printf ( "Add point chunkIndex %u, sweepStep %u of %u \n", chunkIndex, sweepStep, sweepPoints);
|
||||
chunkIndex++; // increment no of data points in current WiFi chunk
|
||||
|
||||
if ( chunkIndex >= wiFiPoints ) // Send the chunk of data and start new jSon document
|
||||
{
|
||||
String wsBuffer;
|
||||
|
||||
if ( wsBuffer )
|
||||
{
|
||||
// Serial.print("D");
|
||||
serializeJson ( jsonDocument, wsBuffer );
|
||||
// Serial.printf("J%u", wsBuffer.length() );
|
||||
unsigned long s = millis();
|
||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||
if (millis() - s > 1000)
|
||||
{
|
||||
Serial.println("webSocketTimeout");
|
||||
Serial.println(wsBuffer);
|
||||
numberOfWebsocketClients = 0;
|
||||
}
|
||||
// Serial.print("j");
|
||||
}
|
||||
|
||||
else
|
||||
Serial.println("No buffer :(");
|
||||
}
|
||||
}
|
||||
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
||||
{
|
||||
chunkIndex = 0;
|
||||
jsonDocument.clear();
|
||||
jsonDocument["mType"] = "chunkSweep";
|
||||
jsonDocument["StartIndex"] = sweepStep;
|
||||
jsonDocument["sweepPoints"] = sweepPoints;
|
||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
||||
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
|
||||
jsonDocInitialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
if ( rxRSSI > pointMaxRSSI ) // RSSI > maximum value for this point so far?
|
||||
{
|
||||
myActual[autoSweepStep] = rxRSSI; // Yes, save it
|
||||
pointMaxRSSI = rxRSSI; // Added by G3ZQC - Remember new maximim
|
||||
pointMaxFreq = oldSweepFreq;
|
||||
}
|
||||
|
||||
if ( gainReading < pointMinGain ) // Gain < minimum gain for this point so far?
|
||||
{
|
||||
myGain[autoSweepStep] = gainReading; // Yes, save it
|
||||
pointMinGain = gainReading; // Added by G3ZQC - Remember new minimum
|
||||
}
|
||||
|
||||
if (rxRSSI < minRSSI) // Detect minimum for sweep
|
||||
minRSSI = rxRSSI;
|
||||
|
||||
|
||||
/*
|
||||
* Have we enough readings for this display point? If yes, so do any averaging etc, reset
|
||||
* the values so peak in the frequency step is recorded and update the display.
|
||||
*/
|
||||
|
||||
if ( autoSweepFreq >= nextPointFreq )
|
||||
{
|
||||
nextPointFreq = nextPointFreq + autoSweepFreqStep; // Next display point frequency
|
||||
autoSweepStep++; // Increment the index
|
||||
|
||||
pointMinGain = 100; // Reset min/max values
|
||||
pointMaxRSSI = 0;
|
||||
|
||||
DrawCheckerBoard ( oldSweepStep ); // Draw the grid for the point in the sweep we have just read
|
||||
|
||||
DisplayPoint ( myActual, oldSweepStep, DB_COLOR );
|
||||
|
||||
if ( setting.ShowGain )
|
||||
displayGainPoint ( myGain, oldSweepStep, GAIN_COLOR );
|
||||
|
||||
/*
|
||||
* Record the peak values
|
||||
*/
|
||||
|
||||
if ( oldSweepStep > 0)
|
||||
{
|
||||
if ( peakLevel < myActual[oldSweepStep] )
|
||||
{
|
||||
peakIndex = oldSweepStep;
|
||||
peakLevel = myActual[oldSweepStep];
|
||||
peakFreq = oldSweepFreq;
|
||||
|
||||
// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
|
||||
// displayPeakData ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save values used by peak detection. Need to save the previous value as we only
|
||||
* know we have a peak once past it!
|
||||
*/
|
||||
|
||||
prevPointRSSI = currentPointRSSI;
|
||||
currentPointRSSI = myActual[oldSweepStep];
|
||||
|
||||
|
||||
/*
|
||||
* Peak point detection. Four peaks, used to position the markers
|
||||
*/
|
||||
if ( currentPointRSSI >= prevPointRSSI ) // Level or ascending
|
||||
{
|
||||
pointsPastDip ++;
|
||||
if ( pointsPastDip == PAST_PEAK_LIMIT )
|
||||
{
|
||||
pointsPastPeak = 0;
|
||||
}
|
||||
|
||||
if ( currentPointRSSI > peakRSSI )
|
||||
{
|
||||
peakRSSI = currentPointRSSI; // Store values
|
||||
peakFreq = oldSweepFreq;
|
||||
peakIndex = oldSweepStep;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pointsPastPeak ++; // only a true peak if value decreased for a number of consecutive points
|
||||
|
||||
if ( pointsPastPeak == PAST_PEAK_LIMIT ) // We have a peak
|
||||
{
|
||||
pointsPastDip = 0;
|
||||
|
||||
/*
|
||||
* Is this peak bigger than previous ones? Only check if bigger than smallest peak so far
|
||||
*/
|
||||
|
||||
if ( peakRSSI > peaks[MARKER_COUNT-1].Level )
|
||||
{
|
||||
for ( uint16_t p = 0; p < MARKER_COUNT; p++ )
|
||||
{
|
||||
if ( peakRSSI > peaks[p].Level )
|
||||
{
|
||||
for ( uint16_t n = 3; n > p; n-- ) // Shuffle lower level peaks down
|
||||
memcpy ( &peaks[n], &peaks[n-1], sizeof ( peak_t ));
|
||||
|
||||
peaks[p].Level = peakRSSI; // Save the peak values
|
||||
peaks[p].Freq = peakFreq;
|
||||
peaks[p].Index = peakIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peakRSSI = 0; // Reset peak values ready for next peak
|
||||
} // We have a peak
|
||||
} // Descending
|
||||
} // if (( autoSweepFreq > 1000000 ) && (oldSweepStep > 0))
|
||||
|
||||
|
||||
/*
|
||||
* Draw the markers if main sweep is displayed. The markers know if they are enabled or not
|
||||
* Only paint if sweep step is in range where there will be a marker
|
||||
*/
|
||||
|
||||
for ( int p = 0; p < MARKER_COUNT; p++ )
|
||||
{
|
||||
if (( abs ( oldSweepStep - oldPeaks[p].Index )
|
||||
<= MARKER_SPRITE_HEIGHT / 2 ) && ( oldPeaks[p].Level > (lastMinRSSI + MARKER_NOISE_LIMIT) ))
|
||||
|
||||
marker[p].Paint ( &img, oldPeaks[p].Index - oldSweepStep,
|
||||
rssiToImgY ( oldPeaks[p].Level ) );
|
||||
}
|
||||
|
||||
// If in the last few points and gain trace is displayed show the gain scale
|
||||
if ( setting.ShowGain && (oldSweepStep > displayPoints - 2 * CHAR_WIDTH) )
|
||||
{
|
||||
int16_t scaleX = displayPoints - 2 * CHAR_WIDTH - oldSweepStep + 1; // relative to the img sprite
|
||||
img.setPivot( scaleX, 0);
|
||||
gainScaleSprite.pushRotated ( &img, 0, TFT_BLACK ); // Send the sprite to the target sprite, with transparent colour
|
||||
}
|
||||
|
||||
if ( oldSweepStep > 0 ) // Only push if not first point (two pixel wide img)
|
||||
img.pushSprite ( xOrigin+oldSweepStep-1, yOrigin );
|
||||
|
||||
myFreq[oldSweepStep] = oldSweepFreq; // Store the frequency for XML file creation
|
||||
|
||||
} // End of "if ( autoSweepFreq >= nextPointFreq )"
|
||||
|
||||
if ( sweepStep >= sweepPoints ) // If we have got to the end of the sweep
|
||||
{
|
||||
// autoSweepStep = 0;
|
||||
sweepStartDone = false;
|
||||
|
||||
if ( sweepCount < 2 )
|
||||
sweepCount++; // Used to disable wifi at start
|
||||
|
||||
oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function
|
||||
|
||||
if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point
|
||||
{
|
||||
myActual[displayPoints-1] = rxRSSI; // Yes, save it
|
||||
myGain[displayPoints-1] = gainReading;
|
||||
myFreq[displayPoints-1] = oldSweepFreq;
|
||||
}
|
||||
|
||||
if ( showRSSI == 1 ) // Only show it once?
|
||||
showRSSI = 0; // Then turn it off
|
||||
|
||||
#ifdef USE_WIFI
|
||||
|
||||
if (( numberOfWebsocketClients > 0) && jsonDocInitialised && (chunkIndex > 0) )
|
||||
{
|
||||
String wsBuffer;
|
||||
|
||||
if (wsBuffer)
|
||||
{
|
||||
serializeJson ( jsonDocument, wsBuffer );
|
||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||
}
|
||||
|
||||
else
|
||||
Serial.println ( "No buffer :(");
|
||||
}
|
||||
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
} // End of "if ( sweepStep >= sweepPoints )"
|
||||
|
||||
|
||||
}
|
33
SweepLo.ino
33
SweepLo.ino
@ -70,6 +70,7 @@ static bool resetAverage; // Flag to indicate a setting has changed and avera
|
||||
|
||||
static bool jsonDocInitialised = false;
|
||||
static uint16_t chunkIndex;
|
||||
static uint32_t offsetIF; // IF frequency offset by half the bandwidth to position in the centre of the filter
|
||||
|
||||
|
||||
|
||||
@ -111,6 +112,12 @@ static uint16_t chunkIndex;
|
||||
old_ownrbw = ownrbw;
|
||||
}
|
||||
|
||||
/*
|
||||
* The FIR filters in the SI4432 are centred above the nominal IF frequency as that is where the signals are meant to be.
|
||||
* To make sure we are not on the edge of the filters offset the IF frequency down by half the bandwidth
|
||||
*/
|
||||
offsetIF = setting.IF_Freq - setting.Bandwidth10 * 50; // bW10 is in kHz * 10, so * 100-> kHz, halved
|
||||
|
||||
/*
|
||||
* Need multiple readings for each pixel in the display to avoid missing signals.
|
||||
* Work out how many points needed for the whole sweep:
|
||||
@ -186,11 +193,13 @@ static uint16_t chunkIndex;
|
||||
uint32_t IF_Shift = ownrbw * 1000; // bandwidth in Hz
|
||||
if (IF_Shift > MAX_IF_SHIFT)
|
||||
IF_Shift = MAX_IF_SHIFT;
|
||||
tempIF = setting.IF_Freq - IF_Shift;
|
||||
tempIF = offsetIF - IF_Shift;
|
||||
} else {
|
||||
tempIF = setting.IF_Freq;
|
||||
tempIF = offsetIF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
spurToggle = !spurToggle;
|
||||
//Serial.printf("tempIF %u, spurOffset=%i, spur:%i, Toggle:%i\n", tempIF, tempIF - setting.IF_Freq, setting.Spur, spurToggle);
|
||||
|
||||
@ -514,15 +523,15 @@ static uint16_t chunkIndex;
|
||||
|
||||
if (( autoSweepFreq > MARKER_MIN_FREQUENCY ) && (oldSweepStep > 0))
|
||||
{
|
||||
// if ( maxRSSI <= myActual[oldSweepStep] )
|
||||
// {
|
||||
// maxIndex = oldSweepStep;
|
||||
// maxRSSI = myActual[oldSweepStep];
|
||||
// maxFreq = oldSweepFreq;
|
||||
//
|
||||
//// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
|
||||
//// displayPeakData ();
|
||||
// }
|
||||
if ( maxRSSI <= myActual[oldSweepStep] )
|
||||
{
|
||||
maxIndex = oldSweepStep;
|
||||
maxRSSI = myActual[oldSweepStep];
|
||||
maxFreq = oldSweepFreq;
|
||||
|
||||
// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
|
||||
// displayPeakData ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -629,7 +638,7 @@ static uint16_t chunkIndex;
|
||||
|
||||
// Serial.printf("MaxRSSI = %i, freq = %i\n", maxRSSI, maxFreq);
|
||||
|
||||
oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function
|
||||
oldPeakLevel = maxRSSI; //Save value of peak level for use by the "SetPowerLevel" function
|
||||
|
||||
if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point
|
||||
{
|
||||
|
223
cmd.cpp
223
cmd.cpp
@ -94,6 +94,10 @@ extern uint32_t startFreq_IF; // Last value of the IF sweep start frequency
|
||||
extern uint32_t stopFreq_IF; // Last value of the IF sweep end frequency
|
||||
extern uint32_t sigFreq_IF; // Last value of the IF sweep end frequency
|
||||
|
||||
extern uint32_t startFreq_RX; // Last value of the IF sweep start frequency
|
||||
extern uint32_t stopFreq_RX; // Last value of the IF sweep end frequency
|
||||
extern uint32_t sigFreq_RX; // Last value of the IF sweep end frequency
|
||||
|
||||
extern uint8_t showRSSI; // When true, RSSI readings are displayed
|
||||
extern int initSweep; // Set by the "RSSI" command to restart the sweep
|
||||
extern bool paused;
|
||||
@ -116,6 +120,9 @@ extern void initSweepLow ();
|
||||
extern void initSigLow ();
|
||||
extern void initIF_Sweep ();
|
||||
extern void setMode (uint16_t newMode);
|
||||
extern uint8_t dBmToRSSI ( double dBm );
|
||||
|
||||
|
||||
/*
|
||||
* The "msgTable" provides a way of translating the ASCII message to the internal
|
||||
* number. Needs to be re-ordered based on expected usage.
|
||||
@ -162,17 +169,19 @@ extern void setMode (uint16_t newMode);
|
||||
{ "SPUR", MSG_SPUR }, // Set Spur reduction on/off
|
||||
{ "WIFITIME", MSG_WIFI_UPDATE }, // Set WiFi Update target time
|
||||
{ "WIFIPTS", MSG_WIFI_POINTS }, // Set WiFi points
|
||||
{ "SKTINT", MSG_WEBSKT_INTERVAL }, // Set WebSocket interval
|
||||
{ "SKTINT", MSG_WEBSKT_INTERVAL }, // Set WebSocket interval
|
||||
{ "SGRXDRIVE", MSG_SG_RX_DRIVE }, // Set Signal Generator RX Drive level
|
||||
{ "SGLODRIVE", MSG_SG_LO_DRIVE }, // Set Signal Generator LO Drive level
|
||||
{ "TGIFDRIVE", MSG_TG_IF_DRIVE }, // Set Track Generator IF Drive level
|
||||
{ "TGLODRIVE", MSG_TG_LO_DRIVE }, // Set Track Generator LO Drive level
|
||||
{ "IFSIGNAL", MSG_IFSIGNAL }, // IF sweep signal frequency
|
||||
{ "TGOFFSET", MSG_TGOFFSET }, // Offset TG IF from SA IF to reduce pass through
|
||||
{ "CTEST", MSG_COLOURTEST }, // Work out how colours work!
|
||||
{ "CTEST", MSG_COLOURTEST}, // Work out how colours work!
|
||||
{ "OFFDEL", MSG_OFFDELAY }, // Offset tuning delay
|
||||
{ "WFMIN", MSG_WFMIN }, // Min level for waterfall colours
|
||||
{ "WFMIN", MSG_WFMIN }, // Min level for waterfall colours
|
||||
{ "WFGAIN", MSG_WFGAIN }, // Gain for waterfall colours
|
||||
{ "RXSWEEP", MSG_RX_SWEEP }, // Set RX Sweep Mode
|
||||
{ "RXSIGNAL", MSG_RXSIGNAL }, // IF sweep signal frequency
|
||||
{ "", MSG_NONE } // Unrecognized command
|
||||
};
|
||||
|
||||
@ -220,6 +229,7 @@ void ShowMenu ()
|
||||
Serial.println ( " SALO..........Set to analyse mode low frequency range" );
|
||||
Serial.println ( " SGLO..........Set to signal generator mode low frequency range" );
|
||||
Serial.println ( " IFSWEEP.......Set to IF Sweep mode to analyse the TinySA SAW filters" );
|
||||
Serial.println ( " RXSWEEP.......Set to RX Sweep mode to analyse the TinySA FIR filters" );
|
||||
Serial.println ( " BANDSCOPE.....Set to BANDSCOPE mode" );
|
||||
|
||||
Serial.println ( " TRACES........Turn display traces on or off ['GAIN' or 'dB']" );
|
||||
@ -1551,6 +1561,10 @@ uint8_t reg69; // Ditto
|
||||
setMode(IF_SWEEP);
|
||||
return true;
|
||||
|
||||
case MSG_RX_SWEEP:
|
||||
setMode(RX_SWEEP);
|
||||
return true;
|
||||
|
||||
case MSG_TGOFFSET:
|
||||
if ( dataLen != 0 ) // Frequency specified?
|
||||
{
|
||||
@ -1572,7 +1586,7 @@ uint8_t reg69; // Ditto
|
||||
freq1 = ParseFrequency ( dataBuff ); // Yes, get new frequency
|
||||
SetIFsweepSigFreq (freq1);
|
||||
}
|
||||
Serial.printf ( "If Signal frequency: %s\n", FormatFrequency ( GetIFsweepSigFreq() ));
|
||||
Serial.printf ( "IF Sweep Signal frequency: %s\n", FormatFrequency ( GetIFsweepSigFreq() ));
|
||||
return true;
|
||||
|
||||
|
||||
@ -1622,6 +1636,7 @@ uint8_t reg69; // Ditto
|
||||
|
||||
/*
|
||||
* The "WFMIN" command sets the min RSSI level for waterfall colouring.
|
||||
* The value is entered in dBm so the value can be judged from the waterfall
|
||||
*
|
||||
* If no number is entered, we report the current setting.
|
||||
*/
|
||||
@ -1653,6 +1668,17 @@ uint8_t reg69; // Ditto
|
||||
Serial.printf ( "Waterfall colour gain: %4.2f\n", setting.WaterfallGain );
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Set signal frequency fro RX Sweep
|
||||
*/
|
||||
case MSG_RXSIGNAL:
|
||||
if ( dataLen != 0 ) // Frequency specified?
|
||||
{
|
||||
freq1 = ParseFrequency ( dataBuff ); // Yes, get new frequency
|
||||
SetRXsweepSigFreq (freq1);
|
||||
}
|
||||
Serial.printf ( "RX Sweep Signal frequency: %s\n", FormatFrequency ( GetRXsweepSigFreq() ));
|
||||
return true;
|
||||
|
||||
|
||||
default:
|
||||
@ -2277,6 +2303,7 @@ int16_t tempBw;
|
||||
if ( setting.Bandwidth10 != oldRBW )
|
||||
{
|
||||
changedSetting = true;
|
||||
SetRXsweepSpan (setting.Bandwidth10 * 1000); // 10 * bandwidth
|
||||
WriteSettings ();
|
||||
}
|
||||
}
|
||||
@ -2720,6 +2747,189 @@ uint32_t GetIFsweepSigFreq ( void )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Specific span setting for RX Sweep mode
|
||||
*
|
||||
*
|
||||
* "SetSweepSpan" will maintain the previous center frequency and attempt to simply
|
||||
* change the range of the scan. If the new limits cause the start frequency to go
|
||||
* or the stop frequency to exceed "STOP_MAX", the range will be adjusted to maintain
|
||||
* an equal range on both sides of the center frequency.
|
||||
*/
|
||||
|
||||
void SetRXsweepSpan ( uint32_t spanRange )
|
||||
{
|
||||
uint32_t startFreq; // These are used in computing the
|
||||
uint32_t stopFreq; // Scan limits
|
||||
uint32_t centerFreq; // Current center frequency
|
||||
uint32_t halfSpan; // Half of the frequency span
|
||||
|
||||
uint32_t lastStart; // Old ssweep start frequency
|
||||
uint32_t lastStop; // and old stop frequency
|
||||
|
||||
// Serial.print ( "Requested span = " ); Serial.println ( FormatFrequency ( spanRange ));
|
||||
|
||||
lastStart = startFreq_RX; // Save the current start frequency
|
||||
lastStop = stopFreq_RX; // and the current stop frequency
|
||||
|
||||
halfSpan = spanRange / 2; // Half the requested span
|
||||
centerFreq = setting.IF_Freq; // Always the IF Freq for this mode
|
||||
|
||||
startFreq = centerFreq - halfSpan; // New computed start frequency
|
||||
stopFreq = centerFreq + halfSpan; // New computed stop frequency
|
||||
|
||||
|
||||
/*
|
||||
* Now we have to range check the computed start and stop frequencies and if either
|
||||
* of those is out of bounds, we will adjust the span accordingly. We'll maintain
|
||||
* the previous center frequency though.
|
||||
*/
|
||||
|
||||
if ( stopFreq > RX_STOP_MAX ) // Range check the stop frequency
|
||||
{
|
||||
stopFreq = RX_STOP_MAX; // Set the stop frequency at the upper limit
|
||||
halfSpan = stopFreq - centerFreq; // Re-compute half span
|
||||
startFreq = centerFreq - halfSpan; // and recompute start frequency
|
||||
}
|
||||
|
||||
if ( startFreq < RX_START_MIN ) // Range check the start frequency
|
||||
{
|
||||
startFreq = RX_START_MIN; // Set start at the limit
|
||||
halfSpan = centerFreq - startFreq; // Re-compute half span
|
||||
stopFreq = centerFreq + halfSpan; // and re-compute stop frequency
|
||||
}
|
||||
|
||||
startFreq = centerFreq - halfSpan; // Re-compute start and
|
||||
stopFreq = centerFreq + halfSpan; // stop frequencies
|
||||
|
||||
// Serial.print ( "Computed start = " ); Serial.println ( FormatFrequency ( startFreq ));
|
||||
// Serial.print ( "Computed stop = " ); Serial.println ( FormatFrequency ( stopFreq ));
|
||||
// Serial.print ( "Half span = " ); Serial.println ( FormatFrequency ( halfSpan ));
|
||||
|
||||
startFreq_RX = startFreq; // Set new start frequency
|
||||
stopFreq_RX = stopFreq; // Set new stop frequency
|
||||
|
||||
if (( startFreq_RX != lastStart )
|
||||
|| ( stopFreq_RX != lastStop )) // Did it change
|
||||
{
|
||||
changedSetting = true; // Yes it did
|
||||
RedrawHisto (); // Redraw labels and restart sweep with new settings
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetRXsweepSpan ()
|
||||
{
|
||||
return stopFreq_RX - startFreq_RX;
|
||||
}
|
||||
|
||||
|
||||
void SetRXsweepStart ( uint32_t startFreq )
|
||||
{
|
||||
uint32_t lastStart; // Old sweep start frequency
|
||||
uint32_t lastStop; // and old stop frequency
|
||||
|
||||
// Serial.print ( "Requested start = " ); Serial.println ( FormatFrequency ( startFreq ));
|
||||
|
||||
lastStart = startFreq_RX; // Save the current start frequency
|
||||
lastStop = stopFreq_RX; // and the current stop frequency
|
||||
|
||||
if ( startFreq < RX_START_MIN ) // Range check
|
||||
startFreq = RX_START_MIN;
|
||||
|
||||
if ( startFreq > RX_STOP_MAX ) // Range check
|
||||
startFreq = RX_STOP_MAX;
|
||||
|
||||
if ( startFreq > stopFreq_RX ) // Start can't be more than current stop
|
||||
stopFreq_RX = RX_STOP_MAX; // So set stop at maximum
|
||||
|
||||
startFreq_RX = startFreq; // Set new start frequency
|
||||
|
||||
if (( startFreq_RX != lastStart )
|
||||
|| ( stopFreq_RX != lastStop )) // Did it change?
|
||||
{
|
||||
changedSetting = true; // Yes it did
|
||||
RedrawHisto (); // Redraw labels and restart sweep with new settings
|
||||
// WriteSettings (); // and save the setting structure
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetRXsweepStart ( void )
|
||||
{
|
||||
return startFreq_RX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SetRXsweepStop ( uint32_t stopFreq )
|
||||
{
|
||||
uint32_t lastStart; // Old sweep start frequency
|
||||
uint32_t lastStop; // and old stop frequency
|
||||
|
||||
// Serial.print ( "Requested stop = " ); Serial.println ( FormatFrequency ( stopFreq ));
|
||||
|
||||
lastStart = startFreq_RX; // Save the current start frequency
|
||||
lastStop = stopFreq_RX; // and the current stop frequency
|
||||
|
||||
if ( stopFreq < RX_START_MIN ) // Range check
|
||||
stopFreq = RX_START_MIN;
|
||||
|
||||
if ( stopFreq > RX_STOP_MAX ) // Range check
|
||||
stopFreq = RX_STOP_MAX;
|
||||
|
||||
if ( stopFreq < startFreq_RX ) // Stop can't be less than current start
|
||||
startFreq_RX = RX_START_MIN; // so set start to minimum frequency
|
||||
|
||||
stopFreq_RX = stopFreq; // Set new stop frequency
|
||||
|
||||
if (( startFreq_RX != lastStart )
|
||||
|| ( stopFreq_RX != lastStop )) // Did it change?
|
||||
{
|
||||
changedSetting = true; // Yes it did
|
||||
RedrawHisto (); // Redraw labels and restart sweep with new settings
|
||||
// WriteSettings (); // and save the setting structure
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetRXsweepStop ( void )
|
||||
{
|
||||
return stopFreq_RX;
|
||||
}
|
||||
|
||||
|
||||
void SetRXsweepSigFreq ( uint32_t sigFreq )
|
||||
{
|
||||
uint32_t lastSigFreq;
|
||||
|
||||
// Serial.print ( "Requested RX sweep signal = " ); Serial.println ( FormatFrequency ( sigFreq_RX ));
|
||||
|
||||
lastSigFreq = sigFreq_RX;
|
||||
|
||||
// check in a sensible range
|
||||
if ( ( sigFreq < 1000000 ) || (sigFreq > 100000000 ) )
|
||||
Serial.println(" Out of range - must be between 1,000,000 and 100,000,000Hz");
|
||||
else
|
||||
{
|
||||
sigFreq_RX = sigFreq;
|
||||
if ( sigFreq_RX != lastSigFreq )
|
||||
changedSetting = true;
|
||||
}
|
||||
|
||||
RedrawHisto (); // Redraw labels and restart sweep with new settings
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetRXsweepSigFreq ( void )
|
||||
{
|
||||
return sigFreq_RX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Specific start/stop frequency setting for Bandscope mode
|
||||
*/
|
||||
@ -3024,8 +3234,9 @@ void SetFreq ( int vfo, uint32_t freq )
|
||||
|
||||
void SetWFMin (int16_t level)
|
||||
{
|
||||
if ( (level >=0) && (level < 255) )
|
||||
setting.WaterfallMin = level;
|
||||
if ( (level >=-130) && (level < -50) )
|
||||
setting.WaterfallMin = dBmToRSSI( (double)level );
|
||||
Serial.printf("Watterfall min set to %i \n", setting.WaterfallMin );
|
||||
WriteSettings();
|
||||
}
|
||||
|
||||
|
21
cmd.h
21
cmd.h
@ -75,6 +75,9 @@
|
||||
#define MSG_OFFDELAY 46 // Adjust offset tuning delay time before taking reading
|
||||
#define MSG_WFMIN 47 // set the min level for the waterfall colours
|
||||
#define MSG_WFGAIN 48 // set the gain for waterfall colouring
|
||||
#define MSG_RX_SWEEP 49 // Set the RX Sweep Mode
|
||||
#define MSG_RXSIGNAL 50 // Set frequency of injected signal for IF Sweep
|
||||
|
||||
#define MSG_COLOURTEST 99 // test of waterfall colours - remove this when done!
|
||||
|
||||
|
||||
@ -168,9 +171,6 @@ uint32_t GetSweepStart ( void );
|
||||
void SetSweepStop ( uint32_t freq ); // Added in Version 2.3
|
||||
uint32_t GetSweepStop ( void );
|
||||
|
||||
void SetIFsweepStart ( uint32_t freq ); // Added in Version 3.0c
|
||||
uint32_t GetIFsweepStart ( void );
|
||||
|
||||
void SetBandscopeStart ( uint32_t freq ); // Added in Version 3.0f
|
||||
uint32_t GetBandscopeStart ( void );
|
||||
|
||||
@ -181,12 +181,27 @@ void SetBandscopeRBW ( int v ); // Sets the resolution bandwidth
|
||||
|
||||
void SetBandscopeLevel ( int ref ); // Sets the decibel level for the top line of the graph
|
||||
|
||||
void SetIFsweepStart ( uint32_t freq ); // Added in Version 3.0c
|
||||
uint32_t GetIFsweepStart ( void );
|
||||
|
||||
void SetIFsweepStop ( uint32_t freq ); // Added in Version 3.0c
|
||||
uint32_t GetIFsweepStop ( void );
|
||||
|
||||
void SetIFsweepSigFreq ( uint32_t freq ); // Added in Version 3.0c
|
||||
uint32_t GetIFsweepSigFreq ( void );
|
||||
|
||||
void SetRXsweepStart ( uint32_t freq );
|
||||
uint32_t GetRXsweepStart ( void );
|
||||
|
||||
void SetRXsweepStop ( uint32_t freq );
|
||||
uint32_t GetRXsweepStop ( void );
|
||||
|
||||
void SetRXsweepSpan ( uint32_t freq );
|
||||
uint32_t GetRXsweepSpan ( void );
|
||||
|
||||
void SetRXsweepSigFreq ( uint32_t freq );
|
||||
uint32_t GetRXsweepSigFreq ( void );
|
||||
|
||||
void SetSweepCenter ( uint32_t freq, uint8_t span );
|
||||
uint32_t GetSweepCenter ( void );
|
||||
|
||||
|
12
my_SA.h
12
my_SA.h
@ -92,6 +92,18 @@
|
||||
#define IF_STOP_MAX 500000000 // 500MHz
|
||||
#define IF_START_MIN 400000000 // 400MHz
|
||||
|
||||
|
||||
/*
|
||||
* Some definitions for RX-Sweep to test the internal FIR filters
|
||||
*/
|
||||
|
||||
#define RX_SWEEP_START 432000000
|
||||
#define RX_SWEEP_STOP 436000000
|
||||
|
||||
// Limits for keypad entry of IF sweep frequency start/stop
|
||||
#define RX_STOP_MAX 440000000 // 500MHz
|
||||
#define RX_START_MIN 430000000 // 400MHz
|
||||
|
||||
|
||||
/*
|
||||
* Spur reduction shifts the IF down from its normal setting every other scan
|
||||
|
49
si4432.cpp
49
si4432.cpp
@ -25,29 +25,35 @@
|
||||
bandpassFilter_t Si4432::_bandpassFilters[]
|
||||
{
|
||||
// bw*10, settle, dwn3, ndec, filset
|
||||
{ 26, 7500, 0, 5, 1 }, // 0 "AUTO" selection possibility
|
||||
{ 28, 7300, 0, 5, 2 }, // 1 "AUTO" selection possibility
|
||||
{ 31, 7000, 0, 5, 3 }, // 2 If user selects 3KHz -> 3.1KHz actual
|
||||
{ 32, 6800, 0, 5, 4 }, // 3 "AUTO" selection possibility
|
||||
{ 37, 6500, 0, 5, 5 }, // 4 "AUTO" selection possibility
|
||||
{ 42, 6000, 0, 5, 6 }, // 5 "AUTO" selection possibility
|
||||
{ 26, 6800, 0, 5, 1 }, // 0 "AUTO" selection possibility
|
||||
{ 28, 6600, 0, 5, 2 }, // 1 "AUTO" selection possibility
|
||||
{ 31, 6600, 0, 5, 3 }, // 2 If user selects 3KHz -> 3.1KHz actual
|
||||
{ 32, 6600, 0, 5, 4 }, // 3 "AUTO" selection possibility
|
||||
{ 37, 6600, 0, 5, 5 }, // 4 "AUTO" selection possibility
|
||||
{ 42, 6600, 0, 5, 6 }, // 5 "AUTO" selection possibility
|
||||
{ 45, 5500, 0, 5, 7 }, // 6 "AUTO" selection possibility
|
||||
{ 49, 5000, 0, 4, 1 }, // 7 "AUTO" selection possibility
|
||||
{ 54, 4200, 0, 4, 2 }, // 8 "AUTO" selection possibility
|
||||
{ 59, 3700, 0, 4, 3 }, // 9 "AUTO" selection possibility
|
||||
{ 72, 3200, 0, 4, 5 }, // 10 "AUTO" selection possibility
|
||||
{ 72, 3300, 0, 4, 5 }, // 10 "AUTO" selection possibility
|
||||
{ 106, 2500, 0, 3, 2 }, // 11 If user selects 10KHz -> 10.6KHz actual
|
||||
{ 322, 1000, 0, 2, 6 }, // 12 If user selects 30KHz -> 32.2KHz actual
|
||||
{ 377, 1000, 0, 1, 1 }, // 13 "AUTO" selection possibility
|
||||
{ 562, 700, 0, 1, 5 }, // 14 "AUTO" selection possibility
|
||||
{ 832, 600, 0, 0, 2 }, // 15 "AUTO" selection possibility
|
||||
{ 1121, 500, 0, 0, 5 }, // 16 If user selects 100KHz -> 112.1KHz actual
|
||||
{ 1811, 500, 1, 1, 9 }, // 17 "AUTO" selection possibility
|
||||
{ 2488, 450, 1, 0, 2 }, // 18 "AUTO" selection possibility
|
||||
{ 3355, 400, 1, 0, 8 }, // 19 If user selects 300KHz -> 335.5KHz actual
|
||||
{ 3618, 300, 1, 0, 9 }, // 20 "AUTO" selection possibility
|
||||
{ 4685, 300, 1, 0, 11 }, // 21 "AUTO" selection possibility
|
||||
{ 6207, 300, 1, 0, 14 } // 22 "AUTO" selection possibility
|
||||
{ 162, 2000, 0, 3, 6 }, // 12 "AUTO" selection possibility
|
||||
{ 210, 1600, 0, 2, 2 }, // 13 "AUTO" selection possibility
|
||||
{ 227, 1500, 0, 2, 3 }, // 14 "AUTO" selection possibility
|
||||
{ 240, 1400, 0, 2, 4 }, // 15 "AUTO" selection possibility
|
||||
{ 282, 1000, 0, 2, 5 }, // 16 "AUTO" selection possibility
|
||||
{ 322, 1000, 0, 2, 6 }, // 17 If user selects 30KHz -> 32.2KHz actual
|
||||
{ 377, 1000, 0, 1, 1 }, // 18 "AUTO" selection possibility
|
||||
{ 562, 700, 0, 1, 5 }, // 19 "AUTO" selection possibility
|
||||
{ 832, 600, 0, 0, 2 }, // 20 "AUTO" selection possibility
|
||||
{ 1121, 500, 0, 0, 5 }, // 21 If user selects 100KHz -> 112.1KHz actual
|
||||
{ 1811, 500, 1, 1, 9 }, // 22 "AUTO" selection possibility
|
||||
{ 2251, 1400, 1, 0, 1 }, // 23 "AUTO" selection possibility
|
||||
{ 2488, 450, 1, 0, 2 }, // 24 "AUTO" selection possibility
|
||||
{ 3355, 400, 1, 0, 8 }, // 25 If user selects 300KHz -> 335.5KHz actual
|
||||
{ 3618, 300, 1, 0, 9 }, // 26 "AUTO" selection possibility
|
||||
{ 4685, 300, 1, 0, 11 }, // 27 "AUTO" selection possibility
|
||||
{ 6207, 300, 1, 0, 14 } // 28 "AUTO" selection possibility
|
||||
};
|
||||
|
||||
|
||||
@ -550,8 +556,11 @@ float Si4432::SetRBW ( float reqBandwidth10, unsigned long* delaytime_p ) // "re
|
||||
*/
|
||||
|
||||
if ( reqBandwidth10 <= _bandpassFilters[0].bandwidth10 )
|
||||
{
|
||||
filter = 0;
|
||||
|
||||
Serial.print ("Minimum RBW");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the requested bandwidth is greater or equal to the value in the first entry,
|
||||
* find the setting that is nearest (and above) the requested setting.
|
||||
@ -560,7 +569,7 @@ float Si4432::SetRBW ( float reqBandwidth10, unsigned long* delaytime_p ) // "re
|
||||
while (( _bandpassFilters[filter-1].bandwidth10 > reqBandwidth10 - 0.01 ) && ( filter > 0 ))
|
||||
filter--;
|
||||
|
||||
// Serial.print ( "filter = " ); Serial.println ( filter );
|
||||
Serial.printf ( "Required = %f, filter = %i\n", reqBandwidth10, filter); Serial.println ( filter );
|
||||
|
||||
|
||||
/*
|
||||
|
@ -31,8 +31,8 @@
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
|
||||
#define PROGRAM_NAME "TinySA" // These are for the WiFi interface
|
||||
#define PROGRAM_VERSION "3.0" // Current version is 3.0
|
||||
#define PROGRAM_NAME "simpleSA" // These are for the WiFi interface
|
||||
#define PROGRAM_VERSION "0.01" // Current version is 0.01 - beta!
|
||||
|
||||
|
||||
/*
|
||||
@ -41,7 +41,7 @@
|
||||
* it out, it will stay set at '1'.
|
||||
*/
|
||||
|
||||
#define TRACE_COUNT 1 // Number fo different traces available
|
||||
#define TRACE_COUNT 1 // Number of different traces available
|
||||
|
||||
|
||||
/*
|
||||
@ -179,7 +179,7 @@
|
||||
*/
|
||||
|
||||
enum { SA_LOW_RANGE, SA_HIGH_RANGE, SIG_GEN_LOW_RANGE, SIG_GEN_HIGH_RANGE,
|
||||
IF_SWEEP, ZERO_SPAN_LOW_RANGE, ZERO_SPAN_HIGH_RANGE, TRACKING_GENERATOR, BANDSCOPE };
|
||||
IF_SWEEP, ZERO_SPAN_LOW_RANGE, ZERO_SPAN_HIGH_RANGE, TRACKING_GENERATOR, BANDSCOPE, RX_SWEEP };
|
||||
|
||||
|
||||
/*
|
||||
|
99
simpleSA.ino
99
simpleSA.ino
@ -380,7 +380,7 @@ int16_t minGrid;
|
||||
* Some varibales for the various operating modes
|
||||
*/
|
||||
uint16_t tinySA_mode = SA_LOW_RANGE; // Low frequency range
|
||||
const char *modeText[] = { "SALo", "SAHi", "SGLo", "SGHi", "IFSw", "0SpL", "0SpH", "TrGn", "BScp" }; // For mode display
|
||||
const char *modeText[] = { "SALo", "SAHi", "SGLo", "SGHi", "IFSw", "0SpL", "0SpH", "TrGn", "BScp", "RXSw" }; // For mode display
|
||||
|
||||
|
||||
float bandwidth; // The current bandwidth (not * 10)
|
||||
@ -420,6 +420,7 @@ extern void StartSigGenMenu ( void ); // Function to launch sig gen menu
|
||||
extern void StartSigGenFreq ( void ); // Function to set frequency
|
||||
extern void ResetSAMenuStack ( void ); // Reinitialise stack for SA mode
|
||||
extern void ResetIFsweepMenuStack ( void ); // Reinitialise stack for IF Sweep mode
|
||||
extern void ResetRXsweepMenuStack ( void ); // Reinitialise stack for IF Sweep mode
|
||||
extern void ResetBandscopeMenuStack ( void ); // Reinitialise stack for Bandscope mode
|
||||
|
||||
extern void ShowSplash ( void ); // Displays the splash screen
|
||||
@ -434,8 +435,14 @@ extern void pushBandscopeSettings ();
|
||||
*/
|
||||
uint32_t startFreq_IF = IF_SWEEP_START;
|
||||
uint32_t stopFreq_IF = IF_SWEEP_STOP;
|
||||
uint32_t sigFreq_IF = 20000000; // 30 Mhz reference
|
||||
uint32_t sigFreq_IF = 15000000; // 15 Mhz reference
|
||||
|
||||
/*
|
||||
* Variables for RXSweep Mode
|
||||
*/
|
||||
uint32_t startFreq_RX = RX_SWEEP_START;
|
||||
uint32_t stopFreq_RX = RX_SWEEP_STOP;
|
||||
uint32_t sigFreq_RX = 15000000; // 15 Mhz reference
|
||||
|
||||
/*
|
||||
* Variables for timing websocket event checks:
|
||||
@ -891,6 +898,10 @@ loopStartMicros = micros();
|
||||
doIF_Sweep(); // IF Sweep
|
||||
break;
|
||||
|
||||
case RX_SWEEP:
|
||||
doRX_Sweep(); // RX Sweep
|
||||
break;
|
||||
|
||||
case BANDSCOPE:
|
||||
doBandscope(); // Bandscope Sweep
|
||||
break;
|
||||
@ -930,14 +941,19 @@ void setMode ( uint16_t newMode )
|
||||
// initSigHigh();
|
||||
// break;
|
||||
|
||||
case BANDSCOPE:
|
||||
initBandscope();
|
||||
break;
|
||||
|
||||
case IF_SWEEP:
|
||||
initIF_Sweep();
|
||||
break;
|
||||
|
||||
case BANDSCOPE:
|
||||
initBandscope();
|
||||
case RX_SWEEP:
|
||||
initRX_Sweep();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DisplayError ( ERR_WARN,
|
||||
"Invalid Mode!",
|
||||
@ -983,6 +999,13 @@ void menuExit()
|
||||
initIF_Sweep();
|
||||
break;
|
||||
|
||||
case RX_SWEEP:
|
||||
if ( setting.Mode == RX_SWEEP )
|
||||
RedrawHisto();
|
||||
else
|
||||
initRX_Sweep();
|
||||
break;
|
||||
|
||||
case BANDSCOPE:
|
||||
if ( setting.Mode == BANDSCOPE )
|
||||
RedrawHisto();
|
||||
@ -999,7 +1022,7 @@ void menuExit()
|
||||
|
||||
|
||||
/*
|
||||
* Initialise common to low, high and IF_Sweeps
|
||||
* Initialise common to low, high, RX and IF_Sweeps
|
||||
*/
|
||||
void init_sweep()
|
||||
{
|
||||
@ -1392,7 +1415,7 @@ double fStart;
|
||||
double fCenter;
|
||||
double fStop;
|
||||
|
||||
// enum { SA_LOW_RANGE, SA_HIGH_RANGE, SIG_GEN_LOW_RANGE, SIG_GEN_HIGH_RANGE, IF_SWEEP, ZERO_SPAN_LOW_RANGE, ZERO_SPAN_HIGH_RANGE, TRACKING_GENERATOR };
|
||||
// enum { SA_LOW_RANGE, SA_HIGH_RANGE, SIG_GEN_LOW_RANGE, SIG_GEN_HIGH_RANGE, IF_SWEEP, ZERO_SPAN_LOW_RANGE, ZERO_SPAN_HIGH_RANGE, TRACKING_GENERATOR, RX_SWEEP };
|
||||
|
||||
tSprite.fillSprite ( BLACK );
|
||||
tSprite.setTextColor ( WHITE );
|
||||
@ -1535,6 +1558,11 @@ double fStop;
|
||||
fCenter = (double) ((( startFreq_IF + stopFreq_IF ) / 2.0 ) / 1000000.0 );
|
||||
fStop = stopFreq_IF/1000000.0;
|
||||
}
|
||||
else if (tinySA_mode == RX_SWEEP) {
|
||||
fStart = startFreq_RX/1000000.0;
|
||||
fCenter = (double) ((( startFreq_RX + stopFreq_RX ) / 2.0 ) / 1000000.0 );
|
||||
fStop = stopFreq_RX/1000000.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fStart = (( (double)setting.ScanStart )/ 1000000.0); // Start freq
|
||||
@ -1721,6 +1749,16 @@ double rssiTodBm ( uint8_t rSSI )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function to convert rSSi to dBm
|
||||
*/
|
||||
|
||||
uint8_t dBmToRSSI ( double dBm )
|
||||
{
|
||||
return ( 2 * ( dBm - setting.Attenuate + 120.0 - setting.LevelOffset ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "DisplayPoint" - Display a point on the chart.
|
||||
*
|
||||
@ -1837,6 +1875,55 @@ void CreateGainScale ()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "CreateGridScale" puts the decibel values for the main trace into a sprite for
|
||||
* display at the left side of the Bandscope grid.
|
||||
* The gainScaleSprite is reused as there in no need for a gain trace on the bandscope
|
||||
*
|
||||
* NOTE Due to temporary error in TFT_eSPI library the inverted colour is used
|
||||
* so TFT_BLUE actually results in TFT_GREEN!
|
||||
*/
|
||||
|
||||
void CreateGridScale ()
|
||||
{
|
||||
gainScaleSprite.deleteSprite();
|
||||
gainScaleSprite.setAttribute ( PSRAM_ENABLE, false );
|
||||
gainScaleSprite.setColorDepth ( 16 ); // Using 16 bit (RGB565) colors
|
||||
gainScaleSprite.createSprite(CHAR_WIDTH * 4, gridHeight);
|
||||
gainScaleSprite.fillSprite(BLACK);
|
||||
gainScaleSprite.setPivot( 0, 0 );
|
||||
gainScaleSprite.setTextSize ( 1 );
|
||||
gainScaleSprite.setTextColor ( TFT_WHITE );
|
||||
int w = gainScaleSprite.width();
|
||||
|
||||
// Serial.printf("Create gain scale - get sprite width %i \n", w);
|
||||
|
||||
if ( w != CHAR_WIDTH * 4 )
|
||||
{
|
||||
Serial.println ( "Error - no gain scale sprite" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Markers at every other line, there are 10 lines
|
||||
int16_t valueInterval = (setting.BandscopeMaxGrid - setting.BandscopeMinGrid) / yGrid * 2 ;
|
||||
int16_t v = setting.BandscopeMaxGrid;
|
||||
int16_t yoffset;
|
||||
|
||||
for ( int i = 0; i < 5; i++ )
|
||||
{
|
||||
if (i > 0)
|
||||
yoffset = -3;
|
||||
else
|
||||
yoffset = 0;
|
||||
gainScaleSprite.setCursor ( 0, yoffset + ( yDelta * i * 2 ));
|
||||
gainScaleSprite.printf ( "%4i", v );
|
||||
v = v - valueInterval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* "ledcAnalogWrite" - Arduino like analogWrite used for PWM control of backlight.
|
||||
*
|
||||
|
97
ui.cpp
97
ui.cpp
@ -94,8 +94,8 @@ typedef struct {
|
||||
// to '6' below!
|
||||
int8_t digit_mode;
|
||||
int8_t current_trace; // 0 to 3 ???
|
||||
int32_t value; // For editing at numeric input area
|
||||
int32_t previous_value;
|
||||
double value; // For editing at numeric input area
|
||||
double previous_value;
|
||||
} uistat_t;
|
||||
|
||||
|
||||
@ -107,8 +107,8 @@ uistat_t uistat = {
|
||||
6, // digit - See note above
|
||||
0, // digit_mode
|
||||
0, // current_trace
|
||||
0, // value
|
||||
0 // previous_value
|
||||
0.0, // value
|
||||
0.0 // previous_value
|
||||
};
|
||||
|
||||
|
||||
@ -198,7 +198,7 @@ enum { KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_FOCUS,
|
||||
KM_REFPOS, KM_ATTENUATION, KM_ACTUALPOWER, KM_IFFREQ, KM_PREAMP,
|
||||
KM_TUNE, KM_SGFREQ, KM_SGLEVEL, KM_SGLEVCAL, KM_IFSTART, KM_IFSTOP,
|
||||
KM_IFSIG, KM_TGOFFSET, KM_TGLO_DRIVE, KM_TGIF_DRIVE, KM_BANDSCOPESTART,
|
||||
KM_WFMIN, KM_WFGAIN, KM_BANDSCOPELEVEL };
|
||||
KM_WFMIN, KM_WFGAIN, KM_BANDSCOPELEVEL, KM_RXSPAN, KM_RXSIG, KM_RBW };
|
||||
|
||||
|
||||
/*
|
||||
@ -216,7 +216,7 @@ static const char * const keypad_mode_label[] =
|
||||
"REFPOS", "ATTEN", "POWER", "IF FREQ", "PREAMP",
|
||||
"XTAL CAL", "SG FREQ", "dBm", "Max dBm", "IF START", "IF STOP",
|
||||
"IF Sig Freq", "TG OFFSET", "TG LO Drive", "TG IF Drive", "START",
|
||||
"WF MIN", "WF GAIN", "REF LEVEL"
|
||||
"WF MIN", "WF GAIN", "REF LEVEL", "RX SPAN", "RX Sig Freq", "RBW"
|
||||
};
|
||||
|
||||
|
||||
@ -274,6 +274,7 @@ static void menu_format_cb ( int item );
|
||||
static void menu_scale_cb ( int item );
|
||||
static void menu_sweep_cb ( int item );
|
||||
static void menu_IF_sweep_cb ( int item ); // M0WID added 3.0c
|
||||
static void menu_RX_sweep_cb ( int item );
|
||||
static void menu_recall_cb ( int item );
|
||||
static void menu_version_cb (int item );
|
||||
static void menu_generate_cb(int item); // WA2FZW - Added in M0WID's Version 05
|
||||
@ -442,8 +443,9 @@ static Menuitem menu_mode[] = // Select mode menu
|
||||
{
|
||||
Menuitem ( MT_FUNC, "\2SWEEP\0LOW", menu_mode_cb ),
|
||||
Menuitem ( MT_FUNC, "\2SIG\0GEN", menu_mode_cb ),
|
||||
Menuitem ( MT_FUNC, "\2IF\0SWEEP", menu_mode_cb ),
|
||||
Menuitem ( MT_FUNC, "\2BAND\0SCOPE",menu_mode_cb ),
|
||||
Menuitem ( MT_FUNC, "\2IF\0SWEEP", menu_mode_cb ),
|
||||
Menuitem ( MT_FUNC, "\2RX\0SWEEP", menu_mode_cb ),
|
||||
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
||||
Menuitem ( MT_END ) // End marker
|
||||
};
|
||||
@ -739,6 +741,17 @@ static Menuitem menu_IFsweep_top[] = // This is the main "IF_SWEEP" menu
|
||||
};
|
||||
|
||||
|
||||
static Menuitem menu_RXsweep_top[] = // This is the main "IF_SWEEP" menu
|
||||
{
|
||||
Menuitem ( MT_MENU, "MODE", menu_mode ),
|
||||
Menuitem ( MT_FUNC, "\2SWEEP\0SPAN", menu_RX_sweep_cb ),
|
||||
Menuitem ( MT_FUNC, "\2SWEEP\0SIG", menu_RX_sweep_cb ),
|
||||
Menuitem ( MT_FUNC, "RBW", menu_RX_sweep_cb ),
|
||||
Menuitem ( MT_MENU, "REFERENCE", menu_refer ), // Select GPIO2 reference frequency
|
||||
Menuitem ( MT_END ) // End marker
|
||||
};
|
||||
|
||||
|
||||
static Menuitem menu_BandscopeSpan[] = // Badscope Span settings
|
||||
{
|
||||
Menuitem ( MT_FUNC, "200kHz", menu_BandscopeSpan_cb ),
|
||||
@ -1145,13 +1158,13 @@ void ShowSplash ( void )
|
||||
tft.setTextColor ( MAGENTA );
|
||||
|
||||
tft.setFreeFont ( &FreeSerifBoldItalic18pt7b ); // Select Free Serif 9 point font
|
||||
tft.drawString ( "TinySA for ESP32", 160, 20 );
|
||||
tft.drawString ( "simpleSA for ESP32", 160, 20 );
|
||||
tft.setTextColor ( WHITE );
|
||||
tft.setFreeFont ( &FreeSansBold9pt7b ); // Select Free Serif 9 point font
|
||||
tft.drawString ( "By WA2FZW, M0WID,", 160, 60 );
|
||||
tft.drawString ( "VK3PE and G3ZQC", 160, 80 );
|
||||
tft.drawString ( "Version 3.0", 160, 100 );
|
||||
tft.drawString ( "Original by Erik (PD0EK)", 160, 120 );
|
||||
tft.drawString ( "Version 0.01", 160, 100 );
|
||||
tft.drawString ( "Original tinySA by Erik (PD0EK)", 160, 120 );
|
||||
|
||||
tft.setTextDatum ( TL_DATUM ); // Back to default top left
|
||||
|
||||
@ -1195,14 +1208,20 @@ void menu_mode_cb ( int item )
|
||||
break;
|
||||
|
||||
case 2: // Set IF Sweep mode
|
||||
setMode(IF_SWEEP);
|
||||
setMode(BANDSCOPE);
|
||||
ui_mode_normal (); // No menu displayed
|
||||
break;
|
||||
|
||||
case 3: // Set IF Sweep mode
|
||||
setMode(BANDSCOPE);
|
||||
setMode(IF_SWEEP);
|
||||
ui_mode_normal (); // No menu displayed
|
||||
break;
|
||||
|
||||
case 4: // Set RX Sweep mode
|
||||
setMode(RX_SWEEP);
|
||||
ui_mode_normal (); // No menu displayed
|
||||
break;
|
||||
|
||||
}
|
||||
changedSetting = true;
|
||||
|
||||
@ -1775,6 +1794,14 @@ static void menu_IF_sweep_cb ( int item )
|
||||
}
|
||||
|
||||
|
||||
static void menu_RX_sweep_cb ( int item )
|
||||
{
|
||||
ui_mode_keypad ( item + KM_RXSPAN - 1 ); // item = 1 -> KM_RXSPAN, 2 -> KM_RXSIG
|
||||
ui_process_keypad ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* *********************************************
|
||||
* BANDSCOPE MENU ITEMS
|
||||
@ -2099,7 +2126,10 @@ static const keypads_t * const keypads_mode_tbl[] =
|
||||
keypads_freq, // KM_BANDSCOPESTART.IF Sweep start frequency
|
||||
keypads_integer, // KM_WFMIN..........Waterfall min level (RSSI)
|
||||
keypads_level, // KM_WFGAIN.........Waterfall Gain
|
||||
keypads_level // KM_BANDSCOPELEVEL.Grid reference level
|
||||
keypads_level, // KM_BANDSCOPELEVEL.Grid reference level
|
||||
keypads_freq, // KM_RXSPAN.........RX Sweep span frequency
|
||||
keypads_freq, // KM_RXSIG..........RX Sweep signal frequency
|
||||
keypads_freq // KM_RBW............RX Sweep RBW
|
||||
|
||||
};
|
||||
|
||||
@ -2503,6 +2533,18 @@ static void fetch_numeric_target ( void )
|
||||
uistat.value = setting.BandscopeMaxGrid;
|
||||
break;
|
||||
|
||||
case KM_RXSPAN:
|
||||
uistat.value = GetRXsweepSpan();
|
||||
break;
|
||||
|
||||
case KM_RXSIG:
|
||||
uistat.value = GetRXsweepSigFreq();
|
||||
break;
|
||||
|
||||
case KM_RBW:
|
||||
uistat.value = (double)setting.Bandwidth10 / 10.0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
uint32_t x = uistat.value;
|
||||
@ -2514,7 +2556,7 @@ static void fetch_numeric_target ( void )
|
||||
uistat.digit = n;
|
||||
|
||||
uistat.previous_value = uistat.value;
|
||||
Serial.printf("uistat previous value %f\n", uistat.previous_value );
|
||||
// Serial.printf("uistat previous value %f\n", uistat.previous_value );
|
||||
}
|
||||
|
||||
|
||||
@ -2950,6 +2992,18 @@ static int keypad_click ( int key )
|
||||
SetBandscopeLevel (( int32_t ) value );
|
||||
break;
|
||||
|
||||
case KM_RXSPAN: // RX Span frequency entered?
|
||||
Serial.printf( "Value = %f\n", value );
|
||||
SetRXsweepSpan (( int32_t ) value );
|
||||
break;
|
||||
|
||||
case KM_RXSIG: // RX Signal frequency entered?
|
||||
SetRXsweepSigFreq (( int32_t ) value );
|
||||
break;
|
||||
|
||||
case KM_RBW: // RBW
|
||||
SetRBW (( int32_t ) (value * 10) );
|
||||
break;
|
||||
|
||||
} // End of "switch"
|
||||
|
||||
@ -3319,6 +3373,21 @@ void ResetIFsweepMenuStack (void)
|
||||
ui_mode_normal ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets the menu stack to root level for RX_SWEEP mode
|
||||
*/
|
||||
void ResetRXsweepMenuStack (void)
|
||||
{
|
||||
tft.unloadFont();
|
||||
selection = -1; // Switch menu mode
|
||||
menu_current_level = 0;
|
||||
menu_stack[0] = menu_RXsweep_top;
|
||||
menu_stack[1] = NULL;
|
||||
menu_stack[2] = NULL;
|
||||
menu_stack[3] = NULL;
|
||||
if (ui_mode != UI_NORMAL)
|
||||
ui_mode_normal ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user