Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC2025A.ino
Go to the documentation of this file.
1 /*!
2 Linear Technology DC2025A Demonstration Board.
3 LTC2668: 16 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 sixteen DACs to test : 0 to 15
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 shutdown 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 th store
62  setting EEPROM menu and select it. Upon Linduinos 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/LTC2668
78 
79 http://www.linear.com/product/LTC2668#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 LTC2668
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 "LTC2668.h"
126 #include <SPI.h>
127 #include <Wire.h>
128 #include "USE_WIRE.h"
129 
130 #ifdef USEWIRE
131 #include "LT_I2C_Wire.h"
132 #include "QuikEval_EEPROM_Wire.h"
133 #else
134 #include "LT_I2C.h"
135 #include "QuikEval_EEPROM.h"
136 #endif
137 
138 // Macros
139 #define REF_EXTERNAL LTC2668_REF_DISABLE //!< External mode
140 #define REF_INTERNAL 0 //!< Internal mode
141 
142 // Function Declaration
143 
144 void restore_dac_from_eeprom(); // Restores DAC settings from EEPROM
145 void print_title(); // Print the title block
146 void print_prompt(int8_t selected_dac); // Prompt the user for an input command
147 int16_t prompt_voltage_or_code(uint8_t selected_dac); // Prompt the user for voltage or code
148 uint16_t get_voltage(uint8_t selected_dac); // Obtains voltage from user
149 uint16_t get_code(); // Obtains code from user
150 
151 void menu_1_select_dac(uint8_t *selected_dac); // Menu 1: prompts user for DAC selection
152 void menu_2_write_to_input_register(uint8_t selected_dac); // Menu 2: sends data to selected DAC register with no update
153 void menu_3_write_and_update_dac(uint8_t selected_dac); // Menu 3: sends data to selected DAC register with update
154 void menu_4_update_power_up_dac(uint8_t selected_dac); // Menu 4: updates and powers up selected DAC
155 void menu_5_power_down_dac(uint8_t selected_dac); // Menu 5: powers down selected DAC
156 void menu_6_set_reference_mode(); // Menu 6: prompts user to enable/disable internal reference
157 void menu_7_set_softspan_range(uint8_t selected_dac); // Menu 7: prompts user to sets the SoftSpan range
158 void menu_8_toggle_select_word(); // Menu 8: prompts user to enter the toggle select word
159 void menu_9_set_mux(); // Menu 9: sets MEX
160 void menu_10_global_toggle_settings(); // Menu 10: sets the global toggle bit
161 void menu_11_enable_disable_eeprom_restore(); // Menu 11: EEPOM restore settings
162 void menu_12_voltage_ramp(); // Menu 12: sets a voltage ramp for the LTC2668
163 void menu_13_settling_test(); // Menu 13: Settling time test
164 void menu_14_demo_board_test(); // Menu 14: Demo Board functional test
165 void menu_15_loopback_test();
166 
167 // Global variable
168 static uint8_t demo_board_connected; //!< Set to 1 if the board is connected
169 
170 //! Used to manipulate EEPROM data.
171 union eeprom_data_union
172 {
173  struct data_struct_type //! EEPROM data structure
174  {
175  int16_t cal_key; //!< The key that keeps track of the calibration
176  uint8_t soft_span_range[16]; //!< SoftSpan range
177  uint16_t dac_code_a[16]; //!< DAC Register A
178  uint16_t dac_code_b[16]; //!< DAC Register B
179  uint16_t toggle_word; //!< Toggle control word
180  uint8_t global_toggle_bit; //!< Global toggle bit
181  uint8_t mux_state; //!< Multiplexer address AND enable bit
182  uint8_t reference_mode; //!< Int. reference may be disabled in external reference mode (not required)
183  } data_struct; //!< Name of structure
184 
185  char byte_array[sizeof(data_struct_type)]; //!< Array used to store the structure
186 };
187 
188 eeprom_data_union eeprom; // Create union
189 
190 // Constants
191 
192 //! Used to keep track to print voltage or print code
193 enum
194 {
195  PROMPT_VOLTAGE = 0, /**< 0 */
196  PROMPT_CODE = 1 /**< 1 */
197 };
198 
199 //! Initialize Linduino
200 void setup()
201 // Setup the program
202 {
203  char demo_name[] = "DC2025"; // Demo Board Name stored in QuikEval EEPROM
204 
205  quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
206  quikeval_SPI_connect(); // Connect SPI to main data port
207  quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz
208 
209  Serial.begin(115200); // Initialize the serial port to the PC
210  print_title();
213  {
215  print_prompt(0);
216  }
217 }
218 
219 //! Repeats Linduino loop
220 void loop()
221 {
222  int16_t user_command;
223  static uint8_t selected_dac = 0; // The selected DAC to be updated (0=CH0, 1=CH1 ... 16=All). Initialized to CH0.
224 
225  if (Serial.available()) // Check for user input
226  {
227  user_command = read_int(); // Read the user command
228  Serial.println(user_command);
229  Serial.print(F("\n"));
230  Serial.flush();
231  switch (user_command)
232  {
233  case 1:
234  menu_1_select_dac(&selected_dac);
235  break;
236  case 2:
237  menu_2_write_to_input_register(selected_dac);
238  break;
239  case 3:
240  menu_3_write_and_update_dac(selected_dac);
241  break;
242  case 4:
243  menu_4_update_power_up_dac(selected_dac);
244  break;
245  case 5:
246  menu_5_power_down_dac(selected_dac);
247  break;
248  case 6:
250  break;
251  case 7:
252  menu_7_set_softspan_range(selected_dac);
253  break;
254  case 8:
256  break;
257  case 9:
258  menu_9_set_mux();
259  break;
260  case 10:
262  break;
263  case 11:
265  break;
266  case 12:
268  break;
269  case 13:
271  break;
272  case 14:
274  break;
275  case 15:
277  break;
278  default:
279  Serial.println(F("Incorrect Option"));
280  break;
281  }
282  Serial.println(F("\n************************************************************"));
283  print_prompt(selected_dac);
284  }
285 
286 }
287 
288 // Function Definitions
289 
290 //! Select which DAC to operate on
291 void menu_1_select_dac(uint8_t *selected_dac)
292 {
293  // Select a DAC to operate on
294  Serial.print(F("Select DAC to operate on (0 to 15, 16 for ALL DACs)"));
295  *selected_dac = read_int();
296  if (*selected_dac == 16)
297  Serial.println(F("All"));
298  else
299  Serial.println(*selected_dac);
300 }
301 
302 //! Write data to input register, but do not update DAC output
303 void menu_2_write_to_input_register(uint8_t selected_dac)
304 {
305  uint16_t dac_code;
306 
307  if (prompt_voltage_or_code(selected_dac) == PROMPT_VOLTAGE)
308  dac_code = get_voltage(selected_dac);
309  else
310  dac_code = get_code();
311 
312  if (selected_dac <= 15)
313  {
314  // Store dac_code to register variable a or b
315  if (eeprom.data_struct.toggle_word & (0x01 << selected_dac))
316  {
317  eeprom.data_struct.dac_code_b[selected_dac] = dac_code;
318  }
319  else
320  eeprom.data_struct.dac_code_a[selected_dac] = dac_code;
321  LTC2668_write(LTC2668_CS, LTC2668_CMD_WRITE_N, selected_dac, dac_code);
322  }
323  else
324  {
325  // Store dac_code to register variable a or b
326  for (uint8_t i = 0; i <= 15 ; i++)
327  {
328  if (eeprom.data_struct.toggle_word & (0x01 << i))
329  {
330  eeprom.data_struct.dac_code_b[i] = dac_code;
331  }
332  else
333  eeprom.data_struct.dac_code_a[i] = dac_code;
334  }
335  LTC2668_write(LTC2668_CS, LTC2668_CMD_WRITE_ALL, selected_dac, dac_code);
336  }
337 }
338 
339 //! Write data to DAC register (which updates output immediately)
340 void menu_3_write_and_update_dac(uint8_t selected_dac)
341 {
342  uint16_t dac_code;
343 
344  if (prompt_voltage_or_code(selected_dac) == PROMPT_VOLTAGE)
345  dac_code = get_voltage(selected_dac);
346  else
347  dac_code = get_code();
348 
349  if (selected_dac <= 15)
350  {
351  // Store dac_code to register variable a or b
352  if (eeprom.data_struct.toggle_word & (0x01 << selected_dac))
353  {
354  eeprom.data_struct.dac_code_b[selected_dac] = dac_code;
355  }
356  else
357  eeprom.data_struct.dac_code_a[selected_dac] = dac_code;
358 
359  LTC2668_write(LTC2668_CS,LTC2668_CMD_WRITE_N_UPDATE_N, selected_dac, dac_code); // Send dac_code
360  }
361  else // All DACs
362  {
363  // Store dac_code to register variable a or b
364  for (uint8_t i = 0; i <= 15 ; i++)
365  {
366  if (eeprom.data_struct.toggle_word & (0x01 << i))
367  {
368  eeprom.data_struct.dac_code_b[i] = dac_code;
369  }
370  else
371  eeprom.data_struct.dac_code_a[i] = dac_code;
372  }
373  LTC2668_write(LTC2668_CS,LTC2668_CMD_WRITE_ALL_UPDATE_ALL, 0, dac_code); // Send dac_code
374  }
375 }
376 
377 //! Update DAC with data that is stored in input register, power up if sleeping
378 void menu_4_update_power_up_dac(uint8_t selected_dac)
379 {
380  // Update DAC
381  if (selected_dac <= 15)
383  else
385 }
386 
387 //! Power down DAC
388 void menu_5_power_down_dac(uint8_t selected_dac)
389 {
390  // Power down DAC
391  if (selected_dac <= 15)
393  else
395 }
396 
397 //! Set reference mode
399 {
400  int16_t user_command;
401  Serial.println(F("0 - Power down the internal reference"));
402  Serial.println(F("1 - Power up the internal reference"));
403  user_command = read_int();
404  if (user_command > 1)
405  user_command = 1;
406  if (user_command < 0)
407  user_command = 0;
408 
409  if (user_command == 1)
410  {
413  Serial.println(F("Internal reference has been powered up"));
414  }
415  else
416  {
419  Serial.println(F("Internal reference has been powered down"));
420  }
421 }
422 
423 //! Set SoftSpan Range
424 void menu_7_set_softspan_range(uint8_t selected_dac)
425 {
426  int16_t user_command;
427 
428  Serial.println(F("0- 0V to 5V"));
429  Serial.println(F("1- 0V to 10V"));
430  Serial.println(F("2- -5V to 5V"));
431  Serial.println(F("3- -10V to 10V"));
432  Serial.println(F("4- -2.5V to 2.5V"));
433  Serial.print(F("Select a SoftSpan Range: "));
434  user_command = read_int();
435 
436  if (user_command > 4)
437  user_command = 4;
438  if (user_command < 0)
439  user_command = 0;
440  Serial.println(user_command);
441 
442  if (selected_dac <= 15)
443  {
444  eeprom.data_struct.soft_span_range[selected_dac] = user_command;
445  LTC2668_write(LTC2668_CS, LTC2668_CMD_SPAN, selected_dac, eeprom.data_struct.soft_span_range[selected_dac]);
446  }
447  else
448  {
449  for (uint8_t i = 0; 0 <= 15; i++)
450  eeprom.data_struct.soft_span_range[i] = user_command;
451 
453  }
454 }
455 
456 //! Enter toggle select word, which also sets the register that will be written
457 //! if bit is 0, register A is written, if 1, register B is written.
459 {
460  // Select a DAC to operate on
461  Serial.println(F("Toggle Select bit sets the register to be written for the corresponding DAC."));
462  Serial.println(F("0 for Register A or 1 for Register B."));
463  Serial.println(F("Note: DAC Update from Register B requires TGB = 1"));
464  Serial.println(F(" DAC Update from Register A requires TCB = 0"));
465  Serial.print(F("Enter Toggle Select Byte as hex (0xMM) or binary (B10101010): "));
466  eeprom.data_struct.toggle_word = read_int();
467 
469  Serial.println(eeprom.data_struct.toggle_word, BIN);
470 }
471 
472 //! Enable / Disable and sets the channel for the MUX
474 {
475  int16_t user_command;
476  Serial.println(F("0- Disable Mux"));
477  Serial.println(F("1- Enable Mux"));
478  Serial.print(F("Enter a command: "));
479  user_command = read_int();
480 
481  if (user_command == 1)
482  {
483  Serial.print(F("Select MUX channel(0-CH0, 1-CH1,...15-CH15 : "));
484  user_command = read_int();
485 
486  if (user_command > 15)
487  user_command = 15;
488  if (user_command < 0);
489  user_command = 0;
490 
491  Serial.println(user_command);
494  }
495  else
496  {
499  Serial.println(F("The MUX has been disabled"));
500  }
501 }
502 //! Enable / Disable the global toggle bit
504 {
505  int16_t user_command;
506  Serial.println(F("0- Disable Global Toggle"));
507  Serial.println(F("1- Enable Global Toggle"));
508  Serial.print(F("Enter a command: "));
509  user_command = read_int();
510 
511  if (user_command > 1)
512  user_command = 1;
513  if (user_command < 0)
514  user_command = 0;
515  Serial.println(user_command);
516 
519 }
520 
521 //! Enable / Disable restoration of DAC values from EEPROM Use with caution - behaviour is undefined if you
522 //! enable restoration and data has NOT been previously stored from a known state.
524 {
525  int16_t user_input;
526  Serial.println(F("\n0- Enable Restoration"));
527  Serial.println(F("1- Disable Restoration"));
528  Serial.println(F("2- Store DAC Settings"));
529  user_input = read_int();
530  switch (user_input)
531  {
532  case 0:
533  Serial.println(F("Enabling EEPROM restoration"));
536  break;
537  case 1:
538  Serial.println(F("Disabling EEPROM restoration"));
539  eeprom.data_struct.cal_key = 0;
541  break;
542  case 2:
545  Serial.println(F("Stored Settings to EEPROM"));
546  }
547 }
548 
549 //! Sets a voltage ramp to all the channels
551 {
552  uint8_t i;
553  for (i=0; i <= 15; ++i)
554  {
556  }
557  Serial.println("A voltage ramp was set to the LTC2668");
558 }
559 
560 ///////////////////////////////////////////////////////////////////////////
561 // The following functions are used internally for testing, and included //
562 // here for reference. //
563 ///////////////////////////////////////////////////////////////////////////
564 
565 // Settling time routine, used for datasheet pictures. Set scope to ARM trigger on SETTLE_TRIGGER
566 // Rising edge, trigger on CS pin for the actual edge that causes the update.
567 // You can test any other channel / starting / final values by setting up the DAC's
568 // register A to the initial (starting) voltage and register B to the final (settled) voltage.
569 // The channel's toggle bit must be set as well.
570 
571 #define INTEGRATOR_CONTROL 2 // Pin to control integrator on settling time circuit
572 // Set low for 100ms after full settling has occurred,
573 // high to run test.
574 #define SETTLE_TRIGGER 3 // High to low edge close to DAC active edge. Can also be
575 // used to drive DAC simulator.
576 #define SETTLE_CHANNEL 0 // Which DAC to test for settling (only one at a time to prevent
577 // crosstalk artefacts.)
579 {
580 /* int16_t user_input, initial, final;
581  int8_t range;
582  Serial.println(F("Select test to run:"));
583  Serial.println(F("0: presently programmed DAC values"));
584  Serial.println(F("1: 0-5 rising"));
585  Serial.println(F("2: 0-5 falling"));
586  Serial.println(F("3: 0-10 rising"));
587  Serial.println(F("4: 0-10 falling"));
588  Serial.println(F("5: bipolar 10 rising"));
589  Serial.println(F("6: bipolar 10 falling"));
590  Serial.println(F("7: 0-5 1/4 to 3/4 scale, rising"));
591  Serial.println(F("8: 0-5 3/4 to 1/4 scale, falling"));
592  Serial.println(F("9: bipolar 5 rising"));
593  Serial.println(F("10: bipolar 5 falling"));
594  Serial.println(F("11: bipolar 2.5 rising"));
595  Serial.println(F("12: bipolar 2.5 falling"));
596 
597  Serial.flush();
598  user_input = read_int();
599  switch (user_input)
600  {
601  case 1:
602  initial = 0x0000;
603  final = 0xFFFF;
604  range = LTC2668_SPAN_0_TO_5V;
605  break;
606  case 2:
607  initial = 0xFFFF;
608  final = 0x0000;
609  range = LTC2668_SPAN_0_TO_5V;
610  break;
611  case 3:
612  initial = 0x0000;
613  final = 0xFFFF;
614  range = LTC2668_SPAN_0_TO_10V;
615  break;
616  case 4:
617  initial = 0xFFFF;
618  final = 0x0000;
619  range = LTC2668_SPAN_0_TO_10V;
620  break;
621  case 5:
622  initial = 0x0000;
623  final = 0xFFFF;
624  range = LTC2668_SPAN_PLUS_MINUS_10V;
625  break;
626  case 6:
627  initial = 0xFFFF;
628  final = 0x0000;
629  range = LTC2668_SPAN_PLUS_MINUS_10V;
630  break;
631  case 7:
632  initial = 0x4000;
633  final = 0xC000;
634  range = LTC2668_SPAN_0_TO_5V;
635  break;
636  case 8:
637  initial = 0xC000;
638  final = 0x4000;
639  range = LTC2668_SPAN_0_TO_5V;
640  break;
641  case 9:
642  initial = 0x0000;
643  final = 0xFFFF;
644  range = LTC2668_SPAN_PLUS_MINUS_5V;
645  break;
646  case 10:
647  initial = 0xFFFF;
648  final = 0x0000;
649  range = LTC2668_SPAN_PLUS_MINUS_5V;
650  break;
651  case 11:
652  initial = 0x0000;
653  final = 0xFFFF;
654  range = LTC2668_SPAN_PLUS_MINUS_2V5;
655  break;
656  case 12:
657  initial = 0xFFFF;
658  final = 0x0000;
659  range = LTC2668_SPAN_PLUS_MINUS_2V5;
660  break;
661  default:
662  Serial.println("Using presently programmed DAC values");
663  }
664  if (user_input != 0) // Load DAC to be tested with range, initial, and final values.
665  {
666  LTC2668_write(LTC2668_CS, LTC2668_CMD_SPAN, SETTLE_CHANNEL, range); // Set Span
667  LTC2668_write(LTC2668_CS, LTC2668_CMD_TOGGLE_SEL, 0, 0x0000); // Point to register A
668  LTC2668_write(LTC2668_CS, LTC2668_CMD_WRITE_N_UPDATE_N, SETTLE_CHANNEL, initial); // Send dac_code
669  LTC2668_write(LTC2668_CS, LTC2668_CMD_TOGGLE_SEL, 0, 0x0001 << SETTLE_CHANNEL); // Point to register B
670  LTC2668_write(LTC2668_CS, LTC2668_CMD_WRITE_N_UPDATE_N, SETTLE_CHANNEL, final); // Send dac_code
671  }
672  Serial.println("Settling time test running, send any character to terminate.");
673  pinMode(INTEGRATOR_CONTROL, OUTPUT);
674  pinMode(SETTLE_TRIGGER, OUTPUT);
675  while (!Serial.available())
676  {
677  PORTD |= 1 << INTEGRATOR_CONTROL; // Disable integrator
678  PORTD |= 1 << SETTLE_TRIGGER;
679  LTC2668_write(LTC2668_CS, LTC2668_CMD_GLOBAL_TOGGLE, 0, 0); // Set global toggle bit LOW, INITIAL value
680  PORTD &= ~(1 << SETTLE_TRIGGER); // Reset settle trigger LOW
681  delay(10); // Wait to get to initial value
682  LTC2668_write(LTC2668_CS, LTC2668_CMD_GLOBAL_TOGGLE, 0, 1); // Set global toggle HIGH, FINAL value
683  delay(10); // Wait to get to final value, here is where you look at the settling
684  PORTD &= ~(1 << INTEGRATOR_CONTROL); // Enable integrator
685  delay(100);
686  }
687  Serial.read();
688  Serial.println("Exiting Settling time test.");
689  */
690 }
691 // Functional test for demo board, tests continuity, EEPROM contents,
692 // And correct resolution DAC installed.
694 {
695  uint8_t i, errorcount = 0;
696 
697  Serial.println(F("Welcome to the LTC2668 Demo Board Test Program."));
698  Serial.print(F("Found board assembly type "));
699  Serial.println(demo_board.option);
700 
701  Serial.println(F("Checking EEPROM contents..."));
702 
704  ui_buffer[48] = 0;
705  Serial.println(ui_buffer);
706  switch (demo_board.option)
707  {
708  case 'A':
709  if (strcmp("LTC2668-16,Cls,D2668,01,01,DC,DC2025A-A,--------", ui_buffer))
710  {
711  Serial.println(F("FAILED EEPROM Contents"));
712  errorcount += 1;
713  }
714  break;
715  case 'B':
716  if (strcmp("LTC2668-12,Cls,D2668,01,01,DC,DC2025A-B,--------", ui_buffer))
717  {
718  Serial.println(F("FAILED EEPROM Contents"));
719  errorcount += 1;
720  }
721  break;
722  }
723  // LTC2668-16,Cls,D2668,01,01,DC,DC2025A-A,--------
724  if (!errorcount)
725  Serial.println(F("EEPROM good!"));
726 
727  Serial.println(F("Ensure all jumpers are in the LEFT position (INT ref, MSP0,1,2 = 1."));
728  Serial.println(F("Writing ramp of voltages to DAC outputs. Verify DAC0 = 0.10V, DAC1 = 0.20V,"));
729  Serial.println(F("DAC2 = 0.3V ... DAC15 = 1.60V. Type 1, enter when done."));
730 
732 
733  for (i=0; i <= 15; ++i)
734  {
737  }
738 
739  read_int(); // Read the user command
740 
741  Serial.println(F("Setting SoftSpan range to +/-10V, DAC15 to -10V, and MUX to DAC15."));
742  Serial.println(F("Verify MUX output is between -9.95V and -10.05V"));
743 
747 
748  Serial.println(F("Type 1, enter when done."));
749  read_int();
750 
753  Serial.println(F("Verifying correct resolution LTC2668 installed"));
754  Serial.println(F("output set to 0V, press REL(delta) button on meter"));
755  Serial.println(F("Type 1, enter when done."));
756  read_int();
758 
759  switch (demo_board.option)
760  {
761  case 'A':
762  Serial.println(F("16 bit device - verify output voltage is GREATER than 1mV"));
763  break;
764  case 'B':
765  Serial.println(F("12 bit device - verify output voltage is LESS than 1mV"));
766  break;
767  }
768  Serial.println(F("Type 1, enter when done."));
769  read_int();
770 }
771 
772 // Loopback test to verify data integrity.
774 {
775  uint16_t i;
776  int8_t ack = 0;
777  Serial.print(F("Testing readback by writing 0-10,000, NOP commands\n"));
778  LTC2668_write(LTC2668_CS, LTC2668_CMD_NO_OPERATION, 0, 0); // If this is the first time the read function is called, need to initialize
779  for (i=0; i<=10000; ++i)
780  {
782  }
783  if (ack)
784  {
785  Serial.print(F("Oops, got an error somewhere!"));
786  }
787  else
788  {
789  Serial.print(F("No errors!!"));
790  }
791 }
792 
793 
794 //! Prompt user to enter a voltage or digital code to send to DAC
795 //! @returns user input
796 int16_t prompt_voltage_or_code(uint8_t selected_dac )
797 {
798  int16_t user_input;
799 
800  Serial.print(F("Type 1 to enter voltage, 2 to enter code: "));
801  Serial.flush();
802  user_input = read_int();
803  Serial.println(user_input);
804 
805  if (user_input != 2)
806  {
807  if (selected_dac >= 16)
808  {
809  Serial.println(F("\nCaution! Voltage SoftSpan could be different for different DACs"));
810  Serial.println(F("Ensure All DACs can be set to desired voltages"));
811  Serial.println(F("DAC 0 is used for SoftSpan values for all DACs."));
812  Serial.print(F("Toggle Register Select Bits 0=A, 1 = B: 0b"));
813  Serial.println(eeprom.data_struct.toggle_word, BIN);
814  }
815  return(PROMPT_VOLTAGE);
816  }
817  else
818  {
819  if (selected_dac >= 16)
820  {
821  Serial.println(F("DAC 0 is used for SoftSpan values for all DACs."));
822  }
823  }
824  return(PROMPT_CODE);
825 }
826 
827 //! Get voltage from user input, calculate DAC code based on lsb, offset
828 //! @returns the DAC code
829 uint16_t get_voltage(uint8_t selected_dac)
830 {
831  float dac_voltage;
832 
833  Serial.print(F("Enter Desired DAC output voltage: "));
834  dac_voltage = read_float();
835  Serial.print(dac_voltage);
836  Serial.println(F(" V"));
837  Serial.flush();
838 
839  if (selected_dac <= 15)
840  return(LTC2668_voltage_to_code(dac_voltage,
841  LTC2668_MIN_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]],
842  LTC2668_MAX_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]]));
843  else
844  return(LTC2668_voltage_to_code(dac_voltage,
847 }
848 
849 //! Get code to send to DAC directly, in decimal, hex, or binary
850 //! @return code from user
851 uint16_t get_code()
852 {
853  uint16_t returncode;
854  Serial.println(F("Enter Desired DAC Code"));
855  Serial.print(F("(Format 32768, 0x8000, 0100000, or B1000000000000000): "));
856  returncode = (uint16_t) read_int();
857  Serial.print(F("0x"));
858  Serial.println(returncode, HEX);
859  Serial.flush();
860  return(returncode);
861 }
862 
863 //! Prints the title block when program first starts.
865 {
866  Serial.println();
867  Serial.println(F("*****************************************************************"));
868  Serial.println(F("* DC2025 Demonstration Program *"));
869  Serial.println(F("* *"));
870  Serial.println(F("* This program demonstrates how to send data to the LTC2668 *"));
871  Serial.println(F("* Sixteen Channel 16/12-bit DAC found on the DC2025 demo board. *"));
872  Serial.println(F("* *"));
873  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
874  Serial.println(F("* *"));
875  Serial.println(F("*****************************************************************"));
876 }
877 
878 //! Prints main menu.
879 void print_prompt(int8_t selected_dac)
880 {
881  // Displays menu
882  Serial.println(F("\nCommand Summary:"));
883  Serial.println(F(" 1-Select DAC"));
884  Serial.println(F(" 2-Write to input register (no update)"));
885  Serial.println(F(" 3-Write and update DAC"));
886  Serial.println(F(" 4-Update / power up DAC"));
887  Serial.println(F(" 5-Power down DAC"));
888  Serial.println(F(" 6-Set reference mode"));
889  Serial.println(F(" 7-Set SoftSpan"));
890  Serial.println(F(" 8-Toggle selected register"));
891  Serial.println(F(" 9-Set Mux"));
892  Serial.println(F(" 10-Global toggle bit settings"));
893  Serial.println(F(" 11-Enable, disable, or store to EEPROM"));
894  Serial.println(F(" 12-Voltage Ramp"));
895  Serial.println(F("\nPresent Values:"));
896  Serial.print(F(" Selected DAC: "));
897 
898  // Display current settings
899  if (selected_dac >= 15 )
900  {
901  Serial.println(F("All"));
902  Serial.print(F(" SoftSpan range: "));
903  Serial.print(LTC2668_MIN_OUTPUT[eeprom.data_struct.soft_span_range[0]], 4);
904  Serial.print(F(" V to "));
905  Serial.print(LTC2668_MAX_OUTPUT[eeprom.data_struct.soft_span_range[0]], 4);
906  Serial.println(F(" V"));
907  }
908  else
909  {
910  Serial.println(selected_dac);
911  Serial.print(F(" SoftSpan range: "));
912  Serial.print(LTC2668_MIN_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]], 4);
913  Serial.print(F(" V to "));
914  Serial.print(LTC2668_MAX_OUTPUT[eeprom.data_struct.soft_span_range[selected_dac]], 4);
915  Serial.println(F(" V"));
916  }
917  Serial.print(F(" Toggle Register: "));
918  for (uint8_t i = 0; i <= 15; i++)
919  {
920  if ((eeprom.data_struct.toggle_word & (0x8000 >> i)))
921  Serial.print(F("B"));
922  else
923  Serial.print(F("A"));
924  }
925  Serial.println();
926 
927  Serial.print(F(" Global Toggle Bit: "));
928  Serial.println(eeprom.data_struct.global_toggle_bit);
929 
930  Serial.print(F(" Reference: "));
932  Serial.println(F("Internal"));
933  else
934  Serial.println(F("External"));
935 
936  Serial.print(F("\nEnter a command: "));
937  Serial.flush();
938 }
939 
940 //! Read the alert settings from EEPROM
942 {
943  int16_t cal_key;
944  int8_t i;
945 
946  // Read the cal key from the EEPROM
948 
949  if (cal_key == EEPROM_CAL_KEY)
950  {
951  // Calibration has been stored, read thresholds
953 
954  // Write SoftSpan ranges
955  for (uint8_t i = 0; i <= 15; i++)
957 
958  // Write stored data to DAC A registers
959  for (uint8_t i = 0; i <= 15 ; i++)
961 
962  LTC2668_write(LTC2668_CS, LTC2668_CMD_TOGGLE_SEL, 0, 0xFFFF); // Set to B registers
963 
964  // Write stored data to DAC B registers
965  for (uint8_t i = 0; i <= 15 ; i++)
967 
969 
971 
973 
975 
976  LTC2668_write(LTC2668_CS,LTC2668_CMD_UPDATE_ALL, 0, 0); // Update ALL
977 
978  Serial.println(F("DAC settings loaded from EEPROM"));
979  }
980  else
981  Serial.println(F("EEPROM data not found"));
982 }
struct demo_board_type demo_board
Instantiate demo board structure.
#define LTC2668_SPAN_PLUS_MINUS_10V
Definition: LTC2668.h:122
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.
static void menu_15_loopback_test()
Definition: DC2025A.ino:773
#define LTC2668_CMD_CONFIG
Configure reference / toggle.
Definition: LTC2668.h:103
#define LTC2668_CMD_SPAN
Write span to dac n.
Definition: LTC2668.h:102
char option
Demo Circuit option (A)
#define LTC2668_CMD_NO_OPERATION
No operation.
Definition: LTC2668.h:111
#define LTC2668_CMD_MUX
Select MUX channel (controlled by 5 LSbs in data word)
Definition: LTC2668.h:107
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.
#define REF_INTERNAL
Internal mode.
Definition: DC2025A.ino:140
unsigned char user_command
static uint16_t get_code()
Get code to send to DAC directly, in decimal, hex, or binary.
Definition: DC2025A.ino:851
#define EEPROM_I2C_ADDRESS
QuikEval EEPROM Library.
#define LTC2668_CMD_WRITE_N
Write to input register n.
Definition: LTC2668.h:95
uint16_t toggle_word
Toggle control word.
Definition: DC2692A.ino:168
#define LTC2668_SPAN_0_TO_10V
Definition: LTC2668.h:120
#define LTC2668_CMD_UPDATE_N
Update (power up) DAC register n.
Definition: LTC2668.h:96
static void menu_7_set_softspan_range(uint8_t selected_dac)
Set SoftSpan Range.
Definition: DC2025A.ino:424
int16_t cal_key
The key that keeps track of the calibration.
Definition: DC2692A.ino:164
Header File for Linduino Libraries and Demo Code.
static void menu_6_set_reference_mode()
Set reference mode.
Definition: DC2025A.ino:398
static void menu_3_write_and_update_dac(uint8_t selected_dac)
Write data to DAC register (which updates output immediately)
Definition: DC2025A.ino:340
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.
#define LTC2668_CMD_TOGGLE_SEL
Select which DACs can be toggled (via toggle pin or global toggle bit)
Definition: LTC2668.h:108
static void menu_1_select_dac(uint8_t *selected_dac)
Select which DAC to operate on.
Definition: DC2025A.ino:291
int8_t LTC2668_write(uint8_t cs, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
Write the 16-bit dac_code to the LTC2668.
Definition: LTC2668.cpp:70
static void menu_14_demo_board_test()
Definition: DC2025A.ino:693
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: DC2025A.ino:796
#define LTC2668_CMD_WRITE_ALL
Write to all input registers.
Definition: LTC2668.h:104
uint8_t mux_state
Multiplexer address AND enable bit.
Definition: DC2692A.ino:170
static void menu_9_set_mux()
Enable / Disable and sets the channel for the MUX.
Definition: DC2025A.ino:473
static void print_prompt(int8_t selected_dac)
Prints main menu.
Definition: DC2025A.ino:879
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.
LTC2668: 16-Channel SPI 16-/12-Bit +/-10V Vout SoftSpan DACs with 10ppm/C Max Reference.
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
#define LTC2668_CMD_SPAN_ALL
Set span for all DACs.
Definition: LTC2668.h:110
static uint8_t demo_board_connected
Set to 1 if the board is connected.
Definition: DC2025A.ino:168
#define LTC2668_CMD_GLOBAL_TOGGLE
Software toggle control via global toggle bit.
Definition: LTC2668.h:109
#define LTC2668_SPAN_0_TO_5V
Definition: LTC2668.h:119
QuikEval EEPROM Library.
static void menu_5_power_down_dac(uint8_t selected_dac)
Power down DAC.
Definition: DC2025A.ino:388
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 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.
const float LTC2668_MIN_OUTPUT[5]
Definition: LTC2668.h:129
static void menu_10_global_toggle_settings()
Enable / Disable the global toggle bit.
Definition: DC2025A.ino:503
static void loop()
Repeats Linduino loop.
Definition: DC2025A.ino:220
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: DC2025A.ino:458
static void restore_dac_from_eeprom()
Read the alert settings from EEPROM.
Definition: DC2025A.ino:941
#define REF_EXTERNAL
External mode.
Definition: DC2025A.ino:139
uint8_t soft_span_range[5]
SoftSpan range.
Definition: DC2692A.ino:165
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
static void menu_2_write_to_input_register(uint8_t selected_dac)
Write data to input register, but do not update DAC output.
Definition: DC2025A.ino:303
eeprom_data_union eeprom
Definition: DC2025A.ino:188
static void print_title()
Prints the title block when program first starts.
Definition: DC2025A.ino:864
uint16_t dac_code_a[16]
DAC Register A.
Definition: DC2692A.ino:166
static void menu_13_settling_test()
Definition: DC2025A.ino:578
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: DC2025A.ino:378
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
char demo_name[]
Demo Board Name stored in QuikEval EEPROM.
Definition: DC1880A.ino:97
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
int32_t read_int()
#define LTC2668_CMD_POWER_DOWN_ALL
Power down chip (all DAC&#39;s, MUX and reference)
Definition: LTC2668.h:100
#define LTC2668_CMD_WRITE_N_UPDATE_N
Write to input register n, update (power-up)
Definition: LTC2668.h:98
uint16_t LTC2668_voltage_to_code(float dac_voltage, float min_output, float max_output)
Calculate a LTC2668 DAC code given the desired output voltage and DAC address (0-3) ...
Definition: LTC2668.cpp:103
float read_float()
#define LTC2668_CMD_UPDATE_ALL
Update all DACs.
Definition: LTC2668.h:105
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
static uint16_t get_voltage(uint8_t selected_dac)
Get voltage from user input, calculate DAC code based on lsb, offset.
Definition: DC2025A.ino:829
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
const float LTC2668_MAX_OUTPUT[5]
Definition: LTC2668.h:130
static int i
Definition: DC2430A.ino:184
struct eeprom_data_union::data_struct_type data_struct
Name of structure.
#define LTC2668_CMD_POWER_DOWN_N
Power down n.
Definition: LTC2668.h:99
static void setup()
Initialize Linduino.
Definition: DC2025A.ino:200
#define EEPROM_CAL_KEY
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: DC2025A.ino:523
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...
char ui_buffer[UI_BUFFER_SIZE]
#define LTC2668_MUX_ENABLE
Definition: LTC2668.h:144
static void menu_12_voltage_ramp()
Sets a voltage ramp to all the channels.
Definition: DC2025A.ino:550
#define LTC2668_CMD_WRITE_ALL_UPDATE_ALL
Write to all input reg, update all DACs.
Definition: LTC2668.h:106
#define LTC2668_CS
Define the SPI CS pin.
Definition: LTC2668.h:90