diff --git a/Bandscope.ino b/Bandscope.ino index c6cbba3..c4b1d3a 100644 --- a/Bandscope.ino +++ b/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 - 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; +} diff --git a/IFsweep.ino b/IFsweep.ino index f9f80df..0aecf39 100644 --- a/IFsweep.ino +++ b/IFsweep.ino @@ -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 diff --git a/SweepLo.ino b/SweepLo.ino index af5cd69..6a2d701 100644 --- a/SweepLo.ino +++ b/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 diff --git a/cmd.cpp b/cmd.cpp index fb03400..0c06c65 100644 --- a/cmd.cpp +++ b/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; @@ -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(); +} diff --git a/cmd.h b/cmd.h index 4d33289..c9a290d 100644 --- a/cmd.h +++ b/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" diff --git a/my_SA.h b/my_SA.h index 3b0fe44..a46f941 100644 --- a/my_SA.h +++ b/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 diff --git a/si4432.cpp b/si4432.cpp index dec49f3..61a1595 100644 --- a/si4432.cpp +++ b/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 ); } /* diff --git a/si4432.h b/si4432.h index 0044f81..07a34c5 100644 --- a/si4432.h +++ b/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 diff --git a/simpleSA.h b/simpleSA.h index 04e4018..b120d9a 100644 --- a/simpleSA.h +++ b/simpleSA.h @@ -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: diff --git a/simpleSA.ino b/simpleSA.ino index cd8bcd7..28ec176 100644 --- a/simpleSA.ino +++ b/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; diff --git a/ui.cpp b/ui.cpp index 05bee68..9c97364 100644 --- a/ui.cpp +++ b/ui.cpp @@ -1170,6 +1170,7 @@ void menu_mode_cb ( int item ) ui_mode_normal (); // No menu displayed break; } + changedSetting = true; }