FrequencyControl improved
Added new RBW options Modified Si4432::Tune to change modes to recalibrate PLL
This commit is contained in:
parent
1cb4cdef6e
commit
f105b70210
124
Bandscope.ino
124
Bandscope.ino
@ -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
|
||||
|
||||
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
|
||||
@ -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
|
||||
/*
|
||||
* 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 = (rxRSSI - 17) << 5 ; // testing colours
|
||||
if (rxRSSI < 17)
|
||||
pixelColour = 0;
|
||||
if (colourTest > 0)
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
29
SweepLo.ino
29
SweepLo.ino
@ -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
|
||||
|
76
cmd.cpp
76
cmd.cpp
@ -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;
|
||||
@ -169,6 +170,9 @@ extern void setMode (uint16_t newMode);
|
||||
{ "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!
|
||||
{ "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
|
||||
};
|
||||
|
||||
@ -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
|
||||
@ -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
10
cmd.h
@ -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"
|
||||
|
4
my_SA.h
4
my_SA.h
@ -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
|
||||
|
75
si4432.cpp
75
si4432.cpp
@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
7
si4432.h
7
si4432.h
@ -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
|
||||
|
@ -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:
|
||||
|
29
simpleSA.ino
29
simpleSA.ino
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user