| 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
31 restore_calibration();
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:
55 calibrate_voltage();
56 default:
57 Serial.println(F("incorrect option"));
58 Serial.println();
59 break;
60 }
61 }
62
63 void display_menu()
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
254 int8_t restore_calibration()
255 // Read the DAC calibration from EEPROM
256 {
257 int16_t cal_key;
258 // Read the cal key from the EEPROM
259 eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
260 if (cal_key == EEPROM_CAL_KEY)
261 {
262 // Calibration has been stored, read offset and lsb
263 eeprom_read_int32(EEPROM_I2C_ADDRESS, &LTC2484_offset_code, EEPROM_CAL_STATUS_ADDRESS + 2); // Offset
264 eeprom_read_float(EEPROM_I2C_ADDRESS, &LTC2484_lsb, EEPROM_CAL_STATUS_ADDRESS + 6); // 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
277 uint8_t calibrate_voltage()
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)"));
325 store_calibration();
326 return(0);
327 }
328
329 //! Store measured calibration parameters to nonvolatile EEPROM on demo board
330 void store_calibration()
331 // Store the ADC calibration to the EEPROM
332 {
333 eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS); // Cal key
334 eeprom_write_int32(EEPROM_I2C_ADDRESS, LTC2484_offset_code, EEPROM_CAL_STATUS_ADDRESS + 2); // Offset
335 eeprom_write_float(EEPROM_I2C_ADDRESS, LTC2484_lsb, EEPROM_CAL_STATUS_ADDRESS + 6); // LSB
336 Serial.println(F("Calibration Stored to EEPROM"));
337 }
LTC6904_CLK_ON_CLK_INV_ON
#define LTC6904_CLK_ON_CLK_INV_ON
Clock on, inverted clock on.
Definition: LTC6904.h:109
LTC6904.h
LTC6904: 1kHz to 68MHz Serial Port Programmable Oscillator.
eeprom_read_int16
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.
Definition: QuikEval_EEPROM.cpp:395
settings
static void settings()
Definition: Audio_Spectrum_Analyzer.ino:75
LTC2484.h
LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation.
test
static void test()
Definition: Audio_Spectrum_Analyzer.ino:205
user_command
unsigned char user_command
Definition: Serial_EEPROM_Test.ino:75
setup
static void setup()
Definition: Audio_Spectrum_Analyzer.ino:26
adc_command
static uint8_t adc_command
Definition: DC2071AA.ino:111
EEPROM_I2C_ADDRESS
#define EEPROM_I2C_ADDRESS
Definition: QuikEval_EEPROM.h:60
LTC2484_AUTO_CALIBRATION
#define LTC2484_AUTO_CALIBRATION
Definition: LTC2484.h:167
calibrate_voltage
static uint8_t calibrate_voltage()
Calibrate ADC given two known inputs.
Definition: Audio_Spectrum_Analyzer.ino:277
analyze
static void analyze()
Definition: Audio_Spectrum_Analyzer.ino:90
store_calibration
static void store_calibration()
Store measured calibration parameters to nonvolatile EEPROM on demo board.
Definition: Audio_Spectrum_Analyzer.ino:330
Linduino.h
Header File for Linduino Libraries and Demo Code.
LTC6904_frequency_to_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
eeprom_read_float
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.
Definition: QuikEval_EEPROM.cpp:435
eeprom_write_int32
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.
Definition: QuikEval_EEPROM.cpp:455
step
static float step
Definition: Audio_Spectrum_Analyzer.ino:19
display_graph
static void display_graph(float data)
Definition: Audio_Spectrum_Analyzer.ino:188
adc_voltage
static float adc_voltage
Definition: DC2071AA.ino:115
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
display_menu
static void display_menu()
Definition: Audio_Spectrum_Analyzer.ino:63
LTC2484_lsb
static float LTC2484_lsb
Ideal LSB size, 5V/(2^29) for a 5V reference.
Definition: Audio_Spectrum_Analyzer.ino:23
LTC2484_code_to_voltage
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.h
LTC24XX General Library: Functions and defines for all SINC4 Delta Sigma ADCs.
MISO_TIMEOUT
const uint16_t MISO_TIMEOUT
The MISO timeout (ms)
Definition: Audio_Spectrum_Analyzer.ino:20
restore_calibration
static int8_t restore_calibration()
Read stored calibration parameters from nonvolatile EEPROM on demo board.
Definition: Audio_Spectrum_Analyzer.ino:254
LTC2484_cal_voltage
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
eeprom_write_float
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.
Definition: QuikEval_EEPROM.cpp:412
eeprom_write_int16
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.
Definition: QuikEval_EEPROM.cpp:377
LTC2484_read
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.h
QuikEval EEPROM Library.
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
EEPROM_CAL_STATUS_ADDRESS
#define EEPROM_CAL_STATUS_ADDRESS
Definition: QuikEval_EEPROM.h:58
LTC2484_EXTERNAL_INPUT
#define LTC2484_EXTERNAL_INPUT
Definition: LTC2484.h:160
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
LTC6904_ADDRESS
#define LTC6904_ADDRESS
ADR 0.
Definition: LTC6904.h:64
stop
static float stop
Definition: Audio_Spectrum_Analyzer.ino:19
LTC6904_write
uint8_t LTC6904_write(uint8_t address, uint16_t code)
Writes 2 bytes.
Definition: LTC6904.cpp:73
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
LTC2484_EOC_timeout
int8_t LTC2484_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
Checks for EOC with a specified timeout.
Definition: LTC2484.cpp:84
quikeval_SPI_connect
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
eeprom_read_int32
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.
Definition: QuikEval_EEPROM.cpp:478
UserInterface.h
read_int
int32_t read_int()
Definition: UserInterface.cpp:93
read_float
float read_float()
Definition: UserInterface.cpp:78
LTC2484_CS
#define LTC2484_CS
define the SPI CS pin
Definition: LTC2484.h:151
LTC2484_REJECTION_60HZ
#define LTC2484_REJECTION_60HZ
Definition: LTC2484.h:165
start
static float start
Definition: Audio_Spectrum_Analyzer.ino:19
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
LTC2484_offset_code
static int32_t LTC2484_offset_code
Ideal offset.
Definition: Audio_Spectrum_Analyzer.ino:24
quikeval_I2C_connect
void quikeval_I2C_connect(void)
Switch MUX to connect I2C pins to QuikEval connector.
Definition: LT_I2C.cpp:401
i
static int i
Definition: DC2430A.ino:184
loop
static void loop()
Definition: Audio_Spectrum_Analyzer.ino:34
EEPROM_CAL_KEY
#define EEPROM_CAL_KEY
Definition: QuikEval_EEPROM.h:59
LTC2484_ENABLE
#define LTC2484_ENABLE
Definition: LTC2484.h:157
adc_code
static uint32_t adc_code
Definition: DC2071AA.ino:113