Merge pull request #19 from DPWilde/WebModeSelect

Web mode select
This commit is contained in:
DPWilde 2020-10-06 23:11:46 +01:00 committed by GitHub
commit f36f478363
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 2299 additions and 208 deletions

View File

@ -237,14 +237,8 @@ static uint16_t chunkIndex;
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
{
jsonDocument.clear ();
chunkIndex = 0;
jsonDocument["PreAmp"] = setting.PreampGain;
jsonDocument["mType"] = "chunkSweep";
jsonDocument["StartIndex"] = 0;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
initChunkSweepDoc (autoSweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
@ -395,12 +389,8 @@ static uint16_t chunkIndex;
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
{
chunkIndex = 0;
jsonDocument.clear();
jsonDocument["mType"] = "chunkSweep";
jsonDocument["StartIndex"] = autoSweepStep;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
initChunkSweepDoc (autoSweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
}

View File

@ -120,6 +120,7 @@ static uint16_t chunkIndex;
} // initSweep || changedSetting
autoSweepStep = 0; // Set the step counter to zero
sweepStep = 0;
autoSweepFreq = startFreq_IF; // Set the start frequency.
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
@ -142,24 +143,16 @@ static uint16_t chunkIndex;
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);
initChunkSweepDoc (sweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
else
jsonDocInitialised = false;
#endif // #ifdef USE_WIFI
sweepStep = 0;
startFreq = startFreq_IF + sigFreq_IF; // Start freq for the LO
stopFreq = stopFreq_IF + sigFreq_IF; // Stop freq for the LO
@ -315,12 +308,8 @@ static uint16_t chunkIndex;
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
initChunkSweepDoc (sweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
}

View File

@ -126,6 +126,7 @@ static uint16_t chunkIndex;
} // initSweep || changedSetting
autoSweepStep = 0; // Set the step counter to zero
sweepStep = 0;
autoSweepFreq = startFreq_RX; // Set the start frequency.
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
@ -148,24 +149,16 @@ static uint16_t chunkIndex;
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
{
jsonDocument.clear ();
chunkIndex = 0;
jsonDocument["PreAmp"] = setting.PreampGain;
jsonDocument["mType"] = "chunkSweep";
jsonDocument["StartIndex"] = 0;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
initChunkSweepDoc (sweepStep);
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
@ -322,12 +315,8 @@ static uint16_t chunkIndex;
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
initChunkSweepDoc (sweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
}

View File

@ -107,6 +107,11 @@ void initSigLow()
oldFreq = 0; // Force write of frequency on first loop
#ifdef USE_WIFI
if ( numberOfWebsocketClients > 0 )
pushSigGenSettings ();
#endif
}
@ -119,6 +124,10 @@ void initSigLow()
void doSigGenLow ()
{
static uint32_t oldIF; // to store the current IF
static uint16_t oldSigGenOutputOn;
float p; // temporary variable for slider percent
static uint16_t sliderRange = ATTENUATOR_RANGE + RX_SI4432_MAX_DRIVE * 3;
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
@ -127,6 +136,29 @@ void doSigGenLow ()
showUpDownButtons = 1;
#endif
if (changedSetting) {
// calculate required drive and attenuator settings
// keep drive as high as possible so nasties are attenuated
uint16_t sgRXDrive = RX_SI4432_MAX_DRIVE;
uint16_t attenuation = sigGenSetting.Calibration - sigGenSetting.Power;
if (attenuation > ATTENUATOR_RANGE )
{
int16_t diff = attenuation - ATTENUATOR_RANGE;
sgRXDrive = RX_SI4432_MAX_DRIVE - (int16_t)( (diff-1)/3 ) - 1 ;
attenuation = ATTENUATOR_RANGE - 2 + (diff-1)%3;
}
SetSGRxDrive(sgRXDrive);
att.SetAtten(attenuation);
Serial.printf("sigGenLow - rxDrive set to %i, attenuation set to %i, cal is %i\n", sgRXDrive, attenuation, sigGenSetting.Calibration);
#ifdef USE_WIFI
if ( numberOfWebsocketClients > 0 )
pushSigGenSettings ();
#endif
changedSetting = false;
}
// Get current touch state and coordinates
boolean pressed = tft.getTouch(&t_x, &t_y); // Just uses standard TFT_eSPI function as not bothered about speed
@ -154,6 +186,7 @@ void doSigGenLow ()
case 5:
case 6:
incrementFreq( pow(10, 8-b) );
changedSetting=true;
break;
case 7: // Decrement buttons
@ -164,6 +197,7 @@ void doSigGenLow ()
case 12:
case 13:
decrementFreq( pow(10, 15-b) );
changedSetting=true;
break;
case 14: // Return to SAlo mode
@ -172,21 +206,6 @@ void doSigGenLow ()
case 15: // toggle the output on/off
sigGenOutputOn = !sigGenOutputOn;
if (sigGenOutputOn) {
SetRX(3); // both LO and RX in transmit. Output levels have been set in the init function
key[b].drawButton(true, sig_keys[b].activeText);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_GREEN, SIG_BACKGROUND_COLOR );
tft.print(" ON");
} else {
SetRX(1); // Both in receive
key[b].drawButton(false, sig_keys[b].text);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_WHITE, SIG_BACKGROUND_COLOR );
tft.print("OFF");
}
break;
case 16: // launch menu
@ -224,6 +243,33 @@ void doSigGenLow ()
return;
}
}
// check if state changed - can change from command or from wifi
switch (b) {
case 15: // On/Off button
if (oldSigGenOutputOn != sigGenOutputOn)
{
if (sigGenOutputOn) {
SetRX(3); // both LO and RX in transmit. Output levels have been set in the init function
key[b].drawButton(true, sig_keys[b].activeText);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_GREEN, SIG_BACKGROUND_COLOR );
tft.print(" ON");
} else {
SetRX(1); // Both in receive
key[b].drawButton(false, sig_keys[b].text);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_WHITE, SIG_BACKGROUND_COLOR );
tft.print("OFF");
}
changedSetting = true;
}
break;
} // on of state change switch
} // end of keys loop
@ -232,12 +278,15 @@ void doSigGenLow ()
// Check if slider touched
if ( sliderPressed( pressed, t_x, t_y) )
{
float p = sliderPercent( t_x ); // position of slider in %
float pwr = p * (ATTENUATOR_RANGE)/100.0 + sigGenSetting.Calibration - ATTENUATOR_RANGE;
p = sliderPercent( t_x ); // position of slider in %
float pwr = p * (sliderRange)/100.0 + sigGenSetting.Calibration - sliderRange;
drawSlider ( SLIDER_X, SLIDER_Y, p, pwr, "dBm" );
att.SetAtten ( ( 100.0 - p ) / 100.0 * ATTENUATOR_RANGE ); // set attenuator to give required output
sigGenSetting.Power = pwr;
changedSetting = true;
} else {
p = ( sigGenSetting.Power - (sigGenSetting.Calibration - sliderRange) ) * 100.0 / sliderRange;
drawSlider ( SLIDER_X, SLIDER_Y, p, sigGenSetting.Power, "dBm" );
}
@ -266,12 +315,15 @@ void doSigGenLow ()
if (sigGenOutputOn)
{
delayMicroseconds(300);
SetRX(3);
SetRX(3); // both LO and RX in tx mode
}
changedSetting = true;
}
oldFreq = sigGenSetting.Frequency;
oldIF = setting.IF_Freq;
oldSigGenOutputOn = sigGenOutputOn;
}

View File

