Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC809A.ino
Go to the documentation of this file.
1 /*!
2 LTC2604: Quad 16-Bit Rail-to-Rail DACs in 16-Lead SSOP
3 
4 @verbatim
5 
6 The LTC2604/LTC2614/LTC2624 are quad 16-,14- and 12-bit 2.5V to 5.5V
7 rail-to-rail voltage output DACs in 16-lead narrow SSOP packages. These
8 parts have separate reference inputs for each DAC. They have built-in
9 high performance output buffers and are 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/LTC2604
18 
19 http://www.linear.com/product/LTC2604#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 LTC2604
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 "LTC2604.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 LTC2604_lsb, int16_t LTC2604_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] = {4.096,4.096,4.096,4.096}; //!< set based on jumper positions
90 static int16_t LTC2604_offset =0;
91 static float LTC2604_lsb[4] = {reference_voltage[0]/ (pow(2,16) - 1) , reference_voltage[1]/ (pow(2,16) - 1),
92  reference_voltage[2]/ (pow(2,16) - 1),reference_voltage[3]/ (pow(2,16) - 1)
93  };
94 
95 // constants
96 
97 //! Lookup table for DAC address. Allows the "All DACs" address to be indexed right after DAC D in loops.
98 //! This technique is very useful for devices with non-monotonic channel addresses.
99 const uint8_t address_map[5] = {LTC2604_DAC_A, LTC2604_DAC_B, LTC2604_DAC_C, LTC2604_DAC_D, LTC2604_DAC_ALL}; //!< Map entered option 0..2 to DAC address
100 
101 //! Used to keep track to print voltage or print code
102 enum
103 {
104  PROMPT_VOLTAGE = 0, /**< 0 */
105  PROMPT_CODE = 1 /**< 1 */
106 };
107 
108 //! Initialize Linduino
109 void setup()
110 // Setup the program
111 {
112  char demo_name[] = "DC809A"; // Demo Board Name stored in QuikEval EEPROM
113  quikeval_SPI_init(); // Configure the spi port for 4MHz SCK
114  quikeval_SPI_connect(); // Connect SPI to main data port
115  Serial.begin(115200); // Initialize the serial port to the PC
116  print_title();
117  demo_board_connected = true; //discover_demo_board(demo_name);
119  {
120  print_prompt(0);
121  }
122 }
123 
124 //! Repeats Linduino loops
125 void loop()
126 {
127  int16_t user_command;
128  static int16_t selected_dac =0; // The selected DAC to be updated (0=A, 1=B ... 5=All). Initialized to "A".
129  // The main control loop
130  if (demo_board_connected) // Do nothing if the demo board is not connected
131  {
132  if (Serial.available()) // Check for user input
133  {
134  user_command = read_int(); // Read the user command
135  Serial.println(user_command);
136  Serial.flush();
137  switch (user_command)
138  {
139  case 1:
140  menu_1_select_dac(&selected_dac);
141  break;
142  case 2:
143  menu_2_write_to_input_register(selected_dac);
144  break;
145  case 3:
146  menu_3_write_and_update_dac(selected_dac);
147  break;
148  case 4:
149  menu_4_update_power_up_dac(selected_dac);
150  break;
151  case 5:
152  menu_5_power_down_dac(selected_dac);
153  break;
154  }
155  Serial.println("\n*****************************************************************");
156  print_prompt(selected_dac);
157  }
158  }
159 }
160 
161 // Function Definitions
162 
163 //! Select which DAC to operate on
164 void menu_1_select_dac(int16_t *selected_dac ) //!< what DAC to operate on
165 {
166  // Select a DAC to operate on
167  Serial.print("Select DAC to operate on (0=A, 1=B, 2=C, 3=D, 4=All)");
168  *selected_dac = read_int();
169  if (*selected_dac == 4)
170  Serial.println("All");
171  else
172  Serial.println(*selected_dac);
173 }
174 
175 //! Write data to input register, but do not update DAC output
176 void menu_2_write_to_input_register(int16_t selected_dac) //!< what DAC to operate on
177 {
178  uint16_t dac_code;
179 
181  dac_code = get_voltage(LTC2604_lsb[selected_dac], LTC2604_offset);
182  else
183  dac_code = get_code();
184 
185  LTC2604_write(LTC2604_CS, LTC2604_CMD_WRITE, address_map[selected_dac], dac_code << shift_count);
186 }
187 
188 //!Write data to DAC register (which updates output immediately)
189 void menu_3_write_and_update_dac(int16_t selected_dac) //!< what DAC to operate on
190 {
191  uint16_t dac_code;
192 
194  dac_code = get_voltage(LTC2604_lsb[selected_dac], LTC2604_offset);
195  else
196  dac_code = get_code();
197 
199 }
200 
201 //! Update DAC with data that is stored in input register, power up if sleeping
202 void menu_4_update_power_up_dac(int16_t selected_dac) //!< what DAC to operate on
203 {
204  // Update DAC
205  LTC2604_write(LTC2604_CS,LTC2604_CMD_UPDATE, address_map[selected_dac], 0x0000);
206 }
207 
208 //! Power down DAC
209 void menu_5_power_down_dac(int16_t selected_dac) //!< what DAC to operate on
210 {
211  // Power down DAC
213 }
214 
215 
216 //! Prompt user to enter a voltage or digital code to send to DAC
217 //! @returns user input
219 {
220  int16_t user_input;
221  Serial.print(F("Type 1 to enter voltage, 2 to enter code:"));
222  Serial.flush();
223  user_input = read_int();
224  Serial.println(user_input);
225 
226  if (user_input != 2)
227  return(PROMPT_VOLTAGE);
228  else
229  return(PROMPT_CODE);
230 }
231 
232 //! Get voltage from user input, calculate DAC code based on lsb, offset
233 //! @returns the DAC code
234 uint16_t get_voltage(float LTC2604_lsb, //!< the voltage LSB of the DAC
235  int16_t LTC2604_offset) //!< the Offset of the DAC
236 {
237  float dac_voltage;
238 
239  Serial.print(F("Enter Desired DAC output voltage: "));
240  dac_voltage = read_float();
241  Serial.print(dac_voltage);
242  Serial.println(" V");
243  Serial.flush();
244  return(LTC2604_voltage_to_code(dac_voltage, LTC2604_lsb, LTC2604_offset));
245 }
246 
247 //! Get code to send to DAC directly, in decimal, hex, or binary
248 //! @return code from user
249 uint16_t get_code()
250 {
251  uint16_t returncode;
252  Serial.println("Enter Desired DAC Code");
253  Serial.print("(Format 32768, 0x8000, 0100000, or B1000000000000000): ");
254  returncode = (uint16_t) read_int();
255  Serial.print("0x");
256  Serial.println(returncode, HEX);
257  Serial.flush();
258  return(returncode);
259 }
260 
261 //! Prints the title block when program first starts.
263 {
264  Serial.println("");
265  Serial.println(F("*****************************************************************"));
266  Serial.println(F("* DC809A Demonstration Program *"));
267  Serial.println(F("* *"));
268  Serial.println(F("* This program demonstrates how to send data to the LTC2604 *"));
269  Serial.println(F("* quad 16/14/12-bit DAC found on the DC809A demo board. *"));
270  Serial.println(F("* *"));
271  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
272  Serial.println(F("* *"));
273  Serial.println(F("*****************************************************************"));
274 }
275 
276 //! Prints main menu.
277 void print_prompt(int16_t selected_dac) //!< what DAC to operate on
278 {
279  Serial.println(F("\nCommand Summary:"));
280  Serial.println(F(" 1-Select DAC"));
281  Serial.println(F(" 2-Write to input register (no update)"));
282  Serial.println(F(" 3-Write and update DAC"));
283  Serial.println(F(" 4-Update / power up DAC"));
284  Serial.println(F(" 5-Power down DAC"));
285 
286  Serial.println("\nPresent Values:");
287  Serial.print(" Selected DAC: ");
288  if (selected_dac != 4)
289  Serial.println((char) (selected_dac + 0x41));
290  else
291  Serial.println("All");
292  Serial.print(" DAC Reference: ");
293  Serial.println("Internal");
294  Serial.print(F("Enter a command:"));
295 
296  Serial.flush();
297 }
static uint8_t demo_board_connected
set to 1 if the board is connected
Definition: DC809A.ino:87
unsigned char user_command
static void setup()
Initialize Linduino.
Definition: DC809A.ino:109
static int16_t prompt_voltage_or_code()
Prompt user to enter a voltage or digital code to send to DAC.
Definition: DC809A.ino:218
#define LTC2604_DAC_D
Definition: LTC2604.h:135
#define LTC2604_CMD_WRITE_UPDATE
Write to input register n, update (power up) all.
Definition: LTC2604.h:114
Header File for Linduino Libraries and Demo Code.
uint16_t LTC2604_voltage_to_code(float dac_voltage, float LTC2604_lsb, int16_t LTC2604_offset)
Calculate a LTC2604 DAC code given the desired output voltage and DAC address (0-3) ...
Definition: LTC2604.cpp:90
static void print_prompt(int16_t selected_dac)
Prints main menu.
Definition: DC809A.ino:277
#define LTC2604_DAC_A
Definition: LTC2604.h:132
static void menu_3_write_and_update_dac(int16_t selected_dac)
Write data to DAC register (which updates output immediately)
Definition: DC809A.ino:189
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: DC809A.ino:202
QuikEval EEPROM Library.
#define LTC2604_DAC_B
Definition: LTC2604.h:133
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
static float LTC2604_lsb[4]
Definition: DC809A.ino:91
static float reference_voltage[4]
set based on jumper positions
Definition: DC809A.ino:89
#define LTC2604_DAC_C
Definition: LTC2604.h:134
#define LTC2604_CMD_UPDATE
Update (power up) DAC register n.
Definition: LTC2604.h:112
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
void LTC2604_write(uint8_t cs, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
Write the 16-bit dac_code to the LTC2604.
Definition: LTC2604.cpp:75
const uint8_t address_map[5]
Lookup table for DAC address.
Definition: DC809A.ino:99
static void print_title()
Prints the title block when program first starts.
Definition: DC809A.ino:262
static int16_t LTC2604_offset
Definition: DC809A.ino:90
static uint16_t get_voltage(float LTC2604_lsb, int16_t LTC2604_offset)
Get voltage from user input, calculate DAC code based on lsb, offset.
Definition: DC809A.ino:234
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
#define LTC2604_CS
Define the SPI CS pin.
Definition: LTC2604.h:104
static void menu_5_power_down_dac(int16_t selected_dac)
Power down DAC.
Definition: DC809A.ino:209
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()
static uint16_t get_code()
Get code to send to DAC directly, in decimal, hex, or binary.
Definition: DC809A.ino:249
static void loop()
Repeats Linduino loops.
Definition: DC809A.ino:125
LTC2604: Quad 16-Bit Rail-to-Rail DACs in 16-Lead SSOP.
static void menu_1_select_dac(int16_t *selected_dac)
Select which DAC to operate on.
Definition: DC809A.ino:164
static void menu_2_write_to_input_register(int16_t selected_dac)
Write data to input register, but do not update DAC output.
Definition: DC809A.ino:176
#define LTC2604_CMD_POWER_DOWN
Power down n.
Definition: LTC2604.h:115
static uint8_t shift_count
The data align shift count for 16-bit =0 14-bit =2 12-bit =4.
Definition: DC809A.ino:88
#define LTC2604_CMD_WRITE
Write to input register n.
Definition: LTC2604.h:111
#define LTC2604_DAC_ALL
Definition: LTC2604.h:136