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