simpleSA/SigLo.ino
M0WID 1746058f31 Fixed TG CS pin define compile error
Corrected problem with CS pins floating if module installed but not initialised.
Also corrected compiler error if neither TG SI4432 defined
2020-10-09 21:14:58 +01:00

346 lines
10 KiB
C++

/*
* ########################################################################
*
* Initialise variables and SI4432 for sig gen mode
*
* ########################################################################
*/
void initSigLow()
{
// Use the TFT_eSPI buttons for now.
// This could be changed to use something similar to the main menu
tft.fillScreen(SIG_BACKGROUND_COLOR);
//img.unloadFont(); // Free up memory from any previous incarnation of img
img.deleteSprite();
img.setColorDepth ( 16 );
img.setAttribute ( PSRAM_ENABLE, false ); // Don't use the PSRAM on the WROVERs
img.createSprite ( 320, 55 ); // used for frequency display
img.loadFont(SA_FONT_LARGE);
SetRX ( 1 ); // LO and RX both in receive until turned on by UI
xmit.SetOffset ( 0 ); // make sure frequency offset registers are zero
rcvr.SetOffset ( 0 );
#ifdef TG_IF_INSTALLED
if (tgIF_OK) {
tg_if.RxMode ( ); // turn off the IF oscillator in tracking generator
}
#endif
#ifdef TG_LO_INSTALLED
if (tgLO_OK) {
tg_lo.RxMode ( ); // turn off the Local Oscillator in tracking generator
}
#endif
int showUpDownButtons = 0;
#ifdef SHOW_FREQ_UP_DOWN_BUTTONS
showUpDownButtons = 1;
#endif
xmit.SetDrive ( sigGenSetting.LO_Drive ); // Set Local Oscillator power level
rcvr.SetDrive ( sigGenSetting.RX_Drive ); // Set receiver SI4432 power level
tinySA_mode = SIG_GEN_LOW_RANGE;
setting.Mode = tinySA_mode;
tft.unloadFont();
tft.setCursor ( xOrigin + 50, SCREEN_HEIGHT - CHAR_HEIGHT );
tft.setTextSize(1);
tft.setTextColor ( YELLOW );
tft.printf ( "Mode:%s", modeText[setting.Mode] );
tft.setTextColor ( WHITE );
tft.loadFont(KEY_FONT);
// draw the buttons
for (int i = 0; i < SIG_KEY_COUNT; i++)
{
if ( showUpDownButtons || ( i > 13 ))
{
key[i].initButton(&tft,
// x, y, w, h, outline, fill, text
sig_keys[i].x,
sig_keys[i].y,
sig_keys[i].width,
sig_keys[i].height,
DARKGREY, // outline colour
sig_keys[i].color, // fill
TFT_BLACK, // Text colour
"", // 10 Byte Label
2); // font size multiplier (not used when font loaded)
// setLabelDatum(uint16_t x_delta, uint16_t y_delta, uint8_t datum)
key[i].setLabelDatum(1, 1, MC_DATUM);
// Draw button and specify label string
// Specifying label string here will allow more than the default 10 byte label
key[i].drawButton(false, sig_keys[i].text);
}
}
// draw the slider to control output level
// we re-purpose the sSprite for this
sSprite.deleteSprite();
sSprite.setColorDepth ( 16 );
sSprite.setAttribute ( PSRAM_ENABLE, false ); // Don't use the PSRAM on the WROVERs
sSprite.createSprite ( SLIDER_WIDTH + 2 * SLIDER_KNOB_RADIUS + 60, 2 * SLIDER_KNOB_RADIUS ); // used for slider and value
sSprite.setTextColor(TFT_ORANGE);
sSprite.loadFont(KEY_FONT);
// Slider range will be something like -60 to -10dBm for low frequency range
// (to be changed once I have worked out what the real values should be)
// Parameter passed in are x, y and slider knob position in %
float sPercent = (float)(sigGenSetting.Power - sigGenSetting.Calibration + ATTENUATOR_RANGE) * 100.0
/ (float)(ATTENUATOR_RANGE);
drawSlider(SLIDER_X, SLIDER_Y, sPercent, sigGenSetting.Power, "dBm");
att.SetAtten ( sigGenSetting.Calibration - sigGenSetting.Power ); // set attenuator to give required output
oldFreq = 0; // Force write of frequency on first loop
#ifdef USE_WIFI
if ( numberOfWebsocketClients > 0 )
pushSigGenSettings ();
#endif
}
/* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
* Low frequency range signal generator
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
*/
void doSigGenLow ()
{
static uint32_t oldIF; // to store the current IF
static uint16_t oldSigGenOutputOn;
float p; // temporary variable for slider percent
static uint16_t sliderRange = ATTENUATOR_RANGE + RX_SI4432_MAX_DRIVE * 3;
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
int showUpDownButtons = 0;
#ifdef SHOW_FREQ_UP_DOWN_BUTTONS
showUpDownButtons = 1;
#endif
if (changedSetting) {
// calculate required drive and attenuator settings
// keep drive as high as possible so nasties are attenuated
uint16_t sgRXDrive = RX_SI4432_MAX_DRIVE;
uint16_t attenuation = sigGenSetting.Calibration - sigGenSetting.Power;
if (attenuation > ATTENUATOR_RANGE )
{
int16_t diff = attenuation - ATTENUATOR_RANGE;
sgRXDrive = RX_SI4432_MAX_DRIVE - (int16_t)( (diff-1)/3 ) - 1 ;
attenuation = ATTENUATOR_RANGE - 2 + (diff-1)%3;
}
SetSGRxDrive(sgRXDrive);
att.SetAtten(attenuation);
Serial.printf("sigGenLow - rxDrive set to %i, attenuation set to %i, cal is %i\n", sgRXDrive, attenuation, sigGenSetting.Calibration);
#ifdef USE_WIFI
if ( numberOfWebsocketClients > 0 )
pushSigGenSettings ();
#endif
changedSetting = false;
}
// Get current touch state and coordinates
boolean pressed = tft.getTouch(&t_x, &t_y); // Just uses standard TFT_eSPI function as not bothered about speed
// Adjust press state of each key appropriately
for (uint8_t b = 0; b < SIG_KEY_COUNT; b++) {
if (pressed && key[b].contains(t_x, t_y))
key[b].press(true); // tell the button it is pressed
else
key[b].press(false); // tell the button it is NOT pressed
}
// Check if any key has changed state
for (uint8_t b = 0; b < SIG_KEY_COUNT; b++)
{
if ( showUpDownButtons || ( b > 13 ))
{
if ( key[b].justPressed() ) {
switch (b) {
case 0: // Increment buttons
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
incrementFreq( pow(10, 8-b) );
changedSetting=true;
break;
case 7: // Decrement buttons
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
decrementFreq( pow(10, 15-b) );
changedSetting=true;
break;
case 14: // Return to SAlo mode
key[b].drawButton(true, sig_keys[b].activeText);
break;
case 15: // toggle the output on/off
sigGenOutputOn = !sigGenOutputOn;
break;
case 16: // launch menu
key[b].drawButton(true, sig_keys[b].activeText);
break;
default:
Serial.printf("Button %i press not handled", b );
break;
}
}
}
if (key[b].isPressed()) { // button held
return;
}
// // If button was just released
if (key[b].justReleased())
{
switch (b) {
case 14: // Return to SAlo mode
WriteSigGenSettings ();
initSweepLow();
break;
case 16: // launch signal generator menu
StartSigGenMenu ( );
return;
case 17: // launch frequency keypad
StartSigGenFreq ( );
return;
}
}
// check if state changed - can change from command or from wifi
switch (b) {
case 15: // On/Off button
if (oldSigGenOutputOn != sigGenOutputOn)
{
if (sigGenOutputOn) {
SetRX(3); // both LO and RX in transmit. Output levels have been set in the init function
key[b].drawButton(true, sig_keys[b].activeText);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_GREEN, SIG_BACKGROUND_COLOR );
tft.print(" ON");
} else {
SetRX(1); // Both in receive
key[b].drawButton(false, sig_keys[b].text);
tft.setCursor(sig_keys[b].x + 30, sig_keys[b].y);
tft.fillRect(sig_keys[b].x + 30, sig_keys[b].y, sig_keys[b].x + 60, sig_keys[b].y + 10, SIG_BACKGROUND_COLOR);
tft.setTextColor(TFT_WHITE, SIG_BACKGROUND_COLOR );
tft.print("OFF");
}
changedSetting = true;
}
break;
} // on of state change switch
} // end of keys loop
// Check if slider touched
if ( sliderPressed( pressed, t_x, t_y) )
{
p = sliderPercent( t_x ); // position of slider in %
float pwr = p * (sliderRange)/100.0 + sigGenSetting.Calibration - sliderRange;
drawSlider ( SLIDER_X, SLIDER_Y, p, pwr, "dBm" );
sigGenSetting.Power = pwr;
changedSetting = true;
} else {
p = ( sigGenSetting.Power - (sigGenSetting.Calibration - sliderRange) ) * 100.0 / sliderRange;
drawSlider ( SLIDER_X, SLIDER_Y, p, sigGenSetting.Power, "dBm" );
}
// draw frequency. Uses a sprite to avoid flicker
img.fillSprite(SIG_BACKGROUND_COLOR);
img.setCursor(5,5);
img.setTextColor(TFT_ORANGE);
img.printf("%s",DisplayFrequency ( sigGenSetting.Frequency ) );
img.pushSprite(0,80);
/*
* set RX to IF_Frequency and LO to IF plus required frequency
*
* but only if value has changed to avoid the SI4432 running its state change sequencer
* The mixer will produce IF + LO and IF - LO
* The Low pass filter will filter out the higher frequency and LO leakage
* The IF SAW filter will smooth out the waveform produced by the SI4432
*/
if ( (oldFreq != sigGenSetting.Frequency) || (oldIF != setting.IF_Freq) )
{
rcvr.SetFrequency ( setting.IF_Freq );
xmit.SetFrequency ( setting.IF_Freq + sigGenSetting.Frequency );
Serial.println("set frequency");
if (sigGenOutputOn)
{
delayMicroseconds(300);
SetRX(3); // both LO and RX in tx mode
}
changedSetting = true;
}
oldFreq = sigGenSetting.Frequency;
oldIF = setting.IF_Freq;
oldSigGenOutputOn = sigGenOutputOn;
}
void incrementFreq(uint32_t amount) {
sigGenSetting.Frequency += amount;
if (sigGenSetting.Frequency > MAX_SIGLO_FREQ)
sigGenSetting.Frequency = MAX_SIGLO_FREQ;
}
void decrementFreq(uint32_t amount) {
if (sigGenSetting.Frequency > amount) {
sigGenSetting.Frequency -= amount;
if (sigGenSetting.Frequency < MIN_SIGLO_FREQ)
sigGenSetting.Frequency = MIN_SIGLO_FREQ;
} else {
sigGenSetting.Frequency = MIN_SIGLO_FREQ;
}
}