Library to control Silicon Labs SI570 10 MHZ TO 1.4 GHZ I2C PROGRAMMABLE XO/VCXO.

Dependents:   t2d Thing2Do

This is the page for the Silicon Laboratories Si570 frequency synthesizer, with I2C interface.

The Si570 XO/Si571 VCXO utilizes Silicon Laboratories’ advanced DSPLL® circuitry to provide a low-jitter clock at any frequency. The Si570/Si571 are user-programmable to any output frequency from 10 to 945 MHz and select frequencies to 1400 MHz with <1 ppb resolution. The device is programmed via an I2C serial interface. Unlike traditional XO/VCXOs where a different crystal is required for each output frequency, the Si57x uses one fixed- frequency crystal and a DSPLL clock synthesis IC to provide any-frequency operation. This IC-based approach allows the crystal resonator to provide exceptional frequency stability and reliability. In addition, DSPLL clock synthesis provides superior supply noise rejection, simplifying the task of generating low-jitter clocks in noisy environments typically found in communication systems.

The Si570 is very popular for amateur radio use. It can be used as the local oscillator in a superheterodyne receiver, or it can be the local oscillator in a direct conversion quadrature receiver for software defined radio (SDR) such as the Softrock. In addition to its use inside a receiver, the Si570 kit can be used as a stand-alone signal source for test and measurement and for other purposes, such as a VFO for your old Heathkit DX40 for that matter. Just keep in mind that the Si570's output is a square wave and may require additional filtering for some purposes.

Image of the SI570 in action

/media/uploads/soldeerridder/si570_sr.jpg

Hello World!

 #include "mbed.h"
 #include "TextLCD.h"
 #include "SI570.h"
 #include "QEI.h"
 
 TextLCD lcd(p11, p12, p15, p16, p29, p30); // rs, e, d0-d3
 SI570 si570(p9, p10, 0xAA);
 QEI wheel (p5, p6, NC, 360);
 
 int main() {
     int wp,swp=0;
     float startfreq=7.0;
     float freq;
 
     while (1) {
         wp =  wheel.getPulses();
         freq=startfreq+wp*0.00001;
         if (swp != wp) {
             si570.set_frequency(freq);
             swp = wp;
         }                
         lcd.locate(0,0);
         lcd.printf("%f MHz", si570.get_frequency());
     }
 }

Links

Reference

SI570.h

Committer:
soldeerridder
Date:
2010-11-09
Revision:
0:dae1bf95c49e

File content as of revision 0:dae1bf95c49e:

/* mbed SI570 Library, for driving the SI570 programable VCXO
 * Copyright (c) 2010, Gerrit Polder, PA3BYA
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef MBED_SI570_H
#define MBED_SI570_H

#include "mbed.h"

//these must be floating point number especially 2^28 so that
//there is enough memory to use them in the calculation
#define POW_2_16              65536.0
#define POW_2_24           16777216.0
#define POW_2_28          268435456.0
#define FOUT_START_UP            56.320     //MHz 
#define PPM                    3500         // +/- max ppm from center frequency
#define FDCO_MAX                5670.0         //MHz
#define FDCO_MIN                4850.0         //MHz


/** Interface to the popular SI570 VCXO  */
class SI570 {
public:
    /** Create an instance of the SI570 connected to specified I2C pins, with the specified address.
     *
     * Example:
     * @code
     * #include "mbed.h"
     * #include "TextLCD.h"
     * #include "SI570.h"
     * #include "QEI.h"
     * 
     * TextLCD lcd(p11, p12, p15, p16, p29, p30); // rs, e, d0-d3
     * SI570 si570(p9, p10, 0xAA);
     * QEI wheel (p5, p6, NC, 360);
     *
     * int main() {
     *     int wp,swp=0;
     *     float startfreq=7.0;
     *     float freq;
     *
     *     while (1) {
     *         wp =  wheel.getPulses();
     *         freq=startfreq+wp*0.00001;
     *         if (swp != wp) {
     *             si570.set_frequency(freq);
     *             swp = wp;
     *         }                
     *         lcd.locate(0,0);
     *         lcd.printf("%f MHz", si570.get_frequency());
     *     }
     * }
     * @endcode
     *
     * @param sda The I2C data pin
     * @param scl The I2C clock pin
     * @param address The I2C address for this SI570
     */
    SI570(PinName sda, PinName scl, int address);

    /** Resets the SI570.
     *
     * Resets and reads the startup configuration from the Si570
     */
    void si570reset(void);
    
   /** Read the current frequency.
     *
     * get the SI570 registers an calculate the current frequency
     *
     * @returns the current frequency   
     */
    double get_frequency(void);

   /** Read the current rfreq value.
     *
     * get the SI570 registers an calculate the current rfreq
     *
     * @returns the current rfreq   
     */    
    double get_rfreq(void);
    
    /** Read the current n1.
     *
     * get the SI570 registers an calculate the current n1
     *
     * @returns the current n1   
     */
    int get_n1(void);
    
   /** Read the current hsdiv.
     *
     * get the SI570 registers an calculate the current hsdiv
     *
     * @returns the current hsdiv   
     */
    int get_hsdiv(void); 
    
   /** Set a new frequency.
     *
     * Set the SI570 registers to output frequency
     * When the new frequency is within the 3500 PPM range of the center frequency, hsdiv and n1 needs not to be reprogrammed, resulting in a glitch free transition.
     * For changes larger than 3500 PPM, the process of freezing and unfreezing the DCO will cause the output clock to momentarily stop and start at any arbitrary point during a clock cycle. This process can take up to 10 ms.
     *
     * @param frequency the frequency to set.
     * @returns the current frequency   
     */   
    int set_frequency(double frequency);


private:
    I2C _i2c;
    int _address;
    char cmd[2];
    char buf[6];
    unsigned char n1;
    unsigned char hsdiv;
    unsigned long frac_bits;
    double rfreq;
    double fxtal_device;
    double currentFreq;
    double currentRfreq;

    void get_registers(void);
    int set_frequency_small_change(double currentFrequency);
    int set_frequency_large_change(double currentFrequency);

    unsigned char SetBits(unsigned char original, unsigned char reset_mask, unsigned char new_val);
};


#endif