Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LTC6947.cpp
Go to the documentation of this file.
1 /*!
2  LTC6947: Ultralow Noise and Spurious 0.35GHz to 6GHz FracN Synthesizer
3 
4 @verbatim
5 
6 The LTC®6947 is a high performance, low noise, 6GHz
7 phase-locked loop (PLL), including a reference divider,
8 phase-frequency detector (PFD), ultralow noise charge
9 pump, fractional feedback divider, and VCO output divider.
10 
11 The fractional divider uses an advanced, 4th order ΔΣ
12 modulator which provides exceptionally low spurious
13 levels. This allows wide loop bandwidths, producing
14 extremely low integrated phase noise values.
15 
16 The programmable VCO output divider, with a range of 1
17 through 6, extends the output frequency range.
18 
19 @endverbatim
20 
21 
22 http://www.linear.com/product/LTC6947
23 
24 http://www.linear.com/product/LTC6947#demoboards
25 
26 
27 Copyright 2018(c) Analog Devices, Inc.
28 
29 All rights reserved.
30 
31 Redistribution and use in source and binary forms, with or without
32 modification, are permitted provided that the following conditions are met:
33  - Redistributions of source code must retain the above copyright
34  notice, this list of conditions and the following disclaimer.
35  - Redistributions in binary form must reproduce the above copyright
36  notice, this list of conditions and the following disclaimer in
37  the documentation and/or other materials provided with the
38  distribution.
39  - Neither the name of Analog Devices, Inc. nor the names of its
40  contributors may be used to endorse or promote products derived
41  from this software without specific prior written permission.
42  - The use of this software may or may not infringe the patent rights
43  of one or more patent holders. This license does not release you
44  from the requirement that you obtain separate licenses from these
45  patent holders to use this software.
46  - Use of the software either in source or binary form, must be run
47  on or directly connected to an Analog Devices Inc. component.
48 
49 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
50 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
51 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
53 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
55 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
56 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
57 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
58 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60 
61 //! @ingroup RF_Timing
62 //! @{
63 //! @defgroup LTC6947 LTC6947: Ultralow Noise and Spurious 0.35GHz to 6GHz FracN Synthesizer
64 //! @}
65 
66 /*! @file
67  @ingroup LTC6947
68  Library for LTC6947: Ultralow Noise and Spurious 0.35GHz to 6GHz FracN Synthesizer
69 */
70 
71 #include <stdint.h>
72 #include <Arduino.h>
73 #include "Linduino.h"
74 #include "UserInterface.h"
75 #include "LT_SPI.h"
76 #include "LTC6947.h"
77 #include <SPI.h>
78 
79 uint8_t LTC6947_reg[LTC6947_NUM_REGADDR]; //!< number of LTC6947 spi addresses
80 uint8_t LTC6947_spi_map[(LTC6947_NUM_REGFIELD+1)][4]; //!< LTC6947 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability
81 
82 unsigned long LTC6947_Fref_MHz = 100; //!< Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy
83 unsigned long LTC6947_Fref_Hz = 0; //!< Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy
84 unsigned long LTC6947_Frf_MHz = 2415; //!< Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy
85 unsigned long LTC6947_Frf_Hz = 0; //!< Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy
86 unsigned long LTC6947_VCO_Max_Freq_MHz = 2536; //!< Max Vco frequency for default on board VCO - MHz portion (xxxx); Fvco max = xxx, yyy,yyy
87 unsigned long LTC6947_VCO_Min_Freq_MHz = 2328; //!< Min Vco frequency for default on board VCO - MHz portion (xxxx); Fvco min = x,xxx, yyy,yyy
88 unsigned long LTC6947_VCO_Max_Freq_Hz = 0; //!< Max Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco max = x,xxx, yyy,yyy
89 unsigned long LTC6947_VCO_Min_Freq_Hz = 0; //!< Min Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco min= x,xxx, yyy,yyy
90 
91 unsigned long zero64[]= {0,0}; //!< for 64bit math functions
92 
93 /* -------------------------------------------------------------------------
94  FUNCTION: LTC6947_read
95  - reads 8 bit Data field to LTC6947.
96  - has to shift data by one bit to account for RW bit
97  -------------------------------------------------------------------------- */
98 uint8_t LTC6947_read(uint8_t cs, int8_t address)
99 {
100  int8_t address_shift;
102 
103  address_shift =(address << 1) | 0x01; // shift to left to account for R/W bit, set bit high for read
104  spi_transfer_word(cs, address_shift<<8 , &rx.LT_uint16);
105 
106  LTC6947_reg[address]=rx.LT_byte[0];
107  return(rx.LT_byte[0]);
108 }
109 
110 
111 /* -------------------------------------------------------------------------
112  FUNCTION: LTC6947_read_field
113  For SPI FIELDS located in 1 or multiple address location
114  - reads specific address locations
115  - identifies and returns specific field in question
116  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
117 --------------------------------------------------------------------------- */
118 long LTC6947_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
119 {
120  int bit_shift, i, num_reg;
121  long field_val, maskbits, pow2;
122 
123  num_reg=0;
124  field_val=0;
125 // determines how many register are used
126  do
127  {
128  bit_shift = (MSB_loc+1)- (numbits-num_reg*8); // determines bit_shift for last register location
129  field_val=LTC6947_read(cs, (address+num_reg))+(field_val<<8); // reads current address locations, shifts previous address location 8 bits
130  num_reg++;
131  }
132  while ((bit_shift<0) && (num_reg<4));
133 
134 // creates a bit mask for complete word,
135  maskbits = 1;
136  pow2=1;
137  for (i=1, maskbits=1; i<numbits; i++)
138  {
139  pow2=pow2*2;
140  maskbits = maskbits+pow2;
141  }
142 
143  field_val=(field_val >>bit_shift) &maskbits;
144  return field_val;
145 }
146 
147 /* -------------------------------------------------------------------------
148  FUNCTION: get_LTC6947_SPI_FIELD
149  For SPI FIELDS
150  - reads specific address locations
151  - identifies and returns specific field in question
152  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
153 --------------------------------------------------------------------------- */
154 long get_LTC6947_SPI_FIELD(uint8_t cs, uint8_t f)
155 {
156 
158 }
159 
160 /* -------------------------------------------------------------------------
161  FUNCTION: LTC6947_write
162  - writes 8 bit Data field to LTC6947.
163  - has to shift data by one bit to account for RW bit
164 --------------------------------------------------------------------------- */
165 void LTC6947_write(uint8_t cs, uint8_t address, uint8_t Data)
166 {
168 
169  address=address << 1; // shift to left to account for R/W bit
170  spi_transfer_word(cs, (address<<8) | Data, &rx.LT_uint16);
171 }
172 
173 
174 /* -------------------------------------------------------------------------
175  FUNCTION: LTC6947_write_field
176  For SPI FIELDS
177  - reads specific address location
178  - identifies and returns specific field in question
179  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
180 ---------------------------------------------------------------------------- */
181 uint8_t LTC6947_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
182 {
183  long current_content, desired_content, reg_val;
184  int LSB_loc, i, j, num_reg, bit_shift;
185  long temp_arr[32];
186 
187  for (i=0; i<32 ; i++) temp_arr[i]=0; // init temp_arr
188 
189 // read data in current address location and put in a bit array
190  num_reg=0;
191  current_content=0;
192  do
193  {
194  bit_shift=(MSB_loc+1)-(numbits-num_reg*8);
195  current_content=LTC6947_read(cs, (address+num_reg)) + (current_content<<8);
196 
197  num_reg++;
198  }
199  while ((bit_shift<0) && (num_reg<4));
200  for (i=0; i<(8*num_reg); i++)
201  {
202  temp_arr[i]=(current_content>>i) & 1;
203  }
204 
205 // exchange current bits with desired bits
206  LSB_loc = 8*(num_reg-1)+MSB_loc-numbits+1;
207  for (i=LSB_loc, j=0; i<=(MSB_loc+(num_reg-1)*8); i++, j++)
208  {
209  temp_arr[i] = (field_data>>j) &1;
210  } // end of for loop
211 
212 // reconstruct bits into an integer
213  desired_content = 0;
214  for (i=0; i<(8*num_reg); i++)
215  {
216  desired_content = desired_content | (temp_arr[i]<<i);
217  } // end of for loop
218 
219 // write new field value to part
220  for (i=0; i<num_reg; i++)
221  {
222  reg_val = (desired_content >> 8*(num_reg-1-i)) & 0xff;
223  LTC6947_write(cs, (address+i), reg_val);
224  } // end of for loop
225 } // end of LTC6947_write_field
226 
227 
228 /* -------------------------------------------------------------------------
229  FUNCTION: get_LTC6947_REGSIZE
230  - returns # of addresses in parts register map (array size)
231 ---------------------------------------------------------------------------- */
233 {
234  return sizeof(LTC6947_reg);
235 }
236 
237 
238 /* -------------------------------------------------------------------------
239  FUNCTION: get_LTC6947_SPI_FIELD_NUMBITS
240  - returns the number of bits for a given field name in the SPI map
241 ---------------------------------------------------------------------------- */
243 {
244  return LTC6947_spi_map[f][NUMBITS];
245 }
246 
247 
248 /* -------------------------------------------------------------------------
249  FUNCTION: get_LTC6947_SPI_FIELD_RW
250  - returns if the given field name is (0)read/write or (1)read_only field
251 ---------------------------------------------------------------------------- */
252 uint8_t get_LTC6947_SPI_FIELD_RW(uint8_t f)
253 {
254  return LTC6947_spi_map[f][R_ONLY];
255 }
256 
257 
258 /* -------------------------------------------------------------------------
259  FUNCTION: set_LTC6947_SPI_FIELD
260  For SPI FIELDS
261  - reads specific address location
262  - identifies and returns specific field in question
263  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
264 ---------------------------------------------------------------------------- */
265 void set_LTC6947_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
266 {
268 }
269 
270 
271 /* -------------------------------------------------------------------------
272  FUNCTION: set_LTC6947_ALLREGS
273  - writes data to all registers at once
274 --------------------------------------------------------------------------- */
275 void set_LTC6947_ALLREGS(uint8_t cs, uint8_t reg01, uint8_t reg02, uint8_t reg03, uint8_t reg04, uint8_t reg05, uint8_t reg06, uint8_t reg07, uint8_t reg08, uint8_t reg09, uint8_t reg0A, uint8_t reg0B, uint8_t reg0C, uint8_t reg0D)
276 {
277  uint8_t i;
278 
279  LTC6947_reg[1] = reg01;
280  LTC6947_reg[2] = reg02;
281  LTC6947_reg[3] = reg03;
282  LTC6947_reg[4] = reg04;
283  LTC6947_reg[5] = reg05;
284  LTC6947_reg[6] = reg06;
285  LTC6947_reg[7] = reg07;
286  LTC6947_reg[8] = reg08;
287  LTC6947_reg[9] = reg09;
288  LTC6947_reg[10] = reg0A;
289  LTC6947_reg[11] = reg0B;
290  LTC6947_reg[12] = reg0C;
291  LTC6947_reg[13] = reg0D;
292 
293  for (i=1; i<14; i++) LTC6947_write(cs, i, LTC6947_reg[i]);
294 } // end of set_LTC6947_ALLREGS
295 
296 
297 /* -------------------------------------------------------------------------
298  FUNCTION: LTC6947_init
299  - initializes the SPI MAP
300  - for ease of programming there is spreadsheet that automates this some.
301 ----------------------------------------------------------------------------*/
303 {
304 
305 // spi map
423 
463 
464 } // end of LTC6947_init
465 
466 void set_LTC6947_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
467 {
468  LTC6947_Fref_MHz=fref_MHz;
469  LTC6947_Fref_Hz=fref_Hz;
470 }
471 
472 void set_LTC6947_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
473 {
474  LTC6947_Frf_MHz=frf_MHz;
475  LTC6947_Frf_Hz=frf_Hz;
476 }
477 
478 void set_LTC6947_global_vcolim(unsigned long fvco_max_MHz, unsigned long fvco_max_Hz, unsigned long fvco_min_MHz, unsigned long fvco_min_Hz)
479 {
480  LTC6947_VCO_Max_Freq_MHz=fvco_max_MHz;
481  LTC6947_VCO_Max_Freq_Hz=fvco_max_Hz;
482  LTC6947_VCO_Min_Freq_MHz=fvco_min_MHz;
483  LTC6947_VCO_Min_Freq_Hz=fvco_min_Hz;
484 }
485 
486 
487 
489 {
490  return LTC6947_Fref_MHz;
491 }
492 
494 {
495  return LTC6947_Fref_Hz;
496 }
497 
499 {
500  return LTC6947_Frf_MHz;
501 }
502 
504 {
505  return LTC6947_Frf_Hz;
506 }
507 
509 {
511 }
512 
514 {
516 }
517 
519 {
521 }
522 
524 {
526 }
527 
528 /* -------------------------------------------------------------------------
529  FUNCTION: calc_odiv
530  - calculates the output divider setting based on the frf and on board
531  VCO frequencies of LTC6947
532  - @return odiv = 1-6 for valid setting, 999 as invalid frequency
533 ---------------------------------------------------------------------------- */
534 unsigned long LTC6947_calc_odiv(unsigned long frf[2])
535 {
536  unsigned long odiv, i;
537  unsigned long max_fout64[2];
538  unsigned long min_fout64[2];
539  unsigned long temp_fout[2];
540  unsigned long temp_i[2];
541  boolean valid_input=false;
542 
543 
546 
547 // verify desired frequency falls within a divider range (1-6)
548  valid_input=false;
549  for (i=1; i<=6; i++)
550  {
551  init64(temp_i,0L,i);
552  temp_fout[0] = frf[0];
553  temp_fout[1] = frf[1];
554  mul64(temp_fout,temp_i);
555  if (lt64(temp_fout,max_fout64) || eq64(temp_fout, max_fout64)) // same as frf*i <= max_fout
556  {
557  if (lt64(min_fout64,temp_fout) || eq64(temp_fout, min_fout64)) // same as frf*i >= min_fout
558  {
559  valid_input=true;
560  odiv=i;
561  }
562  }
563  } // end of for loop
564 
565  if (valid_input == false) odiv= 999L;
566  return odiv;
567 
568 } // end of LTC6947_calc_odiv
569 
570 /* -------------------------------------------------------------------------
571  FUNCTION: LTC6947_set_frf
572  Calculates the integer (N), fractional (NUM) and output divider (OD) SPI values
573  using self created 64bit math functions.
574 
575  Datasheet equations
576  fvco = fpfd*(N + F)
577  frf = fvco/O
578  fpfd = fref/R
579  F=NUM/2^18 = NUM/262144
580 
581  can be modified to the following equations
582  N = (int) (fvco/fpfd) = (int) frf*O*R/fref
583  NUM = (int) [262144 * (frf*O*R/fref -N)]
584 
585  where
586  N = ndiv, O= odiv, NUM=fracN_num in the code below
587 
588  Linduino One (Arduino Uno) is limited to 32 bit floats/double/long.
589  32 bit math functions will create rounding errors with the above equations,
590  tha can result in frequency errors.
591  Therefore, the following code uses self created 64bit functions for 64bit integer math.
592 
593  frf (33 bits) LTC6947-4 max frf/fvco = 6.4GHZ, which is 23 bit number (2^33 = 8.59G)
594  fref (23 bits) LTC6947 min fref = 10MHz, which is a 23 bit number (2^23 = 8.3M)
595  O (3 bits)
596  R (5 bits)
597 
598  step 1: create 64 bit frf and fref numbers
599 
600  step 2: calculate O (output divider)
601 
602  step 3: get current R-divider setting
603 
604  step 4: calculate frf*O*R
605  max bit count/resolution: 33b+3b+5b= 41b
606  step 5: calculate N(10b), using value from step 1
607  N = (int) frf*O*R/fref
608  max bit count/resolution: 41b-23b = 18b
609  step 6: calculate NUM (18b)
610  NUM = (int) [262144 * (frf*O*R/fref -N)]
611  = (int) [2^18 * (frf*O*R/fref -N)]
612  to get the correct value the above calculation are performed like this
613  = ((int)((frf*O*R/fref)<<23) - N<<23 + rounding) >> 5, where << & >> are bit shift left, right
614  * note << 23b was chosen, because step one use 41b, 41b +23b = 64b (max number for 64 bit math)
615  ** note >> 5 was chosen because 23-5 = 2^18, which is the same as multiplying by 262144
616  *** the rounding variable is equivalent to adding 0.5 to the NUM number. the integer operation always
617  rounds down, so adding a 0.5 to the number before rounding down ensures the closest value is
618  selected.
619  In this function the lower 5 bits of (frf*O*R/fref)<<23) - N<<23 (possible variable 0-31)
620  are check to see if they are >=16.
621  If they are then 16 is added to this number before performing the int and >>5 functions.
622 ---------------------------------------------------------------------------- */
624 {
625  unsigned long frf_MHz, frf_Hz, fref_MHz, fref_Hz, odiv, rdiv, ndiv, fracN_num, frac_num_remainder;
626  unsigned long N64[2], NUM64[2], R64[2], O64[2], temp_long[2];
627  char buffer[100];
628  unsigned long frf[2], frf_act[2];
629  unsigned long fref[2];
630  unsigned long temp_math[2];
631  unsigned long frf_rdiv_odiv[2];
632  unsigned long frf_rdiv_odiv_int[2];
633  unsigned long roundup[2];
634 
635  /* step 1: create 64 bit frf and fref numbers
636  32 bit xxxx MHz number and 32 bit yyy yyy Hz number. */
637  frf_MHz=LTC6947_Frf_MHz;
638  frf_Hz=LTC6947_Frf_Hz;
639  HZto64(frf, frf_MHz, frf_Hz);
640 
641  fref_MHz=LTC6947_Fref_MHz;
642  fref_Hz=LTC6947_Fref_Hz;
643  HZto64(fref,fref_MHz,fref_Hz);
644 
645 // step 2: calculate O (output divider)
646  odiv=LTC6947_calc_odiv(frf);
647 
648 // step 3: get current R-divider setting
649  rdiv=get_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_RD); // reads selected field
650 
651 // step 3: calculate frf*O*R
652  frf_rdiv_odiv[0]=0;
653  frf_rdiv_odiv[1]=odiv*rdiv;
654  mul64(frf_rdiv_odiv, frf); // odiv*rdiv*frf
655  frf_rdiv_odiv_int[0]=frf_rdiv_odiv[0]; // copy odiv*rdiv*frf to another variable
656  frf_rdiv_odiv_int[1]=frf_rdiv_odiv[1];
657 
658 // step 4: calculate N(10b), using value from step 3; N = (int) frf*O*R/fref
659  temp_math[0]=fref[0]; // copy fref to temp variable for math operation
660  temp_math[1]=fref[1];
661  div64(frf_rdiv_odiv_int, temp_math); // frf_rdiv_odiv_int= [(frf*odiv*rdiv)]/fref --> int(fvco/fpfd)
662  ndiv=frf_rdiv_odiv_int[1];
663 
664 // step 5: calculate NUM (18b), NUM = (int) [262144 * (frf*O*R/fref -N)]
665 // SEE notes in function header for step 5
666 // ((int)((frf*O*R/fref)<<23) - N<<23 + rounding) >> 5, where << & >> are bit shift left, right
667  shl64by(frf_rdiv_odiv,23);
668  div64(frf_rdiv_odiv, fref); // frf_rdiv_odiv --> [(frf*odiv*rdiv)<<23]/fref
669 
670  shl64by(frf_rdiv_odiv_int,23); // frf_rdiv_odiv_int --> [(int)((frf*odiv*rdiv)/fref)] <<23
671 
672  sub64(frf_rdiv_odiv,frf_rdiv_odiv_int);
673 
674 // NUM is a 18 bit number in the spi register
675 // At this point in the program it is represented by 23 bits
676 // if the lower 5 bits are >=16 (16/31),
677 // then add 16 to the frac_num_remainder. After the bits are
678 // shifted down 5 bits this will be close to added 0.5 bits.
679  frac_num_remainder=(frf_rdiv_odiv[1] & 31L);
680  if (frac_num_remainder >= 16L)
681  {
682  roundup[0]=0L;
683  roundup[1]=16L;
684  add64(frf_rdiv_odiv,roundup);
685  }
686 
687 // shift NUM to get desired 18 bit number for SPI map.
688  shr64by(frf_rdiv_odiv,5);
689  fracN_num=frf_rdiv_odiv[1];
690 
691 // program part and print out results to screen
692  set_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_OD,odiv); // programs output divider
693  Serial.print("OD = ");
694  Serial.println(odiv);
695 
696  Serial.print("RD = ");
697  Serial.println(rdiv);
698 
699  set_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_ND,ndiv); // programs N-divider
700  Serial.print(F("ND = "));
701  Serial.println(ndiv);
702 
703  if (fracN_num > 0L)
704  {
705  set_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_INTN,0L); // programs fractional mode
706  set_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_NUM,fracN_num); // programs NUM
707  if ( (ndiv<35) || (ndiv>1019) ) Serial.print(F("N DIV set to invalid setting - REFER TO DATASHEET\n"));
708  }
709  else
710  {
711  set_LTC6947_SPI_FIELD(LTC6947_CS,LTC6947_INTN,1L); // programs INTN
712  Serial.print(F("When NUM=0, changes to Integer Mode (NUM can not be 0)\n"));
713  if ( (ndiv<32) || (ndiv>1023) ) Serial.print(F("N DIV set to invalid setting - REFER TO DATASHEET\n"));
714  }
715  Serial.print(F("NUM = "));
716  Serial.println(fracN_num);
717 
718 
719 ///// calculate actual fout here and print out
720  frf_act[0]=fref[0];
721  frf_act[1]=fref[1];
722  N64[0]=0;
723  NUM64[0]=0;
724  R64[0]=0;
725  O64[0]=0;
726  N64[1]=ndiv;
727  NUM64[1]=fracN_num;
728  R64[1]=rdiv;
729  O64[1]=odiv;
730 
731  shl64by(N64,18);
732  add64(N64,NUM64); // (N*262144 +NUM)
733  div64(frf_act,R64); // fref/rdiv (or fpfd)
734  mul64(frf_act,N64); // (N*262144 +NUM)*fpdf
735  div64(frf_act,O64); // ((N*262144 +NUM)*fpdf)/odiv
736  shr64by(frf_act,17);
737  if (frf_act[0]==0) // no 32 bit overflow case
738  {
739  Serial.print(F("Actual Output Frequency (closest available) is "));
740  Serial.print(frf_act[1]);
741  Serial.println("Hz");
742  }
743  else // overflow case
744  {
745  temp_math[0]=frf_act[0];
746  temp_math[1]=frf_act[1];
747  temp_long[0]=0;
748  temp_long[1]=OneMHz;
749  div64(temp_math,temp_long); // frf/1e6
750  Serial.print(F("Actual Output Frequency (closest available) is "));
751  Serial.print(temp_math[1]);
752  Serial.print("MHz + ");
753  temp_long[0]=0;
754  temp_long[1]=OneMHz;
755  mul64(temp_math,temp_long); // int(frf/1e6)*1e6
756  sub64(frf_act,temp_math); // frf-int(frf/1e6)*1e6
757  Serial.print(frf_act[1]);
758  Serial.println("Hz");
759  }
760 }
761 
762 
763 /* -------------------------------------------------------------------------
764  FUNCTION: prt
765  Prints HEX representation of 64 bit an
766 ---------------------------------------------------------------------------- */
767 void prt(unsigned long an[])
768 {
769  Serial.print(an[0],HEX);
770  Serial.print(" ");
771  Serial.println(an[1],HEX);
772 }
773 
774 
775 /* -------------------------------------------------------------------------
776  FUNCTION: init64
777  Creates a equivalent 64 bit number from 2 32 bit numbers
778  an[0]=bigPart //upper 32 bits
779  an[1]=littlePart //lower 32 bits
780 ---------------------------------------------------------------------------- */
781 void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart )
782 {
783  an[0]=bigPart;
784  an[1]=littlePart;
785 }
786 
787 /* -------------------------------------------------------------------------
788  FUNCTION: HZto64
789  create a 64 bit Hz number from
790  32 bit xxxx MHz number and 32 bit yyy yyy Hz number.
791  A) if an < 2^32 bits
792  an(upper 32b) = 0
793  an(lower 32b) = MHzPart(32b)*1MHz + HzPart (32b)
794  B) if an > 2^32 bits (4,294,967,296)
795  an(upper 32b) = 1
796  an(lower 32b) = ((MHzPart-4294)*1MHz+HzPart)-967296
797 ---------------------------------------------------------------------------- */
798 void HZto64(unsigned long an[], unsigned long MHzPart, unsigned long HzPart )
799 {
800 
801  if ((MHzPart>4295) || ((MHzPart==4294) && (HzPart>=967296)))
802  {
803  an[0]=1L; // upper 32 bits
804  an[1] =(MHzPart-4294L)*OneMHz + HzPart-967296L; // lower 32 bits
805  }
806  else
807  {
808  an[0] = 0; // upper 32 bits
809  an[1] = MHzPart*OneMHz+HzPart; // lower 32 bits
810  }
811 }
812 
813 /* -------------------------------------------------------------------------
814  FUNCTION: shl64
815  Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
816 ---------------------------------------------------------------------------- */
817 void shl64(unsigned long an[])
818 {
819  an[0] <<= 1;
820  if (an[1] & 0x80000000)
821  an[0]++;
822  an[1] <<= 1;
823 }
824 
825 
826 /* -------------------------------------------------------------------------
827  FUNCTION: shr64
828  Single Bit shift right of equivalent 64 bit number (an[] = an[]>>1)
829 ---------------------------------------------------------------------------- */
830 void shr64(unsigned long an[])
831 {
832  an[1] >>= 1;
833  if (an[0] & 0x1)
834  an[1]+=0x80000000;
835  an[0] >>= 1;
836 }
837 
838 
839 /* -------------------------------------------------------------------------
840  FUNCTION: shl64by
841  Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
842 ---------------------------------------------------------------------------- */
843 void shl64by(unsigned long an[], uint8_t shiftnum)
844 {
845  uint8_t i;
846 
847  for (i=0; i<shiftnum; i++)
848  {
849  an[0] <<= 1;
850  if (an[1] & 0x80000000)
851  an[0]++;
852  an[1] <<= 1;
853  }
854 }
855 
856 
857 /* -------------------------------------------------------------------------
858  FUNCTION: shr64by
859  Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
860 ---------------------------------------------------------------------------- */
861 void shr64by(unsigned long an[], uint8_t shiftnum)
862 {
863  uint8_t i;
864 
865  for (i=0; i<shiftnum; i++)
866  {
867  an[1] >>= 1;
868  if (an[0] & 0x1)
869  an[1]+=0x80000000;
870  an[0] >>= 1;
871  }
872 }
873 
874 
875 /* -------------------------------------------------------------------------
876  FUNCTION: add64
877  64 bit Add ann to an (an[] = an[] + ann[])
878 ---------------------------------------------------------------------------- */
879 void add64(unsigned long an[], unsigned long ann[])
880 {
881  an[0]+=ann[0];
882  if (an[1] + ann[1] < ann[1])
883  an[0]++;
884  an[1]+=ann[1];
885 }
886 
887 
888 /* -------------------------------------------------------------------------
889  FUNCTION: sub64
890  64 bit Subtract ann from an (an[] = an[] - ann[])
891 ---------------------------------------------------------------------------- */
892 void sub64(unsigned long an[], unsigned long ann[])
893 {
894  an[0]-=ann[0];
895  if (an[1] < ann[1])
896  {
897  an[0]--;
898  }
899  an[1]-= ann[1];
900 }
901 
902 
903 /* -------------------------------------------------------------------------
904  FUNCTION: eq64
905  64 bit, if an == ann, then true
906 ---------------------------------------------------------------------------- */
907 boolean eq64(unsigned long an[], unsigned long ann[])
908 {
909  return (an[0]==ann[0]) && (an[1]==ann[1]);
910 }
911 
912 
913 /* -------------------------------------------------------------------------
914  FUNCTION: lt64
915  64 bit, if an < ann, then true
916 ---------------------------------------------------------------------------- */
917 boolean lt64(unsigned long an[], unsigned long ann[])
918 {
919  if (an[0]>ann[0]) return false;
920  return (an[0]<ann[0]) || (an[1]<ann[1]);
921 }
922 
923 
924 /* -------------------------------------------------------------------------
925  FUNCTION: div64
926  64 bit Divide, num=num/div
927 ---------------------------------------------------------------------------- */
928 void div64(unsigned long num[], unsigned long den[])
929 {
930  unsigned long quot[2];
931  unsigned long qbit[2];
932  unsigned long tmp[2];
933  init64(quot,0,0);
934  init64(qbit,0,1);
935 
936  if (eq64(num, zero64)) //numerator 0, call it 0
937  {
938  init64(num,0,0);
939  return;
940  }
941 
942  if (eq64(den, zero64)) //numerator not zero, denominator 0, infinity in my book.
943  {
944  init64(num,0xffffffff,0xffffffff);
945  return;
946  }
947 
948  init64(tmp,0x80000000,0);
949  while (lt64(den,tmp))
950  {
951  shl64(den);
952  shl64(qbit);
953  }
954 
955  while (!eq64(qbit,zero64))
956  {
957  if (lt64(den,num) || eq64(den,num))
958  {
959  sub64(num,den);
960  add64(quot,qbit);
961  }
962  shr64(den);
963  shr64(qbit);
964  }
965 
966  //remainder now in num, but using it to return quotient for now
967  init64(num,quot[0],quot[1]);
968 }
969 
970 
971 /* -------------------------------------------------------------------------
972  FUNCTION: mul64
973  64 bit multiply, an=an*ann
974 ---------------------------------------------------------------------------- */
975 void mul64(unsigned long an[], unsigned long ann[])
976 {
977  unsigned long p[2] = {0,0};
978  unsigned long y[2] = {ann[0], ann[1]};
979  while (!eq64(y,zero64))
980  {
981  if (y[1] & 1)
982  add64(p,an);
983  shl64(an);
984  shr64(y);
985  }
986  init64(an,p[0],p[1]);
987 }
#define LTC6947_CPCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:84
void div64(unsigned long num[], unsigned long den[])
64 bit Divide, num=num/div
Definition: LTC6947.cpp:928
uint8_t LTC6947_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6947 Write Single Field For SPI FIELDS in 1 or multiple address locations reads specific address/f...
Definition: LTC6947.cpp:181
#define LTC6947_NUM_REGFIELD
Defines number of LTC6947 SPI fields, used in spi_map array.
Definition: LTC6947.h:123
#define LTC6947_ND
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:101
unsigned long get_LTC6947_global_VCO_MIN_Hz()
returns global LTC6947_VCO_Min_Freq_Hz
Definition: LTC6947.cpp:523
#define LTC6947_INTN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:95
#define LTC6947_PDALL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:106
#define LTC6947_PDPLL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:109
uint8_t get_LTC6947_SPI_FIELD_NUMBITS(uint8_t f)
returns the number of bits for a given field name in the SPI map
Definition: LTC6947.cpp:242
#define LTC6947_CPUP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:91
#define LTC6947_POR
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:110
void sub64(unsigned long an[], unsigned long ann[])
64 bit Subtract ann from an (an[] = an[] - ann[])
Definition: LTC6947.cpp:892
#define LTC6947_x
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:119
#define LTC6947_RSTFN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:114
unsigned long LTC6947_VCO_Min_Freq_Hz
Min Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco min= x,xxx, yyy,yyy.
Definition: LTC6947.cpp:89
#define LTC6947_BST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:82
unsigned long LTC6947_Fref_MHz
Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy.
Definition: LTC6947.cpp:82
void set_LTC6947_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
sets globals LTC6947_Fref_MHz and LTC6947_Fref_Hz
Definition: LTC6947.cpp:466
void prt(unsigned long an[])
Prints HEX representation of 64 bit an.
Definition: LTC6947.cpp:767
void set_LTC6947_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
Sets the LTC6947 SPI field value calls function LTC6947_read_field, which reads specific address/fiel...
Definition: LTC6947.cpp:265
Header File for Linduino Libraries and Demo Code.
uint8_t get_LTC6947_SPI_FIELD_RW(uint8_t f)
returns if the given field name is (0)read/write or (1)read_only field
Definition: LTC6947.cpp:252
#define LTC6947_CPRST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:90
boolean eq64(unsigned long an[], unsigned long ann[])
64 bit, if an == ann, then true
Definition: LTC6947.cpp:907
void LTC6947_write(uint8_t cs, uint8_t address, uint8_t Data)
LTC6947 Write Single Address writes 8 bit Data field to LTC6947.
Definition: LTC6947.cpp:165
unsigned long LTC6947_VCO_Max_Freq_MHz
Max Vco frequency for default on board VCO - MHz portion (xxxx); Fvco max = xxx, yyy,yyy.
Definition: LTC6947.cpp:86
#define LTC6947_NUM_REGADDR
Defines number of LTC6947 SPI registers, used in spi_map array.
Definition: LTC6947.h:122
uint8_t LTC6947_read(uint8_t cs, int8_t address)
LTC6947 Read Single Address reads 8 bit Data field to LTC6947.
Definition: LTC6947.cpp:98
#define OneMHz
1MHz in long format, used in 64 bit math
Definition: LTC6945.h:121
void shl64(unsigned long an[])
Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6947.cpp:817
unsigned long get_LTC6947_global_VCO_MIN_MHz()
returns global LTC6947_VCO_Min_Freq_MHz
Definition: LTC6947.cpp:513
void shr64(unsigned long an[])
Single Bit shift right of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6947.cpp:830
#define LTC6947_THI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:116
#define LTC6947_RD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:111
#define LTC6947_CPLE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:88
#define LTC6947_REV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:112
unsigned long LTC6947_VCO_Max_Freq_Hz
Max Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco max = x,xxx, yyy,yyy.
Definition: LTC6947.cpp:88
#define LTC6947_OD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:103
#define LTC6947_FILT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:94
#define NUMBITS
Definition: LTC6115.h:69
#define LTC6947_CP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:83
static uint8_t address
Definition: DC2091A.ino:83
void HZto64(unsigned long an[], unsigned long MHzPart, unsigned long HzPart)
create a 64 bit Hz number from 32 bit xxxx MHz number and 32 bit yyy yyy Hz number.
Definition: LTC6947.cpp:798
unsigned long get_LTC6947_global_VCO_MAX_MHz()
returns global LTC6947_VCO_Max_Freq_MHz
Definition: LTC6947.cpp:508
uint8_t LTC6947_spi_map[(LTC6947_NUM_REGFIELD+1)][4]
LTC6947 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability.
Definition: LTC6947.cpp:80
#define LTC6947_CPMID
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:89
#define LTC6947_OMUTE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:104
#define LTC6947_PART
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:105
void set_LTC6947_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
sets globals LTC6947_Frf_MHz and LTC6947_Frf_Hz
Definition: LTC6947.cpp:472
#define LTC6947_LDOEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:96
long LTC6947_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6947 Read Single Field For SPI FIELDS located in 1 or multiple address location reads specific add...
Definition: LTC6947.cpp:118
unsigned long LTC6947_Frf_MHz
Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy.
Definition: LTC6947.cpp:84
#define LTC6947_CPDN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:86
void LTC6947_set_frf()
FUNCTION: LTC6947_set_frf Calculates the integer (N), fractional (NUM) and output divider (OD) SPI va...
Definition: LTC6947.cpp:623
uint16_t LT_uint16
16-bit unsigned integer to be converted to two bytes
Definition: Linduino.h:102
#define R_ONLY
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:119
unsigned long get_LTC6947_global_frf_MHz()
returns global LTC6947_Frf_MHz
Definition: LTC6947.cpp:498
void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
Reads and sends a word.
Definition: LT_SPI.cpp:98
unsigned long LTC6947_VCO_Min_Freq_MHz
Min Vco frequency for default on board VCO - MHz portion (xxxx); Fvco min = x,xxx, yyy,yyy.
Definition: LTC6947.cpp:87
#define LTC6947_RFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:113
unsigned long get_LTC6947_global_fref_Hz()
returns global LTC6947_Fref_Hz
Definition: LTC6947.cpp:493
#define LTC6947_CPINV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:87
unsigned long LTC6947_Fref_Hz
Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy.
Definition: LTC6947.cpp:83
unsigned long zero64[]
for 64bit math functions
Definition: LTC6947.cpp:91
#define LTC6947_PDFN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:107
unsigned long get_LTC6947_global_fref_MHz()
returns global LTC6947_Fref_MHz
Definition: LTC6947.cpp:488
#define LTC6947_LKWIN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:99
void shr64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
Definition: LTC6947.cpp:861
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
unsigned long get_LTC6947_global_VCO_MAX_Hz()
returns global LTC6947_VCO_Max_Freq_Hz
Definition: LTC6947.cpp:518
#define LTC6947_PDOUT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:108
#define LTC6947_TLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:117
#define LTC6947_CPWIDE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:92
#define LTC6947_CPCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:85
#define LTC6947_LDOV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:97
#define ADDRx
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:116
#define LTC6947_UNLOK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:118
LTC6947: Ultralow Noise and Spurious 0.35GHz to 6GHz FracN Synthesizer.
long get_LTC6947_SPI_FIELD(uint8_t cs, uint8_t f)
Gets the LTC6947 SPI field value calls function LTC6947_read_field, which reads specific address loca...
Definition: LTC6947.cpp:154
uint8_t LTC6947_reg[LTC6947_NUM_REGADDR]
number of LTC6947 spi addresses
Definition: LTC6947.cpp:79
void add64(unsigned long an[], unsigned long ann[])
64 bit Add ann to an (an[] = an[] + ann[])
Definition: LTC6947.cpp:879
#define LTC6947_LKCT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:98
#define LTC6947_NUM
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:102
#define LTC6947_LOCK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:100
#define LTC6947_SEED
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:115
#define LTC6947_DITHEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:93
This union splits one int16_t (16-bit signed integer) or uint16_t (16-bit unsigned integer) into two ...
Definition: Linduino.h:99
void LTC6947_init()
Initializes the SPI MAP arrays The values set in initialization are used for all the LTC6947 SPI/WRIT...
Definition: LTC6947.cpp:302
unsigned long LTC6947_calc_odiv(unsigned long frf[2])
calculates the output divider setting based on the frf and on board VCO frequencies of LTC6947 ...
Definition: LTC6947.cpp:534
static int i
Definition: DC2430A.ino:184
void shl64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
Definition: LTC6947.cpp:843
#define LTC6947_AUTORST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6947.h:81
uint8_t LT_byte[2]
2 bytes (unsigned 8-bit integers) to be converted to a 16-bit signed or unsigned integer ...
Definition: Linduino.h:103
#define LTC6947_CS
Define the SPI CS pin.
Definition: LTC6947.h:76
uint8_t get_LTC6947_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6947.cpp:232
void mul64(unsigned long an[], unsigned long ann[])
64 bit multiply, an=an*ann
Definition: LTC6947.cpp:975
unsigned long get_LTC6947_global_frf_Hz()
returns global LTC6947_Frf_Hz
Definition: LTC6947.cpp:503
boolean lt64(unsigned long an[], unsigned long ann[])
64 bit, if an < ann, then true
Definition: LTC6947.cpp:917
void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart)
Creates a equivalent 64 bit number from 2 32 bit numbers.
Definition: LTC6947.cpp:781
void set_LTC6947_global_vcolim(unsigned long fvco_max_MHz, unsigned long fvco_max_Hz, unsigned long fvco_min_MHz, unsigned long fvco_min_Hz)
sets globals LTC6947_VCO_Max_Freq_MHz, LTC6947_VCO_Max_Freq_Hz, LTC6947_VCO_Min_Freq_MHz and LTC6947_...
Definition: LTC6947.cpp:478
void set_LTC6947_ALLREGS(uint8_t cs, uint8_t reg01, uint8_t reg02, uint8_t reg03, uint8_t reg04, uint8_t reg05, uint8_t reg06, uint8_t reg07, uint8_t reg08, uint8_t reg09, uint8_t reg0A, uint8_t reg0B, uint8_t reg0C, uint8_t reg0D)
Writes values to ALL LTC6947 RW addresses.
Definition: LTC6947.cpp:275
unsigned long LTC6947_Frf_Hz
Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy.
Definition: LTC6947.cpp:85
#define DxMSB
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:117