Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC579A.ino
Go to the documentation of this file.
1 /*!
2 LTC2600: Octal 16-Bit Rail-to-Rail DACs in 16-Lead SSOP
3 
4 @verbatim
5 
6 The LTC2600/LTC2610/LTC2620 are octal 16-, 14- and 12-bit, 2.5V-to-5.5V
7 rail-to-rail voltage-output DACs in 16-lead narrow SSOP and 20-lead 4mm × 5mm
8 QFN packages. They have built-in high performance output buffers and are
9 guaranteed monotonic.
10 
11 These parts establish advanced performance standards for output drive,
12 crosstalk and load regulation in single-supply, voltage output multiples.
13 
14 @endverbatim
15 
16 
17 http://www.linear.com/product/LTC2600
18 
19 http://www.linear.com/product/LTC2600#demoboards
20 
21 
22 Copyright 2018(c) Analog Devices, Inc.
23 
24 All rights reserved.
25 
26 Redistribution and use in source and binary forms, with or without
27 modification, are permitted provided that the following conditions are met:
28  - Redistributions of source code must retain the above copyright
29  notice, this list of conditions and the following disclaimer.
30  - Redistributions in binary form must reproduce the above copyright
31  notice, this list of conditions and the following disclaimer in
32  the documentation and/or other materials provided with the
33  distribution.
34  - Neither the name of Analog Devices, Inc. nor the names of its
35  contributors may be used to endorse or promote products derived
36  from this software without specific prior written permission.
37  - The use of this software may or may not infringe the patent rights
38  of one or more patent holders. This license does not release you
39  from the requirement that you obtain separate licenses from these
40  patent holders to use this software.
41  - Use of the software either in source or binary form, must be run
42  on or directly connected to an Analog Devices Inc. component.
43 
44 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
45 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
46 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
48 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
50 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55 
56 
57 /*! @file
58  @ingroup LTC2600
59 */
60 
61 #include <Arduino.h>
62 #include <stdint.h>
63 #include "Linduino.h"
64 #include "LT_SPI.h"
65 #include "UserInterface.h"
66 #include "LT_I2C.h"
67 #include "QuikEval_EEPROM.h"
68 #include "LTC2600.h"
69 #include <SPI.h>
70 #include <Wire.h>
71 
72 //Function Declaration
73 
74 void print_title(); // Print the title block
75 void print_prompt(int16_t selected_dac); // Prompt the user for an input command
76 int16_t prompt_voltage_or_code();
77 uint16_t get_voltage(float LTC2600_lsb, int16_t LTC2600_offset);
78 uint16_t get_code();
79 
80 void menu_1_select_dac(int16_t *selected_dac);
81 void menu_2_write_to_input_register(int16_t selected_dac);
82 void menu_3_write_and_update_dac(int16_t selected_dac);
83 void menu_4_update_power_up_dac(int16_t selected_dac);
84 void menu_5_power_down_dac(int16_t selected_dac);
85 
86 //Global variables
87 static uint8_t demo_board_connected; //!< set to 1 if the board is connected
88 static uint8_t shift_count =0; //!< The data align shift count for 16-bit =0 14-bit =2 12-bit =4
89 static float reference_voltage = 4.096; //!< set based on jumper positions
90 static int16_t LTC2600_offset =0;
91 static float LTC2600_lsb = reference_voltage/ (pow(2,16) - 1);
92 
93 // constants
94 
95 //! Lookup table for DAC address. Allows the "All DACs" address to be indexed right after DAC D in loops.
96 //! This technique is very useful for devices with non-monotonic channel addresses.
97 const uint8_t address_map[5] = {LTC2600_DAC_A, LTC2600_DAC_B, LTC2600_DAC_C, LTC2600_DAC_D, LTC2600_DAC_ALL}; //!< Map entered option 0..2 to DAC address
98 
99 //! Used to keep track to print voltage or print code
100 enum
101 {
102  PROMPT_VOLTAGE = 0, /**< 0 */
103  PROMPT_CODE = 1 /**< 1 */
104 };
105 
106 //! Initialize Linduino
107 void setup()
108 // Setup the program
109 {
110  char demo_name[] = "DC579A"; // Demo Board Name stored in QuikEval EEPROM
111  quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
112  quikeval_SPI_connect(); // Connect SPI to main data port
113  Serial.begin(115200); // Initialize the serial port to the PC
114  print_title();
115  char buffer[50];
116  read_quikeval_id_string(buffer);
117  Serial.println(buffer);
118  demo_board_connected = true; // discover_demo_board(demo_name);
120  {
121  print_prompt(0);
122  }
123 }
124 
125 //! Repeats Linduino loops
126 void loop()
127 {
128  int16_t user_command;
129  static int16_t selected_dac =0; // The selected DAC to be updated (0=A, 1=B ... 5=All). Initialized to "A".
130  // The main control loop
131  if (demo_board_connected) // Do nothing if the demo board is not connected
132  {
133  if (Serial.available()) // Check for user input
134  {
135  user_command = read_int(); // Read the user command
136  Serial.println(user_command);
137  Serial.flush();
138  switch (user_command)
139  {
140  case 1:
141  menu_1_select_dac(&selected_dac);
142  break;
143  case 2:
144  menu_2_write_to_input_register(selected_dac);
145  break;
146  case 3:
147  menu_3_write_and_update_dac(selected_dac);
148  break;
149  case 4:
150  menu_4_update_power_up_dac(selected_dac);
151  break;
152  case 5:
153  menu_5_power_down_dac(selected_dac);
154  break;
155  }
156  Serial.println("\n*****************************************************************");
157  print_prompt(selected_dac);
158  }
159  }
160 }
161 
162 // Function Definitions
163 
164 //! Select which DAC to operate on
165 void menu_1_select_dac(int16_t *selected_dac ) //!< what DAC to operate on
166 {
167  // Select a DAC to operate on
168  Serial.print("Select DAC to operate on (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, 6=G, 7=H, 8=All)");
169  *selected_dac = read_int();
170  if (*selected_dac == 8)
171  {
172  Serial.println("All");
173  *selected_dac = 15;
174  }
175  else
176  {
177  Serial.println(*selected_dac);
178  }
179 }
180 
181 //! Write data to input register, but do not update DAC output
182 void menu_2_write_to_input_register(int16_t selected_dac) //!< what DAC to operate on
183 {
184  uint16_t dac_code;
185 
188  else
189  dac_code = get_code();
190 
191  LTC2600_write(LTC2600_CS, LTC2600_CMD_WRITE, address_map[selected_dac], dac_code << shift_count);
192 }
193 
194 //!Write data to DAC register (which updates output immediately)
195 void menu_3_write_and_update_dac(int16_t selected_dac) //!< what DAC to operate on
196 {
197  uint16_t dac_code;
198 
201  else
202  dac_code = get_code();
203 
205 }
206 
207 //! Update DAC with data that is stored in input register, power up if sleeping
208 void menu_4_update_power_up_dac(int16_t selected_dac) //!< what DAC to operate on
209 {
210  // Update DAC
211  LTC2600_write(LTC2600_CS,LTC2600_CMD_UPDATE, address_map[selected_dac], 0x0000);
212 }
213 
214 //! Power down DAC
215 void menu_5_power_down_dac(int16_t selected_dac) //!< what DAC to operate on
216 {
217  // Power down DAC
219 }
220 
221 
222 //! Prompt user to enter a voltage or digital code to send to DAC
223 //! @returns user input
225 {
226  int16_t user_input;
227  Serial.print(F("Type 1 to enter voltage, 2 to enter code:"));
228  Serial.flush();
229  user_input = read_int();
230  Serial.println(user_input);
231 
232  if (user_input != 2)
233  return(PROMPT_VOLTAGE);
234  else
235  return(PROMPT_CODE);
236 }
237 
238 //! Get voltage from user input, calculate DAC code based on lsb, offset
239 //! @returns the DAC code
240 uint16_t get_voltage(float LTC2600_lsb, //!< the voltage LSB of the DAC
241  int16_t LTC2600_offset) //!< the Offset of the DAC
242 {
243  float dac_voltage;
244 
245  Serial.print(F("Enter Desired DAC output voltage: "));
246  dac_voltage = read_float();
247  Serial.print(dac_voltage);
248  Serial.println(" V");
249  Serial.flush();
250  return(LTC2600_voltage_to_code(dac_voltage, LTC2600_lsb, LTC2600_offset));
251 }
252 
253 //! Get code to send to DAC directly, in decimal, hex, or binary
254 //! @return code from user
255 uint16_t get_code()
256 {
257  uint16_t returncode;
258  Serial.println("Enter Desired DAC Code");
259  Serial.print("(Format 32768, 0x8000, 0100000, or B1000000000000000): ");
260  returncode = (uint16_t) read_int();
261  Serial.print("0x");
262  Serial.println(returncode, HEX);
263  Serial.flush();
264  return(returncode);
265 }
266 
267 //! Prints the title block when program first starts.
269 {
270  Serial.println("");
271  Serial.println(F("*****************************************************************"));
272  Serial.println(F("* DC579A Demonstration Program *"));
273  Serial.println(F("* *"));
274  Serial.println(F("* This program demonstrates how to send data to the LTC2600 *"));
275  Serial.println(F("* octal 16/14/12-bit DAC found on the DC579A demo board. *"));
276  Serial.println(F("* *"));
277  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
278  Serial.println(F("* *"));
279  Serial.println(F("*****************************************************************"));
280 }
281 
282 //! Prints main menu.
283 void print_prompt(int16_t selected_dac) //!< what DAC to operate on
284 {
285  Serial.println(F("\nCommand Summary:"));
286  Serial.println(F(" 1-Select DAC"));
287  Serial.println(F(" 2-Write to input register (no update)"));
288  Serial.println(F(" 3-Write and update DAC"));
289  Serial.println(F(" 4-Update / power up DAC"));
290  Serial.println(F(" 5-Power down DAC"));
291 
292  Serial.println("\nPresent Values:");
293  Serial.print(" Selected DAC: ");
294  if (selected_dac != 4)
295  Serial.println((char) (selected_dac + 0x41));
296  else
297  Serial.println("All");
298  Serial.print(" DAC Reference: ");
299  Serial.println("Internal");
300  Serial.print(F("Enter a command:"));
301 
302  Serial.flush();
303 }
#define LTC2600_CMD_POWER_DOWN
Power down n.
Definition: LTC2600.h:115
#define LTC2600_DAC_A
Definition: LTC2600.h:136
#define LTC2600_CMD_UPDATE
Update (power up) DAC register n.
Definition: LTC2600.h:112
#define LTC2600_CMD_WRITE
Write to input register n.
Definition: LTC2600.h:111
unsigned char user_command
static void menu_2_write_to_input_register(int16_t selected_dac)
Write data to input register, but do not update DAC output.
Definition: DC579A.ino:182
#define LTC2600_CMD_WRITE_UPDATE
Write to input register n, update (power up) all.
Definition: LTC2600.h:114
static void print_prompt(int16_t selected_dac)
Prints main menu.
Definition: DC579A.ino:283
LTC2600: Octal 16-Bit Rail-to-Rail DACs in 16-Lead SSOP.
static int16_t LTC2600_offset
Definition: DC579A.ino:90
Header File for Linduino Libraries and Demo Code.
static float LTC2600_lsb
Definition: DC579A.ino:91
static void setup()
Initialize Linduino.
Definition: DC579A.ino:107
static void menu_5_power_down_dac(int16_t selected_dac)
Power down DAC.
Definition: DC579A.ino:215
uint16_t LTC2600_voltage_to_code(float dac_voltage, float LTC2600_lsb, int16_t LTC2600_offset)
Calculate a LTC2600 DAC code given the desired output voltage and DAC address (0-3) ...
Definition: LTC2600.cpp:90
QuikEval EEPROM Library.
static void menu_3_write_and_update_dac(int16_t selected_dac)
Write data to DAC register (which updates output immediately)
Definition: DC579A.ino:195
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
static uint8_t shift_count
The data align shift count for 16-bit =0 14-bit =2 12-bit =4.
Definition: DC579A.ino:88
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
static void menu_4_update_power_up_dac(int16_t selected_dac)
Update DAC with data that is stored in input register, power up if sleeping.
Definition: DC579A.ino:208
#define LTC2600_DAC_ALL
Definition: LTC2600.h:144
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
static void menu_1_select_dac(int16_t *selected_dac)
Select which DAC to operate on.
Definition: DC579A.ino:165
static uint16_t get_voltage(float LTC2600_lsb, int16_t LTC2600_offset)
Get voltage from user input, calculate DAC code based on lsb, offset.
Definition: DC579A.ino:240
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()
float read_float()
#define LTC2600_CS
Define the SPI CS pin.
Definition: LTC2600.h:104
static void print_title()
Prints the title block when program first starts.
Definition: DC579A.ino:268
void LTC2600_write(uint8_t cs, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
Write the 16-bit dac_code to the LTC2600.
Definition: LTC2600.cpp:75
#define LTC2600_DAC_C
Definition: LTC2600.h:138
#define LTC2600_DAC_B
Definition: LTC2600.h:137
static int16_t prompt_voltage_or_code()
Prompt user to enter a voltage or digital code to send to DAC.
Definition: DC579A.ino:224
static float reference_voltage
set based on jumper positions
Definition: DC579A.ino:89
static uint16_t get_code()
Get code to send to DAC directly, in decimal, hex, or binary.
Definition: DC579A.ino:255
static uint8_t demo_board_connected
set to 1 if the board is connected
Definition: DC579A.ino:87
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...
const uint8_t address_map[5]
Lookup table for DAC address.
Definition: DC579A.ino:97
#define LTC2600_DAC_D
Definition: LTC2600.h:139
static void loop()
Repeats Linduino loops.
Definition: DC579A.ino:126