Silicon Laboratories Inc. Si5351A-B-GT I2C-PROGRAMMABLE ANY-FREQUENCY CMOS CLOCK GENERATOR

Dependents:   clockGenerator Check_Si5351A_Clock_generator t2d Thing2Do ... more

Test program:
/users/kenjiArai/code/Check_Si5351A_Clock_generator/

Committer:
kenjiArai
Date:
Sun Jan 01 01:21:34 2017 +0000
Revision:
0:47b9bfa03730
Child:
1:a2309757c450
Si5351A Clock Generator Library (Silicon Laboratories)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:47b9bfa03730 1 /*
kenjiArai 0:47b9bfa03730 2 * mbed Library / Silicon Laboratories Inc. Si5351A-B-GT
kenjiArai 0:47b9bfa03730 3 * I2C-PROGRAMMABLE ANY-FREQUENCY CMOS CLOCK GENERATOR
kenjiArai 0:47b9bfa03730 4 * https://www.silabs.com/products/
kenjiArai 0:47b9bfa03730 5 * timing/clock-generator/si535x/pages/Si5351A-B-GM.aspx
kenjiArai 0:47b9bfa03730 6 *
kenjiArai 0:47b9bfa03730 7 * Checked on Nucleo-F411RE & F401RE mbed board
kenjiArai 0:47b9bfa03730 8 *
kenjiArai 0:47b9bfa03730 9 * Original & Reference program:
kenjiArai 0:47b9bfa03730 10 * 1)
kenjiArai 0:47b9bfa03730 11 * https://github.com/adafruit/Adafruit_Si5351_Library
kenjiArai 0:47b9bfa03730 12 * see original source (bottom part of si5351a.cpp file)
kenjiArai 0:47b9bfa03730 13 * Software License Agreement (BSD License)
kenjiArai 0:47b9bfa03730 14 * Copyright (c) 2014, Adafruit Industries All rights reserved.
kenjiArai 0:47b9bfa03730 15 * 2)
kenjiArai 0:47b9bfa03730 16 * https://gist.github.com/edy555/f1ee7ef44fe4f5c6f7618ac4cbbe66fb
kenjiArai 0:47b9bfa03730 17 * made by TT@Hokkaido-san (edy555)
kenjiArai 0:47b9bfa03730 18 * http://ttrftech.tumblr.com/
kenjiArai 0:47b9bfa03730 19 * http://ttrftech.tumblr.com/post/150247113216/
kenjiArai 0:47b9bfa03730 20 * si5351a-configuration-how-to-and-signal-quality
kenjiArai 0:47b9bfa03730 21 *
kenjiArai 0:47b9bfa03730 22 * Modified by Kenji Arai / JH1PJL
kenjiArai 0:47b9bfa03730 23 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:47b9bfa03730 24 * http://mbed.org/users/kenjiArai/
kenjiArai 0:47b9bfa03730 25 *
kenjiArai 0:47b9bfa03730 26 * Started: December 24th, 2016
kenjiArai 0:47b9bfa03730 27 * Revised: January 1st, 2017
kenjiArai 0:47b9bfa03730 28 *
kenjiArai 0:47b9bfa03730 29 */
kenjiArai 0:47b9bfa03730 30
kenjiArai 0:47b9bfa03730 31 #include "mbed.h"
kenjiArai 0:47b9bfa03730 32 #include "si5351a.h"
kenjiArai 0:47b9bfa03730 33
kenjiArai 0:47b9bfa03730 34 #if 0 // Debug mode = 1
kenjiArai 0:47b9bfa03730 35 #define DEBUG
kenjiArai 0:47b9bfa03730 36 #endif
kenjiArai 0:47b9bfa03730 37
kenjiArai 0:47b9bfa03730 38 #if defined(DEBUG)
kenjiArai 0:47b9bfa03730 39 #define DBG(...) printf(__VA_ARGS__)
kenjiArai 0:47b9bfa03730 40 #else
kenjiArai 0:47b9bfa03730 41 #define DBG(...) {;}
kenjiArai 0:47b9bfa03730 42 #endif
kenjiArai 0:47b9bfa03730 43
kenjiArai 0:47b9bfa03730 44 #define PLL_N 32
kenjiArai 0:47b9bfa03730 45
kenjiArai 0:47b9bfa03730 46 SI5351A::SI5351A (PinName p_sda, PinName p_scl,
kenjiArai 0:47b9bfa03730 47 uint32_t base_clk_freq,
kenjiArai 0:47b9bfa03730 48 uint8_t xtal_cap,
kenjiArai 0:47b9bfa03730 49 uint8_t drive_current
kenjiArai 0:47b9bfa03730 50 )
kenjiArai 0:47b9bfa03730 51 : _i2c(p_sda, p_scl)
kenjiArai 0:47b9bfa03730 52 {
kenjiArai 0:47b9bfa03730 53 base_freq = base_clk_freq;
kenjiArai 0:47b9bfa03730 54 x_cap = xtal_cap;
kenjiArai 0:47b9bfa03730 55 drv_current = drive_current;
kenjiArai 0:47b9bfa03730 56 si5351_init();
kenjiArai 0:47b9bfa03730 57 }
kenjiArai 0:47b9bfa03730 58
kenjiArai 0:47b9bfa03730 59 SI5351A::SI5351A (I2C& p_i2c,
kenjiArai 0:47b9bfa03730 60 uint32_t base_clk_freq,
kenjiArai 0:47b9bfa03730 61 uint8_t xtal_cap,
kenjiArai 0:47b9bfa03730 62 uint8_t drive_current
kenjiArai 0:47b9bfa03730 63 )
kenjiArai 0:47b9bfa03730 64 : _i2c(p_i2c)
kenjiArai 0:47b9bfa03730 65 {
kenjiArai 0:47b9bfa03730 66 base_freq = base_clk_freq;
kenjiArai 0:47b9bfa03730 67 x_cap = xtal_cap;
kenjiArai 0:47b9bfa03730 68 drv_current = drive_current;
kenjiArai 0:47b9bfa03730 69 si5351_init();
kenjiArai 0:47b9bfa03730 70 }
kenjiArai 0:47b9bfa03730 71
kenjiArai 0:47b9bfa03730 72 /*
kenjiArai 0:47b9bfa03730 73 * 1~100MHz fixed PLL (XTAL * PLL_N)MHz, fractional divider
kenjiArai 0:47b9bfa03730 74 * 100~150MHz fractional PLL 600-900MHz, fixed divider 6
kenjiArai 0:47b9bfa03730 75 * 150~200MHz fractional PLL 600-900MHz, fixed divider 4
kenjiArai 0:47b9bfa03730 76 */
kenjiArai 0:47b9bfa03730 77 uint32_t SI5351A::set_frequency(uint8_t channel, uint32_t freq)
kenjiArai 0:47b9bfa03730 78 {
kenjiArai 0:47b9bfa03730 79 uint8_t pll;
kenjiArai 0:47b9bfa03730 80 double f;
kenjiArai 0:47b9bfa03730 81 uint8_t state;
kenjiArai 0:47b9bfa03730 82 if (channel == SI5351_CLK0){
kenjiArai 0:47b9bfa03730 83 pll = SI5351_PLL_A;
kenjiArai 0:47b9bfa03730 84 } else { // SI5351_CLK1 & SI5351_CLK2
kenjiArai 0:47b9bfa03730 85 pll = SI5351_PLL_B;
kenjiArai 0:47b9bfa03730 86 }
kenjiArai 0:47b9bfa03730 87 si5351_disable_output();
kenjiArai 0:47b9bfa03730 88 if (freq <= FREQ_100MHZ){
kenjiArai 0:47b9bfa03730 89 if((channel == SI5351_CLK1) && (clk2_state == CLK_OUT_FIXEDDIV)){
kenjiArai 0:47b9bfa03730 90 DBG("DBG: Error CLK2 uses as over 100MHz!!\r\n");
kenjiArai 0:47b9bfa03730 91 return 0;
kenjiArai 0:47b9bfa03730 92 } else if((channel == SI5351_CLK2) && (clk1_state == CLK_OUT_FIXEDDIV)){
kenjiArai 0:47b9bfa03730 93 DBG("DBG: Error CLK1 uses as over 100MHz!!\r\n");
kenjiArai 0:47b9bfa03730 94 return 0;
kenjiArai 0:47b9bfa03730 95 }
kenjiArai 0:47b9bfa03730 96 DBG("DBG: Passed condition\r\n");
kenjiArai 0:47b9bfa03730 97 if (freq > FREQ_450KHZ){ // over 450KHz
kenjiArai 0:47b9bfa03730 98 si5351_setupPLL(pll, PLL_N, 0, 1);
kenjiArai 0:47b9bfa03730 99 f = si5351_set_frequency_fixedpll(channel, pll, pll_freq, freq, 0);
kenjiArai 0:47b9bfa03730 100 } else if (freq > FREQ_75KHZ){
kenjiArai 0:47b9bfa03730 101 si5351_setupPLL(pll, PLL_N, 0, 1);
kenjiArai 0:47b9bfa03730 102 f = si5351_set_frequency_fixedpll(
kenjiArai 0:47b9bfa03730 103 channel, pll, pll_freq, freq * 8, SI5351_R_DIV_8);
kenjiArai 0:47b9bfa03730 104 f /= 8.0f;
kenjiArai 0:47b9bfa03730 105 } else if (freq > FREQ_20KHZ){
kenjiArai 0:47b9bfa03730 106 si5351_setupPLL(pll, PLL_N, 0, 1);
kenjiArai 0:47b9bfa03730 107 f = si5351_set_frequency_fixedpll(
kenjiArai 0:47b9bfa03730 108 channel, pll, pll_freq, freq * 32, SI5351_R_DIV_32);
kenjiArai 0:47b9bfa03730 109 f /= 32.0f;
kenjiArai 0:47b9bfa03730 110 } else {
kenjiArai 0:47b9bfa03730 111 si5351_setupPLL(pll, PLL_N, 0, 1);
kenjiArai 0:47b9bfa03730 112 f = si5351_set_frequency_fixedpll(
kenjiArai 0:47b9bfa03730 113 channel, pll, pll_freq, freq * 128, SI5351_R_DIV_128);
kenjiArai 0:47b9bfa03730 114 f /= 128.0f;
kenjiArai 0:47b9bfa03730 115 }
kenjiArai 0:47b9bfa03730 116 state = CLK_OUT_FIXEDPLL;
kenjiArai 0:47b9bfa03730 117 } else {
kenjiArai 0:47b9bfa03730 118 DBG("DBG: Set over 100MHz clock\r\n");
kenjiArai 0:47b9bfa03730 119 if((channel == SI5351_CLK1) && (clk2_state == CLK_OUT_FIXEDPLL)){
kenjiArai 0:47b9bfa03730 120 DBG("DBG: Error CLK2 uses as under 100MHz!!\r\n");
kenjiArai 0:47b9bfa03730 121 return 0;
kenjiArai 0:47b9bfa03730 122 } else if((channel == SI5351_CLK2) && (clk1_state == CLK_OUT_FIXEDPLL)){
kenjiArai 0:47b9bfa03730 123 DBG("DBG: Error CLK1 uses as under 100MHz!!\r\n");
kenjiArai 0:47b9bfa03730 124 return 0;
kenjiArai 0:47b9bfa03730 125 }
kenjiArai 0:47b9bfa03730 126 DBG("DBG: Passed condition\r\n");
kenjiArai 0:47b9bfa03730 127 if (freq < FREQ_150MHZ) {
kenjiArai 0:47b9bfa03730 128 DBG("DBG: Set 100MHz to 150MHz clock\r\n");
kenjiArai 0:47b9bfa03730 129 f = si5351_set_frequency_fixeddiv(channel, pll, freq, 6);
kenjiArai 0:47b9bfa03730 130 } else {
kenjiArai 0:47b9bfa03730 131 DBG("DBG: Set over 150MHz clock\r\n");
kenjiArai 0:47b9bfa03730 132 f = si5351_set_frequency_fixeddiv(channel, pll, freq, 4);
kenjiArai 0:47b9bfa03730 133 }
kenjiArai 0:47b9bfa03730 134 state = CLK_OUT_FIXEDDIV;
kenjiArai 0:47b9bfa03730 135 }
kenjiArai 0:47b9bfa03730 136 si5351_enable_output();
kenjiArai 0:47b9bfa03730 137 if (channel == SI5351_CLK0){
kenjiArai 0:47b9bfa03730 138 clk0_state = state;
kenjiArai 0:47b9bfa03730 139 clk0_freq = f;
kenjiArai 0:47b9bfa03730 140 } else if (channel == SI5351_CLK1){
kenjiArai 0:47b9bfa03730 141 clk1_state = state;
kenjiArai 0:47b9bfa03730 142 clk1_freq = f;
kenjiArai 0:47b9bfa03730 143 } else {
kenjiArai 0:47b9bfa03730 144 clk2_state = state;
kenjiArai 0:47b9bfa03730 145 clk2_freq = f;
kenjiArai 0:47b9bfa03730 146 }
kenjiArai 0:47b9bfa03730 147 DBG("DBG: freq./ Target=%u,Set=%0.1f,diff=%.0f\r\n",
kenjiArai 0:47b9bfa03730 148 freq, f, (double)freq - f);
kenjiArai 0:47b9bfa03730 149 return (uint32_t)f;
kenjiArai 0:47b9bfa03730 150 }
kenjiArai 0:47b9bfa03730 151
kenjiArai 0:47b9bfa03730 152 uint32_t SI5351A::shift_freq(uint8_t channel, int32_t diff)
kenjiArai 0:47b9bfa03730 153 {
kenjiArai 0:47b9bfa03730 154 double f;
kenjiArai 0:47b9bfa03730 155 uint32_t f_err;
kenjiArai 0:47b9bfa03730 156 // Check current status
kenjiArai 0:47b9bfa03730 157 if (channel == SI5351_CLK0){
kenjiArai 0:47b9bfa03730 158 f = clk0_freq;
kenjiArai 0:47b9bfa03730 159 f_err = (uint32_t)f;
kenjiArai 0:47b9bfa03730 160 if ((clk0_state == CLK_OUT_NOT_USED)
kenjiArai 0:47b9bfa03730 161 || (clk0_state == CLK_OUT_FIXEDDIV)){
kenjiArai 0:47b9bfa03730 162 DBG("DBG: error over 100MHz\r\n");
kenjiArai 0:47b9bfa03730 163 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 164 }
kenjiArai 0:47b9bfa03730 165 } else if (channel == SI5351_CLK1){
kenjiArai 0:47b9bfa03730 166 f = clk1_freq;
kenjiArai 0:47b9bfa03730 167 f_err = (uint32_t)f;
kenjiArai 0:47b9bfa03730 168 if ((clk1_state == CLK_OUT_NOT_USED)
kenjiArai 0:47b9bfa03730 169 || (clk1_state == CLK_OUT_FIXEDDIV)){
kenjiArai 0:47b9bfa03730 170 DBG("DBG: error over 100MHz\r\n");
kenjiArai 0:47b9bfa03730 171 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 172 }
kenjiArai 0:47b9bfa03730 173 } else if (channel == SI5351_CLK2){
kenjiArai 0:47b9bfa03730 174 f = clk2_freq;
kenjiArai 0:47b9bfa03730 175 f_err = (uint32_t)f;
kenjiArai 0:47b9bfa03730 176 if ((clk2_state == CLK_OUT_NOT_USED)
kenjiArai 0:47b9bfa03730 177 || (clk2_state == CLK_OUT_FIXEDDIV)){
kenjiArai 0:47b9bfa03730 178 DBG("DBG: error over 100MHz\r\n");
kenjiArai 0:47b9bfa03730 179 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 180 }
kenjiArai 0:47b9bfa03730 181 } else {
kenjiArai 0:47b9bfa03730 182 return 0;
kenjiArai 0:47b9bfa03730 183 }
kenjiArai 0:47b9bfa03730 184 // set new frequency
kenjiArai 0:47b9bfa03730 185 double f_tatget = f + (double)diff;
kenjiArai 0:47b9bfa03730 186 uint32_t freq = (uint32_t)f_tatget;
kenjiArai 0:47b9bfa03730 187 DBG("DBG: Target F=%u\r\n", freq);
kenjiArai 0:47b9bfa03730 188 // only range between 1MHz to 100MHz
kenjiArai 0:47b9bfa03730 189 if ((freq > FREQ_100MHZ) || (freq < FREQ_450KHZ)){// between 450KHz-100MHz
kenjiArai 0:47b9bfa03730 190 DBG("DBG: Out of range\r\n");
kenjiArai 0:47b9bfa03730 191 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 192 }
kenjiArai 0:47b9bfa03730 193 uint32_t div = (floor)((double)pll_freq / (double)freq);
kenjiArai 0:47b9bfa03730 194 uint32_t num = pll_freq - freq * div;
kenjiArai 0:47b9bfa03730 195 uint32_t denom = freq;
kenjiArai 0:47b9bfa03730 196 uint32_t k = gcd(num, denom);
kenjiArai 0:47b9bfa03730 197 num /= k;
kenjiArai 0:47b9bfa03730 198 denom /= k;
kenjiArai 0:47b9bfa03730 199 while (denom >= (1<<20)) {
kenjiArai 0:47b9bfa03730 200 num >>= 1;
kenjiArai 0:47b9bfa03730 201 denom >>= 1;
kenjiArai 0:47b9bfa03730 202 }
kenjiArai 0:47b9bfa03730 203 if (denom == 0){ // Avoid divide by zero
kenjiArai 0:47b9bfa03730 204 DBG("DBG: error demon=0\r\n");
kenjiArai 0:47b9bfa03730 205 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 206 }
kenjiArai 0:47b9bfa03730 207 if (num >=0x100000){ // 20-bit limit
kenjiArai 0:47b9bfa03730 208 DBG("DBG: error num over 20bit\r\n");
kenjiArai 0:47b9bfa03730 209 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 210 }
kenjiArai 0:47b9bfa03730 211 if (denom >=0x100000){ // 20-bit limit
kenjiArai 0:47b9bfa03730 212 DBG("DBG: error denom over 20bit\r\n");
kenjiArai 0:47b9bfa03730 213 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 214 }
kenjiArai 0:47b9bfa03730 215 uint32_t P1, P2, P3;
kenjiArai 0:47b9bfa03730 216 uint32_t multisynth_vale;
kenjiArai 0:47b9bfa03730 217 double multisynth_double;
kenjiArai 0:47b9bfa03730 218 const uint8_t msreg_base[] = {
kenjiArai 0:47b9bfa03730 219 SI5351_REG_42_MULTISYNTH0,
kenjiArai 0:47b9bfa03730 220 SI5351_REG_50_MULTISYNTH1,
kenjiArai 0:47b9bfa03730 221 SI5351_REG_58_MULTISYNTH2,
kenjiArai 0:47b9bfa03730 222 };
kenjiArai 0:47b9bfa03730 223 uint8_t baseaddr = msreg_base[channel];
kenjiArai 0:47b9bfa03730 224 // Fractional mode
kenjiArai 0:47b9bfa03730 225 multisynth_vale = (floor)((double)num /(double)denom);
kenjiArai 0:47b9bfa03730 226 P1 = 128 * div + 128 * multisynth_vale - 512;
kenjiArai 0:47b9bfa03730 227 P2 = 128 * num - denom * 128 * multisynth_vale;
kenjiArai 0:47b9bfa03730 228 P3 = denom;
kenjiArai 0:47b9bfa03730 229 multisynth_double = div + (double)num /(double)denom;
kenjiArai 0:47b9bfa03730 230 // a + b/c between 6..1800
kenjiArai 0:47b9bfa03730 231 if ((multisynth_double < 6.0f) || (multisynth_double > 1800.0f)){
kenjiArai 0:47b9bfa03730 232 DBG("DBG: error multisynth less 6 or over 1800\r\n");
kenjiArai 0:47b9bfa03730 233 return f_err; // return current frequency
kenjiArai 0:47b9bfa03730 234 }
kenjiArai 0:47b9bfa03730 235 DBG("DBG: CLK%u: PLL=%u,div=%u,num=%u,denom=%u\r\n",
kenjiArai 0:47b9bfa03730 236 channel, pll_freq, div, num, denom);
kenjiArai 0:47b9bfa03730 237 // Set the MSx config registers
kenjiArai 0:47b9bfa03730 238 si5351_write(baseaddr, (P3 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 239 si5351_write(baseaddr+1, (P3 & 0x000000ff));
kenjiArai 0:47b9bfa03730 240 si5351_write(baseaddr+2, (P1 & 0x00030000) >> 16);
kenjiArai 0:47b9bfa03730 241 si5351_write(baseaddr+3, (P1 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 242 si5351_write(baseaddr+4, (P1 & 0x000000ff));
kenjiArai 0:47b9bfa03730 243 si5351_write(baseaddr+5,
kenjiArai 0:47b9bfa03730 244 ((P3 & 0x000f0000) >> 12) | ((P2 & 0x000f0000) >> 16));
kenjiArai 0:47b9bfa03730 245 si5351_write(baseaddr+6, (P2 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 246 si5351_write(baseaddr+7, (P2 & 0x000000ff));
kenjiArai 0:47b9bfa03730 247 f = (double)pll_freq / multisynth_double;
kenjiArai 0:47b9bfa03730 248 if (channel == SI5351_CLK0){
kenjiArai 0:47b9bfa03730 249 clk0_freq = f;
kenjiArai 0:47b9bfa03730 250 } else if (channel == SI5351_CLK1){
kenjiArai 0:47b9bfa03730 251 clk1_freq = f;
kenjiArai 0:47b9bfa03730 252 } else { // SI5351_CLK2
kenjiArai 0:47b9bfa03730 253 clk2_freq = f;
kenjiArai 0:47b9bfa03730 254 }
kenjiArai 0:47b9bfa03730 255 return (uint32_t)f;
kenjiArai 0:47b9bfa03730 256 }
kenjiArai 0:47b9bfa03730 257
kenjiArai 0:47b9bfa03730 258 uint32_t SI5351A::read_freq(uint8_t channel)
kenjiArai 0:47b9bfa03730 259 {
kenjiArai 0:47b9bfa03730 260 if (channel == SI5351_CLK0){
kenjiArai 0:47b9bfa03730 261 return (uint32_t)clk0_freq;
kenjiArai 0:47b9bfa03730 262 } else if (channel == SI5351_CLK1){
kenjiArai 0:47b9bfa03730 263 return (uint32_t)clk1_freq;
kenjiArai 0:47b9bfa03730 264 } else { // SI5351_CLK2
kenjiArai 0:47b9bfa03730 265 return (uint32_t)clk2_freq;
kenjiArai 0:47b9bfa03730 266 }
kenjiArai 0:47b9bfa03730 267 }
kenjiArai 0:47b9bfa03730 268
kenjiArai 0:47b9bfa03730 269 static const uint8_t reg_table[] = {
kenjiArai 0:47b9bfa03730 270 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
kenjiArai 0:47b9bfa03730 271 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
kenjiArai 0:47b9bfa03730 272 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
kenjiArai 0:47b9bfa03730 273 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
kenjiArai 0:47b9bfa03730 274 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
kenjiArai 0:47b9bfa03730 275 165, 166, 167, 168, 169, 170
kenjiArai 0:47b9bfa03730 276 };
kenjiArai 0:47b9bfa03730 277
kenjiArai 0:47b9bfa03730 278 void SI5351A::all_reset(void)
kenjiArai 0:47b9bfa03730 279 {
kenjiArai 0:47b9bfa03730 280 plla_freq = 0;
kenjiArai 0:47b9bfa03730 281 pllb_freq = 0;
kenjiArai 0:47b9bfa03730 282 clk0_freq = 0;
kenjiArai 0:47b9bfa03730 283 clk1_freq = 0;
kenjiArai 0:47b9bfa03730 284 clk2_freq = 0;
kenjiArai 0:47b9bfa03730 285 clk0_state = 0;
kenjiArai 0:47b9bfa03730 286 clk1_state = 0;
kenjiArai 0:47b9bfa03730 287 clk2_state = 0;
kenjiArai 0:47b9bfa03730 288 /* Disable all outputs setting CLKx_DIS high */
kenjiArai 0:47b9bfa03730 289 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
kenjiArai 0:47b9bfa03730 290 for (uint16_t i = 0; i < sizeof(reg_table); i++){
kenjiArai 0:47b9bfa03730 291 si5351_write(reg_table[i], 0);
kenjiArai 0:47b9bfa03730 292 }
kenjiArai 0:47b9bfa03730 293 /* Apply soft reset */
kenjiArai 0:47b9bfa03730 294 si5351_write(SI5351_REG_177_PLL_RESET, 0xac);
kenjiArai 0:47b9bfa03730 295 }
kenjiArai 0:47b9bfa03730 296
kenjiArai 0:47b9bfa03730 297 ////////////// Configration for Initialization /////////////////////////////////
kenjiArai 0:47b9bfa03730 298 // length, register addr, data, ...
kenjiArai 0:47b9bfa03730 299 const uint8_t si5351_configs[] = {
kenjiArai 0:47b9bfa03730 300 // 0xff = all outputs are disabled.
kenjiArai 0:47b9bfa03730 301 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff,
kenjiArai 0:47b9bfa03730 302 // CLK0,CLK1(REG_17),CLK2(REG_18) -> Power down mode
kenjiArai 0:47b9bfa03730 303 4, SI5351_REG_16_CLK0_CONTROL,
kenjiArai 0:47b9bfa03730 304 SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN,
kenjiArai 0:47b9bfa03730 305 // Dummy data for PLL
kenjiArai 0:47b9bfa03730 306 9, SI5351_REG_26_PLL_A, /*P3*/0, 0, /*P1*/0, 0, 0, /*P3/P2*/0, 0, 0,
kenjiArai 0:47b9bfa03730 307 // RESET PLL (Both PLLA & PLLB)
kenjiArai 0:47b9bfa03730 308 2, SI5351_REG_177_PLL_RESET, (SI5351_PLL_RESET_A | SI5351_PLL_RESET_B),
kenjiArai 0:47b9bfa03730 309 // Dummy data for MULTISYNTH
kenjiArai 0:47b9bfa03730 310 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 0, /*P1*/0, 0, 0, /*P2|P3*/0, 0, 0,
kenjiArai 0:47b9bfa03730 311 // 0 = enable / CLK0,1,2 (bit 0,1,2 = 0)
kenjiArai 0:47b9bfa03730 312 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xf8,
kenjiArai 0:47b9bfa03730 313 0 // sentinel
kenjiArai 0:47b9bfa03730 314 };
kenjiArai 0:47b9bfa03730 315
kenjiArai 0:47b9bfa03730 316 void SI5351A::si5351_init(void)
kenjiArai 0:47b9bfa03730 317 {
kenjiArai 0:47b9bfa03730 318 addr = SI5351_I2C_ADDR;
kenjiArai 0:47b9bfa03730 319 pll_freq = base_freq * PLL_N;
kenjiArai 0:47b9bfa03730 320 clk0_freq = 0;
kenjiArai 0:47b9bfa03730 321 clk1_freq = 0;
kenjiArai 0:47b9bfa03730 322 clk2_freq = 0;
kenjiArai 0:47b9bfa03730 323 clk0_state = CLK_OUT_NOT_USED;
kenjiArai 0:47b9bfa03730 324 clk1_state = CLK_OUT_NOT_USED;
kenjiArai 0:47b9bfa03730 325 clk2_state = CLK_OUT_NOT_USED;
kenjiArai 0:47b9bfa03730 326 si5351_reset_pll();
kenjiArai 0:47b9bfa03730 327 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
kenjiArai 0:47b9bfa03730 328 // Total load capacitance less than or equal to 12 pF (See AN551)
kenjiArai 0:47b9bfa03730 329 si5351_write(SI5351_REG_183_CRYSTAL_LOAD, x_cap);
kenjiArai 0:47b9bfa03730 330 const uint8_t *p = si5351_configs;
kenjiArai 0:47b9bfa03730 331 while (*p) {
kenjiArai 0:47b9bfa03730 332 uint8_t len = *p++;
kenjiArai 0:47b9bfa03730 333 si5351_bulk_write(p, len);
kenjiArai 0:47b9bfa03730 334 p += len;
kenjiArai 0:47b9bfa03730 335 }
kenjiArai 0:47b9bfa03730 336 // CONTROL for CLK0,1,2
kenjiArai 0:47b9bfa03730 337 uint8_t dt = (drv_current | \
kenjiArai 0:47b9bfa03730 338 SI5351_CLK_INPUT_MULTISYNTH_N | \
kenjiArai 0:47b9bfa03730 339 SI5351_CLK_INTEGER_MODE);
kenjiArai 0:47b9bfa03730 340 si5351_write(SI5351_REG_16_CLK0_CONTROL, dt);
kenjiArai 0:47b9bfa03730 341 si5351_write(SI5351_REG_17_CLK1_CONTROL, dt);
kenjiArai 0:47b9bfa03730 342 si5351_write(SI5351_REG_18_CLK2_CONTROL, dt);
kenjiArai 0:47b9bfa03730 343 si5351_disable_all_output(); // Disable all output
kenjiArai 0:47b9bfa03730 344 }
kenjiArai 0:47b9bfa03730 345
kenjiArai 0:47b9bfa03730 346 void SI5351A::si5351_disable_output(void)
kenjiArai 0:47b9bfa03730 347 {
kenjiArai 0:47b9bfa03730 348 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
kenjiArai 0:47b9bfa03730 349 }
kenjiArai 0:47b9bfa03730 350
kenjiArai 0:47b9bfa03730 351 void SI5351A::si5351_disable_all_output(void)
kenjiArai 0:47b9bfa03730 352 {
kenjiArai 0:47b9bfa03730 353 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
kenjiArai 0:47b9bfa03730 354 si5351_write(SI5351_REG_16_CLK0_CONTROL, 0x80);
kenjiArai 0:47b9bfa03730 355 si5351_write(SI5351_REG_17_CLK1_CONTROL, 0x80);
kenjiArai 0:47b9bfa03730 356 si5351_write(SI5351_REG_18_CLK2_CONTROL, 0x80);
kenjiArai 0:47b9bfa03730 357 }
kenjiArai 0:47b9bfa03730 358
kenjiArai 0:47b9bfa03730 359 void SI5351A::si5351_enable_output(void)
kenjiArai 0:47b9bfa03730 360 {
kenjiArai 0:47b9bfa03730 361 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xf8);
kenjiArai 0:47b9bfa03730 362 }
kenjiArai 0:47b9bfa03730 363
kenjiArai 0:47b9bfa03730 364 void SI5351A::si5351_reset_pll(void)
kenjiArai 0:47b9bfa03730 365 {
kenjiArai 0:47b9bfa03730 366 si5351_write(SI5351_REG_177_PLL_RESET, 0xa0);
kenjiArai 0:47b9bfa03730 367 }
kenjiArai 0:47b9bfa03730 368
kenjiArai 0:47b9bfa03730 369 /**************************************************************************/
kenjiArai 0:47b9bfa03730 370 /*!
kenjiArai 0:47b9bfa03730 371 @brief Sets the multiplier for the specified PLL
kenjiArai 0:47b9bfa03730 372
kenjiArai 0:47b9bfa03730 373 @param pll The PLL to configure, which must be one of the following:
kenjiArai 0:47b9bfa03730 374 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 375 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 376 @param mult The PLL integer multiplier (must be between 15 and 90)
kenjiArai 0:47b9bfa03730 377 @param num The 20-bit numerator for fractional output (0..1,048,575).
kenjiArai 0:47b9bfa03730 378 Set this to '0' for integer output.
kenjiArai 0:47b9bfa03730 379 @param denom The 20-bit denominator for fractional output (1..1,048,575).
kenjiArai 0:47b9bfa03730 380 Set this to '1' or higher to avoid divider by zero errors.
kenjiArai 0:47b9bfa03730 381 @section PLL Configuration
kenjiArai 0:47b9bfa03730 382 fVCO is the PLL output, and must be between 600..900MHz, where:
kenjiArai 0:47b9bfa03730 383 fVCO = fXTAL * (a+(b/c))
kenjiArai 0:47b9bfa03730 384 fXTAL = the crystal input frequency
kenjiArai 0:47b9bfa03730 385 a = an integer between 15 and 90
kenjiArai 0:47b9bfa03730 386 b = the fractional numerator (0..1,048,575)
kenjiArai 0:47b9bfa03730 387 c = the fractional denominator (1..1,048,575)
kenjiArai 0:47b9bfa03730 388 NOTE: Try to use integers whenever possible to avoid clock jitter
kenjiArai 0:47b9bfa03730 389 (only use the a part, setting b to '0' and c to '1').
kenjiArai 0:47b9bfa03730 390 See: http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf
kenjiArai 0:47b9bfa03730 391 */
kenjiArai 0:47b9bfa03730 392 /**************************************************************************/
kenjiArai 0:47b9bfa03730 393 void SI5351A::si5351_setupPLL(
kenjiArai 0:47b9bfa03730 394 uint8_t pll,
kenjiArai 0:47b9bfa03730 395 uint8_t mult,
kenjiArai 0:47b9bfa03730 396 uint32_t num,
kenjiArai 0:47b9bfa03730 397 uint32_t denom)
kenjiArai 0:47b9bfa03730 398 {
kenjiArai 0:47b9bfa03730 399 uint32_t P1; /* PLL config register P1 */
kenjiArai 0:47b9bfa03730 400 uint32_t P2; /* PLL config register P2 */
kenjiArai 0:47b9bfa03730 401 uint32_t P3; /* PLL config register P3 */
kenjiArai 0:47b9bfa03730 402
kenjiArai 0:47b9bfa03730 403 /* Basic validation */
kenjiArai 0:47b9bfa03730 404 DBG("DBG: Enter si5351_setupPLL\r\n");
kenjiArai 0:47b9bfa03730 405 DBG("DBG: pll=%u, mult=%u, num=%u, denom=%u\r\n", pll, mult, num, denom);
kenjiArai 0:47b9bfa03730 406 bool err = false;
kenjiArai 0:47b9bfa03730 407 if (mult <= 14){ /* mult = 15..90 */
kenjiArai 0:47b9bfa03730 408 DBG("DBG: mult lower value error\r\n");
kenjiArai 0:47b9bfa03730 409 err = true;
kenjiArai 0:47b9bfa03730 410 }
kenjiArai 0:47b9bfa03730 411 if (mult >= 91){
kenjiArai 0:47b9bfa03730 412 DBG("DBG: mult bigger value error\r\n");
kenjiArai 0:47b9bfa03730 413 err = true;
kenjiArai 0:47b9bfa03730 414 }
kenjiArai 0:47b9bfa03730 415 if (denom == 0){ /* Avoid divide by zero */
kenjiArai 0:47b9bfa03730 416 DBG("DBG: denom = 0 error\r\n");
kenjiArai 0:47b9bfa03730 417 err = true;
kenjiArai 0:47b9bfa03730 418 }
kenjiArai 0:47b9bfa03730 419 if (num >=0x100000){ /* 20-bit limit */
kenjiArai 0:47b9bfa03730 420 DBG("DBG: num value error\r\n");
kenjiArai 0:47b9bfa03730 421 err = true;
kenjiArai 0:47b9bfa03730 422 }
kenjiArai 0:47b9bfa03730 423 if (denom >=0x100000){ /* 20-bit limit */
kenjiArai 0:47b9bfa03730 424 DBG("DBG: denom value error\r\n");
kenjiArai 0:47b9bfa03730 425 err = true;
kenjiArai 0:47b9bfa03730 426 }
kenjiArai 0:47b9bfa03730 427 if (err == true){
kenjiArai 0:47b9bfa03730 428 if (pll == SI5351_PLL_A){
kenjiArai 0:47b9bfa03730 429 plla_freq = 0;
kenjiArai 0:47b9bfa03730 430 } else { // SI5351_PLL_B
kenjiArai 0:47b9bfa03730 431 pllb_freq = 0;
kenjiArai 0:47b9bfa03730 432 }
kenjiArai 0:47b9bfa03730 433 DBG("DBG: return by error\r\n");
kenjiArai 0:47b9bfa03730 434 return;
kenjiArai 0:47b9bfa03730 435 }
kenjiArai 0:47b9bfa03730 436 /* Feedback Multisynth Divider Equation
kenjiArai 0:47b9bfa03730 437 * where: a = mult, b = num and c = denom
kenjiArai 0:47b9bfa03730 438 * P1 register is an 18-bit value using following formula:
kenjiArai 0:47b9bfa03730 439 * P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512
kenjiArai 0:47b9bfa03730 440 * P2 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 441 * P2[19:0] = 128 * num - denom * floor(128*(num/denom))
kenjiArai 0:47b9bfa03730 442 * P3 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 443 * P3[19:0] = denom
kenjiArai 0:47b9bfa03730 444 */
kenjiArai 0:47b9bfa03730 445 /* Set the main PLL config registers */
kenjiArai 0:47b9bfa03730 446 if (num == 0) {
kenjiArai 0:47b9bfa03730 447 DBG("DBG: num = 0\r\n");
kenjiArai 0:47b9bfa03730 448 /* Integer mode */
kenjiArai 0:47b9bfa03730 449 P1 = 128 * mult - 512;
kenjiArai 0:47b9bfa03730 450 P2 = num;
kenjiArai 0:47b9bfa03730 451 P3 = denom;
kenjiArai 0:47b9bfa03730 452 } else {
kenjiArai 0:47b9bfa03730 453 /* Fractional mode */
kenjiArai 0:47b9bfa03730 454 DBG("DBG: Fractional mode\r\n");
kenjiArai 0:47b9bfa03730 455 P1 = (uint32_t)
kenjiArai 0:47b9bfa03730 456 (128 * mult + floor(128 * ((double)num/(double)denom)) - 512);
kenjiArai 0:47b9bfa03730 457 P2 = (uint32_t)
kenjiArai 0:47b9bfa03730 458 (128 * num - denom * floor(128 * ((double)num/(double)denom)));
kenjiArai 0:47b9bfa03730 459 P3 = denom;
kenjiArai 0:47b9bfa03730 460 }
kenjiArai 0:47b9bfa03730 461 /* Get the appropriate starting point for the PLL registers */
kenjiArai 0:47b9bfa03730 462 const uint8_t pllreg_base[] = {
kenjiArai 0:47b9bfa03730 463 SI5351_REG_26_PLL_A,
kenjiArai 0:47b9bfa03730 464 SI5351_REG_34_PLL_B
kenjiArai 0:47b9bfa03730 465 };
kenjiArai 0:47b9bfa03730 466 uint8_t baseaddr = pllreg_base[pll];
kenjiArai 0:47b9bfa03730 467 /* The datasheet is a nightmare of typos and inconsistencies here! */
kenjiArai 0:47b9bfa03730 468 si5351_write(baseaddr, (P3 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 469 si5351_write(baseaddr+1, (P3 & 0x000000ff));
kenjiArai 0:47b9bfa03730 470 si5351_write(baseaddr+2, (P1 & 0x00030000) >> 16);
kenjiArai 0:47b9bfa03730 471 si5351_write(baseaddr+3, (P1 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 472 si5351_write(baseaddr+4, (P1 & 0x000000ff));
kenjiArai 0:47b9bfa03730 473 si5351_write(baseaddr+5,
kenjiArai 0:47b9bfa03730 474 ((P3 & 0x000f0000) >> 12) | ((P2 & 0x000f0000) >> 16) );
kenjiArai 0:47b9bfa03730 475 si5351_write(baseaddr+6, (P2 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 476 si5351_write(baseaddr+7, (P2 & 0x000000ff));
kenjiArai 0:47b9bfa03730 477 /* Reset both PLLs */
kenjiArai 0:47b9bfa03730 478 si5351_write(SI5351_REG_177_PLL_RESET,
kenjiArai 0:47b9bfa03730 479 SI5351_PLL_RESET_B | SI5351_PLL_RESET_A);
kenjiArai 0:47b9bfa03730 480 /* Store the frequency settings for use with the Multisynth helper */
kenjiArai 0:47b9bfa03730 481 DBG("DBG: Use 26(PLLA) or 34(PLLB)) ->%u and write data\r\n", baseaddr);
kenjiArai 0:47b9bfa03730 482 double f = base_freq * (mult + ((double)num / (double)denom));
kenjiArai 0:47b9bfa03730 483 DBG("DBG: PLL f=%u\r\n", (uint32_t)f);
kenjiArai 0:47b9bfa03730 484 if (pll == SI5351_PLL_A){
kenjiArai 0:47b9bfa03730 485 plla_freq = f;
kenjiArai 0:47b9bfa03730 486 } else { // SI5351_PLL_B
kenjiArai 0:47b9bfa03730 487 pllb_freq = f;
kenjiArai 0:47b9bfa03730 488 }
kenjiArai 0:47b9bfa03730 489 }
kenjiArai 0:47b9bfa03730 490
kenjiArai 0:47b9bfa03730 491 /**************************************************************************/
kenjiArai 0:47b9bfa03730 492 /*!
kenjiArai 0:47b9bfa03730 493 @brief Configures the Multisynth divider, which determines the
kenjiArai 0:47b9bfa03730 494 output clock frequency based on the specified PLL input.
kenjiArai 0:47b9bfa03730 495
kenjiArai 0:47b9bfa03730 496 @param output The output channel to use (0..2)
kenjiArai 0:47b9bfa03730 497 @param pllSource The PLL input source to use, which must be one of:
kenjiArai 0:47b9bfa03730 498 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 499 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 500 @param div The integer divider for the Multisynth output.
kenjiArai 0:47b9bfa03730 501 If pure integer values are used, this value must
kenjiArai 0:47b9bfa03730 502 be one of:
kenjiArai 0:47b9bfa03730 503 - SI5351_MULTISYNTH_DIV_4
kenjiArai 0:47b9bfa03730 504 - SI5351_MULTISYNTH_DIV_6
kenjiArai 0:47b9bfa03730 505 - SI5351_MULTISYNTH_DIV_8
kenjiArai 0:47b9bfa03730 506 If fractional output is used, this value must be
kenjiArai 0:47b9bfa03730 507 between 8 and 900.
kenjiArai 0:47b9bfa03730 508 @param num The 20-bit numerator for fractional output
kenjiArai 0:47b9bfa03730 509 (0..1,048,575). Set this to '0' for integer output.
kenjiArai 0:47b9bfa03730 510 @param denom The 20-bit denominator for fractional output
kenjiArai 0:47b9bfa03730 511 (1..1,048,575). Set this to '1' or higher to
kenjiArai 0:47b9bfa03730 512 avoid divide by zero errors.
kenjiArai 0:47b9bfa03730 513 @section Output Clock Configuration
kenjiArai 0:47b9bfa03730 514
kenjiArai 0:47b9bfa03730 515 The multisynth dividers are applied to the specified PLL output,
kenjiArai 0:47b9bfa03730 516 and are used to reduce the PLL output to a valid range (500kHz
kenjiArai 0:47b9bfa03730 517 to 160MHz). The relationship can be seen in this formula, where
kenjiArai 0:47b9bfa03730 518 fVCO is the PLL output frequency and MSx is the multisynth
kenjiArai 0:47b9bfa03730 519 divider:
kenjiArai 0:47b9bfa03730 520 fOUT = fVCO / MSx
kenjiArai 0:47b9bfa03730 521 Valid multisynth dividers are 4, 6, or 8 when using integers,
kenjiArai 0:47b9bfa03730 522 or any fractional values between 8 + 1/1,048,575 and 900 + 0/1
kenjiArai 0:47b9bfa03730 523
kenjiArai 0:47b9bfa03730 524 The following formula is used for the fractional mode divider:
kenjiArai 0:47b9bfa03730 525 a + b / c
kenjiArai 0:47b9bfa03730 526 a = The integer value, which must be 4, 6 or 8 in integer mode (MSx_INT=1)
kenjiArai 0:47b9bfa03730 527 or 6..1800 in fractional mode (MSx_INT=0).
kenjiArai 0:47b9bfa03730 528 b = The fractional numerator (0..1,048,575)
kenjiArai 0:47b9bfa03730 529 c = The fractional denominator (1..1,048,575)
kenjiArai 0:47b9bfa03730 530
kenjiArai 0:47b9bfa03730 531 @note Try to use integers whenever possible to avoid clock jitter
kenjiArai 0:47b9bfa03730 532 @note For output frequencies > 150MHz, you must set the divider
kenjiArai 0:47b9bfa03730 533 to 4 and adjust to PLL to generate the frequency (for example
kenjiArai 0:47b9bfa03730 534 a PLL of 640 to generate a 160MHz output clock). This is not
kenjiArai 0:47b9bfa03730 535 yet supported in the driver, which limits frequencies to
kenjiArai 0:47b9bfa03730 536 500kHz .. 150MHz.
kenjiArai 0:47b9bfa03730 537 @note For frequencies below 500kHz (down to 8kHz) Rx_DIV must be
kenjiArai 0:47b9bfa03730 538 used, but this isn't currently implemented in the driver.
kenjiArai 0:47b9bfa03730 539 */
kenjiArai 0:47b9bfa03730 540 /**************************************************************************/
kenjiArai 0:47b9bfa03730 541 double SI5351A::si5351_setupMultisynth(
kenjiArai 0:47b9bfa03730 542 uint8_t output,
kenjiArai 0:47b9bfa03730 543 uint8_t pllSource,
kenjiArai 0:47b9bfa03730 544 uint32_t div,
kenjiArai 0:47b9bfa03730 545 uint32_t num,
kenjiArai 0:47b9bfa03730 546 uint32_t denom,
kenjiArai 0:47b9bfa03730 547 uint8_t factor)
kenjiArai 0:47b9bfa03730 548 {
kenjiArai 0:47b9bfa03730 549 uint32_t P1; /* Multisynth config register P1 */
kenjiArai 0:47b9bfa03730 550 uint32_t P2; /* Multisynth config register P2 */
kenjiArai 0:47b9bfa03730 551 uint32_t P3; /* Multisynth config register P3 */
kenjiArai 0:47b9bfa03730 552 uint32_t div4 = 0;
kenjiArai 0:47b9bfa03730 553 uint32_t multisynth_vale;
kenjiArai 0:47b9bfa03730 554 double multisynth_double;
kenjiArai 0:47b9bfa03730 555
kenjiArai 0:47b9bfa03730 556 DBG("DBG: Enter si5351_setupMultisynth\r\n");
kenjiArai 0:47b9bfa03730 557 DBG("DBG: ch=%u, pll=%u, div=%u, num=%u, denom=%u, factor=%u\r\n",
kenjiArai 0:47b9bfa03730 558 output, pllSource, div, num, denom, factor);
kenjiArai 0:47b9bfa03730 559 if (output > 3){
kenjiArai 0:47b9bfa03730 560 return 0;
kenjiArai 0:47b9bfa03730 561 } /* Channel range */
kenjiArai 0:47b9bfa03730 562 if ((div <= 3) || (div >= 1801)){ /* Divider integer 6..1800 */
kenjiArai 0:47b9bfa03730 563 DBG("DBG: div out of range error\r\n");
kenjiArai 0:47b9bfa03730 564 return 0;
kenjiArai 0:47b9bfa03730 565 }
kenjiArai 0:47b9bfa03730 566 if (denom == 0){ /* Avoid divide by zero */
kenjiArai 0:47b9bfa03730 567 DBG("DBG: denom=0 error\r\n");
kenjiArai 0:47b9bfa03730 568 return 0;
kenjiArai 0:47b9bfa03730 569 }
kenjiArai 0:47b9bfa03730 570 if (num >=0x100000){ /* 20-bit limit */
kenjiArai 0:47b9bfa03730 571 DBG("DBG: num bigger error\r\n");
kenjiArai 0:47b9bfa03730 572 return 0;
kenjiArai 0:47b9bfa03730 573 }
kenjiArai 0:47b9bfa03730 574 if (denom >=0x100000){ /* 20-bit limit */
kenjiArai 0:47b9bfa03730 575 DBG("DBG: denom bigger error\r\n");
kenjiArai 0:47b9bfa03730 576 return 0;
kenjiArai 0:47b9bfa03730 577 }
kenjiArai 0:47b9bfa03730 578 DBG("DBG: Passed range check\r\n");
kenjiArai 0:47b9bfa03730 579 /* Get the appropriate starting point for the PLL registers */
kenjiArai 0:47b9bfa03730 580 const uint8_t msreg_base[] = {
kenjiArai 0:47b9bfa03730 581 SI5351_REG_42_MULTISYNTH0,
kenjiArai 0:47b9bfa03730 582 SI5351_REG_50_MULTISYNTH1,
kenjiArai 0:47b9bfa03730 583 SI5351_REG_58_MULTISYNTH2,
kenjiArai 0:47b9bfa03730 584 };
kenjiArai 0:47b9bfa03730 585 uint8_t baseaddr = msreg_base[output];
kenjiArai 0:47b9bfa03730 586 /* Output Multisynth Divider Equations
kenjiArai 0:47b9bfa03730 587 * where: a = div, b = num and c = denom
kenjiArai 0:47b9bfa03730 588 * P1 register is an 18-bit value using following formula:
kenjiArai 0:47b9bfa03730 589 * P1[17:0] = 128 * a + floor(128*(b/c)) - 512
kenjiArai 0:47b9bfa03730 590 * P2 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 591 * P2[19:0] = 128 * b - c * floor(128*(b/c))
kenjiArai 0:47b9bfa03730 592 * P3 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 593 * P3[19:0] = c
kenjiArai 0:47b9bfa03730 594 */
kenjiArai 0:47b9bfa03730 595 /* Set the main PLL config registers */
kenjiArai 0:47b9bfa03730 596 if (div == 4) {
kenjiArai 0:47b9bfa03730 597 DBG("DBG: enter div==4\r\n");
kenjiArai 0:47b9bfa03730 598 div4 = SI5351_DIVBY4;
kenjiArai 0:47b9bfa03730 599 P1 = P2 = 0;
kenjiArai 0:47b9bfa03730 600 P3 = 1;
kenjiArai 0:47b9bfa03730 601 multisynth_double = 4.0f;
kenjiArai 0:47b9bfa03730 602 } else if (num == 0) {
kenjiArai 0:47b9bfa03730 603 DBG("DBG: enter num==0\r\n");
kenjiArai 0:47b9bfa03730 604 /* Integer mode */
kenjiArai 0:47b9bfa03730 605 P1 = 128 * div - 512;
kenjiArai 0:47b9bfa03730 606 P2 = 0;
kenjiArai 0:47b9bfa03730 607 P3 = 1;
kenjiArai 0:47b9bfa03730 608 multisynth_double = (double)div;
kenjiArai 0:47b9bfa03730 609 } else {
kenjiArai 0:47b9bfa03730 610 /* Fractional mode */
kenjiArai 0:47b9bfa03730 611 DBG("DBG: enter Fractional mode\r\n");
kenjiArai 0:47b9bfa03730 612 multisynth_vale = (floor)((double)num /(double)denom);
kenjiArai 0:47b9bfa03730 613 P1 = 128 * div + 128 * multisynth_vale - 512;
kenjiArai 0:47b9bfa03730 614 P2 = 128 * num - denom * 128 * multisynth_vale;
kenjiArai 0:47b9bfa03730 615 P3 = denom;
kenjiArai 0:47b9bfa03730 616 multisynth_double = div + (double)num /(double)denom;
kenjiArai 0:47b9bfa03730 617 /* a + b/c between 6..1800 */
kenjiArai 0:47b9bfa03730 618 if ((multisynth_double < 6.0f) || (multisynth_double > 1800.0f)){
kenjiArai 0:47b9bfa03730 619 return 0;
kenjiArai 0:47b9bfa03730 620 }
kenjiArai 0:47b9bfa03730 621 }
kenjiArai 0:47b9bfa03730 622 /* Set the MSx config registers */
kenjiArai 0:47b9bfa03730 623 si5351_write(baseaddr, (P3 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 624 si5351_write(baseaddr+1, (P3 & 0x000000ff));
kenjiArai 0:47b9bfa03730 625 si5351_write(baseaddr+2, ((P1 & 0x00030000) >> 16) | div4 | factor);
kenjiArai 0:47b9bfa03730 626 si5351_write(baseaddr+3, (P1 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 627 si5351_write(baseaddr+4, (P1 & 0x000000ff));
kenjiArai 0:47b9bfa03730 628 si5351_write(baseaddr+5,
kenjiArai 0:47b9bfa03730 629 ((P3 & 0x000f0000) >> 12) | ((P2 & 0x000f0000) >> 16));
kenjiArai 0:47b9bfa03730 630 si5351_write(baseaddr+6, (P2 & 0x0000ff00) >> 8);
kenjiArai 0:47b9bfa03730 631 si5351_write(baseaddr+7, (P2 & 0x000000ff));
kenjiArai 0:47b9bfa03730 632 /* Configure the clk control and enable the output */
kenjiArai 0:47b9bfa03730 633 const uint8_t clkctrl[] = {
kenjiArai 0:47b9bfa03730 634 SI5351_REG_16_CLK0_CONTROL,
kenjiArai 0:47b9bfa03730 635 SI5351_REG_17_CLK1_CONTROL,
kenjiArai 0:47b9bfa03730 636 SI5351_REG_18_CLK2_CONTROL
kenjiArai 0:47b9bfa03730 637 };
kenjiArai 0:47b9bfa03730 638 uint8_t dat;
kenjiArai 0:47b9bfa03730 639 dat = drv_current | SI5351_CLK_INPUT_MULTISYNTH_N;
kenjiArai 0:47b9bfa03730 640 if (pllSource == SI5351_PLL_B){
kenjiArai 0:47b9bfa03730 641 dat |= SI5351_CLK_PLL_SELECT_B;
kenjiArai 0:47b9bfa03730 642 }
kenjiArai 0:47b9bfa03730 643 if (num == 0){
kenjiArai 0:47b9bfa03730 644 dat |= SI5351_CLK_INTEGER_MODE;
kenjiArai 0:47b9bfa03730 645 }
kenjiArai 0:47b9bfa03730 646 DBG("DBG: CLK%u: reg_%u=0x%02x\r\n", output, clkctrl[output], dat);
kenjiArai 0:47b9bfa03730 647 si5351_write(clkctrl[output], dat);
kenjiArai 0:47b9bfa03730 648 DBG("DBG: a+b/c=%8.2f\r\n", multisynth_double);
kenjiArai 0:47b9bfa03730 649 return multisynth_double;
kenjiArai 0:47b9bfa03730 650 }
kenjiArai 0:47b9bfa03730 651
kenjiArai 0:47b9bfa03730 652 uint32_t SI5351A::gcd(uint32_t x, uint32_t y)
kenjiArai 0:47b9bfa03730 653 {
kenjiArai 0:47b9bfa03730 654 int32_t z;
kenjiArai 0:47b9bfa03730 655 while (y != 0) {
kenjiArai 0:47b9bfa03730 656 z = x % y;
kenjiArai 0:47b9bfa03730 657 x = y;
kenjiArai 0:47b9bfa03730 658 y = z;
kenjiArai 0:47b9bfa03730 659 }
kenjiArai 0:47b9bfa03730 660 return x;
kenjiArai 0:47b9bfa03730 661 }
kenjiArai 0:47b9bfa03730 662
kenjiArai 0:47b9bfa03730 663 double SI5351A::si5351_set_frequency_fixedpll(
kenjiArai 0:47b9bfa03730 664 uint8_t channel,
kenjiArai 0:47b9bfa03730 665 uint32_t pll,
kenjiArai 0:47b9bfa03730 666 uint32_t pllfreq,
kenjiArai 0:47b9bfa03730 667 uint32_t freq,
kenjiArai 0:47b9bfa03730 668 uint8_t factor)
kenjiArai 0:47b9bfa03730 669 {
kenjiArai 0:47b9bfa03730 670 DBG("DBG: Enter si5351_set_frequency_fixedpll\r\n");
kenjiArai 0:47b9bfa03730 671 uint32_t div = (floor)((double)pllfreq / (double)freq); // range: 8 ~ 1800
kenjiArai 0:47b9bfa03730 672 uint32_t num = pllfreq - freq * div;
kenjiArai 0:47b9bfa03730 673 uint32_t denom = freq;
kenjiArai 0:47b9bfa03730 674 //int32_t k = freq / (1<<20) + 1;
kenjiArai 0:47b9bfa03730 675 uint32_t k = gcd(num, denom);
kenjiArai 0:47b9bfa03730 676 num /= k;
kenjiArai 0:47b9bfa03730 677 denom /= k;
kenjiArai 0:47b9bfa03730 678 while (denom >= (1<<20)) {
kenjiArai 0:47b9bfa03730 679 num >>= 1;
kenjiArai 0:47b9bfa03730 680 denom >>= 1;
kenjiArai 0:47b9bfa03730 681 }
kenjiArai 0:47b9bfa03730 682 DBG("DBG: CLK%u: PLL=%u,div=%u,num=%u,denom=%u\r\n",
kenjiArai 0:47b9bfa03730 683 channel, pll, div, num, denom);
kenjiArai 0:47b9bfa03730 684 double x = si5351_setupMultisynth(channel, pll, div, num, denom, factor);
kenjiArai 0:47b9bfa03730 685 if (x == 0.0f){ return 0;}
kenjiArai 0:47b9bfa03730 686 x = (double)pll_freq / x;
kenjiArai 0:47b9bfa03730 687 DBG("DBG: Freqency=%.0f[Hz]\r\n", x);
kenjiArai 0:47b9bfa03730 688 return x;
kenjiArai 0:47b9bfa03730 689 }
kenjiArai 0:47b9bfa03730 690
kenjiArai 0:47b9bfa03730 691 double SI5351A::si5351_set_frequency_fixeddiv(
kenjiArai 0:47b9bfa03730 692 uint8_t channel,
kenjiArai 0:47b9bfa03730 693 uint32_t pll,
kenjiArai 0:47b9bfa03730 694 uint32_t freq,
kenjiArai 0:47b9bfa03730 695 uint32_t div)
kenjiArai 0:47b9bfa03730 696 {
kenjiArai 0:47b9bfa03730 697 DBG("DBG: si5351_set_frequency_fixeddiv\r\n");
kenjiArai 0:47b9bfa03730 698 uint32_t pllfreq = freq * div;
kenjiArai 0:47b9bfa03730 699 uint32_t multi = pllfreq / base_freq;
kenjiArai 0:47b9bfa03730 700 uint32_t num = pllfreq - multi * base_freq;
kenjiArai 0:47b9bfa03730 701 uint32_t denom = base_freq;
kenjiArai 0:47b9bfa03730 702 uint32_t k = gcd(num, denom);
kenjiArai 0:47b9bfa03730 703 num /= k;
kenjiArai 0:47b9bfa03730 704 denom /= k;
kenjiArai 0:47b9bfa03730 705 while (denom >= (1<<20)) {
kenjiArai 0:47b9bfa03730 706 num >>= 1;
kenjiArai 0:47b9bfa03730 707 denom >>= 1;
kenjiArai 0:47b9bfa03730 708 }
kenjiArai 0:47b9bfa03730 709 si5351_setupPLL(pll, multi, num, denom);
kenjiArai 0:47b9bfa03730 710 num = 0;
kenjiArai 0:47b9bfa03730 711 double x = si5351_setupMultisynth(channel, pll, div, num, denom, 0);
kenjiArai 0:47b9bfa03730 712 if (x == 0.0f){ return 0.0f;}
kenjiArai 0:47b9bfa03730 713 if (pll == SI5351_PLL_A){
kenjiArai 0:47b9bfa03730 714 x = plla_freq / x;
kenjiArai 0:47b9bfa03730 715 } else { // SI5351_PLL_B
kenjiArai 0:47b9bfa03730 716 x = pllb_freq / x;
kenjiArai 0:47b9bfa03730 717 }
kenjiArai 0:47b9bfa03730 718 DBG("DBG: Freqency=%.0f[Hz]\r\n", x);
kenjiArai 0:47b9bfa03730 719 return x;
kenjiArai 0:47b9bfa03730 720 }
kenjiArai 0:47b9bfa03730 721
kenjiArai 0:47b9bfa03730 722 void SI5351A::si5351_bulk_write(const uint8_t *buf, uint8_t len)
kenjiArai 0:47b9bfa03730 723 {
kenjiArai 0:47b9bfa03730 724 _i2c.write(addr, (const char*)buf, len, false);
kenjiArai 0:47b9bfa03730 725 }
kenjiArai 0:47b9bfa03730 726
kenjiArai 0:47b9bfa03730 727 void SI5351A::si5351_write(uint8_t reg, uint8_t dat)
kenjiArai 0:47b9bfa03730 728 {
kenjiArai 0:47b9bfa03730 729 uint8_t buf[] = { reg, dat };
kenjiArai 0:47b9bfa03730 730 _i2c.write(addr,(const char *)buf, 2, false);
kenjiArai 0:47b9bfa03730 731 }
kenjiArai 0:47b9bfa03730 732
kenjiArai 0:47b9bfa03730 733 void SI5351A::si5351_read(const uint8_t *buf)
kenjiArai 0:47b9bfa03730 734 {
kenjiArai 0:47b9bfa03730 735 int n = (int)buf[1];
kenjiArai 0:47b9bfa03730 736 _i2c.write(addr,(const char *)buf, 1, true);
kenjiArai 0:47b9bfa03730 737 _i2c.read(addr, (char *)buf, n, false);
kenjiArai 0:47b9bfa03730 738 }
kenjiArai 0:47b9bfa03730 739
kenjiArai 0:47b9bfa03730 740 //----------- DEBUG PURPOSE ----------------------------------------------------
kenjiArai 0:47b9bfa03730 741 // Print memory contents
kenjiArai 0:47b9bfa03730 742 void SI5351A::put_dump (const uint8_t *buff, uint8_t ofs, uint8_t cnt)
kenjiArai 0:47b9bfa03730 743 {
kenjiArai 0:47b9bfa03730 744 printf("%03u ", ofs);
kenjiArai 0:47b9bfa03730 745 for(int n = 0; n < cnt; n++) { // show hex
kenjiArai 0:47b9bfa03730 746 printf(" %02x", buff[n]);
kenjiArai 0:47b9bfa03730 747 }
kenjiArai 0:47b9bfa03730 748 printf("\r\n");
kenjiArai 0:47b9bfa03730 749 }
kenjiArai 0:47b9bfa03730 750
kenjiArai 0:47b9bfa03730 751 void SI5351A::prnt_reg(uint8_t offset, uint8_t n)
kenjiArai 0:47b9bfa03730 752 {
kenjiArai 0:47b9bfa03730 753 uint8_t buf[16];
kenjiArai 0:47b9bfa03730 754 buf[0] = offset;
kenjiArai 0:47b9bfa03730 755 buf[1] = n;
kenjiArai 0:47b9bfa03730 756 si5351_read(buf);
kenjiArai 0:47b9bfa03730 757 put_dump(buf, offset, n);
kenjiArai 0:47b9bfa03730 758 }
kenjiArai 0:47b9bfa03730 759
kenjiArai 0:47b9bfa03730 760 void SI5351A::debug_reg_print(void)
kenjiArai 0:47b9bfa03730 761 {
kenjiArai 0:47b9bfa03730 762 printf("Show Si5351A registers\r\n");
kenjiArai 0:47b9bfa03730 763 printf("reg 0 1 2 3 4 5 6 7 8 9\r\n");
kenjiArai 0:47b9bfa03730 764 prnt_reg(0, 4); // reg0 to reg3
kenjiArai 0:47b9bfa03730 765 prnt_reg(9, 1); // reg9
kenjiArai 0:47b9bfa03730 766 prnt_reg(15, 4); // reg15 to reg18
kenjiArai 0:47b9bfa03730 767 prnt_reg(24, 10); // reg24 to reg33
kenjiArai 0:47b9bfa03730 768 prnt_reg(34, 10); // reg34 to reg43
kenjiArai 0:47b9bfa03730 769 prnt_reg(44, 10); // reg44 to reg53
kenjiArai 0:47b9bfa03730 770 prnt_reg(54, 10); // reg54 to reg63
kenjiArai 0:47b9bfa03730 771 prnt_reg(64, 2); // reg64 to reg65
kenjiArai 0:47b9bfa03730 772 prnt_reg(149, 10); // reg149 to reg158
kenjiArai 0:47b9bfa03730 773 prnt_reg(159, 3); // reg159 to reg161
kenjiArai 0:47b9bfa03730 774 prnt_reg(165, 3); // reg165 to reg167
kenjiArai 0:47b9bfa03730 775 prnt_reg(177, 1); // reg177
kenjiArai 0:47b9bfa03730 776 prnt_reg(183, 1); // reg183
kenjiArai 0:47b9bfa03730 777 prnt_reg(187, 1); // reg187
kenjiArai 0:47b9bfa03730 778 }
kenjiArai 0:47b9bfa03730 779
kenjiArai 0:47b9bfa03730 780 void SI5351A::debug_current_config(void)
kenjiArai 0:47b9bfa03730 781 {
kenjiArai 0:47b9bfa03730 782 uint8_t buf[16];
kenjiArai 0:47b9bfa03730 783 uint8_t dt0;
kenjiArai 0:47b9bfa03730 784 uint8_t dt1;
kenjiArai 0:47b9bfa03730 785 //Step1
kenjiArai 0:47b9bfa03730 786 printf("[BASE CLOCK] --> ");
kenjiArai 0:47b9bfa03730 787 buf[0] = 183; // register address
kenjiArai 0:47b9bfa03730 788 buf[1] = 1; // # of reading bytes
kenjiArai 0:47b9bfa03730 789 si5351_read(buf);
kenjiArai 0:47b9bfa03730 790 printf("Xtal=%u[Hz] with internal cap=", base_freq);
kenjiArai 0:47b9bfa03730 791 dt0 = buf[0] & 0xc0;
kenjiArai 0:47b9bfa03730 792 switch (dt0){
kenjiArai 0:47b9bfa03730 793 case 0xc0:
kenjiArai 0:47b9bfa03730 794 printf("10");
kenjiArai 0:47b9bfa03730 795 break;
kenjiArai 0:47b9bfa03730 796 case 0x80:
kenjiArai 0:47b9bfa03730 797 printf("8");
kenjiArai 0:47b9bfa03730 798 break;
kenjiArai 0:47b9bfa03730 799 case 0x40:
kenjiArai 0:47b9bfa03730 800 printf("6");
kenjiArai 0:47b9bfa03730 801 break;
kenjiArai 0:47b9bfa03730 802 default:
kenjiArai 0:47b9bfa03730 803 printf("?(bad config)");
kenjiArai 0:47b9bfa03730 804 break;
kenjiArai 0:47b9bfa03730 805 }
kenjiArai 0:47b9bfa03730 806 printf("[pF]\r\n");
kenjiArai 0:47b9bfa03730 807 //Step2
kenjiArai 0:47b9bfa03730 808 printf("[PLLn] --> ");
kenjiArai 0:47b9bfa03730 809 buf[0] = 15;
kenjiArai 0:47b9bfa03730 810 buf[1] = 1;
kenjiArai 0:47b9bfa03730 811 si5351_read(buf);
kenjiArai 0:47b9bfa03730 812 dt0 = buf[0];
kenjiArai 0:47b9bfa03730 813 dt1 = dt0 >> 6;
kenjiArai 0:47b9bfa03730 814 printf("Clock in divide by %u", 1U << dt1);
kenjiArai 0:47b9bfa03730 815 printf(" PLLA clock source is ");
kenjiArai 0:47b9bfa03730 816 if (dt0 & 0x04){
kenjiArai 0:47b9bfa03730 817 printf("none XTAL(bad config)");
kenjiArai 0:47b9bfa03730 818 } else {
kenjiArai 0:47b9bfa03730 819 printf("XTAL");
kenjiArai 0:47b9bfa03730 820 }
kenjiArai 0:47b9bfa03730 821 printf(" & PLLB = ");
kenjiArai 0:47b9bfa03730 822 if (dt0 & 0x08){
kenjiArai 0:47b9bfa03730 823 printf("none XTAL(bad config)");
kenjiArai 0:47b9bfa03730 824 } else {
kenjiArai 0:47b9bfa03730 825 printf("XTAL");
kenjiArai 0:47b9bfa03730 826 }
kenjiArai 0:47b9bfa03730 827 printf("\r\n");
kenjiArai 0:47b9bfa03730 828 //Step3
kenjiArai 0:47b9bfa03730 829 printf("[CLK0,1,2] --> ");
kenjiArai 0:47b9bfa03730 830 printf("CLKn output E:enable/D:disable * ");
kenjiArai 0:47b9bfa03730 831 buf[0] = 9; // register address
kenjiArai 0:47b9bfa03730 832 buf[1] = 1; // # of reading bytes
kenjiArai 0:47b9bfa03730 833 si5351_read(buf);
kenjiArai 0:47b9bfa03730 834 dt0 = buf[0] & 0x07;
kenjiArai 0:47b9bfa03730 835 buf[0] = 3; // register address
kenjiArai 0:47b9bfa03730 836 buf[1] = 1; // # of reading bytes
kenjiArai 0:47b9bfa03730 837 si5351_read(buf);
kenjiArai 0:47b9bfa03730 838 dt1 = buf[0] & 0x07;
kenjiArai 0:47b9bfa03730 839 printf("CLK2:");
kenjiArai 0:47b9bfa03730 840 if ((dt0 & 0x04) && (dt1 & 0x04)){
kenjiArai 0:47b9bfa03730 841 printf("D");
kenjiArai 0:47b9bfa03730 842 } else {
kenjiArai 0:47b9bfa03730 843 printf("E");
kenjiArai 0:47b9bfa03730 844 }
kenjiArai 0:47b9bfa03730 845 printf(", CLK1:");
kenjiArai 0:47b9bfa03730 846 if ((dt0 & 0x02) && (dt1 & 0x02)){
kenjiArai 0:47b9bfa03730 847 printf("D");
kenjiArai 0:47b9bfa03730 848 } else {
kenjiArai 0:47b9bfa03730 849 printf("E");
kenjiArai 0:47b9bfa03730 850 }
kenjiArai 0:47b9bfa03730 851 printf(", CLK0:");
kenjiArai 0:47b9bfa03730 852 if ((dt0 & 0x01) && (dt1 & 0x01)){
kenjiArai 0:47b9bfa03730 853 printf("D");
kenjiArai 0:47b9bfa03730 854 } else {
kenjiArai 0:47b9bfa03730 855 printf("E");
kenjiArai 0:47b9bfa03730 856 }
kenjiArai 0:47b9bfa03730 857 printf("\r\n");
kenjiArai 0:47b9bfa03730 858 //Step4
kenjiArai 0:47b9bfa03730 859 buf[0] = 16;
kenjiArai 0:47b9bfa03730 860 buf[1] = 3;
kenjiArai 0:47b9bfa03730 861 si5351_read(buf);
kenjiArai 0:47b9bfa03730 862 printf("--> CLK0 * ");
kenjiArai 0:47b9bfa03730 863 reg_16_17_18(buf[0]);
kenjiArai 0:47b9bfa03730 864 printf("--> CLK1 * ");
kenjiArai 0:47b9bfa03730 865 reg_16_17_18(buf[1]);
kenjiArai 0:47b9bfa03730 866 printf("--> CLK2 * ");
kenjiArai 0:47b9bfa03730 867 reg_16_17_18(buf[2]);
kenjiArai 0:47b9bfa03730 868 //Step5
kenjiArai 0:47b9bfa03730 869 printf("[PLLn P1,P2,P3]\r\n");
kenjiArai 0:47b9bfa03730 870 printf("--> PLLA * ");
kenjiArai 0:47b9bfa03730 871 buf[0] = 26; // register address
kenjiArai 0:47b9bfa03730 872 buf[1] = 8; // # of reading bytes
kenjiArai 0:47b9bfa03730 873 si5351_read(buf);
kenjiArai 0:47b9bfa03730 874 reg_pll_8bytes(buf);
kenjiArai 0:47b9bfa03730 875 printf("--> PLLB * ");
kenjiArai 0:47b9bfa03730 876 buf[0] = 34; // register address
kenjiArai 0:47b9bfa03730 877 buf[1] = 8; // # of reading bytes
kenjiArai 0:47b9bfa03730 878 si5351_read(buf);
kenjiArai 0:47b9bfa03730 879 reg_pll_8bytes(buf);
kenjiArai 0:47b9bfa03730 880 printf("[MultiSynth-n P1,P2,P3]\r\n");
kenjiArai 0:47b9bfa03730 881 printf("--> Mltsyn0 * ");
kenjiArai 0:47b9bfa03730 882 buf[0] = 42; // register address
kenjiArai 0:47b9bfa03730 883 buf[1] = 8; // # of reading bytes
kenjiArai 0:47b9bfa03730 884 si5351_read(buf);
kenjiArai 0:47b9bfa03730 885 reg_mltisyc_8bytes(buf);
kenjiArai 0:47b9bfa03730 886 printf("--> Mltsyn1 * ");
kenjiArai 0:47b9bfa03730 887 buf[0] = 50; // register address
kenjiArai 0:47b9bfa03730 888 buf[1] = 8; // # of reading bytes
kenjiArai 0:47b9bfa03730 889 si5351_read(buf);
kenjiArai 0:47b9bfa03730 890 reg_mltisyc_8bytes(buf);
kenjiArai 0:47b9bfa03730 891 printf("--> Mltsyn2 * ");
kenjiArai 0:47b9bfa03730 892 buf[0] = 58; // register address
kenjiArai 0:47b9bfa03730 893 buf[1] = 8; // # of reading bytes
kenjiArai 0:47b9bfa03730 894 si5351_read(buf);
kenjiArai 0:47b9bfa03730 895 reg_mltisyc_8bytes(buf);
kenjiArai 0:47b9bfa03730 896 }
kenjiArai 0:47b9bfa03730 897
kenjiArai 0:47b9bfa03730 898 void SI5351A::reg_pll_8bytes(uint8_t *buf)
kenjiArai 0:47b9bfa03730 899 {
kenjiArai 0:47b9bfa03730 900 uint32_t dt = ((uint32_t)(buf[5] & 0xf0) << 12) + ((uint32_t)buf[0] << 8)
kenjiArai 0:47b9bfa03730 901 + (uint32_t)buf[1];
kenjiArai 0:47b9bfa03730 902 printf("P3=%6u (0x%05x), ", dt, dt);
kenjiArai 0:47b9bfa03730 903 dt = ((uint32_t)(buf[5] & 0x0f) << 16) + ((uint32_t)buf[6] << 8)
kenjiArai 0:47b9bfa03730 904 + (uint32_t)buf[7];
kenjiArai 0:47b9bfa03730 905 printf("P2=%6u (0x%05x), ", dt, dt);
kenjiArai 0:47b9bfa03730 906 dt = ((uint32_t)(buf[2] & 0x03) << 16) + ((uint32_t)buf[3] << 8)
kenjiArai 0:47b9bfa03730 907 + (uint32_t)buf[4];
kenjiArai 0:47b9bfa03730 908 printf("P1=%6u (0x%05x)\r\n", dt, dt);
kenjiArai 0:47b9bfa03730 909 }
kenjiArai 0:47b9bfa03730 910
kenjiArai 0:47b9bfa03730 911 void SI5351A::reg_mltisyc_8bytes(uint8_t *buf)
kenjiArai 0:47b9bfa03730 912 {
kenjiArai 0:47b9bfa03730 913 uint32_t dt = ((uint32_t)(buf[5] & 0xf0) << 12) + ((uint32_t)buf[0] << 8)
kenjiArai 0:47b9bfa03730 914 + (uint32_t)buf[1];
kenjiArai 0:47b9bfa03730 915 printf("P3=%6u (0x%05x), ", dt, dt);
kenjiArai 0:47b9bfa03730 916 dt = ((uint32_t)(buf[5] & 0x0f) << 16) + ((uint32_t)buf[6] << 8)
kenjiArai 0:47b9bfa03730 917 + (uint32_t)buf[7];
kenjiArai 0:47b9bfa03730 918 printf("P2=%6u (0x%05x), ", dt, dt);
kenjiArai 0:47b9bfa03730 919 dt = ((uint32_t)(buf[2] & 0x03) << 16) + ((uint32_t)buf[3] << 8)
kenjiArai 0:47b9bfa03730 920 + (uint32_t)buf[4];
kenjiArai 0:47b9bfa03730 921 printf("P1=%6u (0x%05x), ", dt, dt);
kenjiArai 0:47b9bfa03730 922 uint8_t d = buf[2];
kenjiArai 0:47b9bfa03730 923 if ((d & 0x0c) == 0x0c){
kenjiArai 0:47b9bfa03730 924 printf("Divided by");
kenjiArai 0:47b9bfa03730 925 } else {
kenjiArai 0:47b9bfa03730 926 printf("Div >");
kenjiArai 0:47b9bfa03730 927 }
kenjiArai 0:47b9bfa03730 928 printf(" 4 mode, ");
kenjiArai 0:47b9bfa03730 929 dt >>= 4;
kenjiArai 0:47b9bfa03730 930 dt &=0x07;
kenjiArai 0:47b9bfa03730 931 printf("R-reg: Divided by %u\r\n", 1U << dt);
kenjiArai 0:47b9bfa03730 932 }
kenjiArai 0:47b9bfa03730 933
kenjiArai 0:47b9bfa03730 934 void SI5351A::reg_16_17_18(uint8_t dt)
kenjiArai 0:47b9bfa03730 935 {
kenjiArai 0:47b9bfa03730 936 printf("Power ");
kenjiArai 0:47b9bfa03730 937 if (dt & 0x80){
kenjiArai 0:47b9bfa03730 938 printf("down(not used)");
kenjiArai 0:47b9bfa03730 939 } else {
kenjiArai 0:47b9bfa03730 940 printf("up(running)");
kenjiArai 0:47b9bfa03730 941 }
kenjiArai 0:47b9bfa03730 942 printf(", MultiSynth-> ");
kenjiArai 0:47b9bfa03730 943 if (dt & 0x40){
kenjiArai 0:47b9bfa03730 944 printf("Integer");
kenjiArai 0:47b9bfa03730 945 } else {
kenjiArai 0:47b9bfa03730 946 printf("Fractional");
kenjiArai 0:47b9bfa03730 947 }
kenjiArai 0:47b9bfa03730 948 printf(" mode, PLL-> ");
kenjiArai 0:47b9bfa03730 949 if (dt & 0x20){
kenjiArai 0:47b9bfa03730 950 printf("PLLB");
kenjiArai 0:47b9bfa03730 951 } else {
kenjiArai 0:47b9bfa03730 952 printf("PLLA");
kenjiArai 0:47b9bfa03730 953 }
kenjiArai 0:47b9bfa03730 954 printf(", Clock-> ");
kenjiArai 0:47b9bfa03730 955 if (dt & 0x20){
kenjiArai 0:47b9bfa03730 956 printf("inverted");
kenjiArai 0:47b9bfa03730 957 } else {
kenjiArai 0:47b9bfa03730 958 printf("not inverted");
kenjiArai 0:47b9bfa03730 959 }
kenjiArai 0:47b9bfa03730 960 printf(", Drive strength-> ");
kenjiArai 0:47b9bfa03730 961 printf("%umA\r\n", 2 + 2 * (dt & 0x03));
kenjiArai 0:47b9bfa03730 962 }
kenjiArai 0:47b9bfa03730 963
kenjiArai 0:47b9bfa03730 964 /**************************************************************************/
kenjiArai 0:47b9bfa03730 965 /*!
kenjiArai 0:47b9bfa03730 966 @brief Configures the Si5351 with config settings generated in
kenjiArai 0:47b9bfa03730 967 ClockBuilder. You can use this function to make sure that
kenjiArai 0:47b9bfa03730 968 your HW is properly configure and that there are no problems
kenjiArai 0:47b9bfa03730 969 with the board itself.
kenjiArai 0:47b9bfa03730 970
kenjiArai 0:47b9bfa03730 971 Running this function should provide the following output:
kenjiArai 0:47b9bfa03730 972 * Channel 0: 120.00 MHz
kenjiArai 0:47b9bfa03730 973 * Channel 1: 12.00 MHz
kenjiArai 0:47b9bfa03730 974 * Channel 2: 13.56 MHz
kenjiArai 0:47b9bfa03730 975 @note This will overwrite all of the config registers!
kenjiArai 0:47b9bfa03730 976 */
kenjiArai 0:47b9bfa03730 977 /**************************************************************************/
kenjiArai 0:47b9bfa03730 978 /* Test setup from SI5351 ClockBuilder
kenjiArai 0:47b9bfa03730 979 * -----------------------------------
kenjiArai 0:47b9bfa03730 980 * XTAL: 25 MHz
kenjiArai 0:47b9bfa03730 981 * Channel 0: 120.00 MHz
kenjiArai 0:47b9bfa03730 982 * Channel 1: 12.00 MHz
kenjiArai 0:47b9bfa03730 983 * Channel 2: 13.56 MHz
kenjiArai 0:47b9bfa03730 984 */
kenjiArai 0:47b9bfa03730 985 static const uint8_t m_si5351_regs_15to92_149to170[100][2] =
kenjiArai 0:47b9bfa03730 986 {
kenjiArai 0:47b9bfa03730 987 { 15, 0x00 }, /* Input source = crystal for PLLA and PLLB */
kenjiArai 0:47b9bfa03730 988 /* CLK0 Control: 8mA drive, Multisynth 0 as CLK0 source, Clock not inverted,
kenjiArai 0:47b9bfa03730 989 Source = PLLA, Multisynth 0 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 990 { 16, 0x4F },
kenjiArai 0:47b9bfa03730 991 /* CLK1 Control: 8mA drive, Multisynth 1 as CLK1 source, Clock not inverted,
kenjiArai 0:47b9bfa03730 992 Source = PLLA, Multisynth 1 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 993 { 17, 0x4F },
kenjiArai 0:47b9bfa03730 994 /* CLK2 Control: 8mA drive, Multisynth 2 as CLK2 source, Clock not inverted,
kenjiArai 0:47b9bfa03730 995 Source = PLLB, Multisynth 2 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 996 { 18, 0x6F },
kenjiArai 0:47b9bfa03730 997 { 19, 0x80 }, /* CLK3 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 998 { 20, 0x80 }, /* CLK4 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 999 { 21, 0x80 }, /* CLK5 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1000 { 22, 0x80 }, /* CLK6 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1001 { 23, 0x80 }, /* CLK7 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1002 { 24, 0x00 }, /* Clock disable state 0..3 (low when disabled) */
kenjiArai 0:47b9bfa03730 1003 { 25, 0x00 }, /* Clock disable state 4..7 (low when disabled) */
kenjiArai 0:47b9bfa03730 1004 /* PLL_A Setup */
kenjiArai 0:47b9bfa03730 1005 { 26, 0x00 }, { 27, 0x05 }, { 28, 0x00 }, { 29, 0x0C },
kenjiArai 0:47b9bfa03730 1006 { 30, 0x66 }, { 31, 0x00 }, { 32, 0x00 }, { 33, 0x02 },
kenjiArai 0:47b9bfa03730 1007 /* PLL_B Setup */
kenjiArai 0:47b9bfa03730 1008 { 34, 0x02 }, { 35, 0x71 }, { 36, 0x00 }, { 37, 0x0C },
kenjiArai 0:47b9bfa03730 1009 { 38, 0x1A }, { 39, 0x00 }, { 40, 0x00 }, { 41, 0x86 },
kenjiArai 0:47b9bfa03730 1010 /* Multisynth Setup */
kenjiArai 0:47b9bfa03730 1011 { 42, 0x00 }, { 43, 0x01 }, { 44, 0x00 }, { 45, 0x01 },
kenjiArai 0:47b9bfa03730 1012 { 46, 0x00 }, { 47, 0x00 }, { 48, 0x00 }, { 49, 0x00 },
kenjiArai 0:47b9bfa03730 1013 { 50, 0x00 }, { 51, 0x01 }, { 52, 0x00 }, { 53, 0x1C },
kenjiArai 0:47b9bfa03730 1014 { 54, 0x00 }, { 55, 0x00 }, { 56, 0x00 }, { 57, 0x00 },
kenjiArai 0:47b9bfa03730 1015 { 58, 0x00 }, { 59, 0x01 }, { 60, 0x00 }, { 61, 0x18 },
kenjiArai 0:47b9bfa03730 1016 { 62, 0x00 }, { 63, 0x00 }, { 64, 0x00 }, { 65, 0x00 },
kenjiArai 0:47b9bfa03730 1017 { 66, 0x00 }, { 67, 0x00 }, { 68, 0x00 }, { 69, 0x00 },
kenjiArai 0:47b9bfa03730 1018 { 70, 0x00 }, { 71, 0x00 }, { 72, 0x00 }, { 73, 0x00 },
kenjiArai 0:47b9bfa03730 1019 { 74, 0x00 }, { 75, 0x00 }, { 76, 0x00 }, { 77, 0x00 },
kenjiArai 0:47b9bfa03730 1020 { 78, 0x00 }, { 79, 0x00 }, { 80, 0x00 }, { 81, 0x00 },
kenjiArai 0:47b9bfa03730 1021 { 82, 0x00 }, { 83, 0x00 }, { 84, 0x00 }, { 85, 0x00 },
kenjiArai 0:47b9bfa03730 1022 { 86, 0x00 }, { 87, 0x00 }, { 88, 0x00 }, { 89, 0x00 },
kenjiArai 0:47b9bfa03730 1023 { 90, 0x00 }, { 91, 0x00 }, { 92, 0x00 },
kenjiArai 0:47b9bfa03730 1024 /* Misc Config Register */
kenjiArai 0:47b9bfa03730 1025 { 149, 0x00 }, { 150, 0x00 }, { 151, 0x00 }, { 152, 0x00 },
kenjiArai 0:47b9bfa03730 1026 { 153, 0x00 }, { 154, 0x00 }, { 155, 0x00 }, { 156, 0x00 },
kenjiArai 0:47b9bfa03730 1027 { 157, 0x00 }, { 158, 0x00 }, { 159, 0x00 }, { 160, 0x00 },
kenjiArai 0:47b9bfa03730 1028 { 161, 0x00 }, { 162, 0x00 }, { 163, 0x00 }, { 164, 0x00 },
kenjiArai 0:47b9bfa03730 1029 { 165, 0x00 }, { 166, 0x00 }, { 167, 0x00 }, { 168, 0x00 },
kenjiArai 0:47b9bfa03730 1030 { 169, 0x00 }, { 170, 0x00 }
kenjiArai 0:47b9bfa03730 1031 };
kenjiArai 0:47b9bfa03730 1032
kenjiArai 0:47b9bfa03730 1033 void SI5351A::debug_example_clock(void)
kenjiArai 0:47b9bfa03730 1034 {
kenjiArai 0:47b9bfa03730 1035 /* Disable all outputs setting CLKx_DIS high */
kenjiArai 0:47b9bfa03730 1036 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
kenjiArai 0:47b9bfa03730 1037 /* Writes configuration data to device using the register map contents
kenjiArai 0:47b9bfa03730 1038 generated by ClockBuilder Desktop (registers 15-92 + 149-170) */
kenjiArai 0:47b9bfa03730 1039 for (uint16_t i = 0; i < sizeof(m_si5351_regs_15to92_149to170)/2; i++){
kenjiArai 0:47b9bfa03730 1040 si5351_write(m_si5351_regs_15to92_149to170[i][0],
kenjiArai 0:47b9bfa03730 1041 m_si5351_regs_15to92_149to170[i][1]);
kenjiArai 0:47b9bfa03730 1042 }
kenjiArai 0:47b9bfa03730 1043 /* Apply soft reset */
kenjiArai 0:47b9bfa03730 1044 si5351_write(SI5351_REG_177_PLL_RESET, 0xac);
kenjiArai 0:47b9bfa03730 1045 /* Enabled desired outputs (see Register 3) */
kenjiArai 0:47b9bfa03730 1046 si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
kenjiArai 0:47b9bfa03730 1047 printf("Please check following output\r\n");
kenjiArai 0:47b9bfa03730 1048 printf("CLK0: 120.00MHz, CLK1: 12.00MHz, CLK2: 13.56MHz\r\n");
kenjiArai 0:47b9bfa03730 1049 }
kenjiArai 0:47b9bfa03730 1050
kenjiArai 0:47b9bfa03730 1051 //---------------------------------------------------------------------------------------------------------------------
kenjiArai 0:47b9bfa03730 1052 // Original & reference files
kenjiArai 0:47b9bfa03730 1053 //---------------------------------------------------------------------------------------------------------------------
kenjiArai 0:47b9bfa03730 1054 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
kenjiArai 0:47b9bfa03730 1055 // Adafruit_SI5351.cpp
kenjiArai 0:47b9bfa03730 1056 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
kenjiArai 0:47b9bfa03730 1057 #if 0
kenjiArai 0:47b9bfa03730 1058 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1059 /*!
kenjiArai 0:47b9bfa03730 1060 @file Adafruit_SI5351.cpp
kenjiArai 0:47b9bfa03730 1061 @author K. Townsend (Adafruit Industries)
kenjiArai 0:47b9bfa03730 1062
kenjiArai 0:47b9bfa03730 1063 @brief Driver for the SI5351 160MHz Clock Gen
kenjiArai 0:47b9bfa03730 1064
kenjiArai 0:47b9bfa03730 1065 @section REFERENCES
kenjiArai 0:47b9bfa03730 1066
kenjiArai 0:47b9bfa03730 1067 Si5351A/B/C Datasheet:
kenjiArai 0:47b9bfa03730 1068 http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf
kenjiArai 0:47b9bfa03730 1069
kenjiArai 0:47b9bfa03730 1070 Manually Generating an Si5351 Register Map:
kenjiArai 0:47b9bfa03730 1071 http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf
kenjiArai 0:47b9bfa03730 1072
kenjiArai 0:47b9bfa03730 1073 @section LICENSE
kenjiArai 0:47b9bfa03730 1074
kenjiArai 0:47b9bfa03730 1075 Software License Agreement (BSD License)
kenjiArai 0:47b9bfa03730 1076
kenjiArai 0:47b9bfa03730 1077 Copyright (c) 2014, Adafruit Industries
kenjiArai 0:47b9bfa03730 1078 All rights reserved.
kenjiArai 0:47b9bfa03730 1079
kenjiArai 0:47b9bfa03730 1080 Redistribution and use in source and binary forms, with or without
kenjiArai 0:47b9bfa03730 1081 modification, are permitted provided that the following conditions are met:
kenjiArai 0:47b9bfa03730 1082 1. Redistributions of source code must retain the above copyright
kenjiArai 0:47b9bfa03730 1083 notice, this list of conditions and the following disclaimer.
kenjiArai 0:47b9bfa03730 1084 2. Redistributions in binary form must reproduce the above copyright
kenjiArai 0:47b9bfa03730 1085 notice, this list of conditions and the following disclaimer in the
kenjiArai 0:47b9bfa03730 1086 documentation and/or other materials provided with the distribution.
kenjiArai 0:47b9bfa03730 1087 3. Neither the name of the copyright holders nor the
kenjiArai 0:47b9bfa03730 1088 names of its contributors may be used to endorse or promote products
kenjiArai 0:47b9bfa03730 1089 derived from this software without specific prior written permission.
kenjiArai 0:47b9bfa03730 1090
kenjiArai 0:47b9bfa03730 1091 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
kenjiArai 0:47b9bfa03730 1092 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
kenjiArai 0:47b9bfa03730 1093 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
kenjiArai 0:47b9bfa03730 1094 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
kenjiArai 0:47b9bfa03730 1095 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
kenjiArai 0:47b9bfa03730 1096 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
kenjiArai 0:47b9bfa03730 1097 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
kenjiArai 0:47b9bfa03730 1098 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
kenjiArai 0:47b9bfa03730 1099 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
kenjiArai 0:47b9bfa03730 1100 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kenjiArai 0:47b9bfa03730 1101 */
kenjiArai 0:47b9bfa03730 1102 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1103 #if defined(__AVR__)
kenjiArai 0:47b9bfa03730 1104 #include <avr/pgmspace.h>
kenjiArai 0:47b9bfa03730 1105 #include <util/delay.h>
kenjiArai 0:47b9bfa03730 1106 #else
kenjiArai 0:47b9bfa03730 1107 #include "pgmspace.h"
kenjiArai 0:47b9bfa03730 1108 #endif
kenjiArai 0:47b9bfa03730 1109 #include <stdlib.h>
kenjiArai 0:47b9bfa03730 1110
kenjiArai 0:47b9bfa03730 1111 #include <Adafruit_SI5351.h>
kenjiArai 0:47b9bfa03730 1112
kenjiArai 0:47b9bfa03730 1113 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1114 /*!
kenjiArai 0:47b9bfa03730 1115 Constructor
kenjiArai 0:47b9bfa03730 1116 */
kenjiArai 0:47b9bfa03730 1117 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1118 Adafruit_SI5351::Adafruit_SI5351(void)
kenjiArai 0:47b9bfa03730 1119 {
kenjiArai 0:47b9bfa03730 1120 m_si5351Config.initialised = false;
kenjiArai 0:47b9bfa03730 1121 m_si5351Config.crystalFreq = SI5351_CRYSTAL_FREQ_25MHZ;
kenjiArai 0:47b9bfa03730 1122 m_si5351Config.crystalLoad = SI5351_CRYSTAL_LOAD_10PF;
kenjiArai 0:47b9bfa03730 1123 m_si5351Config.crystalPPM = 30;
kenjiArai 0:47b9bfa03730 1124 m_si5351Config.plla_configured = false;
kenjiArai 0:47b9bfa03730 1125 m_si5351Config.plla_freq = 0;
kenjiArai 0:47b9bfa03730 1126 m_si5351Config.pllb_configured = false;
kenjiArai 0:47b9bfa03730 1127 m_si5351Config.pllb_freq = 0;
kenjiArai 0:47b9bfa03730 1128 }
kenjiArai 0:47b9bfa03730 1129
kenjiArai 0:47b9bfa03730 1130 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1131 /*!
kenjiArai 0:47b9bfa03730 1132 Initializes I2C and configures the breakout (call this function before
kenjiArai 0:47b9bfa03730 1133 doing anything else)
kenjiArai 0:47b9bfa03730 1134 */
kenjiArai 0:47b9bfa03730 1135 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1136 err_t Adafruit_SI5351::begin(void)
kenjiArai 0:47b9bfa03730 1137 {
kenjiArai 0:47b9bfa03730 1138 /* Initialise I2C */
kenjiArai 0:47b9bfa03730 1139 Wire.begin();
kenjiArai 0:47b9bfa03730 1140
kenjiArai 0:47b9bfa03730 1141 /* ToDo: Make sure we're actually connected */
kenjiArai 0:47b9bfa03730 1142
kenjiArai 0:47b9bfa03730 1143 /* Disable all outputs setting CLKx_DIS high */
kenjiArai 0:47b9bfa03730 1144 ASSERT_STATUS(write8(SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL, 0xFF));
kenjiArai 0:47b9bfa03730 1145
kenjiArai 0:47b9bfa03730 1146 /* Power down all output drivers */
kenjiArai 0:47b9bfa03730 1147 ASSERT_STATUS(write8(SI5351_REGISTER_16_CLK0_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1148 ASSERT_STATUS(write8(SI5351_REGISTER_17_CLK1_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1149 ASSERT_STATUS(write8(SI5351_REGISTER_18_CLK2_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1150 ASSERT_STATUS(write8(SI5351_REGISTER_19_CLK3_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1151 ASSERT_STATUS(write8(SI5351_REGISTER_20_CLK4_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1152 ASSERT_STATUS(write8(SI5351_REGISTER_21_CLK5_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1153 ASSERT_STATUS(write8(SI5351_REGISTER_22_CLK6_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1154 ASSERT_STATUS(write8(SI5351_REGISTER_23_CLK7_CONTROL, 0x80));
kenjiArai 0:47b9bfa03730 1155
kenjiArai 0:47b9bfa03730 1156 /* Set the load capacitance for the XTAL */
kenjiArai 0:47b9bfa03730 1157 ASSERT_STATUS(write8(SI5351_REGISTER_183_CRYSTAL_INTERNAL_LOAD_CAPACITANCE,
kenjiArai 0:47b9bfa03730 1158 m_si5351Config.crystalLoad));
kenjiArai 0:47b9bfa03730 1159
kenjiArai 0:47b9bfa03730 1160 /* Set interrupt masks as required (see Register 2 description in AN619).
kenjiArai 0:47b9bfa03730 1161 By default, ClockBuilder Desktop sets this register to 0x18.
kenjiArai 0:47b9bfa03730 1162 Note that the least significant nibble must remain 0x8, but the most
kenjiArai 0:47b9bfa03730 1163 significant nibble may be modified to suit your needs. */
kenjiArai 0:47b9bfa03730 1164
kenjiArai 0:47b9bfa03730 1165 /* Reset the PLL config fields just in case we call init again */
kenjiArai 0:47b9bfa03730 1166 m_si5351Config.plla_configured = false;
kenjiArai 0:47b9bfa03730 1167 m_si5351Config.plla_freq = 0;
kenjiArai 0:47b9bfa03730 1168 m_si5351Config.pllb_configured = false;
kenjiArai 0:47b9bfa03730 1169 m_si5351Config.pllb_freq = 0;
kenjiArai 0:47b9bfa03730 1170
kenjiArai 0:47b9bfa03730 1171 /* All done! */
kenjiArai 0:47b9bfa03730 1172 m_si5351Config.initialised = true;
kenjiArai 0:47b9bfa03730 1173
kenjiArai 0:47b9bfa03730 1174 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1175 }
kenjiArai 0:47b9bfa03730 1176
kenjiArai 0:47b9bfa03730 1177 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1178 /*!
kenjiArai 0:47b9bfa03730 1179 @brief Configures the Si5351 with config settings generated in
kenjiArai 0:47b9bfa03730 1180 ClockBuilder. You can use this function to make sure that
kenjiArai 0:47b9bfa03730 1181 your HW is properly configure and that there are no problems
kenjiArai 0:47b9bfa03730 1182 with the board itself.
kenjiArai 0:47b9bfa03730 1183
kenjiArai 0:47b9bfa03730 1184 Running this function should provide the following output:
kenjiArai 0:47b9bfa03730 1185 * Channel 0: 120.00 MHz
kenjiArai 0:47b9bfa03730 1186 * Channel 1: 12.00 MHz
kenjiArai 0:47b9bfa03730 1187 * Channel 2: 13.56 MHz
kenjiArai 0:47b9bfa03730 1188
kenjiArai 0:47b9bfa03730 1189 @note This will overwrite all of the config registers!
kenjiArai 0:47b9bfa03730 1190 */
kenjiArai 0:47b9bfa03730 1191 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1192 err_t Adafruit_SI5351::setClockBuilderData(void)
kenjiArai 0:47b9bfa03730 1193 {
kenjiArai 0:47b9bfa03730 1194 uint16_t i = 0;
kenjiArai 0:47b9bfa03730 1195
kenjiArai 0:47b9bfa03730 1196 /* Make sure we've called init first */
kenjiArai 0:47b9bfa03730 1197 ASSERT(m_si5351Config.initialised, ERROR_DEVICENOTINITIALISED);
kenjiArai 0:47b9bfa03730 1198
kenjiArai 0:47b9bfa03730 1199 /* Disable all outputs setting CLKx_DIS high */
kenjiArai 0:47b9bfa03730 1200 ASSERT_STATUS(write8(SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL, 0xFF));
kenjiArai 0:47b9bfa03730 1201
kenjiArai 0:47b9bfa03730 1202 /* Writes configuration data to device using the register map contents
kenjiArai 0:47b9bfa03730 1203 generated by ClockBuilder Desktop (registers 15-92 + 149-170) */
kenjiArai 0:47b9bfa03730 1204 for (i=0; i<sizeof(m_si5351_regs_15to92_149to170)/2; i++)
kenjiArai 0:47b9bfa03730 1205 {
kenjiArai 0:47b9bfa03730 1206 ASSERT_STATUS(write8( m_si5351_regs_15to92_149to170[i][0],
kenjiArai 0:47b9bfa03730 1207 m_si5351_regs_15to92_149to170[i][1] ));
kenjiArai 0:47b9bfa03730 1208 }
kenjiArai 0:47b9bfa03730 1209
kenjiArai 0:47b9bfa03730 1210 /* Apply soft reset */
kenjiArai 0:47b9bfa03730 1211 ASSERT_STATUS(write8(SI5351_REGISTER_177_PLL_RESET, 0xAC));
kenjiArai 0:47b9bfa03730 1212
kenjiArai 0:47b9bfa03730 1213 /* Enabled desired outputs (see Register 3) */
kenjiArai 0:47b9bfa03730 1214 ASSERT_STATUS(write8(SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL, 0x00));
kenjiArai 0:47b9bfa03730 1215
kenjiArai 0:47b9bfa03730 1216 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1217 }
kenjiArai 0:47b9bfa03730 1218
kenjiArai 0:47b9bfa03730 1219 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1220 /*!
kenjiArai 0:47b9bfa03730 1221 @brief Sets the multiplier for the specified PLL using integer values
kenjiArai 0:47b9bfa03730 1222
kenjiArai 0:47b9bfa03730 1223 @param pll The PLL to configure, which must be one of the following:
kenjiArai 0:47b9bfa03730 1224 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 1225 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 1226 @param mult The PLL integer multiplier (must be between 15 and 90)
kenjiArai 0:47b9bfa03730 1227 */
kenjiArai 0:47b9bfa03730 1228 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1229 err_t Adafruit_SI5351::setupPLLInt(si5351PLL_t pll, uint8_t mult)
kenjiArai 0:47b9bfa03730 1230 {
kenjiArai 0:47b9bfa03730 1231 return setupPLL(pll, mult, 0, 1);
kenjiArai 0:47b9bfa03730 1232 }
kenjiArai 0:47b9bfa03730 1233
kenjiArai 0:47b9bfa03730 1234 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1235 /*!
kenjiArai 0:47b9bfa03730 1236 @brief Sets the multiplier for the specified PLL
kenjiArai 0:47b9bfa03730 1237
kenjiArai 0:47b9bfa03730 1238 @param pll The PLL to configure, which must be one of the following:
kenjiArai 0:47b9bfa03730 1239 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 1240 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 1241 @param mult The PLL integer multiplier (must be between 15 and 90)
kenjiArai 0:47b9bfa03730 1242 @param num The 20-bit numerator for fractional output (0..1,048,575).
kenjiArai 0:47b9bfa03730 1243 Set this to '0' for integer output.
kenjiArai 0:47b9bfa03730 1244 @param denom The 20-bit denominator for fractional output (1..1,048,575).
kenjiArai 0:47b9bfa03730 1245 Set this to '1' or higher to avoid divider by zero errors.
kenjiArai 0:47b9bfa03730 1246
kenjiArai 0:47b9bfa03730 1247 @section PLL Configuration
kenjiArai 0:47b9bfa03730 1248
kenjiArai 0:47b9bfa03730 1249 fVCO is the PLL output, and must be between 600..900MHz, where:
kenjiArai 0:47b9bfa03730 1250
kenjiArai 0:47b9bfa03730 1251 fVCO = fXTAL * (a+(b/c))
kenjiArai 0:47b9bfa03730 1252
kenjiArai 0:47b9bfa03730 1253 fXTAL = the crystal input frequency
kenjiArai 0:47b9bfa03730 1254 a = an integer between 15 and 90
kenjiArai 0:47b9bfa03730 1255 b = the fractional numerator (0..1,048,575)
kenjiArai 0:47b9bfa03730 1256 c = the fractional denominator (1..1,048,575)
kenjiArai 0:47b9bfa03730 1257
kenjiArai 0:47b9bfa03730 1258 NOTE: Try to use integers whenever possible to avoid clock jitter
kenjiArai 0:47b9bfa03730 1259 (only use the a part, setting b to '0' and c to '1').
kenjiArai 0:47b9bfa03730 1260
kenjiArai 0:47b9bfa03730 1261 See: http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf
kenjiArai 0:47b9bfa03730 1262 */
kenjiArai 0:47b9bfa03730 1263 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1264 err_t Adafruit_SI5351::setupPLL(si5351PLL_t pll,
kenjiArai 0:47b9bfa03730 1265 uint8_t mult,
kenjiArai 0:47b9bfa03730 1266 uint32_t num,
kenjiArai 0:47b9bfa03730 1267 uint32_t denom)
kenjiArai 0:47b9bfa03730 1268 {
kenjiArai 0:47b9bfa03730 1269 uint32_t P1; /* PLL config register P1 */
kenjiArai 0:47b9bfa03730 1270 uint32_t P2; /* PLL config register P2 */
kenjiArai 0:47b9bfa03730 1271 uint32_t P3; /* PLL config register P3 */
kenjiArai 0:47b9bfa03730 1272
kenjiArai 0:47b9bfa03730 1273 /* Basic validation */
kenjiArai 0:47b9bfa03730 1274 ASSERT( m_si5351Config.initialised, ERROR_DEVICENOTINITIALISED );
kenjiArai 0:47b9bfa03730 1275 ASSERT( (mult > 14) && (mult < 91), ERROR_INVALIDPARAMETER ); /* mult = 15..90 */
kenjiArai 0:47b9bfa03730 1276 ASSERT( denom > 0, ERROR_INVALIDPARAMETER ); /* Avoid divide by zero */
kenjiArai 0:47b9bfa03730 1277 ASSERT( num <= 0xFFFFF, ERROR_INVALIDPARAMETER ); /* 20-bit limit */
kenjiArai 0:47b9bfa03730 1278 ASSERT( denom <= 0xFFFFF, ERROR_INVALIDPARAMETER ); /* 20-bit limit */
kenjiArai 0:47b9bfa03730 1279
kenjiArai 0:47b9bfa03730 1280 /* Feedback Multisynth Divider Equation
kenjiArai 0:47b9bfa03730 1281 *
kenjiArai 0:47b9bfa03730 1282 * where: a = mult, b = num and c = denom
kenjiArai 0:47b9bfa03730 1283 *
kenjiArai 0:47b9bfa03730 1284 * P1 register is an 18-bit value using following formula:
kenjiArai 0:47b9bfa03730 1285 *
kenjiArai 0:47b9bfa03730 1286 * P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512
kenjiArai 0:47b9bfa03730 1287 *
kenjiArai 0:47b9bfa03730 1288 * P2 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 1289 *
kenjiArai 0:47b9bfa03730 1290 * P2[19:0] = 128 * num - denom * floor(128*(num/denom))
kenjiArai 0:47b9bfa03730 1291 *
kenjiArai 0:47b9bfa03730 1292 * P3 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 1293 *
kenjiArai 0:47b9bfa03730 1294 * P3[19:0] = denom
kenjiArai 0:47b9bfa03730 1295 */
kenjiArai 0:47b9bfa03730 1296
kenjiArai 0:47b9bfa03730 1297 /* Set the main PLL config registers */
kenjiArai 0:47b9bfa03730 1298 if (num == 0)
kenjiArai 0:47b9bfa03730 1299 {
kenjiArai 0:47b9bfa03730 1300 /* Integer mode */
kenjiArai 0:47b9bfa03730 1301 P1 = 128 * mult - 512;
kenjiArai 0:47b9bfa03730 1302 P2 = num;
kenjiArai 0:47b9bfa03730 1303 P3 = denom;
kenjiArai 0:47b9bfa03730 1304 }
kenjiArai 0:47b9bfa03730 1305 else
kenjiArai 0:47b9bfa03730 1306 {
kenjiArai 0:47b9bfa03730 1307 /* Fractional mode */
kenjiArai 0:47b9bfa03730 1308 P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512);
kenjiArai 0:47b9bfa03730 1309 P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
kenjiArai 0:47b9bfa03730 1310 P3 = denom;
kenjiArai 0:47b9bfa03730 1311 }
kenjiArai 0:47b9bfa03730 1312
kenjiArai 0:47b9bfa03730 1313 /* Get the appropriate starting point for the PLL registers */
kenjiArai 0:47b9bfa03730 1314 uint8_t baseaddr = (pll == SI5351_PLL_A ? 26 : 34);
kenjiArai 0:47b9bfa03730 1315
kenjiArai 0:47b9bfa03730 1316 /* The datasheet is a nightmare of typos and inconsistencies here! */
kenjiArai 0:47b9bfa03730 1317 ASSERT_STATUS( write8( baseaddr, (P3 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1318 ASSERT_STATUS( write8( baseaddr+1, (P3 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1319 ASSERT_STATUS( write8( baseaddr+2, (P1 & 0x00030000) >> 16));
kenjiArai 0:47b9bfa03730 1320 ASSERT_STATUS( write8( baseaddr+3, (P1 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1321 ASSERT_STATUS( write8( baseaddr+4, (P1 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1322 ASSERT_STATUS( write8( baseaddr+5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16) ));
kenjiArai 0:47b9bfa03730 1323 ASSERT_STATUS( write8( baseaddr+6, (P2 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1324 ASSERT_STATUS( write8( baseaddr+7, (P2 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1325
kenjiArai 0:47b9bfa03730 1326 /* Reset both PLLs */
kenjiArai 0:47b9bfa03730 1327 ASSERT_STATUS( write8(SI5351_REGISTER_177_PLL_RESET, (1<<7) | (1<<5) ));
kenjiArai 0:47b9bfa03730 1328
kenjiArai 0:47b9bfa03730 1329 /* Store the frequency settings for use with the Multisynth helper */
kenjiArai 0:47b9bfa03730 1330 if (pll == SI5351_PLL_A)
kenjiArai 0:47b9bfa03730 1331 {
kenjiArai 0:47b9bfa03730 1332 float fvco = m_si5351Config.crystalFreq * (mult + ( (float)num / (float)denom ));
kenjiArai 0:47b9bfa03730 1333 m_si5351Config.plla_configured = true;
kenjiArai 0:47b9bfa03730 1334 m_si5351Config.plla_freq = (uint32_t)floor(fvco);
kenjiArai 0:47b9bfa03730 1335 }
kenjiArai 0:47b9bfa03730 1336 else
kenjiArai 0:47b9bfa03730 1337 {
kenjiArai 0:47b9bfa03730 1338 float fvco = m_si5351Config.crystalFreq * (mult + ( (float)num / (float)denom ));
kenjiArai 0:47b9bfa03730 1339 m_si5351Config.pllb_configured = true;
kenjiArai 0:47b9bfa03730 1340 m_si5351Config.pllb_freq = (uint32_t)floor(fvco);
kenjiArai 0:47b9bfa03730 1341 }
kenjiArai 0:47b9bfa03730 1342
kenjiArai 0:47b9bfa03730 1343 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1344 }
kenjiArai 0:47b9bfa03730 1345
kenjiArai 0:47b9bfa03730 1346 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1347 /*!
kenjiArai 0:47b9bfa03730 1348 @brief Configures the Multisynth divider using integer output.
kenjiArai 0:47b9bfa03730 1349
kenjiArai 0:47b9bfa03730 1350 @param output The output channel to use (0..2)
kenjiArai 0:47b9bfa03730 1351 @param pllSource The PLL input source to use, which must be one of:
kenjiArai 0:47b9bfa03730 1352 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 1353 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 1354 @param div The integer divider for the Multisynth output,
kenjiArai 0:47b9bfa03730 1355 which must be one of the following values:
kenjiArai 0:47b9bfa03730 1356 - SI5351_MULTISYNTH_DIV_4
kenjiArai 0:47b9bfa03730 1357 - SI5351_MULTISYNTH_DIV_6
kenjiArai 0:47b9bfa03730 1358 - SI5351_MULTISYNTH_DIV_8
kenjiArai 0:47b9bfa03730 1359 */
kenjiArai 0:47b9bfa03730 1360 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1361 err_t Adafruit_SI5351::setupMultisynthInt(uint8_t output,
kenjiArai 0:47b9bfa03730 1362 si5351PLL_t pllSource,
kenjiArai 0:47b9bfa03730 1363 si5351MultisynthDiv_t div)
kenjiArai 0:47b9bfa03730 1364 {
kenjiArai 0:47b9bfa03730 1365 return setupMultisynth(output, pllSource, div, 0, 1);
kenjiArai 0:47b9bfa03730 1366 }
kenjiArai 0:47b9bfa03730 1367
kenjiArai 0:47b9bfa03730 1368
kenjiArai 0:47b9bfa03730 1369 err_t Adafruit_SI5351::setupRdiv(uint8_t output, si5351RDiv_t div) {
kenjiArai 0:47b9bfa03730 1370 ASSERT( output < 3, ERROR_INVALIDPARAMETER); /* Channel range */
kenjiArai 0:47b9bfa03730 1371
kenjiArai 0:47b9bfa03730 1372 uint8_t Rreg, regval;
kenjiArai 0:47b9bfa03730 1373
kenjiArai 0:47b9bfa03730 1374 if (output == 0) Rreg = SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3;
kenjiArai 0:47b9bfa03730 1375 if (output == 1) Rreg = SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3;
kenjiArai 0:47b9bfa03730 1376 if (output == 2) Rreg = SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3;
kenjiArai 0:47b9bfa03730 1377
kenjiArai 0:47b9bfa03730 1378 read8(Rreg, &regval);
kenjiArai 0:47b9bfa03730 1379
kenjiArai 0:47b9bfa03730 1380 regval &= 0x0F;
kenjiArai 0:47b9bfa03730 1381 uint8_t divider = div;
kenjiArai 0:47b9bfa03730 1382 divider &= 0x07;
kenjiArai 0:47b9bfa03730 1383 divider <<= 4;
kenjiArai 0:47b9bfa03730 1384 regval |= divider;
kenjiArai 0:47b9bfa03730 1385 return write8(Rreg, regval);
kenjiArai 0:47b9bfa03730 1386 }
kenjiArai 0:47b9bfa03730 1387
kenjiArai 0:47b9bfa03730 1388 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1389 /*!
kenjiArai 0:47b9bfa03730 1390 @brief Configures the Multisynth divider, which determines the
kenjiArai 0:47b9bfa03730 1391 output clock frequency based on the specified PLL input.
kenjiArai 0:47b9bfa03730 1392
kenjiArai 0:47b9bfa03730 1393 @param output The output channel to use (0..2)
kenjiArai 0:47b9bfa03730 1394 @param pllSource The PLL input source to use, which must be one of:
kenjiArai 0:47b9bfa03730 1395 - SI5351_PLL_A
kenjiArai 0:47b9bfa03730 1396 - SI5351_PLL_B
kenjiArai 0:47b9bfa03730 1397 @param div The integer divider for the Multisynth output.
kenjiArai 0:47b9bfa03730 1398 If pure integer values are used, this value must
kenjiArai 0:47b9bfa03730 1399 be one of:
kenjiArai 0:47b9bfa03730 1400 - SI5351_MULTISYNTH_DIV_4
kenjiArai 0:47b9bfa03730 1401 - SI5351_MULTISYNTH_DIV_6
kenjiArai 0:47b9bfa03730 1402 - SI5351_MULTISYNTH_DIV_8
kenjiArai 0:47b9bfa03730 1403 If fractional output is used, this value must be
kenjiArai 0:47b9bfa03730 1404 between 8 and 900.
kenjiArai 0:47b9bfa03730 1405 @param num The 20-bit numerator for fractional output
kenjiArai 0:47b9bfa03730 1406 (0..1,048,575). Set this to '0' for integer output.
kenjiArai 0:47b9bfa03730 1407 @param denom The 20-bit denominator for fractional output
kenjiArai 0:47b9bfa03730 1408 (1..1,048,575). Set this to '1' or higher to
kenjiArai 0:47b9bfa03730 1409 avoid divide by zero errors.
kenjiArai 0:47b9bfa03730 1410
kenjiArai 0:47b9bfa03730 1411 @section Output Clock Configuration
kenjiArai 0:47b9bfa03730 1412
kenjiArai 0:47b9bfa03730 1413 The multisynth dividers are applied to the specified PLL output,
kenjiArai 0:47b9bfa03730 1414 and are used to reduce the PLL output to a valid range (500kHz
kenjiArai 0:47b9bfa03730 1415 to 160MHz). The relationship can be seen in this formula, where
kenjiArai 0:47b9bfa03730 1416 fVCO is the PLL output frequency and MSx is the multisynth
kenjiArai 0:47b9bfa03730 1417 divider:
kenjiArai 0:47b9bfa03730 1418
kenjiArai 0:47b9bfa03730 1419 fOUT = fVCO / MSx
kenjiArai 0:47b9bfa03730 1420
kenjiArai 0:47b9bfa03730 1421 Valid multisynth dividers are 4, 6, or 8 when using integers,
kenjiArai 0:47b9bfa03730 1422 or any fractional values between 8 + 1/1,048,575 and 900 + 0/1
kenjiArai 0:47b9bfa03730 1423
kenjiArai 0:47b9bfa03730 1424 The following formula is used for the fractional mode divider:
kenjiArai 0:47b9bfa03730 1425
kenjiArai 0:47b9bfa03730 1426 a + b / c
kenjiArai 0:47b9bfa03730 1427
kenjiArai 0:47b9bfa03730 1428 a = The integer value, which must be 4, 6 or 8 in integer mode (MSx_INT=1)
kenjiArai 0:47b9bfa03730 1429 or 8..900 in fractional mode (MSx_INT=0).
kenjiArai 0:47b9bfa03730 1430 b = The fractional numerator (0..1,048,575)
kenjiArai 0:47b9bfa03730 1431 c = The fractional denominator (1..1,048,575)
kenjiArai 0:47b9bfa03730 1432
kenjiArai 0:47b9bfa03730 1433 @note Try to use integers whenever possible to avoid clock jitter
kenjiArai 0:47b9bfa03730 1434
kenjiArai 0:47b9bfa03730 1435 @note For output frequencies > 150MHz, you must set the divider
kenjiArai 0:47b9bfa03730 1436 to 4 and adjust to PLL to generate the frequency (for example
kenjiArai 0:47b9bfa03730 1437 a PLL of 640 to generate a 160MHz output clock). This is not
kenjiArai 0:47b9bfa03730 1438 yet supported in the driver, which limits frequencies to
kenjiArai 0:47b9bfa03730 1439 500kHz .. 150MHz.
kenjiArai 0:47b9bfa03730 1440
kenjiArai 0:47b9bfa03730 1441 @note For frequencies below 500kHz (down to 8kHz) Rx_DIV must be
kenjiArai 0:47b9bfa03730 1442 used, but this isn't currently implemented in the driver.
kenjiArai 0:47b9bfa03730 1443 */
kenjiArai 0:47b9bfa03730 1444 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1445 err_t Adafruit_SI5351::setupMultisynth(uint8_t output,
kenjiArai 0:47b9bfa03730 1446 si5351PLL_t pllSource,
kenjiArai 0:47b9bfa03730 1447 uint32_t div,
kenjiArai 0:47b9bfa03730 1448 uint32_t num,
kenjiArai 0:47b9bfa03730 1449 uint32_t denom)
kenjiArai 0:47b9bfa03730 1450 {
kenjiArai 0:47b9bfa03730 1451 uint32_t P1; /* Multisynth config register P1 */
kenjiArai 0:47b9bfa03730 1452 uint32_t P2; /* Multisynth config register P2 */
kenjiArai 0:47b9bfa03730 1453 uint32_t P3; /* Multisynth config register P3 */
kenjiArai 0:47b9bfa03730 1454
kenjiArai 0:47b9bfa03730 1455 /* Basic validation */
kenjiArai 0:47b9bfa03730 1456 ASSERT( m_si5351Config.initialised, ERROR_DEVICENOTINITIALISED);
kenjiArai 0:47b9bfa03730 1457 ASSERT( output < 3, ERROR_INVALIDPARAMETER); /* Channel range */
kenjiArai 0:47b9bfa03730 1458 ASSERT( div > 3, ERROR_INVALIDPARAMETER); /* Divider integer value */
kenjiArai 0:47b9bfa03730 1459 ASSERT( div < 901, ERROR_INVALIDPARAMETER); /* Divider integer value */
kenjiArai 0:47b9bfa03730 1460 ASSERT( denom > 0, ERROR_INVALIDPARAMETER ); /* Avoid divide by zero */
kenjiArai 0:47b9bfa03730 1461 ASSERT( num <= 0xFFFFF, ERROR_INVALIDPARAMETER ); /* 20-bit limit */
kenjiArai 0:47b9bfa03730 1462 ASSERT( denom <= 0xFFFFF, ERROR_INVALIDPARAMETER ); /* 20-bit limit */
kenjiArai 0:47b9bfa03730 1463
kenjiArai 0:47b9bfa03730 1464 /* Make sure the requested PLL has been initialised */
kenjiArai 0:47b9bfa03730 1465 if (pllSource == SI5351_PLL_A)
kenjiArai 0:47b9bfa03730 1466 {
kenjiArai 0:47b9bfa03730 1467 ASSERT(m_si5351Config.plla_configured = true, ERROR_INVALIDPARAMETER);
kenjiArai 0:47b9bfa03730 1468 }
kenjiArai 0:47b9bfa03730 1469 else
kenjiArai 0:47b9bfa03730 1470 {
kenjiArai 0:47b9bfa03730 1471 ASSERT(m_si5351Config.pllb_configured = true, ERROR_INVALIDPARAMETER);
kenjiArai 0:47b9bfa03730 1472 }
kenjiArai 0:47b9bfa03730 1473
kenjiArai 0:47b9bfa03730 1474 /* Output Multisynth Divider Equations
kenjiArai 0:47b9bfa03730 1475 *
kenjiArai 0:47b9bfa03730 1476 * where: a = div, b = num and c = denom
kenjiArai 0:47b9bfa03730 1477 *
kenjiArai 0:47b9bfa03730 1478 * P1 register is an 18-bit value using following formula:
kenjiArai 0:47b9bfa03730 1479 *
kenjiArai 0:47b9bfa03730 1480 * P1[17:0] = 128 * a + floor(128*(b/c)) - 512
kenjiArai 0:47b9bfa03730 1481 *
kenjiArai 0:47b9bfa03730 1482 * P2 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 1483 *
kenjiArai 0:47b9bfa03730 1484 * P2[19:0] = 128 * b - c * floor(128*(b/c))
kenjiArai 0:47b9bfa03730 1485 *
kenjiArai 0:47b9bfa03730 1486 * P3 register is a 20-bit value using the following formula:
kenjiArai 0:47b9bfa03730 1487 *
kenjiArai 0:47b9bfa03730 1488 * P3[19:0] = c
kenjiArai 0:47b9bfa03730 1489 */
kenjiArai 0:47b9bfa03730 1490
kenjiArai 0:47b9bfa03730 1491 /* Set the main PLL config registers */
kenjiArai 0:47b9bfa03730 1492 if (num == 0)
kenjiArai 0:47b9bfa03730 1493 {
kenjiArai 0:47b9bfa03730 1494 /* Integer mode */
kenjiArai 0:47b9bfa03730 1495 P1 = 128 * div - 512;
kenjiArai 0:47b9bfa03730 1496 P2 = num;
kenjiArai 0:47b9bfa03730 1497 P3 = denom;
kenjiArai 0:47b9bfa03730 1498 }
kenjiArai 0:47b9bfa03730 1499 else
kenjiArai 0:47b9bfa03730 1500 {
kenjiArai 0:47b9bfa03730 1501 /* Fractional mode */
kenjiArai 0:47b9bfa03730 1502 P1 = (uint32_t)(128 * div + floor(128 * ((float)num/(float)denom)) - 512);
kenjiArai 0:47b9bfa03730 1503 P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
kenjiArai 0:47b9bfa03730 1504 P3 = denom;
kenjiArai 0:47b9bfa03730 1505 }
kenjiArai 0:47b9bfa03730 1506
kenjiArai 0:47b9bfa03730 1507 /* Get the appropriate starting point for the PLL registers */
kenjiArai 0:47b9bfa03730 1508 uint8_t baseaddr = 0;
kenjiArai 0:47b9bfa03730 1509 switch (output)
kenjiArai 0:47b9bfa03730 1510 {
kenjiArai 0:47b9bfa03730 1511 case 0:
kenjiArai 0:47b9bfa03730 1512 baseaddr = SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1;
kenjiArai 0:47b9bfa03730 1513 break;
kenjiArai 0:47b9bfa03730 1514 case 1:
kenjiArai 0:47b9bfa03730 1515 baseaddr = SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1;
kenjiArai 0:47b9bfa03730 1516 break;
kenjiArai 0:47b9bfa03730 1517 case 2:
kenjiArai 0:47b9bfa03730 1518 baseaddr = SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1;
kenjiArai 0:47b9bfa03730 1519 break;
kenjiArai 0:47b9bfa03730 1520 }
kenjiArai 0:47b9bfa03730 1521
kenjiArai 0:47b9bfa03730 1522 /* Set the MSx config registers */
kenjiArai 0:47b9bfa03730 1523 ASSERT_STATUS( write8( baseaddr, (P3 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1524 ASSERT_STATUS( write8( baseaddr+1, (P3 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1525 ASSERT_STATUS( write8( baseaddr+2, (P1 & 0x00030000) >> 16)); /* ToDo: Add DIVBY4 (>150MHz) and R0 support (<500kHz) later */
kenjiArai 0:47b9bfa03730 1526 ASSERT_STATUS( write8( baseaddr+3, (P1 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1527 ASSERT_STATUS( write8( baseaddr+4, (P1 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1528 ASSERT_STATUS( write8( baseaddr+5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16) ));
kenjiArai 0:47b9bfa03730 1529 ASSERT_STATUS( write8( baseaddr+6, (P2 & 0x0000FF00) >> 8));
kenjiArai 0:47b9bfa03730 1530 ASSERT_STATUS( write8( baseaddr+7, (P2 & 0x000000FF)));
kenjiArai 0:47b9bfa03730 1531
kenjiArai 0:47b9bfa03730 1532 /* Configure the clk control and enable the output */
kenjiArai 0:47b9bfa03730 1533 uint8_t clkControlReg = 0x0F; /* 8mA drive strength, MS0 as CLK0 source, Clock not inverted, powered up */
kenjiArai 0:47b9bfa03730 1534 if (pllSource == SI5351_PLL_B) clkControlReg |= (1 << 5); /* Uses PLLB */
kenjiArai 0:47b9bfa03730 1535 if (num == 0) clkControlReg |= (1 << 6); /* Integer mode */
kenjiArai 0:47b9bfa03730 1536 switch (output)
kenjiArai 0:47b9bfa03730 1537 {
kenjiArai 0:47b9bfa03730 1538 case 0:
kenjiArai 0:47b9bfa03730 1539 ASSERT_STATUS(write8(SI5351_REGISTER_16_CLK0_CONTROL, clkControlReg));
kenjiArai 0:47b9bfa03730 1540 break;
kenjiArai 0:47b9bfa03730 1541 case 1:
kenjiArai 0:47b9bfa03730 1542 ASSERT_STATUS(write8(SI5351_REGISTER_17_CLK1_CONTROL, clkControlReg));
kenjiArai 0:47b9bfa03730 1543 break;
kenjiArai 0:47b9bfa03730 1544 case 2:
kenjiArai 0:47b9bfa03730 1545 ASSERT_STATUS(write8(SI5351_REGISTER_18_CLK2_CONTROL, clkControlReg));
kenjiArai 0:47b9bfa03730 1546 break;
kenjiArai 0:47b9bfa03730 1547 }
kenjiArai 0:47b9bfa03730 1548
kenjiArai 0:47b9bfa03730 1549 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1550 }
kenjiArai 0:47b9bfa03730 1551
kenjiArai 0:47b9bfa03730 1552 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1553 /*!
kenjiArai 0:47b9bfa03730 1554 @brief Enables or disables all clock outputs
kenjiArai 0:47b9bfa03730 1555 */
kenjiArai 0:47b9bfa03730 1556 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1557 err_t Adafruit_SI5351::enableOutputs(bool enabled)
kenjiArai 0:47b9bfa03730 1558 {
kenjiArai 0:47b9bfa03730 1559 /* Make sure we've called init first */
kenjiArai 0:47b9bfa03730 1560 ASSERT(m_si5351Config.initialised, ERROR_DEVICENOTINITIALISED);
kenjiArai 0:47b9bfa03730 1561
kenjiArai 0:47b9bfa03730 1562 /* Enabled desired outputs (see Register 3) */
kenjiArai 0:47b9bfa03730 1563 ASSERT_STATUS(write8(SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL, enabled ? 0x00: 0xFF));
kenjiArai 0:47b9bfa03730 1564
kenjiArai 0:47b9bfa03730 1565 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1566 }
kenjiArai 0:47b9bfa03730 1567
kenjiArai 0:47b9bfa03730 1568 /* ---------------------------------------------------------------------- */
kenjiArai 0:47b9bfa03730 1569 /* PRUVATE FUNCTIONS */
kenjiArai 0:47b9bfa03730 1570 /* ---------------------------------------------------------------------- */
kenjiArai 0:47b9bfa03730 1571
kenjiArai 0:47b9bfa03730 1572 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1573 /*!
kenjiArai 0:47b9bfa03730 1574 @brief Writes a register and an 8 bit value over I2C
kenjiArai 0:47b9bfa03730 1575 */
kenjiArai 0:47b9bfa03730 1576 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1577 err_t Adafruit_SI5351::write8 (uint8_t reg, uint8_t value)
kenjiArai 0:47b9bfa03730 1578 {
kenjiArai 0:47b9bfa03730 1579 Wire.beginTransmission(SI5351_ADDRESS);
kenjiArai 0:47b9bfa03730 1580 #if ARDUINO >= 100
kenjiArai 0:47b9bfa03730 1581 Wire.write(reg);
kenjiArai 0:47b9bfa03730 1582 Wire.write(value & 0xFF);
kenjiArai 0:47b9bfa03730 1583 #else
kenjiArai 0:47b9bfa03730 1584 Wire.send(reg);
kenjiArai 0:47b9bfa03730 1585 Wire.send(value & 0xFF);
kenjiArai 0:47b9bfa03730 1586 #endif
kenjiArai 0:47b9bfa03730 1587 Wire.endTransmission();
kenjiArai 0:47b9bfa03730 1588
kenjiArai 0:47b9bfa03730 1589 // ToDo: Check for I2C errors
kenjiArai 0:47b9bfa03730 1590
kenjiArai 0:47b9bfa03730 1591 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1592 }
kenjiArai 0:47b9bfa03730 1593
kenjiArai 0:47b9bfa03730 1594 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1595 /*!
kenjiArai 0:47b9bfa03730 1596 @brief Reads an 8 bit value over I2C
kenjiArai 0:47b9bfa03730 1597 */
kenjiArai 0:47b9bfa03730 1598 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1599 err_t Adafruit_SI5351::read8(uint8_t reg, uint8_t *value)
kenjiArai 0:47b9bfa03730 1600 {
kenjiArai 0:47b9bfa03730 1601 Wire.beginTransmission(SI5351_ADDRESS);
kenjiArai 0:47b9bfa03730 1602 #if ARDUINO >= 100
kenjiArai 0:47b9bfa03730 1603 Wire.write(reg);
kenjiArai 0:47b9bfa03730 1604 #else
kenjiArai 0:47b9bfa03730 1605 Wire.send(reg);
kenjiArai 0:47b9bfa03730 1606 #endif
kenjiArai 0:47b9bfa03730 1607 Wire.endTransmission();
kenjiArai 0:47b9bfa03730 1608
kenjiArai 0:47b9bfa03730 1609 Wire.requestFrom(SI5351_ADDRESS, 1);
kenjiArai 0:47b9bfa03730 1610 #if ARDUINO >= 100
kenjiArai 0:47b9bfa03730 1611 *value = Wire.read();
kenjiArai 0:47b9bfa03730 1612 #else
kenjiArai 0:47b9bfa03730 1613 *value = Wire.read();
kenjiArai 0:47b9bfa03730 1614 #endif
kenjiArai 0:47b9bfa03730 1615
kenjiArai 0:47b9bfa03730 1616 // ToDo: Check for I2C errors
kenjiArai 0:47b9bfa03730 1617
kenjiArai 0:47b9bfa03730 1618 return ERROR_NONE;
kenjiArai 0:47b9bfa03730 1619 }
kenjiArai 0:47b9bfa03730 1620
kenjiArai 0:47b9bfa03730 1621 #endif
kenjiArai 0:47b9bfa03730 1622
kenjiArai 0:47b9bfa03730 1623 ////////////////////////////////////////////////////////////////////////////////
kenjiArai 0:47b9bfa03730 1624 // Adafruit_SI5351.h
kenjiArai 0:47b9bfa03730 1625 ////////////////////////////////////////////////////////////////////////////////
kenjiArai 0:47b9bfa03730 1626 #if 0
kenjiArai 0:47b9bfa03730 1627 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1628 /*!
kenjiArai 0:47b9bfa03730 1629 @file Adafruit_SI5351.h
kenjiArai 0:47b9bfa03730 1630 @author K. Townsend (Adafruit Industries)
kenjiArai 0:47b9bfa03730 1631
kenjiArai 0:47b9bfa03730 1632 @section LICENSE
kenjiArai 0:47b9bfa03730 1633
kenjiArai 0:47b9bfa03730 1634 Software License Agreement (BSD License)
kenjiArai 0:47b9bfa03730 1635
kenjiArai 0:47b9bfa03730 1636 Copyright (c) 2014, Adafruit Industries
kenjiArai 0:47b9bfa03730 1637 All rights reserved.
kenjiArai 0:47b9bfa03730 1638
kenjiArai 0:47b9bfa03730 1639 Redistribution and use in source and binary forms, with or without
kenjiArai 0:47b9bfa03730 1640 modification, are permitted provided that the following conditions are met:
kenjiArai 0:47b9bfa03730 1641 1. Redistributions of source code must retain the above copyright
kenjiArai 0:47b9bfa03730 1642 notice, this list of conditions and the following disclaimer.
kenjiArai 0:47b9bfa03730 1643 2. Redistributions in binary form must reproduce the above copyright
kenjiArai 0:47b9bfa03730 1644 notice, this list of conditions and the following disclaimer in the
kenjiArai 0:47b9bfa03730 1645 documentation and/or other materials provided with the distribution.
kenjiArai 0:47b9bfa03730 1646 3. Neither the name of the copyright holders nor the
kenjiArai 0:47b9bfa03730 1647 names of its contributors may be used to endorse or promote products
kenjiArai 0:47b9bfa03730 1648 derived from this software without specific prior written permission.
kenjiArai 0:47b9bfa03730 1649
kenjiArai 0:47b9bfa03730 1650 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
kenjiArai 0:47b9bfa03730 1651 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
kenjiArai 0:47b9bfa03730 1652 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
kenjiArai 0:47b9bfa03730 1653 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
kenjiArai 0:47b9bfa03730 1654 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
kenjiArai 0:47b9bfa03730 1655 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
kenjiArai 0:47b9bfa03730 1656 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
kenjiArai 0:47b9bfa03730 1657 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
kenjiArai 0:47b9bfa03730 1658 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
kenjiArai 0:47b9bfa03730 1659 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kenjiArai 0:47b9bfa03730 1660 */
kenjiArai 0:47b9bfa03730 1661 /**************************************************************************/
kenjiArai 0:47b9bfa03730 1662 #ifndef _SI5351_H_
kenjiArai 0:47b9bfa03730 1663 #define _SI5351_H_
kenjiArai 0:47b9bfa03730 1664
kenjiArai 0:47b9bfa03730 1665 #if ARDUINO >= 100
kenjiArai 0:47b9bfa03730 1666 #include <Arduino.h>
kenjiArai 0:47b9bfa03730 1667 #else
kenjiArai 0:47b9bfa03730 1668 #include <WProgram.h>
kenjiArai 0:47b9bfa03730 1669 #endif
kenjiArai 0:47b9bfa03730 1670 //#include <Adafruit_Sensor.h>
kenjiArai 0:47b9bfa03730 1671 #include <Wire.h>
kenjiArai 0:47b9bfa03730 1672
kenjiArai 0:47b9bfa03730 1673 #include "errors.h"
kenjiArai 0:47b9bfa03730 1674 #include "asserts.h"
kenjiArai 0:47b9bfa03730 1675
kenjiArai 0:47b9bfa03730 1676 #define SI5351_ADDRESS (0x60) // Assumes ADDR pin = low
kenjiArai 0:47b9bfa03730 1677 #define SI5351_READBIT (0x01)
kenjiArai 0:47b9bfa03730 1678
kenjiArai 0:47b9bfa03730 1679 /* Test setup from SI5351 ClockBuilder
kenjiArai 0:47b9bfa03730 1680 * -----------------------------------
kenjiArai 0:47b9bfa03730 1681 * XTAL: 25 MHz
kenjiArai 0:47b9bfa03730 1682 * Channel 0: 120.00 MHz
kenjiArai 0:47b9bfa03730 1683 * Channel 1: 12.00 MHz
kenjiArai 0:47b9bfa03730 1684 * Channel 2: 13.56 MHz
kenjiArai 0:47b9bfa03730 1685 */
kenjiArai 0:47b9bfa03730 1686 static const uint8_t m_si5351_regs_15to92_149to170[100][2] =
kenjiArai 0:47b9bfa03730 1687 {
kenjiArai 0:47b9bfa03730 1688 { 15, 0x00 }, /* Input source = crystal for PLLA and PLLB */
kenjiArai 0:47b9bfa03730 1689 { 16, 0x4F }, /* CLK0 Control: 8mA drive, Multisynth 0 as CLK0 source, Clock not inverted, Source = PLLA, Multisynth 0 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 1690 { 17, 0x4F }, /* CLK1 Control: 8mA drive, Multisynth 1 as CLK1 source, Clock not inverted, Source = PLLA, Multisynth 1 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 1691 { 18, 0x6F }, /* CLK2 Control: 8mA drive, Multisynth 2 as CLK2 source, Clock not inverted, Source = PLLB, Multisynth 2 in integer mode, clock powered up */
kenjiArai 0:47b9bfa03730 1692 { 19, 0x80 }, /* CLK3 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1693 { 20, 0x80 }, /* CLK4 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1694 { 21, 0x80 }, /* CLK5 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1695 { 22, 0x80 }, /* CLK6 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1696 { 23, 0x80 }, /* CLK7 Control: Not used ... clock powered down */
kenjiArai 0:47b9bfa03730 1697 { 24, 0x00 }, /* Clock disable state 0..3 (low when disabled) */
kenjiArai 0:47b9bfa03730 1698 { 25, 0x00 }, /* Clock disable state 4..7 (low when disabled) */
kenjiArai 0:47b9bfa03730 1699 /* PLL_A Setup */
kenjiArai 0:47b9bfa03730 1700 { 26, 0x00 },
kenjiArai 0:47b9bfa03730 1701 { 27, 0x05 },
kenjiArai 0:47b9bfa03730 1702 { 28, 0x00 },
kenjiArai 0:47b9bfa03730 1703 { 29, 0x0C },
kenjiArai 0:47b9bfa03730 1704 { 30, 0x66 },
kenjiArai 0:47b9bfa03730 1705 { 31, 0x00 },
kenjiArai 0:47b9bfa03730 1706 { 32, 0x00 },
kenjiArai 0:47b9bfa03730 1707 { 33, 0x02 },
kenjiArai 0:47b9bfa03730 1708 /* PLL_B Setup */
kenjiArai 0:47b9bfa03730 1709 { 34, 0x02 },
kenjiArai 0:47b9bfa03730 1710 { 35, 0x71 },
kenjiArai 0:47b9bfa03730 1711 { 36, 0x00 },
kenjiArai 0:47b9bfa03730 1712 { 37, 0x0C },
kenjiArai 0:47b9bfa03730 1713 { 38, 0x1A },
kenjiArai 0:47b9bfa03730 1714 { 39, 0x00 },
kenjiArai 0:47b9bfa03730 1715 { 40, 0x00 },
kenjiArai 0:47b9bfa03730 1716 { 41, 0x86 },
kenjiArai 0:47b9bfa03730 1717 /* Multisynth Setup */
kenjiArai 0:47b9bfa03730 1718 { 42, 0x00 },
kenjiArai 0:47b9bfa03730 1719 { 43, 0x01 },
kenjiArai 0:47b9bfa03730 1720 { 44, 0x00 },
kenjiArai 0:47b9bfa03730 1721 { 45, 0x01 },
kenjiArai 0:47b9bfa03730 1722 { 46, 0x00 },
kenjiArai 0:47b9bfa03730 1723 { 47, 0x00 },
kenjiArai 0:47b9bfa03730 1724 { 48, 0x00 },
kenjiArai 0:47b9bfa03730 1725 { 49, 0x00 },
kenjiArai 0:47b9bfa03730 1726 { 50, 0x00 },
kenjiArai 0:47b9bfa03730 1727 { 51, 0x01 },
kenjiArai 0:47b9bfa03730 1728 { 52, 0x00 },
kenjiArai 0:47b9bfa03730 1729 { 53, 0x1C },
kenjiArai 0:47b9bfa03730 1730 { 54, 0x00 },
kenjiArai 0:47b9bfa03730 1731 { 55, 0x00 },
kenjiArai 0:47b9bfa03730 1732 { 56, 0x00 },
kenjiArai 0:47b9bfa03730 1733 { 57, 0x00 },
kenjiArai 0:47b9bfa03730 1734 { 58, 0x00 },
kenjiArai 0:47b9bfa03730 1735 { 59, 0x01 },
kenjiArai 0:47b9bfa03730 1736 { 60, 0x00 },
kenjiArai 0:47b9bfa03730 1737 { 61, 0x18 },
kenjiArai 0:47b9bfa03730 1738 { 62, 0x00 },
kenjiArai 0:47b9bfa03730 1739 { 63, 0x00 },
kenjiArai 0:47b9bfa03730 1740 { 64, 0x00 },
kenjiArai 0:47b9bfa03730 1741 { 65, 0x00 },
kenjiArai 0:47b9bfa03730 1742 { 66, 0x00 },
kenjiArai 0:47b9bfa03730 1743 { 67, 0x00 },
kenjiArai 0:47b9bfa03730 1744 { 68, 0x00 },
kenjiArai 0:47b9bfa03730 1745 { 69, 0x00 },
kenjiArai 0:47b9bfa03730 1746 { 70, 0x00 },
kenjiArai 0:47b9bfa03730 1747 { 71, 0x00 },
kenjiArai 0:47b9bfa03730 1748 { 72, 0x00 },
kenjiArai 0:47b9bfa03730 1749 { 73, 0x00 },
kenjiArai 0:47b9bfa03730 1750 { 74, 0x00 },
kenjiArai 0:47b9bfa03730 1751 { 75, 0x00 },
kenjiArai 0:47b9bfa03730 1752 { 76, 0x00 },
kenjiArai 0:47b9bfa03730 1753 { 77, 0x00 },
kenjiArai 0:47b9bfa03730 1754 { 78, 0x00 },
kenjiArai 0:47b9bfa03730 1755 { 79, 0x00 },
kenjiArai 0:47b9bfa03730 1756 { 80, 0x00 },
kenjiArai 0:47b9bfa03730 1757 { 81, 0x00 },
kenjiArai 0:47b9bfa03730 1758 { 82, 0x00 },
kenjiArai 0:47b9bfa03730 1759 { 83, 0x00 },
kenjiArai 0:47b9bfa03730 1760 { 84, 0x00 },
kenjiArai 0:47b9bfa03730 1761 { 85, 0x00 },
kenjiArai 0:47b9bfa03730 1762 { 86, 0x00 },
kenjiArai 0:47b9bfa03730 1763 { 87, 0x00 },
kenjiArai 0:47b9bfa03730 1764 { 88, 0x00 },
kenjiArai 0:47b9bfa03730 1765 { 89, 0x00 },
kenjiArai 0:47b9bfa03730 1766 { 90, 0x00 },
kenjiArai 0:47b9bfa03730 1767 { 91, 0x00 },
kenjiArai 0:47b9bfa03730 1768 { 92, 0x00 },
kenjiArai 0:47b9bfa03730 1769 /* Misc Config Register */
kenjiArai 0:47b9bfa03730 1770 { 149, 0x00 },
kenjiArai 0:47b9bfa03730 1771 { 150, 0x00 },
kenjiArai 0:47b9bfa03730 1772 { 151, 0x00 },
kenjiArai 0:47b9bfa03730 1773 { 152, 0x00 },
kenjiArai 0:47b9bfa03730 1774 { 153, 0x00 },
kenjiArai 0:47b9bfa03730 1775 { 154, 0x00 },
kenjiArai 0:47b9bfa03730 1776 { 155, 0x00 },
kenjiArai 0:47b9bfa03730 1777 { 156, 0x00 },
kenjiArai 0:47b9bfa03730 1778 { 157, 0x00 },
kenjiArai 0:47b9bfa03730 1779 { 158, 0x00 },
kenjiArai 0:47b9bfa03730 1780 { 159, 0x00 },
kenjiArai 0:47b9bfa03730 1781 { 160, 0x00 },
kenjiArai 0:47b9bfa03730 1782 { 161, 0x00 },
kenjiArai 0:47b9bfa03730 1783 { 162, 0x00 },
kenjiArai 0:47b9bfa03730 1784 { 163, 0x00 },
kenjiArai 0:47b9bfa03730 1785 { 164, 0x00 },
kenjiArai 0:47b9bfa03730 1786 { 165, 0x00 },
kenjiArai 0:47b9bfa03730 1787 { 166, 0x00 },
kenjiArai 0:47b9bfa03730 1788 { 167, 0x00 },
kenjiArai 0:47b9bfa03730 1789 { 168, 0x00 },
kenjiArai 0:47b9bfa03730 1790 { 169, 0x00 },
kenjiArai 0:47b9bfa03730 1791 { 170, 0x00 }
kenjiArai 0:47b9bfa03730 1792 };
kenjiArai 0:47b9bfa03730 1793
kenjiArai 0:47b9bfa03730 1794 /* See http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf for registers 26..41 */
kenjiArai 0:47b9bfa03730 1795 enum
kenjiArai 0:47b9bfa03730 1796 {
kenjiArai 0:47b9bfa03730 1797 SI5351_REGISTER_0_DEVICE_STATUS = 0,
kenjiArai 0:47b9bfa03730 1798 SI5351_REGISTER_1_INTERRUPT_STATUS_STICKY = 1,
kenjiArai 0:47b9bfa03730 1799 SI5351_REGISTER_2_INTERRUPT_STATUS_MASK = 2,
kenjiArai 0:47b9bfa03730 1800 SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL = 3,
kenjiArai 0:47b9bfa03730 1801 SI5351_REGISTER_9_OEB_PIN_ENABLE_CONTROL = 9,
kenjiArai 0:47b9bfa03730 1802 SI5351_REGISTER_15_PLL_INPUT_SOURCE = 15,
kenjiArai 0:47b9bfa03730 1803 SI5351_REGISTER_16_CLK0_CONTROL = 16,
kenjiArai 0:47b9bfa03730 1804 SI5351_REGISTER_17_CLK1_CONTROL = 17,
kenjiArai 0:47b9bfa03730 1805 SI5351_REGISTER_18_CLK2_CONTROL = 18,
kenjiArai 0:47b9bfa03730 1806 SI5351_REGISTER_19_CLK3_CONTROL = 19,
kenjiArai 0:47b9bfa03730 1807 SI5351_REGISTER_20_CLK4_CONTROL = 20,
kenjiArai 0:47b9bfa03730 1808 SI5351_REGISTER_21_CLK5_CONTROL = 21,
kenjiArai 0:47b9bfa03730 1809 SI5351_REGISTER_22_CLK6_CONTROL = 22,
kenjiArai 0:47b9bfa03730 1810 SI5351_REGISTER_23_CLK7_CONTROL = 23,
kenjiArai 0:47b9bfa03730 1811 SI5351_REGISTER_24_CLK3_0_DISABLE_STATE = 24,
kenjiArai 0:47b9bfa03730 1812 SI5351_REGISTER_25_CLK7_4_DISABLE_STATE = 25,
kenjiArai 0:47b9bfa03730 1813 SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1 = 42,
kenjiArai 0:47b9bfa03730 1814 SI5351_REGISTER_43_MULTISYNTH0_PARAMETERS_2 = 43,
kenjiArai 0:47b9bfa03730 1815 SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3 = 44,
kenjiArai 0:47b9bfa03730 1816 SI5351_REGISTER_45_MULTISYNTH0_PARAMETERS_4 = 45,
kenjiArai 0:47b9bfa03730 1817 SI5351_REGISTER_46_MULTISYNTH0_PARAMETERS_5 = 46,
kenjiArai 0:47b9bfa03730 1818 SI5351_REGISTER_47_MULTISYNTH0_PARAMETERS_6 = 47,
kenjiArai 0:47b9bfa03730 1819 SI5351_REGISTER_48_MULTISYNTH0_PARAMETERS_7 = 48,
kenjiArai 0:47b9bfa03730 1820 SI5351_REGISTER_49_MULTISYNTH0_PARAMETERS_8 = 49,
kenjiArai 0:47b9bfa03730 1821 SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1 = 50,
kenjiArai 0:47b9bfa03730 1822 SI5351_REGISTER_51_MULTISYNTH1_PARAMETERS_2 = 51,
kenjiArai 0:47b9bfa03730 1823 SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3 = 52,
kenjiArai 0:47b9bfa03730 1824 SI5351_REGISTER_53_MULTISYNTH1_PARAMETERS_4 = 53,
kenjiArai 0:47b9bfa03730 1825 SI5351_REGISTER_54_MULTISYNTH1_PARAMETERS_5 = 54,
kenjiArai 0:47b9bfa03730 1826 SI5351_REGISTER_55_MULTISYNTH1_PARAMETERS_6 = 55,
kenjiArai 0:47b9bfa03730 1827 SI5351_REGISTER_56_MULTISYNTH1_PARAMETERS_7 = 56,
kenjiArai 0:47b9bfa03730 1828 SI5351_REGISTER_57_MULTISYNTH1_PARAMETERS_8 = 57,
kenjiArai 0:47b9bfa03730 1829 SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1 = 58,
kenjiArai 0:47b9bfa03730 1830 SI5351_REGISTER_59_MULTISYNTH2_PARAMETERS_2 = 59,
kenjiArai 0:47b9bfa03730 1831 SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3 = 60,
kenjiArai 0:47b9bfa03730 1832 SI5351_REGISTER_61_MULTISYNTH2_PARAMETERS_4 = 61,
kenjiArai 0:47b9bfa03730 1833 SI5351_REGISTER_62_MULTISYNTH2_PARAMETERS_5 = 62,
kenjiArai 0:47b9bfa03730 1834 SI5351_REGISTER_63_MULTISYNTH2_PARAMETERS_6 = 63,
kenjiArai 0:47b9bfa03730 1835 SI5351_REGISTER_64_MULTISYNTH2_PARAMETERS_7 = 64,
kenjiArai 0:47b9bfa03730 1836 SI5351_REGISTER_65_MULTISYNTH2_PARAMETERS_8 = 65,
kenjiArai 0:47b9bfa03730 1837 SI5351_REGISTER_66_MULTISYNTH3_PARAMETERS_1 = 66,
kenjiArai 0:47b9bfa03730 1838 SI5351_REGISTER_67_MULTISYNTH3_PARAMETERS_2 = 67,
kenjiArai 0:47b9bfa03730 1839 SI5351_REGISTER_68_MULTISYNTH3_PARAMETERS_3 = 68,
kenjiArai 0:47b9bfa03730 1840 SI5351_REGISTER_69_MULTISYNTH3_PARAMETERS_4 = 69,
kenjiArai 0:47b9bfa03730 1841 SI5351_REGISTER_70_MULTISYNTH3_PARAMETERS_5 = 70,
kenjiArai 0:47b9bfa03730 1842 SI5351_REGISTER_71_MULTISYNTH3_PARAMETERS_6 = 71,
kenjiArai 0:47b9bfa03730 1843 SI5351_REGISTER_72_MULTISYNTH3_PARAMETERS_7 = 72,
kenjiArai 0:47b9bfa03730 1844 SI5351_REGISTER_73_MULTISYNTH3_PARAMETERS_8 = 73,
kenjiArai 0:47b9bfa03730 1845 SI5351_REGISTER_74_MULTISYNTH4_PARAMETERS_1 = 74,
kenjiArai 0:47b9bfa03730 1846 SI5351_REGISTER_75_MULTISYNTH4_PARAMETERS_2 = 75,
kenjiArai 0:47b9bfa03730 1847 SI5351_REGISTER_76_MULTISYNTH4_PARAMETERS_3 = 76,
kenjiArai 0:47b9bfa03730 1848 SI5351_REGISTER_77_MULTISYNTH4_PARAMETERS_4 = 77,
kenjiArai 0:47b9bfa03730 1849 SI5351_REGISTER_78_MULTISYNTH4_PARAMETERS_5 = 78,
kenjiArai 0:47b9bfa03730 1850 SI5351_REGISTER_79_MULTISYNTH4_PARAMETERS_6 = 79,
kenjiArai 0:47b9bfa03730 1851 SI5351_REGISTER_80_MULTISYNTH4_PARAMETERS_7 = 80,
kenjiArai 0:47b9bfa03730 1852 SI5351_REGISTER_81_MULTISYNTH4_PARAMETERS_8 = 81,
kenjiArai 0:47b9bfa03730 1853 SI5351_REGISTER_82_MULTISYNTH5_PARAMETERS_1 = 82,
kenjiArai 0:47b9bfa03730 1854 SI5351_REGISTER_83_MULTISYNTH5_PARAMETERS_2 = 83,
kenjiArai 0:47b9bfa03730 1855 SI5351_REGISTER_84_MULTISYNTH5_PARAMETERS_3 = 84,
kenjiArai 0:47b9bfa03730 1856 SI5351_REGISTER_85_MULTISYNTH5_PARAMETERS_4 = 85,
kenjiArai 0:47b9bfa03730 1857 SI5351_REGISTER_86_MULTISYNTH5_PARAMETERS_5 = 86,
kenjiArai 0:47b9bfa03730 1858 SI5351_REGISTER_87_MULTISYNTH5_PARAMETERS_6 = 87,
kenjiArai 0:47b9bfa03730 1859 SI5351_REGISTER_88_MULTISYNTH5_PARAMETERS_7 = 88,
kenjiArai 0:47b9bfa03730 1860 SI5351_REGISTER_89_MULTISYNTH5_PARAMETERS_8 = 89,
kenjiArai 0:47b9bfa03730 1861 SI5351_REGISTER_90_MULTISYNTH6_PARAMETERS = 90,
kenjiArai 0:47b9bfa03730 1862 SI5351_REGISTER_91_MULTISYNTH7_PARAMETERS = 91,
kenjiArai 0:47b9bfa03730 1863 SI5351_REGISTER_092_CLOCK_6_7_OUTPUT_DIVIDER = 92,
kenjiArai 0:47b9bfa03730 1864 SI5351_REGISTER_165_CLK0_INITIAL_PHASE_OFFSET = 165,
kenjiArai 0:47b9bfa03730 1865 SI5351_REGISTER_166_CLK1_INITIAL_PHASE_OFFSET = 166,
kenjiArai 0:47b9bfa03730 1866 SI5351_REGISTER_167_CLK2_INITIAL_PHASE_OFFSET = 167,
kenjiArai 0:47b9bfa03730 1867 SI5351_REGISTER_168_CLK3_INITIAL_PHASE_OFFSET = 168,
kenjiArai 0:47b9bfa03730 1868 SI5351_REGISTER_169_CLK4_INITIAL_PHASE_OFFSET = 169,
kenjiArai 0:47b9bfa03730 1869 SI5351_REGISTER_170_CLK5_INITIAL_PHASE_OFFSET = 170,
kenjiArai 0:47b9bfa03730 1870 SI5351_REGISTER_177_PLL_RESET = 177,
kenjiArai 0:47b9bfa03730 1871 SI5351_REGISTER_183_CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183
kenjiArai 0:47b9bfa03730 1872 };
kenjiArai 0:47b9bfa03730 1873
kenjiArai 0:47b9bfa03730 1874 typedef enum
kenjiArai 0:47b9bfa03730 1875 {
kenjiArai 0:47b9bfa03730 1876 SI5351_PLL_A = 0,
kenjiArai 0:47b9bfa03730 1877 SI5351_PLL_B,
kenjiArai 0:47b9bfa03730 1878 } si5351PLL_t;
kenjiArai 0:47b9bfa03730 1879
kenjiArai 0:47b9bfa03730 1880 typedef enum
kenjiArai 0:47b9bfa03730 1881 {
kenjiArai 0:47b9bfa03730 1882 SI5351_CRYSTAL_LOAD_6PF = (1<<6),
kenjiArai 0:47b9bfa03730 1883 SI5351_CRYSTAL_LOAD_8PF = (2<<6),
kenjiArai 0:47b9bfa03730 1884 SI5351_CRYSTAL_LOAD_10PF = (3<<6)
kenjiArai 0:47b9bfa03730 1885 } si5351CrystalLoad_t;
kenjiArai 0:47b9bfa03730 1886
kenjiArai 0:47b9bfa03730 1887 typedef enum
kenjiArai 0:47b9bfa03730 1888 {
kenjiArai 0:47b9bfa03730 1889 SI5351_CRYSTAL_FREQ_25MHZ = (25000000),
kenjiArai 0:47b9bfa03730 1890 SI5351_CRYSTAL_FREQ_27MHZ = (27000000)
kenjiArai 0:47b9bfa03730 1891 } si5351CrystalFreq_t;
kenjiArai 0:47b9bfa03730 1892
kenjiArai 0:47b9bfa03730 1893 typedef enum
kenjiArai 0:47b9bfa03730 1894 {
kenjiArai 0:47b9bfa03730 1895 SI5351_MULTISYNTH_DIV_4 = 4,
kenjiArai 0:47b9bfa03730 1896 SI5351_MULTISYNTH_DIV_6 = 6,
kenjiArai 0:47b9bfa03730 1897 SI5351_MULTISYNTH_DIV_8 = 8
kenjiArai 0:47b9bfa03730 1898 } si5351MultisynthDiv_t;
kenjiArai 0:47b9bfa03730 1899
kenjiArai 0:47b9bfa03730 1900 typedef enum
kenjiArai 0:47b9bfa03730 1901 {
kenjiArai 0:47b9bfa03730 1902 SI5351_R_DIV_1 = 0,
kenjiArai 0:47b9bfa03730 1903 SI5351_R_DIV_2 = 1,
kenjiArai 0:47b9bfa03730 1904 SI5351_R_DIV_4 = 2,
kenjiArai 0:47b9bfa03730 1905 SI5351_R_DIV_8 = 3,
kenjiArai 0:47b9bfa03730 1906 SI5351_R_DIV_16 = 4,
kenjiArai 0:47b9bfa03730 1907 SI5351_R_DIV_32 = 5,
kenjiArai 0:47b9bfa03730 1908 SI5351_R_DIV_64 = 6,
kenjiArai 0:47b9bfa03730 1909 SI5351_R_DIV_128 = 7,
kenjiArai 0:47b9bfa03730 1910 } si5351RDiv_t;
kenjiArai 0:47b9bfa03730 1911
kenjiArai 0:47b9bfa03730 1912 typedef struct
kenjiArai 0:47b9bfa03730 1913 {
kenjiArai 0:47b9bfa03730 1914 bool initialised;
kenjiArai 0:47b9bfa03730 1915 si5351CrystalFreq_t crystalFreq;
kenjiArai 0:47b9bfa03730 1916 si5351CrystalLoad_t crystalLoad;
kenjiArai 0:47b9bfa03730 1917 uint32_t crystalPPM;
kenjiArai 0:47b9bfa03730 1918 bool plla_configured;
kenjiArai 0:47b9bfa03730 1919 uint32_t plla_freq;
kenjiArai 0:47b9bfa03730 1920 bool pllb_configured;
kenjiArai 0:47b9bfa03730 1921 uint32_t pllb_freq;
kenjiArai 0:47b9bfa03730 1922 } si5351Config_t;
kenjiArai 0:47b9bfa03730 1923
kenjiArai 0:47b9bfa03730 1924 class Adafruit_SI5351
kenjiArai 0:47b9bfa03730 1925 {
kenjiArai 0:47b9bfa03730 1926 public:
kenjiArai 0:47b9bfa03730 1927 Adafruit_SI5351(void);
kenjiArai 0:47b9bfa03730 1928
kenjiArai 0:47b9bfa03730 1929 err_t begin(void);
kenjiArai 0:47b9bfa03730 1930 err_t setClockBuilderData(void);
kenjiArai 0:47b9bfa03730 1931 err_t setupPLL(si5351PLL_t pll, uint8_t mult, uint32_t num, uint32_t denom);
kenjiArai 0:47b9bfa03730 1932 err_t setupPLLInt(si5351PLL_t pll, uint8_t mult);
kenjiArai 0:47b9bfa03730 1933 err_t setupMultisynth(uint8_t output, si5351PLL_t pllSource, uint32_t div, uint32_t num, uint32_t denom);
kenjiArai 0:47b9bfa03730 1934 err_t setupMultisynthInt(uint8_t output, si5351PLL_t pllSource, si5351MultisynthDiv_t div);
kenjiArai 0:47b9bfa03730 1935 err_t enableOutputs(bool enabled);
kenjiArai 0:47b9bfa03730 1936 err_t setupRdiv(uint8_t output, si5351RDiv_t div);
kenjiArai 0:47b9bfa03730 1937
kenjiArai 0:47b9bfa03730 1938 private:
kenjiArai 0:47b9bfa03730 1939 si5351Config_t m_si5351Config;
kenjiArai 0:47b9bfa03730 1940
kenjiArai 0:47b9bfa03730 1941 err_t write8(uint8_t reg, uint8_t value);
kenjiArai 0:47b9bfa03730 1942 err_t read8(uint8_t reg, uint8_t *value);
kenjiArai 0:47b9bfa03730 1943 };
kenjiArai 0:47b9bfa03730 1944
kenjiArai 0:47b9bfa03730 1945 #endif
kenjiArai 0:47b9bfa03730 1946
kenjiArai 0:47b9bfa03730 1947 #endif
kenjiArai 0:47b9bfa03730 1948 //