Bandscope Grid working
Waterfall next, then speed up frequency changes with offsets and reduce delaytime. Sort out 1 pixel error at start/end
This commit is contained in:
parent
64e45e76ad
commit
16289698dc
229
Bandscope.ino
229
Bandscope.ino
@ -4,6 +4,18 @@
|
||||
*/
|
||||
void initBandscope()
|
||||
{
|
||||
// set up checkerboard sizes
|
||||
waterfallHeight = WATERFALL_HEIGHT;
|
||||
gridHeight = SCREEN_HEIGHT - waterfallHeight - 10;
|
||||
gridWidth = SCREEN_WIDTH;
|
||||
yGrid = Y_GRID; // no of grid divisions
|
||||
yDelta = gridHeight / yGrid; // no of points/division
|
||||
xGrid = X_GRID;
|
||||
xOrigin = 0;
|
||||
yOrigin = 0;
|
||||
displayPoints = setting.BandscopePoints;
|
||||
xDelta = SCREEN_WIDTH / xGrid;
|
||||
|
||||
ClearDisplay ();
|
||||
/*
|
||||
* Set up the "img" Sprite. This is the image for the graph. It makes for faster display
|
||||
@ -22,19 +34,15 @@ void initBandscope()
|
||||
img.setTextSize ( 1 );
|
||||
img.setColorDepth ( 16 );
|
||||
img.setAttribute ( PSRAM_ENABLE, false ); // Don't use the PSRAM on the WROVERs
|
||||
img.createSprite ( 9, GRID_HEIGHT + 1 ); // Only 2 columns wide
|
||||
img.createSprite ( 2, gridHeight + 1 ); // Only 2 columns wide
|
||||
|
||||
|
||||
/*
|
||||
* The "tSprite" is used for displaying the data above the scan grid.
|
||||
* The "tSprite" is used for displaying the data above the scan grid - we don't use it in this mode
|
||||
* The "sSprite" is for displaying the sidebar stuff, no sidebar in this mode
|
||||
*/
|
||||
|
||||
tSprite.deleteSprite();
|
||||
tSprite.setRotation ( 0 );
|
||||
tSprite.setTextSize ( 1 );
|
||||
tSprite.setColorDepth ( 16 );
|
||||
tSprite.setAttribute ( PSRAM_ENABLE, false ); // Don't use the PSRAM on the WROVERs
|
||||
tSprite.createSprite ( tft.width() - X_ORIGIN, Y_ORIGIN );
|
||||
|
||||
sSprite.deleteSprite();
|
||||
/*
|
||||
@ -65,9 +73,7 @@ void initBandscope()
|
||||
|
||||
tinySA_mode = BANDSCOPE;
|
||||
setting.Mode = tinySA_mode;
|
||||
Serial.println("before reset bandscope stack");
|
||||
ResetBandscopeMenuStack(); // Put menu stack back to root level
|
||||
Serial.println("End of initBandscope");
|
||||
}
|
||||
|
||||
|
||||
@ -134,7 +140,7 @@ static uint16_t chunkIndex;
|
||||
{
|
||||
if ( initSweep || changedSetting ) // Something has changed, or a first start, so need to owrk out some basic things
|
||||
{
|
||||
Serial.println("InitBandscope or changedSetting");
|
||||
// Serial.println("InitBandscope or changedSetting");
|
||||
sweepPoints = setting.BandscopePoints;
|
||||
autoSweepFreqStep = ( setting.BandscopeSpan ) / sweepPoints;
|
||||
|
||||
@ -173,8 +179,6 @@ static uint16_t chunkIndex;
|
||||
pushBandscopeSettings ();
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
|
||||
|
||||
} // initSweep || changedSetting
|
||||
|
||||
autoSweepStep = 0; // Set the step counter to zero
|
||||
@ -226,36 +230,9 @@ static uint16_t chunkIndex;
|
||||
// Serial.printf ( "Setting actual Power %f \n", actualPower );
|
||||
}
|
||||
|
||||
pointMinGain = 100; // Reset min/max values
|
||||
pointMaxRSSI = 0;
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
DisplayBandscopeInfo (); // Display axis and other info
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
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;
|
||||
@ -386,161 +363,72 @@ static uint16_t chunkIndex;
|
||||
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
myActual[autoSweepStep] = rxRSSI;
|
||||
|
||||
myGain[autoSweepStep] = gainReading;
|
||||
uint16_t pixelsPerPoint = SCREEN_WIDTH / displayPoints;
|
||||
for (uint16_t i = 0; i< pixelsPerPoint; i++) {
|
||||
|
||||
DrawCheckerBoard ( oldSweepStep ); // Draw the grid for the point in the sweep we have just read
|
||||
uint16_t tmp = oldSweepStep * pixelsPerPoint + i;
|
||||
|
||||
myActual[tmp] = rxRSSI;
|
||||
|
||||
myGain[tmp] = gainReading;
|
||||
|
||||
DrawCheckerBoard ( tmp ); // Draw the grid
|
||||
|
||||
if ( resetAverage || setting.Average == AV_OFF ) // Store data, either as read or as rolling average
|
||||
myData[oldSweepStep] = myActual[oldSweepStep];
|
||||
|
||||
myData[tmp] = myActual[oldSweepStep];
|
||||
else
|
||||
{
|
||||
switch ( setting.Average )
|
||||
{
|
||||
case AV_MIN:
|
||||
if ( myData[oldSweepStep] > myActual[oldSweepStep] )
|
||||
myData[oldSweepStep] = myActual[oldSweepStep];
|
||||
if ( myData[tmp] > myActual[oldSweepStep] )
|
||||
myData[tmp] = myActual[oldSweepStep];
|
||||
break;
|
||||
|
||||
case AV_MAX:
|
||||
if ( myData[oldSweepStep] < myActual[oldSweepStep] )
|
||||
myData[oldSweepStep] = myActual[oldSweepStep];
|
||||
if ( myData[tmp] < myActual[oldSweepStep] )
|
||||
myData[tmp] = myActual[oldSweepStep];
|
||||
break;
|
||||
|
||||
case AV_2:
|
||||
myData[oldSweepStep] = ( myData[oldSweepStep] + myActual[oldSweepStep] ) / 2;
|
||||
myData[tmp] = ( myData[tmp] + myActual[oldSweepStep] ) / 2;
|
||||
break;
|
||||
|
||||
case AV_4:
|
||||
myData[oldSweepStep] = ( myData[oldSweepStep]*3 + myActual[oldSweepStep] ) / 4;
|
||||
myData[tmp] = ( myData[tmp]*3 + myActual[oldSweepStep] ) / 4;
|
||||
break;
|
||||
|
||||
case AV_8:
|
||||
myData[oldSweepStep] = ( myData[oldSweepStep]*7 + myActual[oldSweepStep] ) / 8;
|
||||
myData[tmp] = ( myData[tmp]*7 + myActual[oldSweepStep] ) / 8;
|
||||
break;
|
||||
}
|
||||
DisplayPoint ( myData, oldSweepStep, AVG_COLOR );
|
||||
DisplayPoint ( myData, tmp, AVG_COLOR );
|
||||
}
|
||||
|
||||
if ( setting.ShowSweep )
|
||||
DisplayPoint ( myActual, oldSweepStep, DB_COLOR );
|
||||
DisplayPoint ( myActual, tmp, DB_COLOR );
|
||||
|
||||
if ( setting.ShowGain )
|
||||
displayGainPoint ( myGain, oldSweepStep, GAIN_COLOR );
|
||||
displayGainPoint ( myGain, tmp, GAIN_COLOR );
|
||||
|
||||
if ( setting.ShowStorage )
|
||||
DisplayPoint ( myStorage, oldSweepStep, STORAGE_COLOR );
|
||||
|
||||
if ( setting.SubtractStorage )
|
||||
rxRSSI = 128 + rxRSSI - myStorage[oldSweepStep];
|
||||
|
||||
|
||||
/*
|
||||
* Record the peak values but not if freq low enough to detect the LO
|
||||
*/
|
||||
|
||||
if ( peakLevel < myData[oldSweepStep] )
|
||||
{
|
||||
peakIndex = oldSweepStep;
|
||||
peakLevel = myData[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 = myData[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
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
if ( setting.ShowSweep || setting.Average != AV_OFF )
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
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) )
|
||||
{
|
||||
int16_t scaleX = setting.BandscopePoints - 2 * CHAR_WIDTH - oldSweepStep + 1; // relative to the img sprite
|
||||
int16_t scaleX = setting.BandscopePoints - 2 * CHAR_WIDTH - 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
|
||||
}
|
||||
|
||||
if ( oldSweepStep > 0 ) // Only push if not first point (two pixel wide img)
|
||||
img.pushSprite ( X_ORIGIN+oldSweepStep-1, Y_ORIGIN );
|
||||
if ( tmp > 0 ) // Only push if not first point (two pixel wide img)
|
||||
img.pushSprite ( xOrigin+tmp, yOrigin );
|
||||
|
||||
myFreq[oldSweepStep] = oldSweepFreq; // Store the frequency for XML file creation
|
||||
}
|
||||
|
||||
myFreq[oldSweepStep] = oldSweepFreq; // Store the frequency for XML file creation
|
||||
|
||||
|
||||
if ( autoSweepStep >= sweepPoints ) // If we have got to the end of the sweep
|
||||
@ -552,8 +440,6 @@ static uint16_t chunkIndex;
|
||||
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[setting.BandscopePoints-1] == 0 ) // Ensure a value in last data point
|
||||
{
|
||||
myActual[setting.BandscopePoints-1] = rxRSSI; // Yes, save it
|
||||
@ -565,7 +451,6 @@ static uint16_t chunkIndex;
|
||||
showRSSI = 0; // Then turn it off
|
||||
|
||||
#ifdef USE_WIFI
|
||||
|
||||
if (( numberOfWebsocketClients > 0) && jsonDocInitialised && (chunkIndex > 0) )
|
||||
{
|
||||
String wsBuffer;
|
||||
@ -579,16 +464,16 @@ static uint16_t chunkIndex;
|
||||
else
|
||||
Serial.println ( "No buffer :(");
|
||||
}
|
||||
|
||||
#endif // #ifdef USE_WIFI
|
||||
|
||||
} // End of "if ( sweepStep >= sweepPoints )"
|
||||
} // End of "doSweepLow"
|
||||
} // End of "if ( autoSweepStep >= sweepPoints )"
|
||||
|
||||
} // End of "doBandscope"
|
||||
|
||||
|
||||
/*
|
||||
* "DisplayInfo" - Draws the background text around the checkerboard. Called
|
||||
* when a setting is changed to set axis labels and top info bar
|
||||
* "DisplayBandscopeInfo" - Draws the frequency info below the checkerboard. Called
|
||||
* when a setting is changed to set axis labels
|
||||
*/
|
||||
|
||||
void DisplayBandscopeInfo ()
|
||||
@ -618,30 +503,30 @@ double fStop;
|
||||
|
||||
if ( old_startFreq != fStart || old_stopFreq != fStop )
|
||||
{
|
||||
Serial.printf("DisplayBandscopeInfo fStart %f; old_startFreq %f \n", fStart, old_startFreq);
|
||||
Serial.printf("DisplayBandscopeInfo fStop %f; old_stopFreq %f \n", fStop, old_stopFreq);
|
||||
// Serial.printf("DisplayBandscopeInfo fStart %f; old_startFreq %f \n", fStart, old_startFreq);
|
||||
// Serial.printf("DisplayBandscopeInfo fStop %f; old_stopFreq %f \n", fStop, old_stopFreq);
|
||||
|
||||
tft.fillRect ( X_ORIGIN, SCREEN_HEIGHT -
|
||||
CHAR_HEIGHT, SCREEN_WIDTH - X_ORIGIN - 1, SCREEN_HEIGHT - 1, BLACK );
|
||||
tft.fillRect ( xOrigin, SCREEN_HEIGHT -
|
||||
CHAR_HEIGHT, SCREEN_WIDTH - xOrigin - 1, SCREEN_HEIGHT - 1, BLACK );
|
||||
|
||||
// Show operating mode
|
||||
tft.setCursor ( X_ORIGIN + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( xOrigin + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setTextColor ( DB_COLOR );
|
||||
tft.printf ( "Mode:%s", modeText[setting.Mode] );
|
||||
tft.setTextColor ( WHITE );
|
||||
|
||||
tft.setCursor ( X_ORIGIN + 2, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( xOrigin + 2, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
|
||||
tft.print ( fStart );
|
||||
|
||||
tft.setCursor ( SCREEN_WIDTH - 37, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( SCREEN_WIDTH - 25, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.print ( fStop );
|
||||
|
||||
|
||||
/*
|
||||
* Show the center frequency:
|
||||
*/
|
||||
tft.setCursor ( SCREEN_WIDTH / 2 - 40 + X_ORIGIN, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( SCREEN_WIDTH / 2 - 20 + xOrigin, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.print ( fCenter );
|
||||
tft.print ( "(MHz)" );
|
||||
|
||||
@ -693,7 +578,7 @@ double fStop;
|
||||
int x = tSprite.width () - 45;
|
||||
tSprite.setTextColor ( WHITE );
|
||||
|
||||
tSprite.pushSprite ( X_ORIGIN, 0 ); // Write sprite to the display
|
||||
tSprite.pushSprite ( xOrigin, 0 ); // Write sprite to the display
|
||||
|
||||
updateSidebar = false;
|
||||
} // End of "DisplayBandscopeInfo"
|
||||
|
34
IFsweep.ino
34
IFsweep.ino
@ -8,6 +8,16 @@
|
||||
*/
|
||||
void initIF_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();
|
||||
|
||||
@ -62,10 +72,10 @@ static uint16_t chunkIndex;
|
||||
if ( initSweep || changedSetting ) // Something has changed, or a first start, so need to work out some basic things
|
||||
{
|
||||
Serial.println("Init IFSweep or changedSetting");
|
||||
autoSweepFreqStep = ( stopFreq_IF - startFreq_IF ) / DISPLAY_POINTS;
|
||||
autoSweepFreqStep = ( stopFreq_IF - startFreq_IF ) / displayPoints;
|
||||
|
||||
vbw = autoSweepFreqStep / 1000.0; // Set the video resolution
|
||||
// ownrbw = ((float) ( stopFreq_IF - startFreq_IF )) / DISPLAY_POINTS / 1000.0; // kHz
|
||||
// ownrbw = ((float) ( stopFreq_IF - startFreq_IF )) / displayPoints / 1000.0; // kHz
|
||||
//
|
||||
// if ( ownrbw < 2.6 ) // If it's less than 2.6KHz
|
||||
// ownrbw = 2.6; // set it to 2.6KHz
|
||||
@ -81,7 +91,7 @@ static uint16_t chunkIndex;
|
||||
|
||||
bandwidth = rcvr.SetRBW ( 106.0, &delaytime ); // Set it in the receiver Si4432. delaytime is returned
|
||||
|
||||
sweepPoints = DISPLAY_POINTS; // At least the right number of points for the display
|
||||
sweepPoints = displayPoints; // At least the right number of points for the display
|
||||
|
||||
sweepFreqStep = ( stopFreq_IF - startFreq_IF ) / sweepPoints; // Step for each reading
|
||||
|
||||
@ -95,8 +105,8 @@ static uint16_t chunkIndex;
|
||||
wiFiPoints = wiFiTargetTime / delaytime;
|
||||
if (wiFiPoints > MAX_WIFI_POINTS)
|
||||
wiFiPoints = MAX_WIFI_POINTS;
|
||||
if (wiFiPoints > DISPLAY_POINTS*OVERLAP)
|
||||
wiFiPoints = DISPLAY_POINTS*OVERLAP;
|
||||
if (wiFiPoints > displayPoints*OVERLAP)
|
||||
wiFiPoints = displayPoints*OVERLAP;
|
||||
// Serial.printf("No of wifiPoints set to %i\n", wiFiPoints);
|
||||
|
||||
pushIFSweepSettings();
|
||||
@ -445,15 +455,15 @@ static uint16_t chunkIndex;
|
||||
}
|
||||
|
||||
// If in the last few points and gain trace is displayed show the gain scale
|
||||
if ( setting.ShowGain && (oldSweepStep > DISPLAY_POINTS - 2 * CHAR_WIDTH) )
|
||||
if ( setting.ShowGain && (oldSweepStep > displayPoints - 2 * CHAR_WIDTH) )
|
||||
{
|
||||
int16_t scaleX = DISPLAY_POINTS - 2 * CHAR_WIDTH - oldSweepStep + 1; // relative to the img sprite
|
||||
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 ( X_ORIGIN+oldSweepStep-1, Y_ORIGIN );
|
||||
img.pushSprite ( xOrigin+oldSweepStep-1, yOrigin );
|
||||
|
||||
myFreq[oldSweepStep] = oldSweepFreq; // Store the frequency for XML file creation
|
||||
|
||||
@ -469,11 +479,11 @@ static uint16_t chunkIndex;
|
||||
|
||||
oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function
|
||||
|
||||
if ( myActual[DISPLAY_POINTS-1] == 0 ) // Ensure a value in last data point
|
||||
if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point
|
||||
{
|
||||
myActual[DISPLAY_POINTS-1] = rxRSSI; // Yes, save it
|
||||
myGain[DISPLAY_POINTS-1] = gainReading;
|
||||
myFreq[DISPLAY_POINTS-1] = oldSweepFreq;
|
||||
myActual[displayPoints-1] = rxRSSI; // Yes, save it
|
||||
myGain[displayPoints-1] = gainReading;
|
||||
myFreq[displayPoints-1] = oldSweepFreq;
|
||||
}
|
||||
|
||||
if ( showRSSI == 1 ) // Only show it once?
|
||||
|
@ -47,7 +47,7 @@ void initSigLow()
|
||||
setting.Mode = tinySA_mode;
|
||||
|
||||
tft.unloadFont();
|
||||
tft.setCursor ( X_ORIGIN + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( xOrigin + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setTextSize(1);
|
||||
tft.setTextColor ( YELLOW );
|
||||
tft.printf ( "Mode:%s", modeText[setting.Mode] );
|
||||
|
35
SweepLo.ino
35
SweepLo.ino
@ -4,6 +4,17 @@
|
||||
*/
|
||||
void initSweepLow()
|
||||
{
|
||||
// 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 = SA_LOW_RANGE;
|
||||
@ -77,7 +88,7 @@ static uint16_t chunkIndex;
|
||||
if ( initSweep || changedSetting ) // Something has changed, or a first start, so need to owrk out some basic things
|
||||
{
|
||||
//Serial.println("InitSweep or changedSetting");
|
||||
autoSweepFreqStep = ( setting.ScanStop - setting.ScanStart ) / DISPLAY_POINTS;
|
||||
autoSweepFreqStep = ( setting.ScanStop - setting.ScanStart ) / displayPoints;
|
||||
|
||||
vbw = autoSweepFreqStep / 1000.0; // Set the video resolution
|
||||
ownrbw = setting.Bandwidth10 / 10.0; // and the resolution bandwidth
|
||||
@ -104,8 +115,8 @@ static uint16_t chunkIndex;
|
||||
|
||||
sweepPoints = (uint32_t)(( setting.ScanStop - setting.ScanStart ) / bandwidth / 1000.0 * OVERLAP + 0.5); // allow for some overlap (filters will have 3dB roll off at edge) and round up
|
||||
|
||||
if ( sweepPoints < DISPLAY_POINTS )
|
||||
sweepPoints = DISPLAY_POINTS; // At least the right number of points for the display
|
||||
if ( sweepPoints < displayPoints )
|
||||
sweepPoints = displayPoints; // At least the right number of points for the display
|
||||
|
||||
sweepFreqStep = ( setting.ScanStop - setting.ScanStart ) / sweepPoints; // Step for each reading
|
||||
|
||||
@ -126,8 +137,8 @@ static uint16_t chunkIndex;
|
||||
wiFiPoints = wiFiTargetTime / delaytime;
|
||||
if (wiFiPoints > MAX_WIFI_POINTS)
|
||||
wiFiPoints = MAX_WIFI_POINTS;
|
||||
if (wiFiPoints > DISPLAY_POINTS*OVERLAP)
|
||||
wiFiPoints = DISPLAY_POINTS*OVERLAP;
|
||||
if (wiFiPoints > displayPoints*OVERLAP)
|
||||
wiFiPoints = displayPoints*OVERLAP;
|
||||
//Serial.printf("No of wifiPoints set to %i\n", wiFiPoints);
|
||||
|
||||
if ( numberOfWebsocketClients > 0 )
|
||||
@ -586,15 +597,15 @@ static uint16_t chunkIndex;
|
||||
}
|
||||
|
||||
// If in the last few points and gain trace is displayed show the gain scale
|
||||
if ( setting.ShowGain && (oldSweepStep > DISPLAY_POINTS - 2 * CHAR_WIDTH) )
|
||||
if ( setting.ShowGain && (oldSweepStep > displayPoints - 2 * CHAR_WIDTH) )
|
||||
{
|
||||
int16_t scaleX = DISPLAY_POINTS - 2 * CHAR_WIDTH - oldSweepStep + 1; // relative to the img sprite
|
||||
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 ( X_ORIGIN+oldSweepStep-1, Y_ORIGIN );
|
||||
img.pushSprite ( xOrigin+oldSweepStep-1, yOrigin );
|
||||
|
||||
myFreq[oldSweepStep] = oldSweepFreq; // Store the frequency for XML file creation
|
||||
|
||||
@ -611,11 +622,11 @@ static uint16_t chunkIndex;
|
||||
|
||||
oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function
|
||||
|
||||
if ( myActual[DISPLAY_POINTS-1] == 0 ) // Ensure a value in last data point
|
||||
if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point
|
||||
{
|
||||
myActual[DISPLAY_POINTS-1] = rxRSSI; // Yes, save it
|
||||
myGain[DISPLAY_POINTS-1] = gainReading;
|
||||
myFreq[DISPLAY_POINTS-1] = oldSweepFreq;
|
||||
myActual[displayPoints-1] = rxRSSI; // Yes, save it
|
||||
myGain[displayPoints-1] = gainReading;
|
||||
myFreq[displayPoints-1] = oldSweepFreq;
|
||||
}
|
||||
|
||||
if ( showRSSI == 1 ) // Only show it once?
|
||||
|
35
cmd.cpp
35
cmd.cpp
@ -17,9 +17,9 @@
|
||||
* here in place of much redundant code in those modules.
|
||||
*/
|
||||
|
||||
#include "Cmd.h" // Our associated header
|
||||
#include "cmd.h" // Our associated header
|
||||
#include "preferences.h" // For "SAVE" & "RECALL"
|
||||
#include "Marker.h" // Marker class definition
|
||||
#include "marker.h" // Marker class definition
|
||||
/*
|
||||
* These are the objects for the PE4302 and Si4432 modules. They are created in the
|
||||
* main program file:
|
||||
@ -47,8 +47,25 @@ extern int changedSetting; // Something in "setting" changed
|
||||
|
||||
extern uint16_t tinySA_mode;
|
||||
|
||||
extern uint8_t myData[DISPLAY_POINTS+1];
|
||||
extern uint8_t myStorage[DISPLAY_POINTS+1];
|
||||
/*
|
||||
* Variables to determine size of grid and waterfall
|
||||
* In Bandscope mode the grid is reduced. In future it may be possible to add
|
||||
* a waterfall to the main sweep, but not yet
|
||||
*/
|
||||
extern uint16_t gridHeight;
|
||||
extern uint16_t gridWidth;
|
||||
extern uint16_t yGrid; // no of grid divisions
|
||||
extern uint16_t yDelta; // no of points/division
|
||||
extern uint16_t xGrid;
|
||||
extern uint16_t xOrigin;
|
||||
extern uint16_t yOrigin;
|
||||
extern uint16_t displayPoints;
|
||||
extern uint16_t xDelta;
|
||||
extern uint16_t waterfallHeight;
|
||||
|
||||
|
||||
extern uint8_t myData[SCREEN_WIDTH+1];
|
||||
extern uint8_t myStorage[SCREEN_WIDTH+1];
|
||||
|
||||
extern float bandwidth; // The current bandwidth (not * 10)
|
||||
extern unsigned long delaytime; // In microseconds
|
||||
@ -1453,7 +1470,7 @@ uint8_t reg69; // Ditto
|
||||
{
|
||||
tempValue = atoi ( dataBuff ); // Yes, get new value
|
||||
// check valid
|
||||
if ( (tempValue > 10) && (tempValue < DISPLAY_POINTS * OVERLAP) )
|
||||
if ( (tempValue > 10) && (tempValue < displayPoints * OVERLAP) )
|
||||
{
|
||||
wiFiPoints = tempValue;
|
||||
Serial.printf ( "Chunk size set to: %u\n", tempValue );
|
||||
@ -1461,7 +1478,7 @@ uint8_t reg69; // Ditto
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("Invalid - must be between 10 and %u\n", DISPLAY_POINTS * OVERLAP);
|
||||
Serial.printf("Invalid - must be between 10 and %u\n", displayPoints * OVERLAP);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1953,7 +1970,7 @@ int oldMin = setting.MinGrid;
|
||||
int oldMax = setting.MaxGrid;
|
||||
|
||||
setting.MaxGrid = ref;
|
||||
setting.MinGrid = ref - Y_GRID * setting.PowerGrid;
|
||||
setting.MinGrid = ref - yGrid * setting.PowerGrid;
|
||||
|
||||
if (( oldMin != setting.MinGrid ) || ( oldMax != setting.MaxGrid ))
|
||||
{
|
||||
@ -2014,7 +2031,7 @@ void SetPowerGrid ( int g )
|
||||
int oldGrid = setting.PowerGrid;
|
||||
|
||||
setting.PowerGrid = g;
|
||||
setting.MinGrid = setting.MaxGrid - Y_GRID * g;
|
||||
setting.MinGrid = setting.MaxGrid - yGrid * g;
|
||||
|
||||
if ( oldGrid != setting.PowerGrid )
|
||||
{
|
||||
@ -2083,7 +2100,7 @@ int oldAtten = setting.Attenuate;
|
||||
|
||||
void SetStorage ( void )
|
||||
{
|
||||
for ( int i = 0; i < DISPLAY_POINTS; i++ )
|
||||
for ( int i = 0; i < displayPoints; i++ )
|
||||
myStorage[i] = myData[i];
|
||||
|
||||
setting.ShowStorage = true;
|
||||
|
4
cmd.h
4
cmd.h
@ -13,8 +13,8 @@
|
||||
#define _CMD_H_ // Prevent double inclusion
|
||||
|
||||
#include "simpleSA.h" // General program definitions
|
||||
#include "PE4302.h" // Class definition for thePE4302 attenuator
|
||||
#include "Si4432.h" // Class definition for the Si4432 transceiver
|
||||
#include "pE4302.h" // Class definition for thePE4302 attenuator
|
||||
#include "si4432.h" // Class definition for the Si4432 transceiver
|
||||
#include "preferences.h" // For saving the "setting" structure
|
||||
#include <SPI.h>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* "Marker.cpp" Contains the code for the "Marker" class functions
|
||||
*/
|
||||
|
||||
#include "Marker.h" // Class definition
|
||||
#include "marker.h" // Class definition
|
||||
|
||||
/*
|
||||
* There are two constructors; the first simply creates an uninitialized
|
||||
|
2
menu.cpp
2
menu.cpp
@ -2,7 +2,7 @@
|
||||
* "Menu.cpp" implements the "Menuitem" class.
|
||||
*/
|
||||
|
||||
#include "Menu.h" // Class definition
|
||||
#include "menu.h" // Class definition
|
||||
|
||||
Menuitem::Menuitem () {} // Placeholder constructor
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* I2C GPIO expander to drive a parallel version of the PE4302 module.
|
||||
*/
|
||||
|
||||
#include "PE4302.h"
|
||||
#include "pE4302.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <SPI.h> // Serial Peripheral Interface library
|
||||
#include "Si4432.h" // Our header file
|
||||
#include "si4432.h" // Our header file
|
||||
#include <esp32-hal-spi.h>
|
||||
|
||||
/*
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef TINYSA_H_
|
||||
#define TINYSA_H_ // Prevent double inclusion
|
||||
|
||||
#include "My_SA.h" // User settable parameters
|
||||
#include "my_SA.h" // User settable parameters
|
||||
#include <Arduino.h> // General Arduino definitions
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
*/
|
||||
|
||||
#define DISPLAY_POINTS 290 // Number of scan points in a sweep
|
||||
#define BANDSCOPE_POINTS 80 // Number of scan points in a bandscope sweep
|
||||
#define CHAR_HEIGHT 8 // Height of a character
|
||||
#define HALF_CHAR_H 4 // Half a character height
|
||||
#define CHAR_WIDTH 6 // Width of a character
|
||||
@ -63,6 +64,9 @@
|
||||
|
||||
#define GRID_HEIGHT ( Y_GRID * DELTA_Y ) // Height of checkerboard
|
||||
|
||||
#define WATERFALL_HEIGHT 100 // Height of waterfall in Bandscope mode
|
||||
|
||||
|
||||
/*
|
||||
* Definitions used in signal generator mode
|
||||
*/
|
||||
@ -249,7 +253,7 @@ typedef struct {
|
||||
int16_t TriggerLevel = -40; // Trigger level for ZeroIF mode (dBm)
|
||||
uint32_t BandscopeStart = 7000000; // Start frequency for bandscope sweep
|
||||
uint32_t BandscopeSpan = 200000; // Span for the bandscope sweep
|
||||
uint16_t BandscopePoints = 80; // No of points in the sweep. 80/160/320
|
||||
uint16_t BandscopePoints = BANDSCOPE_POINTS; // No of points in the sweep. 80/160/320
|
||||
|
||||
|
||||
/*
|
||||
|
176
simpleSA.ino
176
simpleSA.ino
@ -128,10 +128,12 @@
|
||||
* SPI now runs at 16MHz (was at 1MHz - oops!)
|
||||
* Additional functions in ui.cmd to allow signed frequency entry.
|
||||
*
|
||||
* Moved to github for trial
|
||||
* Added initial changes for bandscope mode
|
||||
* Added indication of tracking generator on/off
|
||||
* Renamed to simpleSA
|
||||
* Version 3.0f Changes by M0WID
|
||||
* renamed simpleSA. Doesn't seem that simple to me!
|
||||
* First go at bandscope mode
|
||||
* VSPI reduced to 10Mhz as some boards will not run at 16MHz
|
||||
* Put onto github - lets see how it works!
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@ -139,10 +141,10 @@
|
||||
#include <Arduino.h> // Basic Arduino definitions
|
||||
#include <SPI.h> // Serial Peripheral Interface library
|
||||
#include <Wire.h> // I2C library
|
||||
#include "Si4432.h" // Si4432 tranceiver class definitions and prototypes
|
||||
#include "PE4302.h" // PE4302 attenuator class
|
||||
#include "Cmd.h" // Command processing functions
|
||||
#include "Marker.h" // Marker class
|
||||
#include "si4432.h" // Si4432 tranceiver class definitions and prototypes
|
||||
#include "pE4302.h" // PE4302 attenuator class
|
||||
#include "cmd.h" // Command processing functions
|
||||
#include "marker.h" // Marker class
|
||||
|
||||
|
||||
#if USE_WIFI // M0WID - We need the following if using WiFi
|
||||
@ -163,7 +165,7 @@
|
||||
|
||||
/*
|
||||
* Note the actual definitions for display and touch screen pins used are defined
|
||||
* in the file "M0WID_Setup_ILI9341_simpleSA.h" in the "User_Setups" directory of
|
||||
* in the file "M0WID_Setup_ILI9341_TinySA.h" in the "User_Setups" directory of
|
||||
* the "TFT_eSPI" library.
|
||||
*
|
||||
* These are based on using HSPI (spi2) for display and VSPI (spi3) for the SI4432s
|
||||
@ -356,17 +358,35 @@ size_t capacity = JSON_ARRAY_SIZE ( MAX_WIFI_POINTS + 1 )
|
||||
|
||||
static DynamicJsonDocument jsonDocument ( capacity ); // Buffer for json data to be pushed to the web clients
|
||||
static JsonArray Points = jsonDocument.createNestedArray ( "Points" ); // add Points array
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Variables to determine size of grid and waterfall
|
||||
* In Bandscope mode the grid is reduced. In future it may be possible to add
|
||||
* a waterfall to the main sweep, but not yet
|
||||
*/
|
||||
uint16_t gridHeight = GRID_HEIGHT;
|
||||
uint16_t gridWidth = DISPLAY_POINTS;
|
||||
uint16_t yGrid = Y_GRID; // no of grid divisions
|
||||
uint16_t yDelta = gridHeight / yGrid; // no of points/division
|
||||
uint16_t xGrid = X_GRID;
|
||||
uint16_t xOrigin = X_ORIGIN;
|
||||
uint16_t yOrigin = Y_ORIGIN;
|
||||
uint16_t displayPoints = DISPLAY_POINTS;
|
||||
uint16_t xDelta = displayPoints / xGrid;
|
||||
uint16_t waterfallHeight = WATERFALL_HEIGHT;
|
||||
|
||||
/*
|
||||
* 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", "Band" }; // For mode display
|
||||
const char *modeText[] = { "SALo", "SAHi", "SGLo", "SGHi", "IFSw", "0SpL", "0SpH", "TrGn", "BScp" }; // For mode display
|
||||
|
||||
|
||||
float bandwidth; // The current bandwidth (not * 10)
|
||||
unsigned long delaytime = 2000; // M0WID - changed to microseconds and moved here
|
||||
unsigned long delaytime = 2000; // M0WID - changed to microseconds and moved here
|
||||
|
||||
uint32_t steps = DISPLAY_POINTS; // Number of frequency steps in the sweep
|
||||
uint32_t steps = displayPoints; // Number of frequency steps in the sweep
|
||||
uint32_t sweepPoints; // Number of points in the sweep. Can be more than DISPLAY_POINTS if RBW is set less than video resolution
|
||||
uint32_t startFreq = 0; // Default start frequency is 0MHz
|
||||
uint32_t stopFreq = 100000000; // Default stop frequency is 100MHz
|
||||
@ -430,33 +450,33 @@ uint32_t sweepCount; // Used to inhibit handling Wifi until
|
||||
|
||||
/*
|
||||
* These arrays contain the data for the various scan points; they are used in
|
||||
* here and in the "simpleSA_wifi" modules:
|
||||
* here and in the "TinySA_wifi" modules:
|
||||
*/
|
||||
|
||||
uint8_t myData[DISPLAY_POINTS+1];
|
||||
uint8_t myStorage[DISPLAY_POINTS+1];
|
||||
uint8_t myActual[DISPLAY_POINTS+1];
|
||||
uint8_t myGain[DISPLAY_POINTS+1]; // Preamp gain
|
||||
uint32_t myFreq[DISPLAY_POINTS+1]; // Frequency for XML file
|
||||
uint8_t myData[SCREEN_WIDTH+1];
|
||||
uint8_t myStorage[SCREEN_WIDTH+1];
|
||||
uint8_t myActual[SCREEN_WIDTH+1];
|
||||
uint8_t myGain[SCREEN_WIDTH+1]; // Preamp gain
|
||||
uint32_t myFreq[SCREEN_WIDTH+1]; // Frequency for XML file
|
||||
|
||||
uint16_t peakLevel; // Current maximum signal level
|
||||
uint16_t oldPeakLevel; // Old maximum signal level
|
||||
uint16_t peakIndex;
|
||||
uint16_t peakGain; // Actual gain at the peak (ie minimum gain)
|
||||
|
||||
static int old_settingAttenuate = -1000;
|
||||
static int old_settingPowerGrid = -1000;
|
||||
static int old_settingMax = -1;
|
||||
static int old_settingMin = -1;
|
||||
static double old_startFreq = -1;
|
||||
static double old_stopFreq = -1;
|
||||
static int ownrbw = 0;
|
||||
static int old_ownrbw = -1;
|
||||
static int vbw = 0;
|
||||
static int old_vbw = -1;
|
||||
static int old_settingAverage = -1;
|
||||
static int old_settingSpur = -100;
|
||||
static int old_bandwidth = 0;
|
||||
static int old_settingAttenuate = -1000;
|
||||
static int old_settingPowerGrid = -1000;
|
||||
static int old_settingMax = -1;
|
||||
static int old_settingMin = -1;
|
||||
static double old_startFreq = -1;
|
||||
static double old_stopFreq = -1;
|
||||
static int ownrbw = 0;
|
||||
static int old_ownrbw = -1;
|
||||
static int vbw = 0;
|
||||
static int old_vbw = -1;
|
||||
static int old_settingAverage = -1;
|
||||
static int old_settingSpur = -100;
|
||||
static int old_bandwidth = 0;
|
||||
|
||||
int16_t standalone = true;
|
||||
uint16_t spacing = 10000;
|
||||
@ -721,7 +741,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
|
||||
startAP (); // Start it up
|
||||
|
||||
#else // Connect to the router using SSID
|
||||
// and password defined in simpleSA.h
|
||||
// and password defined in TinySA.h
|
||||
|
||||
Serial.println ( "Connecting..." ); // Indicate trying to connect
|
||||
|
||||
@ -769,7 +789,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
|
||||
|
||||
// tft.println("Setup Complete");
|
||||
|
||||
Serial.printf ( "\nsimpleSA Version %s Initialization Complete\n", PROGRAM_VERSION );
|
||||
Serial.printf ( "\nTinySA Version %s Initialization Complete\n", PROGRAM_VERSION );
|
||||
|
||||
ShowMenu (); // Display the menu of commands on serial monitor
|
||||
|
||||
@ -990,7 +1010,7 @@ void init_sweep()
|
||||
img.setTextSize ( 1 );
|
||||
img.setColorDepth ( 16 );
|
||||
img.setAttribute ( PSRAM_ENABLE, false ); // Don't use the PSRAM on the WROVERs
|
||||
img.createSprite ( 2, GRID_HEIGHT + 1 ); // Only 2 columns wide
|
||||
img.createSprite ( 2, gridHeight + 1 ); // Only 2 columns wide
|
||||
|
||||
|
||||
/*
|
||||
@ -1331,16 +1351,18 @@ void RedrawHisto ()
|
||||
old_settingAverage = -1;
|
||||
old_settingSpur = -100;
|
||||
ClearDisplay();
|
||||
switch (tinySA_mode) {
|
||||
switch (tinySA_mode)
|
||||
{
|
||||
case BANDSCOPE:
|
||||
DisplayBandscopeInfo();
|
||||
break;
|
||||
|
||||
default:
|
||||
DisplayInfo();
|
||||
DrawFullCheckerBoard();
|
||||
break;
|
||||
|
||||
}
|
||||
DrawFullCheckerBoard();
|
||||
}
|
||||
|
||||
|
||||
@ -1386,7 +1408,7 @@ double fStop;
|
||||
sSprite.setTextColor ( DB_COLOR );
|
||||
sSprite.printf ( "%4i", setting.MaxGrid );
|
||||
|
||||
sSprite.setCursor ( 0, GRID_HEIGHT + Y_ORIGIN );
|
||||
sSprite.setCursor ( 0, gridHeight + yOrigin );
|
||||
sSprite.printf ( "%4i", setting.MinGrid );
|
||||
|
||||
sSprite.setTextColor ( WHITE );
|
||||
@ -1511,16 +1533,16 @@ double fStop;
|
||||
|
||||
if ( old_startFreq != fStart || old_stopFreq != fStop )
|
||||
{
|
||||
tft.fillRect ( X_ORIGIN, SCREEN_HEIGHT -
|
||||
CHAR_HEIGHT, SCREEN_WIDTH - X_ORIGIN - 1, SCREEN_HEIGHT - 1, BLACK );
|
||||
tft.fillRect ( xOrigin, SCREEN_HEIGHT -
|
||||
CHAR_HEIGHT, SCREEN_WIDTH - xOrigin - 1, SCREEN_HEIGHT - 1, BLACK );
|
||||
|
||||
// Show operating mode
|
||||
tft.setCursor ( X_ORIGIN + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( xOrigin + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setTextColor ( DB_COLOR );
|
||||
tft.printf ( "Mode:%s", modeText[setting.Mode] );
|
||||
tft.setTextColor ( WHITE );
|
||||
|
||||
tft.setCursor ( X_ORIGIN + 2, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( xOrigin + 2, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
|
||||
tft.print ( fStart );
|
||||
// tft.print( "MHz" );
|
||||
@ -1533,7 +1555,7 @@ double fStop;
|
||||
/*
|
||||
* Show the center frequency:
|
||||
*/
|
||||
tft.setCursor ( SCREEN_WIDTH / 2 - 40 + X_ORIGIN, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.setCursor ( SCREEN_WIDTH / 2 - 40 + xOrigin, SCREEN_HEIGHT - CHAR_HEIGHT );
|
||||
tft.print ( fCenter );
|
||||
tft.print ( "(MHz)" );
|
||||
|
||||
@ -1591,7 +1613,7 @@ double fStop;
|
||||
int x = tSprite.width () - 45;
|
||||
tSprite.setTextColor ( WHITE );
|
||||
|
||||
tSprite.pushSprite ( X_ORIGIN, 0 ); // Write sprite to the display
|
||||
tSprite.pushSprite ( xOrigin, 0 ); // Write sprite to the display
|
||||
|
||||
updateSidebar = false;
|
||||
} // End of "DisplayInfo"
|
||||
@ -1604,12 +1626,12 @@ double fStop;
|
||||
|
||||
void DrawFullCheckerBoard()
|
||||
{
|
||||
for ( int p=0; p<DISPLAY_POINTS; p++ )
|
||||
for ( int p=0; p<displayPoints; p++ )
|
||||
{
|
||||
DrawCheckerBoard ( p );
|
||||
|
||||
if ( p > 0 )
|
||||
img.pushSprite( X_ORIGIN+p-1, Y_ORIGIN );
|
||||
img.pushSprite( xOrigin+p-1, yOrigin );
|
||||
}
|
||||
|
||||
// Serial.println ( "DrawFullCheckerBoard" );
|
||||
@ -1620,7 +1642,7 @@ void DrawFullCheckerBoard()
|
||||
* "DrawCheckerBoard" - Paints the grid. It now uses a sprite so no need to
|
||||
* erase the old grid, just draw a new one.
|
||||
*
|
||||
* The sprite is two pixels wide, and the image from the previous data point
|
||||
* The img sprite is two pixels wide, and the image from the previous data point
|
||||
* is scrolled and then new data point drawn. The data from last is scrolled
|
||||
* so any line from before is retained.
|
||||
*/
|
||||
@ -1633,24 +1655,24 @@ void DrawCheckerBoard ( int x )
|
||||
if ( x == 1 )
|
||||
{
|
||||
img.fillSprite ( BLACK ); // Clear the sprite
|
||||
img.drawFastVLine ( 0, 0, GRID_HEIGHT, DARKGREY ); // Draw vertical line at edge
|
||||
img.drawFastVLine ( 0, 0, gridHeight, DARKGREY ); // Draw vertical line at edge
|
||||
|
||||
for ( int y=0; y <= Y_GRID; y++ )
|
||||
img.drawPixel ( 1, y*DELTA_Y, DARKGREY ); // Draw the horizontal grid lines
|
||||
for ( int y=0; y <= yGrid; y++ )
|
||||
img.drawPixel ( 1, y*yDelta, DARKGREY ); // Draw the horizontal grid lines
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
img.setScrollRect ( 0, 0, 2,GRID_HEIGHT, BLACK ); // Scroll the whole sprite
|
||||
img.setScrollRect ( 0, 0, 2,gridHeight, BLACK ); // Scroll the whole sprite
|
||||
img.scroll ( -1, 0 );
|
||||
int lastStep = x - 1;
|
||||
|
||||
if (( x % DELTA_X ) == 0 ) // Need a vertical line here
|
||||
img.drawFastVLine ( 1, 0, GRID_HEIGHT, DARKGREY );
|
||||
if (( x % xDelta ) == 0 ) // Need a vertical line here
|
||||
img.drawFastVLine ( 1, 0, gridHeight, DARKGREY );
|
||||
|
||||
else
|
||||
for ( int y = 0; y <= Y_GRID; y++ )
|
||||
img.drawPixel ( 1, y * DELTA_Y, DARKGREY ); // Draw the horizontal grid lines
|
||||
for ( int y = 0; y <= yGrid; y++ )
|
||||
img.drawPixel ( 1, y * yDelta, DARKGREY ); // Draw the horizontal grid lines
|
||||
}
|
||||
}
|
||||
|
||||
@ -1665,15 +1687,15 @@ uint16_t rssiToImgY ( uint8_t rSSI )
|
||||
int delta = setting.MaxGrid - setting.MinGrid;
|
||||
double y = rssiTodBm ( rSSI );
|
||||
|
||||
y = ( y - setting.MinGrid ) * GRID_HEIGHT / delta;
|
||||
y = ( y - setting.MinGrid ) * gridHeight / delta;
|
||||
|
||||
if ( y >= GRID_HEIGHT )
|
||||
y = GRID_HEIGHT-1;
|
||||
if ( y >= gridHeight )
|
||||
y = gridHeight-1;
|
||||
|
||||
if ( y < 0 )
|
||||
y = 0;
|
||||
|
||||
return GRID_HEIGHT - 1 - (int) y;
|
||||
return gridHeight - 1 - (int) y;
|
||||
}
|
||||
|
||||
|
||||
@ -1703,26 +1725,26 @@ void DisplayPoint ( uint8_t* data, int i, int color )
|
||||
int lastPoint = i - 1;
|
||||
int delta = setting.MaxGrid - setting.MinGrid;
|
||||
double f0 = (( data[i] / 2.0 + setting.Attenuate ) - 120.0 ) + setting.LevelOffset; // Current point
|
||||
f0 = ( f0 - setting.MinGrid ) * GRID_HEIGHT / delta;
|
||||
f0 = ( f0 - setting.MinGrid ) * gridHeight / delta;
|
||||
|
||||
if ( f0 >= GRID_HEIGHT )
|
||||
f0 = GRID_HEIGHT-1;
|
||||
if ( f0 >= gridHeight )
|
||||
f0 = gridHeight-1;
|
||||
|
||||
if ( f0 < 0 )
|
||||
f0 = 0;
|
||||
|
||||
double f1 = (( data[lastPoint] / 2.0 + setting.Attenuate ) - 120.0) + setting.LevelOffset; // Previous point
|
||||
|
||||
f1 = ( f1 - setting.MinGrid ) * GRID_HEIGHT / delta;
|
||||
f1 = ( f1 - setting.MinGrid ) * gridHeight / delta;
|
||||
|
||||
if ( f1 >= GRID_HEIGHT )
|
||||
f1 = GRID_HEIGHT-1;
|
||||
if ( f1 >= gridHeight )
|
||||
f1 = gridHeight-1;
|
||||
|
||||
if ( f1 < 0 )
|
||||
f1 = 0;
|
||||
|
||||
int Y0 = GRID_HEIGHT - 1 - (int) f0;
|
||||
int Y1 = GRID_HEIGHT - 1 - (int) f1;
|
||||
int Y0 = gridHeight - 1 - (int) f0;
|
||||
int Y1 = gridHeight - 1 - (int) f1;
|
||||
|
||||
img.drawLine ( 0, Y1, 1, Y0, color );
|
||||
}
|
||||
@ -1743,26 +1765,26 @@ void displayGainPoint ( unsigned char *data, int i, int color )
|
||||
|
||||
// Serial.printf ( "gain %f \n", f );
|
||||
|
||||
f0 = ( f0 ) * GRID_HEIGHT / delta;
|
||||
f0 = ( f0 ) * gridHeight / delta;
|
||||
|
||||
if ( f0 >= GRID_HEIGHT )
|
||||
f0 = GRID_HEIGHT - 1;
|
||||
if ( f0 >= gridHeight )
|
||||
f0 = gridHeight - 1;
|
||||
|
||||
if ( f0 < 0 )
|
||||
f0 = 0;
|
||||
|
||||
double f1 = ( data[lastPoint] );
|
||||
|
||||
f1 = ( f1 ) * GRID_HEIGHT / delta;
|
||||
f1 = ( f1 ) * gridHeight / delta;
|
||||
|
||||
if ( f1 >= GRID_HEIGHT )
|
||||
f1 = GRID_HEIGHT - 1;
|
||||
if ( f1 >= gridHeight )
|
||||
f1 = gridHeight - 1;
|
||||
|
||||
if ( f1 < 0 )
|
||||
f1 = 0;
|
||||
|
||||
int Y0 = GRID_HEIGHT - 1 - (int) f0;
|
||||
int Y1 = GRID_HEIGHT - 1 - (int) f1;
|
||||
int Y0 = gridHeight - 1 - (int) f0;
|
||||
int Y1 = gridHeight - 1 - (int) f1;
|
||||
|
||||
img.drawLine ( 0, Y1, 1, Y0, color );
|
||||
}
|
||||
@ -1781,7 +1803,7 @@ void CreateGainScale ()
|
||||
gainScaleSprite.deleteSprite();
|
||||
gainScaleSprite.setAttribute ( PSRAM_ENABLE, false );
|
||||
gainScaleSprite.setColorDepth ( 16 ); // Using 16 bit (RGB565) colors
|
||||
gainScaleSprite.createSprite(CHAR_WIDTH * 2, GRID_HEIGHT);
|
||||
gainScaleSprite.createSprite(CHAR_WIDTH * 2, gridHeight);
|
||||
gainScaleSprite.fillSprite(BLACK);
|
||||
gainScaleSprite.setPivot( 0, 0 );
|
||||
gainScaleSprite.setTextSize ( 1 );
|
||||
@ -1798,7 +1820,7 @@ void CreateGainScale ()
|
||||
|
||||
for ( int i = 0; i < 5; i++ )
|
||||
{
|
||||
gainScaleSprite.setCursor ( 0, 2 + ( DELTA_Y * i * 2 ));
|
||||
gainScaleSprite.setCursor ( 0, 2 + ( yDelta * i * 2 ));
|
||||
gainScaleSprite.print ( 50 - ( i * 10 ));
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,23 @@
|
||||
|
||||
|
||||
#include "simpleSA_wifi.h" // WiFi definitions
|
||||
#include "Si4432.h" // Si4432 definitions
|
||||
#include "Cmd.h" // Command processing functions
|
||||
#include "si4432.h" // Si4432 definitions
|
||||
#include "cmd.h" // Command processing functions
|
||||
|
||||
/*
|
||||
* Variables to determine size of grid and waterfall
|
||||
* In Bandscope mode the grid is reduced. In future it may be possible to add
|
||||
* a waterfall to the main sweep, but not yet
|
||||
*/
|
||||
extern uint16_t gridHeight;
|
||||
extern uint16_t gridWidth;
|
||||
extern uint16_t yGrid; // no of grid divisions
|
||||
extern uint16_t yDelta; // no of points/division
|
||||
extern uint16_t xGrid;
|
||||
extern uint16_t displayPoints;
|
||||
extern uint16_t xDelta;
|
||||
extern uint16_t waterfallHeight;
|
||||
|
||||
|
||||
extern int bpfCount; // Number of elements in the bandpassFilters array
|
||||
extern int updateSidebar; // Flag to indicate no of clients has changed
|
||||
@ -376,7 +391,7 @@ void onGetScan ( AsyncWebServerRequest *request )
|
||||
response->print ( "<?xml version=\"1.0\" encoding=\"utf-16\"?>" );
|
||||
response->println ( "<Points>" );
|
||||
|
||||
for( int i = 0; i < DISPLAY_POINTS-1; i++ ) // For each data point
|
||||
for( int i = 0; i < displayPoints-1; i++ ) // For each data point
|
||||
{
|
||||
// Serial.printf ( "<Point F=\"%i\" RSSI=\"%i\"/> %i\n",myFreq[i], myData[i], i );
|
||||
response->printf ( "<P F=\"%i\" R=\"%i\"/>\n", myFreq[i], myData[i] );
|
||||
@ -394,8 +409,8 @@ void onGetScan ( AsyncWebServerRequest *request )
|
||||
|
||||
void onGetGainSweep ( AsyncWebServerRequest *request )
|
||||
{
|
||||
size_t bufferSize = JSON_ARRAY_SIZE ( DISPLAY_POINTS )
|
||||
+ JSON_OBJECT_SIZE ( 1 ) + DISPLAY_POINTS * JSON_OBJECT_SIZE ( 2 );
|
||||
size_t bufferSize = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
||||
+ JSON_OBJECT_SIZE ( 1 ) + SCREEN_WIDTH * JSON_OBJECT_SIZE ( 2 );
|
||||
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse ( false, bufferSize );
|
||||
// response->addHeader ( "Server","ESP Async Web Server" );
|
||||
@ -407,7 +422,7 @@ void onGetGainSweep ( AsyncWebServerRequest *request )
|
||||
* Add the objects to the array
|
||||
*/
|
||||
|
||||
for ( int i = 0; i < DISPLAY_POINTS; i++ ) // For each data point
|
||||
for ( int i = 0; i < displayPoints; i++ ) // For each data point
|
||||
{
|
||||
JsonObject dataPoint = gainPoints.createNestedObject(); // Add an object to the array
|
||||
dataPoint["x"] = myFreq[i]/1000000.0; // set the x(frequency) value
|
||||
@ -426,14 +441,14 @@ void onGetGainSweep ( AsyncWebServerRequest *request )
|
||||
|
||||
void onGetSweep ( AsyncWebServerRequest *request )
|
||||
{
|
||||
size_t bufferSize = JSON_ARRAY_SIZE ( DISPLAY_POINTS )
|
||||
+ JSON_OBJECT_SIZE ( 14 ) + DISPLAY_POINTS * JSON_OBJECT_SIZE ( 2 );
|
||||
size_t bufferSize = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
||||
+ JSON_OBJECT_SIZE ( 14 ) + SCREEN_WIDTH * JSON_OBJECT_SIZE ( 2 );
|
||||
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse ( false, bufferSize );
|
||||
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["dispPoints"] = DISPLAY_POINTS;
|
||||
root["dispPoints"] = displayPoints;
|
||||
root["start"] = setting.ScanStart / 1000.0;
|
||||
root["stop"] = setting.ScanStop / 1000.0;
|
||||
root["IF"] = setting.IF_Freq / 1000000.0;
|
||||
@ -454,7 +469,7 @@ void onGetSweep ( AsyncWebServerRequest *request )
|
||||
JsonArray Points = root.createNestedArray ( "Points" ); // Add Points array
|
||||
|
||||
|
||||
for ( int i = 0; i < DISPLAY_POINTS; i++ ) //For each data point
|
||||
for ( int i = 0; i < displayPoints; i++ ) //For each data point
|
||||
{
|
||||
JsonObject dataPoint = Points.createNestedObject(); // add an object to the array
|
||||
dataPoint["x"] = myFreq[i]/1000000.0; // set the x(frequency) value
|
||||
@ -477,7 +492,7 @@ void onGetSettings (AsyncWebServerRequest *request)
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["mType"] = "Settings";
|
||||
root["dispPoints"] = DISPLAY_POINTS;
|
||||
root["dispPoints"] = displayPoints;
|
||||
root["start"] = setting.ScanStart / 1000.0;
|
||||
root["stop"] = setting.ScanStop / 1000.0;
|
||||
root["IF"] = setting.IF_Freq / 1000000.0;
|
||||
@ -507,12 +522,12 @@ void onGetSettings (AsyncWebServerRequest *request)
|
||||
*/
|
||||
void pushSettings ()
|
||||
{
|
||||
size_t capacity = JSON_ARRAY_SIZE ( DISPLAY_POINTS )
|
||||
+ DISPLAY_POINTS*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
||||
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||
|
||||
jsonDocument["mType"] = "Settings";
|
||||
jsonDocument["dispPoints"] = DISPLAY_POINTS;
|
||||
jsonDocument["dispPoints"] = displayPoints;
|
||||
jsonDocument["start"] = setting.ScanStart / 1000.0;
|
||||
jsonDocument["stop"] = setting.ScanStop / 1000.0;
|
||||
jsonDocument["IF"] = setting.IF_Freq / 1000000.0;
|
||||
@ -551,12 +566,12 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
||||
*/
|
||||
void pushIFSweepSettings ()
|
||||
{
|
||||
size_t capacity = JSON_ARRAY_SIZE ( DISPLAY_POINTS )
|
||||
+ DISPLAY_POINTS*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
||||
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||
|
||||
jsonDocument["mType"] = "Settings";
|
||||
jsonDocument["dispPoints"] = DISPLAY_POINTS;
|
||||
jsonDocument["dispPoints"] = displayPoints;
|
||||
jsonDocument["start"] = startFreq_IF / 1000.0;
|
||||
jsonDocument["stop"] = stopFreq_IF / 1000.0;
|
||||
jsonDocument["IF"] = sigFreq_IF / 1000000.0;
|
||||
@ -594,8 +609,8 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
||||
*/
|
||||
void pushBandscopeSettings ()
|
||||
{
|
||||
size_t capacity = JSON_ARRAY_SIZE ( DISPLAY_POINTS )
|
||||
+ DISPLAY_POINTS*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
||||
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
|
||||
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||
|
||||
jsonDocument["mType"] = "Settings";
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "Arduino.h" // Basic Arduino definitions
|
||||
#include "simpleSA.h" // Program definitions
|
||||
#include "Si4432.h" // RF module definitions
|
||||
#include "si4432.h" // RF module definitions
|
||||
|
||||
#include <WiFi.h> // WiFi library
|
||||
#include <AsyncTCP.h>
|
||||
@ -71,11 +71,11 @@
|
||||
|
||||
extern settings_t setting;
|
||||
|
||||
extern uint8_t myData[DISPLAY_POINTS+1];
|
||||
extern uint8_t myStorage[DISPLAY_POINTS+1];
|
||||
extern uint8_t myActual[DISPLAY_POINTS+1];
|
||||
extern uint8_t myGain[DISPLAY_POINTS+1]; // M0WID addition to record preamp gain
|
||||
extern uint32_t myFreq[DISPLAY_POINTS+1]; // M0WID addition to store frequency for XML file
|
||||
extern uint8_t myData[SCREEN_WIDTH+1];
|
||||
extern uint8_t myStorage[SCREEN_WIDTH+1];
|
||||
extern uint8_t myActual[SCREEN_WIDTH+1];
|
||||
extern uint8_t myGain[SCREEN_WIDTH+1]; // M0WID addition to record preamp gain
|
||||
extern uint32_t myFreq[SCREEN_WIDTH+1]; // M0WID addition to store frequency for XML file
|
||||
|
||||
|
||||
extern WebSocketsServer webSocket; // Initiated in TinySA.ino
|
||||
|
8
ui.cpp
8
ui.cpp
@ -30,12 +30,12 @@
|
||||
#include <SPI.h> // SPI Bus handling library
|
||||
#include "simpleSA.h"
|
||||
#include "ui.h" // User interface definitions and prototypes
|
||||
#include "Cmd.h" // Command processing functions
|
||||
#include "cmd.h" // Command processing functions
|
||||
#include "preferences.h" // Save/recall functions
|
||||
#include <TFT_eSPI.h> // Display/Touch Screen header file
|
||||
#include "Menu.h" // "Menuitem" class definition
|
||||
#include "Marker.h" // Marker class definition
|
||||
#include "Si4432.h" // Si4432 class definition
|
||||
#include "menu.h" // "Menuitem" class definition
|
||||
#include "marker.h" // Marker class definition
|
||||
#include "si4432.h" // Si4432 class definition
|
||||
|
||||
|
||||
extern Marker marker[MARKER_COUNT]; // Array of markers
|
||||
|
Loading…
Reference in New Issue
Block a user