Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC2248A.ino
Go to the documentation of this file.
1 /*!
2 DC2248A
3 LTC6951: Ultra-Low Jitter 2MHz to 2.7GHz Multi-Output Clock Synthesizer with Integrated VCO
4 
5 @verbatim
6 
7  Setup:
8  Set the terminal baud rate to 115200 and select the newline terminator.
9  Refer to Demo Manual DC2248A.
10  Ensure all jumpers are installed in the factory default positions.
11  One Power Supply is needed for this demo board: 6V supply.
12 
13 
14 Command Description:
15  1- Load Default Settings from a Look-up Table- Loads the SPI map from one of 10 options in a look-up table.
16  The look-up table allows the user to select different frequencies and synchronization option. All options
17  assume a 100MHz reference input and a default DC2248A BOM.
18 
19  ** If you want to use a different loop filter, reference frequency or different
20  register settings. Please use LTC6951Wizard for the loop filter design and initial
21  device setup. The register settings from LTC6951Wizard can be entered into menu option 2
22  or you can change the default registers in the LTC6951_lkup_tbl array. After the
23  LTC6951Wizard settings are created, export the register settings by selecting
24  File --> Export Register Settings from the TLC6951Wizard Menu.
25 
26  2- READ/WRITE to Registers Addresses- Selecting this option will cause all the registers to
27  be read, stored to variables, and displayed. The user will then have the option
28  to write to one register address at a time.
29 
30  3- READ/WRITE to Registers Fields- Selecting this option will allow the user
31  to read or write to one register field name at a time.
32 
33  4- This function stores the current SPI settings in the demo boards EEPROM
34 
35  5- This function loads SPI settings from the demo boards EEPROM to the device
36 
37  6- Frequency chnage Timing test (SPI write + Calibration + Settling Time):
38  Provides two frequency settings and allows user to toggle between the two frequencies by
39  changing the N-divider(ND) value. The user can monitor the STATUS pin. The user
40  can trigger off the STATUS or CS pins. In most cases the user will want to set the SPI
41  frequency to 8MHz (see menu option 7)
42 
43  7- SPI Frequency: Allows user to control Linduino's SPI frequency. By default this is set to 8MHz
44  when connecting Linduino directly to the DC2248. If Linduino is connected to the DC2430 the default
45  SPI rate is 4MHz
46 
47  8- If using a DC2430 (Linduino Expander), this allows the user to select 1 of 8 sites to talk to.
48 
49 USER INPUT DATA FORMAT:
50  decimal : 1024
51  hex : 0x400
52  octal : 02000 (leading 0 "zero")
53  binary : B10000000000
54  float : 1024.0
55 
56 @endverbatim
57 
58 http://www.linear.com/product/LTC6951
59 
60 http://www.linear.com/product/LTC6951#demoboards
61 
62 
63 Copyright 2018(c) Analog Devices, Inc.
64 
65 All rights reserved.
66 
67 Redistribution and use in source and binary forms, with or without
68 modification, are permitted provided that the following conditions are met:
69  - Redistributions of source code must retain the above copyright
70  notice, this list of conditions and the following disclaimer.
71  - Redistributions in binary form must reproduce the above copyright
72  notice, this list of conditions and the following disclaimer in
73  the documentation and/or other materials provided with the
74  distribution.
75  - Neither the name of Analog Devices, Inc. nor the names of its
76  contributors may be used to endorse or promote products derived
77  from this software without specific prior written permission.
78  - The use of this software may or may not infringe the patent rights
79  of one or more patent holders. This license does not release you
80  from the requirement that you obtain separate licenses from these
81  patent holders to use this software.
82  - Use of the software either in source or binary form, must be run
83  on or directly connected to an Analog Devices Inc. component.
84 
85 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
86 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
87 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
88 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
89 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
90 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
91 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
92 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
93 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
94 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
95 */
96 
97 /*! @file
98  @ingroup LTC6951
99 */
100 
101 #include <Arduino.h>
102 #include <stdint.h>
103 #include "Linduino.h"
104 #include "LT_SPI.h"
105 #include "UserInterface.h"
106 #include "LT_I2C.h"
107 #include "QuikEval_EEPROM.h"
108 #include "LTC6951.h"
109 #include <SPI.h>
110 #include <Wire.h>
111 
112 // Function Declaration
113 void print_title(); // Print the title block
114 void print_prompt(); // Print the main menu
115 void menu_1_load_default_settings(); // Sub-menus
118 void menu_4_store_settings();
120 void menu_6_multibytewrite();
121 void menu_7_SPI_speed();
123 //void DUTsync();
124 
125 // Global Variables
126 static int8_t demo_board_connected = 0; //!< Demo Board Name stored in QuikEval EEPROM
127 static int8_t dc2248_board_connected = 0; //!< Demo Board Name stored in QuikEval EEPROM
128 uint8_t First_Run=0; //!< if first time through loop = 0, otherwise=1
129 boolean Using_DC2430= false; //!< Indicator if DC2430 (Linduino Expander) is connected
130 
131 // Analog Pins used on DC2430 (Linduino Expander)
132 int dc2430_site_A0_APin =0; //!< DC2430 resistor tree, if it reads 3.3V then DC2430 connected
133 int dc2430_site_A1_APin =1; //!< DC2430 resistor tree, if it reads 1.66V then DC2430 connected
134 int dc2430_site_A2_APin =2; //!< DC2430 INFO ONLY, measures DC2226 (Linduino) VCCIO voltage
135 
136 // Digital Pins used on DC2430 (Linduino Expander)
137 int dc2430_site_DA0_Pin =2; //!< DC2430 digital pin allows Linduino to control which DC2430 site is selected
138 int dc2430_site_DA1_Pin =3; //!< DC2430 digital pin allows Linduino to control which DC2430 site is selected
139 int dc2430_site_DA2_Pin =4; //!< DC2430 digital pin allows Linduino to control which DC2430 site is selected
140 int dc2430_en_Pin =5; //!< DC2430 digital pin enables Linduino to control which DC2430 site is selected & turns on DC2430 LED
141 
142 /* ------------------------------------------------------------------------- */
143 //! Initialize Linduino
144 //! @return void
145 void setup()
146 {
147  char demo_name[] = "DC2248"; // Demo Board Name stored in QuikEval EEPROM
148  uint8_t data;
149  int site_select=0;
150  int dc2430_A0_val=0;
151  int dc2430_A1_val=0;
152  int dc2430_A2_val=0;
153  float dc2430_A0_fval=0;
154  float dc2430_A1_fval=0;
155  float dc2430_A2_fval=0;
156 
157  Using_DC2430= false;
158 
159  quikeval_SPI_init(); //! Configure the spi port for 500kHz SCK
160  quikeval_SPI_connect(); //! Connect SPI to main data port
161  quikeval_I2C_init(); //! Configure the EEPROM I2C port for 100kHz
162  Serial.begin(115200); //! Initialize the serial port to the PC
163  LTC6951_init();
164  print_title();
165 
166 //! **************** DETECT IF USING DC2430 SECTION ******************
167 //! this checks to see if a DC2026 (linduino) to DC2430 (linduino expander)
168 //! by measuring 3 analog voltages
169 //! if a DC2430 is connect then read A0, A1 , A2
170  dc2430_A0_val = analogRead(dc2430_site_A0_APin);
171  dc2430_A0_fval = (5.0*dc2430_A0_val)/1023;
172 
173  dc2430_A1_val = analogRead(dc2430_site_A1_APin);
174  dc2430_A1_fval = (5.0*dc2430_A1_val)/1023;
175 
176 
177 //! If DC2430 located, auto search site 0 to 7 until a DC2248 is found
178  if ((dc2430_A0_fval>3.0) && (dc2430_A0_fval<3.6) && (dc2430_A1_fval>1.5) && (dc2430_A1_fval<1.8))
179  {
180  Serial.println(F("--- DC2430 Connected ---"));
181  Using_DC2430= true;
182  pinMode(dc2430_site_DA0_Pin, OUTPUT);
183  pinMode(dc2430_site_DA1_Pin, OUTPUT);
184  pinMode(dc2430_site_DA2_Pin, OUTPUT);
185  pinMode(dc2430_en_Pin, OUTPUT); // sets the digital pin as output
188 
189  digitalWrite(dc2430_en_Pin, HIGH); // sets the LED on
190  site_select=0;
191  do
192  {
193  dc2430_site_select(site_select);
194  delay(150); //! probably could be shorter, but this allows the eyes to track which site is being tested
195  demo_board_connected = discover_demo_board_local(demo_name); //! Checks if any demo board is connected.
197  {
198  Serial.println(F("\n********************************************************"));
199  dc2248_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
200 
202  {
203  dc2430_A2_val = analogRead(dc2430_site_A2_APin);
204  dc2430_A2_fval = (5.0*dc2430_A2_val)/1023;
205  Serial.print(F("Linduino's JP3 VCCIO voltage = "));
206  Serial.println(dc2430_A2_fval); //! if DC2430 connect, VCCIO voltage set by JP3 on DC2026
207  spi_enable(SPI_CLOCK_DIV4); //! 1) Configure the spi port for 4MHz SCK
208  Serial.println(F("Linduino's SPI Frequency = 4MHz, max DC2430 SPI speed"));
209  Serial.print(F("\nDC2248 FOUND ON DC2430 SITE "));
210  Serial.println(site_select);
211  site_select=15;
212  }
213  }
214 
216  {
217  Serial.print(F("\nDC2248 NOT FOUND ON DC2430 SITE "));
218  Serial.print(site_select);
219  site_select++;
220  }
221  }
222  while (site_select<8);
223 
224  //! if no DC2248A was found. Return dc2430_en_Pin to default state (LOW)
226  {
227  digitalWrite(dc2430_en_Pin, LOW); // sets the LED on
228  Serial.println(F("\n\nConnect DC2248 demo board to DC2430, then press the reset button."));
229  }
230  }
231  else
232  {
233  //! If DC2430 is not located, check to see if Linduino is connected directly to the DC2248
234  //! most common use case
235  Serial.println(F("DC2248A CONNECTED TO LINDUINO"));
236  dc2248_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
238  {
239  Serial.println(F("Linduino's SPI Frequency = 8MHz, max speed"));
240  spi_enable(SPI_CLOCK_DIV2); //! 1) Configure the spi port for 8MHz SCK
241  }
242  }
243 
245  {
246  print_prompt();
247  }
248 } // end of setup()
249 
250 
251 /* ------------------------------------------------------------------------- */
252 //! Repeats Linduino loop
253 //! @return void
254 void loop()
255 {
256  uint16_t user_command; // User input command
257 
258  if (Serial.available()) // Check for user input
259  {
260  if (First_Run==0)
261  {
262  First_Run=1;
263  }
264 
265  user_command = read_int(); //! Reads the user command
266  if (user_command != 'm')
267  Serial.println(user_command);
268 
269  switch (user_command) //! Prints the appropriate submenu
270  {
271  case 1:
273  break;
274 
275  case 2:
277  break;
278 
279  case 3:
281  break;
282 
283  case 4:
285  break;
286 
287  case 5:
289  break;
290 
291  case 6:
293  break;
294 
295  case 7:
297  break;
298 
299  case 8:
301  break;
302 
303 
304  default:
305  Serial.println(F("Incorrect Option"));
306  break;
307  } // end of switch statement
308  Serial.println(F("\n*****************************************************************"));
309  print_prompt();
310  } // end of if statement
311 } // end of loop()
312 
313 // Function Definitions
314 /* ------------------------------------------------------------------------- */
315 //! Menu 1: Load Default SPI Register Settings
316 //! This function loads the register settings from a look up table.
317 //! The setting loaded with this function assume the LTC6951's
318 //! reference is set to 100MHz and the DC2248A's BOM has not been modified.
319 //! The settings in the look up table were created using the LTC6951Wizard.
320 //! It is recommended to use the LTC6951Wizard to create the register settings for
321 //! all desired frequency plans and enter these frequency plans into a look-up table.
322 //! The LTC6951Wizard generates register values for optimal LTC6951 performance.
323 //! @return void
325 {
326 
327  uint8_t field_num;
328  long field_val;
329 
330  field_val=999L;
331  field_num=1;
332 // Read/Write loop, can exit loop by choosing 'm'
333  while (field_num != 0)
334  {
335  Serial.print(F("\n*****************************************************************"));
336  Serial.print(F("\n************* Select LTC6951 Configuration *****************"));
337  Serial.println(F("\n*****************************************************************"));
338 
339  // Select Fields to read and write to
340  Serial.print(F("1- OUT[4:0] = 600MHZ, EZSync\n"));
341  Serial.print(F("2- OUT[4:0] = 600MHZ, EZSync Ref Aligned\n"));
342  Serial.print(F("3- OUT[4:0] = 600MHZ, EZParallelSync\n"));
343  Serial.print(F("4- OUT[4:0] = 600MHZ, ParallelSync\n"));
344  Serial.print(F("5- OUT[3:0] = 2500MHZ, OUT4:625MHz, EZSync\n"));
345  Serial.print(F("6- OUT[3:0] = 2500MHZ, OUT4:625MHz, EZSync Ref Aligned\n"));
346  Serial.print(F("7- OUT[3:1] = 2400MHZ, OUT0&OUT4 = 600MHz, EZParallelSync\n"));
347  Serial.print(F("8- OUT[3:0] = 2500MHZ, OUT4 = 625MHz, ParallelSync\n"));
348  Serial.print(F("9- OUT[4:0] = Same frequencies as DC2226 U10, JESD204B SC1, ParallelSync\n"));
349  Serial.print(F("10- OUT[4:0] = Same frequencies as DC2226 U13, JESD204B SC1, ParallelSync\n"));
350  Serial.println(F("0 - Return to Main Menu\n"));
351 
352  Serial.println(F("Load LTC6951 register settings from a look up table (Settings created from LTC6951Wizard)"));
353  Serial.println(F("Enter a command (1-10), or '0' to return to Main Menu): "));
354  field_num = read_int(); //! Reads the user command
355  Serial.println(field_num);
356 
357  // User input: enter new setting for selected register
358  if (field_num != 0)
359  {
360  field_num=field_num-1;
361  set_LTC6951_REGS_lkup_tbl(field_num);
362  field_num=field_num+1;
363  } // end if user_command != 0 statement
364  } // end while loop
365 } // end menu_1_load_default_settings function
366 
367 
368 /* ------------------------------------------------------------------------- */
369 //! Menu 2: Reads and/or Writes the SPI register address
370 //! This function reads and displays all SPI register address settings in HEX format.
371 //! It then provides an option to modify(write to) individual registers one at time
372 //!
373 //! EXAMPLE:
374 //! - 0- ADDR00 = 0x04 (read only)
375 //! - 1- ADDR01 = 0x04
376 //! - ....
377 //! - 21- ADDR15 = 0x04
378 //! - 22- ADDR16 = 0x65 (read only)
379 //! - 0 - Return to Main Menu
380 //! - Enter a command (1-21 to modify register, or '0' to return to Main Menu):
381 //! @return void
383 {
384  uint8_t i, regval, user_regval, num_reg;
385  uint16_t user_address; // User input command
386 
387  num_reg = get_LTC6951_REGSIZE();
388  user_address=1;
389 // Read/Write loop, can exit loop by choosing '0'
390  while (user_address != 0)
391  {
392  Serial.println(F("\n*****************************************************************"));
393  // Read All Registers and display results
394  for (i=0; i<num_reg; i++)
395  {
396  regval = LTC6951_read(LTC6951_CS,i);
397  Serial.print(i);
398  if (i<16)
399  Serial.print(F("- ADDR0"));
400  else
401  Serial.print(F("- ADDR"));
402  Serial.print(i, HEX);
403  Serial.print(F(" = 0x"));
404  if (regval<16) Serial.print(F("0"));
405  Serial.print(regval, HEX);
406  if (i==3) Serial.print(F(" (warning: if D2=1 it resets all registers. RES6951 Bit)"));
407  if ((i==0)||(i==(num_reg-1))) Serial.print(F(" (read only) "));
408  Serial.println("");
409  } // end for loop
410  Serial.print(F("0 - Return to Main Menu\n\n"));
411  // User input: Select which register to modify, or return to main menu
412  Serial.print(F("Enter a command (1-19 to modify register, or '0' to return to Main Menu): "));
413  user_address = read_int(); //! Reads the user command
414  Serial.println(user_address);
415 
416  // User input: enter new setting for selected register
417  if (user_address >0 && user_address<(num_reg-1))
418  {
419  Serial.print(F("What value should ADDR"));
420  Serial.print(user_address);
421  Serial.print(F(" be set to (ex: HEX format 0xff): "));
422  user_regval = read_int(); //! Reads the user command
423  Serial.println(user_regval);
424 
425  // writes new setting to part
426  LTC6951_write(LTC6951_CS, (uint8_t)user_address, user_regval);
427  } // end if statement
428  } // end while loop
429 } // end menu_2_RW_to_reg_addresss
430 
431 
432 /* ------------------------------------------------------------------------- */
433 //! Support function for function menu_3_RW_to_reg_field
434 //! displays current state of select field
435 //! provides user the option to write to that field or return to menu
436 //! @return field value (user input) that will be written to part
437 long field_menu_RW(long field_val, //!< current state of the selected field
438  char field_name[], //!< SPI Field name selected
439  uint8_t f //!< SPI field identifier identifies selected fields information in SPI MAP arrays
440  )
441 {
442  long usr_field_val;
443  uint8_t field_size, i;
444  long max_num=1, pow2=1;
445 
446  Serial.print("CURRENT STATE (HEX): ");
447  Serial.print(field_name);
448  Serial.print("= 0x");
449  Serial.println(field_val, HEX);
450 
451  if (get_LTC6951_SPI_FIELD_RW(f)==0)
452  {
453  field_size=get_LTC6951_SPI_FIELD_NUMBITS(f);
454  for (i=1; i<field_size; i++)
455  {
456  pow2=pow2*2;
457  max_num=max_num + pow2;
458  }
459 
460  Serial.print("What value should ");
461  Serial.print(field_name);
462  Serial.print(" be set to or type '-1' to exit: (ex: HEX format 0x00 to 0x");
463  Serial.print(max_num, HEX);
464  Serial.print(")");
465  usr_field_val = read_int(); //! Reads the user command
466 
467  if (usr_field_val>=0 && usr_field_val<=max_num)
468  {
469  Serial.println(usr_field_val);
470  return usr_field_val;
471  }
472  else
473  {
474  return field_val;
475  } // end of if statement
476  } // end of if statement
477 } // end of field_menu_RW
478 
479 
480 /* ------------------------------------------------------------------------- */
481 //! Menu 3: Reads and/or Writes individual SPI fields
482 //! This function provides the user with a list of all SPI fields.
483 //! The user can select a SPI field to read its current value.
484 //! Then the user will be provided with an option to write to that field
485 //! or return to the selection menu.
486 //!
487 //! EXAMPLE:
488 //! - 1-ALCCAL 25-LKWIN 49-PART *
489 //! - 2-ALCEN 26-LOCK * 50-PD
490 //! - ....
491 //! - 21-DLY4 45-OINV1 69-SYNCEN4
492 //! - 23-INVSTAT 47-OINV3 71-x
493 //! - 24-LKCT 48-OINV4
494 //! - 0 - Return to Main Menu
495 //! - * = READ ONLY FIELD
496 //! - Enter a command (1-71 to modify register, or '0' to return to Main Menu):
497 //! @return void
499 {
500  uint8_t field_num;
501  long field_val;
502 
503  field_val=999L;
504  field_num=1;
505 // Read/Write loop, can exit loop by choosing 'm'
506  while (field_num != 0)
507  {
508  Serial.println(F("\n*****************************************************************"));
509  // Select Fields to read and write to
510  Serial.print(F("1-ALCCAL 25-LKWIN 49-PART *\n"));
511  Serial.print(F("2-ALCEN 26-LOCK * 50-PD\n"));
512  Serial.print(F("3-ALCHI * 27-!LOCK * 51-PDALL\n"));
513  Serial.print(F("4-ALCLO * 28-MCO 52-PDOUT\n"));
514  Serial.print(F("5-ALCMON 29-MC1 53-PDPLL\n"));
515  Serial.print(F("6-ALCULOK 30-MC2 54-PDREFPK\n"));
516  Serial.print(F("7-AUTOCAL 31-MC3 55-PDVCO\n"));
517  Serial.print(F("8-BD 32-MC4 56-POR\n"));
518  Serial.print(F("9-BST 33-MD0 57-RAO\n"));
519  Serial.print(F("10-CAL 34-MD1 58-RD\n"));
520  Serial.print(F("11-CP 35-MD2 59-REFOK *\n"));
521  Serial.print(F("12-CPDN 36-MD3 60-!REFOK *\n"));
522  Serial.print(F("13-CPMID 37-MD4 61-REV *\n"));
523  Serial.print(F("14-CPRST 38-MUTE0 62-SN\n"));
524  Serial.print(F("15-CPUP 39-MUTE1 63-SR\n"));
525  Serial.print(F("16-CPWIDE 40-MUTE2 64-SSYNC\n"));
526  Serial.print(F("17-DLY0 41-MUTE3 65-SYNCEN0\n"));
527  Serial.print(F("18-DLY1 42-MUTE4 66-SYNCEN1\n"));
528  Serial.print(F("19-DLY2 43-ND 67-SYNCEN2\n"));
529  Serial.print(F("20-DLY3 44-OINV0 68-SYNCEN3\n"));
530  Serial.print(F("21-DLY4 45-OINV1 69-SYNCEN4\n"));
531  Serial.print(F("22-FILT 46-OINV2 70-UNLOCK *\n"));
532  Serial.print(F("23-INVSTAT 47-OINV3 71-x\n"));
533  Serial.print(F("24-LKCT 48-OINV4 \n"));
534 
535  Serial.print(F("0 - Return to Main Menu\n"));
536  Serial.print(F("* = READ ONLY FIELD\n\n"));
537 
538  Serial.print(F("Enter a command (1-71 to modify register, or '0' to return to Main Menu): "));
539  field_num = read_int(); //! Reads the user command
540  Serial.println(field_num);
541 
542  // User input: enter new setting for selected register
543  if (field_num != 0)
544  {
545  switch (field_num) //! Prints the appropriate submenu
546  {
547  default:
548  field_val=get_LTC6951_SPI_FIELD(LTC6951_CS,field_num); // reads selected field
549  field_val=field_menu_RW(field_val," ",field_num); // user interface control and printout
550  if (field_val>-1)
551  {
552  set_LTC6951_SPI_FIELD(LTC6951_CS, field_num, field_val); // updates selected field
553  }
554  break;
555  } // end of switch statement
556  } // end if user_command != 0 statement
557  } // end while loop
558 } // end menu_3_RW_to_reg_field function
559 
560 
561 /* ------------------------------------------------------------------------- */
562 //! Store PLL settings to nonvolatile EEPROM on demo board
563 //! @return void
565 {
566 // Store the PLL Settings to the EEPROM
567  uint8_t regval;
568 
569  uint8_t addr_offset;
570  uint8_t num_reg;
571 
572  addr_offset=2;
573  num_reg = get_LTC6951_REGSIZE();
574 
576 
577  for (uint8_t i = 0; i <= num_reg ; i++)
578  {
579  regval = LTC6951_read(LTC6951_CS,i);
581  }
582  Serial.println(F("PLL Settings Stored to EEPROM"));
583 
584 }
585 
586 /* ------------------------------------------------------------------------- */
587 //! Read stored PLL settings from nonvolatile EEPROM on demo board
588 //! @return void
590 {
591 // Read the PLL settings from EEPROM
592  int16_t cal_key;
593  uint8_t regval;
594  uint8_t user_address;
595 
596  uint8_t addr_offset;
597  uint8_t num_reg;
598  long field_val;
599  uint8_t field_num;
600 
601  addr_offset=2;
602  num_reg = get_LTC6951_REGSIZE();
603 
604 // read the cal key from the EEPROM
606  if (cal_key == EEPROM_CAL_KEY)
607  {
608  // PLL Settings has been stored, read PLL Settings
609  user_address=2;
610  for (uint8_t i = 0; i <= num_reg ; i++)
611  {
612  eeprom_read_byte(EEPROM_I2C_ADDRESS,(char *) &regval, EEPROM_CAL_STATUS_ADDRESS + i+addr_offset);
613  LTC6951_write(LTC6951_CS, (uint8_t)i, regval);
614  user_address++;
615  }
616  Serial.println(F("LTC6951 Settings Restored"));
617 
618  Serial.println(F("Calibrate LTC6951 VCO"));
620  delay(1); // Calibrations typically ~50us long, CAL bit clears automatically
621 
622  Serial.println(F("Syncs LTC6951 OUTPUTS"));
623  DUTsync(1);
624 
625  }
626  else
627  {
628  Serial.println(F("PLL Settings not found"));
629  }
630 
631 }
632 
633 /* ------------------------------------------------------------------------- */
634 //! Syncs LTC6951 Outputs using SSYNC bit
635 //! @return void
636 void DUTsync(uint16_t delay_num)
637 {
639  delay(1);
641  delay(delay_num);
642 }
643 
644 /* ------------------------------------------------------------------------- */
645 //! Frequency change Timing test (SPI write + Calibration + Settling Time):
646 //! Provides two frequency settings and allows user to toggle between the two frequencies by
647 //! changing the N-divider(ND) value. The user can monitor the STATUS pin. The user
648 //! can trigger off the STATUS or CS pins. In most cases the user will want to set the SPI
649 //! frequency to 8MHz (see menu option 7)
650 //! @return void
652 {
653  uint8_t init_setup;
654  uint8_t lkup_tbl_row; // User input command
655 
656  lkup_tbl_row=1;
657  init_setup=1;
658 
659 // Read/Write loop, can exit loop by choosing '0'
660  while (lkup_tbl_row != 0)
661  {
662  Serial.println(F("\n*****************************************************************"));
663  Serial.println(F("This option is good for measuring calibration and settling time"));
664  Serial.println(F("It allows one to hop back and forth between 2 frequencies"));
665  Serial.println(F("For different frequencies - modify the lookup table in function"));
666  Serial.println(F("Fset_LTC6951_REGS_freq_jump. LTC6951Wizard exports register settings"));
667  Serial.println(F("in the correct format for an easy modification"));
668  Serial.println(F("For best timing results, set the SPI clock frequency to 8MHz (main menu: option 7)"));
669 
670  // Read All Registers and display results
671  Serial.println(F("1 - Frequency 1: 600MHz"));
672  Serial.println(F("2 - Frequency 2: 550MHz\n"));
673  Serial.print(F("0 - Return to Main Menu\n\n"));
674  Serial.print(F("Select an Option (0,1, or 2) : "));
675  lkup_tbl_row = read_int(); //! Reads the user command
676  Serial.println(lkup_tbl_row);
677 
678  if ((lkup_tbl_row >2)|| (lkup_tbl_row <0))
679  {
680  Serial.println(F("Not an option - try again"));
681  }
682  else if (lkup_tbl_row == 0)
683  {
684  // do nothing
685  }
686  else
687  {
688  set_LTC6951_REGS_freq_jump((lkup_tbl_row-1), init_setup);
689  init_setup=0;
690  }
691  } // end while loop
692 }
693 
694 
695 /* ------------------------------------------------------------------------- */
696 //! Read stored PLL settings from nonvolatile EEPROM on demo board
697 //! @return void
699 {
700  int temp_val;
701 
702  Serial.println(F("\nCommand Summary:"));
703  if (Using_DC2430)
704  {
705  Serial.println(F(" 1-8MHz NOT Available with DC2430"));
706  }
707  else
708  {
709  Serial.println(F(" 1-SPI Clock = 8MHz"));
710  }
711  Serial.println(F(" 2-SPI Clock = 4MHz"));
712  Serial.println(F(" 3-SPI Clock = 2MHz"));
713  Serial.println(F(" 4-SPI Clock = 1MHz"));
714  Serial.println(F(" 5-SPI Clock = 500kHz"));
715  Serial.println("");
716  Serial.print(F("Enter a command: "));
717  temp_val = read_int(); //! Reads the user command
718 
719  switch (temp_val) //! Prints the appropriate submenu
720  {
721  case 1:
722  if (Using_DC2430)
723  {
724  Serial.println(F("incorrect option"));
725  }
726  else
727  {
728  spi_enable(SPI_CLOCK_DIV2); //! 1) Configure the spi port for 8MHz SCK
729  }
730  break;
731 
732  case 2:
733  spi_enable(SPI_CLOCK_DIV4); //! 1) Configure the spi port for 4MHz SCK
734  break;
735 
736  case 3:
737  spi_enable(SPI_CLOCK_DIV8); //! 1) Configure the spi port for 2MHz SCK
738  break;
739 
740  case 4:
741  spi_enable(SPI_CLOCK_DIV16); //! 1) Configure the spi port for 1MHz SCK
742  break;
743 
744  case 5:
745  spi_enable(SPI_CLOCK_DIV32); //! 1) Configure the spi port for 500kHz SCK
746  break;
747 
748  default:
749  Serial.println(F("Incorrect Option"));
750  break;
751  }
752 }
753 
754 
755 /* ------------------------------------------------------------------------- */
756 //! Read stored PLL settings from nonvolatile EEPROM on demo board
757 //! @return void
759 {
760  int temp_val;
761  char demo_name[] = "DC2248"; // Demo Board Name stored in QuikEval EEPROM
762 
763 
764  Serial.println(F("\nCommand Summary:"));
765  Serial.println(F(" 0-Site 0"));
766  Serial.println(F(" 1-Site 1"));
767  Serial.println(F(" 2-Site 2"));
768  Serial.println(F(" 3-Site 3"));
769  Serial.println(F(" 4-Site 4"));
770  Serial.println(F(" 5-Site 5"));
771  Serial.println(F(" 6-Site 6"));
772  Serial.println(F(" 7-Site 7"));
773 
774  Serial.println("");
775  Serial.print(F("Enter a command: "));
776  temp_val = read_int(); //! Reads the user command
777 
778  dc2430_site_select(temp_val);
779 
782  demo_board_connected = discover_demo_board_local(demo_name); //! Checks if any demo board is connected.
783 
785  {
786  Serial.println(F("\n********************************************************"));
787  dc2248_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
788  }
790  {
791  Serial.print(F("\nDC2248 NOT FOUND ON DC2430 SITE "));
792  Serial.print(temp_val);
793  }
794 
795 }
796 
797 /* ------------------------------------------------------------------------- */
798 //! Called from function menu_8_DC2430_site_select(), programs DC2430 to site selected
799 //! @return void
800 void dc2430_site_select(int site_select)
801 {
802 
803  switch (site_select) //! Prints the appropriate submenu
804  {
805  case 0:
806  digitalWrite(dc2430_site_DA0_Pin, LOW);
807  digitalWrite(dc2430_site_DA1_Pin, LOW);
808  digitalWrite(dc2430_site_DA2_Pin, LOW);
809  break;
810 
811  case 1:
812  digitalWrite(dc2430_site_DA0_Pin, HIGH);
813  digitalWrite(dc2430_site_DA1_Pin, LOW);
814  digitalWrite(dc2430_site_DA2_Pin, LOW);
815  break;
816 
817  case 2:
818  digitalWrite(dc2430_site_DA0_Pin, LOW);
819  digitalWrite(dc2430_site_DA1_Pin, HIGH);
820  digitalWrite(dc2430_site_DA2_Pin, LOW);
821  break;
822 
823  case 3:
824  digitalWrite(dc2430_site_DA0_Pin, HIGH);
825  digitalWrite(dc2430_site_DA1_Pin, HIGH);
826  digitalWrite(dc2430_site_DA2_Pin, LOW);
827  break;
828 
829  case 4:
830  digitalWrite(dc2430_site_DA0_Pin, LOW);
831  digitalWrite(dc2430_site_DA1_Pin, LOW);
832  digitalWrite(dc2430_site_DA2_Pin, HIGH);
833  break;
834 
835  case 5:
836  digitalWrite(dc2430_site_DA0_Pin, HIGH);
837  digitalWrite(dc2430_site_DA1_Pin, LOW);
838  digitalWrite(dc2430_site_DA2_Pin, HIGH);
839  break;
840 
841  case 6:
842  digitalWrite(dc2430_site_DA0_Pin, LOW);
843  digitalWrite(dc2430_site_DA1_Pin, HIGH);
844  digitalWrite(dc2430_site_DA2_Pin, HIGH);
845  break;
846 
847  case 7:
848  digitalWrite(dc2430_site_DA0_Pin, HIGH);
849  digitalWrite(dc2430_site_DA1_Pin, HIGH);
850  digitalWrite(dc2430_site_DA2_Pin, HIGH);
851  break;
852 
853  default:
854  Serial.println(F("Incorrect Option"));
855  break;
856  }
857 
858 }
859 
860 /* ------------------------------------------------------------------------- */
861 //! Prints the title block when program first starts.
863 {
864 
865  Serial.println(F("\n****************************************************************************************************"));
866  Serial.println(F("* DC2248 Demonstration Program *"));
867  Serial.println(F("* - Input Voltage 6V-20V (J15/J16) *"));
868  Serial.println(F("* *"));
869  Serial.println(F("* This program demonstrates how to send data to the LTC6951 Ultralow Jitter *"));
870  Serial.println(F("* Multi-Output Clock Synthesizer with Integrated VCO. *"));
871  Serial.println(F("* *"));
872  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator. *"));
873  Serial.println(F("* *"));
874  Serial.println(F("* Recommendations on how to best use LTC6951Wizard and DC2248 Linduino code together *"));
875  Serial.println(F("* Use LTC6951Wizard to *"));
876  Serial.println(F("* - determine best SPI register values for specific frequenices and Sync Methods for all settings *"));
877  Serial.println(F("* - determine loop filter value *"));
878  Serial.println(F("* - Simulate LTC6951 Phase noise and Time Domain response *"));
879  Serial.println(F("* - initial engineering evaluation *"));
880  Serial.println(F("* Use DC2248 Linduino code *"));
881  Serial.println(F("* - Create a look up table of the SPI register values created from LTC6951Wizard (option 1) *"));
882  Serial.println(F("* - Software development for reading and writing to specific register/address (option 2 & 3) *"));
883  Serial.println(F("* - Storing demo board settings on the demo board EEPROM *"));
884  Serial.println(F("* - test that require a fast SPI clocks up to 8MHz, (i.e. settling time) *"));
885  Serial.println(F("* - starting place to use the DC2248 with the DC2430 *"));
886  Serial.println(F("****************************************************************************************************"));
887  Serial.println();
888 } // end of print_title
889 
890 
891 /* ------------------------------------------------------------------------- */
892 //! Prints main menu.
894 {
895 
896  Serial.println(F("\nCommand Summary:"));
897  Serial.println(F(" 1-Load Default Settings from a Look-up Table"));
898  Serial.println(F(" 2-READ/WRITE to Registers Addresses"));
899  Serial.println(F(" 3-READ/WRITE to Registers Fields"));
900  Serial.println(F(" 4-Store LTC6951 SPI settings to the DC2248's EEPROM"));
901  Serial.println(F(" 5-Restore LTC6951 SPI settings from the DC2248's EEPROM"));
902  Serial.println(F(" 6-Timing Measurement Aid: SPI WRITE + CALIBRAION + SETTLING TIME"));
903  Serial.println(F(" 7-Adjust SPI frequency"));
904  if (Using_DC2430)
905  {
906  Serial.println(F(" 8-DC2430 Site Selector"));
907  }
908  Serial.println("");
909  Serial.print(F("Enter a command: "));
910 } // end of print_prompt
911 
912 
static void menu_6_multibytewrite()
Frequency change Timing test (SPI write + Calibration + Settling Time): Provides two frequency settin...
Definition: DC2248A.ino:651
uint8_t eeprom_read_int16(uint8_t i2c_address, int16_t *read_data, uint16_t address)
Read the two byte integer data from the EEPROM starting at address.
unsigned char user_command
#define EEPROM_I2C_ADDRESS
uint8_t get_LTC6951_SPI_FIELD_RW(uint8_t f)
returns if the given field name is (0)read/write or (1)read_only field
Definition: LTC6951.cpp:262
uint8_t eeprom_write_byte(uint8_t i2c_address, char data, uint16_t address)
Write the data byte to the EEPROM with i2c_address starting at EEPROM address.
uint8_t get_LTC6951_SPI_FIELD_NUMBITS(uint8_t f)
returns the number of bits for a given field name in the SPI map
Definition: LTC6951.cpp:252
LTC6951: Ultra-Low Jitter 2MHz to 2.7GHz Multi-Output Clock Synthesizer with Integrated VCO...
static void menu_3_RW_to_reg_field()
Menu 3: Reads and/or Writes individual SPI fields This function provides the user with a list of all ...
Definition: DC2248A.ino:498
Header File for Linduino Libraries and Demo Code.
static void dc2430_site_select(int site_select)
Called from function menu_8_DC2430_site_select(), programs DC2430 to site selected.
Definition: DC2248A.ino:800
void set_LTC6951_REGS_freq_jump(uint8_t lkup_tbl_row, uint8_t init_setup)
This function toggles between two frequencies.
Definition: LTC6951.cpp:430
void set_LTC6951_REGS_lkup_tbl(uint8_t lkup_tbl_row)
Writes values to ALL LTC6951 RW addresses from a look-up table.
Definition: LTC6951.cpp:322
void spi_enable(uint8_t spi_clock_divider)
Setup the processor for hardware SPI communication.
Definition: LT_SPI.cpp:160
static void DUTsync(uint16_t delay_num)
Syncs LTC6951 Outputs using SSYNC bit.
Definition: DC2248A.ino:636
static int dc2430_site_DA0_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:137
#define LTC6951_SSYNC
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6951.h:144
static void menu_7_SPI_speed()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:698
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
static void menu_8_DC2430_site_select()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:758
static int dc2430_en_Pin
DC2430 digital pin enables Linduino to control which DC2430 site is selected & turns on DC2430 LED...
Definition: DC2248A.ino:140
static void setup()
Initialize Linduino.
Definition: DC2248A.ino:145
static int dc2430_site_DA2_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:139
uint8_t eeprom_write_int16(uint8_t i2c_address, int16_t write_data, uint16_t address)
Write the 2 byte integer data to the EEPROM starting at address.
uint8_t LTC6951_read(uint8_t cs, int8_t address)
LTC6951 Read Single Address reads 8 bit Data field to LTC6951.
Definition: LTC6951.cpp:108
static int8_t demo_board_connected
Demo Board Name stored in QuikEval EEPROM.
Definition: DC2248A.ino:126
uint8_t eeprom_read_byte(uint8_t i2c_address, char *data, uint16_t address)
Read a data byte at address from the EEPROM with i2c_address.
QuikEval EEPROM Library.
uint8_t get_LTC6951_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6951.cpp:242
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
#define EEPROM_CAL_STATUS_ADDRESS
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
#define LTC6951_CS
Define the SPI CS pin.
Definition: LTC6951.h:76
static void print_title()
Prints the title block when program first starts.
Definition: DC2248A.ino:862
static void menu_1_load_default_settings()
Menu 1: Load Default SPI Register Settings This function loads the register settings from a look up t...
Definition: DC2248A.ino:324
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
static void menu_5_restore_settings()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:589
static int dc2430_site_A0_APin
DC2430 resistor tree, if it reads 3.3V then DC2430 connected.
Definition: DC2248A.ino:132
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
static void menu_2_RW_to_reg_addresss()
Menu 2: Reads and/or Writes the SPI register address This function reads and displays all SPI registe...
Definition: DC2248A.ino:382
static uint8_t First_Run
if first time through loop = 0, otherwise=1
Definition: DC2248A.ino:128
int32_t read_int()
boolean Using_DC2430
Indicator if DC2430 (Linduino Expander) is connected.
Definition: DC2248A.ino:129
static void print_prompt()
Prints main menu.
Definition: DC2248A.ino:893
static int dc2430_site_A2_APin
DC2430 INFO ONLY, measures DC2226 (Linduino) VCCIO voltage.
Definition: DC2248A.ino:134
void LTC6951_init()
Initializes the SPI MAP arrays The values set in initialization are used for all the LTC6951 SPI/WRIT...
Definition: LTC6951.cpp:535
void LTC6951_write(uint8_t cs, uint8_t address, uint8_t Data)
LTC6951 Write Single Address writes 8 bit Data field to LTC6951.
Definition: LTC6951.cpp:175
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
void set_LTC6951_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
Sets the LTC6951 SPI field value calls function LTC6951_read_field, which reads specific address/fiel...
Definition: LTC6951.cpp:275
long field_menu_RW(long field_val, char field_name[], uint8_t f)
Support function for function menu_3_RW_to_reg_field displays current state of select field provides ...
Definition: DC2248A.ino:437
static int i
Definition: DC2430A.ino:184
long get_LTC6951_SPI_FIELD(uint8_t cs, uint8_t f)
Gets the LTC6951 SPI field value calls function LTC6951_read_field, which reads specific address loca...
Definition: LTC6951.cpp:164
int8_t discover_demo_board_local(char *demo_name)
Read the ID string from the EEPROM and determine if any demo board is connected.
Definition: LTC6951.cpp:831
static int8_t dc2248_board_connected
Demo Board Name stored in QuikEval EEPROM.
Definition: DC2248A.ino:127
#define EEPROM_CAL_KEY
#define LTC6951_CAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6951.h:90
static void menu_4_store_settings()
Store PLL settings to nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:564
static int dc2430_site_DA1_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:138
static void loop()
Repeats Linduino loop.
Definition: DC2248A.ino:254
static int dc2430_site_A1_APin
DC2430 resistor tree, if it reads 1.66V then DC2430 connected.
Definition: DC2248A.ino:133