Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LTC6945.cpp
Go to the documentation of this file.
1 /*!
2  LTC6945: Ultralow Noise and Spurious 0.35GHz to 6GHz Integer-N Synthesizer
3 
4 @verbatim
5 
6 The LTC®6945 is a high performance, low noise, 6GHz phase-locked
7 loop (PLL), including a reference divider, phase-frequency
8 detector (PFD) with phase-lock indicator, charge
9 pump, integer feedback divider and VCO output divider.
10 
11 The part features a buffered, programmable VCO output
12 divider with a range of 1 through 6. The differential, low
13 noise output buffer has user-programmable output power
14 ranging from –6dBm to 3dBm, and may be muted through
15 either a digital input pin or software.
16 
17 The low noise reference buffer outputs a typical 0dBm
18 square wave directly into a 50Ω impedance from 10MHz
19 to 250MHz, or may be disabled through software.
20 
21 The ultralow noise charge pump contains selectable high
22 and low voltage clamps useful for VCO monitoring, and
23 also may be set to provide a V+/2 bias.
24 
25 All device settings are controlled through a SPI-compatible
26 serial port.
27 
28 @endverbatim
29 
30 
31 http://www.linear.com/product/LTC6945
32 
33 http://www.linear.com/product/LTC6945#demoboards
34 
35 
36 Copyright 2018(c) Analog Devices, Inc.
37 
38 All rights reserved.
39 
40 Redistribution and use in source and binary forms, with or without
41 modification, are permitted provided that the following conditions are met:
42  - Redistributions of source code must retain the above copyright
43  notice, this list of conditions and the following disclaimer.
44  - Redistributions in binary form must reproduce the above copyright
45  notice, this list of conditions and the following disclaimer in
46  the documentation and/or other materials provided with the
47  distribution.
48  - Neither the name of Analog Devices, Inc. nor the names of its
49  contributors may be used to endorse or promote products derived
50  from this software without specific prior written permission.
51  - The use of this software may or may not infringe the patent rights
52  of one or more patent holders. This license does not release you
53  from the requirement that you obtain separate licenses from these
54  patent holders to use this software.
55  - Use of the software either in source or binary form, must be run
56  on or directly connected to an Analog Devices Inc. component.
57 
58 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
59 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
60 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
62 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
63 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
64 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
65 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
66 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 */
69 
70 //! @ingroup RF_Timing
71 //! @{
72 //! @defgroup LTC6945 LTC6945: Ultralow Noise and Spurious 0.35GHz to 6GHz Integer-N Synthesizer
73 //! @}
74 
75 /*! @file
76  @ingroup LTC6945
77  Library for LTC6945: Ultralow Noise and Spurious 0.35GHz to 6GHz Integer-N Synthesizer
78 */
79 
80 #include <stdint.h>
81 #include <Arduino.h>
82 #include "Linduino.h"
83 #include "UserInterface.h"
84 #include "LT_SPI.h"
85 #include "LTC6945.h"
86 #include <SPI.h>
87 
88 uint8_t LTC6945_reg[LTC6945_NUM_REGADDR]; //!< number of LTC6945 spi addresses
89 uint8_t LTC6945_spi_map[(LTC6945_NUM_REGFIELD+1)][4]; //!< LTC6945 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability
90 
91 unsigned long LTC6945_Fref_MHz = 100; //!< Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy
92 unsigned long LTC6945_Fref_Hz = 0; //!< Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy
93 unsigned long LTC6945_Frf_MHz = 914; //!< Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy
94 unsigned long LTC6945_Frf_Hz = 0; //!< Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy
95 unsigned long LTC6945_VCO_Max_Freq_MHz = 928; //!< Max Vco frequency for default on board VCO - MHz portion (xxxx); Fvco max = xxx, yyy,yyy
96 unsigned long LTC6945_VCO_Min_Freq_MHz = 902; //!< Min Vco frequency for default on board VCO - MHz portion (xxxx); Fvco min = x,xxx, yyy,yyy
97 unsigned long LTC6945_VCO_Max_Freq_Hz = 0; //!< Max Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco max = x,xxx, yyy,yyy
98 unsigned long LTC6945_VCO_Min_Freq_Hz = 0; //!< Min Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco min= x,xxx, yyy,yyy
99 
100 unsigned long zero64[]= {0,0}; //!< for 64bit math functions
101 
102 /* -------------------------------------------------------------------------
103  FUNCTION: LTC6945_read
104  - reads 8 bit Data field to LTC6945.
105  - has to shift data by one bit to account for RW bit
106  -------------------------------------------------------------------------- */
107 uint8_t LTC6945_read(uint8_t cs, int8_t address)
108 {
109  int8_t address_shift;
111 
112  address_shift =(address << 1) | 0x01; // shift to left to account for R/W bit, set bit high for read
113  spi_transfer_word(cs, address_shift<<8 , &rx.LT_uint16);
114 
115  LTC6945_reg[address]=rx.LT_byte[0];
116  return(rx.LT_byte[0]);
117 }
118 
119 
120 /* -------------------------------------------------------------------------
121  FUNCTION: LTC6945_read_field
122  For SPI FIELDS located in 1 or multiple address location
123  - reads specific address locations
124  - identifies and returns specific field in question
125  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
126 --------------------------------------------------------------------------- */
127 long LTC6945_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
128 {
129  int bit_shift, i, num_reg;
130  long field_val, maskbits, pow2;
131 
132  num_reg=0;
133  field_val=0;
134 // determines how many register are used
135  do
136  {
137  bit_shift = (MSB_loc+1)- (numbits-num_reg*8); // determines bit_shift for last register location
138  field_val=LTC6945_read(cs, (address+num_reg))+(field_val<<8); // reads current address locations, shifts previous address location 8 bits
139  num_reg++;
140  }
141  while ((bit_shift<0) && (num_reg<4));
142 
143 // creates a bit mask for complete word,
144  maskbits = 1;
145  pow2=1;
146  for (i=1, maskbits=1; i<numbits; i++)
147  {
148  pow2=pow2*2;
149  maskbits = maskbits+pow2;
150  }
151 
152  field_val=(field_val >>bit_shift) &maskbits;
153  return field_val;
154 }
155 
156 /* -------------------------------------------------------------------------
157  FUNCTION: get_LTC6945_SPI_FIELD
158  For SPI FIELDS
159  - reads specific address locations
160  - identifies and returns specific field in question
161  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
162 --------------------------------------------------------------------------- */
163 long get_LTC6945_SPI_FIELD(uint8_t cs, uint8_t f)
164 {
165 
167 }
168 
169 /* -------------------------------------------------------------------------
170  FUNCTION: LTC6945_write
171  - writes 8 bit Data field to LTC6945.
172  - has to shift data by one bit to account for RW bit
173 --------------------------------------------------------------------------- */
174 void LTC6945_write(uint8_t cs, uint8_t address, uint8_t Data)
175 {
177 
178  address=address << 1; // shift to left to account for R/W bit
179  spi_transfer_word(cs, (address<<8) | Data, &rx.LT_uint16);
180 }
181 
182 
183 /* -------------------------------------------------------------------------
184  FUNCTION: LTC6945_write_field
185  For SPI FIELDS
186  - reads specific address location
187  - identifies and returns specific field in question
188  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
189 ---------------------------------------------------------------------------- */
190 uint8_t LTC6945_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
191 {
192  long current_content, desired_content, reg_val;
193  int LSB_loc, i, j, num_reg, bit_shift;
194  long temp_arr[32];
195 
196  for (i=0; i<32 ; i++) temp_arr[i]=0; // init temp_arr
197 
198 // read data in current address location and put in a bit array
199  num_reg=0;
200  current_content=0;
201  do
202  {
203  bit_shift=(MSB_loc+1)-(numbits-num_reg*8);
204  current_content=LTC6945_read(cs, (address+num_reg)) + (current_content<<8);
205 
206  num_reg++;
207  }
208  while ((bit_shift<0) && (num_reg<4));
209  for (i=0; i<(8*num_reg); i++)
210  {
211  temp_arr[i]=(current_content>>i) & 1;
212  }
213 
214 // exchange current bits with desired bits
215  LSB_loc = 8*(num_reg-1)+MSB_loc-numbits+1;
216  for (i=LSB_loc, j=0; i<=(MSB_loc+(num_reg-1)*8); i++, j++)
217  {
218  temp_arr[i] = (field_data>>j) &1;
219  } // end of for loop
220 
221 // reconstruct bits into an integer
222  desired_content = 0;
223  for (i=0; i<(8*num_reg); i++)
224  {
225  desired_content = desired_content | (temp_arr[i]<<i);
226  } // end of for loop
227 
228 // write new field value to part
229  for (i=0; i<num_reg; i++)
230  {
231  reg_val = (desired_content >> 8*(num_reg-1-i)) & 0xff;
232  LTC6945_write(cs, (address+i), reg_val);
233  } // end of for loop
234 } // end of LTC6945_write_field
235 
236 
237 /* -------------------------------------------------------------------------
238  FUNCTION: get_LTC6945_REGSIZE
239  - returns # of addresses in parts register map (array size)
240 ---------------------------------------------------------------------------- */
242 {
243  return sizeof(LTC6945_reg);
244 }
245 
246 
247 /* -------------------------------------------------------------------------
248  FUNCTION: get_LTC6945_SPI_FIELD_NUMBITS
249  - returns the number of bits for a given field name in the SPI map
250 ---------------------------------------------------------------------------- */
252 {
253  return LTC6945_spi_map[f][NUMBITS];
254 }
255 
256 
257 /* -------------------------------------------------------------------------
258  FUNCTION: get_LTC6945_SPI_FIELD_RW
259  - returns if the given field name is (0)read/write or (1)read_only field
260 ---------------------------------------------------------------------------- */
261 uint8_t get_LTC6945_SPI_FIELD_RW(uint8_t f)
262 {
263  return LTC6945_spi_map[f][R_ONLY];
264 }
265 
266 
267 /* -------------------------------------------------------------------------
268  FUNCTION: set_LTC6945_SPI_FIELD
269  For SPI FIELDS
270  - reads specific address location
271  - identifies and returns specific field in question
272  - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
273 ---------------------------------------------------------------------------- */
274 void set_LTC6945_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
275 {
277 }
278 
279 
280 /* -------------------------------------------------------------------------
281  FUNCTION: set_LTC6945_ALLREGS
282  - writes data to all registers at once
283 --------------------------------------------------------------------------- */
284 void set_LTC6945_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)
285 {
286  uint8_t i;
287 
288  LTC6945_reg[1] = reg01;
289  LTC6945_reg[2] = reg02;
290  LTC6945_reg[3] = reg03;
291  LTC6945_reg[4] = reg04;
292  LTC6945_reg[5] = reg05;
293  LTC6945_reg[6] = reg06;
294  LTC6945_reg[7] = reg07;
295  LTC6945_reg[8] = reg08;
296  LTC6945_reg[9] = reg09;
297  LTC6945_reg[10] = reg0A;
298 
299  for (i=1; i<11; i++) LTC6945_write(cs, i, LTC6945_reg[i]);
300 } // end of set_LTC6945_ALLREGS
301 
302 
303 /* -------------------------------------------------------------------------
304  FUNCTION: LTC6945_init
305  - initializes the SPI MAP
306  - for ease of programming there is spreadsheet that automates this some.
307 ----------------------------------------------------------------------------*/
309 {
310 
311 // spi map
405 
437 
438 } // end of LTC6945_init
439 
440 void set_LTC6945_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
441 {
442  LTC6945_Fref_MHz=fref_MHz;
443  LTC6945_Fref_Hz=fref_Hz;
444 }
445 
446 void set_LTC6945_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
447 {
448  LTC6945_Frf_MHz=frf_MHz;
449  LTC6945_Frf_Hz=frf_Hz;
450 }
451 
452 void set_LTC6945_global_vcolim(unsigned long fvco_max_MHz, unsigned long fvco_max_Hz, unsigned long fvco_min_MHz, unsigned long fvco_min_Hz)
453 {
454  LTC6945_VCO_Max_Freq_MHz=fvco_max_MHz;
455  LTC6945_VCO_Max_Freq_Hz=fvco_max_Hz;
456  LTC6945_VCO_Min_Freq_MHz=fvco_min_MHz;
457  LTC6945_VCO_Min_Freq_Hz=fvco_min_Hz;
458 }
459 
460 
461 
463 {
464  return LTC6945_Fref_MHz;
465 }
466 
468 {
469  return LTC6945_Fref_Hz;
470 }
471 
473 {
474  return LTC6945_Frf_MHz;
475 }
476 
478 {
479  return LTC6945_Frf_Hz;
480 }
481 
483 {
485 }
486 
488 {
490 }
491 
493 {
495 }
496 
498 {
500 }
501 
502 /* -------------------------------------------------------------------------
503  FUNCTION: calc_odiv
504  - calculates the output divider setting based on the frf and on board
505  VCO frequencies of LTC6945
506  - @return odiv = 1-6 for valid setting, 999 as invalid frequency
507 ---------------------------------------------------------------------------- */
508 unsigned long LTC6945_calc_odiv(unsigned long frf[2])
509 {
510  unsigned long odiv, i;
511  unsigned long max_fout64[2];
512  unsigned long min_fout64[2];
513  unsigned long temp_fout[2];
514  unsigned long temp_i[2];
515  boolean valid_input=false;
516 
517 
520 
521 // verify desired frequency falls within a divider range (1-6)
522  valid_input=false;
523  for (i=1; i<=6; i++)
524  {
525  init64(temp_i,0L,i);
526  temp_fout[0] = frf[0];
527  temp_fout[1] = frf[1];
528  mul64(temp_fout,temp_i);
529  if (lt64(temp_fout,max_fout64) || eq64(temp_fout, max_fout64)) // same as frf*i <= max_fout
530  {
531  if (lt64(min_fout64,temp_fout) || eq64(temp_fout, min_fout64)) // same as frf*i >= min_fout
532  {
533  valid_input=true;
534  odiv=i;
535  }
536  }
537  } // end of for loop
538 
539  if (valid_input == false) odiv= 999L;
540  return odiv;
541 
542 } // end of LTC6945_calc_odiv
543 
544 /* -------------------------------------------------------------------------
545  FUNCTION: LTC6945_set_frf
546  Calculates the integer (N) and output divider (OD) SPI values
547  using self created 64bit math functions.
548 
549  Datasheet equations
550  fvco = fpfd*N
551  frf = fvco/O
552  fpfd = fref/R
553 
554  can be modified to the following equations
555  N = (int) (fvco/fpfd) = (int) frf*O*R/fref
556 
557  where
558  N = ndiv, O= odiv, in the code below
559 
560  Linduino One (Arduino Uno) is limited to 32 bit floats/double/long.
561  32 bit math functions will create rounding errors with the above equations,
562  tha can result in frequency errors.
563  Therefore, the following code uses self created 64bit functions for 64bit integer math.
564 
565  - frf (33 bits) LTC6945 max frf/fvco = 6.0GHZ, which is 23 bit number (2^33 = 8.59G)
566  - fref (23 bits) LTC6945 min fref = 10MHz, which is a 23 bit number (2^23 = 8.3M)
567  - O (3 bits)
568  - R (10 bits)
569 
570  step 1: create 64 bit frf and fref numbers
571 
572  step 2: calculate O (output divider)
573 
574  step 3: get current R-divider setting
575 
576  step 4: calculate frf*O*R
577  - max bit count/resolution: 33b+3b+10b= 46b
578 
579  step 5: calculate N(16b), using value from step 1
580  - N = (int) frf*O*R/fref
581  - max bit count/resolution: 46b-23b = 13b
582 ---------------------------------------------------------------------------- */
584 {
585  unsigned long frf_MHz, frf_Hz, fref_MHz, fref_Hz, odiv, rdiv, ndiv, N_remainder;
586  unsigned long N64[2], R64[2], O64[2], temp_long[2];
587  char buffer[100];
588  unsigned long frf[2], frf_act[2];
589  unsigned long fref[2];
590  unsigned long temp_math[2];
591  unsigned long frf_rdiv_odiv[2];
592  unsigned long frf_rdiv_odiv_int[2];
593  unsigned long roundup[2];
594 
595  /* step 1: create 64 bit frf and fref numbers
596  32 bit xxxx MHz number and 32 bit yyy yyy Hz number. */
597  frf_MHz=LTC6945_Frf_MHz;
598  frf_Hz=LTC6945_Frf_Hz;
599  HZto64(frf, frf_MHz, frf_Hz);
600 
601  fref_MHz=LTC6945_Fref_MHz;
602  fref_Hz=LTC6945_Fref_Hz;
603  HZto64(fref,fref_MHz,fref_Hz);
604 
605 // step 2: calculate O (output divider)
606  odiv=LTC6945_calc_odiv(frf);
607 
608 // step 3: get current R-divider setting
609  rdiv=get_LTC6945_SPI_FIELD(LTC6945_CS,LTC6945_RD); // reads selected field
610 
611 // step 4: calculate frf*O*R
612  frf_rdiv_odiv[0]=0;
613  frf_rdiv_odiv[1]=odiv*rdiv;
614  mul64(frf_rdiv_odiv, frf); // odiv*rdiv*frf
615  frf_rdiv_odiv_int[0]=frf_rdiv_odiv[0]; // copy odiv*rdiv*frf to another variable
616  frf_rdiv_odiv_int[1]=frf_rdiv_odiv[1];
617 
618 // step 5: calculate N(16b), using value from step 3; N = (int) frf*O*R/fref
619  temp_math[0]=fref[0]; // copy fref to temp variable for math operation
620  temp_math[1]=fref[1];
621  div64(frf_rdiv_odiv_int, temp_math); // frf_rdiv_odiv_int= [(frf*odiv*rdiv)]/fref --> int(fvco/fpfd)
622  ndiv=frf_rdiv_odiv_int[1];
623 
624 // step 6: find N for closest frequency - accounts for rounding with integer math
625  temp_math[0]=fref[0]; // copy fref to temp variable for math operation
626  temp_math[1]=fref[1];
627  shl64by(frf_rdiv_odiv,13); // frf_rdiv_odiv --> [(frf*odiv*rdiv)<<13]/fref = N(double) <<13
628  div64(frf_rdiv_odiv,temp_math);
629  shl64by(frf_rdiv_odiv_int,13); // frf_rdiv_odiv_int --> [(int)((frf*odiv*rdiv)/fref)] <<13 = N(int) <<13
630  sub64(frf_rdiv_odiv,frf_rdiv_odiv_int); // N(double) <<13 - N(int)<<13
631 
632 // at this point frf_rdiv_odiv is the delta between N(double) and N(int) shifted by 13 bits.
633 // if this remainder is < 4096, N(int) will give the closest frequency
634 // if this remainder is >=4096, N(int)+1 will give the closest frequency
635 // 4096 is mid point of the 13 bit number range
636  N_remainder = (frf_rdiv_odiv[1] & 8191L); // 13 bits max code = 8191
637  if (N_remainder >= 4096)
638  {
639  ndiv=ndiv+1;
640  }
641 
642 // program part and print out results to screen
643  set_LTC6945_SPI_FIELD(LTC6945_CS,LTC6945_OD,odiv); // programs output divider
644  Serial.print("OD = ");
645  Serial.println(odiv);
646 
647  Serial.print("RD = ");
648  Serial.println(rdiv);
649 
650  set_LTC6945_SPI_FIELD(LTC6945_CS,LTC6945_ND,ndiv); // programs N-divider
651  Serial.print(F("ND = "));
652  Serial.println(ndiv);
653 
654 
655 ///// calculate actual fout here and print out
656  frf_act[0]=fref[0];
657  frf_act[1]=fref[1];
658  N64[0]=0;
659  R64[0]=0;
660  O64[0]=0;
661  N64[1]=ndiv;
662  R64[1]=rdiv;
663  O64[1]=odiv;
664 
665  mul64(frf_act,N64); // N*fref
666  div64(frf_act,R64); // N*fref/rdiv (or N*fpfd)
667  div64(frf_act,O64); // N*fpdf/odiv
668  if (frf_act[0]==0) // no 32 bit overflow case
669  {
670  Serial.print(F("Actual Output Frequency (closest available) is "));
671  Serial.print(frf_act[1]);
672  Serial.println("Hz");
673  }
674  else // overflow case
675  {
676  temp_math[0]=frf_act[0];
677  temp_math[1]=frf_act[1];
678  temp_long[0]=0;
679  temp_long[1]=OneMHz;
680  div64(temp_math,temp_long); // frf/1e6
681  Serial.print(F("Actual Output Frequency (closest available) is "));
682  Serial.print(temp_math[1]);
683  Serial.print("MHz + ");
684  temp_long[0]=0;
685  temp_long[1]=OneMHz;
686  mul64(temp_math,temp_long); // int(frf/1e6)*1e6
687  sub64(frf_act,temp_math); // frf-int(frf/1e6)*1e6
688  Serial.print(frf_act[1]);
689  Serial.println("Hz");
690  }
691 }
692 
693 
694 /* -------------------------------------------------------------------------
695  FUNCTION: prt
696  Prints HEX representation of 64 bit an
697 ---------------------------------------------------------------------------- */
698 void prt(unsigned long an[])
699 {
700  Serial.print(an[0],HEX);
701  Serial.print(" ");
702  Serial.println(an[1],HEX);
703 }
704 
705 
706 /* -------------------------------------------------------------------------
707  FUNCTION: init64
708  Creates a equivalent 64 bit number from 2 32 bit numbers
709  an[0]=bigPart //upper 32 bits
710  an[1]=littlePart //lower 32 bits
711 ---------------------------------------------------------------------------- */
712 void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart )
713 {
714  an[0]=bigPart;
715  an[1]=littlePart;
716 }
717 
718 /* -------------------------------------------------------------------------
719  FUNCTION: HZto64
720  create a 64 bit Hz number from
721  32 bit xxxx MHz number and 32 bit yyy yyy Hz number.
722  A) if an < 2^32 bits
723  an(upper 32b) = 0
724  an(lower 32b) = MHzPart(32b)*1MHz + HzPart (32b)
725  B) if an > 2^32 bits (4,294,967,296)
726  an(upper 32b) = 1
727  an(lower 32b) = ((MHzPart-4294)*1MHz+HzPart)-967296
728 ---------------------------------------------------------------------------- */
729 void HZto64(unsigned long an[], unsigned long MHzPart, unsigned long HzPart )
730 {
731 
732  if ((MHzPart>4295) || ((MHzPart==4294) && (HzPart>=967296)))
733  {
734  an[0]=1L; // upper 32 bits
735  an[1] =(MHzPart-4294L)*OneMHz + HzPart-967296L; // lower 32 bits
736  }
737  else
738  {
739  an[0] = 0; // upper 32 bits
740  an[1] = MHzPart*OneMHz+HzPart; // lower 32 bits
741  }
742 }
743 
744 /* -------------------------------------------------------------------------
745  FUNCTION: shl64
746  Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
747 ---------------------------------------------------------------------------- */
748 void shl64(unsigned long an[])
749 {
750  an[0] <<= 1;
751  if (an[1] & 0x80000000)
752  an[0]++;
753  an[1] <<= 1;
754 }
755 
756 
757 /* -------------------------------------------------------------------------
758  FUNCTION: shr64
759  Single Bit shift right of equivalent 64 bit number (an[] = an[]>>1)
760 ---------------------------------------------------------------------------- */
761 void shr64(unsigned long an[])
762 {
763  an[1] >>= 1;
764  if (an[0] & 0x1)
765  an[1]+=0x80000000;
766  an[0] >>= 1;
767 }
768 
769 
770 /* -------------------------------------------------------------------------
771  FUNCTION: shl64by
772  Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
773 ---------------------------------------------------------------------------- */
774 void shl64by(unsigned long an[], uint8_t shiftnum)
775 {
776  uint8_t i;
777 
778  for (i=0; i<shiftnum; i++)
779  {
780  an[0] <<= 1;
781  if (an[1] & 0x80000000)
782  an[0]++;
783  an[1] <<= 1;
784  }
785 }
786 
787 
788 /* -------------------------------------------------------------------------
789  FUNCTION: shr64by
790  Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
791 ---------------------------------------------------------------------------- */
792 void shr64by(unsigned long an[], uint8_t shiftnum)
793 {
794  uint8_t i;
795 
796  for (i=0; i<shiftnum; i++)
797  {
798  an[1] >>= 1;
799  if (an[0] & 0x1)
800  an[1]+=0x80000000;
801  an[0] >>= 1;
802  }
803 }
804 
805 
806 /* -------------------------------------------------------------------------
807  FUNCTION: add64
808  64 bit Add ann to an (an[] = an[] + ann[])
809 ---------------------------------------------------------------------------- */
810 void add64(unsigned long an[], unsigned long ann[])
811 {
812  an[0]+=ann[0];
813  if (an[1] + ann[1] < ann[1])
814  an[0]++;
815  an[1]+=ann[1];
816 }
817 
818 
819 /* -------------------------------------------------------------------------
820  FUNCTION: sub64
821  64 bit Subtract ann from an (an[] = an[] - ann[])
822 ---------------------------------------------------------------------------- */
823 void sub64(unsigned long an[], unsigned long ann[])
824 {
825  an[0]-=ann[0];
826  if (an[1] < ann[1])
827  {
828  an[0]--;
829  }
830  an[1]-= ann[1];
831 }
832 
833 
834 /* -------------------------------------------------------------------------
835  FUNCTION: eq64
836  64 bit, if an == ann, then true
837 ---------------------------------------------------------------------------- */
838 boolean eq64(unsigned long an[], unsigned long ann[])
839 {
840  return (an[0]==ann[0]) && (an[1]==ann[1]);
841 }
842 
843 
844 /* -------------------------------------------------------------------------
845  FUNCTION: lt64
846  64 bit, if an < ann, then true
847 ---------------------------------------------------------------------------- */
848 boolean lt64(unsigned long an[], unsigned long ann[])
849 {
850  if (an[0]>ann[0]) return false;
851  return (an[0]<ann[0]) || (an[1]<ann[1]);
852 }
853 
854 
855 /* -------------------------------------------------------------------------
856  FUNCTION: div64
857  64 bit Divide, num=num/div
858 ---------------------------------------------------------------------------- */
859 void div64(unsigned long num[], unsigned long den[])
860 {
861  unsigned long quot[2];
862  unsigned long qbit[2];
863  unsigned long tmp[2];
864  init64(quot,0,0);
865  init64(qbit,0,1);
866 
867  if (eq64(num, zero64)) //numerator 0, call it 0
868  {
869  init64(num,0,0);
870  return;
871  }
872 
873  if (eq64(den, zero64)) //numerator not zero, denominator 0, infinity in my book.
874  {
875  init64(num,0xffffffff,0xffffffff);
876  return;
877  }
878 
879  init64(tmp,0x80000000,0);
880  while (lt64(den,tmp))
881  {
882  shl64(den);
883  shl64(qbit);
884  }
885 
886  while (!eq64(qbit,zero64))
887  {
888  if (lt64(den,num) || eq64(den,num))
889  {
890  sub64(num,den);
891  add64(quot,qbit);
892  }
893  shr64(den);
894  shr64(qbit);
895  }
896 
897  //remainder now in num, but using it to return quotient for now
898  init64(num,quot[0],quot[1]);
899 }
900 
901 
902 /* -------------------------------------------------------------------------
903  FUNCTION: mul64
904  64 bit multiply, an=an*ann
905 ---------------------------------------------------------------------------- */
906 void mul64(unsigned long an[], unsigned long ann[])
907 {
908  unsigned long p[2] = {0,0};
909  unsigned long y[2] = {ann[0], ann[1]};
910  while (!eq64(y,zero64))
911  {
912  if (y[1] & 1)
913  add64(p,an);
914  shl64(an);
915  shr64(y);
916  }
917  init64(an,p[0],p[1]);
918 }
boolean lt64(unsigned long an[], unsigned long ann[])
64 bit, if an < ann, then true
Definition: LTC6945.cpp:848
#define LTC6945_CP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:82
unsigned long get_LTC6945_global_VCO_MIN_Hz()
returns global LTC6945_VCO_Min_Freq_Hz
Definition: LTC6945.cpp:497
unsigned long LTC6945_Fref_Hz
Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy.
Definition: LTC6945.cpp:92
void set_LTC6945_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
sets globals LTC6945_Frf_MHz and LTC6945_Frf_Hz
Definition: LTC6945.cpp:446
void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart)
Creates a equivalent 64 bit number from 2 32 bit numbers.
Definition: LTC6945.cpp:712
#define LTC6945_LOCK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:95
long LTC6945_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6945 Read Single Field For SPI FIELDS located in 1 or multiple address location reads specific add...
Definition: LTC6945.cpp:127
#define LTC6945_NUM_REGADDR
Defines number of LTC6945 SPI registers, used in spi_map array.
Definition: LTC6945.h:113
long get_LTC6945_SPI_FIELD(uint8_t cs, uint8_t f)
Gets the LTC6945 SPI field value calls function LTC6945_read_field, which reads specific address loca...
Definition: LTC6945.cpp:163
void sub64(unsigned long an[], unsigned long ann[])
64 bit Subtract ann from an (an[] = an[] - ann[])
Definition: LTC6945.cpp:823
void div64(unsigned long num[], unsigned long den[])
64 bit Divide, num=num/div
Definition: LTC6945.cpp:859
void set_LTC6945_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
Sets the LTC6945 SPI field value calls function LTC6945_read_field, which reads specific address/fiel...
Definition: LTC6945.cpp:274
#define LTC6945_FILT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:91
#define LTC6945_CPRST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:88
void prt(unsigned long an[])
Prints HEX representation of 64 bit an.
Definition: LTC6945.cpp:698
uint8_t LTC6945_read(uint8_t cs, int8_t address)
LTC6945 Read Single Address reads 8 bit Data field to LTC6945.
Definition: LTC6945.cpp:107
#define LTC6945_NUM_REGFIELD
Defines number of LTC6945 SPI fields, used in spi_map array.
Definition: LTC6945.h:114
Header File for Linduino Libraries and Demo Code.
uint8_t get_LTC6945_SPI_FIELD_RW(uint8_t f)
returns if the given field name is (0)read/write or (1)read_only field
Definition: LTC6945.cpp:261
#define LTC6945_LKEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:93
void shl64(unsigned long an[])
Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6945.cpp:748
#define LTC6945_BST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:81
unsigned long LTC6945_calc_odiv(unsigned long frf[2])
calculates the output divider setting based on the frf and on board VCO frequencies of LTC6945 ...
Definition: LTC6945.cpp:508
void shr64(unsigned long an[])
Single Bit shift right of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6945.cpp:761
#define LTC6945_TLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:109
uint8_t get_LTC6945_SPI_FIELD_NUMBITS(uint8_t f)
returns the number of bits for a given field name in the SPI map
Definition: LTC6945.cpp:251
unsigned long get_LTC6945_global_fref_MHz()
returns global LTC6945_Fref_MHz
Definition: LTC6945.cpp:462
#define OneMHz
1MHz in long format, used in 64 bit math
Definition: LTC6945.h:121
boolean eq64(unsigned long an[], unsigned long ann[])
64 bit, if an == ann, then true
Definition: LTC6945.cpp:838
uint8_t LTC6945_reg[LTC6945_NUM_REGADDR]
number of LTC6945 spi addresses
Definition: LTC6945.cpp:88
unsigned long LTC6945_VCO_Min_Freq_MHz
Min Vco frequency for default on board VCO - MHz portion (xxxx); Fvco min = x,xxx, yyy,yyy.
Definition: LTC6945.cpp:96
void LTC6945_init()
Initializes the SPI MAP arrays The values set in initialization are used for all the LTC6945 SPI/WRIT...
Definition: LTC6945.cpp:308
#define LTC6945_PDALL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:100
#define LTC6945_ND
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:96
#define LTC6945_OD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:97
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: LTC6945.cpp:729
uint8_t LTC6945_spi_map[(LTC6945_NUM_REGFIELD+1)][4]
LTC6945 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability.
Definition: LTC6945.cpp:89
void set_LTC6945_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
sets globals LTC6945_Fref_MHz and LTC6945_Fref_Hz
Definition: LTC6945.cpp:440
#define NUMBITS
Definition: LTC6115.h:69
static uint8_t address
Definition: DC2091A.ino:83
unsigned long get_LTC6945_global_fref_Hz()
returns global LTC6945_Fref_Hz
Definition: LTC6945.cpp:467
#define LTC6945_POR
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:104
unsigned long get_LTC6945_global_frf_MHz()
returns global LTC6945_Frf_MHz
Definition: LTC6945.cpp:472
unsigned long LTC6945_Frf_MHz
Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy.
Definition: LTC6945.cpp:93
unsigned long LTC6945_VCO_Min_Freq_Hz
Min Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco min= x,xxx, yyy,yyy.
Definition: LTC6945.cpp:98
#define LTC6945_PDOUT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:101
#define LTC6945_THI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:108
#define LTC6945_PDPLL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:102
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 LTC6945_VCO_Max_Freq_Hz
Max Vco frequency for default on board VCO - Hz portion (yyy,yyy); Fvco max = x,xxx, yyy,yyy.
Definition: LTC6945.cpp:97
void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
Reads and sends a word.
Definition: LT_SPI.cpp:98
void set_LTC6945_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)
Writes values to ALL LTC6945 RW addresses.
Definition: LTC6945.cpp:284
unsigned long get_LTC6945_global_frf_Hz()
returns global LTC6945_Frf_Hz
Definition: LTC6945.cpp:477
#define LTC6945_LKWIN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:94
void LTC6945_set_frf()
FUNCTION: LTC6945_set_frf Calculates the integer (N), fractional (NUM) and output divider (OD) SPI va...
Definition: LTC6945.cpp:583
unsigned long get_LTC6945_global_VCO_MAX_Hz()
returns global LTC6945_VCO_Max_Freq_Hz
Definition: LTC6945.cpp:492
#define LTC6945_CPINV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:86
unsigned long get_LTC6945_global_VCO_MAX_MHz()
returns global LTC6945_VCO_Max_Freq_MHz
Definition: LTC6945.cpp:482
#define LTC6945_CS
Define the SPI CS pin.
Definition: LTC6945.h:76
#define LTC6945_RFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:107
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
unsigned long zero64[]
for 64bit math functions
Definition: LTC6945.cpp:100
#define LTC6945_LKCT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:92
unsigned long LTC6945_Fref_MHz
Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy.
Definition: LTC6945.cpp:91
#define LTC6945_CPMID
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:87
void shr64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
Definition: LTC6945.cpp:792
#define LTC6945_CPDN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:85
void add64(unsigned long an[], unsigned long ann[])
64 bit Add ann to an (an[] = an[] + ann[])
Definition: LTC6945.cpp:810
unsigned long LTC6945_VCO_Max_Freq_MHz
Max Vco frequency for default on board VCO - MHz portion (xxxx); Fvco max = xxx, yyy,yyy.
Definition: LTC6945.cpp:95
#define LTC6945_CPCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:83
#define ADDRx
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:116
#define LTC6945_PART
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:99
#define LTC6945_CPWIDE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:90
#define LTC6945_CPCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:84
uint8_t LTC6945_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6945 Write Single Field For SPI FIELDS in 1 or multiple address locations reads specific address/f...
Definition: LTC6945.cpp:190
void LTC6945_write(uint8_t cs, uint8_t address, uint8_t Data)
LTC6945 Write Single Address writes 8 bit Data field to LTC6945.
Definition: LTC6945.cpp:174
LTC6945: Ultralow Noise and Spurious 0.35GHz to 6GHz Integer-N Synthesizer.
unsigned long get_LTC6945_global_VCO_MIN_MHz()
returns global LTC6945_VCO_Min_Freq_MHz
Definition: LTC6945.cpp:487
#define LTC6945_RD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:105
uint8_t get_LTC6945_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6945.cpp:241
#define LTC6945_x
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:111
This union splits one int16_t (16-bit signed integer) or uint16_t (16-bit unsigned integer) into two ...
Definition: Linduino.h:99
void shl64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
Definition: LTC6945.cpp:774
static int i
Definition: DC2430A.ino:184
#define LTC6945_PDREFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:103
unsigned long LTC6945_Frf_Hz
Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy.
Definition: LTC6945.cpp:94
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 LTC6945_OMUTE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:98
#define LTC6945_UNLOCK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:110
void set_LTC6945_global_vcolim(unsigned long fvco_max_MHz, unsigned long fvco_max_Hz, unsigned long fvco_min_MHz, unsigned long fvco_min_Hz)
sets globals LTC6945_VCO_Max_Freq_MHz, LTC6945_VCO_Max_Freq_Hz, LTC6945_VCO_Min_Freq_MHz and LTC6945_...
Definition: LTC6945.cpp:452
#define LTC6945_REV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:106
void mul64(unsigned long an[], unsigned long ann[])
64 bit multiply, an=an*ann
Definition: LTC6945.cpp:906
#define LTC6945_CPUP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6945.h:89
#define DxMSB
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:117