Library to control Silicon Labs SI570 10 MHZ TO 1.4 GHZ I2C PROGRAMMABLE XO/VCXO.
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
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
- NXP mbed design challenge entry: Si570-Based Universal HAM Radio VFO
- www.agri-vision.nl (home of this project)
- Experiments with software defined radio (SDR) using Softrock, the Si570 VCXO, and a hacked Linux based ADM5120 router to control the Si570, using a web browser.
- Review of Si570 Frequency Synthesizer Kit from K5JHF and K5BCQ
- DG8SAQ - Si570 control with AVR
Reference
SI570.h@0:dae1bf95c49e, 2010-11-09 (annotated)
- Committer:
- soldeerridder
- Date:
- Tue Nov 09 20:56:52 2010 +0000
- Revision:
- 0:dae1bf95c49e
added documentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
soldeerridder | 0:dae1bf95c49e | 1 | /* mbed SI570 Library, for driving the SI570 programable VCXO |
soldeerridder | 0:dae1bf95c49e | 2 | * Copyright (c) 2010, Gerrit Polder, PA3BYA |
soldeerridder | 0:dae1bf95c49e | 3 | * |
soldeerridder | 0:dae1bf95c49e | 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
soldeerridder | 0:dae1bf95c49e | 5 | * of this software and associated documentation files (the "Software"), to deal |
soldeerridder | 0:dae1bf95c49e | 6 | * in the Software without restriction, including without limitation the rights |
soldeerridder | 0:dae1bf95c49e | 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
soldeerridder | 0:dae1bf95c49e | 8 | * copies of the Software, and to permit persons to whom the Software is |
soldeerridder | 0:dae1bf95c49e | 9 | * furnished to do so, subject to the following conditions: |
soldeerridder | 0:dae1bf95c49e | 10 | * |
soldeerridder | 0:dae1bf95c49e | 11 | * The above copyright notice and this permission notice shall be included in |
soldeerridder | 0:dae1bf95c49e | 12 | * all copies or substantial portions of the Software. |
soldeerridder | 0:dae1bf95c49e | 13 | * |
soldeerridder | 0:dae1bf95c49e | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
soldeerridder | 0:dae1bf95c49e | 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
soldeerridder | 0:dae1bf95c49e | 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
soldeerridder | 0:dae1bf95c49e | 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
soldeerridder | 0:dae1bf95c49e | 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
soldeerridder | 0:dae1bf95c49e | 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
soldeerridder | 0:dae1bf95c49e | 20 | * THE SOFTWARE. |
soldeerridder | 0:dae1bf95c49e | 21 | */ |
soldeerridder | 0:dae1bf95c49e | 22 | |
soldeerridder | 0:dae1bf95c49e | 23 | #ifndef MBED_SI570_H |
soldeerridder | 0:dae1bf95c49e | 24 | #define MBED_SI570_H |
soldeerridder | 0:dae1bf95c49e | 25 | |
soldeerridder | 0:dae1bf95c49e | 26 | #include "mbed.h" |
soldeerridder | 0:dae1bf95c49e | 27 | |
soldeerridder | 0:dae1bf95c49e | 28 | //these must be floating point number especially 2^28 so that |
soldeerridder | 0:dae1bf95c49e | 29 | //there is enough memory to use them in the calculation |
soldeerridder | 0:dae1bf95c49e | 30 | #define POW_2_16 65536.0 |
soldeerridder | 0:dae1bf95c49e | 31 | #define POW_2_24 16777216.0 |
soldeerridder | 0:dae1bf95c49e | 32 | #define POW_2_28 268435456.0 |
soldeerridder | 0:dae1bf95c49e | 33 | #define FOUT_START_UP 56.320 //MHz |
soldeerridder | 0:dae1bf95c49e | 34 | #define PPM 3500 // +/- max ppm from center frequency |
soldeerridder | 0:dae1bf95c49e | 35 | #define FDCO_MAX 5670.0 //MHz |
soldeerridder | 0:dae1bf95c49e | 36 | #define FDCO_MIN 4850.0 //MHz |
soldeerridder | 0:dae1bf95c49e | 37 | |
soldeerridder | 0:dae1bf95c49e | 38 | |
soldeerridder | 0:dae1bf95c49e | 39 | /** Interface to the popular SI570 VCXO */ |
soldeerridder | 0:dae1bf95c49e | 40 | class SI570 { |
soldeerridder | 0:dae1bf95c49e | 41 | public: |
soldeerridder | 0:dae1bf95c49e | 42 | /** Create an instance of the SI570 connected to specified I2C pins, with the specified address. |
soldeerridder | 0:dae1bf95c49e | 43 | * |
soldeerridder | 0:dae1bf95c49e | 44 | * Example: |
soldeerridder | 0:dae1bf95c49e | 45 | * @code |
soldeerridder | 0:dae1bf95c49e | 46 | * #include "mbed.h" |
soldeerridder | 0:dae1bf95c49e | 47 | * #include "TextLCD.h" |
soldeerridder | 0:dae1bf95c49e | 48 | * #include "SI570.h" |
soldeerridder | 0:dae1bf95c49e | 49 | * #include "QEI.h" |
soldeerridder | 0:dae1bf95c49e | 50 | * |
soldeerridder | 0:dae1bf95c49e | 51 | * TextLCD lcd(p11, p12, p15, p16, p29, p30); // rs, e, d0-d3 |
soldeerridder | 0:dae1bf95c49e | 52 | * SI570 si570(p9, p10, 0xAA); |
soldeerridder | 0:dae1bf95c49e | 53 | * QEI wheel (p5, p6, NC, 360); |
soldeerridder | 0:dae1bf95c49e | 54 | * |
soldeerridder | 0:dae1bf95c49e | 55 | * int main() { |
soldeerridder | 0:dae1bf95c49e | 56 | * int wp,swp=0; |
soldeerridder | 0:dae1bf95c49e | 57 | * float startfreq=7.0; |
soldeerridder | 0:dae1bf95c49e | 58 | * float freq; |
soldeerridder | 0:dae1bf95c49e | 59 | * |
soldeerridder | 0:dae1bf95c49e | 60 | * while (1) { |
soldeerridder | 0:dae1bf95c49e | 61 | * wp = wheel.getPulses(); |
soldeerridder | 0:dae1bf95c49e | 62 | * freq=startfreq+wp*0.00001; |
soldeerridder | 0:dae1bf95c49e | 63 | * if (swp != wp) { |
soldeerridder | 0:dae1bf95c49e | 64 | * si570.set_frequency(freq); |
soldeerridder | 0:dae1bf95c49e | 65 | * swp = wp; |
soldeerridder | 0:dae1bf95c49e | 66 | * } |
soldeerridder | 0:dae1bf95c49e | 67 | * lcd.locate(0,0); |
soldeerridder | 0:dae1bf95c49e | 68 | * lcd.printf("%f MHz", si570.get_frequency()); |
soldeerridder | 0:dae1bf95c49e | 69 | * } |
soldeerridder | 0:dae1bf95c49e | 70 | * } |
soldeerridder | 0:dae1bf95c49e | 71 | * @endcode |
soldeerridder | 0:dae1bf95c49e | 72 | * |
soldeerridder | 0:dae1bf95c49e | 73 | * @param sda The I2C data pin |
soldeerridder | 0:dae1bf95c49e | 74 | * @param scl The I2C clock pin |
soldeerridder | 0:dae1bf95c49e | 75 | * @param address The I2C address for this SI570 |
soldeerridder | 0:dae1bf95c49e | 76 | */ |
soldeerridder | 0:dae1bf95c49e | 77 | SI570(PinName sda, PinName scl, int address); |
soldeerridder | 0:dae1bf95c49e | 78 | |
soldeerridder | 0:dae1bf95c49e | 79 | /** Resets the SI570. |
soldeerridder | 0:dae1bf95c49e | 80 | * |
soldeerridder | 0:dae1bf95c49e | 81 | * Resets and reads the startup configuration from the Si570 |
soldeerridder | 0:dae1bf95c49e | 82 | */ |
soldeerridder | 0:dae1bf95c49e | 83 | void si570reset(void); |
soldeerridder | 0:dae1bf95c49e | 84 | |
soldeerridder | 0:dae1bf95c49e | 85 | /** Read the current frequency. |
soldeerridder | 0:dae1bf95c49e | 86 | * |
soldeerridder | 0:dae1bf95c49e | 87 | * get the SI570 registers an calculate the current frequency |
soldeerridder | 0:dae1bf95c49e | 88 | * |
soldeerridder | 0:dae1bf95c49e | 89 | * @returns the current frequency |
soldeerridder | 0:dae1bf95c49e | 90 | */ |
soldeerridder | 0:dae1bf95c49e | 91 | double get_frequency(void); |
soldeerridder | 0:dae1bf95c49e | 92 | |
soldeerridder | 0:dae1bf95c49e | 93 | /** Read the current rfreq value. |
soldeerridder | 0:dae1bf95c49e | 94 | * |
soldeerridder | 0:dae1bf95c49e | 95 | * get the SI570 registers an calculate the current rfreq |
soldeerridder | 0:dae1bf95c49e | 96 | * |
soldeerridder | 0:dae1bf95c49e | 97 | * @returns the current rfreq |
soldeerridder | 0:dae1bf95c49e | 98 | */ |
soldeerridder | 0:dae1bf95c49e | 99 | double get_rfreq(void); |
soldeerridder | 0:dae1bf95c49e | 100 | |
soldeerridder | 0:dae1bf95c49e | 101 | /** Read the current n1. |
soldeerridder | 0:dae1bf95c49e | 102 | * |
soldeerridder | 0:dae1bf95c49e | 103 | * get the SI570 registers an calculate the current n1 |
soldeerridder | 0:dae1bf95c49e | 104 | * |
soldeerridder | 0:dae1bf95c49e | 105 | * @returns the current n1 |
soldeerridder | 0:dae1bf95c49e | 106 | */ |
soldeerridder | 0:dae1bf95c49e | 107 | int get_n1(void); |
soldeerridder | 0:dae1bf95c49e | 108 | |
soldeerridder | 0:dae1bf95c49e | 109 | /** Read the current hsdiv. |
soldeerridder | 0:dae1bf95c49e | 110 | * |
soldeerridder | 0:dae1bf95c49e | 111 | * get the SI570 registers an calculate the current hsdiv |
soldeerridder | 0:dae1bf95c49e | 112 | * |
soldeerridder | 0:dae1bf95c49e | 113 | * @returns the current hsdiv |
soldeerridder | 0:dae1bf95c49e | 114 | */ |
soldeerridder | 0:dae1bf95c49e | 115 | int get_hsdiv(void); |
soldeerridder | 0:dae1bf95c49e | 116 | |
soldeerridder | 0:dae1bf95c49e | 117 | /** Set a new frequency. |
soldeerridder | 0:dae1bf95c49e | 118 | * |
soldeerridder | 0:dae1bf95c49e | 119 | * Set the SI570 registers to output frequency |
soldeerridder | 0:dae1bf95c49e | 120 | * 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. |
soldeerridder | 0:dae1bf95c49e | 121 | * 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. |
soldeerridder | 0:dae1bf95c49e | 122 | * |
soldeerridder | 0:dae1bf95c49e | 123 | * @param frequency the frequency to set. |
soldeerridder | 0:dae1bf95c49e | 124 | * @returns the current frequency |
soldeerridder | 0:dae1bf95c49e | 125 | */ |
soldeerridder | 0:dae1bf95c49e | 126 | int set_frequency(double frequency); |
soldeerridder | 0:dae1bf95c49e | 127 | |
soldeerridder | 0:dae1bf95c49e | 128 | |
soldeerridder | 0:dae1bf95c49e | 129 | private: |
soldeerridder | 0:dae1bf95c49e | 130 | I2C _i2c; |
soldeerridder | 0:dae1bf95c49e | 131 | int _address; |
soldeerridder | 0:dae1bf95c49e | 132 | char cmd[2]; |
soldeerridder | 0:dae1bf95c49e | 133 | char buf[6]; |
soldeerridder | 0:dae1bf95c49e | 134 | unsigned char n1; |
soldeerridder | 0:dae1bf95c49e | 135 | unsigned char hsdiv; |
soldeerridder | 0:dae1bf95c49e | 136 | unsigned long frac_bits; |
soldeerridder | 0:dae1bf95c49e | 137 | double rfreq; |
soldeerridder | 0:dae1bf95c49e | 138 | double fxtal_device; |
soldeerridder | 0:dae1bf95c49e | 139 | double currentFreq; |
soldeerridder | 0:dae1bf95c49e | 140 | double currentRfreq; |
soldeerridder | 0:dae1bf95c49e | 141 | |
soldeerridder | 0:dae1bf95c49e | 142 | void get_registers(void); |
soldeerridder | 0:dae1bf95c49e | 143 | int set_frequency_small_change(double currentFrequency); |
soldeerridder | 0:dae1bf95c49e | 144 | int set_frequency_large_change(double currentFrequency); |
soldeerridder | 0:dae1bf95c49e | 145 | |
soldeerridder | 0:dae1bf95c49e | 146 | unsigned char SetBits(unsigned char original, unsigned char reset_mask, unsigned char new_val); |
soldeerridder | 0:dae1bf95c49e | 147 | }; |
soldeerridder | 0:dae1bf95c49e | 148 | |
soldeerridder | 0:dae1bf95c49e | 149 | |
soldeerridder | 0:dae1bf95c49e | 150 | #endif |