Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LTC6946.cpp
Go to the documentation of this file.
1 /*!
2 LTC6946: Ultralow Noise and Spurious 0.37GHz to 6.39GHz Integer-N Synthesizer with Integrated VCO
3 
4 @verbatim
5 
6 The LTC®6946 is a high performance, low noise, 6.39GHz
7 phase-locked loop (PLL) with a fully integrated VCO,
8 including a reference divider, phase-frequency detector
9 (PFD) with phase-lock indicator, ultralow noise charge
10 pump, integer feedback divider, and VCO output divider.
11 The charge pump contains selectable high and low voltage
12 clamps useful for VCO monitoring.
13 
14 The integrated low noise VCO uses no external components.
15 It is internally calibrated to the correct output frequency
16 with no external system support.
17 
18 The part features a buffered, programmable VCO output
19 divider with a range of 1 through 6, providing a wide
20 frequency range.
21 
22 @endverbatim
23 
24 
25 http://www.linear.com/product/LTC6946
26 
27 http://www.linear.com/product/LTC6946#demoboards
28 
29 
30 Copyright 2018(c) Analog Devices, Inc.
31 
32 All rights reserved.
33 
34 Redistribution and use in source and binary forms, with or without
35 modification, are permitted provided that the following conditions are met:
36  - Redistributions of source code must retain the above copyright
37  notice, this list of conditions and the following disclaimer.
38  - Redistributions in binary form must reproduce the above copyright
39  notice, this list of conditions and the following disclaimer in
40  the documentation and/or other materials provided with the
41  distribution.
42  - Neither the name of Analog Devices, Inc. nor the names of its
43  contributors may be used to endorse or promote products derived
44  from this software without specific prior written permission.
45  - The use of this software may or may not infringe the patent rights
46  of one or more patent holders. This license does not release you
47  from the requirement that you obtain separate licenses from these
48  patent holders to use this software.
49  - Use of the software either in source or binary form, must be run
50  on or directly connected to an Analog Devices Inc. component.
51 
52 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
53 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
54 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
56 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
58 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
59 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
60 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63 
64 
65 //! @ingroup RF_Timing
66 //! @{
67 //! @defgroup LTC6946 LTC6946: Ultralow Noise and Spurious 0.37GHz to 6.39GHz IntegerN Synthesizer with Integrated VCO
68 //! @}
69 
70 /*! @file
71  @ingroup LTC6946
72  Library for LTC6946: Ultralow Noise and Spurious 0.37GHz to 6.39GHz IntegerN Synthesizer with Integrated VCO
73 */
74 
75 #include <stdint.h>
76 #include <Arduino.h>
77 #include "Linduino.h"
78 #include "UserInterface.h"
79 #include "LT_SPI.h"
80 #include "LTC6946.h"
81 #include <SPI.h>
82 
83 uint8_t LTC6946_reg[LTC6946_NUM_REGADDR]; //!< number of LTC6946 spi addresses
84 uint8_t LTC6946_spi_map[(LTC6946_NUM_REGFIELD+1)][4]; //!< LTC6946 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability
85 
86 unsigned long LTC6946_Fref_MHz = 100; //!< Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy
87 unsigned long LTC6946_Fref_Hz = 0; //!< Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy
88 unsigned long LTC6946_Frf_MHz = 900; //!< Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy
89 unsigned long LTC6946_Frf_Hz = 0; //!< Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy
90 
91 unsigned long zero64[]= {0,0}; //!< for 64bit math functions
92 
93 /* -------------------------------------------------------------------------
94  FUNCTION: LTC6946_read
95  - reads 8 bit Data field to LTC6946.
96  - has to shift data by one bit to account for RW bit
97  -------------------------------------------------------------------------- */
98 uint8_t LTC6946_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  LTC6946_reg[address]=rx.LT_byte[0];
107  return(rx.LT_byte[0]);
108 }
109 
110 
111 /* -------------------------------------------------------------------------
112  FUNCTION: LTC6946_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 LTC6946_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=LTC6946_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_LTC6946_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_LTC6946_SPI_FIELD(uint8_t cs, uint8_t f)
155 {
156 
158 }
159 
160 /* -------------------------------------------------------------------------
161  FUNCTION: LTC6946_write
162  - writes 8 bit Data field to LTC6946.
163  - has to shift data by one bit to account for RW bit
164 --------------------------------------------------------------------------- */
165 void LTC6946_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: LTC6946_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 LTC6946_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=LTC6946_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  LTC6946_write(cs, (address+i), reg_val);
224  } // end of for loop
225 } // end of LTC6946_write_field
226 
227 
228 /* -------------------------------------------------------------------------
229  FUNCTION: get_LTC6946_REGSIZE
230  - returns # of addresses in parts register map (array size)
231 ---------------------------------------------------------------------------- */
233 {
234  return sizeof(LTC6946_reg);
235 }
236 
237 
238 /* -------------------------------------------------------------------------
239  FUNCTION: get_LTC6946_SPI_FIELD_NUMBITS
240  - returns the number of bits for a given field name in the SPI map
241 ---------------------------------------------------------------------------- */
243 {
244  return LTC6946_spi_map[f][NUMBITS];
245 }
246 
247 
248 /* -------------------------------------------------------------------------
249  FUNCTION: get_LTC6946_SPI_FIELD_RW
250  - returns if the given field name is (0)read/write or (1)read_only field
251 ---------------------------------------------------------------------------- */
252 uint8_t get_LTC6946_SPI_FIELD_RW(uint8_t f)
253 {
254  return LTC6946_spi_map[f][R_ONLY];
255 }
256 
257 
258 /* -------------------------------------------------------------------------
259  FUNCTION: set_LTC6946_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_LTC6946_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
266 {
268 }
269 
270 
271 /* -------------------------------------------------------------------------
272  FUNCTION: set_LTC6946_ALLREGS
273  - writes data to all registers at once
274 --------------------------------------------------------------------------- */
275 void set_LTC6946_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)
276 {
277  uint8_t i;
278 
279  LTC6946_reg[1] = reg01;
280  LTC6946_reg[2] = reg02;
281  LTC6946_reg[3] = reg03;
282  LTC6946_reg[4] = reg04;
283  LTC6946_reg[5] = reg05;
284  LTC6946_reg[6] = reg06;
285  LTC6946_reg[7] = reg07;
286  LTC6946_reg[8] = reg08;
287  LTC6946_reg[9] = reg09;
288  LTC6946_reg[10] = reg0A;
289 
290  for (i=1; i<11; i++) LTC6946_write(cs, i, LTC6946_reg[i]);
291 } // end of set_LTC6946_ALLREGS
292 
293 
294 /* -------------------------------------------------------------------------
295  FUNCTION: LTC6946_init
296  - initializes the SPI MAP
297  - for ease of programming there is spreadsheet that automates this some.
298 ----------------------------------------------------------------------------*/
300 {
301 
302 // spi map
426 
468 
469 
470 } // end of LTC6946_init
471 
472 void set_LTC6946_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
473 {
474  LTC6946_Fref_MHz=fref_MHz;
475  LTC6946_Fref_Hz=fref_Hz;
476 }
477 
478 void set_LTC6946_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
479 {
480  LTC6946_Frf_MHz=frf_MHz;
481  LTC6946_Frf_Hz=frf_Hz;
482 }
483 
485 {
486  return LTC6946_Fref_MHz;
487 }
488 
490 {
491  return LTC6946_Fref_Hz;
492 }
493 
495 {
496  return LTC6946_Frf_MHz;
497 }
498 
500 {
501  return LTC6946_Frf_Hz;
502 }
503 
504 
505 /* -------------------------------------------------------------------------
506  FUNCTION: calc_odiv
507  - calculates the output divider setting based on the frf and version of LTC6946
508  - @return odiv = 1-6 for valid setting, 999 as invalid frequency
509 ---------------------------------------------------------------------------- */
510 unsigned long LTC6946_calc_odiv(char part_version[], unsigned long frf[2])
511 {
512  unsigned long odiv, max_fout, min_fout, temp_val,i, temp_out;
513  unsigned long max_fout64[2];
514  unsigned long min_fout64[2];
515  unsigned long temp_fout[2];
516  unsigned long temp_i[2];
517  boolean valid_input=false;
518 
519 // Determine which frequency range to verify too based on part version
520  if (part_version[8]=='1') // if this is a LTC6946-1
521  {
522  max_fout=LTC6946_1_MAXFREQ;
523  min_fout=LTC6946_1_MINFREQ;
524  }
525  else if (part_version[8]=='2') // if this is a LTC6946-2
526  {
527  max_fout=LTC6946_2_MAXFREQ;
528  min_fout=LTC6946_2_MINFREQ;
529  }
530  else if (part_version[8]=='3') // if this is a LTC6946-3
531  {
532  max_fout=LTC6946_3_MAXFREQ;
533  min_fout=LTC6946_3_MINFREQ;
534  }
535  else if (part_version[8]=='4') // if this is a LTC6946-4
536  {
537  max_fout=LTC6946_4_MAXFREQ;
538  min_fout=LTC6946_4_MINFREQ;
539  }
540  else
541  {
542  Serial.print("No default Frequencies for this board: ");
543  Serial.println(part_version);
544  } // end if-then-else statement
545  HZto64(max_fout64,max_fout,0L);
546  HZto64(min_fout64,min_fout,0L);
547 
548 // verify desired frequency falls within a divider range (1-6)
549  valid_input=false;
550  for (i=1; i<=6; i++)
551  {
552  init64(temp_i,0L,i);
553  temp_fout[0] = frf[0];
554  temp_fout[1] = frf[1];
555  mul64(temp_fout,temp_i);
556  if (lt64(temp_fout,max_fout64) || eq64(temp_fout, max_fout64)) // same as frf*i <= max_fout
557  {
558  if (lt64(min_fout64,temp_fout) || eq64(temp_fout, min_fout64)) // same as frf*i >= min_fout
559  {
560  valid_input=true;
561  odiv=i;
562  }
563  }
564  } // end of for loop
565 
566  if (valid_input == false) odiv= 999L;
567  return odiv;
568 
569 } // end of LTC6946_calc_odiv
570 
571 /* -------------------------------------------------------------------------
572  FUNCTION: LTC6946_set_frf
573  Calculates the integer (N) and output divider (OD) SPI values
574  using self created 64bit math functions.
575 
576  Datasheet equations
577  fvco = fpfd*N
578  frf = fvco/O
579  fpfd = fref/R
580 
581  can be modified to the following equations
582  N = (int) (fvco/fpfd) = (int) frf*O*R/fref
583 
584  where
585  N = ndiv, O= odiv, in the code below
586 
587  Linduino One (Arduino Uno) is limited to 32 bit floats/double/long.
588  32 bit math functions will create rounding errors with the above equations,
589  tha can result in frequency errors.
590  Therefore, the following code uses self created 64bit functions for 64bit integer math.
591 
592  - frf (33 bits) LTC6946 max frf/fvco = 6.0GHZ, which is 23 bit number (2^33 = 8.59G)
593  - fref (23 bits) LTC6946 min fref = 10MHz, which is a 23 bit number (2^23 = 8.3M)
594  - O (3 bits)
595  - R (10 bits)
596 
597  step 1: create 64 bit frf and fref numbers
598 
599  step 2: calculate O (output divider)
600 
601  step 3: get current R-divider setting
602 
603  step 4: calculate frf*O*R
604  max bit count/resolution: 33b+3b+10b= 46b
605  step 5: calculate N(16b), using value from step 1
606  - N = (int) frf*O*R/fref
607  - max bit count/resolution: 46b-23b = 13b
608 ---------------------------------------------------------------------------- */
609 void LTC6946_set_frf(char part_version[])
610 {
611  unsigned long frf_MHz, frf_Hz, fref_MHz, fref_Hz, odiv, rdiv, ndiv, N_remainder, temp_val;
612  unsigned long N64[2], R64[2], O64[2], temp_long[2];
613  char buffer[100];
614  unsigned long frf[2], frf_act[2];
615  unsigned long fref[2];
616  unsigned long temp_math[2];
617  unsigned long frf_rdiv_odiv[2];
618  unsigned long frf_rdiv_odiv_int[2];
619  unsigned long roundup[2];
620  uint8_t regval;
621  uint8_t address;
622  uint8_t tx1;
623  uint8_t tx2;
624  uint8_t tx3;
625  uint8_t tx4;
626  uint8_t tx5;
627  uint8_t *rx;
628  /* step 1: create 64 bit frf and fref numbers
629  32 bit xxxx MHz number and 32 bit yyy yyy Hz number. */
630  frf_MHz=LTC6946_Frf_MHz;
631  frf_Hz=LTC6946_Frf_Hz;
632  HZto64(frf, frf_MHz, frf_Hz);
633 
634  fref_MHz=LTC6946_Fref_MHz;
635  fref_Hz=LTC6946_Fref_Hz;
636  HZto64(fref,fref_MHz,fref_Hz);
637 
638 // step 2: calculate O (output divider)
639  odiv=LTC6946_calc_odiv(part_version,frf);
640 
641 // step 3: get current R-divider setting
642 #if 1
643  rdiv=get_LTC6946_SPI_FIELD(LTC6946_CS,LTC6946_RD); // reads selected field
644 #endif
645 
646 
647 // step 4: calculate frf*O*R
648  frf_rdiv_odiv[0]=0;
649  frf_rdiv_odiv[1]=odiv*rdiv;
650  mul64(frf_rdiv_odiv, frf); // odiv*rdiv*frf
651  frf_rdiv_odiv_int[0]=frf_rdiv_odiv[0]; // copy odiv*rdiv*frf to another variable
652  frf_rdiv_odiv_int[1]=frf_rdiv_odiv[1];
653 
654 // step 5: calculate N(16b), using value from step 3; N = (int) frf*O*R/fref
655  temp_math[0]=fref[0]; // copy fref to temp variable for math operation
656  temp_math[1]=fref[1];
657  div64(frf_rdiv_odiv_int, temp_math); // frf_rdiv_odiv_int= [(frf*odiv*rdiv)]/fref --> int(fvco/fpfd)
658  ndiv=frf_rdiv_odiv_int[1];
659 
660 // step 6: find N for closest frequency - accounts for rounding with integer math
661  temp_math[0]=fref[0]; // copy fref to temp variable for math operation
662  temp_math[1]=fref[1];
663  shl64by(frf_rdiv_odiv,13); // frf_rdiv_odiv --> [(frf*odiv*rdiv)<<13]/fref = N(double) <<13
664  div64(frf_rdiv_odiv,temp_math);
665  shl64by(frf_rdiv_odiv_int,13); // frf_rdiv_odiv_int --> [(int)((frf*odiv*rdiv)/fref)] <<13 = N(int) <<13
666  sub64(frf_rdiv_odiv,frf_rdiv_odiv_int); // N(double) <<13 - N(int)<<13
667 
668 // at this point frf_rdiv_odiv is the delta between N(double) and N(int) shifted by 13 bits.
669 // if this remainder is < 4096, N(int) will give the closest frequency
670 // if this remainder is >=4096, N(int)+1 will give the closest frequency
671 // 4096 is mid point of the 13 bit number range
672  N_remainder = (frf_rdiv_odiv[1] & 8191L); // 13 bits max code = 8191
673  if (N_remainder >= 4096)
674  {
675  ndiv=ndiv+1;
676  }
677 
678 
679 // program part and print out results to screen
680  set_LTC6946_SPI_FIELD(LTC6946_CS,LTC6946_OD,odiv); // programs output divider
681  Serial.print("OD = ");
682  Serial.println(odiv);
683 
684  Serial.print("RD = ");
685  Serial.println(rdiv);
686 
687  Serial.print(F("ND = "));
688  Serial.println(ndiv);
689 #if 1
690  /* ------------single byte transfer method ---------------- */
691  set_LTC6946_SPI_FIELD(LTC6946_CS,LTC6946_ND,ndiv); // programs N-divider
692 
693 // calibrate the part
694  address = 0x07;
695  regval = 0x63; // sets ALCMON=1, ALCCAL=1, LKEN=1 and CAL=1
696  LTC6946_write(LTC6946_CS, address, regval);
697 #endif
698 
699 #if 0
700  /* ------------multi byte transfer method ---------------- */
701  tx1=5<<1; // shift 1 bit to account for write bit=0
702  tx2=(0xff00 & ndiv)>>8;
703  tx3=(0xff & ndiv);
704  tx4=0x63;
705  tx5 = LTC6946_read(LTC6946_CS,8);
706  Serial.print(F("tx1 = "));
707  Serial.println(tx1);
708  Serial.print(F("tx2 = "));
709  Serial.println(tx2);
710  Serial.print(F("tx3 = "));
711  Serial.println(tx3);
712  Serial.print(F("tx4 = "));
713  Serial.println(tx4);
714  Serial.print(F("tx5 = "));
715  Serial.println(tx5);
716  temp_val = read_int(); //! Reads the user command
717  output_low(QUIKEVAL_CS); //! 1) Pull CS low
718  *rx = SPI.transfer(tx1); //! 2) Read byte and send byte
719  *rx = SPI.transfer(tx2); //! 2) Read byte and send byte
720  *rx = SPI.transfer(tx3); //! 2) Read byte and send byte
721  *rx = SPI.transfer(tx4); //! 2) Read byte and send byte
722  *rx = SPI.transfer(tx5); //! 2) Read byte and send byte
723  output_high(QUIKEVAL_CS); //! 3) Pull CS high
724 #endif
725 
726 ///// calculate actual fout here and print out
727  frf_act[0]=fref[0];
728  frf_act[1]=fref[1];
729  N64[0]=0;
730  R64[0]=0;
731  O64[0]=0;
732  N64[1]=ndiv;
733  R64[1]=rdiv;
734  O64[1]=odiv;
735 
736  mul64(frf_act,N64); // N*fref
737  div64(frf_act,R64); // N*fref/rdiv (or N*fpfd)
738  div64(frf_act,O64); // N*fpdf/odiv
739  if (frf_act[0]==0) // no 32 bit overflow case
740  {
741  Serial.print(F("Actual Output Frequency (closest available) is "));
742  Serial.print(frf_act[1]);
743  Serial.println("Hz");
744  }
745  else // overflow case
746  {
747  temp_math[0]=frf_act[0];
748  temp_math[1]=frf_act[1];
749  temp_long[0]=0;
750  temp_long[1]=OneMHz;
751  div64(temp_math,temp_long); // frf/1e6
752  Serial.print(F("Actual Output Frequency (closest available) is "));
753  Serial.print(temp_math[1]);
754  Serial.print("MHz + ");
755  temp_long[0]=0;
756  temp_long[1]=OneMHz;
757  mul64(temp_math,temp_long); // int(frf/1e6)*1e6
758  sub64(frf_act,temp_math); // frf-int(frf/1e6)*1e6
759  Serial.print(frf_act[1]);
760  Serial.println("Hz");
761  }
762 }
763 
764 
765 /* -------------------------------------------------------------------------
766  FUNCTION: prt
767  Prints HEX representation of 64 bit an
768 ---------------------------------------------------------------------------- */
769 void prt(unsigned long an[])
770 {
771  Serial.print(an[0],HEX);
772  Serial.print(" ");
773  Serial.println(an[1],HEX);
774 }
775 
776 
777 /* -------------------------------------------------------------------------
778  FUNCTION: init64
779  Creates a equivalent 64 bit number from 2 32 bit numbers
780  an[0]=bigPart //upper 32 bits
781  an[1]=littlePart //lower 32 bits
782 ---------------------------------------------------------------------------- */
783 void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart )
784 {
785  an[0]=bigPart;
786  an[1]=littlePart;
787 }
788 
789 /* -------------------------------------------------------------------------
790  FUNCTION: HZto64
791  create a 64 bit Hz number from
792  32 bit xxxx MHz number and 32 bit yyy yyy Hz number.
793  A) if an < 2^32 bits
794  an(upper 32b) = 0
795  an(lower 32b) = MHzPart(32b)*1MHz + HzPart (32b)
796  B) if an > 2^32 bits (4,294,967,296)
797  an(upper 32b) = 1
798  an(lower 32b) = ((MHzPart-4294)*1MHz+HzPart)-967296
799 ---------------------------------------------------------------------------- */
800 void HZto64(unsigned long an[], unsigned long MHzPart, unsigned long HzPart )
801 {
802 
803  if ((MHzPart>4295) || ((MHzPart==4294) && (HzPart>=967296)))
804  {
805  an[0]=1L; // upper 32 bits
806  an[1] =(MHzPart-4294L)*OneMHz + HzPart-967296L; // lower 32 bits
807  }
808  else
809  {
810  an[0] = 0; // upper 32 bits
811  an[1] = MHzPart*OneMHz+HzPart; // lower 32 bits
812  }
813 }
814 
815 /* -------------------------------------------------------------------------
816  FUNCTION: shl64
817  Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
818 ---------------------------------------------------------------------------- */
819 void shl64(unsigned long an[])
820 {
821  an[0] <<= 1;
822  if (an[1] & 0x80000000)
823  an[0]++;
824  an[1] <<= 1;
825 }
826 
827 
828 /* -------------------------------------------------------------------------
829  FUNCTION: shr64
830  Single Bit shift right of equivalent 64 bit number (an[] = an[]>>1)
831 ---------------------------------------------------------------------------- */
832 void shr64(unsigned long an[])
833 {
834  an[1] >>= 1;
835  if (an[0] & 0x1)
836  an[1]+=0x80000000;
837  an[0] >>= 1;
838 }
839 
840 
841 /* -------------------------------------------------------------------------
842  FUNCTION: shl64by
843  Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
844 ---------------------------------------------------------------------------- */
845 void shl64by(unsigned long an[], uint8_t shiftnum)
846 {
847  uint8_t i;
848 
849  for (i=0; i<shiftnum; i++)
850  {
851  an[0] <<= 1;
852  if (an[1] & 0x80000000)
853  an[0]++;
854  an[1] <<= 1;
855  }
856 }
857 
858 
859 /* -------------------------------------------------------------------------
860  FUNCTION: shr64by
861  Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
862 ---------------------------------------------------------------------------- */
863 void shr64by(unsigned long an[], uint8_t shiftnum)
864 {
865  uint8_t i;
866 
867  for (i=0; i<shiftnum; i++)
868  {
869  an[1] >>= 1;
870  if (an[0] & 0x1)
871  an[1]+=0x80000000;
872  an[0] >>= 1;
873  }
874 }
875 
876 
877 /* -------------------------------------------------------------------------
878  FUNCTION: add64
879  64 bit Add ann to an (an[] = an[] + ann[])
880 ---------------------------------------------------------------------------- */
881 void add64(unsigned long an[], unsigned long ann[])
882 {
883  an[0]+=ann[0];
884  if (an[1] + ann[1] < ann[1])
885  an[0]++;
886  an[1]+=ann[1];
887 }
888 
889 
890 /* -------------------------------------------------------------------------
891  FUNCTION: sub64
892  64 bit Subtract ann from an (an[] = an[] - ann[])
893 ---------------------------------------------------------------------------- */
894 void sub64(unsigned long an[], unsigned long ann[])
895 {
896  an[0]-=ann[0];
897  if (an[1] < ann[1])
898  {
899  an[0]--;
900  }
901  an[1]-= ann[1];
902 }
903 
904 
905 /* -------------------------------------------------------------------------
906  FUNCTION: eq64
907  64 bit, if an == ann, then true
908 ---------------------------------------------------------------------------- */
909 boolean eq64(unsigned long an[], unsigned long ann[])
910 {
911  return (an[0]==ann[0]) && (an[1]==ann[1]);
912 }
913 
914 
915 /* -------------------------------------------------------------------------
916  FUNCTION: lt64
917  64 bit, if an < ann, then true
918 ---------------------------------------------------------------------------- */
919 boolean lt64(unsigned long an[], unsigned long ann[])
920 {
921  if (an[0]>ann[0]) return false;
922  return (an[0]<ann[0]) || (an[1]<ann[1]);
923 }
924 
925 
926 /* -------------------------------------------------------------------------
927  FUNCTION: div64
928  64 bit Divide, num=num/div
929 ---------------------------------------------------------------------------- */
930 void div64(unsigned long num[], unsigned long den[])
931 {
932  unsigned long quot[2];
933  unsigned long qbit[2];
934  unsigned long tmp[2];
935  init64(quot,0,0);
936  init64(qbit,0,1);
937 
938  if (eq64(num, zero64)) //numerator 0, call it 0
939  {
940  init64(num,0,0);
941  return;
942  }
943 
944  if (eq64(den, zero64)) //numerator not zero, denominator 0, infinity in my book.
945  {
946  init64(num,0xffffffff,0xffffffff);
947  return;
948  }
949 
950  init64(tmp,0x80000000,0);
951  while (lt64(den,tmp))
952  {
953  shl64(den);
954  shl64(qbit);
955  }
956 
957  while (!eq64(qbit,zero64))
958  {
959  if (lt64(den,num) || eq64(den,num))
960  {
961  sub64(num,den);
962  add64(quot,qbit);
963  }
964  shr64(den);
965  shr64(qbit);
966  }
967 
968  //remainder now in num, but using it to return quotient for now
969  init64(num,quot[0],quot[1]);
970 }
971 
972 
973 /* -------------------------------------------------------------------------
974  FUNCTION: mul64
975  64 bit multiply, an=an*ann
976 ---------------------------------------------------------------------------- */
977 void mul64(unsigned long an[], unsigned long ann[])
978 {
979  unsigned long p[2] = {0,0};
980  unsigned long y[2] = {ann[0], ann[1]};
981  while (!eq64(y,zero64))
982  {
983  if (y[1] & 1)
984  add64(p,an);
985  shl64(an);
986  shr64(y);
987  }
988  init64(an,p[0],p[1]);
989 }
void sub64(unsigned long an[], unsigned long ann[])
64 bit Subtract ann from an (an[] = an[] - ann[])
Definition: LTC6946.cpp:894
#define LTC6946_THI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:118
void shl64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
Definition: LTC6946.cpp:845
void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart)
Creates a equivalent 64 bit number from 2 32 bit numbers.
Definition: LTC6946.cpp:783
void mul64(unsigned long an[], unsigned long ann[])
64 bit multiply, an=an*ann
Definition: LTC6946.cpp:977
void prt(unsigned long an[])
Prints HEX representation of 64 bit an.
Definition: LTC6946.cpp:769
unsigned long LTC6946_Frf_Hz
Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy.
Definition: LTC6946.cpp:89
unsigned long get_LTC6946_global_fref_MHz()
returns global LTC6946_Fref_MHz
Definition: LTC6946.cpp:484
#define LTC6946_NUM_REGFIELD
Defines number of LTC6946 SPI fields, used in spi_map array.
Definition: LTC6946.h:125
void LTC6946_init()
Initializes the SPI MAP arrays The values set in initialization are used all the LTC6946 SPI/WRITE an...
Definition: LTC6946.cpp:299
#define LTC6946_TLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:119
#define LTC6946_CPINV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:94
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
Header File for Linduino Libraries and Demo Code.
#define LTC6946_CP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:90
void shr64(unsigned long an[])
Single Bit shift right of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6946.cpp:832
#define LTC6946_2_MINFREQ
LTC6946-2 lower freq limit.
Definition: LTC6946.h:140
#define LTC6946_4_MINFREQ
LTC6946-4 lower freq limit.
Definition: LTC6946.h:142
#define LTC6946_RD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:115
#define LTC6946_REV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:116
#define LTC6946_ALCULOK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:86
#define OneMHz
1MHz in long format, used in 64 bit math
Definition: LTC6945.h:121
#define LTC6946_CS
Define the SPI CS pin.
Definition: LTC6946.h:76
#define LTC6946_NUM_REGADDR
Defines number of LTC6946 SPI registers, used in spi_map array.
Definition: LTC6946.h:124
#define LTC6946_3_MINFREQ
LTC6946-3 lower freq limit.
Definition: LTC6946.h:141
#define LTC6946_3_MAXFREQ
LTC6946-3 upper freq limit.
Definition: LTC6946.h:136
#define LTC6946_PDOUT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:110
boolean eq64(unsigned long an[], unsigned long ann[])
64 bit, if an == ann, then true
Definition: LTC6946.cpp:909
void shl64(unsigned long an[])
Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6946.cpp:819
uint8_t LTC6946_spi_map[(LTC6946_NUM_REGFIELD+1)][4]
LTC6946 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability.
Definition: LTC6946.cpp:84
#define LTC6946_BD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:87
unsigned long LTC6946_Fref_Hz
Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy.
Definition: LTC6946.cpp:87
#define LTC6946_OD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:106
#define LTC6946_ALCMON
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:85
#define NUMBITS
Definition: LTC6115.h:69
static uint8_t address
Definition: DC2091A.ino:83
#define LTC6946_CPWIDE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:98
uint8_t get_LTC6946_SPI_FIELD_NUMBITS(uint8_t f)
returns the number of bits for a given field name in the SPI map
Definition: LTC6946.cpp:242
void set_LTC6946_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 LTC6946 RW address.
Definition: LTC6946.cpp:275
#define LTC6946_MTCAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:104
#define LTC6946_ALCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:84
unsigned long get_LTC6946_global_fref_Hz()
returns global LTC6946_Fref_Hz
Definition: LTC6946.cpp:489
#define LTC6946_PDVCO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:113
#define LTC6946_LKEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:101
#define LTC6946_FILT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:99
#define LTC6946_ALCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:83
#define LTC6946_1_MAXFREQ
LTC6946-1 upper freq limit.
Definition: LTC6946.h:134
uint16_t LT_uint16
16-bit unsigned integer to be converted to two bytes
Definition: Linduino.h:102
unsigned long LTC6946_calc_odiv(char part_version[], unsigned long frf[2])
calculates the output divider setting based on the frf and version of LTC6946
Definition: LTC6946.cpp:510
#define LTC6946_1_MINFREQ
LTC6946-1 lower freq limit.
Definition: LTC6946.h:139
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
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: LTC6946.cpp:800
#define R_ONLY
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:119
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_LTC6946_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
Sets the LTC6946 SPI field value calls function LTC6946_read_field, which reads specific address/fiel...
Definition: LTC6946.cpp:265
#define LTC6946_CPRST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:96
uint8_t LTC6946_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6946 Write Single Field For SPI FIELDS in 1 or multiple address locations reads specific address/f...
Definition: LTC6946.cpp:181
uint8_t get_LTC6946_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6946.cpp:232
#define LTC6946_PDREFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:112
#define LTC6946_BST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:88
void LTC6946_write(uint8_t cs, uint8_t address, uint8_t Data)
LTC6946 Write Single Address writes 8 bit Data field to LTC6946.
Definition: LTC6946.cpp:165
#define LTC6946_CAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:89
#define LTC6946_LOCK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:103
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
LTC6946: Ultralow Noise and Spurious 0.37GHz to 6.39GHz Integer-N Synthesizer with Integrated VCO...
#define LTC6946_PDALL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:109
unsigned long zero64[]
for 64bit math functions
Definition: LTC6946.cpp:91
#define LTC6946_4_MAXFREQ
LTC6946-4 upper freq limit.
Definition: LTC6946.h:137
#define ADDRx
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:116
#define LTC6946_ALCCAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:81
unsigned long get_LTC6946_global_frf_MHz()
returns global LTC6946_Frf_MHz
Definition: LTC6946.cpp:494
#define LTC6946_RFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:117
void LTC6946_set_frf(char part_version[])
FUNCTION: LTC6946_set_frf Calculates the integer (N), fractional (NUM) and output divider (OD) SPI va...
Definition: LTC6946.cpp:609
void shr64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
Definition: LTC6946.cpp:863
int32_t read_int()
unsigned long LTC6946_Frf_MHz
Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy.
Definition: LTC6946.cpp:88
unsigned long LTC6946_Fref_MHz
Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy.
Definition: LTC6946.cpp:86
long LTC6946_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6946 Read Single Field For SPI FIELDS located in 1 or multiple address locations reads specific ad...
Definition: LTC6946.cpp:118
#define LTC6946_ALCEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:82
#define LTC6946_UNLOK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:120
This union splits one int16_t (16-bit signed integer) or uint16_t (16-bit unsigned integer) into two ...
Definition: Linduino.h:99
void add64(unsigned long an[], unsigned long ann[])
64 bit Add ann to an (an[] = an[] + ann[])
Definition: LTC6946.cpp:881
void set_LTC6946_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
sets globals LTC6946_Frf_MHz and LTC6946_Frf_Hz
Definition: LTC6946.cpp:478
#define LTC6946_LKWIN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:102
#define LTC6946_PDPLL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:111
boolean lt64(unsigned long an[], unsigned long ann[])
64 bit, if an < ann, then true
Definition: LTC6946.cpp:919
unsigned long get_LTC6946_global_frf_Hz()
returns global LTC6946_Frf_Hz
Definition: LTC6946.cpp:499
#define LTC6946_LKCT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:100
#define LTC6946_2_MAXFREQ
LTC6946-2 upper freq limit.
Definition: LTC6946.h:135
#define LTC6946_CPUP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:97
static int i
Definition: DC2430A.ino:184
#define LTC6946_OMUTE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:107
#define LTC6946_CPCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:91
uint8_t LTC6946_read(uint8_t cs, int8_t address)
LTC6946 Read Single Address reads 8 bit Data field to LTC6946.
Definition: LTC6946.cpp:98
#define LTC6946_x
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:121
uint8_t get_LTC6946_SPI_FIELD_RW(uint8_t f)
returns if the given field name is (0)read/write or (1)read_only field
Definition: LTC6946.cpp:252
#define LTC6946_PART
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:108
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 QUIKEVAL_CS
QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin...
Definition: Linduino.h:57
uint8_t LTC6946_reg[LTC6946_NUM_REGADDR]
number of LTC6946 spi addresses
Definition: LTC6946.cpp:83
#define LTC6946_POR
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:114
#define LTC6946_CPDN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:93
long get_LTC6946_SPI_FIELD(uint8_t cs, uint8_t f)
Gets the LTC6946 SPI field value calls function LTC6946_read_field, which reads specific address loca...
Definition: LTC6946.cpp:154
#define LTC6946_CPCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:92
void div64(unsigned long num[], unsigned long den[])
64 bit Divide, num=num/div
Definition: LTC6946.cpp:930
#define LTC6946_ND
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:105
void set_LTC6946_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
sets globals LTC6946_Fref_MHz and LTC6946_Fref_Hz
Definition: LTC6946.cpp:472
#define LTC6946_CPMID
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6946.h:95
#define DxMSB
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:117