Kenji Arai / Si5351A

Dependents:   clockGenerator Check_Si5351A_Clock_generator t2d Thing2Do ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers si5351a.h Source File

si5351a.h

00001 /*
00002  * mbed Library / Silicon Laboratories Inc. Si5351A-B-GT
00003  *      I2C-PROGRAMMABLE ANY-FREQUENCY CMOS CLOCK GENERATOR
00004  *      https://www.silabs.com/products/
00005  *          timing/clock-generator/si535x/pages/Si5351A-B-GM.aspx
00006  *
00007  *  Checked on Nucleo-F411RE & F401RE mbed board
00008  *
00009  *  Original & Reference program:
00010  *  1)
00011  *      https://github.com/adafruit/Adafruit_Si5351_Library
00012  *      see original source (bottom part of si5351a.cpp file)
00013  *         Software License Agreement (BSD License)
00014  *         Copyright (c) 2014, Adafruit Industries  All rights reserved.
00015  *  2)
00016  *      https://gist.github.com/edy555/f1ee7ef44fe4f5c6f7618ac4cbbe66fb
00017  *      made by TT@Hokkaido-san (edy555)
00018  *      http://ttrftech.tumblr.com/
00019  *      http://ttrftech.tumblr.com/post/150247113216/
00020  *          si5351a-configuration-how-to-and-signal-quality
00021  *
00022  *  Modified by Kenji Arai / JH1PJL
00023  *      http://www.page.sannet.ne.jp/kenjia/index.html
00024  *      http://mbed.org/users/kenjiArai/
00025  *
00026  *      Started:  December 24th, 2016
00027  *      Revised:  August   23rd, 2017
00028  *
00029  */
00030 
00031 #ifndef         MBED_SI5351A
00032 #define         MBED_SI5351A
00033 
00034 #if 0           // Range extend mode -> set 1
00035 #define         RANGE_EXTENDED
00036 #endif
00037 #if defined(RANGE_EXTENDED)
00038 #warning "Si5351A PLL range is only 600MHz to 900MHz."
00039 #warning "If you use RANGE_EXTENDED mode, PLL sets 250MHz to 1.3GHz."
00040 #warning "This causes high possibility to make a \
00041              PARMANENT DAMAGE for the chip!!!!!"
00042 #warning "Don't use this mode!!!"
00043 #endif
00044 
00045 ////////////// ADDRESS /////////////////////////////////////////////////////////
00046 //  7bit address = 0b1100000(0x60) -> 8bit = 0b11000000(0xc0)
00047 //      -> Fixed adddress (No other choises)
00048 #define SI5351_I2C_ADDR     (0x60<<1)
00049 
00050 ////////////// REGISTER DEFINITION /////////////////////////////////////////////
00051 #define SI5351_REG_3_OUTPUT_ENABLE_CONTROL  3
00052 #define SI5351_REG_16_CLK0_CONTROL          16
00053 #define SI5351_REG_17_CLK1_CONTROL          17
00054 #define SI5351_REG_18_CLK2_CONTROL          18
00055 #define SI5351_REG_26_PLL_A                 26
00056 #define SI5351_REG_34_PLL_B                 34
00057 #define SI5351_REG_42_MULTISYNTH0           42
00058 #define SI5351_REG_44_MULTISYNTH0_P3        44
00059 #define SI5351_REG_50_MULTISYNTH1           50
00060 #define SI5351_REG_52_MULTISYNTH1_P3        52
00061 #define SI5351_REG_58_MULTISYNTH2           58
00062 #define SI5351_REG_60_MULTISYNTH2_P3        60
00063 #define SI5351_REG_177_PLL_RESET            177
00064 #define SI5351_REG_183_CRYSTAL_LOAD         183
00065 
00066 ////////////// Configration ////////////////////////////////////////////////////
00067 // PLLn
00068 #define SI5351_PLL_A        0
00069 #define SI5351_PLL_B        1
00070 // CLKn
00071 #define SI5351_CLK0         0
00072 #define SI5351_CLK1         1
00073 #define SI5351_CLK2         2
00074 // REG_44_MULTISYNTH0, REG_52_MULTISYNTH1, REG_60_MULTISYNTH2
00075 #define SI5351_R_DIV_1      (0<<4)
00076 #define SI5351_R_DIV_2      (1<<4)
00077 #define SI5351_R_DIV_4      (2<<4)
00078 #define SI5351_R_DIV_8      (3<<4)
00079 #define SI5351_R_DIV_16     (4<<4)
00080 #define SI5351_R_DIV_32     (5<<4)
00081 #define SI5351_R_DIV_64     (6<<4)
00082 #define SI5351_R_DIV_128    (7<<4)
00083 #define SI5351_DIVBY4       (3<<2)
00084 // REG_16_CLK0_CONTROL, REG_17_CLK1_CONTROL, REG_18_CLK2_CONTROL
00085 #define SI5351_CLK_POWERDOWN                (1<<7)
00086 #define SI5351_CLK_INTEGER_MODE             (1<<6)
00087 #define SI5351_CLK_PLL_SELECT_B             (1<<5)
00088 #define SI5351_CLK_INVERT                   (1<<4)
00089 #define SI5351_CLK_INPUT_MASK               (3<<2)
00090 #define SI5351_CLK_INPUT_XTAL               (0<<2)
00091 #define SI5351_CLK_INPUT_CLKIN              (1<<2)
00092 #define SI5351_CLK_INPUT_MULTISYNTH_0_4     (2<<2)
00093 #define SI5351_CLK_INPUT_MULTISYNTH_N       (3<<2)
00094 #define SI5351_CLK_DRIVE_STRENGTH_MASK      (3<<0)
00095 #define SI5351_CLK_DRIVE_STRENGTH_2MA       (0<<0)
00096 #define SI5351_CLK_DRIVE_STRENGTH_4MA       (1<<0)
00097 #define SI5351_CLK_DRIVE_STRENGTH_6MA       (2<<0)
00098 #define SI5351_CLK_DRIVE_STRENGTH_8MA       (3<<0)
00099 // REG_177_PLL_RESET
00100 #define SI5351_PLL_RESET_B          (1<<7)
00101 #define SI5351_PLL_RESET_A          (1<<5)
00102 // REG_183_CRYSTAL_LOAD
00103 #define SI5351_CRYSTAL_LOAD_6PF     (1<<6)
00104 #define SI5351_CRYSTAL_LOAD_8PF     (2<<6)
00105 #define SI5351_CRYSTAL_LOAD_10PF    (3<<6)
00106 
00107 // Frequency
00108 #define FREQ_900MHZ     (900000000UL)
00109 #define FREQ_600MHZ     (600000000UL)
00110 #define FREQ_200MHZ     (200000000UL)
00111 #define FREQ_150MHZ     (150000000UL)
00112 #define FREQ_110MHZ     (110000000UL)
00113 #define FREQ_1MHZ       (1000000UL)
00114 #define FREQ_450KHZ     (450000UL)
00115 #define FREQ_75KHZ      (75000UL)
00116 #define FREQ_20KHZ      (20000UL)
00117 
00118 typedef enum {  // Operating mode
00119   CLK_OUT_NOT_USED  = 0, CLK_OUT_FIXEDPLL, CLK_OUT_FIXEDDIV
00120 } OperatingMode;
00121 
00122 /** Silicon Laboratories Inc. Si5351A
00123  *
00124  * @code
00125  * #include "mbed.h"
00126  * #include "si5351a.h"
00127  *
00128  * I2C i2c(I2C_SDA, I2C_SCL);       // communication with Si5351A
00129  * SI5351 clk(i2c, 25000000UL);     // Base clock = 25MHz
00130  *
00131  * int main() {
00132  *   clk.set_frequency(SI5351_CLK0, 10000000);   // CLK0=10MHz
00133  *   while(true) {
00134  *      wait(1000);
00135  *   }
00136  * }
00137  *
00138  * // ---------  CAUTION & RESTRICTION -----------------------------------------
00139  * // 1) SETTING METHOD
00140  * // 2.6KHz~100MHz: fixed PLL(around 900 or around 600MHz), fractional divider
00141  * // 100~150MHz: fractional PLL 600-900MHz, fixed divider 6
00142  * // 150~200MHz: fractional PLL 600-900MHz, fixed divider 4
00143  * //
00144  * // 2) RESOURCE USAGE
00145  * // PLLA -> only for CLK0 (You can change freqency any time to any value.)
00146  * // PLLB -> use for bothe CLK1 & CLK2
00147  * // If you set a freq. less than 100MHz,
00148  * //    You can change both CLK1 & CLK2 independently.
00149  * // Over 100MHz, you may have a trouble becase need to change PLLB freq.
00150  * //
00151  * // 3) DISCONTINUITY
00152  * // If you use multiple output, you will lose output signal when you change
00153  * //   the output frequency even not specific CLKn during I2C acccess. 
00154  * // --------------------------------------------------------------------------
00155  *
00156  * @endcode
00157  */
00158 
00159 class SI5351A
00160 {
00161 public:
00162     /** Configure data pin
00163       * @param data SDA and SCL pins
00164       * @param External base clock frequency
00165       * @param Internal capacitor value (10pF, 8pF & 6pF/ Default 8pF)
00166       * @param Output current drive strength(Default 2mA) same value CLK0,1,2
00167       */
00168     SI5351A(PinName p_sda, PinName p_scl,
00169             uint32_t base_clk_freq,
00170             uint8_t xtal_cap = SI5351_CRYSTAL_LOAD_8PF,
00171             uint8_t drive_current = SI5351_CLK_DRIVE_STRENGTH_2MA
00172     );
00173 
00174     /** Configure data pin (with other devices on I2C line)
00175       * @param I2C previous definition
00176       * @param External base clock frequency
00177       * @param Internal capacitor value (10pF, 8pF & 6pF/ Default 8pF)
00178       * @param Output current drive strength(Default 2mA) same value CLK0,1,2
00179       */
00180     SI5351A(I2C& p_i2c,
00181             uint32_t base_clk_freq,
00182             uint8_t xtal_cap = SI5351_CRYSTAL_LOAD_8PF,
00183             uint8_t drive_current = SI5351_CLK_DRIVE_STRENGTH_2MA
00184     );
00185 
00186     /** Set frequency
00187       * @param output channel CLK0=0, CLK1=1, CLK2=2
00188       * @param target frequency (unit = Hz)
00189       * @return output frequency
00190       */
00191     uint32_t set_frequency(uint8_t channel, uint32_t freq);
00192 
00193     /** shift frequency after setting frequency (Range: 750KHz to 100MHz )
00194       * @param desired channel CLK0=0, CLK1=1, CLK2=2
00195       * @param sift(+/-) frequency (unit = Hz)
00196       * @return output frequency
00197       */
00198     uint32_t shift_freq(uint8_t channel, int32_t diff);
00199 
00200     /** read frequency
00201       * @param select channel CLK0=0, CLK1=1, CLK2=2
00202       * @return output frequency
00203       */
00204     uint32_t read_freq(uint8_t channel);
00205 
00206     /** compensation frequency
00207       * @param Target freuency (setting value)
00208       * @param Measured freuency (actual value)
00209       * @return none
00210       */
00211     void f_compensation(uint32_t target_f, uint32_t measured_f);
00212 
00213     /** reset Si5351A all registers
00214       * @param none
00215       * @return none
00216       */
00217     void all_reset(void);
00218 
00219     //--------------- Debug interface ------------------------------------------
00220 
00221     /** debug / print registers
00222       * @param none
00223       * @return none (but print on console)
00224       */
00225     void debug_reg_print(void);
00226 
00227     /** debug / check registers and shows current configlation
00228       * @param none
00229       * @return none (but print on console)
00230       */
00231     void debug_current_config(void);
00232 
00233     /** debug / set CLK0: 120.00MHz, CLK1: 12.00MHz, CLK2: 13.56MHz
00234       *          as demonstration purpose for hardware check  (@25MHz Xtal)
00235       * @param none
00236       * @return none
00237       */
00238     void debug_example_clock(void);
00239 
00240 protected:
00241     I2C *_i2c_p;
00242     I2C &_i2c;
00243 
00244     uint32_t gcd(uint32_t x, uint32_t y);
00245     void si5351_read(const uint8_t *buf);
00246     void si5351_write(uint8_t reg, uint8_t dat);
00247     void si5351_bulk_write(const uint8_t *buf, uint8_t len);
00248     double si5351_set_frequency_fixeddiv(
00249                         uint8_t     channel,
00250                         uint32_t    pll,
00251                         uint32_t    freq,
00252                         uint32_t    div);
00253     double si5351_set_frequency_fixedpll(
00254                         uint8_t     channel,
00255                         uint32_t    pll,
00256                         uint32_t    pllfreq,
00257                         uint32_t    freq,
00258                         uint8_t     factor);
00259     double si5351_setupMultisynth(
00260                         uint8_t     output,
00261                         uint8_t     pllSource,
00262                         uint32_t    div,
00263                         uint32_t    num,
00264                         uint32_t    denom,
00265                         uint8_t     factor);
00266     void si5351_setupPLL(
00267                         uint8_t     pll,
00268                         uint8_t     mult,
00269                         uint32_t    num,
00270                         uint32_t    denom);
00271     void si5351_set_PLL_input_condition(uint32_t freq);
00272     void si5351_reset_pll(void);
00273     void si5351_enable_output(void);
00274     void si5351_disable_output(void);
00275     void si5351_disable_all_output(void);
00276     void si5351_init(void);
00277     void put_dump(const uint8_t *buff, uint8_t ofs, uint8_t cnt);
00278     void prnt_reg(uint8_t offset, uint8_t n);
00279     void reg_16_17_18(uint8_t dt);
00280     void reg_pll_8bytes(uint8_t *buf);
00281     void reg_mltisyc_8bytes(uint8_t *buf);
00282 
00283 private:
00284     uint8_t     addr;           // Chip I2C address
00285     uint32_t    base_freq;      // Xtal oscilation freq.
00286     uint8_t     x_cap;          // Internal capacitor value
00287     uint8_t     drv_current;    // Output current drive strength
00288     uint8_t     pll_n;          // PLL div number (PLL_N)
00289     uint32_t    pll_freq;       // XTAL * pll_n
00290     uint32_t    plla_freq;      // Calculated freq of PLLA
00291     uint32_t    pllb_freq;      // Calculated freq of PLLB
00292     double      compensation;   // Compensation data
00293     // Setting frequency
00294     double      clk0_freq;
00295     double      clk1_freq;
00296     double      clk2_freq;
00297     // operating mode
00298     uint8_t     clk0_state;
00299     uint8_t     clk1_state;
00300     uint8_t     clk2_state;
00301 
00302 };   // class SI5351A
00303 
00304 #endif  // MBED_SI5351A