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();
204  {
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:
242  break;
243  case 7:
244  menu_7_set_softspan_range(selected_dac);
245  break;
246  case 8:
248  break;
249  case 9:
250  menu_9_set_mux();
251  break;
252  case 10:
254  break;
255  case 11:
257  break;
258  case 12:
260  break;
261  case 13:
263  break;
264  case 14:
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)
372  else
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)
382  else
384 }
385 
386 //! Set reference mode
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  {
402  Serial.println(F("Internal reference has been powered up"));
403  }
404  else
405  {
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 
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.
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 
461  Serial.println(eeprom.data_struct.toggle_word, BIN);
462 }
463 
464 //! Enable / Disable and sets the channel for the 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);
486  }
487  else
488  {
491  Serial.println(F("The MUX has been disabled"));
492  }
493 }
494 //! Enable / Disable the global toggle bit
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 
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.
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"));
528  break;
529  case 1:
530  Serial.println(F("Disabling EEPROM restoration"));
531  eeprom.data_struct.cal_key = 0;
533  break;
534  case 2:
537  Serial.println(F("Stored Settings to EEPROM"));
538  }
539 }
540 
541 //! Sets a voltage ramp to all the channels
543 {
544  uint8_t i;
545  for (i=0; i <= 3; ++i)
546  {
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.
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 
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 
593 
594  for (i=0; i <= 3; ++i)
595  {
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 
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 
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();
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."));
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."));
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."));
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."));
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.
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  {
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,
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.
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
808 {
809  int16_t cal_key;
810  int8_t i;
811 
812  // Read the cal key from the EEPROM
814 
815  if (cal_key == EEPROM_CAL_KEY)
816  {
817  // Calibration has been stored, read thresholds
819 
820  // Write SoftSpan ranges
821  for (uint8_t i = 0; i <= 3; i++)
823 
824  // Write stored data to DAC A registers
825  for (uint8_t i = 0; i <= 3 ; 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++)
833 
835 
837 
839 
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 }
struct demo_board_type demo_board
Instantiate demo board structure.
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.
#define LTC2664_CMD_WRITE_N_UPDATE_N
Write to input register n, update (power-up)
Definition: LTC2664.h:98
static void menu_5_power_down_dac(uint8_t selected_dac)
Power down DAC.
Definition: DC2376A.ino:377
char option
Demo Circuit option (A)
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
const float LTC2664_MIN_OUTPUT[5]
Definition: LTC2664.h:129
#define REF_EXTERNAL
External mode.
Definition: DC2376A.ino:132
uint16_t toggle_word
Toggle control word.
Definition: DC2692A.ino:168
#define LTC2664_CMD_SPAN_ALL
Set span for all DACs.
Definition: LTC2664.h:110
int16_t cal_key
The key that keeps track of the calibration.
Definition: DC2692A.ino:164
#define LTC2664_CMD_NO_OPERATION
No operation.
Definition: LTC2664.h:111
static void menu_6_set_reference_mode()
Set reference mode.
Definition: DC2376A.ino:387
#define LTC2664_CMD_POWER_DOWN_N
Power down n.
Definition: LTC2664.h:99
#define LTC2664_CMD_CONFIG
Configure reference / toggle.
Definition: LTC2664.h:103
Header File for Linduino Libraries and Demo Code.
#define LTC2664_CMD_UPDATE_ALL
Update all DACs.
Definition: LTC2664.h:105
#define LTC2664_SPAN_PLUS_MINUS_10V
Definition: LTC2664.h:122
static void loop()
Repeats Linduino loop.
Definition: DC2376A.ino:211
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.
static void menu_14_loopback_test()
Definition: DC2376A.ino:657
static void print_prompt(int8_t selected_dac)
Prints main menu.
Definition: DC2376A.ino:763
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
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
#define LTC2664_CMD_WRITE_ALL_UPDATE_ALL
Write to all input reg, update all DACs.
Definition: LTC2664.h:106
static void menu_7_set_softspan_range(uint8_t selected_dac)
Set SoftSpan Range.
Definition: DC2376A.ino:413
uint8_t mux_state
Multiplexer address AND enable bit.
Definition: DC2692A.ino:170
LTC2664: 4-Channel SPI 16-/12-Bit +/-10V Vout SoftSpan DACs with 10ppm/C Max Reference.
#define LTC2664_CMD_GLOBAL_TOGGLE
Software toggle control via global toggle bit.
Definition: LTC2664.h:109
eeprom_data_union eeprom
Definition: DC2376A.ino:179
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.
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 Library.
#define LTC2664_CS
Define the SPI CS pin.
Definition: LTC2664.h:90
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
Used to manipulate EEPROM data.
Definition: DC2692A.ino:160
#define LTC2664_CMD_SPAN
Write span to dac n.
Definition: LTC2664.h:102
#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.
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
uint8_t soft_span_range[5]
SoftSpan range.
Definition: DC2692A.ino:165
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
const float LTC2664_MAX_OUTPUT[5]
Definition: LTC2664.h:130
static void setup()
Initialize Linduino.
Definition: DC2376A.ino:191
uint16_t dac_code_a[16]
DAC Register A.
Definition: DC2692A.ino:166
static void menu_12_voltage_ramp()
Sets a voltage ramp to all the channels.
Definition: DC2376A.ino:542
#define LTC2664_CMD_WRITE_ALL
Write to all input registers.
Definition: LTC2664.h:104
static void menu_10_global_toggle_settings()
Enable / Disable the global toggle bit.
Definition: DC2376A.ino:495
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
#define REF_INTERNAL
Internal mode.
Definition: DC2376A.ino:133
static void menu_1_select_dac(uint8_t *selected_dac)
Select which DAC to operate on.
Definition: DC2376A.ino:280
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
#define LTC2664_CMD_WRITE_N
Write to input register n.
Definition: LTC2664.h:95
int32_t read_int()
#define LTC2664_CMD_MUX
Select MUX channel (controlled by 5 LSbs in data word)
Definition: LTC2664.h:107
static void menu_9_set_mux()
Enable / Disable and sets the channel for the MUX.
Definition: DC2376A.ino:465
#define LTC2664_CMD_UPDATE_N
Update (power up) DAC register n.
Definition: LTC2664.h:96
static void print_title()
Prints the title block when program first starts.
Definition: DC2376A.ino:748
#define LTC2664_SPAN_0_TO_5V
Definition: LTC2664.h:119
static void menu_13_demo_board_test()
Definition: DC2376A.ino:554
float read_float()
#define LTC2664_SPAN_0_TO_10V
Definition: LTC2664.h:120
char byte_array[sizeof(data_struct_type)]
Array used to store the structure.
Definition: DC2692A.ino:174
uint16_t dac_code_b[16]
DAC Register B.
Definition: DC2692A.ino:167
#define LTC2664_MUX_ENABLE
Definition: LTC2664.h:144
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
#define LTC2664_CMD_TOGGLE_SEL
Select which DACs can be toggled (via toggle pin or global toggle bit)
Definition: LTC2664.h:108
uint8_t global_toggle_bit
Global toggle bit.
Definition: DC2692A.ino:169
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
static void restore_dac_from_eeprom()
Read the alert settings from EEPROM.
Definition: DC2376A.ino:807
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
static int i
Definition: DC2430A.ino:184
#define LTC2664_CMD_POWER_DOWN_ALL
Power down chip (all DAC&#39;s, MUX and reference)
Definition: LTC2664.h:100
struct eeprom_data_union::data_struct_type data_struct
Name of structure.
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
static uint8_t demo_board_connected
Set to 1 if the board is connected.
Definition: DC2376A.ino:159
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
static uint16_t get_code()
Get code to send to DAC directly, in decimal, hex, or binary.
Definition: DC2376A.ino:735
#define EEPROM_CAL_KEY
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...
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
char ui_buffer[UI_BUFFER_SIZE]