RXSweep mode added

Also scale for bandscope
This commit is contained in:
M0WID 2020-08-21 22:02:22 +01:00
parent 76d7cd9aee
commit 6479c6050b
10 changed files with 989 additions and 69 deletions

View File

@ -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
View 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 )"
}

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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 );
/*

View File

@ -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 };
/*

View File

@ -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
View File

@ -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 ();
}
/*