FrequencyControl improved

Added new RBW options
Modified Si4432::Tune to change modes to recalibrate PLL
This commit is contained in:
M0WID 2020-08-20 22:27:55 +01:00
parent 1cb4cdef6e
commit f105b70210
11 changed files with 290 additions and 91 deletions

View File

@ -93,7 +93,10 @@ void initBandscope()
* *
* Frequency scheme: * Frequency scheme:
* When the LO frequency is < 480MHz the LO can be adjusted +- 80kHz from the * When the LO frequency is < 480MHz the LO can be adjusted +- 80kHz from the
* nominal frequency in 156.25Hz steps. * nominal frequency in 156.25Hz steps, ie +- 512 steps.
* Actually this is not possible! +-511 steps is
*
*
* If the LO is above 480MHz the the adjustment is +-160kHz in 312.5Hz steps. * If the LO is above 480MHz the the adjustment is +-160kHz in 312.5Hz steps.
* If the IF is 434MHz then 480MHz -> 46Mhz for the signal being analysed, so fine * If the IF is 434MHz then 480MHz -> 46Mhz for the signal being analysed, so fine
* for most of the HF bands. * for most of the HF bands.
@ -112,6 +115,8 @@ void initBandscope()
* When the offset value reaches +80kHz then we need to reset the LO (using normal delaytime) * When the offset value reaches +80kHz then we need to reset the LO (using normal delaytime)
* and continue until we get to the end of the sweep. * and continue until we get to the end of the sweep.
* *
* Due to the limitation of not being able to do +-512, or +-16 stesp, we will use +-31 steps per frequency
* jump instead
* *
*/ */
@ -122,12 +127,10 @@ void doBandscope()
static uint32_t autoSweepStep = 0; static uint32_t autoSweepStep = 0;
static uint32_t autoSweepFreq = 0; static uint32_t autoSweepFreq = 0;
static uint32_t autoSweepFreqStep = 0; static uint32_t autoSweepFreqStep = 0;
static uint32_t nextPointFreq = 0; // Frequency for the next display point. Used for substeps
static unsigned long setFreqMicros; static unsigned long setFreqMicros;
static unsigned long nowMicros; static unsigned long nowMicros;
static unsigned long bandscopeDelay;
//static uint32_t sweepStep; // Step count
//static uint32_t sweepFreqStep;
static int16_t pointMinGain; // to record minimum gain for the current display point static int16_t pointMinGain; // to record minimum gain for the current display point
static int16_t pointMaxRSSI; // to record max RSSI of the samples in the current display point static int16_t pointMaxRSSI; // to record max RSSI of the samples in the current display point
@ -135,13 +138,6 @@ static uint32_t pointMaxFreq; // record frequency where maximum occurred
static int16_t lastMode; // Record last operating mode (sig gen, normal) static int16_t lastMode; // Record last operating mode (sig gen, normal)
static uint16_t currentPointRSSI;
static uint16_t peakRSSI;
static uint16_t prevPointRSSI;
static uint32_t peakFreq;
static uint16_t peakIndex;
static uint16_t pointsPastPeak;
static uint16_t pointsPastDip;
static uint16_t minRSSI = 255; // Minimum level for the sweep static uint16_t minRSSI = 255; // Minimum level for the sweep
static uint16_t lastMinRSSI; // Minimum level for the previous sweep static uint16_t lastMinRSSI; // Minimum level for the previous sweep
@ -171,9 +167,10 @@ static uint16_t chunkIndex;
{ {
sweepPoints = setting.BandscopePoints; sweepPoints = setting.BandscopePoints;
autoSweepFreqStep = ( setting.BandscopeSpan ) / sweepPoints; autoSweepFreqStep = ( setting.BandscopeSpan ) / sweepPoints;
offsetFreqIncrement = autoSweepFreqStep; // 2500 Hz for 200kHz span, 80 points per sweep
vbw = autoSweepFreqStep / 1000.0; // Set the video resolution vbw = autoSweepFreqStep / 1000.0; // Set the video resolution
ownrbw = 2.6; // and fix the resolution bandwidth to 2.6kHz ownrbw = 3.1; // and fix the resolution bandwidth to 2.6kHz
bandwidth = rcvr.SetRBW ( ownrbw * 10.0, &delaytime ); // Set it in the receiver Si4432 bandwidth = rcvr.SetRBW ( ownrbw * 10.0, &delaytime ); // Set it in the receiver Si4432
@ -192,6 +189,9 @@ static uint16_t chunkIndex;
resetAverage = changedSetting; resetAverage = changedSetting;
maxGrid = setting.BandscopeMaxGrid;
minGrid = setting.BandscopeMinGrid;
#ifdef USE_WIFI #ifdef USE_WIFI
// Vary number of points to send in each chunk depending on delaytime // Vary number of points to send in each chunk depending on delaytime
@ -212,15 +212,23 @@ static uint16_t chunkIndex;
autoSweepStep = 0; // Set the step counter to zero autoSweepStep = 0; // Set the step counter to zero
autoSweepFreq = setting.BandscopeStart; // Set the start frequency. autoSweepFreq = setting.BandscopeStart; // Set the start frequency.
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
while (( micros() - setFreqMicros ) < delaytime ) // Make sure enough time has elasped since previous frequency write while (( micros() - setFreqMicros ) < delaytime ) // Make sure enough time has elasped since previous frequency write
{ {
} }
resetOffsets();
// set the offset value in the SI4432
xmit.SetOffset(offsetValue);
setFreqMicros = micros(); // Store the time the frequency was changed setFreqMicros = micros(); // Store the time the frequency was changed
xmit.SetFrequency ( setting.IF_Freq + autoSweepFreq ); // set the LO frequency, tempIF is offset if spur reduction on
// set the LO frequency (offsetFreq is -ve at start!)
uint32_t xmitFreq = setting.IF_Freq + autoSweepFreq - offsetFreq;
// Serial.printf("XmitFreq %i\n", xmitFreq);
xmit.SetFrequency ( xmitFreq );
// delay will vary depending on whether or not the nominal frequency is changed
bandscopeDelay = delaytime; // long delay
#ifdef USE_WIFI #ifdef USE_WIFI
@ -250,13 +258,6 @@ static uint16_t chunkIndex;
// Serial.printf(" start %i; stop %i; points %i \n", startFreq, stopFreq, sweepPoints ); // Serial.printf(" start %i; stop %i; points %i \n", startFreq, stopFreq, sweepPoints );
if ( setActualPowerRequested )
{
SetPowerLevel ( actualPower );
setActualPowerRequested = false;
}
lastMinRSSI = minRSSI; lastMinRSSI = minRSSI;
minRSSI = 255; // real value should always be less minRSSI = 255; // real value should always be less
@ -288,7 +289,7 @@ static uint16_t chunkIndex;
*/ */
nowMicros = micros(); nowMicros = micros();
while (( nowMicros - setFreqMicros ) < delaytime ) while (( nowMicros - setFreqMicros ) < bandscopeDelay )
{ {
if ( ( nowMicros - setFreqMicros + delaytime > 200 ) && if ( ( nowMicros - setFreqMicros + delaytime > 200 ) &&
@ -328,15 +329,30 @@ static uint16_t chunkIndex;
autoSweepFreq += autoSweepFreqStep; // Increment the frequency autoSweepFreq += autoSweepFreqStep; // Increment the frequency
autoSweepStep++; // and increment the step count autoSweepStep++; // and increment the step count
offsetFreq += offsetFreqIncrement;
offsetValue += offsetIncrement;
/* /*
* Change the transmitter frequency for the next reading and record the time for * Change the local oscillator frequency for the next reading and record the time for
* the RBW required settling delay. * the RBW required settling delay.
*/ */
uint32_t f = setting.IF_Freq + autoSweepFreq;
setFreqMicros = micros(); // Store the time the LO frequency was changed setFreqMicros = micros(); // Store the time the LO frequency was changed
xmit.SetFrequency ( f ); // Set the new LO frequency as soon as RSSI read
if (offsetValue >= 512) // reached offset limits
{
resetOffsets();
xmit.SetOffset(offsetValue);
uint32_t f = setting.IF_Freq + autoSweepFreq - offsetFreq;
// Serial.printf("Sweep setFreq %i\n", f);
xmit.SetFrequency ( f ); // Set the new LO frequency as soon as RSSI read
bandscopeDelay = delaytime;
}
else
{
xmit.SetOffset(offsetValue);
bandscopeDelay = offsetDelayTime;
}
#ifdef USE_WIFI #ifdef USE_WIFI
@ -402,7 +418,7 @@ static uint16_t chunkIndex;
myGain[tmp] = gainReading; myGain[tmp] = gainReading;
DrawCheckerBoard ( tmp ); // Draw the grid DrawCheckerBoard ( tmp ); // Draw the grid
if ( resetAverage || setting.Average == AV_OFF ) // Store data, either as read or as rolling average if ( resetAverage || setting.Average == AV_OFF ) // Store data, either as read or as rolling average
myData[tmp] = myActual[oldSweepStep]; myData[tmp] = myActual[oldSweepStep];
@ -453,18 +469,38 @@ static uint16_t chunkIndex;
} }
if ( tmp > 0 ) // Only push if not first point (two pixel wide img) if ( tmp > 0 ) // Only push if not first point (two pixel wide img)
img.pushSprite ( xOrigin+tmp, yOrigin ); img.pushSprite ( xOrigin + tmp - 1 , yOrigin );
// put data into the top row of the waterfall /*
// 16 bit colours have 5 bits for Red, 6 bits for Green, 5 bits for Blue * put data into the top row of the waterfall
// We will just change the green here for first test * 16 bit colours have 5 bits for Red, 6 bits for Green, 5 bits for Blue
* We will just change the green level here for first test
uint32_t pixelColour = (rxRSSI - 17) << 5 ; // testing colours */
if (rxRSSI < 17) uint32_t level = (uint32_t)( (float)(rxRSSI - setting.WaterfallMin) * setting.WaterfallGain) ; // testing colours
pixelColour = 0; if (rxRSSI < setting.WaterfallMin)
if (colourTest > 0) level = 0;
uint32_t green = level;
uint32_t red = 0;
uint32_t blue = 0;
if (green > 63)
{
green = 63;
red = level - 63;
if ( red > 31 )
{
red = 31;
blue = level - 63 - 31;
if ( blue > 31 )
blue = 31;
}
}
uint32_t pixelColour = (red << 11) + (green << 5) + blue;
if (colourTest > 0) // delete at some stage
pixelColour = colourTest; pixelColour = colourTest;
// Serial.printf("rxRSSI %i; colour %i \n", rxRSSI, pixelColour);
// Serial.printf("rxRSSI %i; red %i; green %i; blue %i; colour %i \n", rxRSSI, red, green, blue, pixelColour);
sSprite.drawPixel ( tmp, 0, pixelColour ); sSprite.drawPixel ( tmp, 0, pixelColour );
} }
@ -627,3 +663,21 @@ double fStop;
updateSidebar = false; updateSidebar = false;
} // End of "DisplayBandscopeInfo" } // End of "DisplayBandscopeInfo"
void resetOffsets ()
{
if (setting.BandscopeStart < 480000000) // low range. Assume never change range mid sweep!
{
offsetStep = -31;
offsetIncrement = 16; // 16 * 156.25 = 2500
}
else // high range
{
offsetStep = -63;
offsetIncrement = 8; // 8 * 312.5 = 2500
}
offsetFreq = offsetStep * offsetFreqIncrement;
offsetValue = offsetStep * offsetIncrement;
}

View File

@ -99,6 +99,9 @@ static uint16_t chunkIndex;
xmit.SetPowerReference ( setting.ReferenceOut ); // Set the GPIO reference output xmit.SetPowerReference ( setting.ReferenceOut ); // Set the GPIO reference output
maxGrid = setting.MaxGrid;
minGrid = setting.MinGrid;
#ifdef USE_WIFI #ifdef USE_WIFI
// Vary number of points to send in each chunk depending on delaytime // Vary number of points to send in each chunk depending on delaytime
// A chunk is sent at the end of each sweep regardless // A chunk is sent at the end of each sweep regardless

View File

@ -58,6 +58,9 @@ static uint16_t peakRSSI;
static uint16_t prevPointRSSI; static uint16_t prevPointRSSI;
static uint32_t peakFreq; static uint32_t peakFreq;
static uint16_t peakIndex; static uint16_t peakIndex;
static uint16_t maxRSSI;
static uint32_t maxFreq;
static uint16_t maxIndex;
static uint16_t pointsPastPeak; static uint16_t pointsPastPeak;
static uint16_t pointsPastDip; static uint16_t pointsPastDip;
static uint16_t minRSSI; // Minimum level for the sweep static uint16_t minRSSI; // Minimum level for the sweep
@ -131,6 +134,9 @@ static uint16_t chunkIndex;
xmit.SetPowerReference ( setting.ReferenceOut ); // Set the GPIO reference output if wanted xmit.SetPowerReference ( setting.ReferenceOut ); // Set the GPIO reference output if wanted
maxGrid = setting.MaxGrid;
minGrid = setting.MinGrid;
#ifdef USE_WIFI #ifdef USE_WIFI
// Vary number of points to send in each chunk depending on delaytime // Vary number of points to send in each chunk depending on delaytime
// A chunk is sent at the end of each sweep regardless // A chunk is sent at the end of each sweep regardless
@ -280,6 +286,7 @@ static uint16_t chunkIndex;
pointsPastPeak = 0; // Avoid possible peak detection at start of sweep pointsPastPeak = 0; // Avoid possible peak detection at start of sweep
peakRSSI = 0; peakRSSI = 0;
maxRSSI = 0;
sweepStartDone = true; // Make sure this initialize is only done once per sweep sweepStartDone = true; // Make sure this initialize is only done once per sweep
initSweep = false; initSweep = false;
@ -358,7 +365,7 @@ static uint16_t chunkIndex;
uint32_t f = tempIF + autoSweepFreq; uint32_t f = tempIF + autoSweepFreq;
xmit.SetFrequency ( f ); // Set the new LO frequency as soon as RSSI read xmit.SetFrequency ( f ); // Set the new LO frequency as soon as RSSI read
// Serial.printf("Required: %i Actual %i\n", tempIF+autoSweepFreq, xmit.GetFrequency()); // Serial.printf("LO Required: %i Actual %i\n", tempIF+autoSweepFreq, xmit.GetFrequency());
#ifdef SI_TG_LO_CS #ifdef SI_TG_LO_CS
if (tgLO_OK && (trackGenSetting.Mode == 1) ) if (tgLO_OK && (trackGenSetting.Mode == 1) )
@ -507,15 +514,15 @@ static uint16_t chunkIndex;
if (( autoSweepFreq > MARKER_MIN_FREQUENCY ) && (oldSweepStep > 0)) if (( autoSweepFreq > MARKER_MIN_FREQUENCY ) && (oldSweepStep > 0))
{ {
if ( peakLevel < myData[oldSweepStep] ) // if ( maxRSSI <= myActual[oldSweepStep] )
{ // {
peakIndex = oldSweepStep; // maxIndex = oldSweepStep;
peakLevel = myData[oldSweepStep]; // maxRSSI = myActual[oldSweepStep];
peakFreq = oldSweepFreq; // maxFreq = oldSweepFreq;
//
// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep); //// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
// displayPeakData (); //// displayPeakData ();
} // }
/* /*
@ -620,6 +627,8 @@ static uint16_t chunkIndex;
if ( sweepCount < 2 ) if ( sweepCount < 2 )
sweepCount++; // Used to disable wifi at start sweepCount++; // Used to disable wifi at start
// Serial.printf("MaxRSSI = %i, freq = %i\n", maxRSSI, maxFreq);
oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function oldPeakLevel = peakLevel; //Save value of peak level for use by the "SetPowerLevel" function
if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point if ( myActual[displayPoints-1] == 0 ) // Ensure a value in last data point

84
cmd.cpp
View File

@ -69,6 +69,7 @@ extern uint8_t myStorage[SCREEN_WIDTH+1];
extern float bandwidth; // The current bandwidth (not * 10) extern float bandwidth; // The current bandwidth (not * 10)
extern unsigned long delaytime; // In microseconds extern unsigned long delaytime; // In microseconds
extern unsigned long offsetDelayTime; // In microseconds
extern unsigned long wiFiTargetTime; extern unsigned long wiFiTargetTime;
extern uint16_t wiFiPoints; extern uint16_t wiFiPoints;
@ -166,10 +167,13 @@ extern void setMode (uint16_t newMode);
{ "SGLODRIVE", MSG_SG_LO_DRIVE }, // Set Signal Generator LO Drive level { "SGLODRIVE", MSG_SG_LO_DRIVE }, // Set Signal Generator LO Drive level
{ "TGIFDRIVE", MSG_TG_IF_DRIVE }, // Set Track Generator IF Drive level { "TGIFDRIVE", MSG_TG_IF_DRIVE }, // Set Track Generator IF Drive level
{ "TGLODRIVE", MSG_TG_LO_DRIVE }, // Set Track Generator LO Drive level { "TGLODRIVE", MSG_TG_LO_DRIVE }, // Set Track Generator LO Drive level
{ "IFSIGNAL", MSG_IFSIGNAL }, // IF sweep signal frequency { "IFSIGNAL", MSG_IFSIGNAL }, // IF sweep signal frequency
{ "TGOFFSET", MSG_TGOFFSET }, // Offset TG IF from SA IF to reduce pass through { "TGOFFSET", MSG_TGOFFSET }, // Offset TG IF from SA IF to reduce pass through
{ "CTEST", MSG_COLOURTEST }, // Work out how colours work! { "CTEST", MSG_COLOURTEST }, // Work out how colours work!
{ "", MSG_NONE } // Unrecognized command { "OFFDEL", MSG_OFFDELAY }, // Offset tuning delay
{ "WFMIN", MSG_WFMIN }, // Min level for waterfall colours
{ "WFGAIN", MSG_WFGAIN }, // Gain for waterfall colours
{ "", MSG_NONE } // Unrecognized command
}; };
int msgCount = ELEMENTS ( msgTable); int msgCount = ELEMENTS ( msgTable);
@ -227,6 +231,9 @@ void ShowMenu ()
Serial.printf ( " SCALE.........Set the dB/horizontal line value; currently: %ddB\n", setting.PowerGrid ); Serial.printf ( " SCALE.........Set the dB/horizontal line value; currently: %ddB\n", setting.PowerGrid );
Serial.printf ( " WFMIN.........Set the minimum RSSI level for waterfall colouring: %i\n", setting.WaterfallMin );
Serial.printf ( " WFGAIN........Set the gain for waterfall colouring: %d\n", setting.WaterfallGain );
Serial.println ( "\nOther Commands:\n" ); Serial.println ( "\nOther Commands:\n" );
Serial.print ( " DRIVE.........Local oscillator drive level [0 to 7]; currently: " ); Serial.print ( " DRIVE.........Local oscillator drive level [0 to 7]; currently: " );
@ -259,6 +266,8 @@ void ShowMenu ()
Serial.printf ( " DELAY.........Timestep in uS, currently: %uuS\n", delaytime ); Serial.printf ( " DELAY.........Timestep in uS, currently: %uuS\n", delaytime );
Serial.printf ( " OFFDEL........Timestep in uS for Bandscope, currently: %uuS\n", offsetDelayTime );
Serial.print ( " VFO...........Set or get active VFO [R, ( L or T ), I(tg If), G(tG LO)]; currently: " ); Serial.print ( " VFO...........Set or get active VFO [R, ( L or T ), I(tg If), G(tG LO)]; currently: " );
if ( VFO == RX_4432 ) if ( VFO == RX_4432 )
@ -461,6 +470,7 @@ int16_t addr; // Si4432 register address
int16_t tempValue; // Temporary value of something int16_t tempValue; // Temporary value of something
int32_t tempFreq; // Temporary frequency int32_t tempFreq; // Temporary frequency
float tempFloat;
uint32_t freq1; // Several other temporary frequencies uint32_t freq1; // Several other temporary frequencies
uint32_t freq2; // used in computing the center uint32_t freq2; // used in computing the center
@ -660,7 +670,7 @@ uint8_t reg69; // Ditto
* Unlike the touch-screen equivalent command, here you can set any value you like as opposed * Unlike the touch-screen equivalent command, here you can set any value you like as opposed
* to chosing from a list of standard settings. * to chosing from a list of standard settings.
* *
* If no number is entered, we report the current setting. * If no number is entered, we report the current setting.
*/ */
case MSG_SCALE: case MSG_SCALE:
@ -945,6 +955,20 @@ uint8_t reg69; // Ditto
Serial.printf ( "Time per scan step = %uuS\n", delaytime ); Serial.printf ( "Time per scan step = %uuS\n", delaytime );
return true; return true;
/*
* The "OFFDEL" command sets the timestep in uS for tuning using offsets.
*/
case MSG_OFFDELAY: // Set the timestep in uS, currently 2000
if ( dataLen != 0 ) // Anything entered?
{
offsetDelayTime = atol ( dataBuff ); // Yes, set new delay time
DisplayInfo ();
}
Serial.printf ( "Offset delay time per bandscope step = %uuS\n", offsetDelayTime );
return true;
/* /*
* The "VFO" command sets the active VFO * The "VFO" command sets the active VFO
@ -1289,6 +1313,9 @@ uint8_t reg69; // Ditto
* The "TUNE" comand allows the use to specify the crystal load capacitance for the * The "TUNE" comand allows the use to specify the crystal load capacitance for the
* selected VFO. This teaks the frequency. See A440 and the TinySA documentation for * selected VFO. This teaks the frequency. See A440 and the TinySA documentation for
* info on how it really works. * info on how it really works.
*
* We need to force the SI4432 to recalibrate the PLL after each tune by putting it into READY mode
*
*/ */
case MSG_TUNE: case MSG_TUNE:
@ -1593,6 +1620,39 @@ uint8_t reg69; // Ditto
} }
} }
/*
* The "WFMIN" command sets the min RSSI level for waterfall colouring.
*
* If no number is entered, we report the current setting.
*/
case MSG_WFMIN:
if ( dataLen != 0 ) // Value specified?
{
tempValue = atoi ( dataBuff ); // Yes, get grid reference value
SetWFMin ( tempValue ); // Set it
DisplayInfo (); // Re display the scan
}
Serial.printf ( "Waterfall Minimum RSSI value: %i\n", setting.WaterfallMin );
return true;
/*
* The "WFGAIN" command sets the min RSSI level for waterfall colouring.
*
* If no number is entered, we report the current setting.
*/
case MSG_WFGAIN:
if ( dataLen != 0 ) // Value specified?
{
tempFloat = atof ( dataBuff ); // Yes, get grid reference value
SetWFGain ( tempFloat ); // Set it
Serial.printf("tempFloat = %4.2f\n", tempFloat);
DisplayInfo (); // Re display the scan
}
Serial.printf ( "Waterfall colour gain: %4.2f\n", setting.WaterfallGain );
return true;
default: default:
@ -2685,7 +2745,7 @@ uint32_t lastStart; // Old sweep start frequency
changedSetting = true; // Yes it did changedSetting = true; // Yes it did
initSweep = true; initSweep = true;
// RedrawHisto (); // Redraw labels and restart sweep with new settings // RedrawHisto (); // Redraw labels and restart sweep with new settings
// WriteSettings (); // and save the setting structure WriteSettings (); // and save the setting structure
} }
} }
@ -2922,3 +2982,17 @@ void SetFreq ( int vfo, uint32_t freq )
if ( vfo == TX_4432 ) // Transmitter? if ( vfo == TX_4432 ) // Transmitter?
xmit.SetFrequency ( freq ); xmit.SetFrequency ( freq );
} }
void SetWFMin (int16_t level)
{
if ( (level >=0) && (level < 255) )
setting.WaterfallMin = level;
WriteSettings();
}
void SetWFGain (float gain)
{
if ((gain > 0.1) && (gain < 3.0))
setting.WaterfallGain = gain;
WriteSettings();
}

