| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

LTC6948.cpp
Go to the documentation of this file.
1 /*!
2 LTC6948: Ultralow Noise and Spurious 0.37GHz to 6.39GHz FracN Synthesizer with Integrated VCO
3
4 @verbatim
5
6 The LTC®6948 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), ultralow noise charge pump, fractional feedback
10 divider, and VCO output divider.
11
12 The fractional divider uses an advanced, 4th order ΔΣ
13 modulator which provides exceptionally low spurious
14 levels. This allows wide loop bandwidths, producing extremely
15 low integrated phase noise values.
16
17 The programmable VCO output divider, with a range of 1
18 through 6, extends the output frequency range.
19
20 @endverbatim
21
22
23 http://www.linear.com/product/LTC6948
24
25 http://www.linear.com/product/LTC6948#demoboards
26
27
28 Copyright 2018(c) Analog Devices, Inc.
29
30 All rights reserved.
31
32 Redistribution and use in source and binary forms, with or without
33 modification, are permitted provided that the following conditions are met:
34 - Redistributions of source code must retain the above copyright
35 notice, this list of conditions and the following disclaimer.
36 - Redistributions in binary form must reproduce the above copyright
37 notice, this list of conditions and the following disclaimer in
38 the documentation and/or other materials provided with the
39 distribution.
40 - Neither the name of Analog Devices, Inc. nor the names of its
41 contributors may be used to endorse or promote products derived
42 from this software without specific prior written permission.
43 - The use of this software may or may not infringe the patent rights
44 of one or more patent holders. This license does not release you
45 from the requirement that you obtain separate licenses from these
46 patent holders to use this software.
47 - Use of the software either in source or binary form, must be run
48 on or directly connected to an Analog Devices Inc. component.
49
50 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
51 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
52 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
54 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
56 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 */
61
62 //! @ingroup RF_Timing
63 //! @{
64 //! @defgroup LTC6948 LTC6948: Ultralow Noise and Spurious 0.37GHz to 6.39GHz FracN Synthesizer with Integrated VCO
65 //! @}
66
67 /*! @file
68 @ingroup LTC6948
69 Library for LTC6948: Ultralow Noise and Spurious 0.37GHz to 6.39GHz FracN Synthesizer with Integrated VCO
70 */
71
72 #include <stdint.h>
73 #include <Arduino.h>
74 #include "Linduino.h"
75 #include "UserInterface.h"
76 #include "LT_SPI.h"
77 #include "LTC6948.h"
78 #include <SPI.h>
79
80 uint8_t LTC6948_reg[LTC6948_NUM_REGADDR]; //!< number of LTC6948 spi addresses
81 uint8_t LTC6948_spi_map[(LTC6948_NUM_REGFIELD+1)][4]; //!< LTC6948 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability
82
83 unsigned long LTC6948_Fref_MHz = 100; //!< Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy
84 unsigned long LTC6948_Fref_Hz = 0; //!< Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy
85 unsigned long LTC6948_Frf_MHz = 907; //!< Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy
86 unsigned long LTC6948_Frf_Hz = 0; //!< Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy
87
88 unsigned long zero64[]= {0,0}; //!< for 64bit math functions
89
90 /* -------------------------------------------------------------------------
91 FUNCTION: LTC6948_read
92 - reads 8 bit Data field to LTC6948.
93 - has to shift data by one bit to account for RW bit
94 -------------------------------------------------------------------------- */
95 uint8_t LTC6948_read(uint8_t cs, int8_t address)
96 {
97 int8_t address_shift;
98 LT_union_int16_2bytes rx;
99
100 address_shift =(address << 1) | 0x01; // shift to left to account for R/W bit, set bit high for read
101 spi_transfer_word(cs, address_shift<<8 , &rx.LT_uint16);
102
103 LTC6948_reg[address]=rx.LT_byte[0];
104 return(rx.LT_byte[0]);
105 }
106
107
108 /* -------------------------------------------------------------------------
109 FUNCTION: LTC6948_read_field
110 For SPI FIELDS located in 1 or multiple address location
111 - reads specific address locations
112 - identifies and returns specific field in question
113 - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
114 --------------------------------------------------------------------------- */
115 long LTC6948_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
116 {
117 int bit_shift, i, num_reg;
118 long field_val, maskbits, pow2;
119
120 num_reg=0;
121 field_val=0;
122 // determines how many register are used
123 do
124 {
125 bit_shift = (MSB_loc+1)- (numbits-num_reg*8); // determines bit_shift for last register location
126 field_val=LTC6948_read(cs, (address+num_reg))+(field_val<<8); // reads current address locations, shifts previous address location 8 bits
127 num_reg++;
128 }
129 while ((bit_shift<0) && (num_reg<4));
130
131 // creates a bit mask for complete word,
132 maskbits = 1;
133 pow2=1;
134 for (i=1, maskbits=1; i<numbits; i++)
135 {
136 pow2=pow2*2;
137 maskbits = maskbits+pow2;
138 }
139
140 field_val=(field_val >>bit_shift) &maskbits;
141 return field_val;
142 }
143
144 /* -------------------------------------------------------------------------
145 FUNCTION: get_LTC6948_SPI_FIELD
146 For SPI FIELDS
147 - reads specific address locations
148 - identifies and returns specific field in question
149 - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
150 --------------------------------------------------------------------------- */
151 long get_LTC6948_SPI_FIELD(uint8_t cs, uint8_t f)
152 {
153
154 return LTC6948_read_field(cs, LTC6948_spi_map[f][ADDRx], LTC6948_spi_map[f][DxMSB], LTC6948_spi_map[f][NUMBITS]);
155 }
156
157 /* -------------------------------------------------------------------------
158 FUNCTION: LTC6948_write
159 - writes 8 bit Data field to LTC6948.
160 - has to shift data by one bit to account for RW bit
161 --------------------------------------------------------------------------- */
162 void LTC6948_write(uint8_t cs, uint8_t address, uint8_t Data)
163 {
164 LT_union_int16_2bytes rx;
165
166 address=address << 1; // shift to left to account for R/W bit
167 spi_transfer_word(cs, (address<<8) | Data, &rx.LT_uint16);
168 }
169
170
171 /* -------------------------------------------------------------------------
172 FUNCTION: LTC6948_write_field
173 For SPI FIELDS
174 - reads specific address location
175 - identifies and returns specific field in question
176 - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
177 ---------------------------------------------------------------------------- */
178 uint8_t LTC6948_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
179 {
180 long current_content, desired_content, reg_val;
181 int LSB_loc, i, j, num_reg, bit_shift;
182 long temp_arr[32];
183
184 for (i=0; i<32 ; i++) temp_arr[i]=0; // init temp_arr
185
186 // read data in current address location and put in a bit array
187 num_reg=0;
188 current_content=0;
189 do
190 {
191 bit_shift=(MSB_loc+1)-(numbits-num_reg*8);
192 current_content=LTC6948_read(cs, (address+num_reg)) + (current_content<<8);
193
194 num_reg++;
195 }
196 while ((bit_shift<0) && (num_reg<4));
197 for (i=0; i<(8*num_reg); i++)
198 {
199 temp_arr[i]=(current_content>>i) & 1;
200 }
201
202 // exchange current bits with desired bits
203 LSB_loc = 8*(num_reg-1)+MSB_loc-numbits+1;
204 for (i=LSB_loc, j=0; i<=(MSB_loc+(num_reg-1)*8); i++, j++)
205 {
206 temp_arr[i] = (field_data>>j) &1;
207 } // end of for loop
208
209 // reconstruct bits into an integer
210 desired_content = 0;
211 for (i=0; i<(8*num_reg); i++)
212 {
213 desired_content = desired_content | (temp_arr[i]<<i);
214 } // end of for loop
215
216 // write new field value to part
217 for (i=0; i<num_reg; i++)
218 {
219 reg_val = (desired_content >> 8*(num_reg-1-i)) & 0xff;
220 LTC6948_write(cs, (address+i), reg_val);
221 } // end of for loop
222 } // end of LTC6948_write_field
223
224
225 /* -------------------------------------------------------------------------
226 FUNCTION: get_LTC6948_REGSIZE
227 - returns # of addresses in parts register map (array size)
228 ---------------------------------------------------------------------------- */
229 uint8_t get_LTC6948_REGSIZE()
230 {
231 return sizeof(LTC6948_reg);
232 }
233
234
235 /* -------------------------------------------------------------------------
236 FUNCTION: get_LTC6948_SPI_FIELD_NUMBITS
237 - returns the number of bits for a given field name in the SPI map
238 ---------------------------------------------------------------------------- */
239 uint8_t get_LTC6948_SPI_FIELD_NUMBITS(uint8_t f)
240 {
241 return LTC6948_spi_map[f][NUMBITS];
242 }
243
244
245 /* -------------------------------------------------------------------------
246 FUNCTION: get_LTC6948_SPI_FIELD_RW
247 - returns if the given field name is (0)read/write or (1)read_only field
248 ---------------------------------------------------------------------------- */
249 uint8_t get_LTC6948_SPI_FIELD_RW(uint8_t f)
250 {
251 return LTC6948_spi_map[f][R_ONLY];
252 }
253
254
255 /* -------------------------------------------------------------------------
256 FUNCTION: set_LTC6948_SPI_FIELD
257 For SPI FIELDS
258 - reads specific address location
259 - identifies and returns specific field in question
260 - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
261 ---------------------------------------------------------------------------- */
262 void set_LTC6948_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
263 {
264 LTC6948_write_field(cs, field_data, LTC6948_spi_map[f][ADDRx], LTC6948_spi_map[f][DxMSB], LTC6948_spi_map[f][NUMBITS]);
265 }
266
267
268 /* -------------------------------------------------------------------------
269 FUNCTION: set_LTC6948_ALLREGS
270 - writes data to all registers at once
271 --------------------------------------------------------------------------- */
272 void set_LTC6948_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)
273 {
274 uint8_t i;
275
276 LTC6948_reg[1] = reg01;
277 LTC6948_reg[2] = reg02;
278 LTC6948_reg[3] = reg03;
279 LTC6948_reg[4] = reg04;
280 LTC6948_reg[5] = reg05;
281 LTC6948_reg[6] = reg06;
282 LTC6948_reg[7] = reg07;
283 LTC6948_reg[8] = reg08;
284 LTC6948_reg[9] = reg09;
285 LTC6948_reg[10] = reg0A;
286 LTC6948_reg[11] = reg0B;
287 LTC6948_reg[12] = reg0C;
288 LTC6948_reg[13] = reg0D;
289
290 for (i=1; i<14; i++) LTC6948_write(cs, i, LTC6948_reg[i]);
291 } // end of set_LTC6948_ALLREGS
292
293
294 /* -------------------------------------------------------------------------
295 FUNCTION: LTC6948_init
296 - initializes the SPI MAP
297 - for ease of programming there is spreadsheet that automates this some.
298 ----------------------------------------------------------------------------*/
299 void LTC6948_init()
300 {
301
302 // spi map
303 LTC6948_spi_map[LTC6948_ALCCAL][ADDRx]=0x03;
304 LTC6948_spi_map[LTC6948_ALCCAL][DxMSB]= 5;
305 LTC6948_spi_map[LTC6948_ALCCAL][NUMBITS]= 1;
306 LTC6948_spi_map[LTC6948_ALCEN][ADDRx]=0x03;
307 LTC6948_spi_map[LTC6948_ALCEN][DxMSB]= 7;
308 LTC6948_spi_map[LTC6948_ALCEN][NUMBITS]= 1;
309 LTC6948_spi_map[LTC6948_ALCHI][ADDRx]=0x00;
310 LTC6948_spi_map[LTC6948_ALCHI][DxMSB]= 4;
311 LTC6948_spi_map[LTC6948_ALCHI][NUMBITS]= 1;
312 LTC6948_spi_map[LTC6948_ALCLO][ADDRx]=0x00;
313 LTC6948_spi_map[LTC6948_ALCLO][DxMSB]= 3;
314 LTC6948_spi_map[LTC6948_ALCLO][NUMBITS]= 1;
315 LTC6948_spi_map[LTC6948_ALCMON][ADDRx]=0x03;
316 LTC6948_spi_map[LTC6948_ALCMON][DxMSB]= 6;
317 LTC6948_spi_map[LTC6948_ALCMON][NUMBITS]= 1;
318 LTC6948_spi_map[LTC6948_ALCULOK][ADDRx]=0x03;
319 LTC6948_spi_map[LTC6948_ALCULOK][DxMSB]= 4;
320 LTC6948_spi_map[LTC6948_ALCULOK][NUMBITS]= 1;
321 LTC6948_spi_map[LTC6948_AUTOCAL][ADDRx]=0x03;
322 LTC6948_spi_map[LTC6948_AUTOCAL][DxMSB]= 3;
323 LTC6948_spi_map[LTC6948_AUTOCAL][NUMBITS]= 1;
324 LTC6948_spi_map[LTC6948_AUTORST][ADDRx]=0x03;
325 LTC6948_spi_map[LTC6948_AUTORST][DxMSB]= 2;
326 LTC6948_spi_map[LTC6948_AUTORST][NUMBITS]= 1;
327 LTC6948_spi_map[LTC6948_BD][ADDRx]=0x04;
328 LTC6948_spi_map[LTC6948_BD][DxMSB]= 7;
329 LTC6948_spi_map[LTC6948_BD][NUMBITS]= 4;
330 LTC6948_spi_map[LTC6948_BST][ADDRx]=0x0b;
331 LTC6948_spi_map[LTC6948_BST][DxMSB]= 7;
332 LTC6948_spi_map[LTC6948_BST][NUMBITS]= 1;
333 LTC6948_spi_map[LTC6948_CAL][ADDRx]=0x0a;
334 LTC6948_spi_map[LTC6948_CAL][DxMSB]= 0;
335 LTC6948_spi_map[LTC6948_CAL][NUMBITS]= 1;
336 LTC6948_spi_map[LTC6948_CP][ADDRx]=0x0c;
337 LTC6948_spi_map[LTC6948_CP][DxMSB]= 2;
338 LTC6948_spi_map[LTC6948_CP][NUMBITS]= 3;
339 LTC6948_spi_map[LTC6948_CPCHI][ADDRx]=0x0d;
340 LTC6948_spi_map[LTC6948_CPCHI][DxMSB]= 7;
341 LTC6948_spi_map[LTC6948_CPCHI][NUMBITS]= 1;
342 LTC6948_spi_map[LTC6948_CPCLO][ADDRx]=0x0d;
343 LTC6948_spi_map[LTC6948_CPCLO][DxMSB]= 6;
344 LTC6948_spi_map[LTC6948_CPCLO][NUMBITS]= 1;
345 LTC6948_spi_map[LTC6948_CPDN][ADDRx]=0x0d;
346 LTC6948_spi_map[LTC6948_CPDN][DxMSB]= 0;
347 LTC6948_spi_map[LTC6948_CPDN][NUMBITS]= 1;
348 LTC6948_spi_map[LTC6948_CPINV][ADDRx]=0x0d;
349 LTC6948_spi_map[LTC6948_CPINV][DxMSB]= 4;
350 LTC6948_spi_map[LTC6948_CPINV][NUMBITS]= 1;
351 LTC6948_spi_map[LTC6948_CPLE][ADDRx]=0x04;
352 LTC6948_spi_map[LTC6948_CPLE][DxMSB]= 3;
353 LTC6948_spi_map[LTC6948_CPLE][NUMBITS]= 1;
354 LTC6948_spi_map[LTC6948_CPMID][ADDRx]=0x0d;
355 LTC6948_spi_map[LTC6948_CPMID][DxMSB]= 5;
356 LTC6948_spi_map[LTC6948_CPMID][NUMBITS]= 1;
357 LTC6948_spi_map[LTC6948_CPRST][ADDRx]=0x0d;
358 LTC6948_spi_map[LTC6948_CPRST][DxMSB]= 2;
359 LTC6948_spi_map[LTC6948_CPRST][NUMBITS]= 1;
360 LTC6948_spi_map[LTC6948_CPUP][ADDRx]=0x0d;
361 LTC6948_spi_map[LTC6948_CPUP][DxMSB]= 1;
362 LTC6948_spi_map[LTC6948_CPUP][NUMBITS]= 1;
363 LTC6948_spi_map[LTC6948_CPWIDE][ADDRx]=0x0d;
364 LTC6948_spi_map[LTC6948_CPWIDE][DxMSB]= 3;
365 LTC6948_spi_map[LTC6948_CPWIDE][NUMBITS]= 1;
366 LTC6948_spi_map[LTC6948_DITHEN][ADDRx]=0x03;
367 LTC6948_spi_map[LTC6948_DITHEN][DxMSB]= 1;
368 LTC6948_spi_map[LTC6948_DITHEN][NUMBITS]= 1;
369 LTC6948_spi_map[LTC6948_FILT][ADDRx]=0x0b;
370 LTC6948_spi_map[LTC6948_FILT][DxMSB]= 6;
371 LTC6948_spi_map[LTC6948_FILT][NUMBITS]= 2;
372 LTC6948_spi_map[LTC6948_INTN][ADDRx]=0x03;
373 LTC6948_spi_map[LTC6948_INTN][DxMSB]= 0;
374 LTC6948_spi_map[LTC6948_INTN][NUMBITS]= 1;
375 LTC6948_spi_map[LTC6948_LDOEN][ADDRx]=0x04;
376 LTC6948_spi_map[LTC6948_LDOEN][DxMSB]= 2;
377 LTC6948_spi_map[LTC6948_LDOEN][NUMBITS]= 1;
378 LTC6948_spi_map[LTC6948_LDOV][ADDRx]=0x04;
379 LTC6948_spi_map[LTC6948_LDOV][DxMSB]= 1;
380 LTC6948_spi_map[LTC6948_LDOV][NUMBITS]= 2;
381 LTC6948_spi_map[LTC6948_LKCT][ADDRx]=0x0c;
382 LTC6948_spi_map[LTC6948_LKCT][DxMSB]= 4;
383 LTC6948_spi_map[LTC6948_LKCT][NUMBITS]= 2;
384 LTC6948_spi_map[LTC6948_LKWIN][ADDRx]=0x0c;
385 LTC6948_spi_map[LTC6948_LKWIN][DxMSB]= 7;
386 LTC6948_spi_map[LTC6948_LKWIN][NUMBITS]= 3;
387 LTC6948_spi_map[LTC6948_LOCK][ADDRx]=0x00;
388 LTC6948_spi_map[LTC6948_LOCK][DxMSB]= 2;
389 LTC6948_spi_map[LTC6948_LOCK][NUMBITS]= 1;
390 LTC6948_spi_map[LTC6948_MTCAL][ADDRx]=0x02;
391 LTC6948_spi_map[LTC6948_MTCAL][DxMSB]= 2;
392 LTC6948_spi_map[LTC6948_MTCAL][NUMBITS]= 1;
393 LTC6948_spi_map[LTC6948_ND][ADDRx]=0x06;
394 LTC6948_spi_map[LTC6948_ND][DxMSB]= 1;
395 LTC6948_spi_map[LTC6948_ND][NUMBITS]= 10;
396 LTC6948_spi_map[LTC6948_NUM][ADDRx]=0x08;
397 LTC6948_spi_map[LTC6948_NUM][DxMSB]= 5;
398 LTC6948_spi_map[LTC6948_NUM][NUMBITS]= 18;
399 LTC6948_spi_map[LTC6948_OD][ADDRx]=0x0b;
400 LTC6948_spi_map[LTC6948_OD][DxMSB]= 2;
401 LTC6948_spi_map[LTC6948_OD][NUMBITS]= 3;
402 LTC6948_spi_map[LTC6948_OMUTE][ADDRx]=0x02;
403 LTC6948_spi_map[LTC6948_OMUTE][DxMSB]= 1;
404 LTC6948_spi_map[LTC6948_OMUTE][NUMBITS]= 1;
405 LTC6948_spi_map[LTC6948_PART][ADDRx]=0x0e;
406 LTC6948_spi_map[LTC6948_PART][DxMSB]= 3;
407 LTC6948_spi_map[LTC6948_PART][NUMBITS]= 4;
408 LTC6948_spi_map[LTC6948_PDALL][ADDRx]=0x02;
409 LTC6948_spi_map[LTC6948_PDALL][DxMSB]= 7;
410 LTC6948_spi_map[LTC6948_PDALL][NUMBITS]= 1;
411 LTC6948_spi_map[LTC6948_PDFN][ADDRx]=0x02;
412 LTC6948_spi_map[LTC6948_PDFN][DxMSB]= 3;
413 LTC6948_spi_map[LTC6948_PDFN][NUMBITS]= 1;
414 LTC6948_spi_map[LTC6948_PDOUT][ADDRx]=0x02;
415 LTC6948_spi_map[LTC6948_PDOUT][DxMSB]= 4;
416 LTC6948_spi_map[LTC6948_PDOUT][NUMBITS]= 1;
417 LTC6948_spi_map[LTC6948_PDPLL][ADDRx]=0x02;
418 LTC6948_spi_map[LTC6948_PDPLL][DxMSB]= 6;
419 LTC6948_spi_map[LTC6948_PDPLL][NUMBITS]= 1;
420 LTC6948_spi_map[LTC6948_PDVCO][ADDRx]=0x02;
421 LTC6948_spi_map[LTC6948_PDVCO][DxMSB]= 5;
422 LTC6948_spi_map[LTC6948_PDVCO][NUMBITS]= 1;
423 LTC6948_spi_map[LTC6948_POR][ADDRx]=0x02;
424 LTC6948_spi_map[LTC6948_POR][DxMSB]= 0;
425 LTC6948_spi_map[LTC6948_POR][NUMBITS]= 1;
426 LTC6948_spi_map[LTC6948_RD][ADDRx]=0x06;
427 LTC6948_spi_map[LTC6948_RD][DxMSB]= 7;
428 LTC6948_spi_map[LTC6948_RD][NUMBITS]= 5;
429 LTC6948_spi_map[LTC6948_REV][ADDRx]=0x0e;
430 LTC6948_spi_map[LTC6948_REV][DxMSB]= 7;
431 LTC6948_spi_map[LTC6948_REV][NUMBITS]= 4;
432 LTC6948_spi_map[LTC6948_RFO][ADDRx]=0x0b;
433 LTC6948_spi_map[LTC6948_RFO][DxMSB]= 4;
434 LTC6948_spi_map[LTC6948_RFO][NUMBITS]= 2;
435 LTC6948_spi_map[LTC6948_RSTFN][ADDRx]=0x0a;
436 LTC6948_spi_map[LTC6948_RSTFN][DxMSB]= 1;
437 LTC6948_spi_map[LTC6948_RSTFN][NUMBITS]= 1;
438 LTC6948_spi_map[LTC6948_SEED][ADDRx]=0x05;
439 LTC6948_spi_map[LTC6948_SEED][DxMSB]= 7;
440 LTC6948_spi_map[LTC6948_SEED][NUMBITS]= 8;
441 LTC6948_spi_map[LTC6948_THI][ADDRx]=0x00;
442 LTC6948_spi_map[LTC6948_THI][DxMSB]= 1;
443 LTC6948_spi_map[LTC6948_THI][NUMBITS]= 1;
444 LTC6948_spi_map[LTC6948_TLO][ADDRx]=0x00;
445 LTC6948_spi_map[LTC6948_TLO][DxMSB]= 0;
446 LTC6948_spi_map[LTC6948_TLO][NUMBITS]= 1;
447 LTC6948_spi_map[LTC6948_UNLOK][ADDRx]=0x00;
448 LTC6948_spi_map[LTC6948_UNLOK][DxMSB]= 5;
449 LTC6948_spi_map[LTC6948_UNLOK][NUMBITS]= 1;
450 LTC6948_spi_map[LTC6948_x][ADDRx]=0x01;
451 LTC6948_spi_map[LTC6948_x][DxMSB]= 5;
452 LTC6948_spi_map[LTC6948_x][NUMBITS]= 6;
453
454 LTC6948_spi_map[LTC6948_ALCCAL][R_ONLY]= 0;
455 LTC6948_spi_map[LTC6948_ALCEN][R_ONLY]= 0;
456 LTC6948_spi_map[LTC6948_ALCHI][R_ONLY]= 1;
457 LTC6948_spi_map[LTC6948_ALCLO][R_ONLY]= 1;
458 LTC6948_spi_map[LTC6948_ALCMON][R_ONLY]= 0;
459 LTC6948_spi_map[LTC6948_ALCULOK][R_ONLY]= 0;
460 LTC6948_spi_map[LTC6948_AUTOCAL][R_ONLY]= 0;
461 LTC6948_spi_map[LTC6948_AUTORST][R_ONLY]= 0;
462 LTC6948_spi_map[LTC6948_BD][R_ONLY]= 0;
463 LTC6948_spi_map[LTC6948_BST][R_ONLY]= 0;
464 LTC6948_spi_map[LTC6948_CAL][R_ONLY]= 0;
465 LTC6948_spi_map[LTC6948_CP][R_ONLY]= 0;
466 LTC6948_spi_map[LTC6948_CPCHI][R_ONLY]= 0;
467 LTC6948_spi_map[LTC6948_CPCLO][R_ONLY]= 0;
468 LTC6948_spi_map[LTC6948_CPDN][R_ONLY]= 0;
469 LTC6948_spi_map[LTC6948_CPINV][R_ONLY]= 0;
470 LTC6948_spi_map[LTC6948_CPLE][R_ONLY]= 0;
471 LTC6948_spi_map[LTC6948_CPMID][R_ONLY]= 0;
472 LTC6948_spi_map[LTC6948_CPRST][R_ONLY]= 0;
473 LTC6948_spi_map[LTC6948_CPUP][R_ONLY]= 0;
474 LTC6948_spi_map[LTC6948_CPWIDE][R_ONLY]= 0;
475 LTC6948_spi_map[LTC6948_DITHEN][R_ONLY]= 0;
476 LTC6948_spi_map[LTC6948_FILT][R_ONLY]= 0;
477 LTC6948_spi_map[LTC6948_INTN][R_ONLY]= 0;
478 LTC6948_spi_map[LTC6948_LDOEN][R_ONLY]= 0;
479 LTC6948_spi_map[LTC6948_LDOV][R_ONLY]= 0;
480 LTC6948_spi_map[LTC6948_LKCT][R_ONLY]= 0;
481 LTC6948_spi_map[LTC6948_LKWIN][R_ONLY]= 0;
482 LTC6948_spi_map[LTC6948_LOCK][R_ONLY]= 1;
483 LTC6948_spi_map[LTC6948_MTCAL][R_ONLY]= 0;
484 LTC6948_spi_map[LTC6948_ND][R_ONLY]= 0;
485 LTC6948_spi_map[LTC6948_NUM][R_ONLY]= 0;
486 LTC6948_spi_map[LTC6948_OD][R_ONLY]= 0;
487 LTC6948_spi_map[LTC6948_OMUTE][R_ONLY]= 0;
488 LTC6948_spi_map[LTC6948_PART][R_ONLY]= 1;
489 LTC6948_spi_map[LTC6948_PDALL][R_ONLY]= 0;
490 LTC6948_spi_map[LTC6948_PDFN][R_ONLY]= 0;
491 LTC6948_spi_map[LTC6948_PDOUT][R_ONLY]= 0;
492 LTC6948_spi_map[LTC6948_PDPLL][R_ONLY]= 0;
493 LTC6948_spi_map[LTC6948_PDVCO][R_ONLY]= 0;
494 LTC6948_spi_map[LTC6948_POR][R_ONLY]= 0;
495 LTC6948_spi_map[LTC6948_RD][R_ONLY]= 0;
496 LTC6948_spi_map[LTC6948_REV][R_ONLY]= 1;
497 LTC6948_spi_map[LTC6948_RFO][R_ONLY]= 0;
498 LTC6948_spi_map[LTC6948_RSTFN][R_ONLY]= 0;
499 LTC6948_spi_map[LTC6948_SEED][R_ONLY]= 0;
500 LTC6948_spi_map[LTC6948_THI][R_ONLY]= 1;
501 LTC6948_spi_map[LTC6948_TLO][R_ONLY]= 1;
502 LTC6948_spi_map[LTC6948_UNLOK][R_ONLY]= 1;
503 LTC6948_spi_map[LTC6948_x][R_ONLY]= 0;
504
505 } // end of LTC6948_init
506
507 void set_LTC6948_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
508 {
509 LTC6948_Fref_MHz=fref_MHz;
510 LTC6948_Fref_Hz=fref_Hz;
511 }
512
513 void set_LTC6948_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
514 {
515 LTC6948_Frf_MHz=frf_MHz;
516 LTC6948_Frf_Hz=frf_Hz;
517 }
518
519 unsigned long get_LTC6948_global_fref_MHz()
520 {
521 return LTC6948_Fref_MHz;
522 }
523
524 unsigned long get_LTC6948_global_fref_Hz()
525 {
526 return LTC6948_Fref_Hz;
527 }
528
529 unsigned long get_LTC6948_global_frf_MHz()
530 {
531 return LTC6948_Frf_MHz;
532 }
533
534 unsigned long get_LTC6948_global_frf_Hz()
535 {
536 return LTC6948_Frf_Hz;
537 }
538
539
540 /* -------------------------------------------------------------------------
541 FUNCTION: calc_odiv
542 - calculates the output divider setting based on the frf and version of LTC6948
543 - @return odiv = 1-6 for valid setting, 999 as invalid frequency
544 ---------------------------------------------------------------------------- */
545 unsigned long LTC6948_calc_odiv(char part_version[], unsigned long frf[2])
546 {
547 unsigned long odiv, max_fout, min_fout, temp_val,i, temp_out;
548 unsigned long max_fout64[2];
549 unsigned long min_fout64[2];
550 unsigned long temp_fout[2];
551 unsigned long temp_i[2];
552 boolean valid_input=false;
553
554 // Determine which frequency range to verify too based on part version
555 if (part_version[8]=='1') // if this is a LTC6948-1
556 {
557 max_fout=LTC6948_1_MAXFREQ;
558 min_fout=LTC6948_1_MINFREQ;
559 }
560 else if (part_version[8]=='2') // if this is a LTC6948-2
561 {
562 max_fout=LTC6948_2_MAXFREQ;
563 min_fout=LTC6948_2_MINFREQ;
564 }
565 else if (part_version[8]=='3') // if this is a LTC6948-3
566 {
567 max_fout=LTC6948_3_MAXFREQ;
568 min_fout=LTC6948_3_MINFREQ;
569 }
570 else if (part_version[8]=='4') // if this is a LTC6948-4
571 {
572 max_fout=LTC6948_4_MAXFREQ;
573 min_fout=LTC6948_4_MINFREQ;
574 }
575 else
576 {
577 Serial.print("No default Frequencies for this board: ");
578 Serial.println(part_version);
579 } // end if-then-else statement
580 HZto64(max_fout64,max_fout,0L);
581 HZto64(min_fout64,min_fout,0L);
582
583 // verify desired frequency falls within a divider range (1-6)
584 valid_input=false;
585 for (i=1; i<=6; i++)
586 {
587 init64(temp_i,0L,i);
588 temp_fout[0] = frf[0];
589 temp_fout[1] = frf[1];
590 mul64(temp_fout,temp_i);
591 if (lt64(temp_fout,max_fout64) || eq64(temp_fout, max_fout64)) // same as frf*i <= max_fout
592 {
593 if (lt64(min_fout64,temp_fout) || eq64(temp_fout, min_fout64)) // same as frf*i >= min_fout
594 {
595 valid_input=true;
596 odiv=i;
597 }
598 }
599 } // end of for loop
600
601 if (valid_input == false) odiv= 999L;
602 return odiv;
603
604 } // end of LTC6948_calc_odiv
605
606 /* -------------------------------------------------------------------------
607 FUNCTION: LTC6948_set_frf
608 Calculates the integer (N), fractional (NUM) and output divider (OD) SPI values
609 using self created 64bit math functions.
610
611 Datasheet equations
612 fvco = fpfd*(N + F)
613 frf = fvco/O
614 fpfd = fref/R
615 F=NUM/2^18 = NUM/262144
616
617 can be modified to the following equations
618 N = (int) (fvco/fpfd) = (int) frf*O*R/fref
619 NUM = (int) [262144 * (frf*O*R/fref -N)]
620
621 where
622 N = ndiv, O= odiv, NUM=fracN_num in the code below
623
624 Linduino One (Arduino Uno) is limited to 32 bit floats/double/long.
625 32 bit math functions will create rounding errors with the above equations,
626 that can result in frequency errors.
627 Therefore, the following code uses self created 64bit functions for 64bit integer math.
628
629 frf (33 bits) LTC6948-4 max frf/fvco = 6.4GHZ, which is 23 bit number (2^33 = 8.59G)
630 fref (23 bits) LTC6948 min fref = 10MHz, which is a 23 bit number (2^23 = 8.3M)
631 O (3 bits)
632 R (5 bits)
633
634 step 1: create 64 bit frf and fref numbers
635
636 step 2: calculate O (output divider)
637
638 step 3: get current R-divider setting
639
640 step 4: calculate frf*O*R
641 max bit count/resolution: 33b+3b+5b= 41b
642 step 5: calculate N(10b), using value from step 1
643 N = (int) frf*O*R/fref
644 max bit count/resolution: 41b-23b = 18b
645 step 6: calculate NUM (18b)
646 NUM = (int) [262144 * (frf*O*R/fref -N)]
647 = (int) [2^18 * (frf*O*R/fref -N)]
648 to get the correct value the above calculation are performed like this
649 = ((int)((frf*O*R/fref)<<23) - N<<23 + rounding) >> 5, where << & >> are bit shift left, right
650 * note << 23b was chosen, because step one use 41b, 41b +23b = 64b (max number for 64 bit math)
651 ** note >> 5 was chosen because 23-5 = 2^18, which is the same as multiplying by 262144
652 *** the rounding variable is equivalent to adding 0.5 to the NUM number. The integer operation always
653 rounds down, so adding a 0.5 to the number before rounding down ensures the closest value is
654 selected.
655 In this function the lower 5 bits of (frf*O*R/fref)<<23) - N<<23 (possible variable 0-31)
656 are check to see if they are >=16.
657 If they are then 16 is added to this number before performing the int and >>5 functions.
658 ---------------------------------------------------------------------------- */
659 void LTC6948_set_frf(char part_version[])
660 {
661 unsigned long frf_MHz, frf_Hz, fref_MHz, fref_Hz, odiv, rdiv, ndiv, fracN_num, frac_num_remainder;
662 unsigned long N64[2], NUM64[2], R64[2], O64[2], temp_long[2];
663 char buffer[100];
664 unsigned long frf[2], frf_act[2];
665 unsigned long fref[2];
666 unsigned long temp_math[2];
667 unsigned long frf_rdiv_odiv[2];
668 unsigned long frf_rdiv_odiv_int[2];
669 unsigned long roundup[2];
670
671 /* step 1: create 64 bit frf and fref numbers
672 32 bit xxxx MHz number and 32 bit yyy yyy Hz number. */
673 frf_MHz=LTC6948_Frf_MHz;
674 frf_Hz=LTC6948_Frf_Hz;
675 HZto64(frf, frf_MHz, frf_Hz);
676
677 fref_MHz=LTC6948_Fref_MHz;
678 fref_Hz=LTC6948_Fref_Hz;
679 HZto64(fref,fref_MHz,fref_Hz);
680
681 // step 2: calculate O (output divider)
682 odiv=LTC6948_calc_odiv(part_version,frf);
683
684 // step 3: get current R-divider setting
685 rdiv=get_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_RD); // reads selected field
686
687 // step 3: calculate frf*O*R
688 frf_rdiv_odiv[0]=0;
689 frf_rdiv_odiv[1]=odiv*rdiv;
690 mul64(frf_rdiv_odiv, frf); // odiv*rdiv*frf
691 frf_rdiv_odiv_int[0]=frf_rdiv_odiv[0]; // copy odiv*rdiv*frf to another variable
692 frf_rdiv_odiv_int[1]=frf_rdiv_odiv[1];
693
694 // step 4: calculate N(10b), using value from step 3; N = (int) frf*O*R/fref
695 temp_math[0]=fref[0]; // copy fref to temp variable for math operation
696 temp_math[1]=fref[1];
697 div64(frf_rdiv_odiv_int, temp_math); // frf_rdiv_odiv_int= [(frf*odiv*rdiv)]/fref --> int(fvco/fpfd)
698 ndiv=frf_rdiv_odiv_int[1];
699
700 // step 5: calculate NUM (18b), NUM = (int) [262144 * (frf*O*R/fref -N)]
701 // SEE notes in function header for step 5
702 // ((int)((frf*O*R/fref)<<23) - N<<23 + rounding) >> 5, where << & >> are bit shift left, right
703 shl64by(frf_rdiv_odiv,23);
704 div64(frf_rdiv_odiv, fref); // frf_rdiv_odiv --> [(frf*odiv*rdiv)<<23]/fref
705
706 shl64by(frf_rdiv_odiv_int,23); // frf_rdiv_odiv_int --> [(int)((frf*odiv*rdiv)/fref)] <<23
707
708 sub64(frf_rdiv_odiv,frf_rdiv_odiv_int);
709
710 // NUM is a 18 bit number in the spi register
711 // At this point in the program it is represented by 23 bits
712 // if the lower 5 bits are >=16 (16/31),
713 // then add 16 to the frac_num_remainder. After the bits are
714 // shifted down 5 bits this will be close to added 0.5 bits.
715 frac_num_remainder=(frf_rdiv_odiv[1] & 31L);
716 if (frac_num_remainder >= 16L)
717 {
718 roundup[0]=0L;
719 roundup[1]=16L;
720 add64(frf_rdiv_odiv,roundup);
721 }
722
723 // shift NUM to get desired 18 bit number for SPI map.
724 shr64by(frf_rdiv_odiv,5);
725 fracN_num=frf_rdiv_odiv[1];
726
727 // program part and print out results to screen
728 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_OD,odiv); // programs output divider
729 Serial.print("OD = ");
730 Serial.println(odiv);
731
732 Serial.print("RD = ");
733 Serial.println(rdiv);
734
735 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_ND,ndiv); // programs N-divider
736 Serial.print(F("ND = "));
737 Serial.println(ndiv);
738
739 if (fracN_num > 0L)
740 {
741 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_INTN,0L); // programs fractional mode
742 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_NUM,fracN_num); // programs NUM
743 if ( (ndiv<35) || (ndiv>1019) ) Serial.print(F("N DIV set to invalid setting - REFER TO DATASHEET\n"));
744 }
745 else
746 {
747 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_INTN,1L); // programs INTN
748 Serial.print(F("When NUM=0, changes to Integer Mode (NUM can not be 0)\n"));
749 if ( (ndiv<32) || (ndiv>1023) ) Serial.print(F("N DIV set to invalid setting - REFER TO DATASHEET\n"));
750 }
751 Serial.print(F("NUM = "));
752 Serial.println(fracN_num);
753
754 set_LTC6948_SPI_FIELD(LTC6948_CS,LTC6948_CAL,1); // calibrates part
755
756
757 ///// calculate actual fout here and print out
758 frf_act[0]=fref[0];
759 frf_act[1]=fref[1];
760 N64[0]=0;
761 NUM64[0]=0;
762 R64[0]=0;
763 O64[0]=0;
764 N64[1]=ndiv;
765 NUM64[1]=fracN_num;
766 R64[1]=rdiv;
767 O64[1]=odiv;
768
769 shl64by(N64,18);
770 add64(N64,NUM64); // (N*262144 +NUM)
771 div64(frf_act,R64); // fref/rdiv (or fpfd)
772 mul64(frf_act,N64); // (N*262144 +NUM)*fpdf
773 div64(frf_act,O64); // ((N*262144 +NUM)*fpdf)/odiv
774 shr64by(frf_act,17);
775 if (frf_act[0]==0) // no 32 bit overflow case
776 {
777 Serial.print(F("Actual Output Frequency (closest available) is "));
778 Serial.print(frf_act[1]);
779 Serial.println("Hz");
780 }
781 else // overflow case
782 {
783 temp_math[0]=frf_act[0];
784 temp_math[1]=frf_act[1];
785 temp_long[0]=0;
786 temp_long[1]=OneMHz;
787 div64(temp_math,temp_long); // frf/1e6
788 Serial.print(F("Actual Output Frequency (closest available) is "));
789 Serial.print(temp_math[1]);
790 Serial.print("MHz + ");
791 temp_long[0]=0;
792 temp_long[1]=OneMHz;
793 mul64(temp_math,temp_long); // int(frf/1e6)*1e6
794 sub64(frf_act,temp_math); // frf-int(frf/1e6)*1e6
795 Serial.print(frf_act[1]);
796 Serial.println("Hz");
797 }
798 }
799
800
801 /* -------------------------------------------------------------------------
802 FUNCTION: prt
803 Prints HEX representation of 64 bit an
804 ---------------------------------------------------------------------------- */
805 void prt(unsigned long an[])
806 {
807 Serial.print(an[0],HEX);
808 Serial.print(" ");
809 Serial.println(an[1],HEX);
810 }
811
812
813 /* -------------------------------------------------------------------------
814 FUNCTION: init64
815 Creates a equivalent 64 bit number from 2 32 bit numbers
816 an[0]=bigPart //upper 32 bits
817 an[1]=littlePart //lower 32 bits
818 ---------------------------------------------------------------------------- */
819 void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart )
820 {
821 an[0]=bigPart;
822 an[1]=littlePart;
823 }
824
825 /* -------------------------------------------------------------------------
826 FUNCTION: HZto64
827 create a 64 bit Hz number from
828 32 bit xxxx MHz number and 32 bit yyy yyy Hz number.
829 A) if an < 2^32 bits
830 an(upper 32b) = 0
831 an(lower 32b) = MHzPart(32b)*1MHz + HzPart (32b)
832 B) if an > 2^32 bits (4,294,967,296)
833 an(upper 32b) = 1
834 an(lower 32b) = ((MHzPart-4294)*1MHz+HzPart)-967296
835 ---------------------------------------------------------------------------- */
836 void HZto64(unsigned long an[], unsigned long MHzPart, unsigned long HzPart )
837 {
838
839 if ((MHzPart>4295) || ((MHzPart==4294) && (HzPart>=967296)))
840 {
841 an[0]=1L; // upper 32 bits
842 an[1] =(MHzPart-4294L)*OneMHz + HzPart-967296L; // lower 32 bits
843 }
844 else
845 {
846 an[0] = 0; // upper 32 bits
847 an[1] = MHzPart*OneMHz+HzPart; // lower 32 bits
848 }
849 }
850
851 /* -------------------------------------------------------------------------
852 FUNCTION: shl64
853 Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
854 ---------------------------------------------------------------------------- */
855 void shl64(unsigned long an[])
856 {
857 an[0] <<= 1;
858 if (an[1] & 0x80000000)
859 an[0]++;
860 an[1] <<= 1;
861 }
862
863
864 /* -------------------------------------------------------------------------
865 FUNCTION: shr64
866 Single Bit shift right of equivalent 64 bit number (an[] = an[]>>1)
867 ---------------------------------------------------------------------------- */
868 void shr64(unsigned long an[])
869 {
870 an[1] >>= 1;
871 if (an[0] & 0x1)
872 an[1]+=0x80000000;
873 an[0] >>= 1;
874 }
875
876
877 /* -------------------------------------------------------------------------
878 FUNCTION: shl64by
879 Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
880 ---------------------------------------------------------------------------- */
881 void shl64by(unsigned long an[], uint8_t shiftnum)
882 {
883 uint8_t i;
884
885 for (i=0; i<shiftnum; i++)
886 {
887 an[0] <<= 1;
888 if (an[1] & 0x80000000)
889 an[0]++;
890 an[1] <<= 1;
891 }
892 }
893
894
895 /* -------------------------------------------------------------------------
896 FUNCTION: shr64by
897 Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
898 ---------------------------------------------------------------------------- */
899 void shr64by(unsigned long an[], uint8_t shiftnum)
900 {
901 uint8_t i;
902
903 for (i=0; i<shiftnum; i++)
904 {
905 an[1] >>= 1;
906 if (an[0] & 0x1)
907 an[1]+=0x80000000;
908 an[0] >>= 1;
909 }
910 }
911
912
913 /* -------------------------------------------------------------------------
914 FUNCTION: add64
915 64 bit Add ann to an (an[] = an[] + ann[])
916 ---------------------------------------------------------------------------- */
917 void add64(unsigned long an[], unsigned long ann[])
918 {
919 an[0]+=ann[0];
920 if (an[1] + ann[1] < ann[1])
921 an[0]++;
922 an[1]+=ann[1];
923 }
924
925
926 /* -------------------------------------------------------------------------
927 FUNCTION: sub64
928 64 bit Subtract ann from an (an[] = an[] - ann[])
929 ---------------------------------------------------------------------------- */
930 void sub64(unsigned long an[], unsigned long ann[])
931 {
932 an[0]-=ann[0];
933 if (an[1] < ann[1])
934 {
935 an[0]--;
936 }
937 an[1]-= ann[1];
938 }
939
940
941 /* -------------------------------------------------------------------------
942 FUNCTION: eq64
943 64 bit, if an == ann, then true
944 ---------------------------------------------------------------------------- */
945 boolean eq64(unsigned long an[], unsigned long ann[])
946 {
947 return (an[0]==ann[0]) && (an[1]==ann[1]);
948 }
949
950
951 /* -------------------------------------------------------------------------
952 FUNCTION: lt64
953 64 bit, if an < ann, then true
954 ---------------------------------------------------------------------------- */
955 boolean lt64(unsigned long an[], unsigned long ann[])
956 {
957 if (an[0]>ann[0]) return false;
958 return (an[0]<ann[0]) || (an[1]<ann[1]);
959 }
960
961
962 /* -------------------------------------------------------------------------
963 FUNCTION: div64
964 64 bit Divide, num=num/div
965 ---------------------------------------------------------------------------- */
966 void div64(unsigned long num[], unsigned long den[])
967 {
968 unsigned long quot[2];
969 unsigned long qbit[2];
970 unsigned long tmp[2];
971 init64(quot,0,0);
972 init64(qbit,0,1);
973
974 if (eq64(num, zero64)) //numerator 0, call it 0
975 {
976 init64(num,0,0);
977 return;
978 }
979
980 if (eq64(den, zero64)) //numerator not zero, denominator 0, infinity in my book.
981 {
982 init64(num,0xffffffff,0xffffffff);
983 return;
984 }
985
986 init64(tmp,0x80000000,0);
987 while (lt64(den,tmp))
988 {
989 shl64(den);
990 shl64(qbit);
991 }
992
993 while (!eq64(qbit,zero64))
994 {
995 if (lt64(den,num) || eq64(den,num))
996 {
997 sub64(num,den);
998 add64(quot,qbit);
999 }
1000 shr64(den);
1001 shr64(qbit);
1002 }
1003
1004 //remainder now in num, but using it to return quotient for now
1005 init64(num,quot[0],quot[1]);
1006 }
1007
1008
1009 /* -------------------------------------------------------------------------
1010 FUNCTION: mul64
1011 64 bit multiply, an=an*ann
1012 ---------------------------------------------------------------------------- */
1013 void mul64(unsigned long an[], unsigned long ann[])
1014 {
1015 unsigned long p[2] = {0,0};
1016 unsigned long y[2] = {ann[0], ann[1]};
1017 while (!eq64(y,zero64))
1018 {
1019 if (y[1] & 1)
1020 add64(p,an);
1021 shl64(an);
1022 shr64(y);
1023 }
1024 init64(an,p[0],p[1]);
1025 }
init64
void init64(unsigned long an[], unsigned long bigPart, unsigned long littlePart)
Creates a equivalent 64 bit number from 2 32 bit numbers.
Definition: LTC6948.cpp:819
mul64
void mul64(unsigned long an[], unsigned long ann[])
64 bit multiply, an=an*ann
Definition: LTC6948.cpp:1013
LTC6948_2_MINFREQ
#define LTC6948_2_MINFREQ
LTC6948-2 lower freq limit.
Definition: LTC6948.h:149
LTC6948_3_MINFREQ
#define LTC6948_3_MINFREQ
LTC6948-3 lower freq limit.
Definition: LTC6948.h:150
LTC6948_read
uint8_t LTC6948_read(uint8_t cs, int8_t address)
LTC6948 Read Single Address reads 8 bit Data field to LTC6948.
Definition: LTC6948.cpp:95
sub64
void sub64(unsigned long an[], unsigned long ann[])
64 bit Subtract ann from an (an[] = an[] - ann[])
Definition: LTC6948.cpp:930
LTC6948_Fref_Hz
unsigned long LTC6948_Fref_Hz
Default Fref frequency - Hz portion (yyy,yyy); Fref = x,xxx, yyy,yyy.
Definition: LTC6948.cpp:84
LTC6948_UNLOK
#define LTC6948_UNLOK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:129
LTC6948_Frf_Hz
unsigned long LTC6948_Frf_Hz
Default Frf frequency - Hz portion (yyy,yyy); Frf = x,xxx, yyy,yyy.
Definition: LTC6948.cpp:86
LTC6948_PDOUT
#define LTC6948_PDOUT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:118
LTC6948_OMUTE
#define LTC6948_OMUTE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:114
LTC6948_1_MINFREQ
#define LTC6948_1_MINFREQ
LTC6948-1 lower freq limit.
Definition: LTC6948.h:148
LTC6948_ALCEN
#define LTC6948_ALCEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:82
div64
void div64(unsigned long num[], unsigned long den[])
64 bit Divide, num=num/div
Definition: LTC6948.cpp:966
prt
void prt(unsigned long an[])
Prints HEX representation of 64 bit an.
Definition: LTC6948.cpp:805
LTC6948_CPCLO
#define LTC6948_CPCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:94
LTC6948_PART
#define LTC6948_PART
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:115
LTC6948_SEED
#define LTC6948_SEED
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:126
LTC6948_CPRST
#define LTC6948_CPRST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:99
LTC6948_LKWIN
#define LTC6948_LKWIN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:108
LTC6948_read_field
long LTC6948_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6948 Read Single Field For SPI FIELDS located in 1 or multiple address locations reads specific ad...
Definition: LTC6948.cpp:115
LTC6948_LKCT
#define LTC6948_LKCT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:107
get_LTC6948_SPI_FIELD
long get_LTC6948_SPI_FIELD(uint8_t cs, uint8_t f)
Gets the LTC6948 SPI field value calls function LTC6948_read_field, which reads specific address loca...
Definition: LTC6948.cpp:151
LTC6948_ALCULOK
#define LTC6948_ALCULOK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:86
Linduino.h
Header File for Linduino Libraries and Demo Code.
shl64
void shl64(unsigned long an[])
Single Bit shift left of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6948.cpp:855
LTC6948_CPINV
#define LTC6948_CPINV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:96
LTC6948_CPCHI
#define LTC6948_CPCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:93
LTC6948_CPUP
#define LTC6948_CPUP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:100
get_LTC6948_REGSIZE
uint8_t get_LTC6948_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6948.cpp:229
LTC6948_RSTFN
#define LTC6948_RSTFN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:125
LTC6948_OD
#define LTC6948_OD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:113
LTC6948_write
void LTC6948_write(uint8_t cs, uint8_t address, uint8_t Data)
LTC6948 Write Single Address writes 8 bit Data field to LTC6948.
Definition: LTC6948.cpp:162
LTC6948_NUM
#define LTC6948_NUM
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:112
LTC6948_FILT
#define LTC6948_FILT
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:103
LTC6948_ALCHI
#define LTC6948_ALCHI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:83
LTC6948_MTCAL
#define LTC6948_MTCAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:110
get_LTC6948_global_frf_Hz
unsigned long get_LTC6948_global_frf_Hz()
returns global LTC6948_Frf_Hz
Definition: LTC6948.cpp:534
LTC6948_AUTORST
#define LTC6948_AUTORST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:88
OneMHz
#define OneMHz
1MHz in long format, used in 64 bit math
Definition: LTC6945.h:121
shr64
void shr64(unsigned long an[])
Single Bit shift right of equivalent 64 bit number (an[] = an[]<<1)
Definition: LTC6948.cpp:868
LTC6948_4_MAXFREQ
#define LTC6948_4_MAXFREQ
LTC6948-4 upper freq limit.
Definition: LTC6948.h:146
set_LTC6948_SPI_FIELD
void set_LTC6948_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
Sets the LTC6948 SPI field value calls function LTC6948_read_field, which reads specific address/fiel...
Definition: LTC6948.cpp:262
LTC6948_4_MINFREQ
#define LTC6948_4_MINFREQ
LTC6948-4 lower freq limit.
Definition: LTC6948.h:151
eq64
boolean eq64(unsigned long an[], unsigned long ann[])
64 bit, if an == ann, then true
Definition: LTC6948.cpp:945
LTC6948_AUTOCAL
#define LTC6948_AUTOCAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:87
get_LTC6948_global_fref_Hz
unsigned long get_LTC6948_global_fref_Hz()
returns global LTC6948_Fref_Hz
Definition: LTC6948.cpp:524
LTC6948_CPMID
#define LTC6948_CPMID
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:98
HZto64
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: LTC6948.cpp:836
LTC6948_LDOV
#define LTC6948_LDOV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:106
LTC6948_ALCLO
#define LTC6948_ALCLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:84
LTC6948_CS
#define LTC6948_CS
Define the SPI CS pin.
Definition: LTC6948.h:76
NUMBITS
#define NUMBITS
Definition: LTC6115.h:69
address
static uint8_t address
Definition: DC2091A.ino:83
LTC6948_init
void LTC6948_init()
Initializes the SPI MAP arrays The values set in initialization are used all the LTC6948 SPI/WRITE an...
Definition: LTC6948.cpp:299
LTC6948_1_MAXFREQ
#define LTC6948_1_MAXFREQ
LTC6948-1 upper freq limit.
Definition: LTC6948.h:143
get_LTC6948_SPI_FIELD_RW
uint8_t get_LTC6948_SPI_FIELD_RW(uint8_t f)
returns if the given field name is (0)read/write or (1)read_only field
Definition: LTC6948.cpp:249
set_LTC6948_ALLREGS
void set_LTC6948_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 LTC6948 RW address.
Definition: LTC6948.cpp:272
LTC6948_PDFN
#define LTC6948_PDFN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:117
LTC6948_ND
#define LTC6948_ND
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:111
LTC6948_write_field
uint8_t LTC6948_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
LTC6948 Write Single Field For SPI FIELDS in 1 or multiple address locations reads specific address/f...
Definition: LTC6948.cpp:178
LT_union_int16_2bytes::LT_uint16
uint16_t LT_uint16
16-bit unsigned integer to be converted to two bytes
Definition: Linduino.h:102
LTC6948_DITHEN
#define LTC6948_DITHEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:102
R_ONLY
#define R_ONLY
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:119
LTC6948_PDALL
#define LTC6948_PDALL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:116
spi_transfer_word
void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
Reads and sends a word.
Definition: LT_SPI.cpp:98
LTC6948_CPWIDE
#define LTC6948_CPWIDE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:101
LTC6948_INTN
#define LTC6948_INTN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:104
LTC6948_3_MAXFREQ
#define LTC6948_3_MAXFREQ
LTC6948-3 upper freq limit.
Definition: LTC6948.h:145
LTC6948_spi_map
uint8_t LTC6948_spi_map[(LTC6948_NUM_REGFIELD+1)][4]
LTC6948 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability.
Definition: LTC6948.cpp:81
LTC6948_NUM_REGADDR
#define LTC6948_NUM_REGADDR
Defines number of LTC6948 SPI registers, used in spi_map array.
Definition: LTC6948.h:133
set_LTC6948_global_fref
void set_LTC6948_global_fref(unsigned long fref_MHz, unsigned long fref_Hz)
sets globals LTC6948_Fref_MHz and LTC6948_Fref_Hz
Definition: LTC6948.cpp:507
zero64
unsigned long zero64[]
for 64bit math functions
Definition: LTC6948.cpp:88
LTC6948_set_frf
void LTC6948_set_frf(char part_version[])
FUNCTION: LTC6948_set_frf Calculates the integer (N), fractional (NUM) and output divider (OD) SPI va...
Definition: LTC6948.cpp:659
LTC6948_POR
#define LTC6948_POR
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:121
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
LTC6948_x
#define LTC6948_x
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:130
set_LTC6948_global_frf
void set_LTC6948_global_frf(unsigned long frf_MHz, unsigned long frf_Hz)
sets globals LTC6948_Frf_MHz and LTC6948_Frf_Hz
Definition: LTC6948.cpp:513
add64
void add64(unsigned long an[], unsigned long ann[])
64 bit Add ann to an (an[] = an[] + ann[])
Definition: LTC6948.cpp:917
LTC6948_CP
#define LTC6948_CP
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:92
LTC6948_THI
#define LTC6948_THI
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:127
shr64by
void shr64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift right of equivalent 64 bit number (an[] = an[]>>shiftnum)
Definition: LTC6948.cpp:899
ADDRx
#define ADDRx
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:116
LTC6948_Fref_MHz
unsigned long LTC6948_Fref_MHz
Default Fref frequency - MHz portion (xxx); Fref = xxx, yyy,yyy.
Definition: LTC6948.cpp:83
LTC6948_reg
uint8_t LTC6948_reg[LTC6948_NUM_REGADDR]
number of LTC6948 spi addresses
Definition: LTC6948.cpp:80
LTC6948_NUM_REGFIELD
#define LTC6948_NUM_REGFIELD
Defines number of LTC6948 SPI fields, used in spi_map array.
Definition: LTC6948.h:134
UserInterface.h
LTC6948_CAL
#define LTC6948_CAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:91
LTC6948_ALCCAL
#define LTC6948_ALCCAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:81
LTC6948_LDOEN
#define LTC6948_LDOEN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:105
LTC6948_REV
#define LTC6948_REV
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:123
LT_union_int16_2bytes
This union splits one int16_t (16-bit signed integer) or uint16_t (16-bit unsigned integer) into two ...
Definition: Linduino.h:99
LTC6948.h
LTC6948: Ultralow Noise and Spurious 0.37GHz to 6.39GHz FracN Synthesizer with Integrated VCO...
LTC6948_ALCMON
#define LTC6948_ALCMON
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:85
LTC6948_BD
#define LTC6948_BD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:89
get_LTC6948_global_fref_MHz
unsigned long get_LTC6948_global_fref_MHz()
returns global LTC6948_Fref_MHz
Definition: LTC6948.cpp:519
i
static int i
Definition: DC2430A.ino:184
shl64by
void shl64by(unsigned long an[], uint8_t shiftnum)
Multi Bit shift left of equivalent 64 bit number (an[] = an[]<<shiftnum)
Definition: LTC6948.cpp:881
LTC6948_RFO
#define LTC6948_RFO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:124
LTC6948_RD
#define LTC6948_RD
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:122
LT_union_int16_2bytes::LT_byte
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
LTC6948_CPLE
#define LTC6948_CPLE
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:97
LTC6948_2_MAXFREQ
#define LTC6948_2_MAXFREQ
LTC6948-2 upper freq limit.
Definition: LTC6948.h:144
LTC6948_PDVCO
#define LTC6948_PDVCO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:120
get_LTC6948_SPI_FIELD_NUMBITS
uint8_t get_LTC6948_SPI_FIELD_NUMBITS(uint8_t f)
returns the number of bits for a given field name in the SPI map
Definition: LTC6948.cpp:239
LTC6948_calc_odiv
unsigned long LTC6948_calc_odiv(char part_version[], unsigned long frf[2])
calculates the output divider setting based on the frf and version of LTC6948
Definition: LTC6948.cpp:545
LTC6948_Frf_MHz
unsigned long LTC6948_Frf_MHz
Default Frf frequency - MHz portion (xxxx); Frf = x,xxx, yyy,yyy.
Definition: LTC6948.cpp:85
LTC6948_CPDN
#define LTC6948_CPDN
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:95
LTC6948_PDPLL
#define LTC6948_PDPLL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:119
LTC6948_LOCK
#define LTC6948_LOCK
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:109
lt64
boolean lt64(unsigned long an[], unsigned long ann[])
64 bit, if an < ann, then true
Definition: LTC6948.cpp:955
LTC6948_BST
#define LTC6948_BST
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:90
get_LTC6948_global_frf_MHz
unsigned long get_LTC6948_global_frf_MHz()
returns global LTC6948_Frf_MHz
Definition: LTC6948.cpp:529
DxMSB
#define DxMSB
used for 2nd dim of 2d spi_map array
Definition: LTC6945.h:117
LTC6948_TLO
#define LTC6948_TLO
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6948.h:128