Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
Audio_Spectrum_Analyzer.ino
Go to the documentation of this file.
1 #include <Arduino.h>
2 #include <stdint.h>
3 #include "Linduino.h"
4 #include "LT_SPI.h"
5 #include "UserInterface.h"
6 #include "LT_I2C.h"
7 #include "QuikEval_EEPROM.h"
8 #include "LTC6904.h"
9 #include "LTC2484.h"
10 #include <SPI.h>
11 #include <Wire.h>
12 #include "LTC24XX_general.h"
13 
14 int8_t restore_calibration(); // Read the DAC calibration from EEPROM, Return 1 if successful, 0 if not
15 void store_calibration(); // Store the ADC calibration to the EEPROM
16 uint8_t calibrate_voltage();
17 
18 // Global variables
19 static float start, stop, step;
20 const uint16_t MISO_TIMEOUT = 1000; //!< The MISO timeout (ms)
21 
22 // Calibration variables
23 static float LTC2484_lsb = 9.3132258E-9; //!< Ideal LSB size, 5V/(2^29) for a 5V reference
24 static int32_t LTC2484_offset_code = 0; //!< Ideal offset
25 
26 void setup()
27 {
28  Serial.begin(115200);
29  quikeval_SPI_init(); // Configures the SPI port for 4MHz SCK
30  quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz SCK
32 }
33 
34 void loop()
35 {
36  int16_t user_command; // User input command
37 
38  display_menu();
39 
40  user_command = read_int(); // Reads the user command (if available).
41  Serial.println(user_command);
42 
43  switch (user_command)
44  {
45  case 1:
46  settings();
47  break;
48  case 2:
49  analyze();
50  break;
51  case 3:
52  test();
53  break;
54  case 4:
56  default:
57  Serial.println(F("incorrect option"));
58  Serial.println();
59  break;
60  }
61 }
62 
64 {
65  Serial.println();
66  Serial.println(F("Main Menu"));
67  Serial.println(F("1-Settings"));
68  Serial.println(F("2-Analyze"));
69  Serial.println(F("3-Test Clock"));
70  Serial.println(F("4-Calibrate ADC"));
71  Serial.println();
72  Serial.print(F("Enter a command: "));
73 }
74 
75 void settings()
76 {
77  Serial.println(F("Enter the Start frequency (KHz)"));
78  start = read_float();
79  Serial.println(start, 4);
80 
81  Serial.println(F("Enter the Stop frequency (KHz)"));
82  stop = read_float();
83  Serial.println(stop, 4);
84 
85  Serial.println(F("Enter Step size (kHz)"));
86  step = read_float();
87  Serial.println(step, 4);
88 }
89 
90 void analyze()
91 {
92 
93  float clock;
94  int32_t clock_code;
95  uint16_t i;
96  uint8_t adc_command;
97 
98 
99  clock = start/10; // Set Clock to 100 times the start frequency
100 
101  Serial.println();
102  Serial.println();
103  Serial.println(F("Sweeping..."));
104  Serial.println();
105  Serial.println(F(" --------------------------------0 dBV-|"));
106  Serial.println(F(" V"));
107  for (i=0; i<= (stop-start)/step; i++)
108  {
109  float adc_voltage = 0;
110  int32_t adc_code = 0;
111 
112  quikeval_I2C_connect(); // Connects I2C port to the QuikEval connector
113 
114  clock_code = LTC6904_frequency_to_code(clock, (uint8_t)LTC6904_CLK_ON_CLK_INV_ON);
115  clock += (step)/10;
116  LTC6904_write(LTC6904_ADDRESS, (uint32_t)clock_code);
117 
118  delay(500);
119 
120  quikeval_SPI_connect(); // Connects SPI to QuikEval port
121 
122  delay (500);
123 
124  // Build ADC command to read the ADC voltage
125  adc_command = LTC2484_ENABLE;
126  adc_command |= LTC2484_EXTERNAL_INPUT;
127  adc_command |= LTC2484_AUTO_CALIBRATION;
128  adc_command |= LTC2484_REJECTION_60HZ;
129 
130 
131  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
132  return;
133  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Throw away last reading
134 
135  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
136  return;
137  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Obtains the current reading and stores to adc_code variable
138 
139  // Convert adc_code to voltage
140  adc_voltage = LTC2484_code_to_voltage(adc_code, LTC2484_lsb, LTC2484_offset_code);
141 
142  adc_voltage *= 2; // Scale by 2 because Vrms was devided by two by the filter.
143 
144  if (i==0)
145  {
146  if (start<=9)
147  Serial.print(F(" "));
148  else if (start<=99)
149  Serial.print(F(" "));
150 
151  Serial.print(start);
152  Serial.print(F("KHz"));
153  }
154  else if (i == (stop-start)/step)
155  {
156  if (stop<=9)
157  Serial.print(F(" "));
158  else if (stop<=99)
159  Serial.print(F(" "));
160  Serial.print(stop);
161  Serial.print(F("KHz"));
162  }
163  else if (adc_voltage > .1)
164  {
165  if (start+i*step <= 9)
166  Serial.print(F(" "));
167  else if (start+i*step <= 99)
168  Serial.print(F(" "));
169  Serial.print(start+i*step);
170  Serial.print(F("KHz"));
171  }
172  else
173  Serial.print(F(" "));
174  display_graph(adc_voltage);
175  }
176 
177  // Display data
178  Serial.println();
179  Serial.print(F("Step: "));
180  Serial.println(step, 4);
181  for (i=0; i<= (stop-start)/step; i++)
182  {
183 
184  }
185 
186 }
187 
188 void display_graph(float data)
189 {
190  int16_t i, j;
191 
192  data /= 0.025;
193 
194  j = (int16_t) data;
195 
196  if (j > 40)
197  j = 40;
198  for (i=0; i<=j; i++)
199  {
200  Serial.print(F("#"));
201  }
202  Serial.println();
203 }
204 
205 void test()
206 {
207 
208  float freq;
209  int32_t clock_code;
210  float adc_voltage;
211  int32_t adc_code;
212  uint8_t adc_command;
213 
214  Serial.print(F("Enter the desired clock freq (KHz)"));
215 
216  freq = read_float();
217 
218  Serial.println(freq, 4);
219 
220  clock_code = LTC6904_frequency_to_code(freq/1000, (uint8_t)LTC6904_CLK_ON_CLK_INV_ON);
221 
222  if (clock_code == -1)
223  {
224  Serial.println("No Sloution");
225  return;
226  }
227  LTC6904_write(LTC6904_ADDRESS, (uint32_t)clock_code);
228  delay(3000);
229 
230  // Build ADC command to read the ADC voltage
231  adc_command = LTC2484_ENABLE;
232  adc_command |= LTC2484_EXTERNAL_INPUT;
233  adc_command |= LTC2484_AUTO_CALIBRATION;
234  adc_command |= LTC2484_REJECTION_60HZ;
235 
236 
237  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
238  return;
239  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Throw away last reading
240 
241  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
242  return;
243  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Obtains the current reading and stores to adc_code variable
244 
245  // Convert adc_code to voltage
246  adc_voltage = LTC2484_code_to_voltage(adc_code, LTC2484_lsb, LTC2484_offset_code);
247 
248  Serial.print("Voltage: ");
249  Serial.println(adc_voltage, 4);
250 }
251 
252 //! Read stored calibration parameters from nonvolatile EEPROM on demo board
253 //! @return 0 if successful, 1 if failure
255 // Read the DAC calibration from EEPROM
256 {
257  int16_t cal_key;
258  // Read the cal key from the EEPROM
260  if (cal_key == EEPROM_CAL_KEY)
261  {
262  // Calibration has been stored, read offset and lsb
265  Serial.println(F("Calibration Restored"));
266  return (1);
267  }
268  else
269  {
270  Serial.println(F("Calibration not found"));
271  return (0);
272  }
273 }
274 
275 //! Calibrate ADC given two known inputs
276 //! @return 0 if successful, 1 if failure
278 {
279  // Calibrate voltage measurement
280  float zero_voltage; // Measured cal voltage
281  float fs_voltage; // Measured cal voltage
282  int32_t zero_code; // Cal zero code
283  int32_t fs_code; // Cal full scale code
284  uint8_t user_command; // The user input command
285  int32_t adc_code = 0; // The LTC2484 code
286  uint8_t adc_command; // The LTC2484 command byte
287 
288  Serial.println(F("Short the inputs to ground calibrate the offset."));
289  Serial.println(F("or apply a voltage for the lower point in two point calibration"));
290  Serial.print(F("Enter the measured input voltage:"));
291  zero_voltage = read_float();
292  Serial.println(zero_voltage, 6);
293 
294  // Build ADC command to read the ADC voltage
295  adc_command = LTC2484_ENABLE;
296  adc_command |= LTC2484_EXTERNAL_INPUT;
297  adc_command |= LTC2484_AUTO_CALIBRATION;
298  adc_command |= LTC2484_REJECTION_60HZ;
299 
300  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
301  return(1);
302  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Throw away previous reading
303  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
304  return(1);
305  LTC2484_read(LTC2484_CS, adc_command, &zero_code); // Measure zero
306 
307  Serial.println(F("Apply ~2.49V to +IN"));
308  Serial.println(F("Enter the measured input voltage:"));
309  fs_voltage = read_float();
310 
311  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
312  return(1);
313  LTC2484_read(LTC2484_CS, adc_command, &adc_code); // Throw away previous reading
314  if (LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT)) // Check for EOC
315  return(1);
316  LTC2484_read(LTC2484_CS, adc_command, &fs_code); // Measure full scale
317 
318  LTC2484_cal_voltage(zero_code, fs_code, zero_voltage, fs_voltage, &LTC2484_lsb, &LTC2484_offset_code);
319 
320  Serial.print(F("ADC offset : "));
321  Serial.print(LTC2484_offset_code);
322  Serial.print(F(" ADC lsb : "));
323  Serial.print(LTC2484_lsb * 1.0e9, 4);
324  Serial.println(F("nV (32-bits)"));
326  return(0);
327 }
328 
329 //! Store measured calibration parameters to nonvolatile EEPROM on demo board
331 // Store the ADC calibration to the EEPROM
332 {
336  Serial.println(F("Calibration Stored to EEPROM"));
337 }
#define LTC6904_CLK_ON_CLK_INV_ON
Clock on, inverted clock on.
Definition: LTC6904.h:109
LTC6904: 1kHz to 68MHz Serial Port Programmable Oscillator.
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.
static void settings()
LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation.
static void test()
unsigned char user_command
static void setup()
static uint8_t adc_command
Definition: DC2071AA.ino:111
#define EEPROM_I2C_ADDRESS
#define LTC2484_AUTO_CALIBRATION
Definition: LTC2484.h:167
static uint8_t calibrate_voltage()
Calibrate ADC given two known inputs.
static void analyze()
static void store_calibration()
Store measured calibration parameters to nonvolatile EEPROM on demo board.
Header File for Linduino Libraries and Demo Code.
uint16_t LTC6904_frequency_to_code(float frequency, uint8_t clk)
Calculates the code necessary to create the clock frequency.
Definition: LTC6904.cpp:82
uint8_t eeprom_read_float(uint8_t i2c_address, float *read_data, uint16_t address)
Read the four byte float data from the EEPROM starting at address.
uint8_t eeprom_write_int32(uint8_t i2c_address, int32_t write_data, uint16_t address)
Write the 4 byte long data to the EEPROM starting at address.
static float step
static void display_graph(float data)
static float adc_voltage
Definition: DC2071AA.ino:115
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
static void display_menu()
static float LTC2484_lsb
Ideal LSB size, 5V/(2^29) for a 5V reference.
float LTC2484_code_to_voltage(int32_t adc_code, float LTC2484_lsb, int32_t LTC2484_offset_code)
Calculates the LTC2484 input bipolar voltage.
Definition: LTC2484.cpp:96
LTC24XX General Library: Functions and defines for all SINC4 Delta Sigma ADCs.
const uint16_t MISO_TIMEOUT
The MISO timeout (ms)
static int8_t restore_calibration()
Read stored calibration parameters from nonvolatile EEPROM on demo board.
void LTC2484_cal_voltage(int32_t zero_code, int32_t fs_code, float zero_voltage, float fs_voltage, float *LTC2484_lsb, int32_t *LTC2484_offset_code)
Calibrate the lsb.
Definition: LTC2484.cpp:109
uint8_t eeprom_write_float(uint8_t i2c_address, float write_data, uint16_t address)
Write the 4 byte float data to the EEPROM starting at address.
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.
void LTC2484_read(uint8_t cs, uint8_t adc_command, int32_t *adc_code)
Read LTC2484 result, program configuration for next conversion.
Definition: LTC2484.cpp:90
QuikEval EEPROM Library.
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
#define EEPROM_CAL_STATUS_ADDRESS
#define LTC2484_EXTERNAL_INPUT
Definition: LTC2484.h:160
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
#define LTC6904_ADDRESS
ADR 0.
Definition: LTC6904.h:64
static float stop
uint8_t LTC6904_write(uint8_t address, uint16_t code)
Writes 2 bytes.
Definition: LTC6904.cpp:73
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
int8_t LTC2484_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
Checks for EOC with a specified timeout.
Definition: LTC2484.cpp:84
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
uint8_t eeprom_read_int32(uint8_t i2c_address, int32_t *read_data, uint16_t address)
Read the four byte long data from the EEPROM starting at address.
int32_t read_int()
float read_float()
#define LTC2484_CS
define the SPI CS pin
Definition: LTC2484.h:151
#define LTC2484_REJECTION_60HZ
Definition: LTC2484.h:165
static float start
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
static int32_t LTC2484_offset_code
Ideal offset.
void quikeval_I2C_connect(void)
Switch MUX to connect I2C pins to QuikEval connector.
Definition: LT_I2C.cpp:401
static int i
Definition: DC2430A.ino:184
static void loop()
#define EEPROM_CAL_KEY
#define LTC2484_ENABLE
Definition: LTC2484.h:157
static uint32_t adc_code
Definition: DC2071AA.ino:113