10
cmd.h
View File

@ -72,7 +72,11 @@
#define MSG_TGOFFSET 43 // Offset TG IF frequency from SA IF #define MSG_TGOFFSET 43 // Offset TG IF frequency from SA IF
#define MSG_BANDSCOPE 44 // Set Bandscope Mode #define MSG_BANDSCOPE 44 // Set Bandscope Mode
#define MSG_IFSWEEP 45 // Set IF Sweep Mode #define MSG_IFSWEEP 45 // Set IF Sweep Mode
#define MSG_COLOURTEST 46 // test of colours - remove this when done! #define MSG_OFFDELAY 46 // Adjust offset tuning delay time before taking reading
#define MSG_WFMIN 47 // set the min level for the waterfall colours
#define MSG_WFGAIN 48 // set the gain for waterfall colouring
#define MSG_COLOURTEST 99 // test of waterfall colours - remove this when done!
typedef struct // Keeps everything together typedef struct // Keeps everything together
{ {
@ -189,4 +193,8 @@ void SetFreq ( int vfo, uint32_t freq );
bool UpdateMarker ( uint8_t mkr, char action ); bool UpdateMarker ( uint8_t mkr, char action );
void SetWFMin (int16_t level);
void SetWFGain (float gain);
#endif // End of "Cmd.h" #endif // End of "Cmd.h"

View File

@ -200,8 +200,8 @@
* The values here were Erik's original values * The values here were Erik's original values
*/ */
#define TX_CAPACITANCE 0x64 // Transmitter (LO) crystal load capacitance #define TX_CAPACITANCE 0x65 // Transmitter (LO) crystal load capacitance
#define RX_CAPACITANCE 0x64 // Receiver crystal load capacitance #define RX_CAPACITANCE 0x59 // Receiver crystal load capacitance
#define TG_LO_CAPACITANCE 0x64 // Tracking generator LO crystal load capacitance #define TG_LO_CAPACITANCE 0x64 // Tracking generator LO crystal load capacitance
#define TG_IF_CAPACITANCE 0x62 // Tracking generator IF crystal load capacitance #define TG_IF_CAPACITANCE 0x62 // Tracking generator IF crystal load capacitance

View File

@ -26,20 +26,28 @@ bandpassFilter_t Si4432::_bandpassFilters[]
{ {
// bw*10, settle, dwn3, ndec, filset // bw*10, settle, dwn3, ndec, filset
{ 26, 7500, 0, 5, 1 }, // 0 "AUTO" selection possibility { 26, 7500, 0, 5, 1 }, // 0 "AUTO" selection possibility
{ 31, 7000, 0, 5, 3 }, // 1 If user selects 3KHz -> 3.1KHz actual { 28, 7300, 0, 5, 2 }, // 1 "AUTO" selection possibility
{ 59, 3700, 0, 4, 3 }, // 2 "AUTO" selection possibility { 31, 7000, 0, 5, 3 }, // 2 If user selects 3KHz -> 3.1KHz actual
{ 106, 2500, 0, 3, 2 }, // 3 If user selects 10KHz -> 10.6KHz actual { 32, 6800, 0, 5, 4 }, // 3 "AUTO" selection possibility
{ 322, 1000, 0, 2, 6 }, // 4 If user selects 30KHz -> 32.2KHz actual { 37, 6500, 0, 5, 5 }, // 4 "AUTO" selection possibility
{ 377, 1000, 0, 1, 1 }, // 5 "AUTO" selection possibility { 42, 6000, 0, 5, 6 }, // 5 "AUTO" selection possibility
{ 562, 700, 0, 1, 5 }, // 6 "AUTO" selection possibility { 45, 5500, 0, 5, 7 }, // 6 "AUTO" selection possibility
{ 832, 600, 0, 0, 2 }, // 7 "AUTO" selection possibility { 49, 5000, 0, 4, 1 }, // 7 "AUTO" selection possibility
{ 1121, 500, 0, 0, 5 }, // 8 If user selects 100KHz -> 112.1KHz actual { 54, 4200, 0, 4, 2 }, // 8 "AUTO" selection possibility
{ 1811, 500, 1, 1, 9 }, // 9 "AUTO" selection possibility { 59, 3700, 0, 4, 3 }, // 9 "AUTO" selection possibility
{ 2488, 450, 1, 0, 2 }, // 10 "AUTO" selection possibility { 72, 3200, 0, 4, 5 }, // 10 "AUTO" selection possibility
{ 3355, 400, 1, 0, 8 }, // 11 If user selects 300KHz -> 335.5KHz actual { 106, 2500, 0, 3, 2 }, // 11 If user selects 10KHz -> 10.6KHz actual
{ 3618, 300, 1, 0, 9 }, // 12 "AUTO" selection possibility { 322, 1000, 0, 2, 6 }, // 12 If user selects 30KHz -> 32.2KHz actual
{ 4685, 300, 1, 0, 11 }, // 13 "AUTO" selection possibility { 377, 1000, 0, 1, 1 }, // 13 "AUTO" selection possibility
{ 6207, 300, 1, 0, 14 } // 14 "AUTO" selection possibility { 562, 700, 0, 1, 5 }, // 14 "AUTO" selection possibility
{ 832, 600, 0, 0, 2 }, // 15 "AUTO" selection possibility
{ 1121, 500, 0, 0, 5 }, // 16 If user selects 100KHz -> 112.1KHz actual
{ 1811, 500, 1, 1, 9 }, // 17 "AUTO" selection possibility
{ 2488, 450, 1, 0, 2 }, // 18 "AUTO" selection possibility
{ 3355, 400, 1, 0, 8 }, // 19 If user selects 300KHz -> 335.5KHz actual
{ 3618, 300, 1, 0, 9 }, // 20 "AUTO" selection possibility
{ 4685, 300, 1, 0, 11 }, // 21 "AUTO" selection possibility
{ 6207, 300, 1, 0, 14 } // 22 "AUTO" selection possibility
}; };
@ -195,9 +203,10 @@ bool Si4432::Init ( uint8_t cap )
* 03/24 - Logic verified against A440 register edscription document * 03/24 - Logic verified against A440 register edscription document
*/ */
WriteByte ( REG_OFC1, ( RXON | PLLON | XTON )); // Receiver, PLL and "Ready Mode" all on
Tune ( cap ); // Set the crystal capacitance to fine tune frequency Tune ( cap ); // Set the crystal capacitance to fine tune frequency
WriteByte ( REG_OFC1, ( RXON | PLLON | XTON )); // Receiver, PLL and "Ready Mode" all on
SetFrequency ( 443920000 ); // 443.92MHz SetFrequency ( 443920000 ); // 443.92MHz
delayMicroseconds ( 300 ); // Time to allow the SI4432 state machine to do its stuff delayMicroseconds ( 300 ); // Time to allow the SI4432 state machine to do its stuff
Serial.printf ( "End of Init - _cs = %i\n", _cs ); Serial.printf ( "End of Init - _cs = %i\n", _cs );
@ -337,7 +346,7 @@ uint8_t registerBuf[4]; // Used to send frequency data in burst mode
/* /*
* add half the frequency resolution to required frequency so the actual value is rounded to nearest, not lowest * add half the frequency resolution to required frequency so the actual value is rounded to nearest, not lowest
* Frequency resoluion is 156.25 in low band, 312.5 in high band but freq is already divided above * Frequency resoluion is 156.25Hz in low band, 312.5Hz in high band but freq is already divided above
*/ */
freq = freq + 78; freq = freq + 78;
/* /*
@ -465,10 +474,10 @@ void Si4432::SetOffsetFreq ( int32_t freq )
uint16_t fo = (double)posFreq/(156.25 * (double)(_hbsel + 1)); uint16_t fo = (double)posFreq/(156.25 * (double)(_hbsel + 1));
if (freq < 0) if (freq < 0)
// do twos complement - invert the bits (0-8) (use XOR) and add one // do twos complement - invert the bits (0-9) (use XOR) and add one
fo = (fo ^ 0x3F) + 1; fo = (fo ^ 0x3FF) + 1;
Serial.printf(" offset frequency %i fo=%3x \n", freq, fo); //Serial.printf(" offset frequency %i fo=%3x \n", freq, fo);
// write to the Si4432 // write to the Si4432
registerBuf[0] = REG_FOFF1|0x80; // First register in write mode (bit 7 set) registerBuf[0] = REG_FOFF1|0x80; // First register in write mode (bit 7 set)
@ -493,7 +502,7 @@ void Si4432::SetOffset ( int32_t offset )
{ {
uint8_t registerBuf[3]; // Used to send data in burst mode uint8_t registerBuf[3]; // Used to send data in burst mode
uint32_t posOffset; uint16_t posOffset;
if (offset < 0) if (offset < 0)
posOffset = -offset; posOffset = -offset;
else else
@ -502,10 +511,10 @@ void Si4432::SetOffset ( int32_t offset )
uint16_t fo = posOffset; uint16_t fo = posOffset;
if (offset < 0) if (offset < 0)
// do twos complement - invert the bits (0-8) (use XOR) and add one // do twos complement - invert the bits (0-9) (use XOR) and add one
fo = (fo ^ 0x3F) + 1; fo = (fo ^ 0x3FF) + 1;
Serial.printf(" offset %i fo=%3x \n", offset, fo); //Serial.printf(" posoffset %3x, offset %i fo=%3x \n", posOffset, offset, fo);
// write to the Si4432 // write to the Si4432
registerBuf[0] = REG_FOFF1|0x80; // First register in write mode (bit 7 set) registerBuf[0] = REG_FOFF1|0x80; // First register in write mode (bit 7 set)
@ -748,15 +757,35 @@ void Si4432::RxMode () // Put module in RX mode
WriteByte ( REG_OFC1, ( RXON | PLLON | XTON )); // Receiver, PLL and "Ready Mode" all on WriteByte ( REG_OFC1, ( RXON | PLLON | XTON )); // Receiver, PLL and "Ready Mode" all on
} }
void Si4432::ReadyMode () // Put module into ready mode, rx and tx off
{
WriteByte ( REG_OFC1, XTON ); // "Ready Mode" on
}
void Si4432::SetMode (uint8_t newMode)
{
WriteByte ( REG_OFC1, newMode ); // "Ready Mode" on
}
uint8_t Si4432::GetMode ()
{
return ReadByte ( REG_OFC1 );
}
/* /*
* "Tune" sets the crystal tuning capacitance. * "Tune" sets the crystal tuning capacitance.
*
* We need to cycle the PLL to force a recalibration after the tune
*/ */
void Si4432::Tune ( uint8_t cap ) // Set the crystal tuning capacitance void Si4432::Tune ( uint8_t cap ) // Set the crystal tuning capacitance
{ {
_capacitance = cap; // Save in local data _capacitance = cap; // Save in local data
WriteByte ( REG_COLC, _capacitance ); // Send to the Si4432 WriteByte ( REG_COLC, _capacitance ); // Send to the Si4432
uint8_t currentMode = ReadByte ( REG_OFC1 );
ReadyMode ();
delayMicroseconds(300);
SetMode ( currentMode );
} }
/* /*

View File

@ -183,7 +183,6 @@ void SetOffset ( int32_t offset ); // Offset based on number of offset incre
void SetPowerReference ( int freq ); // Set the GPIO output for the LO void SetPowerReference ( int freq ); // Set the GPIO output for the LO
void SetDrive ( uint8_t level ); // Sets the drive level void SetDrive ( uint8_t level ); // Sets the drive level
void TxMode ( uint8_t level ); // Put module in TX mode
float SetRBW ( float reqBandwidth10, unsigned long* delaytime_p ); // "reqBandwidth" in kHz * 10 float SetRBW ( float reqBandwidth10, unsigned long* delaytime_p ); // "reqBandwidth" in kHz * 10
@ -194,7 +193,13 @@ bool PreAmpAGC(); // Reads the register and return true if agc set to a
bool GetPreAmpAGC (); // Return true if agc set to auto bool GetPreAmpAGC (); // Return true if agc set to auto
uint8_t GetRSSI (); // Get Receiver Signal Strength uint8_t GetRSSI (); // Get Receiver Signal Strength
void RxMode (); // Put module in RX mode void RxMode (); // Put module in RX mode
void TxMode ( uint8_t level ); // Put module in TX mode
void ReadyMode (); // Put module in READY mode, crystal on, PLL off
uint8_t GetMode ();
void SetMode (uint8_t newMode);
void Tune ( uint8_t cap ); // Set the crystal tuning capacitance void Tune ( uint8_t cap ); // Set the crystal tuning capacitance
void WriteByte ( byte reg, byte setting ); // Write a byte of data to the specified register void WriteByte ( byte reg, byte setting ); // Write a byte of data to the specified register

View File

@ -233,7 +233,7 @@ typedef struct {
int8_t Attenuate = 0; // Attenuator setting (***) int8_t Attenuate = 0; // Attenuator setting (***)
int8_t Generate = 0; // Signal generator mode if not zero (***) int8_t Generate = 0; // Signal generator mode if not zero (***)
int16_t Bandwidth10 = 0; // Resolution Bandwidth setting*10; 0 = auto int16_t Bandwidth10 = 0; // Resolution Bandwidth setting*10; 0 = auto
int16_t LevelOffset = 0; // Related to power reading; not sure what though! int16_t LevelOffset = 0; // Calibration value (move to config?)
int8_t ReferenceOut = 1; // Transmitter GPIO2 set to 15MHz int8_t ReferenceOut = 1; // Transmitter GPIO2 set to 15MHz
int16_t PowerGrid = 10; // dB/vertical divison on the grid int16_t PowerGrid = 10; // dB/vertical divison on the grid
bool Spur = 0; // Spur reduction on or off bool Spur = 0; // Spur reduction on or off
@ -243,7 +243,7 @@ typedef struct {
bool SubtractStorage = 0; // Subtract stored scan (on or off) bool SubtractStorage = 0; // Subtract stored scan (on or off)
bool ShowGain = 1; // Display gain trace (on or off) bool ShowGain = 1; // Display gain trace (on or off)
bool ShowSweep = 1; // Display dB trace (on or off) bool ShowSweep = 1; // Display dB trace (on or off)
uint8_t Drive = 6; // LO Drive power (***) uint8_t Drive = 6; // LO Drive power (***) (move to config?)
uint8_t SigGenDrive = 5; // Signal generator drive (for RX SI4432) uint8_t SigGenDrive = 5; // Signal generator drive (for RX SI4432)
uint8_t spareUint8t_1 = 5; // spare uint8_t spareUint8t_1 = 5; // spare
uint8_t spareUint8t_2 = 5; // spare uint8_t spareUint8t_2 = 5; // spare
@ -254,7 +254,10 @@ typedef struct {
uint32_t BandscopeStart = 7000000; // Start frequency for bandscope sweep uint32_t BandscopeStart = 7000000; // Start frequency for bandscope sweep
uint32_t BandscopeSpan = 200000; // Span for the bandscope sweep uint32_t BandscopeSpan = 200000; // Span for the bandscope sweep
uint16_t BandscopePoints = BANDSCOPE_POINTS; // No of points in the sweep. 80/160/320 uint16_t BandscopePoints = BANDSCOPE_POINTS; // No of points in the sweep. 80/160/320
int16_t BandscopeMaxGrid= -30;
int16_t BandscopeMinGrid= -130;
int16_t WaterfallMin = 17; // RSSI values below this are treated as zero
float WaterfallGain = 1.5; // Multiply RSSI value to get colour intensity
/* /*
* The following line should read: * The following line should read:

View File

@ -373,6 +373,8 @@ uint16_t yOrigin = Y_ORIGIN;
uint16_t displayPoints = DISPLAY_POINTS; uint16_t displayPoints = DISPLAY_POINTS;
uint16_t xDelta = displayPoints / xGrid; uint16_t xDelta = displayPoints / xGrid;
uint16_t waterfallHeight = WATERFALL_HEIGHT; uint16_t waterfallHeight = WATERFALL_HEIGHT;
int16_t maxGrid;
int16_t minGrid;
/* /*
* Some varibales for the various operating modes * Some varibales for the various operating modes
@ -382,7 +384,7 @@ const char *modeText[] = { "SALo", "SAHi", "SGLo", "SGHi", "IFSw", "0SpL", "0SpH
float bandwidth; // The current bandwidth (not * 10) float bandwidth; // The current bandwidth (not * 10)
unsigned long delaytime = 2000; // M0WID - changed to microseconds and moved here unsigned long delaytime = 2000; // delay time to allow SI4432 filters to settle
uint32_t steps = displayPoints; // Number of frequency steps in the sweep uint32_t steps = displayPoints; // Number of frequency steps in the sweep
uint32_t sweepPoints; // Number of points in the sweep. Can be more than DISPLAY_POINTS if RBW is set less than video resolution uint32_t sweepPoints; // Number of points in the sweep. Can be more than DISPLAY_POINTS if RBW is set less than video resolution
@ -390,6 +392,17 @@ uint32_t startFreq = 0; // Default start frequency is 0MHz
uint32_t stopFreq = 100000000; // Default stop frequency is 100MHz uint32_t stopFreq = 100000000; // Default stop frequency is 100MHz
uint32_t tempIF; // IF used for this sweep. Changes if Spur reduction is on uint32_t tempIF; // IF used for this sweep. Changes if Spur reduction is on
/*
* Variables for offset frequency tuning
*/
int32_t offsetFreq; // Frequency offset from nominal setting
int16_t offsetStep; // increments by one at each reading
int16_t offsetValue; // Offset value to be written to Si4432
int16_t offsetIncrement; // Increment of offsetValue per reading
int32_t offsetFreqIncrement; // Increment offsetFreq per reading
unsigned long offsetDelayTime = 5000; // Delay time when using frequency offset to change frequency
int VFO = RX_4432; // Set current VFO for command parser to the receiver Si4432 int VFO = RX_4432; // Set current VFO for command parser to the receiver Si4432
int gainReading; // Current preamp gain (will vary during a scan if AGC enabled) int gainReading; // Current preamp gain (will vary during a scan if AGC enabled)
@ -1404,10 +1417,10 @@ double fStop;
sSprite.setCursor ( 0, CHAR_HEIGHT * 2 ); sSprite.setCursor ( 0, CHAR_HEIGHT * 2 );
sSprite.setTextColor ( DB_COLOR ); sSprite.setTextColor ( DB_COLOR );
sSprite.printf ( "%4i", setting.MaxGrid ); sSprite.printf ( "%4i", maxGrid );
sSprite.setCursor ( 0, gridHeight + yOrigin ); sSprite.setCursor ( 0, gridHeight + yOrigin );
sSprite.printf ( "%4i", setting.MinGrid ); sSprite.printf ( "%4i", minGrid );
sSprite.setTextColor ( WHITE ); sSprite.setTextColor ( WHITE );
sSprite.setCursor ( 0, HALF_CHAR_H * 8 ); sSprite.setCursor ( 0, HALF_CHAR_H * 8 );
@ -1682,10 +1695,10 @@ void DrawCheckerBoard ( int x )
uint16_t rssiToImgY ( uint8_t rSSI ) uint16_t rssiToImgY ( uint8_t rSSI )
{ {
int delta = setting.MaxGrid - setting.MinGrid; int delta = maxGrid - minGrid;
double y = rssiTodBm ( rSSI ); double y = rssiTodBm ( rSSI );
y = ( y - setting.MinGrid ) * gridHeight / delta; y = ( y - minGrid ) * gridHeight / delta;
if ( y >= gridHeight ) if ( y >= gridHeight )
y = gridHeight-1; y = gridHeight-1;
@ -1721,9 +1734,9 @@ void DisplayPoint ( uint8_t* data, int i, int color )
return; return;
int lastPoint = i - 1; int lastPoint = i - 1;
int delta = setting.MaxGrid - setting.MinGrid; int delta = maxGrid - minGrid;
double f0 = (( data[i] / 2.0 + setting.Attenuate ) - 120.0 ) + setting.LevelOffset; // Current point double f0 = (( data[i] / 2.0 + setting.Attenuate ) - 120.0 ) + setting.LevelOffset; // Current point
f0 = ( f0 - setting.MinGrid ) * gridHeight / delta; f0 = ( f0 - minGrid ) * gridHeight / delta;
if ( f0 >= gridHeight ) if ( f0 >= gridHeight )
f0 = gridHeight-1; f0 = gridHeight-1;
@ -1733,7 +1746,7 @@ void DisplayPoint ( uint8_t* data, int i, int color )
double f1 = (( data[lastPoint] / 2.0 + setting.Attenuate ) - 120.0) + setting.LevelOffset; // Previous point double f1 = (( data[lastPoint] / 2.0 + setting.Attenuate ) - 120.0) + setting.LevelOffset; // Previous point
f1 = ( f1 - setting.MinGrid ) * gridHeight / delta; f1 = ( f1 - minGrid ) * gridHeight / delta;
if ( f1 >= gridHeight ) if ( f1 >= gridHeight )
f1 = gridHeight-1; f1 = gridHeight-1;

1
ui.cpp
View File

@ -1170,6 +1170,7 @@ void menu_mode_cb ( int item )
ui_mode_normal (); // No menu displayed ui_mode_normal (); // No menu displayed
break; break;
} }
changedSetting = true;
} }