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:
Thu Jan 05 12:28:27 2017 +0000
Revision:
1:a2309757c450
Parent:
0:47b9bfa03730
Child:
2:8fe745836ea6
Fixed BUG

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