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:
* 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 IF is 434MHz then 480MHz -> 46Mhz for the signal being analysed, so fine
* 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)
* 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 autoSweepFreq = 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 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 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 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 lastMinRSSI; // Minimum level for the previous sweep
@ -171,9 +167,10 @@ static uint16_t chunkIndex;
{
sweepPoints = setting.BandscopePoints;
autoSweepFreqStep = ( setting.BandscopeSpan ) / sweepPoints;
offsetFreqIncrement = autoSweepFreqStep; // 2500 Hz for 200kHz span, 80 points per sweep
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
@ -192,6 +189,9 @@ static uint16_t chunkIndex;
resetAverage = changedSetting;
maxGrid = setting.BandscopeMaxGrid;
minGrid = setting.BandscopeMinGrid;
#ifdef USE_WIFI
// 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
autoSweepFreq = setting.BandscopeStart; // Set the start frequency.
nextPointFreq = autoSweepFreq + autoSweepFreqStep;
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
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
@ -250,13 +258,6 @@ static uint16_t chunkIndex;
// Serial.printf(" start %i; stop %i; points %i \n", startFreq, stopFreq, sweepPoints );
if ( setActualPowerRequested )
{
SetPowerLevel ( actualPower );
setActualPowerRequested = false;
}
lastMinRSSI = minRSSI;
minRSSI = 255; // real value should always be less
@ -288,7 +289,7 @@ static uint16_t chunkIndex;
*/
nowMicros = micros();
while (( nowMicros - setFreqMicros ) < delaytime )
while (( nowMicros - setFreqMicros ) < bandscopeDelay )
{
if ( ( nowMicros - setFreqMicros + delaytime > 200 ) &&
@ -328,15 +329,30 @@ static uint16_t chunkIndex;
autoSweepFreq += autoSweepFreqStep; // Increment the frequency
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.
*/
uint32_t f = setting.IF_Freq + autoSweepFreq;
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
@ -402,7 +418,7 @@ static uint16_t chunkIndex;
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
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)
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
// We will just change the green here for first test
uint32_t pixelColour = (rxRSSI - 17) << 5 ; // testing colours
if (rxRSSI < 17)
pixelColour = 0;
if (colourTest > 0)
/*
* 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
* We will just change the green level here for first test
*/
uint32_t level = (uint32_t)( (float)(rxRSSI - setting.WaterfallMin) * setting.WaterfallGain) ; // testing colours
if (rxRSSI < setting.WaterfallMin)
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;
// 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 );
}
@ -627,3 +663,21 @@ double fStop;
updateSidebar = false;
} // 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
maxGrid = setting.MaxGrid;
minGrid = setting.MinGrid;
#ifdef USE_WIFI
// Vary number of points to send in each chunk depending on delaytime
// 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 uint32_t peakFreq;
static uint16_t peakIndex;
static uint16_t maxRSSI;
static uint32_t maxFreq;
static uint16_t maxIndex;
static uint16_t pointsPastPeak;
static uint16_t pointsPastDip;
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
maxGrid = setting.MaxGrid;
minGrid = setting.MinGrid;
#ifdef USE_WIFI
// Vary number of points to send in each chunk depending on delaytime
// 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
peakRSSI = 0;
maxRSSI = 0;
sweepStartDone = true; // Make sure this initialize is only done once per sweep
initSweep = false;
@ -358,7 +365,7 @@ static uint16_t chunkIndex;
uint32_t f = tempIF + autoSweepFreq;
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
if (tgLO_OK && (trackGenSetting.Mode == 1) )
@ -507,15 +514,15 @@ static uint16_t chunkIndex;
if (( autoSweepFreq > MARKER_MIN_FREQUENCY ) && (oldSweepStep > 0))
{
if ( peakLevel < myData[oldSweepStep] )
{
peakIndex = oldSweepStep;
peakLevel = myData[oldSweepStep];
peakFreq = oldSweepFreq;
// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
// displayPeakData ();
}
// if ( maxRSSI <= myActual[oldSweepStep] )
// {
// maxIndex = oldSweepStep;
// maxRSSI = myActual[oldSweepStep];
// maxFreq = oldSweepFreq;
//
//// Serial.printf( "peakLevel set %i, index %i\n", peakLevel, oldSweepStep);
//// displayPeakData ();
// }
/*
@ -620,6 +627,8 @@ static uint16_t chunkIndex;
if ( sweepCount < 2 )
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
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 unsigned long delaytime; // In microseconds
extern unsigned long offsetDelayTime; // In microseconds
extern unsigned long wiFiTargetTime;
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
{ "TGIFDRIVE", MSG_TG_IF_DRIVE }, // Set Track Generator IF Drive level
{ "TGLODRIVE", MSG_TG_LO_DRIVE }, // Set Track Generator LO Drive level
{ "IFSIGNAL", MSG_IFSIGNAL }, // IF sweep signal frequency
{ "TGOFFSET", MSG_TGOFFSET }, // Offset TG IF from SA IF to reduce pass through
{ "IFSIGNAL", MSG_IFSIGNAL }, // IF sweep signal frequency
{ "TGOFFSET", MSG_TGOFFSET }, // Offset TG IF from SA IF to reduce pass through
{ "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);
@ -227,6 +231,9 @@ void ShowMenu ()
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.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 ( " 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: " );
if ( VFO == RX_4432 )
@ -461,6 +470,7 @@ int16_t addr; // Si4432 register address
int16_t tempValue; // Temporary value of something
int32_t tempFreq; // Temporary frequency
float tempFloat;
uint32_t freq1; // Several other temporary frequencies
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
* 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:
@ -945,6 +955,20 @@ uint8_t reg69; // Ditto
Serial.printf ( "Time per scan step = %uuS\n", delaytime );
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
@ -1289,6 +1313,9 @@ uint8_t reg69; // Ditto
* 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
* 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:
@ -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:
@ -2685,7 +2745,7 @@ uint32_t lastStart; // Old sweep start frequency
changedSetting = true; // Yes it did
initSweep = true;
// 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?
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_BANDSCOPE 44 // Set Bandscope 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
{
@ -189,4 +193,8 @@ void SetFreq ( int vfo, uint32_t freq );
bool UpdateMarker ( uint8_t mkr, char action );
void SetWFMin (int16_t level);
void SetWFGain (float gain);
#endif // End of "Cmd.h"

View File

@ -200,8 +200,8 @@
* The values here were Erik's original values
*/
#define TX_CAPACITANCE 0x64 // Transmitter (LO) crystal load capacitance
#define RX_CAPACITANCE 0x64 // Receiver crystal load capacitance
#define TX_CAPACITANCE 0x65 // Transmitter (LO) crystal load capacitance
#define RX_CAPACITANCE 0x59 // Receiver 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

View File

@ -26,20 +26,28 @@ bandpassFilter_t Si4432::_bandpassFilters[]
{
// bw*10, settle, dwn3, ndec, filset
{ 26, 7500, 0, 5, 1 }, // 0 "AUTO" selection possibility
{ 31, 7000, 0, 5, 3 }, // 1 If user selects 3KHz -> 3.1KHz actual
{ 59, 3700, 0, 4, 3 }, // 2 "AUTO" selection possibility
{ 106, 2500, 0, 3, 2 }, // 3 If user selects 10KHz -> 10.6KHz actual
{ 322, 1000, 0, 2, 6 }, // 4 If user selects 30KHz -> 32.2KHz actual
{ 377, 1000, 0, 1, 1 }, // 5 "AUTO" selection possibility
{ 562, 700, 0, 1, 5 }, // 6 "AUTO" selection possibility
{ 832, 600, 0, 0, 2 }, // 7 "AUTO" selection possibility
{ 1121, 500, 0, 0, 5 }, // 8 If user selects 100KHz -> 112.1KHz actual
{ 1811, 500, 1, 1, 9 }, // 9 "AUTO" selection possibility
{ 2488, 450, 1, 0, 2 }, // 10 "AUTO" selection possibility
{ 3355, 400, 1, 0, 8 }, // 11 If user selects 300KHz -> 335.5KHz actual
{ 3618, 300, 1, 0, 9 }, // 12 "AUTO" selection possibility
{ 4685, 300, 1, 0, 11 }, // 13 "AUTO" selection possibility
{ 6207, 300, 1, 0, 14 } // 14 "AUTO" selection possibility
{ 28, 7300, 0, 5, 2 }, // 1 "AUTO" selection possibility
{ 31, 7000, 0, 5, 3 }, // 2 If user selects 3KHz -> 3.1KHz actual
{ 32, 6800, 0, 5, 4 }, // 3 "AUTO" selection possibility
{ 37, 6500, 0, 5, 5 }, // 4 "AUTO" selection possibility
{ 42, 6000, 0, 5, 6 }, // 5 "AUTO" selection possibility
{ 45, 5500, 0, 5, 7 }, // 6 "AUTO" selection possibility
{ 49, 5000, 0, 4, 1 }, // 7 "AUTO" selection possibility
{ 54, 4200, 0, 4, 2 }, // 8 "AUTO" selection possibility
{ 59, 3700, 0, 4, 3 }, // 9 "AUTO" selection possibility
{ 72, 3200, 0, 4, 5 }, // 10 "AUTO" selection possibility
{ 106, 2500, 0, 3, 2 }, // 11 If user selects 10KHz -> 10.6KHz actual
{ 322, 1000, 0, 2, 6 }, // 12 If user selects 30KHz -> 32.2KHz actual
{ 377, 1000, 0, 1, 1 }, // 13 "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
*/
WriteByte ( REG_OFC1, ( RXON | PLLON | XTON )); // Receiver, PLL and "Ready Mode" all on
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
delayMicroseconds ( 300 ); // Time to allow the SI4432 state machine to do its stuff
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
* 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;
/*
@ -465,10 +474,10 @@ void Si4432::SetOffsetFreq ( int32_t freq )
uint16_t fo = (double)posFreq/(156.25 * (double)(_hbsel + 1));
if (freq < 0)
// do twos complement - invert the bits (0-8) (use XOR) and add one
fo = (fo ^ 0x3F) + 1;
// do twos complement - invert the bits (0-9) (use XOR) and add one
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
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
uint32_t posOffset;
uint16_t posOffset;
if (offset < 0)
posOffset = -offset;
else
@ -502,10 +511,10 @@ void Si4432::SetOffset ( int32_t offset )
uint16_t fo = posOffset;
if (offset < 0)
// do twos complement - invert the bits (0-8) (use XOR) and add one
fo = (fo ^ 0x3F) + 1;
// do twos complement - invert the bits (0-9) (use XOR) and add one
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
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
}
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.
*
* We need to cycle the PLL to force a recalibration after the tune
*/
void Si4432::Tune ( uint8_t cap ) // Set the crystal tuning capacitance
{
_capacitance = cap; // Save in local data
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 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
@ -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
uint8_t GetRSSI (); // Get Receiver Signal Strength
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 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 Generate = 0; // Signal generator mode if not zero (***)
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
int16_t PowerGrid = 10; // dB/vertical divison on the grid
bool Spur = 0; // Spur reduction on or off
@ -243,7 +243,7 @@ typedef struct {
bool SubtractStorage = 0; // Subtract stored scan (on or off)
bool ShowGain = 1; // Display gain 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 spareUint8t_1 = 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 BandscopeSpan = 200000; // Span for the bandscope sweep
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:

View File

@ -373,6 +373,8 @@ uint16_t yOrigin = Y_ORIGIN;
uint16_t displayPoints = DISPLAY_POINTS;
uint16_t xDelta = displayPoints / xGrid;
uint16_t waterfallHeight = WATERFALL_HEIGHT;
int16_t maxGrid;
int16_t minGrid;
/*
* 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)
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 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 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 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.setTextColor ( DB_COLOR );
sSprite.printf ( "%4i", setting.MaxGrid );
sSprite.printf ( "%4i", maxGrid );
sSprite.setCursor ( 0, gridHeight + yOrigin );
sSprite.printf ( "%4i", setting.MinGrid );
sSprite.printf ( "%4i", minGrid );
sSprite.setTextColor ( WHITE );
sSprite.setCursor ( 0, HALF_CHAR_H * 8 );
@ -1682,10 +1695,10 @@ void DrawCheckerBoard ( int x )
uint16_t rssiToImgY ( uint8_t rSSI )
{
int delta = setting.MaxGrid - setting.MinGrid;
int delta = maxGrid - minGrid;
double y = rssiTodBm ( rSSI );
y = ( y - setting.MinGrid ) * gridHeight / delta;
y = ( y - minGrid ) * gridHeight / delta;
if ( y >= gridHeight )
y = gridHeight-1;
@ -1721,9 +1734,9 @@ void DisplayPoint ( uint8_t* data, int i, int color )
return;
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
f0 = ( f0 - setting.MinGrid ) * gridHeight / delta;
f0 = ( f0 - minGrid ) * gridHeight / delta;
if ( f0 >= gridHeight )
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
f1 = ( f1 - setting.MinGrid ) * gridHeight / delta;
f1 = ( f1 - minGrid ) * gridHeight / delta;
if ( f1 >= gridHeight )
f1 = gridHeight-1;

1
ui.cpp
View File

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