| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

DC2376A.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology DC2376A Demonstration Board.
3 LTC2664: 4 Channel SPI 16-/12-Bit Rail-to-Rail DACs with 10ppm/C Max Reference.
4
5 @verbatim
6 NOTES
7 Setup:
8 Set the terminal baud rate to 115200 and select the newline terminator.
9
10 An external +/- 15V power supply is required to power the circuit.
11
12 The program displays calculated voltages which are based on the voltage
13 of the reference used, be it internal or external. A precision voltmeter
14 is needed to verify the actual measured voltages against the calculated
15 voltage displayed.
16
17 If an external reference is used, a precision voltage
18 source is required to apply the external reference voltage. A
19 precision voltmeter is also required to measure the external reference
20 voltage.
21
22 Explanation of Commands:
23 1- Select DAC: Select one of four DACs to test : 0 to 3
24
25 2- Write to DAC input register: Value is stored in the DAC for updating
26 later, allowing multiple channels to be updated at once, either
27 through a software "Update All" command or by asserting the LDAC# pin.
28 User will be prompted to enter either a code in hex or decimal, or a
29 voltage. If a voltage is entered, a code will be calculated based on
30 the active scaling and reference parameters - ideal values if no
31 calibration was ever stored.
32
33 3- Write and Update: Similar to item 1, but DAC is updated immediately.
34
35 4- Update DAC: Copies the value from the input register into the DAC
36 Register. Note that a "write and update" command writes the code to
37 BOTH the input register and DAC register, so subsequent "update"
38 commands will simply re-copy the same data (no change in output.)
39
40 5- Power Down DAC: Disable DAC output. Power supply current is reduced.
41 DAC code present in DAC registers at time of shut down are preserved.
42
43 6- Set reference mode, either internal or external: Selecting external
44 mode powers down the internal reference voltage. It is the users
45 responsibility to apply a 2.5V reference.
46
47 7- Set SoftSpan: There are four options. In external mode, it is the users
48 responsibility to compensate for the desired voltage.
49
50 8- Toggle Selected Word: Switch between register A or B for DAC code.
51
52 9- Set MUX: Enables / disables the MUX and sets the channel.
53
54 10- Global Toggle Bit Settings - Enabling this feature sets the DAC to
55 toggle from register A(when TGL pin is LOW) and register b(when TGL pin
56 is HIGH). TGL pin is set HIGH with an internal pull up when the global toggle bit
57 is set, and TGL pin is set LOW with an internal pull down when the global toggle bit
58 is not set.
59
60 11- Enable, disable, or store to EEPROM: To store to EEROM ensure all
61 registers are set to their desired settings. Next, go to the store
62 setting EEPROM menu and select it. Upon Linduino power up, the
63 previously stored settings will be restored.
64
65 12- Voltage Ramp: Sets a voltage ramp to all the channels. CH0 = 0V, CH1 = 0.1V,
66 CH2 = 0.2V, CH3 = 0.4V, ect.
67
68 USER INPUT DATA FORMAT:
69 decimal : 1024
70 hex : 0x400
71 octal : 02000 (leading 0 "zero")
72 binary : B10000000000
73 float : 1024.0
74
75 @endverbatim
76
77 http://www.linear.com/product/LTC2664
78
79 http://www.linear.com/product/LTC2664#demoboards
80
81
82 Copyright 2018(c) Analog Devices, Inc.
83
84 All rights reserved.
85
86 Redistribution and use in source and binary forms, with or without
87 modification, are permitted provided that the following conditions are met:
88 - Redistributions of source code must retain the above copyright
89 notice, this list of conditions and the following disclaimer.
90 - Redistributions in binary form must reproduce the above copyright
91 notice, this list of conditions and the following disclaimer in
92 the documentation and/or other materials provided with the
93 distribution.
94 - Neither the name of Analog Devices, Inc. nor the names of its
95 contributors may be used to endorse or promote products derived
96 from this software without specific prior written permission.
97 - The use of this software may or may not infringe the patent rights
98 of one or more patent holders. This license does not release you
99 from the requirement that you obtain separate licenses from these
100 patent holders to use this software.
101 - Use of the software either in source or binary form, must be run
102 on or directly connected to an Analog Devices Inc. component.
103
104 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
105 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
106 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
107 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
108 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
109 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
110 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
111 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
112 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
113 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
114 */
115
116 /*! @file
117 @ingroup LTC2664
118 */
119
120 #include <Arduino.h>
121 #include <stdint.h>
122 #include "Linduino.h"
123 #include "LT_SPI.h"
124 #include "UserInterface.h"
125 #include "LT_I2C.h"
126 #include "QuikEval_EEPROM.h"
127 #include "LTC2664.h"
128 #include <SPI.h>
129 #include <Wire.h>
130
131 // Macros
132 #define REF_EXTERNAL LTC2664_REF_DISABLE //!< External mode
133 #define REF_INTERNAL 0 //!< Internal mode
134
135 // Function Declaration
136
137 void restore_dac_from_eeprom(); // Restores DAC settings from EEPROM
138 void print_title(); // Print the title block
139 void print_prompt(int8_t selected_dac); // Prompt the user for an input command
140 int16_t prompt_voltage_or_code(uint8_t selected_dac); // Prompt the user for voltage or code
141 uint16_t get_voltage(uint8_t selected_dac); // Obtains voltage from user
142 uint16_t get_code(); // Obtains code from user
143
144 void menu_1_select_dac(uint8_t *selected_dac); // Menu 1: prompts user for DAC selection
145 void menu_2_write_to_input_register(uint8_t selected_dac); // Menu 2: sends data to selected DAC register with no update
146 void menu_3_write_and_update_dac(uint8_t selected_dac); // Menu 3: sends data to selected DAC register with update
147 void menu_4_update_power_up_dac(uint8_t selected_dac); // Menu 4: updates and powers up selected DAC
148 void menu_5_power_down_dac(uint8_t selected_dac); // Menu 5: powers down selected DAC
149 void menu_6_set_reference_mode(); // Menu 6: prompts user to enable/disable internal reference
150 void menu_7_set_softspan_range(uint8_t selected_dac); // Menu 7: prompts user to sets the SoftSpan range
151 void menu_8_toggle_select_word(); // Menu 8: prompts user to enter the toggle select word
152 void menu_9_set_mux(); // Menu 9: sets MUX
153 void menu_10_global_toggle_settings(); // Menu 10: sets the global toggle bit
154 void menu_11_enable_disable_eeprom_restore(); // Menu 11: EEPOM restore settings
155 void menu_12_voltage_ramp(); // Menu 12: sets a voltage ramp for the LTC2664
156 void menu_13_demo_board_test(); // Menu 13: Demo Board functional test
157 void menu_14_loopback_test();
158 // Global variable
159 static uint8_t demo_board_connected; //!< Set to 1 if the board is connected
160
161 //! Used to manipulate EEPROM data.
162 union eeprom_data_union
163 {
164 struct data_struct_type //! EEPROM data structure
165 {
166 int16_t cal_key; //!< The key that keeps track of the calibration
167 uint8_t soft_span_range[4]; //!< SoftSpan range
168 uint16_t dac_code_a[4]; //!< DAC Register A
169 uint16_t dac_code_b[4]; //!< DAC Register B
170 uint16_t toggle_word; //!< Toggle control word
171 uint8_t global_toggle_bit; //!< Global toggle bit
172 uint8_t mux_state; //!< Multiplexer address AND enable bit
173 uint8_t reference_mode; //!< Int. reference may be disabled in external reference mode (not required)
174 } data_struct; //!< Name of structure
175
176 char byte_array[sizeof(data_struct_type)]; //!< Array used to store the structure
177 };
178
179 eeprom_data_union eeprom; // Create union
180
181 // Constants
182
183 //! Used to keep track to print voltage or print code
184 enum
185 {
186 PROMPT_VOLTAGE = 0, /**< 0 */
187 PROMPT_CODE = 1 /**< 1 */
188 };
189
190 //! Initialize Linduino
191 void setup()
192 // Setup the program
193 {
194 char demo_name[] = "DC2376"; // Demo Board Name stored in QuikEval EEPROM
195
196 quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
197 quikeval_SPI_connect(); // Connect SPI to main data port
198 quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz
199
200 Serial.begin(115200); // Initialize the serial port to the PC
201 print_title();
202 demo_board_connected = discover_demo_board(demo_name);
203 if (demo_board_connected)
204 {
205 restore_dac_from_eeprom();
206 print_prompt(0);
207 }
208 }
209
210 //! Repeats Linduino loop
211 void loop()
212 {
213
214 int16_t user_command;
215 static uint8_t selected_dac = 0; // The selected DAC to be updated (0=CH0, 1=CH1 ... 8=All). Initialized to CH0.
216
217 if (Serial.available()) // Check for user input
218 {
219 user_command = read_int(); // Read the user command
220 Serial.println(user_command);
221 Serial.print(F("\n"));
222 Serial.flush();
223 switch (user_command)
224 {
225 case 1:
226 menu_1_select_dac(&selected_dac);
227 break;
228 case 2:
229 menu_2_write_to_input_register(selected_dac);
230 break;
231 case 3:
232 menu_3_write_and_update_dac(selected_dac);
233 break;
234 case 4:
235 menu_4_update_power_up_dac(selected_dac);
236 break;
237 case 5:
238 menu_5_power_down_dac(selected_dac);
239 break;
240 case 6:
241 menu_6_set_reference_mode();
242 break;
243 case 7:
244 menu_7_set_softspan_range(selected_dac);
245 break;
246 case 8:
247 menu_8_toggle_select_word();
248 break;
249 case 9:
250 menu_9_set_mux();
251 break;
252 case 10:
253 menu_10_global_toggle_settings();
254 break;
255 case 11:
256 menu_11_enable_disable_eeprom_restore();
257 break;
258 case 12:
259 menu_12_voltage_ramp();
260 break;
261 case 13:
262 menu_13_demo_board_test();
263 break;
264 case 14:
265 menu_14_loopback_test();
266 break;
267 default:
268 Serial.println(F("Incorrect Option"));
269 break;
270 }
271 Serial.println(F("\n************************************************************"));
272 print_prompt(selected_dac);
273 }
274
275 }
276
277 // Function Definitions
278
279 //! Select which DAC to operate on
280 void menu_1_select_dac(uint8_t *selected_dac)
281 {
282 // Select a DAC to operate on
283 Serial.print(F("Select DAC to operate on (0 to 3, 4 for ALL DACs): "));
284 *selected_dac = read_int();
285 if (*selected_dac == 4)
286 Serial.println(F("All"));
287 else
288 Serial.println(*selected_dac);
289 }
290
291 //! Write data to input register, but do not update DAC output
292 void menu_2_write_to_input_register(uint8_t selected_dac)
293 {
294 uint16_t dac_code;
295
296 if (prompt_voltage_or_code(selected_dac) == PROMPT_VOLTAGE)
297 dac_code = get_voltage(selected_dac);
298 else
299 dac_code = get_code();
300
301 if (selected_dac <= 3)
302 {
303 // Store dac_code to register variable a or b
304 if (eeprom.data_struct.toggle_word & (0x01 << selected_dac))
305 {
306 eeprom.data_struct.dac_code_b[selected_dac] = dac_code;
307 }
308 else
309 eeprom.data_struct.dac_code_a[selected_dac] = dac_code;
310 LTC2664_write(LTC2664_CS, LTC2664_CMD_WRITE_N, selected_dac, dac_code);
311 }
312 else
313 {
314 // Store dac_code to register variable a or b
315 for (uint8_t i = 0; i <= 3 ; i++)
316 {
317 if (eeprom.data_struct.toggle_word & (0x01 << i))
318 {
319 eeprom.data_struct.dac_code_b[i] = dac_code;
320 }
321 else
322 eeprom.data_struct.dac_code_a[i] = dac_code;
323 }
324 LTC2664_write(LTC2664_CS, LTC2664_CMD_WRITE_ALL, selected_dac, dac_code);
325 }
326 }
327
328 //! Write data to DAC register (which updates output immediately)
329 void menu_3_write_and_update_dac(uint8_t selected_dac)
330 {
331 uint16_t dac_code;
332
333 if (prompt_voltage_or_code(selected_dac) == PROMPT_VOLTAGE)
334 dac_code = get_voltage(selected_dac);
335 else
336 dac_code = get_code();
337
338 if (selected_dac <= 3)
339 {
340 // Store dac_code to register variable a or b
341 if (eeprom.data_struct.toggle_word & (0x01 << selected_dac))
342 {
343 eeprom.data_struct.dac_code_b[selected_dac] = dac_code;
344 }
345 else
346 eeprom.data_struct.dac_code_a[selected_dac] = dac_code;
347
348 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, selected_dac, dac_code); // Send dac_code
349 }
350 else // All DACs
351 {
352 // Store dac_code to register variable a or b
353 for (uint8_t i = 0; i <= 3 ; i++)
354 {
355 if (eeprom.data_struct.toggle_word & (0x01 << i))
356 {
357 eeprom.data_struct.dac_code_b[i] = dac_code;
358 }
359 else
360 eeprom.data_struct.dac_code_a[i] = dac_code;
361 }
362 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_ALL_UPDATE_ALL, 0, dac_code); // Send dac_code
363 }
364 }
365
366 //! Update DAC with data that is stored in input register, power up if sleeping
367 void menu_4_update_power_up_dac(uint8_t selected_dac)
368 {
369 // Update DAC
370 if (selected_dac <= 3)
371 LTC2664_write(LTC2664_CS,LTC2664_CMD_UPDATE_N, selected_dac, 0);
372 else
373 LTC2664_write(LTC2664_CS,LTC2664_CMD_UPDATE_ALL, 0, 0);
374 }
375
376 //! Power down DAC
377 void menu_5_power_down_dac(uint8_t selected_dac)
378 {
379 // Power down DAC
380 if (selected_dac <= 3)
381 LTC2664_write(LTC2664_CS, LTC2664_CMD_POWER_DOWN_N, selected_dac, 0);
382 else
383 LTC2664_write(LTC2664_CS, LTC2664_CMD_POWER_DOWN_ALL, 0, 0);
384 }
385
386 //! Set reference mode
387 void menu_6_set_reference_mode(void)
388 {
389 int16_t user_command;
390 Serial.println(F("0 - Power down the internal reference"));
391 Serial.println(F("1 - Power up the internal reference"));
392 user_command = read_int();
393 if (user_command > 1)
394 user_command = 1;
395 if (user_command < 0)
396 user_command = 0;
397
398 if (user_command == 1)
399 {
400 eeprom.data_struct.reference_mode = REF_INTERNAL;
401 LTC2664_write(LTC2664_CS, LTC2664_CMD_CONFIG, 0, eeprom.data_struct.reference_mode);
402 Serial.println(F("Internal reference has been powered up"));
403 }
404 else
405 {
406 eeprom.data_struct.reference_mode = REF_EXTERNAL;
407 LTC2664_write(LTC2664_CS, LTC2664_CMD_CONFIG, 0, eeprom.data_struct.reference_mode);
408 Serial.println(F("Internal reference has been powered down"));
409 }
410 }
411
412 //! Set SoftSpan Range
413 void menu_7_set_softspan_range(uint8_t selected_dac)
414 {
415 int16_t user_command;
416
417 Serial.println(F("0- 0V to 5V"));
418 Serial.println(F("1- 0V to 10V"));
419 Serial.println(F("2- -5V to 5V"));
420 Serial.println(F("3- -10V to 10V"));
421 Serial.println(F("4- -2.5V to 2.5V"));
422 Serial.print(F("Select a SoftSpan Range: "));
423 user_command = read_int();
424
425 if (user_command > 4)
426 user_command = 4;
427 if (user_command < 0)
428 user_command = 0;
429 Serial.println(user_command);
430
431 if (selected_dac <= 3)
432 {
433 eeprom.data_struct.soft_span_range[selected_dac] = user_command;
434 LTC2664_write(LTC2664_CS, LTC2664_CMD_SPAN, selected_dac, eeprom.data_struct.soft_span_range[selected_dac]);
435 }
436 else
437 {
438 for (uint8_t i = 0; 0 <= 3; i++)
439 eeprom.data_struct.soft_span_range[i] = user_command;
440
441 LTC2664_write(LTC2664_CS, LTC2664_CMD_SPAN_ALL, 0, eeprom.data_struct.soft_span_range[0]);
442 }
443 }
444
445 //! Enter toggle select word, which also sets the register that will be written
446 //! if bit is 0, register A is written, if 1, register B is written.
447 void menu_8_toggle_select_word()
448 {
449 // Select a DAC to operate on
450 Serial.println(F("Toggle Select bit sets the register to be written for the corresponding DAC."));
451 Serial.println(F("0 for Register A or 1 for Register B."));
452 Serial.println(F("Note: DAC Update from Register B requires TGB = 1"));
453 Serial.println(F(" DAC Update from Register A requires TCB = 0"));
454 Serial.print(F("Enter Toggle Select Byte as hex (0xM) or binary (B1010): "));
455
456
457 eeprom.data_struct.toggle_word = read_int();
458 // Toggle bits are stored as 16 bit word with 12 don't care bits
459
460 LTC2664_write(LTC2664_CS, LTC2664_CMD_TOGGLE_SEL, 0, eeprom.data_struct.toggle_word);
461 Serial.println(eeprom.data_struct.toggle_word, BIN);
462 }
463
464 //! Enable / Disable and sets the channel for the MUX
465 void menu_9_set_mux()
466 {
467 int16_t user_command;
468 Serial.println(F("0- Disable Mux"));
469 Serial.println(F("1- Enable Mux"));
470 Serial.print(F("Enter a command: "));
471 user_command = read_int();
472
473 if (user_command == 1)
474 {
475 Serial.print(F("Select MUX channel(0-MUXIN0, 1-VOUT0, 2-VOUT1, 3-MUXIN1, 4-MUXIN2, 5-VOUT2, 6-VOUT3, 7-MUXIN3, 8-REFLO, 9-REF, 10-TEMP Monitor, 11-V+, 12-V- : "));
476 user_command = read_int();
477
478 if (user_command > 12)
479 user_command = 12;
480 if (user_command < 0)
481 user_command = 0;
482
483 Serial.println(user_command);
484 eeprom.data_struct.mux_state = LTC2664_MUX_ENABLE | user_command;
485 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, eeprom.data_struct.mux_state);
486 }
487 else
488 {
489 eeprom.data_struct.mux_state = LTC2664_MUX_ENABLE | user_command;
490 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, eeprom.data_struct.mux_state);
491 Serial.println(F("The MUX has been disabled"));
492 }
493 }
494 //! Enable / Disable the global toggle bit
495 void menu_10_global_toggle_settings()
496 {
497 int16_t user_command;
498 Serial.println(F("0- Disable Global Toggle"));
499 Serial.println(F("1- Enable Global Toggle"));
500 Serial.print(F("Enter a command: "));
501 user_command = read_int();
502
503 if (user_command > 1)
504 user_command = 1;
505 if (user_command < 0)
506 user_command = 0;
507 Serial.println(user_command);
508
509 eeprom.data_struct.global_toggle_bit = user_command;
510 LTC2664_write(LTC2664_CS, LTC2664_CMD_GLOBAL_TOGGLE, 0, eeprom.data_struct.global_toggle_bit);
511 }
512
513 //! Enable / Disable restoration of DAC values from EEPROM Use with caution - behaviour is undefined if you
514 //! enable restoration and data has NOT been previously stored from a known state.
515 void menu_11_enable_disable_eeprom_restore()
516 {
517 int16_t user_input;
518 Serial.println(F("\n0- Enable Restoration"));
519 Serial.println(F("1- Disable Restoration"));
520 Serial.println(F("2- Store DAC Settings"));
521 user_input = read_int();
522 switch (user_input)
523 {
524 case 0:
525 Serial.println(F("Enabling EEPROM restoration"));
526 eeprom.data_struct.cal_key = EEPROM_CAL_KEY;
527 eeprom_write_int16(EEPROM_I2C_ADDRESS, eeprom.data_struct.cal_key, EEPROM_CAL_STATUS_ADDRESS);
528 break;
529 case 1:
530 Serial.println(F("Disabling EEPROM restoration"));
531 eeprom.data_struct.cal_key = 0;
532 eeprom_write_int16(EEPROM_I2C_ADDRESS, eeprom.data_struct.cal_key, EEPROM_CAL_STATUS_ADDRESS);
533 break;
534 case 2:
535 eeprom.data_struct.cal_key = EEPROM_CAL_KEY;
536 eeprom_write_byte_array(EEPROM_I2C_ADDRESS, eeprom.byte_array, EEPROM_CAL_STATUS_ADDRESS, sizeof(eeprom_data_union));
537 Serial.println(F("Stored Settings to EEPROM"));
538 }
539 }
540
541 //! Sets a voltage ramp to all the channels
542 void menu_12_voltage_ramp()
543 {
544 uint8_t i;
545 for (i=0; i <= 3; ++i)
546 {
547 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, i, i * 1312);
548 }
549 Serial.println("A voltage ramp was set to the LTC2664");
550 }
551
552 // Functional test for demo board, tests continuity, EEPROM contents,
553 // And correct resolution DAC installed.
554 void menu_13_demo_board_test()
555 {
556 uint8_t i, errorcount = 0;
557
558 Serial.println(F("Welcome to the LTC2664 Demo Board Test Program."));
559 Serial.print(F("Found board assembly type "));
560 Serial.println(demo_board.option);
561
562 Serial.println(F("Checking EEPROM contents..."));
563
564 read_quikeval_id_string(&ui_buffer[0]);
565 ui_buffer[48] = 0;
566 Serial.println(ui_buffer);
567 switch (demo_board.option)
568 {
569 case 'A':
570 if (strcmp("LTC2664-16,Cls,D2668,01,01,DC,DC2376A-A,--------", ui_buffer))
571 {
572 Serial.println(F("FAILED EEPROM Contents"));
573 errorcount += 1;
574 }
575 break;
576 case 'B':
577 if (strcmp("LTC2664-12,Cls,D2668,01,01,DC,DC2376A-B,--------", ui_buffer))
578 {
579 Serial.println(F("FAILED EEPROM Contents"));
580 errorcount += 1;
581 }
582 break;
583 }
584
585 if (!errorcount)
586 Serial.println(F("EEPROM good!"));
587
588 Serial.println(F("Ensure all jumpers are in the LEFT position (INT ref, MSP0,1,2 = 1."));
589 Serial.println(F("Writing ramp of voltages to DAC outputs. Verify DAC0 = 0.10V, DAC1 = 0.20V,"));
590 Serial.println(F("DAC2 = 0.3V ... DAC7 = 0.8V. Type 1, enter when done."));
591
592 LTC2664_write(LTC2664_CS, LTC2664_CMD_CONFIG, 0, REF_INTERNAL);
593
594 for (i=0; i <= 3; ++i)
595 {
596 LTC2664_write(LTC2664_CS,LTC2664_CMD_SPAN, i, LTC2664_SPAN_0_TO_5V);
597 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, i, (i + 1) * 1312);
598 }
599
600 read_int(); // Read the user command
601
602 Serial.println(F("Setting SoftSpan range to +/-10V, DAC7 to -10V, and MUX to DAC7."));
603 Serial.println(F("Verify MUX output is between -9.95V and -10.05V"));
604
605 LTC2664_write(LTC2664_CS,LTC2664_CMD_SPAN, 3, LTC2664_SPAN_PLUS_MINUS_10V);
606 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, 3, 0x0000);
607 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, LTC2664_MUX_ENABLE | 6); // Note MUX mapping according to Datasheet Table 5
608
609 Serial.println(F("Type 1, enter when done."));
610 read_int();
611
612 LTC2664_write(LTC2664_CS,LTC2664_CMD_SPAN, 3, LTC2664_SPAN_0_TO_10V);
613 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, 3, 0x0000);
614 Serial.println(F("Verifying correct resolution LTC2664 installed"));
615 Serial.println(F("output set to 0V, press REL(delta) button on meter"));
616 Serial.println(F("Type 1, enter when done."));
617 read_int();
618 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N_UPDATE_N, 3, 0x000F);
619
620 switch (demo_board.option)
621 {
622 case 'A':
623 Serial.println(F("16 bit device - verify output voltage is GREATER than 1mV"));
624 break;
625 case 'B':
626 Serial.println(F("12 bit device - verify output voltage is LESS than 1mV"));
627 break;
628 }
629
630 Serial.println(F("Type 1, enter when done."));
631 read_int();
632
633 Serial.println(F("Connect MUXIN0 to REF, verify MUX output is between 2.4 and 2.6V."));
634 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, LTC2664_MUX_ENABLE | 0);
635 Serial.println(F("Type 1, enter when done."));
636 read_int();
637
638 Serial.println(F("Connect MUXIN1 to REF, verify MUX output is between 2.4 and 2.6V."));
639 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, LTC2664_MUX_ENABLE | 3);
640 Serial.println(F("Type 1, enter when done."));
641 read_int();
642
643 Serial.println(F("Connect MUXIN2 to REF, verify MUX output is between 2.4 and 2.6V."));
644 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, LTC2664_MUX_ENABLE | 4);
645 Serial.println(F("Type 1, enter when done."));
646 read_int();
647
648 Serial.println(F("Connect MUXIN3 to REF, verify MUX output is between 2.4 and 2.6V."));
649 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, LTC2664_MUX_ENABLE | 7);
650 Serial.println(F("Type 1, enter when done."));
651 read_int();
652
653 Serial.println(F("All Done! Returning to main menu..."));
654 }
655
656 // Loopback test to verify data integrity.
657 void menu_14_loopback_test()
658 {
659 uint16_t i;
660 int8_t ack = 0;
661 Serial.print(F("Testing readback by writing 0-10,000, NOP commands\n"));
662 LTC2664_write(LTC2664_CS, LTC2664_CMD_NO_OPERATION, 0, 0); // If this is the first time the read function is called, need to initialize
663 for (i=0; i<=10000; ++i)
664 {
665 ack |= LTC2664_write(LTC2664_CS, LTC2664_CMD_NO_OPERATION, 0, i);
666 }
667 if (ack)
668 {
669 Serial.print(F("Oops, got an error somewhere!"));
670 }
671 else
672 {
673 Serial.print(F("No errors!!"));
674 }
675 }
676
677
678 //! Prompt user to enter a voltage or digital code to send to DAC
679 //! @returns user input
680 int16_t prompt_voltage_or_code(uint8_t selected_dac )
681 {
682 int16_t user_input;
683
684 Serial.print(F("Type 1 to enter voltage, 2 to enter code: "));
685 Serial.flush();
686 user_input = read_int();
687 Serial.println(user_input);
688
689 if (user_input != 2)
690 {
691 if (selected_dac >= 8)
692 {
693 Serial.println(F("\nCaution! Voltage SoftSpan could be different for different DACs"));
694 Serial.println(F("Ensure All DACs can be set to desired voltages"));
695 Serial.println(F("DAC 0 is used for SoftSpan values for all DACs."));
696 Serial.print(F("Toggle Register Select Bits 0=A, 1 = B: 0b"));
697 Serial.println(eeprom.data_struct.toggle_word, BIN);
698 }
699 return(PROMPT_VOLTAGE);
700 }
701 else
702 {
703 if (selected_dac >= 8)
704 {
705 Serial.println(F("DAC 0 is used for SoftSpan values for all DACs."));
706 }
707 }
708 return(PROMPT_CODE);
709 }
710
711 //! Get voltage from user input, calculate DAC code based on lsb, offset
712 //! @returns the DAC code
713 uint16_t get_voltage(uint8_t selected_dac)
714 {
715 float dac_voltage;
716
717 Serial.print(F("Enter Desired DAC output voltage: "));
718 dac_voltage = read_float();
719 Serial.print(dac_voltage);
720 Serial.println(F(" V"));
721 Serial.flush();
722
723 if (selected_dac <= 3)
724 return(LTC2664_voltage_to_code(dac_voltage,
725 LTC2664_MIN_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]],
726 LTC2664_MAX_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]]));
727 else
728 return(LTC2664_voltage_to_code(dac_voltage,
729 LTC2664_MIN_OUTPUT[eeprom.data_struct.soft_span_range[0]],
730 LTC2664_MAX_OUTPUT[eeprom.data_struct.soft_span_range[0]]));
731 }
732
733 //! Get code to send to DAC directly, in decimal, hex, or binary
734 //! @return code from user
735 uint16_t get_code()
736 {
737 uint16_t returncode;
738 Serial.println(F("Enter Desired DAC Code"));
739 Serial.print(F("(Format 32768, 0x8000, 0100000, or B1000000000000000): "));
740 returncode = (uint16_t) read_int();
741 Serial.print(F("0x"));
742 Serial.println(returncode, HEX);
743 Serial.flush();
744 return(returncode);
745 }
746
747 //! Prints the title block when program first starts.
748 void print_title()
749 {
750 Serial.println();
751 Serial.println(F("*****************************************************************"));
752 Serial.println(F("* DC2376 Demonstration Program *"));
753 Serial.println(F("* *"));
754 Serial.println(F("* This program demonstrates how to send data to the LTC2664 *"));
755 Serial.println(F("* Four Channel 16/12-bit DAC found on the DC2376 demo board. *"));
756 Serial.println(F("* *"));
757 Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
758 Serial.println(F("* *"));
759 Serial.println(F("*****************************************************************"));
760 }
761
762 //! Prints main menu.
763 void print_prompt(int8_t selected_dac)
764 {
765 // Displays menu
766 Serial.println(F("\nCommand Summary:"));
767 Serial.println(F(" 1-Select DAC"));
768 Serial.println(F(" 2-Write to input register (no update)"));
769 Serial.println(F(" 3-Write and update DAC"));
770 Serial.println(F(" 4-Update / power up DAC"));
771 Serial.println(F(" 5-Power down DAC"));
772 Serial.println(F(" 6-Set reference mode"));
773 Serial.println(F(" 7-Set SoftSpan"));
774 Serial.println(F(" 8-Toggle selected register"));
775 Serial.println(F(" 9-Set Mux"));
776 Serial.println(F(" 10-Global toggle bit settings"));
777 Serial.println(F(" 11-Enable, disable, or store to EEPROM"));
778 Serial.println(F(" 12-Voltage Ramp"));
779 Serial.println(F("\nPresent Values:"));
780 Serial.print(F(" Selected DAC: "));
781
782 // Display current settings
783 if (selected_dac >= 3 )
784 {
785 Serial.println(F("All"));
786 Serial.print(F(" SoftSpan range: "));
787 Serial.print(LTC2664_MIN_OUTPUT[eeprom.data_struct.soft_span_range[0]], 4);
788 Serial.print(F(" V to "));
789 Serial.print(LTC2664_MAX_OUTPUT[eeprom.data_struct.soft_span_range[0]], 4);
790 Serial.println(F(" V"));
791 }
792 else
793 {
794 Serial.println(selected_dac);
795 Serial.print(F(" SoftSpan range: "));
796 Serial.print(LTC2664_MIN_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]], 4);
797 Serial.print(F(" V to "));
798 Serial.print(LTC2664_MAX_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]], 4);
799 Serial.println(F(" V"));
800 }
801 Serial.print(F(" Toggle Register: "));
802 Serial.print(F("\nEnter a command: "));
803 Serial.flush();
804 }
805
806 //! Read the alert settings from EEPROM
807 void restore_dac_from_eeprom()
808 {
809 int16_t cal_key;
810 int8_t i;
811
812 // Read the cal key from the EEPROM
813 eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
814
815 if (cal_key == EEPROM_CAL_KEY)
816 {
817 // Calibration has been stored, read thresholds
818 eeprom_read_byte_array(EEPROM_I2C_ADDRESS, eeprom.byte_array, EEPROM_CAL_STATUS_ADDRESS, sizeof(eeprom_data_union));
819
820 // Write SoftSpan ranges
821 for (uint8_t i = 0; i <= 3; i++)
822 LTC2664_write(LTC2664_CS, LTC2664_CMD_SPAN, i, eeprom.data_struct.soft_span_range[i]);
823
824 // Write stored data to DAC A registers
825 for (uint8_t i = 0; i <= 3 ; i++)
826 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N, i, eeprom.data_struct.dac_code_a[i]);
827
828 LTC2664_write(LTC2664_CS, LTC2664_CMD_TOGGLE_SEL, 0, 0xFFFF); // Set to B registers
829
830 // Write stored data to DAC B registers
831 for (uint8_t i = 0; i <= 3 ; i++)
832 LTC2664_write(LTC2664_CS,LTC2664_CMD_WRITE_N, i, eeprom.data_struct.dac_code_b[i]);
833
834 LTC2664_write(LTC2664_CS, LTC2664_CMD_TOGGLE_SEL, 0, eeprom.data_struct.toggle_word); // Set toggle word
835
836 LTC2664_write(LTC2664_CS, LTC2664_CMD_GLOBAL_TOGGLE, 0, eeprom.data_struct.global_toggle_bit); // Set global toggle Bit
837
838 LTC2664_write(LTC2664_CS,LTC2664_CMD_MUX, 0, eeprom.data_struct.mux_state); // Set MUX
839
840 LTC2664_write(LTC2664_CS, LTC2664_CMD_CONFIG, 0, eeprom.data_struct.reference_mode); // Set reference
841
842 LTC2664_write(LTC2664_CS,LTC2664_CMD_UPDATE_ALL, 0, 0); // Update ALL
843
844 Serial.println(F("DAC settings loaded from EEPROM"));
845 }
846 else
847 Serial.println(F("EEPROM data not found"));
848 }
demo_board
struct demo_board_type demo_board
Instantiate demo board structure.
Definition: QuikEval_EEPROM.cpp:71
eeprom_read_byte_array
uint8_t eeprom_read_byte_array(uint8_t i2c_address, char *data, uint16_t address, uint8_t num_bytes)
Read a data byte at address from the EEPROM with i2c_address.
Definition: QuikEval_EEPROM.cpp:304
LTC2664_CMD_WRITE_N_UPDATE_N
#define LTC2664_CMD_WRITE_N_UPDATE_N
Write to input register n, update (power-up)
Definition: LTC2664.h:98
menu_5_power_down_dac
static void menu_5_power_down_dac(uint8_t selected_dac)
Power down DAC.
Definition: DC2376A.ino:377
demo_board_type::option
char option
Demo Circuit option (A)
Definition: QuikEval_EEPROM.h:72
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
PROMPT_CODE
1
Definition: DC2376A.ino:187
user_command
unsigned char user_command
Definition: Serial_EEPROM_Test.ino:75
EEPROM_I2C_ADDRESS
#define EEPROM_I2C_ADDRESS
Definition: QuikEval_EEPROM.h:60
LTC2664_MIN_OUTPUT
const float LTC2664_MIN_OUTPUT[5]
Definition: LTC2664.h:129
REF_EXTERNAL
#define REF_EXTERNAL
External mode.
Definition: DC2376A.ino:132
eeprom_data_union::data_struct_type::toggle_word
uint16_t toggle_word
Toggle control word.
Definition: DC2692A.ino:168
LTC2664_CMD_SPAN_ALL
#define LTC2664_CMD_SPAN_ALL
Set span for all DACs.
Definition: LTC2664.h:110
eeprom_data_union::data_struct_type::cal_key
int16_t cal_key
The key that keeps track of the calibration.
Definition: DC2692A.ino:164
LTC2664_CMD_NO_OPERATION
#define LTC2664_CMD_NO_OPERATION
No operation.
Definition: LTC2664.h:111
menu_6_set_reference_mode
static void menu_6_set_reference_mode()
Set reference mode.
Definition: DC2376A.ino:387
LTC2664_CMD_POWER_DOWN_N
#define LTC2664_CMD_POWER_DOWN_N
Power down n.
Definition: LTC2664.h:99
LTC2664_CMD_CONFIG
#define LTC2664_CMD_CONFIG
Configure reference / toggle.
Definition: LTC2664.h:103
Linduino.h
Header File for Linduino Libraries and Demo Code.
LTC2664_CMD_UPDATE_ALL
#define LTC2664_CMD_UPDATE_ALL
Update all DACs.
Definition: LTC2664.h:105
LTC2664_SPAN_PLUS_MINUS_10V
#define LTC2664_SPAN_PLUS_MINUS_10V
Definition: LTC2664.h:122
loop
static void loop()
Repeats Linduino loop.
Definition: DC2376A.ino:211
eeprom_write_byte_array
uint8_t eeprom_write_byte_array(uint8_t i2c_address, char data[], uint16_t address, uint8_t num_bytes)
Write the data byte array to the EEPROM with i2c_address starting at EEPROM address.
Definition: QuikEval_EEPROM.cpp:234
menu_14_loopback_test
static void menu_14_loopback_test()
Definition: DC2376A.ino:657
print_prompt
static void print_prompt(int8_t selected_dac)
Prints main menu.
Definition: DC2376A.ino:763
get_voltage
static uint16_t get_voltage(uint8_t selected_dac)
Get voltage from user input, calculate DAC code based on lsb, offset.
Definition: DC2376A.ino:713
LTC2664_write
int8_t LTC2664_write(uint8_t cs, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
Write the 16-bit dac_code to the LTC2664.
Definition: LTC2664.cpp:70
LTC2664_CMD_WRITE_ALL_UPDATE_ALL
#define LTC2664_CMD_WRITE_ALL_UPDATE_ALL
Write to all input reg, update all DACs.
Definition: LTC2664.h:106
menu_7_set_softspan_range
static void menu_7_set_softspan_range(uint8_t selected_dac)
Set SoftSpan Range.
Definition: DC2376A.ino:413
eeprom_data_union::data_struct_type::mux_state
uint8_t mux_state
Multiplexer address AND enable bit.
Definition: DC2692A.ino:170
LTC2664.h
LTC2664: 4-Channel SPI 16-/12-Bit +/-10V Vout SoftSpan DACs with 10ppm/C Max Reference.
LTC2664_CMD_GLOBAL_TOGGLE
#define LTC2664_CMD_GLOBAL_TOGGLE
Software toggle control via global toggle bit.
Definition: LTC2664.h:109
eeprom
eeprom_data_union eeprom
Definition: DC2376A.ino:179
eeprom_data_union::data_struct_type::reference_mode
uint8_t reference_mode
Int.
Definition: DC2692A.ino:171
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
menu_8_toggle_select_word
static void menu_8_toggle_select_word()
Enter toggle select word, which also sets the register that will be written if bit is 0...
Definition: DC2376A.ino:447
QuikEval_EEPROM.h
QuikEval EEPROM Library.
LTC2664_CS
#define LTC2664_CS
Define the SPI CS pin.
Definition: LTC2664.h:90
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
eeprom_data_union
Used to manipulate EEPROM data.
Definition: DC2692A.ino:160
LTC2664_CMD_SPAN
#define LTC2664_CMD_SPAN
Write span to dac n.
Definition: LTC2664.h:102
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
LTC2664_voltage_to_code
uint16_t LTC2664_voltage_to_code(float dac_voltage, float min_output, float max_output)
Calculate a LTC2664 DAC code given the desired output voltage and DAC address (0-3) ...
Definition: LTC2664.cpp:109
eeprom_data_union::data_struct_type::soft_span_range
uint8_t soft_span_range[5]
SoftSpan range.
Definition: DC2692A.ino:165
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
LTC2664_MAX_OUTPUT
const float LTC2664_MAX_OUTPUT[5]
Definition: LTC2664.h:130
setup
static void setup()
Initialize Linduino.
Definition: DC2376A.ino:191
eeprom_data_union::data_struct_type::dac_code_a
uint16_t dac_code_a[16]
DAC Register A.
Definition: DC2692A.ino:166
menu_12_voltage_ramp
static void menu_12_voltage_ramp()
Sets a voltage ramp to all the channels.
Definition: DC2376A.ino:542
LTC2664_CMD_WRITE_ALL
#define LTC2664_CMD_WRITE_ALL
Write to all input registers.
Definition: LTC2664.h:104
menu_10_global_toggle_settings
static void menu_10_global_toggle_settings()
Enable / Disable the global toggle bit.
Definition: DC2376A.ino:495
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
REF_INTERNAL
#define REF_INTERNAL
Internal mode.
Definition: DC2376A.ino:133
menu_1_select_dac
static void menu_1_select_dac(uint8_t *selected_dac)
Select which DAC to operate on.
Definition: DC2376A.ino:280
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
LTC2664_CMD_WRITE_N
#define LTC2664_CMD_WRITE_N
Write to input register n.
Definition: LTC2664.h:95
UserInterface.h
read_int
int32_t read_int()
Definition: UserInterface.cpp:93
LTC2664_CMD_MUX
#define LTC2664_CMD_MUX
Select MUX channel (controlled by 5 LSbs in data word)
Definition: LTC2664.h:107
menu_9_set_mux
static void menu_9_set_mux()
Enable / Disable and sets the channel for the MUX.
Definition: DC2376A.ino:465
LTC2664_CMD_UPDATE_N
#define LTC2664_CMD_UPDATE_N
Update (power up) DAC register n.
Definition: LTC2664.h:96
print_title
static void print_title()
Prints the title block when program first starts.
Definition: DC2376A.ino:748
LTC2664_SPAN_0_TO_5V
#define LTC2664_SPAN_0_TO_5V
Definition: LTC2664.h:119
menu_13_demo_board_test
static void menu_13_demo_board_test()
Definition: DC2376A.ino:554
read_float
float read_float()
Definition: UserInterface.cpp:78
LTC2664_SPAN_0_TO_10V
#define LTC2664_SPAN_0_TO_10V
Definition: LTC2664.h:120
eeprom_data_union::byte_array
char byte_array[sizeof(data_struct_type)]
Array used to store the structure.
Definition: DC2692A.ino:174
eeprom_data_union::data_struct_type::dac_code_b
uint16_t dac_code_b[16]
DAC Register B.
Definition: DC2692A.ino:167
LTC2664_MUX_ENABLE
#define LTC2664_MUX_ENABLE
Definition: LTC2664.h:144
PROMPT_VOLTAGE
0
Definition: DC2376A.ino:186
menu_3_write_and_update_dac
static void menu_3_write_and_update_dac(uint8_t selected_dac)
Write data to DAC register (which updates output immediately)
Definition: DC2376A.ino:329
LTC2664_CMD_TOGGLE_SEL
#define LTC2664_CMD_TOGGLE_SEL
Select which DACs can be toggled (via toggle pin or global toggle bit)
Definition: LTC2664.h:108
eeprom_data_union::data_struct_type::global_toggle_bit
uint8_t global_toggle_bit
Global toggle bit.
Definition: DC2692A.ino:169
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
restore_dac_from_eeprom
static void restore_dac_from_eeprom()
Read the alert settings from EEPROM.
Definition: DC2376A.ino:807
menu_11_enable_disable_eeprom_restore
static void menu_11_enable_disable_eeprom_restore()
Enable / Disable restoration of DAC values from EEPROM Use with caution - behaviour is undefined if y...
Definition: DC2376A.ino:515
i
static int i
Definition: DC2430A.ino:184
LTC2664_CMD_POWER_DOWN_ALL
#define LTC2664_CMD_POWER_DOWN_ALL
Power down chip (all DAC&#39;s, MUX and reference)
Definition: LTC2664.h:100
eeprom_data_union::data_struct
struct eeprom_data_union::data_struct_type data_struct
Name of structure.
prompt_voltage_or_code
static int16_t prompt_voltage_or_code(uint8_t selected_dac)
Prompt user to enter a voltage or digital code to send to DAC.
Definition: DC2376A.ino:680
demo_board_connected
static uint8_t demo_board_connected
Set to 1 if the board is connected.
Definition: DC2376A.ino:159
menu_2_write_to_input_register
static void menu_2_write_to_input_register(uint8_t selected_dac)
Write data to input register, but do not update DAC output.
Definition: DC2376A.ino:292
get_code
static uint16_t get_code()
Get code to send to DAC directly, in decimal, hex, or binary.
Definition: DC2376A.ino:735
EEPROM_CAL_KEY
#define EEPROM_CAL_KEY
Definition: QuikEval_EEPROM.h:59
read_quikeval_id_string
uint8_t read_quikeval_id_string(char *buffer)
Read the id string from the EEPROM, then parse the product name, demo board name, and demo board opti...
Definition: QuikEval_EEPROM.cpp:77
menu_4_update_power_up_dac
static void menu_4_update_power_up_dac(uint8_t selected_dac)
Update DAC with data that is stored in input register, power up if sleeping.
Definition: DC2376A.ino:367
ui_buffer
char ui_buffer[UI_BUFFER_SIZE]
Definition: UserInterface.cpp:46