| 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
116 void menu_2_RW_to_reg_addresss();
117 void menu_3_RW_to_reg_field();
118 void menu_4_store_settings();
119 void menu_5_restore_settings();
120 void menu_6_multibytewrite();
121 void menu_7_SPI_speed();
122 void menu_8_DC2430_site_select();
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
186 dc2248_board_connected =0;
187 demo_board_connected = 0;
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.
196 if (demo_board_connected)
197 {
198 Serial.println(F("\n********************************************************"));
199 dc2248_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
200
201 if (dc2248_board_connected)
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
215 if (!dc2248_board_connected)
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)
225 if (!dc2248_board_connected)
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.
237 if (dc2248_board_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
244 if (dc2248_board_connected)
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:
272 menu_1_load_default_settings();
273 break;
274
275 case 2:
276 menu_2_RW_to_reg_addresss();
277 break;
278
279 case 3:
280 menu_3_RW_to_reg_field();
281 break;
282
283 case 4:
284 menu_4_store_settings();
285 break;
286
287 case 5:
288 menu_5_restore_settings();
289 break;
290
291 case 6:
292 menu_6_multibytewrite();
293 break;
294
295 case 7:
296 menu_7_SPI_speed();
297 break;
298
299 case 8:
300 menu_8_DC2430_site_select();
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
324 void menu_1_load_default_settings()
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
382 void menu_2_RW_to_reg_addresss()
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
498 void menu_3_RW_to_reg_field()
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
564 void menu_4_store_settings()
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
575 eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS); // Cal key
576
577 for (uint8_t i = 0; i <= num_reg ; i++)
578 {
579 regval = LTC6951_read(LTC6951_CS,i);
580 eeprom_write_byte(EEPROM_I2C_ADDRESS,(char) regval, EEPROM_CAL_STATUS_ADDRESS+ i+addr_offset);
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
589 void menu_5_restore_settings()
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
605 eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
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"));
619 set_LTC6951_SPI_FIELD(LTC6951_CS, LTC6951_CAL, 1L);
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 {
638 set_LTC6951_SPI_FIELD(LTC6951_CS, LTC6951_SSYNC, 1L);
639 delay(1);
640 set_LTC6951_SPI_FIELD(LTC6951_CS, LTC6951_SSYNC, 0L);
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
651 void menu_6_multibytewrite()
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
698 void menu_7_SPI_speed()
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
758 void menu_8_DC2430_site_select()
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
780 demo_board_connected=0;
781 dc2248_board_connected=0;
782 demo_board_connected = discover_demo_board_local(demo_name); //! Checks if any demo board is connected.
783
784 if (demo_board_connected)
785 {
786 Serial.println(F("\n********************************************************"));
787 dc2248_board_connected = discover_demo_board(demo_name); //! Checks if correct demo board is connected.
788 }
789 if (!dc2248_board_connected)
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.
862 void print_title()
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.
893 void print_prompt()
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
menu_6_multibytewrite
static void menu_6_multibytewrite()
Frequency change Timing test (SPI write + Calibration + Settling Time): Provides two frequency settin...
Definition: DC2248A.ino:651
eeprom_read_int16
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.
Definition: QuikEval_EEPROM.cpp:395
user_command
unsigned char user_command
Definition: Serial_EEPROM_Test.ino:75
EEPROM_I2C_ADDRESS
#define EEPROM_I2C_ADDRESS
Definition: QuikEval_EEPROM.h:60
get_LTC6951_SPI_FIELD_RW
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
eeprom_write_byte
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.
Definition: QuikEval_EEPROM.cpp:214
get_LTC6951_SPI_FIELD_NUMBITS
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.h
LTC6951: Ultra-Low Jitter 2MHz to 2.7GHz Multi-Output Clock Synthesizer with Integrated VCO...
menu_3_RW_to_reg_field
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
Linduino.h
Header File for Linduino Libraries and Demo Code.
dc2430_site_select
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
set_LTC6951_REGS_freq_jump
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
set_LTC6951_REGS_lkup_tbl
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
spi_enable
void spi_enable(uint8_t spi_clock_divider)
Setup the processor for hardware SPI communication.
Definition: LT_SPI.cpp:160
DUTsync
static void DUTsync(uint16_t delay_num)
Syncs LTC6951 Outputs using SSYNC bit.
Definition: DC2248A.ino:636
dc2430_site_DA0_Pin
static int dc2430_site_DA0_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:137
LTC6951_SSYNC
#define LTC6951_SSYNC
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6951.h:144
menu_7_SPI_speed
static void menu_7_SPI_speed()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:698
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
menu_8_DC2430_site_select
static void menu_8_DC2430_site_select()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:758
dc2430_en_Pin
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
setup
static void setup()
Initialize Linduino.
Definition: DC2248A.ino:145
dc2430_site_DA2_Pin
static int dc2430_site_DA2_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:139
eeprom_write_int16
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.
Definition: QuikEval_EEPROM.cpp:377
LTC6951_read
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
demo_board_connected
static int8_t demo_board_connected
Demo Board Name stored in QuikEval EEPROM.
Definition: DC2248A.ino:126
eeprom_read_byte
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.
Definition: QuikEval_EEPROM.cpp:282
QuikEval_EEPROM.h
QuikEval EEPROM Library.
get_LTC6951_REGSIZE
uint8_t get_LTC6951_REGSIZE()
returns # of addresses in parts register map (array size)
Definition: LTC6951.cpp:242
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
EEPROM_CAL_STATUS_ADDRESS
#define EEPROM_CAL_STATUS_ADDRESS
Definition: QuikEval_EEPROM.h:58
discover_demo_board
int8_t discover_demo_board(char *demo_name)
Read the ID string from the EEPROM and determine if the correct board is connected.
Definition: QuikEval_EEPROM.cpp:141
LTC6951_CS
#define LTC6951_CS
Define the SPI CS pin.
Definition: LTC6951.h:76
print_title
static void print_title()
Prints the title block when program first starts.
Definition: DC2248A.ino:862
menu_1_load_default_settings
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.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
menu_5_restore_settings
static void menu_5_restore_settings()
Read stored PLL settings from nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:589
dc2430_site_A0_APin
static int dc2430_site_A0_APin
DC2430 resistor tree, if it reads 3.3V then DC2430 connected.
Definition: DC2248A.ino:132
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
demo_name
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
quikeval_SPI_connect
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
menu_2_RW_to_reg_addresss
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
UserInterface.h
First_Run
static uint8_t First_Run
if first time through loop = 0, otherwise=1
Definition: DC2248A.ino:128
read_int
int32_t read_int()
Definition: UserInterface.cpp:93
Using_DC2430
boolean Using_DC2430
Indicator if DC2430 (Linduino Expander) is connected.
Definition: DC2248A.ino:129
print_prompt
static void print_prompt()
Prints main menu.
Definition: DC2248A.ino:893
dc2430_site_A2_APin
static int dc2430_site_A2_APin
DC2430 INFO ONLY, measures DC2226 (Linduino) VCCIO voltage.
Definition: DC2248A.ino:134
LTC6951_init
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
LTC6951_write
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
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
set_LTC6951_SPI_FIELD
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
field_menu_RW
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
i
static int i
Definition: DC2430A.ino:184
get_LTC6951_SPI_FIELD
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
discover_demo_board_local
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
dc2248_board_connected
static int8_t dc2248_board_connected
Demo Board Name stored in QuikEval EEPROM.
Definition: DC2248A.ino:127
EEPROM_CAL_KEY
#define EEPROM_CAL_KEY
Definition: QuikEval_EEPROM.h:59
LTC6951_CAL
#define LTC6951_CAL
for spi_map array, defines location for field specific information used to create the spi map ...
Definition: LTC6951.h:90
menu_4_store_settings
static void menu_4_store_settings()
Store PLL settings to nonvolatile EEPROM on demo board.
Definition: DC2248A.ino:564
dc2430_site_DA1_Pin
static int dc2430_site_DA1_Pin
DC2430 digital pin allows Linduino to control which DC2430 site is selected.
Definition: DC2248A.ino:138
loop
static void loop()
Repeats Linduino loop.
Definition: DC2248A.ino:254
dc2430_site_A1_APin
static int dc2430_site_A1_APin
DC2430 resistor tree, if it reads 1.66V then DC2430 connected.
Definition: DC2248A.ino:133