SetOffset Function done

Rationalised SI4432 Init
Added SI4432:SetOffset function - not tested
This commit is contained in:
M0WID 2020-08-18 21:30:39 +01:00
parent 94d02de911
commit be199ef50c
2 changed files with 91 additions and 120 deletions

View File

@ -97,82 +97,6 @@ bool Si4432::Init ( uint8_t cap )
if ( !Reset () ) // Reset the module
return false; // If that failed
SubInit (); // Things common to both modules
/*
*
* We turn on receive mode ("RXON"), the PLL ("PLLON") and ready mode
* ("XTON"). The Si4432 module does not have the 32.768 kHz crystal for
* the microcontroller, so we do not turn on the "X32KSEL" bit.
*
* The initial frequency is set to 433.92 MHz which is a typical IF
* Finally the GPIO-2 pin is set to ground.
*
* 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
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 );
return true;
}
//bool Si4432::TX_Init ( uint8_t cap, uint8_t power )
//{
// _type = TX_4432; // We're a transmitter
//
// if ( !Reset () ) // Reset the module
// return false; // If that failed
// _pwr = power; // Set the transmitter power level
// SubInit (); // Things common to both modules
//
//
///*
// * Settings specific to the transmitter module.
// *
// * This is almost identical to how we set up the receiver except we turn
// * on the "TXON" bit (0x08) instead of the "RXON" bit. We also set the
// * transmitter power based on the mixer module being used. ("CalcPower"
// * function sets the value).
// *
// * GPIO-2 is handled differently; here, we set GPIO-2 to output the
// * microcontroller clock at maximum drive level (0xC0). We also set the
// * microcontroller clock speed to 10MHz.
// *
// * 03/24 - Logic verified against A440
// */
//
// Tune ( cap ); // Set the crystal capacitance
// WriteByte ( REG_TXPWR, _pwr ); // Power based on mixer in use
//
// WriteByte ( REG_GPIO2, 0xC0 ); // Maximum drive and microcontroller clock output
// WriteByte ( REG_MCOC, 0x02 ); // Set 10MHz clock output
//
// SetFrequency ( 443920000 ); // 433.92MHz (setting.IF_Freq???)
//
// delayMicroseconds ( 300 ); // Doesn't work without this!
//
// WriteByte ( REG_OFC1, ( TXON | PLLON | XTON )); // Transmitter, PLL and "Ready Mode" all on
//
//// Serial.println ( "End of TX_Init" );
//
// return true;
//}
/*
* "SubInit" is used by the "Init" function to set up
* all the registers.
*/
void Si4432::SubInit ()
{
/*
@ -257,10 +181,31 @@ void Si4432::SubInit ()
WriteByte ( REG_GPIO1, 0x15 ); // GPIO-1 RX State (output)
WriteByte ( REG_GPIO2, 0x1F ); // Set GPIO-2 output to ground until needed
/*
*
* We turn on receive mode ("RXON"), the PLL ("PLLON") and ready mode
* ("XTON"). The Si4432 module does not have the 32.768 kHz crystal for
* the microcontroller, so we do not turn on the "X32KSEL" bit.
*
* The initial frequency is set to 433.92 MHz which is a typical IF
* Finally the GPIO-2 pin is set to ground.
*
* 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
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 );
return true;
}
/*
* "Reset" - Initializes the Si4432.
*
@ -369,7 +314,7 @@ uint8_t Si4432::ReadByte ( uint8_t reg )
void Si4432::SetFrequency ( uint32_t freq )
{
int hbsel; // High/low band select bit
int hbsel; // high band select, but shifted to the correct location in the byte
int sbsel; // Sideband select bit
uint16_t carrier; // Carrier frequency
uint32_t reqFreq = freq; // Copy of requested frequency
@ -440,56 +385,31 @@ uint8_t registerBuf[4]; // Used to send frequency data in burst mode
/*
* M0WID mod - Update the frequency in "burst" mode as opposed to separate
* writes for each register, but only update what is needed
* writes for each register
*/
uint8_t ncf1 = ( carrier >> 8 ) & 0xFF;
// if (fbs != _fbs) // write all three registers
// {
registerBuf[0] = REG_FBS|0x80; // First register in write mode (bit 7 set)
registerBuf[1] = fbs; // FBS register value
registerBuf[2] = ncf1 ; // NCF1 value
registerBuf[3] = carrier & 0xFF; // NCF0 value
//_spi->beginTransaction ( SPISettings ( BUS_SPEED, BUS_ORDER, BUS_MODE ));
// spiSimpleTransaction(_spi->bus());
digitalWrite ( _cs, LOW ); // Select the correct device
_spi->transfer ( registerBuf, 4 ); // Send the data
digitalWrite ( _cs, HIGH ); // Deselect the device
//_spi->endTransaction();
_ncf1 = ncf1;
_fbs = fbs;
// }
// else if (ncf1 != _ncf1) // Only write both bytes of the carrier data
// {
// registerBuf[0] = REG_NCF1|0x80; // First register in write mode (bit 7 set)
// registerBuf[1] = ncf1 ; // NCF1 value
// registerBuf[2] = carrier & 0xFF; // NCF0 value
// digitalWrite ( _cs, LOW ); // Select the correct device
// _spi->transfer ( registerBuf, 3 ); // Send the data
// digitalWrite ( _cs, HIGH ); // Deselect the device
// _ncf1 = ncf1;
// }
// else // Only write the least significant byte of the carrier register
// {
// registerBuf[0] = REG_NCF0|0x80; // First register in write mode (bit 7 set)
// registerBuf[1] = carrier & 0xFF; // NCF0 value
// digitalWrite ( _cs, LOW ); // Select the correct device
// _spi->transfer ( registerBuf, 2 ); // Send the data
// digitalWrite ( _cs, HIGH ); // Deselect the device
//
// }
registerBuf[0] = REG_FBS|0x80; // First register in write mode (bit 7 set)
registerBuf[1] = fbs; // FBS register value
registerBuf[2] = ncf1 ; // NCF1 value
registerBuf[3] = carrier & 0xFF; // NCF0 value
//_spi->beginTransaction ( SPISettings ( BUS_SPEED, BUS_ORDER, BUS_MODE ));
// spiSimpleTransaction(_spi->bus());
digitalWrite ( _cs, LOW ); // Select the correct device
_spi->transfer ( registerBuf, 4 ); // Send the data
digitalWrite ( _cs, HIGH ); // Deselect the device
//_spi->endTransaction();
_ncf1 = ncf1;
_fbs = fbs;
uint32_t fb = ( fbs & F_BAND ) ;
hbsel = hbsel>>5; // should be 1 or 0
_hbsel = hbsel>>5; // should be 1 or 0
// _freq will contain the actual frequency, not necessarily what was requested
_freq = (double)(10000000 * (hbsel + 1 )) * ( (double)fb + (double)24 + (double)carrier / (double)64000) ;
_freq = (double)(10000000 * (_hbsel + 1 )) * ( (double)fb + (double)24 + (double)carrier / (double)64000) ;
// Serial.printf("set Freq :%i, actual:%i, fb:%i, fc:%i, hbsel:%i\n", reqFreq, _freq, fb, carrier, hbsel);
// _spi->endTransaction(); // Release the bus
// delayMicroseconds ( WRITE_DELAY ); // Delay needed when writing frequency
// Serial.print ( ", N = " );
// Serial.print ( N );
@ -518,10 +438,55 @@ uint8_t registerBuf[4]; // Used to send frequency data in burst mode
* handled by the calling program.
*/
// delayMicroseconds ( _dt ); // M0WID - Delay depends on RBW
// delayMicroseconds ( _dt );
}
/*
* "SetOffset" adjusts the frequency from the nominal value set in SetFrequency.
* It is intended for use by the SI4432 AFC algorithm to enable more accurate
* frequency matching of different radios, but we can turn off the AFC and use it
* to adjust the frequency without having the Si4432 go through its TX-RX-TX state machine
* and enable reduced edlay times from setting a frequency to getting valid readings
* The offset can vary +- 80kHz in low bands (f<480MHz) and +-160kHz in high bands (480-960MHz)
* negative numbers are twos complement of the positive offset
*/
void Si4432::SetOffset ( int32_t offset )
{
uint8_t registerBuf[3]; // Used to send data in burst mode
uint32_t posOffset;
if (offset < 0)
posOffset = -offset;
else
posOffset = offset;
uint16_t fo = (double)offset/(156.25 * (double)(_hbsel + 1));
if (offset < 0)
// do twos complement - invert the bits (0-8) (use XOR) and add one
fo = (fo ^ 0x3F) + 1;
Serial.printf(" offset %i fo=%3x \n", offset, fo);
// write to the Si4432
registerBuf[0] = REG_FOFF1|0x80; // First register in write mode (bit 7 set)
registerBuf[1] = fo & 0xFF; // first 8 bits
registerBuf[2] = (fo >> 8 ) & 0x03; // last 2 bits
//_spi->beginTransaction ( SPISettings ( BUS_SPEED, BUS_ORDER, BUS_MODE ));
// spiSimpleTransaction(_spi->bus());
digitalWrite ( _cs, LOW ); // Select the correct device
_spi->transfer ( registerBuf, 3 ); // Send the data
digitalWrite ( _cs, HIGH ); // Deselect the device
//_spi->endTransaction();
}
/*
* "SetRBW" Sets the "Resolution Bandwidth" based on a required value passed in
* and returns the actual value chosen as well as the required delay to allow the

View File

@ -142,6 +142,9 @@
#define REG_TXPWR 0x6D // Transmitter Power
#define REG_FOFF1 0x73 // Frequency Offset registers
#define REG_FOFF2 0x74
#define REG_FBS 0x75 // Frequency Band Select
#define SBSEL 0x40
#define HBSEL 0x20
@ -175,6 +178,8 @@ void SetFrequency ( uint32_t Freq ); // Set module's frequency
uint32_t GetFrequency (); // Get the module's frequency
uint32_t ReadFrequency (); // Read frequency from SI4432
void SetOffset ( int32_t offset ); // Set a frequency offset from the nominal frequency
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
@ -221,6 +226,7 @@ uint8_t _pwr; // Current power output (TX only?)
uint8_t _type; // Transmitter or receiver
uint8_t _capacitance; // Crystal load capacitance
SPIClass* _spi; // Pointer to the SPI object
int _hbsel; // High band (1) or low band (0)
uint8_t _fbs; // Current value of frequency band select register
uint8_t _ncf1; // Current value for most significant byte of carrier
uint32_t _freq; // Current actual frequency