@ -73,6 +73,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
static uint32_t tgIF; // Track gen IF - SA IF plus any offset if both SI4432 defined
@ -181,10 +182,20 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
tg_lo.RxMode();
#endif
#if defined(SI_TG_IF_CS) && defined(SI_TG_LO_CS)
if (tgLO_OK && tgIF_OK && (trackGenSetting.Mode == 2) ) // tracking gen as signal generator
{
tg_if.SetFrequency ( setting.IF_Freq + trackGenSetting.Offset );
tg_lo.SetFrequency ( setting.IF_Freq + trackGenSetting.Offset + trackGenSetting.Frequency );
tg_lo.TxMode ( trackGenSetting.LO_Drive ); // Set tracking generator LO on
tg_if.TxMode ( trackGenSetting.IF_Drive ); // Set tracking generator IF on
}
#endif
} // initSweep || changedSetting
autoSweepStep = 0; // Set the step counter to zero
sweepStep = 0;
autoSweepFreq = setting.ScanStart; // Set the start frequency.
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
@ -207,6 +218,12 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
tempIF = offsetIF;
}
// track gen IF follows LO if only one SI4432, otherwise its offset by an amount to reduce blow by
if (tgLO_OK)
tgIF = tempIF + trackGenSetting.Offset;
else
tgIF = tempIF;
spurToggle = !spurToggle;
@ -225,7 +242,7 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
#ifdef SI_TG_IF_CS
if (tgIF_OK && (trackGenSetting.Mode == 1) )
tg_if.SetFrequency ( tempIF + trackGenSetting.Offset ); // Set tracking generator IF for the sweep
tg_if.SetFrequency ( tgIF ); // Set tracking generator IF for the sweep
#endif
}
@ -233,13 +250,11 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
#ifdef SI_TG_LO_CS
if (tgLO_OK && (trackGenSetting.Mode == 1) )
tg_lo.SetFrequency ( tempIF + autoSweepFreq + trackGenSetting.Offset ); // Set tracking generator LO
tg_lo.SetFrequency ( tgIF + autoSweepFreq ); // Set tracking generator LO
#endif
setFreqMicros = micros(); // Store the time the frequency was changed
// if (trackGenSetting.Mode == 1) // debug
// Serial.printf("tglo start %i at %i\n", tg_lo.GetFrequency(), setFreqMicros);
/*
* Actual frequency in the SI4432 is rounded and is limited by the possible resolution
@ -253,22 +268,15 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
{
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);
initChunkSweepDoc (sweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
else
jsonDocInitialised = false;
#endif // #ifdef USE_WIFI
sweepStep = 0;
startFreq = setting.ScanStart + tempIF; // Start freq for the LO
stopFreq = setting.ScanStop + tempIF; // Stop freq for the LO
@ -438,7 +446,11 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
{
Serial.println("webSocketTimeout");
Serial.println(wsBuffer);
numberOfWebsocketClients = 0;
websocketFailCount++;
if (websocketFailCount > 2)
numberOfWebsocketClients = 0;
} else {
websocketFailCount = 0; // reset if OK
}
// Serial.print("j");
}
@ -450,12 +462,8 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
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
initChunkSweepDoc (sweepStep);
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
jsonDocInitialised = true;
}
}

177
cmd.cpp
View File

@ -106,6 +106,7 @@ extern uint32_t colourTest;
extern Marker marker[MARKER_COUNT]; // Array of marker objects
extern uint16_t sigGenOutputOn; // signal generator state - 0 = off, 1 = on
/*
* Functions still in the main program file. Maybe some need to move here?
@ -183,6 +184,13 @@ extern uint8_t dBmToRSSI ( double dBm );
{ "RXSWEEP", MSG_RX_SWEEP }, // Set RX Sweep Mode
{ "RXSIGNAL", MSG_RXSIGNAL }, // IF sweep signal frequency
{ "EXTGAIN", MSG_EXTGAIN }, // External gain or attenuation
{ "SGON", MSG_SGON }, // turn on signal generator output
{ "SGOFF", MSG_SGOFF }, // turn off signal generator output
{ "SGFREQ", MSG_SGFREQ }, // Set Signal Generator Frequency
{ "TRACKON", MSG_TGON }, // turn on tracking generator output
{ "TRACKOFF", MSG_TGOFF }, // turn off tracking generator output
{ "TRACKSIG", MSG_TGSIG }, // turn off tracking generator output
{ "TGFREQ", MSG_TGFREQ }, // Set Track gen freq for sig gen mode
{ "", MSG_NONE } // Unrecognized command
};
@ -196,7 +204,7 @@ int msgCount = ELEMENTS ( msgTable);
void ShowMenu ()
{
Serial.printf ( "\nTiny Spectrum Analyzer Version %s - User Commands:\n\n", PROGRAM_VERSION );
Serial.printf ( "\nsimpleSA Spectrum Analyzer %s - User Commands:\n\n", PROGRAM_VERSION );
Serial.println ( "Sweep Settings:\n" );
Serial.print ( " START.........Sweep start frequency, currently: " );
@ -248,25 +256,53 @@ void ShowMenu ()
Serial.printf ( " WFMIN.........Set the minimum RSSI level for waterfall colouring: %i\n", setting.WaterfallMin );
Serial.printf ( " WFGAIN........Set the gain for waterfall colouring: %d\n", setting.WaterfallGain );
Serial.println ( "\nOther Commands:\n" );
Serial.print ( " DRIVE.........Local oscillator drive level [0 to 7]; currently: " );
Serial.println ( setting.Drive );
Serial.println ( "\nSignal Generator Commands:\n" );
Serial.println ( " SGON..........Turn on signal generator output" );
Serial.print ( " SGOFF.........Turn off signal generator output; currently " );
Serial.println ( sigGenOutputOn );
Serial.print ( " SGFREQ........Signal Generator frequency, currently: " );
Serial.println ( FormatFrequency ( sigGenSetting.Frequency ));
Serial.print ( " SGLODRIVE.....Local oscillator drive level in signal generator mode [0 to 7]; currently: " );
Serial.println ( sigGenSetting.LO_Drive );
Serial.print ( " SGRXDRIVE.....Local oscillator drive level in signal generator mode [0 to 7]; currently: " );
Serial.print ( " SGRXDRIVE.....RX SI4432 oscillator drive level in signal generator mode [0 to ");
Serial.print ( RX_SI4432_MAX_DRIVE );
Serial.print ( "]; currently: " );
Serial.println ( sigGenSetting.RX_Drive );
#ifdef SI_TG_IF_CS
Serial.println ( "\nTracking Generator Commands:\n" );
Serial.println ( " TRACKON.......Turn on tracking generator output" );
#ifdef SI_TG_LO_CS
Serial.println ( " TRACKSIG......Turn on tracking generator signal generator output" );
#endif
Serial.print ( " TRACKOFF......Turn off tracking generator output; currently " );
Serial.println ( trackGenSetting.Mode );
#ifdef SI_TG_LO_CS
Serial.print ( " TGLODRIVE.....Local oscillator drive level in tracking generator mode [0 to 7]; currently: " );
Serial.println ( trackGenSetting.LO_Drive );
#endif
Serial.print ( " TGIFDRIVE.....Local oscillator drive level in tracking generator mode [0 to 7]; currently: " );
Serial.println ( trackGenSetting.IF_Drive );
#ifdef SI_TG_LO_CS
Serial.print ( " TGOFFSET......Tracking generator offset from SA IF; currently: " );
Serial.println ( trackGenSetting.Offset );
Serial.print ( " TGFREQ........Tracking generator signal generator frequency; currently: " );
Serial.println ( trackGenSetting.Frequency );
#endif
#endif
Serial.println ( "\nOther Commands:\n" );
Serial.print ( " DRIVE.........Local oscillator drive level [0 to 7]; currently: " );
Serial.println ( setting.Drive );
Serial.println ( " SAVE .........Save the current scan configuration [0 to 4]" );
@ -759,6 +795,29 @@ uint8_t reg69; // Ditto
return true;
/*
* Signal Generator On/Off commands
*
*/
case MSG_SGON:
SetSGState(1);
return true;
case MSG_SGOFF:
SetSGState(0);
return true;
case MSG_SGFREQ:
if ( dataLen != 0 ) // Frequency specified?
{
freq1 = ParseFrequency ( dataBuff ); // Yes, get new frequency
SetSGFreq (freq1);
}
Serial.printf ( "Signal Generator frequency: %i\n", FormatFrequency ( freq1 ));
return true;
/*
* The "SGLODRIVE" command sets the local oscillator "drive" level in signal generator mode.
@ -769,7 +828,7 @@ uint8_t reg69; // Ditto
tempValue = atoi ( dataBuff ); // Yes, convert to a number
if (( tempValue < MIN_DRIVE ) || ( tempValue > MAX_DRIVE ))
Serial.printf ( "Invalid drive specification: %d\n", tempValue );
Serial.printf ( "Invalid LO drive: %d\n", tempValue );
else // Set the transmitter drive level
SetSGLoDrive ( tempValue ); // "SetSGLoDrive" saves the settings
}
@ -781,17 +840,17 @@ uint8_t reg69; // Ditto
return true;
/*
* The "SGLODRIVE" command sets the receiver (IF) oscillator "drive" level in signal generator mode.
* The "SGRXDRIVE" command sets the receiver (IF) oscillator "drive" level in signal generator mode.
*/
case MSG_SG_RX_DRIVE:
if ( dataLen != 0 ) // Drive level specified?
{
tempValue = atoi ( dataBuff ); // Yes, convert to a number
if (( tempValue < MIN_DRIVE ) || ( tempValue > MAX_DRIVE ))
Serial.printf ( "Invalid drive specification: %d\n", tempValue );
if (( tempValue < MIN_DRIVE ) || ( tempValue > RX_SI4432_MAX_DRIVE ))
Serial.printf ( "Invalid RX drive: %d - (%d-%d)\n", tempValue, MIN_DRIVE, RX_SI4432_MAX_DRIVE );
else // Set the transmitter drive level
SetSGRxDrive ( tempValue ); // "SetTGRxDrive" saves the settings
SetSGRxDrive ( tempValue ); // "SetSGRxDrive" saves the settings
}
Serial.printf ( "SigGen RX Drive: %d (+%udBm)\n", sigGenSetting.RX_Drive, driveLevel[sigGenSetting.RX_Drive] );
@ -800,8 +859,26 @@ uint8_t reg69; // Ditto
return true;
/*
* Tracking Generator On/Off commands
*
*/
case MSG_TGON:
SetTracking(1);
return true;
case MSG_TGOFF:
SetTracking(0);
return true;
#ifdef SI_TG_LO_CS
case MSG_TGSIG:
SetTracking(2);
return true;
/*
* The "TGLODRIVE" command sets the local oscillator "drive" level in tracking generator mode.
* (only valid if two SI4432 used for the tracking generator)
@ -1578,6 +1655,14 @@ uint8_t reg69; // Ditto
Serial.printf ( "Tracking Generator IF offset: %i\n", trackGenSetting.Offset ); // sort out signed version of format frequency!!!!!!!!!!!!!!!!!!!
return true;
case MSG_TGFREQ:
if ( dataLen != 0 ) // Frequency specified?
{
freq1 = ParseFrequency ( dataBuff ); // Yes, get new frequency
SetTGFreq (freq1);
}
Serial.printf ( "Tracking Signal Generator frequency: %i\n", FormatFrequency ( trackGenSetting.Frequency ));
return true;
/*
@ -2295,6 +2380,7 @@ void RequestSetPowerLevel ( float o )
/*
* "SetPowerLevel"
* Adjusts displayed power to match the actual input signal power - calibration function
*/
void SetPowerLevel ( double o )
@ -2433,6 +2519,32 @@ int oldLevel = setting.Drive;
}
/* Set SGFreq sets the signal generator Frequency
* Signal generator frequency may change frequently, so don't save the setting
* Settings are saved when leaving the mode
* parameter is in Hz
*/
bool SetSGFreq (uint32_t f)
{
if ( ( f >= MIN_SIGLO_FREQ ) && ( f <= MAX_SIGLO_FREQ ) )
{
sigGenSetting.Frequency = f;
return true;
}
else
return false;
}
/*
* Sig gen state is not saved - always want to start in off state
*/
void SetSGState (uint16_t s)
{
sigGenOutputOn = s;
}
/*
* "SetSGLoDrive" sets the transmitter max output level in signal generator mode.
*
@ -2479,13 +2591,16 @@ int oldLevel = sigGenSetting.LO_Drive;
* 1 => +2dBm 5 => +14dBm
* 2 => +5dBm 6 => +17dBm
* 3 => +8dBm 7 => +20dBm
* Note the power limits of the B3555 SAW filter is 10dBm
* RX_SI4432_MAX_DRIVE is set in my_SA.h to suit the attenuator pad and losses
* in your build.
*/
void SetSGRxDrive ( uint8_t level )
{
int oldLevel = sigGenSetting.RX_Drive;
if (( level < 0 ) || ( level > 7 ))
if (( level < 0 ) || ( level > RX_SI4432_MAX_DRIVE ))
return;
else
@ -2503,6 +2618,20 @@ int oldLevel = sigGenSetting.RX_Drive;
}
void SetSGPower ( int16_t dBm )
{
// Add algorithm to set attenuator and IF drive level
// initially limit to just set attenuator
if ( dBm > sigGenSetting.Calibration )
dBm = sigGenSetting.Calibration;
if ( dBm < (sigGenSetting.Calibration - ATTENUATOR_RANGE - RX_SI4432_MAX_DRIVE * 3) )
dBm = sigGenSetting.Calibration - ATTENUATOR_RANGE;
sigGenSetting.Power = dBm;
changedSetting = true;
}
#ifdef SI_TG_LO_CS
/*
* "SetTGLoDrive" sets the transmitter max output level for the tracking generator.
@ -2618,6 +2747,28 @@ int32_t GetTGOffset ( )
return trackGenSetting.Offset;
}
/*
* Set the Track Gen frequency - M0WID addition
*/
bool SetTGFreq ( int32_t freq )
{
int32_t oldFreq = trackGenSetting.Frequency;
if (( freq < MIN_SIGLO_FREQ ) || ( freq > MAX_SIGLO_FREQ )) // If out of limits
return false; // Don't change it
trackGenSetting.Frequency = freq;
if ( oldFreq != trackGenSetting.Frequency )
{
changedSetting = true;
WriteTrackGenSettings ();
}
return true; // Frequency was good
}
/*
* "SetSweepStart" and "GetSweepStart" were added in Version 2.3. They used to be in

11
cmd.h
View File

@ -78,6 +78,13 @@
#define MSG_RX_SWEEP 49 // Set the RX Sweep Mode
#define MSG_RXSIGNAL 50 // Set frequency of injected signal for IF Sweep
#define MSG_EXTGAIN 51 // Set external gain or attenuation
#define MSG_SGON 52 // Turn Signal Generator output on
#define MSG_SGOFF 53 // Turn Signal Generator output off
#define MSG_SGFREQ 54 // Set Signal Generator Frequency
#define MSG_TGON 55 // Turn Tracking Generator output on
#define MSG_TGOFF 56 // Turn Tracking Generator output off
#define MSG_TGFREQ 57 // Set Track Gen frequency for sig gen mode
#define MSG_TGSIG 58 // Set Track Gen sig gen mode
#define MSG_COLOURTEST 99 // test of waterfall colours - remove this when done!
@ -139,13 +146,17 @@ void SetGenerate ( int8_t g ); // Puts the unit into or out of signal generat
bool SetIFFrequency ( int32_t f ); // Sets the IF frequency
void SetLoDrive ( uint8_t level ); // Sets LO Si4432 output level
void SetSGState (uint16_t s);
bool SetSGFreq ( uint32_t freq); // set signal generator frequency - returns false if invalid
void SetSGLoDrive ( uint8_t level );
void SetSGRxDrive ( uint8_t level );
void SetSGPower ( int16_t dBm ); // Set signal generator attenuator and drive levels
void SetTracking ( int8_t m ); // set tracking generator mode
void SetTGLoDrive ( uint8_t level ); // set tracking generator drive
void SetTGIfDrive ( uint8_t level );
bool SetTGOffset ( int32_t offset); // set tracking generator offset - returns false if invalid
bool SetTGFreq ( int32_t freq); // set tracking generator freq for sig gen mode - returns false if invalid
int32_t GetTGOffset (void );
void SetTGPower ( int16_t dBm ); // Set TG attenuator and drive levels

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>[TinySA]</title>
<title>[simpleSA]</title>
<link rel="stylesheet" type="text/css" href="styles.css" media="all" />
<meta charset="UTF-8">
@ -46,18 +46,18 @@
<h1>About</h1>
<p style="max-width:700px;">
The TinySA has been developed by Erik PD0EK.
This version has been adapted to run on the ESP32 DevKit module by Dave M0WID and John WA2FZW.
This simpleSA running on an ESP32 has been adapted by Dave M0WID and John WA2FZW.<br />
It was based on an early prototype design of the TinySA by Erik PD0EK.<br />
Information can be found at <a href = "https://groups.io/g/HBTE">https://groups.io/g/HBTE</a>
</p>
<hr/>
<form method="get" action="/doReboot">
To reboot click <button style="background-color: red; color: white;"
onclick="return confirm('Are you sure?')" type="submit">here</button>
</form>
<form method="get" action="/doReboot">
To reboot click <button style="background-color: red; color: white;"
onclick="return confirm('Are you sure?')" type="submit">here</button>
</form>
</div>
</div>
<div id=footer>Copyright &copy; <span id="programCopyright"></span></div>
<div id=footer>Copyright &copy; <span id="programCopyright">M0WID and WA2FZW</span></div>
</body>
</html>

View File

@ -32,7 +32,7 @@
<html>
<head>
<title>TinySA-ESP</title>
<title>simpleSA</title>
<link rel="stylesheet" type="text/css" href="styles.css">
<!-- get file below from http://canvasjs.com/ -->
<script type="text/javascript" src="canvasjs.min.js"></script>
@ -41,7 +41,7 @@
</head>
<body style="min-width:100vw">
<div class='norm'>
<div class='norm' id="top">
<button id="homeButton" onclick="window.location.href='index.html';">Home</button>
<!-- <button id="settingsButton" onclick="window.location.href='settings.html';">Settings</button>
@ -50,12 +50,66 @@
<button id="aboutButton" onclick="window.location.href='about.html';">About</button>
</div>
<div class ="Grid">
<div class = "Grid-cell" id="chartSA" ></div>
<div class = "Grid-cell" id="chartSA" style="display:none">
<!-- container for chart -->
</div>
<div class = "Grid-cell" id="sigGen" style="display:block">
<!-- container for sig gen controls -->
<br />
<div class="sigTitle">Signal Generator</div>
<br />
<div class="sigFreq">
<button class = "inc-button" id="incButton">+</button>
<br />
<label for="setSigGenFreq8" class="sigFreqLabel">Frequency:</label>
<input class="sigFreqInput" id="setSigGenFreq8" name="setSigGenFreq8" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq7" name="setSigGenFreq7" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq6" name="setSigGenFreq6" type="number" min=-1 max=10 value=0>
<span class="sigFreqText">,</span>
<input class="sigFreqInput" id="setSigGenFreq5" name="setSigGenFreq5" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq4" name="setSigGenFreq4" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq3" name="setSigGenFreq3" type="number" min=-1 max=10 value=0>
<span class="sigFreqText">,</span>
<input class="sigFreqInput" id="setSigGenFreq2" name="setSigGenFreq2" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq1" name="setSigGenFreq1" type="number" min=-1 max=10 value=0>
<input class="sigFreqInput" id="setSigGenFreq0" name="setSigGenFreq0" type="number" min=0 max=10 value=0>
<span class="sigFreqText">Hz &nbsp;</span>
<button class = "on-button" id="sigOnButton">On/Off</button>
<br />
<button class = "inc-button" id="decButton">-</button>
</div>
<br /><br />
<label for="setSigGenPower" class = "sigLevelLabel">Level:</label>
<input class="sigLevelInput" id="setSigGenPower" name="setSigGenPower" type="number" min=-70 max=20 value=0>
dBm
<br /><br />
<div class="slidecontainer">
<input type="range" min=-70 max=20 value=0 class="slider" id="sigLevelSlider">
</div>
</div>
<br />
<div class = "Grid-cell-side" id="postSweepSettings" >
<!--<form style="width: 90vw; margin-left: 80px" action="doSetSweep" method="get"> -->
<h1>Sweep</h1>
<div class="setting" >
<select class="Sweep-select" id="setMode" name="setMode">
<option class="sweep-option" value="0">Sweep Low</option>
<!-- <option class="sweep-option" value="1">Sweep High</option> -->
<option class="sweep-option" value="2">Sig Gen</option>
<!-- <option class="sweep-option" value="3">Sig Gen High</option> -->
<option class="sweep-option" value="4">SAW Test</option>
<!-- <option class="sweep-option" value="5">Zero Span</option> -->
<!-- <option class="sweep-option" value="6">Zero Span High</option> -->
<option class="sweep-option" value="7">Bandscope</option>
<option class="sweep-option" value="8">RBW Test</option>
</select>
<img src="refresh.png" id="refresh" name = "refresh" height = "18">
</div>
<div class="setting" >
<label for="setStart" class="setting-label">Start:</label>
<input class="value-input" name='setStart' type="number" id="setStart" maxlength="9" min="0" max="350" required>
@ -113,9 +167,10 @@
<br />
<div class="setting" >
<label for="setAtten" class="setting-label">Atten:</label>
<input class="value-input" name='setAtten' type="number" step="1" id ="setAtten" maxlength="3" min="0" max="31" required>
<input class="value-input" name='setAtten' type="number" step="1" id ="setAtten" maxlength=3 min=0 max=31 required>
dB
<label for="setExtern" class="setting-label">External:</label>
<input class="value-input" name='setExtern' type="number" step="1" id ="setExtern" maxlength="3" min="-60" max="60" required>
<input class="value-input" name='setExtern' type="number" step="1" id ="setExtern" maxlength=3 min=-60 max=60 required>
<!--<select class="select-input" id="setAtten" name="setAtten"></select> -->
dB
</div>
@ -137,25 +192,36 @@
<br />
<div id="spur">
<div class="setting" >
<label class="setting-label">Spur Reduce:</label>
<label class="setting-widelabel">Spur Reduce:</label>
<input class="checkbox-input" type="checkbox" id="spurReduction" size="1" value="0" />
</div>
</div>
<div id="tracking">
<div class="setting" >
<label class="setting-label">TrackGen:</label>
<input class="checkbox-input" type="checkbox" id="trackGen" size="1" value="0" />
<input class="value-input" type="number" id="setTrackGenPower" placeholder="setTrackGenPower" maxlength = "9" min="-60" max="20" value="0" />
dBm
<select class="select-input" id="trackGen" name="trackGen">
<option class="select-option" value=0>Off</option>
<option class="select-option" value=1>Track</option>
<option class="select-option" value=2>Generate</option>
</select>
<br />
<label class="setting-label">Level:</label>
<input class="value-input" type="number" id="setTrackGenPower" placeholder="setTrackGenPower" maxlength = "6" min="-60" max="20" value="0" />
dBm
</div>
<div class="setting" >
<label for="setTGFreq" class="setting-label">TG Freq:</label>
<input class="value-input" name='setTGFreq' type="number" id="setTGFreq" maxlength="9" min=0 max=350 required>
MHz
</div>
</div>
<br />
<div id="signal_info">
<div class="setting" >
<label class="setting-label">Points:</label>
<input class="value-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
<label class="setting-label">Time:</label>
<input class="value-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
<input class="sweep-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
pts
<input class="sweep-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
ms
</div>
</div>
@ -179,7 +245,7 @@
dB
</div>
<div class="setting" >
<button class = "set-button" type="submit" id="setActPower">Set Actual</button>
<button id="setActPower">Set Actual</button>
<input class="value-input" type="number" id="setPowerValue" placeholder="setPowerValue" maxlength = "9" min="-60" max="20" value="0" />
dBm
</div>
@ -257,8 +323,9 @@
<div style="width: 100px; display: inline-block">Pings:
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
</div>
<div style="width: 100px; display: inline-block">Refresh Interval:
<div style="width: 160px; display: inline-block">Refresh:
<input class="value-input" type="number" id="refreshInterval" size="3" min="100" max="3000" value="500" />
ms
</div>
</form>
</div>
@ -268,8 +335,17 @@
</div>
<script type="text/javascript">
var frequency = 0;
var freqStep = 1000000;
var chartDiv = document.getElementById('chartSA');
var sigDiv = document.getElementById('sigGen');
var refreshInterval = document.getElementById('refreshInterval');
var refresh = document.getElementById('refresh');
var setMode = document.getElementById('setMode');
var sweepStart = document.getElementById('sweepStart');
var sweepStop = document.getElementById('sweepStop');
var setStart = document.getElementById('setStart');
@ -292,12 +368,28 @@ var setPreAmp = document.getElementById('setPreAmp');
var setAverage = document.getElementById('Average');
var setTrackGen = document.getElementById('trackGen');
var setTrackGenPower = document.getElementById('setTrackGenPower');
var setTGFreq = document.getElementById('setTGFreq');
var store1 = document.getElementById('store1');
var store2 = document.getElementById('store2');
var store3 = document.getElementById('store3');
var store4 = document.getElementById('store4');
//var messageWindow = document.getElementById('message');
var sigLevelSlider = document.getElementById('sigLevelSlider');
var setSigGenPower = document.getElementById('setSigGenPower');
var setSigGenFreq = document.getElementById('setSigGenFreq');
var sigOnButton = document.getElementById('sigOnButton');
var setSigGenFreq0 = document.getElementById('setSigGenFreq0');
var setSigGenFreq1 = document.getElementById('setSigGenFreq1');
var setSigGenFreq2 = document.getElementById('setSigGenFreq2');
var setSigGenFreq3 = document.getElementById('setSigGenFreq3');
var setSigGenFreq4 = document.getElementById('setSigGenFreq4');
var setSigGenFreq5 = document.getElementById('setSigGenFreq5');
var setSigGenFreq6 = document.getElementById('setSigGenFreq6');
var setSigGenFreq7 = document.getElementById('setSigGenFreq7');
var setSigGenFreq8 = document.getElementById('setSigGenFreq8');
var tempCenter;
// initialise these to silly values to force an update first time round
@ -316,6 +408,13 @@ var oldSweepPoints = 0;
var oldSpur = 2;
var oldTrackGen = 2;
var oldTrackGenPower = 1000;
var oldTGFreq = -1;
var oldSigGen = -1;
var oldSigGenPower = 1000;
var oldSigGenFreq = -1;
var oldSigGenMod = -1;
var oldSigGenModFreq = -1;
var oldSigOnButton = -1;
// Chart configuration - Scope
var RSSISamples = [
@ -410,17 +509,28 @@ var chartSA = new CanvasJS.Chart("chartSA",
zoomType: "xy",
//height:800,
title: {
text: "ESP32 TinySA",
text: "simpleSA",
fontSize: 28
},
axisX: {
title: "Frequency (MHz)",
titleFontSize: 24
titleFontSize: 24,
gridThickness: 1,
gridColor: "WhiteSmoke",
stripLines:[
{
startValue:50,
thickness:1,
color:"#d8d8d8",
}
]
},
axisY:
{
title: "dB",
title: "dBm",
titleFontSize: 24,
gridThickness: 1,
gridColor: "WhiteSmoke",
minimum: -120
},
axisY2: [
@ -439,6 +549,7 @@ var chartSA = new CanvasJS.Chart("chartSA",
exportEnabled: true,
legend: {
cursor: "pointer",
fontSize: 16,
itemclick: function (e) {
//console.log("legend click: " + e.dataPointIndex);
//console.log(e);
@ -526,9 +637,16 @@ renderChart();
// Add handlers for the change events in the input fields
refresh.addEventListener('click', (event) => {
sendValue("r", 0);
});
setMode.addEventListener('change', (event) => {
sendValue("m", setMode.value);
});
setStart.addEventListener('change', (event) => {
sendValue("a", setStart.value);
sendValue("a", setStart.value);
});
setStop.addEventListener('change', (event) => {
@ -589,13 +707,17 @@ setSpur.addEventListener('change', (event) => {
});
setTrackGen.addEventListener('change', (event) => {
if (setTrackGen.checked) {
sendValue("t", 1);
} else {
sendValue("t", 0);
}
sendValue("t", setTrackGen.value);
});
setTrackGenPower.addEventListener('change', (event) => {
sendValue("T", setTrackGenPower.value);
});
setTGFreq.addEventListener('change', (event) => {
sendValue("f", setTGFreq.value);
});
store1.addEventListener('change', (event) => {
if (store1.checked) {
@ -653,6 +775,188 @@ store4.addEventListener('change', (event) => {
}
});
function changeStep(newStep) {
freqStep = newStep;
setSigGenFreq0.style.color = "black";
setSigGenFreq1.style.color = "black";
setSigGenFreq2.style.color = "black";
setSigGenFreq3.style.color = "black";
setSigGenFreq4.style.color = "black";
setSigGenFreq5.style.color = "black";
setSigGenFreq6.style.color = "black";
setSigGenFreq7.style.color = "black";
setSigGenFreq8.style.color = "black";
switch(freqStep) {
case 1:
setSigGenFreq0.style.color = "red";
break;
case 10:
setSigGenFreq1.style.color = "red";
break;
case 100:
setSigGenFreq2.style.color = "red";
break;
case 1000:
setSigGenFreq3.style.color = "red";
break;
case 10000:
setSigGenFreq4.style.color = "red";
break;
case 100000:
setSigGenFreq5.style.color = "red";
break;
case 1000000:
setSigGenFreq6.style.color = "red";
break;
case 10000000:
setSigGenFreq7.style.color = "red";
break;
case 100000000:
setSigGenFreq8.style.color = "red";
break;
}
};
changeStep(freqStep); // initial pass
function incdec(direction, factor) {
if (direction > 0) {
if ( (frequency + factor) <= 250000000)
frequency += factor;
} else {
if (frequency >= factor)
frequency -= factor;
}
if (frequency > 250000000)
frequency = 250000000;
if (frequency < 0)
frequency = 0;
console.log("incdec:", frequency);
var tempFreq = frequency;
setSigGenFreq0.value = frequency%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq1.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq2.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq3.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq4.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq5.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq6.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq7.value = tempFreq%10;
tempFreq = parseInt(tempFreq/10);
setSigGenFreq8.value = tempFreq%10;
if (factor != 0)
sendValue("F", frequency);
}
incButton.onclick = function() {incdec(1, freqStep)};
decButton.onclick = function() {incdec(-1, freqStep)};
setSigGenFreq0.onfocus = function() {changeStep(1)};
setSigGenFreq1.onfocus = function() {changeStep(10)};
setSigGenFreq2.onfocus = function() {changeStep(100)};
setSigGenFreq3.onfocus = function() {changeStep(1000)};
setSigGenFreq4.onfocus = function() {changeStep(10000)};
setSigGenFreq5.onfocus = function() {changeStep(100000)};
setSigGenFreq6.onfocus = function() {changeStep(1000000)};
setSigGenFreq7.onfocus = function() {changeStep(10000000)};
setSigGenFreq8.onfocus = function() {changeStep(100000000)};
setSigGenFreq0.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(1);
incdec(-event.deltaY,1);
});
setSigGenFreq1.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(10);
incdec(-event.deltaY,10);
});
setSigGenFreq2.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(100);
incdec(-event.deltaY,100);
});
setSigGenFreq3.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(1000);
incdec(-event.deltaY,1000);
});
setSigGenFreq4.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(10000);
incdec(-event.deltaY,10000);
});
setSigGenFreq5.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(100000);
incdec(-event.deltaY,100000);
});
setSigGenFreq6.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(1000000);
incdec(-event.deltaY,1000000);
});
setSigGenFreq7.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(10000000);
incdec(-event.deltaY,10000000);
});
setSigGenFreq8.addEventListener('wheel', (event) => {
event.preventDefault();
changeStep(100000000);
incdec(-event.deltaY,100000000);
});
setSigGenPower.onchange = function() {
sendValue("L", setSigGenPower.value);
sigLevelSlider.value = this.value;
};
// Update the current level value (each time you drag the slider handle)
sigLevelSlider.oninput = function() {
setSigGenPower.value = this.value;
setSigGenPower.onchange();
}
function styleSigGenButton ( val ) {
if (sigOnButton.value == 1) {
sigOnButton.style="background-color:green";
} else {
sigOnButton.style="background-color:lightgrey";
}
}
sigOnButton.onclick = function() {
if (sigOnButton.value == 1) {
sigOnButton.value = 0;
} else {
sigOnButton.value = 1;
}
styleSigGenButton (sigOnButton.value);
sendValue("G", sigOnButton.value);
}
//var roundtripTime = document.getElementById('roundtripTime');
//var messageCount = document.getElementById('messageCount');
//var missedReplies = document.getElementById('missedReplies');
@ -685,7 +989,7 @@ function renderChart()
//missedReplies.value = missedMessageCounter;
hostName.value = "ws://" + location.host + ":81";
// connect to TinySA server
// connect to simpleSA server
connect(hostName.value);
// At this point the page is running
@ -703,6 +1007,95 @@ var indexUpdateMilliSeconds = 1 * 1000;
function handleSettings (settings)
{
setMode.value = settings.mode;
if (setMode.value == 8) { // RX Sweep (RBW test)
setStart.max = settings.IF;
setStop.max = 600;
setStart.min = 350;
setStart.disabled = false;
setStop.min = settings.IF;
setStop.disabled = false;
setCenter.disabled = true;
setSpan.disabled = true;
setRBW.disabled = false;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackGen.disabled = true;
setTGFreq.disabled = true;
setTrackGenPower.disabled = true;
sigDiv.style.display = "none";
chartDiv.style.display = "block";
} else if (settings.mode == 4 ) { // IF Sweep (SAW test)
setStart.max = settings.IF;
setStop.max = 460;
setStart.min = 400;
setStop.min = settings.IF;
setStart.disabled = false;
setStop.disabled = false;
setCenter.disabled = true;
setSpan.disabled = true;
setRBW.disabled = true;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackGen.disabled = true;
setTGFreq.disabled = true;
setTrackGenPower.disabled = true;
sigDiv.style.display = "none";
chartDiv.style.display = "block";
} else if (settings.mode == 7 ) { // BANDSCOPE
setStart.max = 350;
setStop.max = 350;
setStart.min = 0;
setStop.min = 0;
setStart.disabled = false;
setStop.disabled = true;
setCenter.disabled = true;
setSpan.disabled = false;
setRBW.disabled = false;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackGen.disabled = true;
setTrackGenPower.disabled = true;
sigDiv.style.display = "none";
chartDiv.style.display = "block";
} else if (settings.mode == 2 ) { // Signal Generator
setStart.max = 350;
setStop.max = 350;
setStart.min = 0;
setStop.min = 0;
setStart.disabled = true;
setStop.disabled = true;
setCenter.disabled = true;
setSpan.disabled = true;
setRBW.disabled = true;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackGen.disabled = true;
setTGFreq.disabled = true;
setTrackGenPower.disabled = true;
sigDiv.style.display = "block";
chartDiv.style.display = "none";
} else {
setStart.max = 350;
setStop.max = 350;
setStart.min = 0;
setStop.min = 0;
setStart.disabled = false;
setStop.disabled = false;
setCenter.disabled = false;
setSpan.disabled = false;
setRBW.disabled = false;
setRefOut.disabled = false;
setSpur.disabled = false;
setTrackGen.disabled = false;
setTGFreq.disabled = false;
setTrackGenPower.disabled = false;
sigDiv.style.display = "none";
chartDiv.style.display = "block";
}
actRBW.value = settings.bandwidth;
@ -774,16 +1167,43 @@ function handleSettings (settings)
oldSpur = settings.spur;
}
if (settings.tg != oldTrackGen) {
if (settings.tg) {
setTrackGen.checked = true; // Tracking Generator checkbox
} else {
setTrackGen.checked = false; // Tracking Generator checkbox
}
if (settings.sg != oldSigGen) { // Sig gen on/off
sigOnButton.value = settings.sg;
oldSigGen = settings.sg;
styleSigGenButton (sigOnButton.value);
}
if (settings.sgFreq != oldSigGenFreq) { // sig gen frequency
frequency = settings.sgFreq;
oldSigGenFreq = settings.sgFreq;
incdec(0,0);
console.log("sigGenFreq=" + settings.sgFreq);
}
sigLevelSlider.max = settings.sgCal; // Limits for sig gen power
sigLevelSlider.min = settings.sgCal - settings.sgRange;
setSigGenPower.max = settings.sgCal;
setSigGenPower.min = settings.sgCal - settings.sgRange;
if (settings.sgPower != oldSigGenPower) {
setSigGenPower.value = settings.sgPower;
sigLevelSlider.value = settings.sgPower;
oldSigGenPower = settings.sgPower;
}
if (settings.tg != oldTrackGen) { // tracking generator state
setTrackGen.value = settings.tg;
oldTrackGen = settings.tg;
}
if (settings.tgPower != oldTrackGenPower) {
if (settings.tgFreq != oldTGFreq) { // tracking generator frequency for sig gen mode
setTGFreq.value = settings.tgFreq;
oldTGFreq = settings.tgFreq;
}
if (settings.tgPower != oldTrackGenPower) { // tracking generator output power
setTrackGenPower.value = settings.tgPower;
oldTrackGenPower = settings.tgPower;
}
@ -1095,17 +1515,19 @@ function connect(host)
connection.send('Hello from Browser :-) ' + new Date());
sendMessage();
sendPingVar = setInterval(function(){ sendPing() }, 30000);
sendValue("r",0); // request settings
// Get the settings to make sure current
$.getJSON( "getSettings")
.done(function (settings) {
handleSettings(settings);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Settings Request Failed: " + err);
});
//$.getJSON( "getSettings")
// .done(function (settings) {
// handleSettings(settings);
// })
//
// .fail(function(jqxhr, textStatus, error) {
// var err = textStatus +", " + error;
// console.log("Settings Request Failed: " + err);
// });
var items = document.querySelectorAll(".value-input");
var i;
@ -1119,6 +1541,18 @@ function connect(host)
items[i].disabled = false;
}
var items = document.querySelectorAll(".select-button");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
var items = document.querySelectorAll(".checkbox-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
};
connection.onclose = function(event)
@ -1141,6 +1575,18 @@ function connect(host)
items[i].disabled = true;
}
var items = document.querySelectorAll(".select-button");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
var items = document.querySelectorAll(".checkbox-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
};
connection.onerror = function(error)
@ -1176,7 +1622,7 @@ function connect(host)
}
else if (myObject.mType == "chunkSweep")
{
console.log("handle chunk Sweep:" + myObject.StartIndex);
//console.log("handle chunk Sweep:" + myObject.StartIndex);
handleChunkData(myObject);
}
else
@ -1210,19 +1656,30 @@ function sendValue(c, val)
// s Span
// d Local Oscillator Drive
// g PreAmpGain/Mode
// p set actual power to peak value
// i IF frequency
// m mode
// p set actual power to peak value
// o RefOut
// r request Settings are pushed
// A internal attenuation (PE4302)
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
// R requested RBW
// S Spur reduction Off/On
// t trackGen Off/On/Fixed
// T trackGen output level
// f trackgen signal generator frequency
// F Sig Gen frequency
// L Sig Gen level (dBm)
// G Sig Gen Off/On
// P Sig Gen set max output level (dBm)
//
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
connection.send("#" + c + " " + val);
console.log("Command:" + c + val);
if (connectionStatus.value == "Connected") {
connection.send("#" + c + " " + val);
console.log("Command:" + c + val);
} else {
console.log("No connection - Command:" + c + val);
}
}

View File

@ -627,7 +627,7 @@ store1.addEventListener('change', (event) => {
});
store2.addEventListener('change', (event) => {
if (store1.checked) {
if (store2.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
@ -641,7 +641,7 @@ store2.addEventListener('change', (event) => {
});
store3.addEventListener('change', (event) => {
if (store1.checked) {
if (store3.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
@ -655,7 +655,7 @@ store3.addEventListener('change', (event) => {
});
store4.addEventListener('change', (event) => {
if (store1.checked) {
if (store4.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}

BIN
data/refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

976
data/siggen.html Normal file
View File

@ -0,0 +1,976 @@
<!--
This application is loosly based on the code found here:
Repository: https://github.com/krzychb/EspScopeA0
Version: Delta
Flie: index.htm
Revision: 0.1.0
Date: 10-Jul-2016
Author: krzychb at gazeta.pl
Copyright (c) 2016 Krzysztof Budzynski. All rights reserved.
This modified version takes the samples from the TinySA
spectrum analyser and displays in a web page.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-->
<!DOCTYPE html>
<html>
<head>
<title>simpleSA-ESP</title>
<link rel="stylesheet" type="text/css" href="styles.css">
<!-- get file below from http://canvasjs.com/ -->
<script type="text/javascript" src="canvasjs.min.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="support.js"></script>
</head>
<body style="min-width:100vw">
<div class='norm'>
<button id="homeButton" onclick="window.location.href='index.html';">Home</button>
<!-- <button id="settingsButton" onclick="window.location.href='settings.html';">Settings</button>
<button id="backupRestoreButton" onclick="window.location.href='backupRestore.html';">Backup/Restore</button>
// <button id="helpButton" onclick="window.location.href='help.html';">Help</button> -->
<button id="aboutButton" onclick="window.location.href='about.html';">About</button>
</div>
<div class ="Grid">
<div class = "Grid-cell" id="chartSA" ></div>
<br />
<div class = "Grid-cell-side" id="postSweepSettings" >
<!--<form style="width: 90vw; margin-left: 80px" action="doSetSweep" method="get"> -->
<div class="setting" >
<select class="Sweep-select" id="setMode" name="setMode">
<option class="sweep-option" value="0">Sweep Low</option>
<!-- <option class="sweep-option" value="1">Sweep High</option> -->
<option class="sweep-option" value="2">Sig Gen</option>
<!-- <option class="sweep-option" value="3">Sig Gen High</option> -->
<option class="sweep-option" value="4">SAW Test</option>
<!-- <option class="sweep-option" value="5">Zero Span</option> -->
<!-- <option class="sweep-option" value="6">Zero Span High</option> -->
<option class="sweep-option" value="7">Bandscope</option>
<option class="sweep-option" value="8">RBW Test</option>
</select>
<img src="refresh.png" id="refresh" name = "refresh" height = "18">
</div>
<div class="setting" >
<label for="setFreq" class="setting-label">Frequency:</label>
<input class="value-input" name='setFreq' type="number" id="setFreq" maxlength="9" min="0" max="350" required>
MHz
</div>
<br />
<div class="setting" >
<label for="setLevel" class="setting-label">Level:</label>
<input class="value-input" name='setLevel' type="number" step="1" id ="setLevel" maxlength="4" min="-31" max="0" required>
dBm
</div>
<hr />
<h1>Settings</h1>
<div class="setting" >
<label for="calLevel" class="setting-label">Max Level:</label>
<input class="value-display" type="text" disabled="1" id="calLevel" size="1" value="0" />
dB
</div>
<div class="setting" >
<button class = "set-button" type="submit" id="setActPower">Set Max</button>
<input class="value-input" type="number" id="setMaxPower" placeholder="setMaxPower" maxlength = "9" min="-60" max="20" value="0" />
dBm
</div>
<br />
<div class="setting" >
<label for="setLODrive" class="setting-label">LO Drive:</label>
<select class="select-input" id="setLODrive" name="setLODrive">
<option class="select-option" value="0">-1</option>
<option class="select-option" value="1">2</option>
<option class="select-option" value="2">5</option>
<option class="select-option" value="3">8</option>
<option class="select-option" value="4">11</option>
<option class="select-option" value="5">14</option>
<option class="select-option" value="6">17</option>
<option class="select-option" value="7">20</option>
</select>
dBm
</div>
<div class="setting" >
<label for="setIF" class="setting-label">IF:</label>
<input class="value-input" type="number" id="setIF" size="1" value="433.92" min="433" max=435 step=0.01 />
MHz
</div>
</div>
<!--</form> -->
</div>
<!-- Below chart (hopefully!) -->
<div class = "Grid">
<div class = "Grid-cell-connection" id="status" >
<hr />
<div id="connection-status">
<form onsubmit="return false;">
<div style="width: 400px; display: inline-block">Host:
<input type="text" id="hostName" value="ws://hostName:81" style="width:160px;"/>
<input type="button" value="Connect" onclick="connect(hostName.value)" />
<input type="button" value="Disconnect" onclick="disconnect()" />
</div>
<div style="width: 250px; display: inline-block">Status:
<input type="text" id="connectionStatus" value="Idle" style="border: 0" />
</div>
<div style="width: 100px; display: inline-block">Pings:
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
</div>
<div style="width: 100px; display: inline-block">Refresh Interval:
<input class="value-input" type="number" id="refreshInterval" size="3" min="100" max="3000" value="500" />
</div>
</form>
</div>
<!-- <input class="message-display" type="text" disabled="1" id="message" size="1" value="json message" /> -->
</div>
</div>
<script type="text/javascript">
var refreshInterval = document.getElementById('refreshInterval');
var refresh = document.getElementById('refresh');
var setMode = document.getElementById('setMode');
var setFreq = document.getElementById('setFreq');
var setLevel = document.getElementById('setLevel');
var calLevel = document.getElementByID('calLevel');
var setActPower = document.getElementById('setActPower');
var setMaxPower = document.getElementByID('setMaxPower');
var setLODrive = document.getElementById('setLODrive');
var setIF = document.getElementById('setIF');
//var messageWindow = document.getElementById('message');
// initialise these to silly values to force an update first time round
var oldFreq = 0
var oldSetLevel = 100;
var oldCalLevel = 100;
var oldMaxPower = 100;
var oldLODrive = -1;
var oldIF = 0;
// Add handlers for the change events in the input fields
refresh.addEventListener('click', (event) => {
sendValue("r", 0);
});
setMode.addEventListener('change', (event) => {
sendValue("m", setMode.value);
});
setFreq.addEventListener('change', (event) => {
sendValue("a", setStart.value);
});
setStop.addEventListener('change', (event) => {
sendValue("b", setStop.value);
});
setCenter.addEventListener('change', (event) => {
sendValue("c", setCenter.value);
});
setLODrive.addEventListener('change', (event) => {
if ((setLODrive.value >=0) && (setLODrive.value <= 7))
sendValue("d", setLODrive.value);
});
setIF.addEventListener('change', (event) => {
sendValue("i", setIF.value);
});
setRefOut.addEventListener('change', (event) => {
sendValue("o", setRefOut.value);
});
setActPower.addEventListener('click', (event) => {
sendValue("p", setPowerValue.value);
});
setSpan.addEventListener('change', (event) => {
sendValue("s", setSpan.value);
});
setAtten.addEventListener('change', (event) => {
sendValue("A", setAtten.value);
});
setExtern.addEventListener('change', (event) => {
sendValue("E", setExtern.value);
});
setRBW.addEventListener('change', (event) => {
sendValue("R", setRBW.value);
});
setPreAmp.addEventListener('change', (event) => {
if (setPreAmp.value == "96") {
sendValue("g", setPreAmp.value);
} else {
sendValue("g", setPreAmp.selectedOptions[0].text);
}
});
setSpur.addEventListener('change', (event) => {
if (setSpur.checked) {
sendValue("S", 1);
} else {
sendValue("S", 0);
}
});
setTrackGen.addEventListener('change', (event) => {
if (setTrackGen.checked) {
sendValue("t", 1);
} else {
sendValue("t", 0);
}
});
store1.addEventListener('change', (event) => {
if (store1.checked) {
var b = parseFloat(levelOffset.value) + parseFloat(setAtten.value) - 120 - parseFloat(setExtern.value);
chartSA.options.data[5].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[5].dataPoints.length = 2; // reset
}
});
store2.addEventListener('change', (event) => {
if (store2.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[6].dataPoints.length = 2; // reset
}
});
store3.addEventListener('change', (event) => {
if (store3.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[7].dataPoints.length = 2; // reset
}
});
store4.addEventListener('change', (event) => {
if (store4.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[8].dataPoints.length = 2; // reset
}
});
//var roundtripTime = document.getElementById('roundtripTime');
//var messageCount = document.getElementById('messageCount');
//var missedReplies = document.getElementById('missedReplies');
var messageCounter = 0;
var missedMessageCounter = 0;
var messageSendMilis;
var connection;
var connectionStatus = document.getElementById('connectionStatus');
var hostName = document.getElementById('hostName');
var pingCounter = 0;
var sendPingVar;
var dateObject;
/*
* Timed update of chart render to reduce load on slow smartphones or tablets
*/
function renderChart()
{
setTimeout(function(){renderChart()}, refreshInterval.value);
chartSA.render();
//setTimeout(renderChart, refreshInterval.value);
}
//messageCount.value = messageCounter;
//missedReplies.value = missedMessageCounter;
hostName.value = "ws://" + location.host + ":81";
// connect to TinySA server
connect(hostName.value);
// At this point the page is running
$(document).ready(function () {
update();
var chartUpdateVar;
// chartUpdateVar = setInterval(renderChart, 500);
});
var initDone = false;
var indexUpdateMilliSeconds = 1 * 1000;
function handleSettings (settings)
{
setMode.value = settings.mode;
if (setMode.value == 8) { // RX Sweep (RBW test)
setStart.max = settings.IF;
setStop.max = 600;
setStart.min = 350;
setStop.min = settings.IF;
setStop.disabled = false;
setCenter.disabled = true;
setSpan.disabled = true;
setRBW.disabled = false;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackgen.disabled = true;
setTrackGenPower.disabled = true;
} else if (settings.mode == 4 ) { // IF Sweep (SAW test)
setStart.max = settings.IF;
setStop.max = 460;
setStart.min = 400;
setStop.min = settings.IF;
setStop.disabled = false;
setCenter.disabled = true;
setSpan.disabled = true;
setRBW.disabled = true;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackgen.disabled = true;
setTrackGenPower.disabled = true;
} else if (settings.mode == 7 ) { // BANDSCOPE
setStart.max = 350;
setStop.max = 350;
setStart.min = 0;
setStop.min = 0;
setStop.disabled = true;
setCenter.disabled = true;
setSpan.disabled = false;
setRBW.disabled = false;
setRefOut.disabled = true;
setSpur.disabled = true;
setTrackgen.disabled = true;
setTrackGenPower.disabled = true;
} else {
setStart.max = 350;
setStop.max = 350;
setStart.min = 0;
setStop.min = 0;
setStop.disabled = false;
setCenter.disabled = false;
setSpan.disabled = false;
setRBW.disabled = false;
setRefOut.disabled = false;
setSpur.disabled = false;
setTrackgen.disabled = false;
setTrackGenPower.disabled = false;
}
actRBW.value = settings.bandwidth;
levelOffset.value = settings.levelOffset;
// console.log("levelOffset=" + settings.levelOffset);
if (settings.start/1000 != oldSweepStart) {
//console.log("Start:" + settings.start + " Stop:" + settings.stop + " oldStart:" + oldSweepStart);
//sweepStart.value = settings.start/1000;
setStart.value = settings.start/1000; // change default if changed
oldSweepStart = setStart.value;
setSpan.value = (settings.stop - settings.start)/1000;
}
if (settings.stop/1000 != oldSweepStop) {
//sweepStop.value = settings.stop/1000;
setStop.value = settings.stop/1000; // change default if changed
oldSweepStop = setStop.value;
setSpan.value = (settings.stop - settings.start)/1000;
}
tempCenter = ( (parseFloat(settings.stop) - parseFloat(settings.start) )/2 + parseFloat(settings.start) ) / 1000; // calculate center
if (tempCenter != oldSweepCenter) {
setCenter.value = tempCenter;
oldSweepCenter = tempCenter;
}
if (settings.attenuation != oldAttenuation) {
setAtten.value = settings.attenuation;
oldAttenuation = settings.attenuation;
}
if (settings.extGain != oldExternalGain) {
setExtern.value = settings.extGain;
oldExternalGain = settings.extGain;
}
if (settings.setRBW != oldSetRBW) {
setRBW.value = settings.setRBW;
oldSetRBW = settings.setRBW;
}
if (settings.RefOut != oldSetRefOut) {
setRefOut.value = settings.RefOut; // reference output dropdown
oldSetRefOut = settings.RefOut;
}
if (settings.Drive != oldDrive) {
setLODrive.value = settings.Drive; // LO Drive dropdown
oldDrive = settings.Drive;
}
if (settings.IF != oldIF) {
setIF.value = settings.IF; // IF value
oldIF = settings.IF;
}
if (settings.PreAmp != oldPreAmp) {
setPreAmp.value = settings.PreAmp; // PreAmp Gain value
oldPreAmp = settings.PreAmp;
}
if (settings.spur != oldSpur) {
if (settings.spur) {
spurReduction.checked = true; // Spur reduction checkbox
} else {
spurReduction.checked = false; // Spur reduction checkbox
}
oldSpur = settings.spur;
}
if (settings.tg != oldTrackGen) {
if (settings.tg) {
setTrackGen.checked = true; // Tracking Generator checkbox
} else {
setTrackGen.checked = false; // Tracking Generator checkbox
}
oldTrackGen = settings.tg;
}
if (settings.tgPower != oldTrackGenPower) {
setTrackGenPower.value = settings.tgPower;
oldTrackGenPower = settings.tgPower;
}
chartSA.options.axisX.minimum = setStart.value;
chartSA.options.axisX.maximum = setStop.value;
initDone = false;
}
function handleData (data) // rarely used! see handleChunkData for most sweeps
{
if (data.sweepPoints != sweepPoints.value) {
// reset chart data
chartSA.options.data[0].dataPoints.length = 2;
chartSA.options.data[1].dataPoints.length = 2;
chartSA.options.data[3].dataPoints.length = 2;
sweepPoints.value = data.sweepPoints;
}
var b = parseFloat(levelOffset.value) + parseFloat(setAtten.value) - 120 - parseFloat(setExtern.value);
//chartSA.options.data[0].dataPoints = data.Points; // First series dB
chartSA.options.data[0].dataPoints = data.Points.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
chartSA.options.data[1].dataPoints = data.Points; // RSSI trace
chartSA.options.data[1].axisYType = "secondary";
if ((initDone == 0) || (oldSweepPoints != data.sweepPoints) || (oldDataPointCount != data.Points.length)) {
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints // first run
initDone = 1;
oldSweepPoints = data.Points.length;
oldDataPointCount = data.Points.length;
}
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-1/setAverage) + obj.y*1/setAverage;
return rObj
})
chartSA.options.axisX.minimum = setStart.value;
chartSA.options.axisX.maximum = setStop.value;
// chartSA.options.axisY.minimum = -120;
// chartSA.options.axisY.maximum = 0;
chartSA.options.axisY2.minimum = 0;
chartSA.options.axisY2.maximum = 255;
// RSSISamples.from(data.Points); // moves data
//console.log(RSSISamples[10].y);
// update the chart
chartSA.render();
}
function handleChunkData (data)
{
var init = false;
var n = data.sweepPoints;
if (n != oldSweepPoints) {
// reset chart data
chartSA.options.data[0].dataPoints.length = 0;
chartSA.options.data[1].dataPoints.length = 0;
chartSA.options.data[2].dataPoints.length = 0;
chartSA.options.data[3].dataPoints.length = 0;
chartSA.options.data[4].dataPoints.length = 0;
// add dummy data points
var i;
for (i=0; i<n; i++) {
var p = {x:250, y:-120};
var q = {x:250, y:0};
var r = {x:250, y:49};
var s = {x:250, y:-120};
var m = {x:250, y:10};
chartSA.options.data[0].dataPoints.push(p); // dB
chartSA.options.data[1].dataPoints.push(q); // RSSI
chartSA.options.data[2].dataPoints.push(r); // gain
chartSA.options.data[3].dataPoints.push(s); // average
chartSA.options.data[4].dataPoints.push(m); // min - initialise to high value
}
//chartSA.options.data[0].dataPoints.length = n; // reduces size if > no of data points
//chartSA.options.data[1].dataPoints.length = n;
//chartSA.options.data[2].dataPoints.length = n;
//chartSA.options.data[3].dataPoints.length = n;
sweepPoints.value = data.sweepPoints;
init = true;
initDone = false;
oldSweepPoints = n;
//chartSA.render();
}
var dataStart = data.StartIndex;
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
var a = 1/setAverage.value;
data.Points.forEach (function (point, index) { // copy data into the chart data series
var p = {};
p = point; // create a copy not a reference ??
var f = {};
f = point.x;
chartSA.options.data[1].dataPoints[dataStart + index] = p; // RSSI
chartSA.options.data[0].dataPoints[dataStart + index].x = f * 1;
var dB = p.y/2+b;
chartSA.options.data[0].dataPoints[dataStart + index].y = dB * 1;
//chartSA.options.data[3].dataPoints[dataStart + index] = point;
//try {
//chartSA.options.data[3].dataPoints[dataStart + index].x = f * 1;
// if (initDone) {
// var av = chartSA.options.data[3].dataPoints[dataStart + index].y*(1-a) + dB*a;
// chartSA.options.data[3].dataPoints[dataStart + index].y = av * 1;
// } else {
// chartSA.options.data[3].dataPoints[dataStart + index].y = dB * 1;
// }
//}
//catch {
// chartSA.options.data[3].dataPoints[dataStart + index].y = point.y/2+b;
//}
})
// If end of sweep update the average and min data sets
if (dataStart + data.Points.length >= data.sweepPoints) {
if (!initDone) { // If first time then set the values to current dB series
initDone = true;
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = obj.y*1;
return rObj
})
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = obj.y*1;
return rObj
})
} else {
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-a) + obj.y*a;
return rObj
})
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = Math.min(chartSA.options.data[4].dataPoints[index].y, obj.y);
return rObj
})
}
if (chartSA.options.data[2].visible) {
$.getJSON( "getGainSweep") // proper line
// $.getJSON( "getGainSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
});
}
}
//chartSA.render();
// dataPoints.value = chartSA.options.data[0].dataPoints.length;
sweepTime.value = data.sweepTime;
}
function update()
{
// Get the settings
$.getJSON( "getSettings")
.done(function (settings) {
handleSettings(settings);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Settings Request Failed: " + err);
});
// Get the sweep data
$.getJSON( "getSweep") // proper line
// $.getJSON( "getSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
handleData(data);
//setTimeout(update, indexUpdateMilliSeconds);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Sweep Request Failed: " + err);
});
if (chartSA.options.data[2].visible) {
$.getJSON( "getGainSweep") // proper line
// $.getJSON( "getGainSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
});
}
}
/*
// This method is called to add all necessary options to a
// select representing the available resolution bandwidths(RBW).
// default is auto
*/
function buildRBWSelect()
{
let dropdown = $('#setRBW');
dropdown.empty();
// Populate dropdown with list of RBW
$.getJSON("getRbwList", function (data) {
dropdown.append($('<option class="select-option" ></option>').attr('value', 0).text("Auto"));
$.each(data, function (key, bpf) {
dropdown.append($('<option class="select-option" ></option>').attr('value', bpf.bw10).text(bpf.bw));
})
});
//dropdown.prop('selectedIndex', 0);
}
buildRBWSelect();
/*
// This method is called to add all necessary options to a
// select representing the available attenuations.
// default is auto
*/
function buildAttenSelect()
{
let dropdown = $('#setAtten');
dropdown.empty();
// Populate dropdown with list of RBW
$.getJSON("getAttenList", function (data) {
$.each(data, function (key, att) {
dropdown.append($('<option class="select-option" ></option>').attr('value', att.dB).text(att.dB));
})
});
//dropdown.prop('selectedIndex', 0);
}
//buildAttenSelect();
function connect(host)
{
if(connection)
{
//connection.close(); // restart
return; // already connected
}
connectionStatus.value = "Connecting...";
connection = new WebSocket(host, ['arduino']);
connection.onopen = function()
{
connectionStatus.value = "Connected";
connectionStatus.style = "background-color:lightgreen";
connection.send('Hello from Browser :-) ' + new Date());
sendMessage();
sendPingVar = setInterval(function(){ sendPing() }, 30000);
sendValue("r",0); // request settings
// Get the settings to make sure current
//$.getJSON( "getSettings")
// .done(function (settings) {
// handleSettings(settings);
// })
//
// .fail(function(jqxhr, textStatus, error) {
// var err = textStatus +", " + error;
// console.log("Settings Request Failed: " + err);
// });
var items = document.querySelectorAll(".value-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
var items = document.querySelectorAll(".select-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
};
connection.onclose = function(event)
{
clearInterval(sendPingVar);
connectionStatus.value = "Disconnected";
connectionStatus.style = "background-color:red";
//connection.removeEventListeners();
connection = null;
// Disable user input
var items = document.querySelectorAll(".value-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
var items = document.querySelectorAll(".select-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
};
connection.onerror = function(error)
{
console.log("WebSocket Error ", error);
};
connection.onmessage = function(message) // to be used later when we send data at each sweep
{
//console.log("Websocket message received");
// show message
//messageWindow.value = message.data;
//messageSize.value = message.data.length;
// check only messages begining with '{'
if(message.data[0] == "{")
{
// //console.log("Parsing message");
myObject = JSON.parse(message.data);
//console.log("message type " + myObject.mType);
if (myObject.mType == "Settings")
{
pointsCount = myObject.dispPoints;
// sweepSamples = myObject.Points;
//console.log("handle settings");
handleSettings(myObject);
}
else if (myObject.mType == "fullSweep")
{
//console.log("handle full Sweep");
handleData(myObject);
}
else if (myObject.mType == "chunkSweep")
{
//console.log("handle chunk Sweep:" + myObject.StartIndex);
handleChunkData(myObject);
}
else
{
console.log("Invalid json message type");
}
}
};
}
function disconnect()
{
if(connection)
{
connection.close();
}
else
{
connectionStatus.value = "Not connected yet";
}
}
function sendValue(c, val)
{
//
// Message format
// #(code) value where code is a single char. Case is important
// a start freq (MHz) - sig gen freq if in sig gen mode
// b stop frequency
// c centre frequency
// s Span
// d Local Oscillator Drive
// g PreAmpGain/Mode
// i IF frequency
// m mode
// p set actual power to peak value
// o RefOut
// r request Settings are pushed
// A internal attenuation (PE4302)
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
// R requested RBW
// S Spur reduction Off/On
// t trackGen Off/On/Fixed
// T trackGen output level
// L Sig Gen level (dBm)
// G Sig Gen Off/On
// P Sig Gen set max output level (dBm)
//
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
connection.send("#" + c + " " + val);
console.log("Command:" + c + val);
}
function sendMessage()
{
messageCounter++;
//messageCount.value = messageCounter;
dateObject = new Date();
messageSendMilis = dateObject.getTime();
//
// Message format
// # MESSAGE_NUMBER SAMPLE_THRESHOLD NUMBER_OF_SAMPLES
//
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
connection.send("# " + messageCounter + " " + sweepStart + " " + sweepStop);
}
function sendPing()
{
connection.send('ping');
pingCounter++;
connectionPings.value = pingCounter;
}
</script>
</body>
</html>

View File

@ -22,7 +22,7 @@
}
.norm {
width: 100%;
width: 95%;
height: 3vh;
font-family: Arial, Helvetica, sans-serif;
margin-top: 5px;
@ -127,6 +127,14 @@ input[type="number"] {
background-color: lightgrey;
}
.sweep-display {
border: 0;
text-align: right;
width: 65px;
display: inline-block;
background-color: lightgrey;
}
.message-display {
border: 0;
text-align: left;
@ -156,17 +164,47 @@ input[type="number"] {
border: solid 1px grey;
text-align: right;
text-align-last: right;
width: 75px;
width: 77px;
display: inline-block;
}
.Sweep-select {
border: solid 1px grey;
text-align: left;
text-align-last: left;
width: 150px;
display: inline-block;
color: black;
font-weight: bolder;
background-repeat: no-repeat;
margin: 10px;
}
.select-option {
text-align: right;
text-align-last: right;
}
.sweep-option {
text-align: left;
text-align-last: left;
}
.set-button {
font-size: 14px;
.inc-button {
width: 60px;
height: 30px;
font-size: 14px;
float: right;
margin-right:60px;
margin-top:3px;
}
.on-button {
width: 60px;
height: 33px;
font-size: 14px;
float: right;
margin-right:0px;
margin-top:3px;
}
.setting {
@ -176,8 +214,120 @@ input[type="number"] {
.setting-label {
width: 80px;
display: inline-block;
}
.setting-widelabel {
width: 138px;
display: inline-block;
}
.sigTitle {
font-size: 36px;
font-weight: bold;
}
.sigFreq {
font-weight: bolder;
font-size: 32px;
margin: 0;
padding: 0;
letter-spacing: -10px;
width: 500px;
}
.sigFreqLabel {
width: 180px;
display: inline-block;
font-size: 32px;
margin: 0;
padding: 0;
letter-spacing: normal;
}
.sigFreqText {
display: inline-block;
font-size: 32px;
margin: 0;
padding: 0;
letter-spacing: normal;
}
input.sigFreqInput {
border: solid 1px grey;
text-align: right;
width: 18px;
display: inline-block;
font-size: 32px;
margin: 0;
padding: 0;
}
input.sigFrequencyInput {
border: solid 1px grey;
text-align: right;
width: 180px;
display: inline-block;
font-size: 32px;
margin: 0;
padding: 0;
}
input.sigFreqInput::-webkit-outer-spin-button,
input.sigFreqInput::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input.sigFreqInput {
-moz-appearance: textfield;
}
.sigLevelLabel {
width: 180px;
display: inline-block;
font-size: 32px;
letter-spacing: normal;
}
input.sigLevelInput {
border: solid 1px grey;
text-align: right;
width: 180px;
display: inline-block;
font-size: 32px;
}
TH, .bold {
background-color: lightblue;
color: black;
}
.slider {
-webkit-appearance: none;
width: 340px;
height: 15px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}

View File

@ -25,6 +25,7 @@
#define USE_WIFI true // Changed in Version 2.6 to true/false
// #define USE_ACCESS_POINT // Comment out if want to connect to SSID, leave in to use access point
// #define AP_PASSWORD "none"
#define WIFI_SSID ":)" // SSID of your WiFi if not using access point
#define WIFI_PASSWORD "S0ftR0ckRXTX" // Password for your WiFi
@ -64,6 +65,9 @@
// #define SLIDER_MAX_POWER -13.0
#define ATTENUATOR_RANGE 30 // in dB
// the B3555 SAW filter has max power rating of 10dBm.
// Drive of 4 = 11dBm but 1 dB pad in my build. If you have a larger attenuator pad you can try higher powers
#define RX_SI4432_MAX_DRIVE 4 // corresponds to 11dBm
/*
* These definitions control the values that get set when you select "AUTO SETTINGS" from

View File

@ -272,7 +272,7 @@ const char* unit[4] = { "RX", "TX", "TGIF", "TGLO" }; // For debugging
WriteByte ( REG_OFC1, SW_RESET ); // Always perform a system reset
while ( millis() - startTime < 10000 ) // Try for 10 seconds
while ( millis() - startTime < 2000 ) // Try for 2 seconds
{
regRead = ReadByte ( REG_IS2 );

View File

@ -32,7 +32,7 @@
#define PROGRAM_NAME "simpleSA" // These are for the WiFi interface
#define PROGRAM_VERSION "0.01" // Current version is 0.01 - beta!
#define PROGRAM_VERSION "Version 0.1" // Current version - beta!
/*
@ -186,7 +186,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, RX_SWEEP };
IF_SWEEP, ZERO_SPAN_LOW_RANGE, ZERO_SPAN_HIGH_RANGE, BANDSCOPE, RX_SWEEP };
/*

View File

@ -127,11 +127,20 @@
* Additional functions in ui.cmd to allow signed frequency entry.
*
* Version 3.0f Changes by M0WID
*
* Version 0.03
* 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! Version numbering changed - still in beta!
*
* Version 0.1
* Tracking generator now can be used as a signal generator
* Web page for signal generator
* RX sweep for testing the SI4432 FIR filters
* Output range of signal generator increased by also reducing SI4432 output power as well as uing attenuator
* Storage feature - temporary only not to disk - added to web page traces
* X grid lines added to web chart
*/
@ -348,13 +357,14 @@ uint8_t numberOfWebsocketClients; // How many connections
uint16_t wiFiPoints; // Push data to the wifi clinets when this many points collected
unsigned long wiFiTargetTime = WIFI_UPDATE_TARGET_TIME;
unsigned long websocketInterval = WEBSOCKET_INTERVAL;
uint16_t websocketFailCount;
#ifdef USE_WIFI
// Json document buffers
size_t capacity = JSON_ARRAY_SIZE ( MAX_WIFI_POINTS + 1 )
+ ( MAX_WIFI_POINTS + 1 ) * JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE( 5 );
//size_t capacity = JSON_ARRAY_SIZE ( MAX_WIFI_POINTS + 1 )
// + ( MAX_WIFI_POINTS + 1 ) * JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE( 5 );
static DynamicJsonDocument jsonDocument ( capacity ); // Buffer for json data to be pushed to the web clients
static DynamicJsonDocument jsonDocument ( 4000 ); // Buffer for json data to be pushed to the web clients
static JsonArray Points = jsonDocument.createNestedArray ( "Points" ); // add Points array
#endif
@ -380,7 +390,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", "RXSw" }; // For mode display
const char *modeText[] = { "SALo", "SAHi", "SGLo", "SGHi", "IFSw", "0SpL", "0SpH", "BScp", "RXSw" }; // For mode display
float bandwidth; // The current bandwidth (not * 10)
@ -503,7 +513,7 @@ uint16_t spacing = 10000;
bool paused = false;
bool sigGenOutputOn = false;
uint16_t sigGenOutputOn = false;
uint32_t oldFreq; // to store the current Signal Generator frequency
/*
@ -671,6 +681,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
// If the tracking generator IF SI4432 is defined, then check to see if it is connected
tgIF_OK = false;
#ifdef SI_TG_IF_CS
// pinMode (SI_TG_IF_CS, INPUT); //Start off in input mode, no pullup
// delay(2);
@ -680,6 +691,8 @@ bool fsStatus = false; // True if SPIFFS loads ok
// delay(2);
// tgIF_OK = tg_if.Init ( config.tgIF_capacitance );
tft.setCursor(0,180);
tft.println ( "Initializing track gen IF SI4432" );
if ( tg_if.Init ( config.tgIF_capacitance ) )
{
tft.println ("Tracking IF initialised");
@ -708,6 +721,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
// If the tracking generator LO SI4432 is defined, then check to see if it is connected
tgLO_OK = false;
#ifdef SI_TG_LO_CS
// pinMode (SI_TG_LO_CS, INPUT); //Start off in input mode, no pullup
// delay(2);
@ -715,6 +729,9 @@ bool fsStatus = false; // True if SPIFFS loads ok
// // Tracking gen LO present - initialise it, but not in TX mode yet
// pinMode (SI_TG_LO_CS, OUTPUT);
// delay(2);
tft.println ( "Initializing track gen LO SI4432" );
tgLO_OK = tg_lo.Init ( config.tgLO_capacitance );
if ( tgLO_OK )
tft.println ("Tracking LO initialised");
@ -729,7 +746,9 @@ bool fsStatus = false; // True if SPIFFS loads ok
// pinMode (SI_TG_LO_CS, OUTPUT);
// digitalWrite(SI_TG_LO_CS, HIGH); // make sure it doesn't get selected
// }
#else
pinMode (25, OUTPUT);
digitalWrite(25, HIGH); // make sure it doesn't get selected
#endif
@ -809,7 +828,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
// tft.println("Setup Complete");
Serial.printf ( "\nTinySA Version %s Initialization Complete\n", PROGRAM_VERSION );
Serial.printf ( "\nsimpleSA %s Initialization Complete\n", PROGRAM_VERSION );
ShowMenu (); // Display the menu of commands on serial monitor
@ -1113,6 +1132,21 @@ void init_sweep()
}
/*
* Initialise the JSON document that is used to push the sweep data to the web clients
* Used in all the sweep modes
*/
void initChunkSweepDoc (uint32_t startIndex)
{
jsonDocument.clear ();
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
jsonDocument["mType"] = "chunkSweep";
jsonDocument["StartIndex"] = startIndex;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
}
/*
* Initialise high frequency mode sweep.

View File

@ -33,12 +33,15 @@ extern uint16_t displayPoints;
extern uint16_t xDelta;
extern uint16_t waterfallHeight;
extern unsigned long sweepMicros; // To report the scan time
extern int bpfCount; // Number of elements in the bandpassFilters array
extern int updateSidebar; // Flag to indicate no of clients has changed
extern void ClearDisplay ();
extern void DisplayError ( uint8_t severity, const char *l1, const char *l2, const char *l3, const char *l4 );
extern void setMode (uint16_t newMode);
/*
* In Version 1.8, the transmitter and receiver Si4432 modules are implemented as
@ -54,6 +57,7 @@ extern uint8_t AGC_Reg; // Fixed value for preampGain if not auto
extern uint32_t startFreq_IF;
extern uint32_t stopFreq_IF;
extern uint32_t sigFreq_IF;
extern uint16_t sigGenOutputOn;
extern uint32_t startFreq_RX;
extern uint32_t stopFreq_RX;
@ -101,7 +105,14 @@ boolean startAP () // Start the WiFi Access Point, keep the user informed.
{
ClearDisplay (); // Fade to black
Serial.println ( "Starting Access Point" ); // Put in the instructions
delay(2000);
// Scan WiFi SSIDs
WiFi.scanNetworks(true);
/*
@ -123,9 +134,9 @@ boolean startAP () // Start the WiFi Access Point, keep the user informed.
DisplayError ( ERR_WARN, "Failed to open AP:", "WiFi Disabled", NULL, NULL );
else
ipAddress = WiFi.localIP ();
ipAddress = WiFi.softAPIP();
Serial.printf ( "Access Point started, result = %b \n", result );
Serial.printf ( "Access Point started, result = %i \n", result );
return result;
}
@ -210,10 +221,32 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
/*
* Format of message to process
*
* #a 123.123 Start frequency
* #b 123.123 Stop frequency
* Message format
* #(code) value where code is a single char. Case is important
*
* a start freq (MHz) - sig gen freq if in sig gen mode
* b stop frequency
* c centre frequency
* s Span
* d Local Oscillator Drive
* g PreAmpGain/Mode
* i IF frequency
* m mode
* p set actual power to peak value
* o RefOut
* r request Settings are pushed
* A internal attenuation (PE4302)
* E external gain ( eg attenuator(-ve) or preamp(+ve) )
* R requested RBW
* S Spur reduction Off/On
* t trackGen Off/On/Generate
* T trackGen output level
* f trackgen signal generator frequency
* F Sig Gen frequency
* L Sig Gen level (dBm)
* G Sig Gen Off/On
* P Sig Gen set max output level (dBm)
*
* Other formats are ignored
*/
@ -234,11 +267,37 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
switch ( payload[1] )
{
case 'a':
SetSweepStart ( value * 1000000.0 ); // Set sweep start frequency
switch (setting.Mode) {
case SA_LOW_RANGE:
SetSweepStart ( value * 1000000.0 ); // Set Low range sweep start frequency
break;
case SIG_GEN_LOW_RANGE:
SetSweepStart ( value * 1000000.0 ); // Set Low range sweep start frequency
break;
case IF_SWEEP:
SetIFsweepStart ( value * 1000000.0 ); // Set IF sweep start frequency
break;
case RX_SWEEP:
SetRXsweepStart ( value * 1000000.0 ); // Set RX sweep start frequency
break;
case BANDSCOPE:
SetBandscopeStart ( value * 1000000.0 ); // Set sweep start frequency
break;
}
break;
case 'b':
SetSweepStop ( value * 1000000.0 ); // Set sweep stop frequency
switch (setting.Mode) {
case SA_LOW_RANGE:
SetSweepStop ( value * 1000000.0 ); // Set Low range sweep start frequency
break;
case IF_SWEEP:
SetIFsweepStop ( value * 1000000.0 ); // Set IF sweep start frequency
break;
case RX_SWEEP:
SetRXsweepStop ( value * 1000000.0 ); // Set RX sweep start frequency
break;
}
break;
case 'c':
@ -249,6 +308,10 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
SetLoDrive ( (uint8_t) value );
break;
case 'f':
SetTGFreq ( value );
break;
case 'g':
SetPreampGain( (int) value ); // Set PreAmp gain register
break;
@ -257,6 +320,10 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
SetIFFrequency ( (int32_t) ( value * 1000000.0 ));
break;
case 'm': // Set mode
setMode ( (int16_t) ( value ));
break;
case 'o': // Ref Output (LO GPIO2)
SetRefOutput ( (int) value );
break;
@ -265,10 +332,43 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
RequestSetPowerLevel( value );
break;
case 'r': // request of settings by client
switch (setting.Mode)
{
case (SA_LOW_RANGE):
pushSettings();
break;
case (IF_SWEEP):
pushIFSweepSettings();
break;
case (RX_SWEEP):
pushRXSweepSettings();
break;
case (BANDSCOPE):
pushBandscopeSettings();
break;
case (SIG_GEN_LOW_RANGE):
pushSigGenSettings();
break;
default:
Serial.println("Invalid mode in Request setting handler - simpleSA_wifi.cpp");
}
break;
case 's': // Adjust sweep span
SetSweepSpan ( (int32_t) ( value * 1000000.0 ));
break;
case 't': // Tracking Generator off/on/generate
SetTracking ( (int8_t)value );
break;
case 'A': // Internal Attenuation (PE4302)
SetAttenuation ( value );
break;
@ -277,6 +377,18 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
SetExtGain ( value );
break;
case 'F':
SetSGFreq ( value ); // Signal Generator Frequency
break;
case 'G':
SetSGState ( (uint16_t)value ); // Signal Generator output on/off
break;
case 'L': // Signal Generator output power (dBm)
SetSGPower ( value );
break;
case 'R': // Requested RBW. 0=Auto
SetRBW ( value );
Serial.printf("Wifi RBW %f\n", value);
@ -286,10 +398,6 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
SetSpur ( (int8_t)value );
break;
case 't': // Tracking Generator on/off
SetTracking ( (int8_t)value );
break;
case 'T': // Tracking Generator output power (dBm)
SetTGPower ( value );
break;
@ -508,6 +616,7 @@ void onGetSettings (AsyncWebServerRequest *request)
JsonObject root = response->getRoot();
root["mType"] = "Settings";
root["mode"] = setting.Mode;
root["dispPoints"] = displayPoints;
root["start"] = setting.ScanStart / 1000.0;
root["stop"] = setting.ScanStop / 1000.0;
@ -523,6 +632,18 @@ void onGetSettings (AsyncWebServerRequest *request)
root["spur"] = setting.Spur;
root["tg"] = trackGenSetting.Mode;
root["tgPower"] = trackGenSetting.Power;
root["tgFreq"] = trackGenSetting.Frequency;
root["tgMod"] = trackGenSetting.ModulationType;
root["tgModFreq"] = trackGenSetting.ModFrequency;
root["sg"] = sigGenOutputOn; //
root["sgPower"] = sigGenSetting.Power;
root["sgMod"] = sigGenSetting.ModulationType;
root["sgModFreq"] = sigGenSetting.ModFrequency;
root["sgFreq"] = sigGenSetting.Frequency;
root["sgCal"] = sigGenSetting.Calibration;
root["sgRange"] = ATTENUATOR_RANGE + 11; // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
root["tgCal"] = trackGenSetting.Calibration;
root["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so 20dBm output is possible.
if ( AGC_On )
root["PreAmp"] = 0x60; // Auto
@ -546,10 +667,11 @@ if ( numberOfWebsocketClients == 0 )
return;
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 16 );
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 17 );
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
jsonDocument["mType"] = "Settings";
jsonDocument["mode"] = setting.Mode;
jsonDocument["dispPoints"] = displayPoints;
jsonDocument["start"] = setting.ScanStart / 1000.0;
jsonDocument["stop"] = setting.ScanStop / 1000.0;
@ -565,10 +687,21 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
jsonDocument["spur"] = setting.Spur;
jsonDocument["tg"] = trackGenSetting.Mode;
jsonDocument["tgPower"] = trackGenSetting.Power;
jsonDocument["tgFreq"] = trackGenSetting.Frequency;
jsonDocument["tgMod"] = trackGenSetting.ModulationType;
jsonDocument["tgModFreq"] = trackGenSetting.ModFrequency;
jsonDocument["sg"] = sigGenOutputOn; //
jsonDocument["sgPower"] = sigGenSetting.Power;
jsonDocument["sgMod"] = sigGenSetting.ModulationType;
jsonDocument["sgModFreq"] = sigGenSetting.ModFrequency;
jsonDocument["sgFreq"] = sigGenSetting.Frequency;
jsonDocument["sgCal"] = sigGenSetting.Calibration;
jsonDocument["sgRange"] = ATTENUATOR_RANGE + 11; // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
jsonDocument["tgCal"] = trackGenSetting.Calibration;
jsonDocument["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so 20dBm output is possible.
if ( AGC_On )
jsonDocument["PreAmp"] = 0x60; // Auto
else
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
@ -579,7 +712,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
serializeJson ( jsonDocument, wsBuffer );
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
}
else
Serial.println ( "No buffer :(");
@ -593,14 +725,15 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
void pushIFSweepSettings ()
{
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 17 );
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
jsonDocument["mType"] = "Settings";
jsonDocument["mode"] = setting.Mode;
jsonDocument["dispPoints"] = displayPoints;
jsonDocument["start"] = startFreq_IF / 1000.0;
jsonDocument["stop"] = stopFreq_IF / 1000.0;
jsonDocument["IF"] = sigFreq_IF / 1000000.0;
jsonDocument["IF"] = setting.IF_Freq / 1000000.0;
jsonDocument["attenuation"] = setting.Attenuate;
jsonDocument["extGain"] = setting.ExternalGain;
jsonDocument["levelOffset"] = setting.LevelOffset;
@ -610,10 +743,21 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
jsonDocument["Drive"] = setting.Drive;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["spur"] = setting.Spur;
jsonDocument["tg"] = trackGenSetting.Mode;
jsonDocument["tgPower"] = trackGenSetting.Power;
jsonDocument["tgFreq"] = trackGenSetting.Frequency;
jsonDocument["sg"] = sigGenOutputOn; //
jsonDocument["sgPower"] = sigGenSetting.Power;
jsonDocument["sgMod"] = sigGenSetting.ModulationType;
jsonDocument["sgModFreq"] = sigGenSetting.ModFrequency;
jsonDocument["sgFreq"] = sigGenSetting.Frequency;
jsonDocument["sgCal"] = sigGenSetting.Calibration;
jsonDocument["sgRange"] = ATTENUATOR_RANGE + 11; // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
jsonDocument["tgCal"] = trackGenSetting.Calibration;
jsonDocument["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so 20dBm output is possible.
if ( AGC_On )
jsonDocument["PreAmp"] = 0x60; // Auto
else
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
@ -624,7 +768,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
serializeJson ( jsonDocument, wsBuffer );
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
}
else
Serial.println ( "No buffer :(");
@ -638,10 +781,11 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
void pushRXSweepSettings ()
{
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 17 );
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
jsonDocument["mType"] = "Settings";
jsonDocument["mode"] = setting.Mode;
jsonDocument["dispPoints"] = displayPoints;
jsonDocument["start"] = startFreq_RX / 1000.0;
jsonDocument["stop"] = stopFreq_RX / 1000.0;
@ -655,10 +799,21 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
jsonDocument["Drive"] = setting.Drive;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["spur"] = setting.Spur;
jsonDocument["tg"] = trackGenSetting.Mode;
jsonDocument["tgPower"] = trackGenSetting.Power;
jsonDocument["tgFreq"] = trackGenSetting.Frequency;
jsonDocument["sg"] = sigGenOutputOn; //
jsonDocument["sgPower"] = sigGenSetting.Power;
jsonDocument["sgMod"] = sigGenSetting.ModulationType;
jsonDocument["sgModFreq"] = sigGenSetting.ModFrequency;
jsonDocument["sgFreq"] = sigGenSetting.Frequency;
jsonDocument["sgCal"] = sigGenSetting.Calibration;
jsonDocument["sgRange"] = ATTENUATOR_RANGE + 11; // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
jsonDocument["tgCal"] = trackGenSetting.Calibration;
jsonDocument["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so 20dBm output is possible.
if ( AGC_On )
jsonDocument["PreAmp"] = 0x60; // Auto
else
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
@ -669,7 +824,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
serializeJson ( jsonDocument, wsBuffer );
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
}
else
Serial.println ( "No buffer :(");
@ -683,10 +837,11 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
void pushBandscopeSettings ()
{
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 13 );
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 17 );
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
jsonDocument["mType"] = "Settings";
jsonDocument["mode"] = setting.Mode;
jsonDocument["dispPoints"] = setting.BandscopePoints;
jsonDocument["start"] = setting.BandscopeStart / 1000.0;
jsonDocument["stop"] = ( setting.BandscopeStart + setting.BandscopeSpan ) / 1000.0;
@ -700,10 +855,21 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
jsonDocument["Drive"] = setting.Drive;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["spur"] = setting.Spur;
jsonDocument["tg"] = trackGenSetting.Mode;
jsonDocument["tgPower"] = trackGenSetting.Power;
jsonDocument["tgFreq"] = trackGenSetting.Frequency;
jsonDocument["sg"] = sigGenOutputOn; //
jsonDocument["sgPower"] = sigGenSetting.Power;
jsonDocument["sgMod"] = sigGenSetting.ModulationType;
jsonDocument["sgModFreq"] = sigGenSetting.ModFrequency;
jsonDocument["sgFreq"] = sigGenSetting.Frequency;
jsonDocument["sgCal"] = sigGenSetting.Calibration;
jsonDocument["sgRange"] = ATTENUATOR_RANGE + 11; // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
jsonDocument["tgCal"] = trackGenSetting.Calibration;
jsonDocument["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so 20dBm output is possible.
if ( AGC_On )
jsonDocument["PreAmp"] = 0x60; // Auto
else
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
@ -714,13 +880,74 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
serializeJson ( jsonDocument, wsBuffer );
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
}
else
Serial.println ( "No buffer :(");
// Serial.printf ( "Push Settings sweepPoints %u\n", sweepPoints );
}
/*
* Push the settings data to the websocket clients
*/
void pushSigGenSettings ()
{
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
+ SCREEN_WIDTH*JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 17 );
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
jsonDocument["mType"] = "Settings";
jsonDocument["mode"] = setting.Mode;
jsonDocument["dispPoints"] = displayPoints;
jsonDocument["start"] = startFreq_IF / 1000.0;
jsonDocument["stop"] = stopFreq_IF / 1000.0;
jsonDocument["IF"] = setting.IF_Freq / 1000000.0;
jsonDocument["attenuation"] = setting.Attenuate;
jsonDocument["extGain"] = setting.ExternalGain;
jsonDocument["levelOffset"] = setting.LevelOffset;
jsonDocument["setRBW"] = setting.Bandwidth10;
jsonDocument["bandwidth"] = bandwidth;
jsonDocument["RefOut"] = setting.ReferenceOut;
jsonDocument["Drive"] = setting.Drive;
jsonDocument["sweepPoints"] = sweepPoints;
jsonDocument["spur"] = setting.Spur;
jsonDocument["tg"] = trackGenSetting.Mode;
jsonDocument["tgPower"] = trackGenSetting.Power;
jsonDocument["tgMod"] = trackGenSetting.ModulationType;
jsonDocument["tgModFreq"] = trackGenSetting.ModFrequency;
jsonDocument["tgFreq"] = trackGenSetting.Frequency;
jsonDocument["sg"] = sigGenOutputOn; //
jsonDocument["sgPower"] = sigGenSetting.Power;
jsonDocument["sgMod"] = sigGenSetting.ModulationType;
jsonDocument["sgModFreq"] = sigGenSetting.ModFrequency;
jsonDocument["sgFreq"] = sigGenSetting.Frequency;
jsonDocument["sgCal"] = sigGenSetting.Calibration;
jsonDocument["sgRange"] = (ATTENUATOR_RANGE + RX_SI4432_MAX_DRIVE * 3); // SI4432 output can be adjusted over 21dBm but max to SAW filter is 10dBm
jsonDocument["tgCal"] = trackGenSetting.Calibration;
jsonDocument["tgRange"] = ATTENUATOR_RANGE + 21; // no SAW filter so full 20dBm output is possible.
if ( AGC_On )
jsonDocument["PreAmp"] = 0x60; // Auto
else
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
String wsBuffer;
if ( wsBuffer )
{
serializeJson ( jsonDocument, wsBuffer );
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
}
else
Serial.println ( "No buffer :(");
// Serial.printf ( "Push Settings sweepPoints %u\n", sweepPoints );
}
/*
* Prepare a response ready for push to web clients
*/

View File

@ -33,21 +33,26 @@
#include <time.h>
#include <sys/time.h>
#define SSID_NAME "TinySA" // Name of access point
#define SSID_NAME "simpleSA" // Name of access point
/*
* Function prototypes:
*/
extern boolean startAP ();
extern boolean connectWiFi ();
extern void buildServer ();
extern void addTagNameValue ( char *b, char *_name, char *value );
extern char *escapeXML ( char *s );
extern void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t lenght );
extern char *FormatIPAddress ( IPAddress ipAddress );
boolean startAP ();
boolean connectWiFi ();
void buildServer ();
void addTagNameValue ( char *b, char *_name, char *value );
char *escapeXML ( char *s );
void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t lenght );
char *FormatIPAddress ( IPAddress ipAddress );
void pushSettings ();
void pushIFSweepSettings ();
void pushRXSweepSettings ();
void pushBandscopeSettings ();
void pushSigGenSettings ();
void initChunkSweepDoc (uint32_t startIndex);
/*
* Functions outside of "TinySA_wifi:

60
ui.cpp
View File

@ -197,7 +197,7 @@ uint8_t operation_requested = OP_NONE; // No operations so far
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_IFSIG, KM_TGOFFSET, KM_TGFREQ, KM_TGLO_DRIVE, KM_TGIF_DRIVE, KM_BANDSCOPESTART,
KM_WFMIN, KM_WFGAIN, KM_BANDSCOPELEVEL, KM_RXSPAN, KM_RXSIG, KM_RBW,
KM_EXTERN };
@ -216,7 +216,7 @@ static const char * const keypad_mode_label[] =
"START", "STOP", "CENTER", "SPAN", "FOCUS",
"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",
"IF Sig Freq", "TG OFFSET", "TG FREQ", "TG LO Drive", "TG IF Drive", "START",
"WF MIN", "WF GAIN", "REF LEVEL", "RX SPAN", "RX Sig Freq", "RBW",
"EXTERNAL"
};
@ -291,6 +291,7 @@ static void menu_WaterfallGain_cb ( int item );
static void menu_tracking_cb(int item); // M0WID - added in 3.0e
static void menu_tg_offset_cb(int item); // M0WID - added in 3.0e
static void menu_tg_frequency_cb(int item); // M0WID - added in 3.0e
static void menu_tgIF_drive_cb(int item); // M0WID - added in 3.0e
static void menu_tgLO_drive_cb(int item); // M0WID - added in 3.0e
@ -489,11 +490,13 @@ static Menuitem menu_tracking[] = // Tracking generator mode
{
Menuitem ( MT_FUNC, "OFF", menu_tracking_cb ),
Menuitem ( MT_FUNC, "ON", menu_tracking_cb ),
Menuitem ( MT_FUNC, "OFFSET", menu_tg_offset_cb ),
Menuitem ( MT_FUNC, "\2IF\0DRIVE", menu_tgIF_drive_cb ),
#ifdef SI_TG_LO_CS
Menuitem ( MT_FUNC, "GENERATE", menu_tracking_cb ),
Menuitem ( MT_FUNC, "FREQUENCY",menu_tg_frequency_cb ),
Menuitem ( MT_FUNC, "OFFSET", menu_tg_offset_cb ),
Menuitem ( MT_FUNC, "\2LO\0DRIVE", menu_tgLO_drive_cb ),
#endif
Menuitem ( MT_FUNC, "\2IF\0DRIVE", menu_tgIF_drive_cb ),
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
Menuitem ( MT_END ) // End marker
};
@ -1168,7 +1171,7 @@ void ShowSplash ( void )
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 0.01", 160, 100 );
tft.drawString ( PROGRAM_VERSION, 160, 100 );
tft.drawString ( "Original tinySA by Erik (PD0EK)", 160, 120 );
tft.setTextDatum ( TL_DATUM ); // Back to default top left
@ -1387,6 +1390,17 @@ void menu_tg_offset_cb ( int item )
ui_process_keypad ();
}
/*
* "menu_tg_frequency_cb" - Handles setting the tracking generator frequency when in sig gen mode
*/
void menu_tg_frequency_cb ( int item )
{
int km = KM_TGFREQ;
tft.fillScreen ( bg );
ui_mode_keypad ( km );
ui_process_keypad ();
}
/*
@ -1449,6 +1463,11 @@ static void menu_tracking_cb (int item )
ui_mode_normal (); // Back to sweep
break;
case 2: // Turn Sig gen mode
SetTracking (2);
ui_mode_normal (); // Back to sweep
break;
}
}
@ -2132,6 +2151,7 @@ static const keypads_t * const keypads_mode_tbl[] =
keypads_freq, // KM_IFSTOP.........IF Sweep stop frequency
keypads_freq, // KM_IFSIG..........IF Sweep signal frequency
keypads_signed_freq, // KM_TGOFFSET.......Offset Frequency of TG IF compared to SA IF
keypads_freq, // KM_TGFREQ.........Frequency of TG in sig gen mode
keypads_level, // KM_TGLO_DRIVE.....Tracking generator LO drive
keypads_level, // KM_TGIF_DRIVE.....Tracking generator IF drive
keypads_freq, // KM_BANDSCOPESTART.IF Sweep start frequency
@ -2521,6 +2541,10 @@ static void fetch_numeric_target ( void )
uistat.value = trackGenSetting.Offset;
break;
case KM_TGFREQ:
uistat.value = trackGenSetting.Frequency;
break;
case KM_TGIF_DRIVE:
uistat.value = trackGenSetting.IF_Drive;
break;
@ -2944,6 +2968,23 @@ static int keypad_click ( int key )
SetTGOffset ( (int32_t)value );
break;
case KM_TGFREQ:
if ( (value > MAX_SIGLO_FREQ) || (value < MIN_SIGLO_FREQ) )
{
strcpy ( fBuff, FormatSignedFrequency (( int32_t ) value ));
DisplayError ( ERR_WARN,
fBuff,
"Invalid Frequency!",
NULL,
NULL );
}
else
SetTGFreq ( (int32_t)value );
break;
case KM_TGIF_DRIVE:
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
{
@ -2957,6 +2998,8 @@ static int keypad_click ( int key )
SetTGIfDrive ( (uint8_t)value );
break;
#ifdef SI_TG_LO_CS
case KM_TGLO_DRIVE:
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
{
@ -2969,7 +3012,8 @@ static int keypad_click ( int key )
else
SetTGLoDrive ( (uint8_t)value );
break;
#endif
case KM_BANDSCOPESTART: // Bandscope Start frequency entered?
SetBandscopeStart (( int32_t ) value );
@ -3227,21 +3271,25 @@ void UiProcessTouch ( void )
if ( (touch_y < 10) && (touch_x < 160) )
{
marker[0].Toggle(); // marker 1
setting.MkrStatus[0] = marker[0].Status();
return;
}
else if ( (touch_y < 10) && (touch_x > 160) )
{
marker[2].Toggle(); // marker 3
setting.MkrStatus[2] = marker[2].Status();
return;
}
else if ( (touch_y < 20) && (touch_x < 160) )
{
marker[1].Toggle(); // marker 2
setting.MkrStatus[1] = marker[1].Status();
return;
}
else if ( (touch_y < 20) && (touch_x > 160) )
{
marker[3].Toggle(); // marker 4
setting.MkrStatus[3] = marker[3].Status();
return;
}
else if ( (touch_y < 40) && (touch_x > 30) )