commit
f36f478363
@ -237,14 +237,8 @@ static uint16_t chunkIndex;
|
|||||||
|
|
||||||
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
||||||
{
|
{
|
||||||
jsonDocument.clear ();
|
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
|
initChunkSweepDoc (autoSweepStep);
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain;
|
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
|
||||||
jsonDocument["StartIndex"] = 0;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
@ -395,12 +389,8 @@ static uint16_t chunkIndex;
|
|||||||
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
||||||
{
|
{
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
jsonDocument.clear();
|
initChunkSweepDoc (autoSweepStep);
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocument["StartIndex"] = autoSweepStep;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
|
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
IFsweep.ino
19
IFsweep.ino
@ -120,6 +120,7 @@ static uint16_t chunkIndex;
|
|||||||
} // initSweep || changedSetting
|
} // initSweep || changedSetting
|
||||||
|
|
||||||
autoSweepStep = 0; // Set the step counter to zero
|
autoSweepStep = 0; // Set the step counter to zero
|
||||||
|
sweepStep = 0;
|
||||||
autoSweepFreq = startFreq_IF; // Set the start frequency.
|
autoSweepFreq = startFreq_IF; // Set the start frequency.
|
||||||
|
|
||||||
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
||||||
@ -142,24 +143,16 @@ static uint16_t chunkIndex;
|
|||||||
|
|
||||||
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
||||||
{
|
{
|
||||||
jsonDocument.clear ();
|
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
|
||||||
jsonDocument["StartIndex"] = 0;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocInitialised = false;
|
jsonDocInitialised = false;
|
||||||
|
|
||||||
#endif // #ifdef USE_WIFI
|
#endif // #ifdef USE_WIFI
|
||||||
|
|
||||||
sweepStep = 0;
|
|
||||||
startFreq = startFreq_IF + sigFreq_IF; // Start freq for the LO
|
startFreq = startFreq_IF + sigFreq_IF; // Start freq for the LO
|
||||||
stopFreq = stopFreq_IF + sigFreq_IF; // Stop 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
|
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
||||||
{
|
{
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
jsonDocument.clear();
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocument["StartIndex"] = sweepStep;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
|
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
RXsweep.ino
19
RXsweep.ino
@ -126,6 +126,7 @@ static uint16_t chunkIndex;
|
|||||||
} // initSweep || changedSetting
|
} // initSweep || changedSetting
|
||||||
|
|
||||||
autoSweepStep = 0; // Set the step counter to zero
|
autoSweepStep = 0; // Set the step counter to zero
|
||||||
|
sweepStep = 0;
|
||||||
autoSweepFreq = startFreq_RX; // Set the start frequency.
|
autoSweepFreq = startFreq_RX; // Set the start frequency.
|
||||||
|
|
||||||
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
||||||
@ -148,24 +149,16 @@ static uint16_t chunkIndex;
|
|||||||
|
|
||||||
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
if ( numberOfWebsocketClients > 0 ) // Start off the json document for the scan
|
||||||
{
|
{
|
||||||
jsonDocument.clear ();
|
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain;
|
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
|
||||||
jsonDocument["StartIndex"] = 0;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocInitialised = false;
|
jsonDocInitialised = false;
|
||||||
|
|
||||||
#endif // #ifdef USE_WIFI
|
#endif // #ifdef USE_WIFI
|
||||||
|
|
||||||
sweepStep = 0;
|
|
||||||
startFreq = startFreq_RX; // Start freq for the RX
|
startFreq = startFreq_RX; // Start freq for the RX
|
||||||
stopFreq = stopFreq_RX; // Stop 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
|
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
||||||
{
|
{
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
jsonDocument.clear();
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocument["StartIndex"] = sweepStep;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
|
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
90
SigLo.ino
90
SigLo.ino
@ -107,6 +107,11 @@ void initSigLow()
|
|||||||
|
|
||||||
oldFreq = 0; // Force write of frequency on first loop
|
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 ()
|
void doSigGenLow ()
|
||||||
{
|
{
|
||||||
static uint32_t oldIF; // to store the current IF
|
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
|
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
|
||||||
|
|
||||||
@ -127,6 +136,29 @@ void doSigGenLow ()
|
|||||||
showUpDownButtons = 1;
|
showUpDownButtons = 1;
|
||||||
#endif
|
#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
|
// 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
|
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 5:
|
||||||
case 6:
|
case 6:
|
||||||
incrementFreq( pow(10, 8-b) );
|
incrementFreq( pow(10, 8-b) );
|
||||||
|
changedSetting=true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: // Decrement buttons
|
case 7: // Decrement buttons
|
||||||
@ -164,6 +197,7 @@ void doSigGenLow ()
|
|||||||
case 12:
|
case 12:
|
||||||
case 13:
|
case 13:
|
||||||
decrementFreq( pow(10, 15-b) );
|
decrementFreq( pow(10, 15-b) );
|
||||||
|
changedSetting=true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 14: // Return to SAlo mode
|
case 14: // Return to SAlo mode
|
||||||
@ -172,21 +206,6 @@ void doSigGenLow ()
|
|||||||
|
|
||||||
case 15: // toggle the output on/off
|
case 15: // toggle the output on/off
|
||||||
sigGenOutputOn = !sigGenOutputOn;
|
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;
|
break;
|
||||||
|
|
||||||
case 16: // launch menu
|
case 16: // launch menu
|
||||||
@ -225,6 +244,33 @@ void doSigGenLow ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
} // end of keys loop
|
||||||
|
|
||||||
|
|
||||||
@ -232,12 +278,15 @@ void doSigGenLow ()
|
|||||||
// Check if slider touched
|
// Check if slider touched
|
||||||
if ( sliderPressed( pressed, t_x, t_y) )
|
if ( sliderPressed( pressed, t_x, t_y) )
|
||||||
{
|
{
|
||||||
float p = sliderPercent( t_x ); // position of slider in %
|
p = sliderPercent( t_x ); // position of slider in %
|
||||||
float pwr = p * (ATTENUATOR_RANGE)/100.0 + sigGenSetting.Calibration - ATTENUATOR_RANGE;
|
float pwr = p * (sliderRange)/100.0 + sigGenSetting.Calibration - sliderRange;
|
||||||
|
|
||||||
drawSlider ( SLIDER_X, SLIDER_Y, p, pwr, "dBm" );
|
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;
|
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)
|
if (sigGenOutputOn)
|
||||||
{
|
{
|
||||||
delayMicroseconds(300);
|
delayMicroseconds(300);
|
||||||
SetRX(3);
|
SetRX(3); // both LO and RX in tx mode
|
||||||
}
|
}
|
||||||
|
changedSetting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
oldFreq = sigGenSetting.Frequency;
|
oldFreq = sigGenSetting.Frequency;
|
||||||
oldIF = setting.IF_Freq;
|
oldIF = setting.IF_Freq;
|
||||||
|
oldSigGenOutputOn = sigGenOutputOn;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
44
SweepLo.ino
44
SweepLo.ino
@ -73,6 +73,7 @@ static bool resetAverage; // Flag to indicate a setting has changed and avera
|
|||||||
static bool jsonDocInitialised = false;
|
static bool jsonDocInitialised = false;
|
||||||
static uint16_t chunkIndex;
|
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 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();
|
tg_lo.RxMode();
|
||||||
#endif
|
#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
|
} // initSweep || changedSetting
|
||||||
|
|
||||||
autoSweepStep = 0; // Set the step counter to zero
|
autoSweepStep = 0; // Set the step counter to zero
|
||||||
|
sweepStep = 0;
|
||||||
autoSweepFreq = setting.ScanStart; // Set the start frequency.
|
autoSweepFreq = setting.ScanStart; // Set the start frequency.
|
||||||
|
|
||||||
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
|
||||||
@ -207,6 +218,12 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
|
|||||||
tempIF = offsetIF;
|
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;
|
spurToggle = !spurToggle;
|
||||||
@ -225,7 +242,7 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
|
|||||||
|
|
||||||
#ifdef SI_TG_IF_CS
|
#ifdef SI_TG_IF_CS
|
||||||
if (tgIF_OK && (trackGenSetting.Mode == 1) )
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,13 +250,11 @@ static uint32_t offsetIF; // IF frequency offset by half the bandwidth to pos
|
|||||||
|
|
||||||
#ifdef SI_TG_LO_CS
|
#ifdef SI_TG_LO_CS
|
||||||
if (tgLO_OK && (trackGenSetting.Mode == 1) )
|
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
|
#endif
|
||||||
|
|
||||||
setFreqMicros = micros(); // Store the time the frequency was changed
|
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
|
* 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 ();
|
jsonDocument.clear ();
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
|
||||||
jsonDocument["StartIndex"] = 0;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocInitialised = false;
|
jsonDocInitialised = false;
|
||||||
|
|
||||||
#endif // #ifdef USE_WIFI
|
#endif // #ifdef USE_WIFI
|
||||||
|
|
||||||
sweepStep = 0;
|
|
||||||
startFreq = setting.ScanStart + tempIF; // Start freq for the LO
|
startFreq = setting.ScanStart + tempIF; // Start freq for the LO
|
||||||
stopFreq = setting.ScanStop + tempIF; // Stop 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("webSocketTimeout");
|
||||||
Serial.println(wsBuffer);
|
Serial.println(wsBuffer);
|
||||||
|
websocketFailCount++;
|
||||||
|
if (websocketFailCount > 2)
|
||||||
numberOfWebsocketClients = 0;
|
numberOfWebsocketClients = 0;
|
||||||
|
} else {
|
||||||
|
websocketFailCount = 0; // reset if OK
|
||||||
}
|
}
|
||||||
// Serial.print("j");
|
// 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
|
if ( ( chunkIndex >= wiFiPoints ) || !jsonDocInitialised ) // Start new jSon document
|
||||||
{
|
{
|
||||||
chunkIndex = 0;
|
chunkIndex = 0;
|
||||||
jsonDocument.clear();
|
initChunkSweepDoc (sweepStep);
|
||||||
jsonDocument["mType"] = "chunkSweep";
|
Points = jsonDocument.createNestedArray ( "Points" ); // Add Points array
|
||||||
jsonDocument["StartIndex"] = sweepStep;
|
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
|
||||||
jsonDocument["sweepTime"] = (uint32_t)(sweepMicros/1000);
|
|
||||||
Points = jsonDocument.createNestedArray ("Points" ); // Add Points array
|
|
||||||
jsonDocInitialised = true;
|
jsonDocInitialised = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
177
cmd.cpp
177
cmd.cpp
@ -106,6 +106,7 @@ extern uint32_t colourTest;
|
|||||||
|
|
||||||
extern Marker marker[MARKER_COUNT]; // Array of marker objects
|
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?
|
* 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
|
{ "RXSWEEP", MSG_RX_SWEEP }, // Set RX Sweep Mode
|
||||||
{ "RXSIGNAL", MSG_RXSIGNAL }, // IF sweep signal frequency
|
{ "RXSIGNAL", MSG_RXSIGNAL }, // IF sweep signal frequency
|
||||||
{ "EXTGAIN", MSG_EXTGAIN }, // External gain or attenuation
|
{ "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
|
{ "", MSG_NONE } // Unrecognized command
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -196,7 +204,7 @@ int msgCount = ELEMENTS ( msgTable);
|
|||||||
|
|
||||||
void ShowMenu ()
|
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.println ( "Sweep Settings:\n" );
|
||||||
|
|
||||||
Serial.print ( " START.........Sweep start frequency, currently: " );
|
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 ( " 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.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 ( "\nSignal Generator Commands:\n" );
|
||||||
Serial.println ( setting.Drive );
|
|
||||||
|
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.print ( " SGLODRIVE.....Local oscillator drive level in signal generator mode [0 to 7]; currently: " );
|
||||||
Serial.println ( sigGenSetting.LO_Drive );
|
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 );
|
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.print ( " TGLODRIVE.....Local oscillator drive level in tracking generator mode [0 to 7]; currently: " );
|
||||||
Serial.println ( trackGenSetting.LO_Drive );
|
Serial.println ( trackGenSetting.LO_Drive );
|
||||||
|
#endif
|
||||||
Serial.print ( " TGIFDRIVE.....Local oscillator drive level in tracking generator mode [0 to 7]; currently: " );
|
Serial.print ( " TGIFDRIVE.....Local oscillator drive level in tracking generator mode [0 to 7]; currently: " );
|
||||||
Serial.println ( trackGenSetting.IF_Drive );
|
Serial.println ( trackGenSetting.IF_Drive );
|
||||||
|
#ifdef SI_TG_LO_CS
|
||||||
Serial.print ( " TGOFFSET......Tracking generator offset from SA IF; currently: " );
|
Serial.print ( " TGOFFSET......Tracking generator offset from SA IF; currently: " );
|
||||||
Serial.println ( trackGenSetting.Offset );
|
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]" );
|
Serial.println ( " SAVE .........Save the current scan configuration [0 to 4]" );
|
||||||
|
|
||||||
@ -759,6 +795,29 @@ uint8_t reg69; // Ditto
|
|||||||
|
|
||||||
return true;
|
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.
|
* 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
|
tempValue = atoi ( dataBuff ); // Yes, convert to a number
|
||||||
|
|
||||||
if (( tempValue < MIN_DRIVE ) || ( tempValue > MAX_DRIVE ))
|
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
|
else // Set the transmitter drive level
|
||||||
SetSGLoDrive ( tempValue ); // "SetSGLoDrive" saves the settings
|
SetSGLoDrive ( tempValue ); // "SetSGLoDrive" saves the settings
|
||||||
}
|
}
|
||||||
@ -781,17 +840,17 @@ uint8_t reg69; // Ditto
|
|||||||
return true;
|
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:
|
case MSG_SG_RX_DRIVE:
|
||||||
if ( dataLen != 0 ) // Drive level specified?
|
if ( dataLen != 0 ) // Drive level specified?
|
||||||
{
|
{
|
||||||
tempValue = atoi ( dataBuff ); // Yes, convert to a number
|
tempValue = atoi ( dataBuff ); // Yes, convert to a number
|
||||||
|
|
||||||
if (( tempValue < MIN_DRIVE ) || ( tempValue > MAX_DRIVE ))
|
if (( tempValue < MIN_DRIVE ) || ( tempValue > RX_SI4432_MAX_DRIVE ))
|
||||||
Serial.printf ( "Invalid drive specification: %d\n", tempValue );
|
Serial.printf ( "Invalid RX drive: %d - (%d-%d)\n", tempValue, MIN_DRIVE, RX_SI4432_MAX_DRIVE );
|
||||||
else // Set the transmitter drive level
|
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] );
|
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;
|
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
|
#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.
|
* The "TGLODRIVE" command sets the local oscillator "drive" level in tracking generator mode.
|
||||||
* (only valid if two SI4432 used for the tracking generator)
|
* (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!!!!!!!!!!!!!!!!!!!
|
Serial.printf ( "Tracking Generator IF offset: %i\n", trackGenSetting.Offset ); // sort out signed version of format frequency!!!!!!!!!!!!!!!!!!!
|
||||||
return true;
|
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"
|
* "SetPowerLevel"
|
||||||
|
* Adjusts displayed power to match the actual input signal power - calibration function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SetPowerLevel ( double o )
|
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.
|
* "SetSGLoDrive" sets the transmitter max output level in signal generator mode.
|
||||||
*
|
*
|
||||||
@ -2479,13 +2591,16 @@ int oldLevel = sigGenSetting.LO_Drive;
|
|||||||
* 1 => +2dBm 5 => +14dBm
|
* 1 => +2dBm 5 => +14dBm
|
||||||
* 2 => +5dBm 6 => +17dBm
|
* 2 => +5dBm 6 => +17dBm
|
||||||
* 3 => +8dBm 7 => +20dBm
|
* 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 )
|
void SetSGRxDrive ( uint8_t level )
|
||||||
{
|
{
|
||||||
int oldLevel = sigGenSetting.RX_Drive;
|
int oldLevel = sigGenSetting.RX_Drive;
|
||||||
|
|
||||||
if (( level < 0 ) || ( level > 7 ))
|
if (( level < 0 ) || ( level > RX_SI4432_MAX_DRIVE ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
else
|
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
|
#ifdef SI_TG_LO_CS
|
||||||
/*
|
/*
|
||||||
* "SetTGLoDrive" sets the transmitter max output level for the tracking generator.
|
* "SetTGLoDrive" sets the transmitter max output level for the tracking generator.
|
||||||
@ -2618,6 +2747,28 @@ int32_t GetTGOffset ( )
|
|||||||
return trackGenSetting.Offset;
|
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
|
* "SetSweepStart" and "GetSweepStart" were added in Version 2.3. They used to be in
|
||||||
|
11
cmd.h
11
cmd.h
@ -78,6 +78,13 @@
|
|||||||
#define MSG_RX_SWEEP 49 // Set the RX Sweep Mode
|
#define MSG_RX_SWEEP 49 // Set the RX Sweep Mode
|
||||||
#define MSG_RXSIGNAL 50 // Set frequency of injected signal for IF Sweep
|
#define MSG_RXSIGNAL 50 // Set frequency of injected signal for IF Sweep
|
||||||
#define MSG_EXTGAIN 51 // Set external gain or attenuation
|
#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!
|
#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
|
bool SetIFFrequency ( int32_t f ); // Sets the IF frequency
|
||||||
|
|
||||||
void SetLoDrive ( uint8_t level ); // Sets LO Si4432 output level
|
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 SetSGLoDrive ( uint8_t level );
|
||||||
void SetSGRxDrive ( 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 SetTracking ( int8_t m ); // set tracking generator mode
|
||||||
void SetTGLoDrive ( uint8_t level ); // set tracking generator drive
|
void SetTGLoDrive ( uint8_t level ); // set tracking generator drive
|
||||||
void SetTGIfDrive ( uint8_t level );
|
void SetTGIfDrive ( uint8_t level );
|
||||||
bool SetTGOffset ( int32_t offset); // set tracking generator offset - returns false if invalid
|
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 );
|
int32_t GetTGOffset (void );
|
||||||
void SetTGPower ( int16_t dBm ); // Set TG attenuator and drive levels
|
void SetTGPower ( int16_t dBm ); // Set TG attenuator and drive levels
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>[TinySA]</title>
|
<title>[simpleSA]</title>
|
||||||
<link rel="stylesheet" type="text/css" href="styles.css" media="all" />
|
<link rel="stylesheet" type="text/css" href="styles.css" media="all" />
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
@ -46,8 +46,8 @@
|
|||||||
<h1>About</h1>
|
<h1>About</h1>
|
||||||
|
|
||||||
<p style="max-width:700px;">
|
<p style="max-width:700px;">
|
||||||
The TinySA has been developed by Erik PD0EK.
|
This simpleSA running on an ESP32 has been adapted by Dave M0WID and John WA2FZW.<br />
|
||||||
This version has been adapted to run on the ESP32 DevKit module by Dave M0WID and John WA2FZW.
|
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>
|
Information can be found at <a href = "https://groups.io/g/HBTE">https://groups.io/g/HBTE</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -58,6 +58,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id=footer>Copyright © <span id="programCopyright"></span></div>
|
<div id=footer>Copyright © <span id="programCopyright">M0WID and WA2FZW</span></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
539
data/index.html
539
data/index.html
@ -32,7 +32,7 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>TinySA-ESP</title>
|
<title>simpleSA</title>
|
||||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
<!-- get file below from http://canvasjs.com/ -->
|
<!-- get file below from http://canvasjs.com/ -->
|
||||||
<script type="text/javascript" src="canvasjs.min.js"></script>
|
<script type="text/javascript" src="canvasjs.min.js"></script>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="min-width:100vw">
|
<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="homeButton" onclick="window.location.href='index.html';">Home</button>
|
||||||
<!-- <button id="settingsButton" onclick="window.location.href='settings.html';">Settings</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>
|
<button id="aboutButton" onclick="window.location.href='about.html';">About</button>
|
||||||
</div>
|
</div>
|
||||||
<div class ="Grid">
|
<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 </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 />
|
<br />
|
||||||
|
|
||||||
<div class = "Grid-cell-side" id="postSweepSettings" >
|
<div class = "Grid-cell-side" id="postSweepSettings" >
|
||||||
<!--<form style="width: 90vw; margin-left: 80px" action="doSetSweep" method="get"> -->
|
<!--<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" >
|
<div class="setting" >
|
||||||
<label for="setStart" class="setting-label">Start:</label>
|
<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>
|
<input class="value-input" name='setStart' type="number" id="setStart" maxlength="9" min="0" max="350" required>
|
||||||
@ -113,9 +167,10 @@
|
|||||||
<br />
|
<br />
|
||||||
<div class="setting" >
|
<div class="setting" >
|
||||||
<label for="setAtten" class="setting-label">Atten:</label>
|
<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>
|
<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> -->
|
<!--<select class="select-input" id="setAtten" name="setAtten"></select> -->
|
||||||
dB
|
dB
|
||||||
</div>
|
</div>
|
||||||
@ -137,25 +192,36 @@
|
|||||||
<br />
|
<br />
|
||||||
<div id="spur">
|
<div id="spur">
|
||||||
<div class="setting" >
|
<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" />
|
<input class="checkbox-input" type="checkbox" id="spurReduction" size="1" value="0" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tracking">
|
<div id="tracking">
|
||||||
<div class="setting" >
|
<div class="setting" >
|
||||||
<label class="setting-label">TrackGen:</label>
|
<label class="setting-label">TrackGen:</label>
|
||||||
<input class="checkbox-input" type="checkbox" id="trackGen" size="1" value="0" />
|
<select class="select-input" id="trackGen" name="trackGen">
|
||||||
<input class="value-input" type="number" id="setTrackGenPower" placeholder="setTrackGenPower" maxlength = "9" min="-60" max="20" value="0" />
|
<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
|
dBm
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div id="signal_info">
|
<div id="signal_info">
|
||||||
<div class="setting" >
|
<div class="setting" >
|
||||||
<label class="setting-label">Points:</label>
|
<input class="sweep-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
|
||||||
<input class="value-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
|
pts
|
||||||
<label class="setting-label">Time:</label>
|
<input class="sweep-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
|
||||||
<input class="value-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
|
|
||||||
ms
|
ms
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -179,7 +245,7 @@
|
|||||||
dB
|
dB
|
||||||
</div>
|
</div>
|
||||||
<div class="setting" >
|
<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" />
|
<input class="value-input" type="number" id="setPowerValue" placeholder="setPowerValue" maxlength = "9" min="-60" max="20" value="0" />
|
||||||
dBm
|
dBm
|
||||||
</div>
|
</div>
|
||||||
@ -257,8 +323,9 @@
|
|||||||
<div style="width: 100px; display: inline-block">Pings:
|
<div style="width: 100px; display: inline-block">Pings:
|
||||||
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
|
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
|
||||||
</div>
|
</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" />
|
<input class="value-input" type="number" id="refreshInterval" size="3" min="100" max="3000" value="500" />
|
||||||
|
ms
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -268,8 +335,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<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 refreshInterval = document.getElementById('refreshInterval');
|
||||||
|
|
||||||
|
var refresh = document.getElementById('refresh');
|
||||||
|
var setMode = document.getElementById('setMode');
|
||||||
var sweepStart = document.getElementById('sweepStart');
|
var sweepStart = document.getElementById('sweepStart');
|
||||||
var sweepStop = document.getElementById('sweepStop');
|
var sweepStop = document.getElementById('sweepStop');
|
||||||
var setStart = document.getElementById('setStart');
|
var setStart = document.getElementById('setStart');
|
||||||
@ -292,12 +368,28 @@ var setPreAmp = document.getElementById('setPreAmp');
|
|||||||
var setAverage = document.getElementById('Average');
|
var setAverage = document.getElementById('Average');
|
||||||
var setTrackGen = document.getElementById('trackGen');
|
var setTrackGen = document.getElementById('trackGen');
|
||||||
var setTrackGenPower = document.getElementById('setTrackGenPower');
|
var setTrackGenPower = document.getElementById('setTrackGenPower');
|
||||||
|
var setTGFreq = document.getElementById('setTGFreq');
|
||||||
var store1 = document.getElementById('store1');
|
var store1 = document.getElementById('store1');
|
||||||
var store2 = document.getElementById('store2');
|
var store2 = document.getElementById('store2');
|
||||||
var store3 = document.getElementById('store3');
|
var store3 = document.getElementById('store3');
|
||||||
var store4 = document.getElementById('store4');
|
var store4 = document.getElementById('store4');
|
||||||
//var messageWindow = document.getElementById('message');
|
//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;
|
var tempCenter;
|
||||||
|
|
||||||
// initialise these to silly values to force an update first time round
|
// initialise these to silly values to force an update first time round
|
||||||
@ -316,6 +408,13 @@ var oldSweepPoints = 0;
|
|||||||
var oldSpur = 2;
|
var oldSpur = 2;
|
||||||
var oldTrackGen = 2;
|
var oldTrackGen = 2;
|
||||||
var oldTrackGenPower = 1000;
|
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
|
// Chart configuration - Scope
|
||||||
var RSSISamples = [
|
var RSSISamples = [
|
||||||
@ -410,17 +509,28 @@ var chartSA = new CanvasJS.Chart("chartSA",
|
|||||||
zoomType: "xy",
|
zoomType: "xy",
|
||||||
//height:800,
|
//height:800,
|
||||||
title: {
|
title: {
|
||||||
text: "ESP32 TinySA",
|
text: "simpleSA",
|
||||||
fontSize: 28
|
fontSize: 28
|
||||||
},
|
},
|
||||||
axisX: {
|
axisX: {
|
||||||
title: "Frequency (MHz)",
|
title: "Frequency (MHz)",
|
||||||
titleFontSize: 24
|
titleFontSize: 24,
|
||||||
|
gridThickness: 1,
|
||||||
|
gridColor: "WhiteSmoke",
|
||||||
|
stripLines:[
|
||||||
|
{
|
||||||
|
startValue:50,
|
||||||
|
thickness:1,
|
||||||
|
color:"#d8d8d8",
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
axisY:
|
axisY:
|
||||||
{
|
{
|
||||||
title: "dB",
|
title: "dBm",
|
||||||
titleFontSize: 24,
|
titleFontSize: 24,
|
||||||
|
gridThickness: 1,
|
||||||
|
gridColor: "WhiteSmoke",
|
||||||
minimum: -120
|
minimum: -120
|
||||||
},
|
},
|
||||||
axisY2: [
|
axisY2: [
|
||||||
@ -439,6 +549,7 @@ var chartSA = new CanvasJS.Chart("chartSA",
|
|||||||
exportEnabled: true,
|
exportEnabled: true,
|
||||||
legend: {
|
legend: {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
|
fontSize: 16,
|
||||||
itemclick: function (e) {
|
itemclick: function (e) {
|
||||||
//console.log("legend click: " + e.dataPointIndex);
|
//console.log("legend click: " + e.dataPointIndex);
|
||||||
//console.log(e);
|
//console.log(e);
|
||||||
@ -526,6 +637,13 @@ renderChart();
|
|||||||
|
|
||||||
// Add handlers for the change events in the input fields
|
// 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) => {
|
setStart.addEventListener('change', (event) => {
|
||||||
sendValue("a", setStart.value);
|
sendValue("a", setStart.value);
|
||||||
@ -589,13 +707,17 @@ setSpur.addEventListener('change', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTrackGen.addEventListener('change', (event) => {
|
setTrackGen.addEventListener('change', (event) => {
|
||||||
if (setTrackGen.checked) {
|
sendValue("t", setTrackGen.value);
|
||||||
sendValue("t", 1);
|
|
||||||
} else {
|
|
||||||
sendValue("t", 0);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTrackGenPower.addEventListener('change', (event) => {
|
||||||
|
sendValue("T", setTrackGenPower.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
setTGFreq.addEventListener('change', (event) => {
|
||||||
|
sendValue("f", setTGFreq.value);
|
||||||
|
});
|
||||||
|
|
||||||
store1.addEventListener('change', (event) => {
|
store1.addEventListener('change', (event) => {
|
||||||
if (store1.checked) {
|
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 roundtripTime = document.getElementById('roundtripTime');
|
||||||
//var messageCount = document.getElementById('messageCount');
|
//var messageCount = document.getElementById('messageCount');
|
||||||
//var missedReplies = document.getElementById('missedReplies');
|
//var missedReplies = document.getElementById('missedReplies');
|
||||||
@ -685,7 +989,7 @@ function renderChart()
|
|||||||
//missedReplies.value = missedMessageCounter;
|
//missedReplies.value = missedMessageCounter;
|
||||||
hostName.value = "ws://" + location.host + ":81";
|
hostName.value = "ws://" + location.host + ":81";
|
||||||
|
|
||||||
// connect to TinySA server
|
// connect to simpleSA server
|
||||||
connect(hostName.value);
|
connect(hostName.value);
|
||||||
|
|
||||||
// At this point the page is running
|
// At this point the page is running
|
||||||
@ -703,6 +1007,95 @@ var indexUpdateMilliSeconds = 1 * 1000;
|
|||||||
|
|
||||||
function handleSettings (settings)
|
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;
|
actRBW.value = settings.bandwidth;
|
||||||
|
|
||||||
|
|
||||||
@ -774,16 +1167,43 @@ function handleSettings (settings)
|
|||||||
oldSpur = settings.spur;
|
oldSpur = settings.spur;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.tg != oldTrackGen) {
|
if (settings.sg != oldSigGen) { // Sig gen on/off
|
||||||
if (settings.tg) {
|
sigOnButton.value = settings.sg;
|
||||||
setTrackGen.checked = true; // Tracking Generator checkbox
|
oldSigGen = settings.sg;
|
||||||
} else {
|
styleSigGenButton (sigOnButton.value);
|
||||||
setTrackGen.checked = false; // Tracking Generator checkbox
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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;
|
setTrackGenPower.value = settings.tgPower;
|
||||||
oldTrackGenPower = settings.tgPower;
|
oldTrackGenPower = settings.tgPower;
|
||||||
}
|
}
|
||||||
@ -1096,16 +1516,18 @@ function connect(host)
|
|||||||
sendMessage();
|
sendMessage();
|
||||||
sendPingVar = setInterval(function(){ sendPing() }, 30000);
|
sendPingVar = setInterval(function(){ sendPing() }, 30000);
|
||||||
|
|
||||||
// Get the settings to make sure current
|
sendValue("r",0); // request settings
|
||||||
$.getJSON( "getSettings")
|
|
||||||
.done(function (settings) {
|
|
||||||
handleSettings(settings);
|
|
||||||
})
|
|
||||||
|
|
||||||
.fail(function(jqxhr, textStatus, error) {
|
// Get the settings to make sure current
|
||||||
var err = textStatus +", " + error;
|
//$.getJSON( "getSettings")
|
||||||
console.log("Settings Request Failed: " + err);
|
// .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 items = document.querySelectorAll(".value-input");
|
||||||
var i;
|
var i;
|
||||||
@ -1119,6 +1541,18 @@ function connect(host)
|
|||||||
items[i].disabled = false;
|
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)
|
connection.onclose = function(event)
|
||||||
@ -1141,6 +1575,18 @@ function connect(host)
|
|||||||
items[i].disabled = true;
|
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)
|
connection.onerror = function(error)
|
||||||
@ -1176,7 +1622,7 @@ function connect(host)
|
|||||||
}
|
}
|
||||||
else if (myObject.mType == "chunkSweep")
|
else if (myObject.mType == "chunkSweep")
|
||||||
{
|
{
|
||||||
console.log("handle chunk Sweep:" + myObject.StartIndex);
|
//console.log("handle chunk Sweep:" + myObject.StartIndex);
|
||||||
handleChunkData(myObject);
|
handleChunkData(myObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1210,19 +1656,30 @@ function sendValue(c, val)
|
|||||||
// s Span
|
// s Span
|
||||||
// d Local Oscillator Drive
|
// d Local Oscillator Drive
|
||||||
// g PreAmpGain/Mode
|
// g PreAmpGain/Mode
|
||||||
// p set actual power to peak value
|
|
||||||
// i IF frequency
|
// i IF frequency
|
||||||
|
// m mode
|
||||||
|
// p set actual power to peak value
|
||||||
// o RefOut
|
// o RefOut
|
||||||
|
// r request Settings are pushed
|
||||||
// A internal attenuation (PE4302)
|
// A internal attenuation (PE4302)
|
||||||
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
|
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
|
||||||
// R requested RBW
|
// R requested RBW
|
||||||
// S Spur reduction Off/On
|
// S Spur reduction Off/On
|
||||||
// t trackGen Off/On/Fixed
|
// t trackGen Off/On/Fixed
|
||||||
// T trackGen output level
|
// 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("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
|
||||||
|
if (connectionStatus.value == "Connected") {
|
||||||
connection.send("#" + c + " " + val);
|
connection.send("#" + c + " " + val);
|
||||||
console.log("Command:" + c + val);
|
console.log("Command:" + c + val);
|
||||||
|
} else {
|
||||||
|
console.log("No connection - Command:" + c + val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -627,7 +627,7 @@ store1.addEventListener('change', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
store2.addEventListener('change', (event) => {
|
store2.addEventListener('change', (event) => {
|
||||||
if (store1.checked) {
|
if (store2.checked) {
|
||||||
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
||||||
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
||||||
let rObj = {}
|
let rObj = {}
|
||||||
@ -641,7 +641,7 @@ store2.addEventListener('change', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
store3.addEventListener('change', (event) => {
|
store3.addEventListener('change', (event) => {
|
||||||
if (store1.checked) {
|
if (store3.checked) {
|
||||||
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
||||||
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
||||||
let rObj = {}
|
let rObj = {}
|
||||||
@ -655,7 +655,7 @@ store3.addEventListener('change', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
store4.addEventListener('change', (event) => {
|
store4.addEventListener('change', (event) => {
|
||||||
if (store1.checked) {
|
if (store4.checked) {
|
||||||
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
|
||||||
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
||||||
let rObj = {}
|
let rObj = {}
|
||||||
|
BIN
data/refresh.png
Normal file
BIN
data/refresh.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 655 B |
976
data/siggen.html
Normal file
976
data/siggen.html
Normal 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>
|
156
data/styles.css
156
data/styles.css
@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.norm {
|
.norm {
|
||||||
width: 100%;
|
width: 95%;
|
||||||
height: 3vh;
|
height: 3vh;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
@ -127,6 +127,14 @@ input[type="number"] {
|
|||||||
background-color: lightgrey;
|
background-color: lightgrey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sweep-display {
|
||||||
|
border: 0;
|
||||||
|
text-align: right;
|
||||||
|
width: 65px;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
.message-display {
|
.message-display {
|
||||||
border: 0;
|
border: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -156,17 +164,47 @@ input[type="number"] {
|
|||||||
border: solid 1px grey;
|
border: solid 1px grey;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-align-last: right;
|
text-align-last: right;
|
||||||
width: 75px;
|
width: 77px;
|
||||||
display: inline-block;
|
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 {
|
.select-option {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-align-last: right;
|
text-align-last: right;
|
||||||
}
|
}
|
||||||
|
.sweep-option {
|
||||||
|
text-align: left;
|
||||||
|
text-align-last: left;
|
||||||
|
}
|
||||||
|
|
||||||
.set-button {
|
.inc-button {
|
||||||
|
width: 60px;
|
||||||
|
height: 30px;
|
||||||
font-size: 14px;
|
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 {
|
.setting {
|
||||||
@ -176,8 +214,120 @@ input[type="number"] {
|
|||||||
.setting-label {
|
.setting-label {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
display: inline-block;
|
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 {
|
TH, .bold {
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
color: black;
|
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;
|
||||||
|
}
|
||||||
|
4
my_SA.h
4
my_SA.h
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#define USE_WIFI true // Changed in Version 2.6 to true/false
|
#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 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_SSID ":)" // SSID of your WiFi if not using access point
|
||||||
#define WIFI_PASSWORD "S0ftR0ckRXTX" // Password for your WiFi
|
#define WIFI_PASSWORD "S0ftR0ckRXTX" // Password for your WiFi
|
||||||
@ -64,6 +65,9 @@
|
|||||||
// #define SLIDER_MAX_POWER -13.0
|
// #define SLIDER_MAX_POWER -13.0
|
||||||
#define ATTENUATOR_RANGE 30 // in dB
|
#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
|
* These definitions control the values that get set when you select "AUTO SETTINGS" from
|
||||||
|
@ -272,7 +272,7 @@ const char* unit[4] = { "RX", "TX", "TGIF", "TGLO" }; // For debugging
|
|||||||
|
|
||||||
WriteByte ( REG_OFC1, SW_RESET ); // Always perform a system reset
|
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 );
|
regRead = ReadByte ( REG_IS2 );
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define PROGRAM_NAME "simpleSA" // These are for the WiFi interface
|
#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,
|
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 };
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
48
simpleSA.ino
48
simpleSA.ino
@ -127,11 +127,20 @@
|
|||||||
* Additional functions in ui.cmd to allow signed frequency entry.
|
* Additional functions in ui.cmd to allow signed frequency entry.
|
||||||
*
|
*
|
||||||
* Version 3.0f Changes by M0WID
|
* Version 3.0f Changes by M0WID
|
||||||
|
*
|
||||||
|
* Version 0.03
|
||||||
* renamed simpleSA. Doesn't seem that simple to me!
|
* renamed simpleSA. Doesn't seem that simple to me!
|
||||||
* First go at bandscope mode
|
* First go at bandscope mode
|
||||||
* VSPI reduced to 10Mhz as some boards will not run at 16MHz
|
* 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!
|
* 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
|
uint16_t wiFiPoints; // Push data to the wifi clinets when this many points collected
|
||||||
unsigned long wiFiTargetTime = WIFI_UPDATE_TARGET_TIME;
|
unsigned long wiFiTargetTime = WIFI_UPDATE_TARGET_TIME;
|
||||||
unsigned long websocketInterval = WEBSOCKET_INTERVAL;
|
unsigned long websocketInterval = WEBSOCKET_INTERVAL;
|
||||||
|
uint16_t websocketFailCount;
|
||||||
|
|
||||||
#ifdef USE_WIFI
|
#ifdef USE_WIFI
|
||||||
// Json document buffers
|
// Json document buffers
|
||||||
size_t capacity = JSON_ARRAY_SIZE ( MAX_WIFI_POINTS + 1 )
|
//size_t capacity = JSON_ARRAY_SIZE ( MAX_WIFI_POINTS + 1 )
|
||||||
+ ( MAX_WIFI_POINTS + 1 ) * JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE( 5 );
|
// + ( 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
|
static JsonArray Points = jsonDocument.createNestedArray ( "Points" ); // add Points array
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -380,7 +390,7 @@ int16_t minGrid;
|
|||||||
* Some varibales for the various operating modes
|
* Some varibales for the various operating modes
|
||||||
*/
|
*/
|
||||||
uint16_t tinySA_mode = SA_LOW_RANGE; // Low frequency range
|
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)
|
float bandwidth; // The current bandwidth (not * 10)
|
||||||
@ -503,7 +513,7 @@ uint16_t spacing = 10000;
|
|||||||
|
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
|
||||||
bool sigGenOutputOn = false;
|
uint16_t sigGenOutputOn = false;
|
||||||
uint32_t oldFreq; // to store the current Signal Generator frequency
|
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
|
// If the tracking generator IF SI4432 is defined, then check to see if it is connected
|
||||||
tgIF_OK = false;
|
tgIF_OK = false;
|
||||||
|
|
||||||
#ifdef SI_TG_IF_CS
|
#ifdef SI_TG_IF_CS
|
||||||
// pinMode (SI_TG_IF_CS, INPUT); //Start off in input mode, no pullup
|
// pinMode (SI_TG_IF_CS, INPUT); //Start off in input mode, no pullup
|
||||||
// delay(2);
|
// delay(2);
|
||||||
@ -680,6 +691,8 @@ bool fsStatus = false; // True if SPIFFS loads ok
|
|||||||
// delay(2);
|
// delay(2);
|
||||||
// tgIF_OK = tg_if.Init ( config.tgIF_capacitance );
|
// 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 ) )
|
if ( tg_if.Init ( config.tgIF_capacitance ) )
|
||||||
{
|
{
|
||||||
tft.println ("Tracking IF initialised");
|
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
|
// If the tracking generator LO SI4432 is defined, then check to see if it is connected
|
||||||
tgLO_OK = false;
|
tgLO_OK = false;
|
||||||
|
|
||||||
#ifdef SI_TG_LO_CS
|
#ifdef SI_TG_LO_CS
|
||||||
// pinMode (SI_TG_LO_CS, INPUT); //Start off in input mode, no pullup
|
// pinMode (SI_TG_LO_CS, INPUT); //Start off in input mode, no pullup
|
||||||
// delay(2);
|
// 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
|
// // Tracking gen LO present - initialise it, but not in TX mode yet
|
||||||
// pinMode (SI_TG_LO_CS, OUTPUT);
|
// pinMode (SI_TG_LO_CS, OUTPUT);
|
||||||
// delay(2);
|
// delay(2);
|
||||||
|
|
||||||
|
tft.println ( "Initializing track gen LO SI4432" );
|
||||||
|
|
||||||
tgLO_OK = tg_lo.Init ( config.tgLO_capacitance );
|
tgLO_OK = tg_lo.Init ( config.tgLO_capacitance );
|
||||||
if ( tgLO_OK )
|
if ( tgLO_OK )
|
||||||
tft.println ("Tracking LO initialised");
|
tft.println ("Tracking LO initialised");
|
||||||
@ -729,7 +746,9 @@ bool fsStatus = false; // True if SPIFFS loads ok
|
|||||||
// pinMode (SI_TG_LO_CS, OUTPUT);
|
// pinMode (SI_TG_LO_CS, OUTPUT);
|
||||||
// digitalWrite(SI_TG_LO_CS, HIGH); // make sure it doesn't get selected
|
// 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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -809,7 +828,7 @@ bool fsStatus = false; // True if SPIFFS loads ok
|
|||||||
|
|
||||||
// tft.println("Setup Complete");
|
// 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
|
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.
|
* Initialise high frequency mode sweep.
|
||||||
|
@ -33,12 +33,15 @@ extern uint16_t displayPoints;
|
|||||||
extern uint16_t xDelta;
|
extern uint16_t xDelta;
|
||||||
extern uint16_t waterfallHeight;
|
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 bpfCount; // Number of elements in the bandpassFilters array
|
||||||
extern int updateSidebar; // Flag to indicate no of clients has changed
|
extern int updateSidebar; // Flag to indicate no of clients has changed
|
||||||
extern void ClearDisplay ();
|
extern void ClearDisplay ();
|
||||||
extern void DisplayError ( uint8_t severity, const char *l1, const char *l2, const char *l3, const char *l4 );
|
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
|
* 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 startFreq_IF;
|
||||||
extern uint32_t stopFreq_IF;
|
extern uint32_t stopFreq_IF;
|
||||||
extern uint32_t sigFreq_IF;
|
extern uint32_t sigFreq_IF;
|
||||||
|
extern uint16_t sigGenOutputOn;
|
||||||
|
|
||||||
extern uint32_t startFreq_RX;
|
extern uint32_t startFreq_RX;
|
||||||
extern uint32_t stopFreq_RX;
|
extern uint32_t stopFreq_RX;
|
||||||
@ -101,8 +105,15 @@ boolean startAP () // Start the WiFi Access Point, keep the user informed.
|
|||||||
{
|
{
|
||||||
ClearDisplay (); // Fade to black
|
ClearDisplay (); // Fade to black
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Serial.println ( "Starting Access Point" ); // Put in the instructions
|
Serial.println ( "Starting Access Point" ); // Put in the instructions
|
||||||
|
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
// Scan WiFi SSIDs
|
||||||
|
WiFi.scanNetworks(true);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start by kicking off the soft-AP. Call depends on whether or not password
|
* Start by kicking off the soft-AP. Call depends on whether or not password
|
||||||
@ -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 );
|
DisplayError ( ERR_WARN, "Failed to open AP:", "WiFi Disabled", NULL, NULL );
|
||||||
|
|
||||||
else
|
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;
|
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
|
* Message format
|
||||||
* #b 123.123 Stop frequency
|
* #(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
|
* 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] )
|
switch ( payload[1] )
|
||||||
{
|
{
|
||||||
case 'a':
|
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;
|
break;
|
||||||
|
|
||||||
case 'b':
|
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;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
@ -249,6 +308,10 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
|
|||||||
SetLoDrive ( (uint8_t) value );
|
SetLoDrive ( (uint8_t) value );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
SetTGFreq ( value );
|
||||||
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
SetPreampGain( (int) value ); // Set PreAmp gain register
|
SetPreampGain( (int) value ); // Set PreAmp gain register
|
||||||
break;
|
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 ));
|
SetIFFrequency ( (int32_t) ( value * 1000000.0 ));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'm': // Set mode
|
||||||
|
setMode ( (int16_t) ( value ));
|
||||||
|
break;
|
||||||
|
|
||||||
case 'o': // Ref Output (LO GPIO2)
|
case 'o': // Ref Output (LO GPIO2)
|
||||||
SetRefOutput ( (int) value );
|
SetRefOutput ( (int) value );
|
||||||
break;
|
break;
|
||||||
@ -265,10 +332,43 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
|
|||||||
RequestSetPowerLevel( value );
|
RequestSetPowerLevel( value );
|
||||||
break;
|
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
|
case 's': // Adjust sweep span
|
||||||
SetSweepSpan ( (int32_t) ( value * 1000000.0 ));
|
SetSweepSpan ( (int32_t) ( value * 1000000.0 ));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 't': // Tracking Generator off/on/generate
|
||||||
|
SetTracking ( (int8_t)value );
|
||||||
|
break;
|
||||||
|
|
||||||
case 'A': // Internal Attenuation (PE4302)
|
case 'A': // Internal Attenuation (PE4302)
|
||||||
SetAttenuation ( value );
|
SetAttenuation ( value );
|
||||||
break;
|
break;
|
||||||
@ -277,6 +377,18 @@ void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t paylo
|
|||||||
SetExtGain ( value );
|
SetExtGain ( value );
|
||||||
break;
|
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
|
case 'R': // Requested RBW. 0=Auto
|
||||||
SetRBW ( value );
|
SetRBW ( value );
|
||||||
Serial.printf("Wifi RBW %f\n", 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 );
|
SetSpur ( (int8_t)value );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't': // Tracking Generator on/off
|
|
||||||
SetTracking ( (int8_t)value );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'T': // Tracking Generator output power (dBm)
|
case 'T': // Tracking Generator output power (dBm)
|
||||||
SetTGPower ( value );
|
SetTGPower ( value );
|
||||||
break;
|
break;
|
||||||
@ -508,6 +616,7 @@ void onGetSettings (AsyncWebServerRequest *request)
|
|||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
root["mType"] = "Settings";
|
root["mType"] = "Settings";
|
||||||
|
root["mode"] = setting.Mode;
|
||||||
root["dispPoints"] = displayPoints;
|
root["dispPoints"] = displayPoints;
|
||||||
root["start"] = setting.ScanStart / 1000.0;
|
root["start"] = setting.ScanStart / 1000.0;
|
||||||
root["stop"] = setting.ScanStop / 1000.0;
|
root["stop"] = setting.ScanStop / 1000.0;
|
||||||
@ -523,6 +632,18 @@ void onGetSettings (AsyncWebServerRequest *request)
|
|||||||
root["spur"] = setting.Spur;
|
root["spur"] = setting.Spur;
|
||||||
root["tg"] = trackGenSetting.Mode;
|
root["tg"] = trackGenSetting.Mode;
|
||||||
root["tgPower"] = trackGenSetting.Power;
|
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 )
|
if ( AGC_On )
|
||||||
root["PreAmp"] = 0x60; // Auto
|
root["PreAmp"] = 0x60; // Auto
|
||||||
@ -546,10 +667,11 @@ if ( numberOfWebsocketClients == 0 )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
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
|
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||||
|
|
||||||
jsonDocument["mType"] = "Settings";
|
jsonDocument["mType"] = "Settings";
|
||||||
|
jsonDocument["mode"] = setting.Mode;
|
||||||
jsonDocument["dispPoints"] = displayPoints;
|
jsonDocument["dispPoints"] = displayPoints;
|
||||||
jsonDocument["start"] = setting.ScanStart / 1000.0;
|
jsonDocument["start"] = setting.ScanStart / 1000.0;
|
||||||
jsonDocument["stop"] = setting.ScanStop / 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["spur"] = setting.Spur;
|
||||||
jsonDocument["tg"] = trackGenSetting.Mode;
|
jsonDocument["tg"] = trackGenSetting.Mode;
|
||||||
jsonDocument["tgPower"] = trackGenSetting.Power;
|
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 )
|
if ( AGC_On )
|
||||||
jsonDocument["PreAmp"] = 0x60; // Auto
|
jsonDocument["PreAmp"] = 0x60; // Auto
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
||||||
|
|
||||||
@ -579,7 +712,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
serializeJson ( jsonDocument, wsBuffer );
|
serializeJson ( jsonDocument, wsBuffer );
|
||||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Serial.println ( "No buffer :(");
|
Serial.println ( "No buffer :(");
|
||||||
|
|
||||||
@ -593,14 +725,15 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
void pushIFSweepSettings ()
|
void pushIFSweepSettings ()
|
||||||
{
|
{
|
||||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
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
|
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||||
|
|
||||||
jsonDocument["mType"] = "Settings";
|
jsonDocument["mType"] = "Settings";
|
||||||
|
jsonDocument["mode"] = setting.Mode;
|
||||||
jsonDocument["dispPoints"] = displayPoints;
|
jsonDocument["dispPoints"] = displayPoints;
|
||||||
jsonDocument["start"] = startFreq_IF / 1000.0;
|
jsonDocument["start"] = startFreq_IF / 1000.0;
|
||||||
jsonDocument["stop"] = stopFreq_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["attenuation"] = setting.Attenuate;
|
||||||
jsonDocument["extGain"] = setting.ExternalGain;
|
jsonDocument["extGain"] = setting.ExternalGain;
|
||||||
jsonDocument["levelOffset"] = setting.LevelOffset;
|
jsonDocument["levelOffset"] = setting.LevelOffset;
|
||||||
@ -610,10 +743,21 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
jsonDocument["Drive"] = setting.Drive;
|
jsonDocument["Drive"] = setting.Drive;
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
jsonDocument["sweepPoints"] = sweepPoints;
|
||||||
jsonDocument["spur"] = setting.Spur;
|
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 )
|
if ( AGC_On )
|
||||||
jsonDocument["PreAmp"] = 0x60; // Auto
|
jsonDocument["PreAmp"] = 0x60; // Auto
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
||||||
|
|
||||||
@ -624,7 +768,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
serializeJson ( jsonDocument, wsBuffer );
|
serializeJson ( jsonDocument, wsBuffer );
|
||||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Serial.println ( "No buffer :(");
|
Serial.println ( "No buffer :(");
|
||||||
|
|
||||||
@ -638,10 +781,11 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
void pushRXSweepSettings ()
|
void pushRXSweepSettings ()
|
||||||
{
|
{
|
||||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
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
|
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||||
|
|
||||||
jsonDocument["mType"] = "Settings";
|
jsonDocument["mType"] = "Settings";
|
||||||
|
jsonDocument["mode"] = setting.Mode;
|
||||||
jsonDocument["dispPoints"] = displayPoints;
|
jsonDocument["dispPoints"] = displayPoints;
|
||||||
jsonDocument["start"] = startFreq_RX / 1000.0;
|
jsonDocument["start"] = startFreq_RX / 1000.0;
|
||||||
jsonDocument["stop"] = stopFreq_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["Drive"] = setting.Drive;
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
jsonDocument["sweepPoints"] = sweepPoints;
|
||||||
jsonDocument["spur"] = setting.Spur;
|
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 )
|
if ( AGC_On )
|
||||||
jsonDocument["PreAmp"] = 0x60; // Auto
|
jsonDocument["PreAmp"] = 0x60; // Auto
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
||||||
|
|
||||||
@ -669,7 +824,6 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
serializeJson ( jsonDocument, wsBuffer );
|
serializeJson ( jsonDocument, wsBuffer );
|
||||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Serial.println ( "No buffer :(");
|
Serial.println ( "No buffer :(");
|
||||||
|
|
||||||
@ -683,10 +837,11 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
void pushBandscopeSettings ()
|
void pushBandscopeSettings ()
|
||||||
{
|
{
|
||||||
size_t capacity = JSON_ARRAY_SIZE ( SCREEN_WIDTH )
|
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
|
static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to be pushed to the web clients
|
||||||
|
|
||||||
jsonDocument["mType"] = "Settings";
|
jsonDocument["mType"] = "Settings";
|
||||||
|
jsonDocument["mode"] = setting.Mode;
|
||||||
jsonDocument["dispPoints"] = setting.BandscopePoints;
|
jsonDocument["dispPoints"] = setting.BandscopePoints;
|
||||||
jsonDocument["start"] = setting.BandscopeStart / 1000.0;
|
jsonDocument["start"] = setting.BandscopeStart / 1000.0;
|
||||||
jsonDocument["stop"] = ( setting.BandscopeStart + setting.BandscopeSpan ) / 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["Drive"] = setting.Drive;
|
||||||
jsonDocument["sweepPoints"] = sweepPoints;
|
jsonDocument["sweepPoints"] = sweepPoints;
|
||||||
jsonDocument["spur"] = setting.Spur;
|
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 )
|
if ( AGC_On )
|
||||||
jsonDocument["PreAmp"] = 0x60; // Auto
|
jsonDocument["PreAmp"] = 0x60; // Auto
|
||||||
|
|
||||||
else
|
else
|
||||||
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
jsonDocument["PreAmp"] = setting.PreampGain; // Fixed gain
|
||||||
|
|
||||||
@ -714,13 +880,74 @@ static DynamicJsonDocument jsonDocument ( capacity ); // buffer for json data to
|
|||||||
serializeJson ( jsonDocument, wsBuffer );
|
serializeJson ( jsonDocument, wsBuffer );
|
||||||
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
webSocket.broadcastTXT ( wsBuffer ); // Send to all connected websocket clients
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Serial.println ( "No buffer :(");
|
Serial.println ( "No buffer :(");
|
||||||
|
|
||||||
// Serial.printf ( "Push Settings sweepPoints %u\n", sweepPoints );
|
// 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
|
* Prepare a response ready for push to web clients
|
||||||
*/
|
*/
|
||||||
|
@ -33,21 +33,26 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#define SSID_NAME "TinySA" // Name of access point
|
#define SSID_NAME "simpleSA" // Name of access point
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function prototypes:
|
* Function prototypes:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern boolean startAP ();
|
boolean startAP ();
|
||||||
extern boolean connectWiFi ();
|
boolean connectWiFi ();
|
||||||
extern void buildServer ();
|
void buildServer ();
|
||||||
extern void addTagNameValue ( char *b, char *_name, char *value );
|
void addTagNameValue ( char *b, char *_name, char *value );
|
||||||
extern char *escapeXML ( char *s );
|
char *escapeXML ( char *s );
|
||||||
extern void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t lenght );
|
void webSocketEvent ( uint8_t num, WStype_t type, uint8_t* payload, size_t lenght );
|
||||||
extern char *FormatIPAddress ( IPAddress ipAddress );
|
char *FormatIPAddress ( IPAddress ipAddress );
|
||||||
|
void pushSettings ();
|
||||||
|
void pushIFSweepSettings ();
|
||||||
|
void pushRXSweepSettings ();
|
||||||
|
void pushBandscopeSettings ();
|
||||||
|
void pushSigGenSettings ();
|
||||||
|
void initChunkSweepDoc (uint32_t startIndex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions outside of "TinySA_wifi:
|
* Functions outside of "TinySA_wifi:
|
||||||
|
58
ui.cpp
58
ui.cpp
@ -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,
|
enum { KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_FOCUS,
|
||||||
KM_REFPOS, KM_ATTENUATION, KM_ACTUALPOWER, KM_IFFREQ, KM_PREAMP,
|
KM_REFPOS, KM_ATTENUATION, KM_ACTUALPOWER, KM_IFFREQ, KM_PREAMP,
|
||||||
KM_TUNE, KM_SGFREQ, KM_SGLEVEL, KM_SGLEVCAL, KM_IFSTART, KM_IFSTOP,
|
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_WFMIN, KM_WFGAIN, KM_BANDSCOPELEVEL, KM_RXSPAN, KM_RXSIG, KM_RBW,
|
||||||
KM_EXTERN };
|
KM_EXTERN };
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ static const char * const keypad_mode_label[] =
|
|||||||
"START", "STOP", "CENTER", "SPAN", "FOCUS",
|
"START", "STOP", "CENTER", "SPAN", "FOCUS",
|
||||||
"REFPOS", "ATTEN", "POWER", "IF FREQ", "PREAMP",
|
"REFPOS", "ATTEN", "POWER", "IF FREQ", "PREAMP",
|
||||||
"XTAL CAL", "SG FREQ", "dBm", "Max dBm", "IF START", "IF STOP",
|
"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",
|
"WF MIN", "WF GAIN", "REF LEVEL", "RX SPAN", "RX Sig Freq", "RBW",
|
||||||
"EXTERNAL"
|
"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_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_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_tgIF_drive_cb(int item); // M0WID - added in 3.0e
|
||||||
static void menu_tgLO_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, "OFF", menu_tracking_cb ),
|
||||||
Menuitem ( MT_FUNC, "ON", 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
|
#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 ),
|
Menuitem ( MT_FUNC, "\2LO\0DRIVE", menu_tgLO_drive_cb ),
|
||||||
#endif
|
#endif
|
||||||
|
Menuitem ( MT_FUNC, "\2IF\0DRIVE", menu_tgIF_drive_cb ),
|
||||||
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
||||||
Menuitem ( MT_END ) // End marker
|
Menuitem ( MT_END ) // End marker
|
||||||
};
|
};
|
||||||
@ -1168,7 +1171,7 @@ void ShowSplash ( void )
|
|||||||
tft.setFreeFont ( &FreeSansBold9pt7b ); // Select Free Serif 9 point font
|
tft.setFreeFont ( &FreeSansBold9pt7b ); // Select Free Serif 9 point font
|
||||||
tft.drawString ( "By WA2FZW, M0WID,", 160, 60 );
|
tft.drawString ( "By WA2FZW, M0WID,", 160, 60 );
|
||||||
tft.drawString ( "VK3PE and G3ZQC", 160, 80 );
|
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.drawString ( "Original tinySA by Erik (PD0EK)", 160, 120 );
|
||||||
|
|
||||||
tft.setTextDatum ( TL_DATUM ); // Back to default top left
|
tft.setTextDatum ( TL_DATUM ); // Back to default top left
|
||||||
@ -1387,6 +1390,17 @@ void menu_tg_offset_cb ( int item )
|
|||||||
ui_process_keypad ();
|
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
|
ui_mode_normal (); // Back to sweep
|
||||||
break;
|
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_IFSTOP.........IF Sweep stop frequency
|
||||||
keypads_freq, // KM_IFSIG..........IF Sweep signal frequency
|
keypads_freq, // KM_IFSIG..........IF Sweep signal frequency
|
||||||
keypads_signed_freq, // KM_TGOFFSET.......Offset Frequency of TG IF compared to SA IF
|
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_TGLO_DRIVE.....Tracking generator LO drive
|
||||||
keypads_level, // KM_TGIF_DRIVE.....Tracking generator IF drive
|
keypads_level, // KM_TGIF_DRIVE.....Tracking generator IF drive
|
||||||
keypads_freq, // KM_BANDSCOPESTART.IF Sweep start frequency
|
keypads_freq, // KM_BANDSCOPESTART.IF Sweep start frequency
|
||||||
@ -2521,6 +2541,10 @@ static void fetch_numeric_target ( void )
|
|||||||
uistat.value = trackGenSetting.Offset;
|
uistat.value = trackGenSetting.Offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KM_TGFREQ:
|
||||||
|
uistat.value = trackGenSetting.Frequency;
|
||||||
|
break;
|
||||||
|
|
||||||
case KM_TGIF_DRIVE:
|
case KM_TGIF_DRIVE:
|
||||||
uistat.value = trackGenSetting.IF_Drive;
|
uistat.value = trackGenSetting.IF_Drive;
|
||||||
break;
|
break;
|
||||||
@ -2944,6 +2968,23 @@ static int keypad_click ( int key )
|
|||||||
SetTGOffset ( (int32_t)value );
|
SetTGOffset ( (int32_t)value );
|
||||||
break;
|
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:
|
case KM_TGIF_DRIVE:
|
||||||
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
||||||
{
|
{
|
||||||
@ -2957,6 +2998,8 @@ static int keypad_click ( int key )
|
|||||||
SetTGIfDrive ( (uint8_t)value );
|
SetTGIfDrive ( (uint8_t)value );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SI_TG_LO_CS
|
||||||
case KM_TGLO_DRIVE:
|
case KM_TGLO_DRIVE:
|
||||||
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
||||||
{
|
{
|
||||||
@ -2969,6 +3012,7 @@ static int keypad_click ( int key )
|
|||||||
else
|
else
|
||||||
SetTGLoDrive ( (uint8_t)value );
|
SetTGLoDrive ( (uint8_t)value );
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
case KM_BANDSCOPESTART: // Bandscope Start frequency entered?
|
case KM_BANDSCOPESTART: // Bandscope Start frequency entered?
|
||||||
@ -3227,21 +3271,25 @@ void UiProcessTouch ( void )
|
|||||||
if ( (touch_y < 10) && (touch_x < 160) )
|
if ( (touch_y < 10) && (touch_x < 160) )
|
||||||
{
|
{
|
||||||
marker[0].Toggle(); // marker 1
|
marker[0].Toggle(); // marker 1
|
||||||
|
setting.MkrStatus[0] = marker[0].Status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( (touch_y < 10) && (touch_x > 160) )
|
else if ( (touch_y < 10) && (touch_x > 160) )
|
||||||
{
|
{
|
||||||
marker[2].Toggle(); // marker 3
|
marker[2].Toggle(); // marker 3
|
||||||
|
setting.MkrStatus[2] = marker[2].Status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( (touch_y < 20) && (touch_x < 160) )
|
else if ( (touch_y < 20) && (touch_x < 160) )
|
||||||
{
|
{
|
||||||
marker[1].Toggle(); // marker 2
|
marker[1].Toggle(); // marker 2
|
||||||
|
setting.MkrStatus[1] = marker[1].Status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( (touch_y < 20) && (touch_x > 160) )
|
else if ( (touch_y < 20) && (touch_x > 160) )
|
||||||
{
|
{
|
||||||
marker[3].Toggle(); // marker 4
|
marker[3].Toggle(); // marker 4
|
||||||
|
setting.MkrStatus[3] = marker[3].Status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( (touch_y < 40) && (touch_x > 30) )
|
else if ( (touch_y < 40) && (touch_x > 30) )
|
||||||
|
Loading…
Reference in New Issue
Block a user