| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

DC590B_enhanced.ino
Go to the documentation of this file.
1 //! @todo Review this file? Document with Doxygen? Time permitting...
2 /*
3 DC590B USB to Serial Controller
4
5 This file contains the routines to emulate the DC590B USB to Serial Converter. All commands
6 are supported except Uxxy the Write Port D bus. Added the 'D' delay ms command.
7 With this program, the Linduino can be used by the QuikEval program running on a PC
8 to communicate with QuikEval compatible demo boards.
9
10 The Kxy bit bang command uses the following pin mappings :
11 0-Linduino 2
12 1-Linduino 3
13 2-Linduino 4
14 3-Linduino 5
15 4-Linduino 6
16 5-Linduino 7
17
18
19 Copyright 2018(c) Analog Devices, Inc.
20
21 All rights reserved.
22
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions are met:
25 - Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 - Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in
29 the documentation and/or other materials provided with the
30 distribution.
31 - Neither the name of Analog Devices, Inc. nor the names of its
32 contributors may be used to endorse or promote products derived
33 from this software without specific prior written permission.
34 - The use of this software may or may not infringe the patent rights
35 of one or more patent holders. This license does not release you
36 from the requirement that you obtain separate licenses from these
37 patent holders to use this software.
38 - Use of the software either in source or binary form, must be run
39 on or directly connected to an Analog Devices Inc. component.
40
41 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
42 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
43 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
45 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
47 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
48 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 */
52
53 #include <Arduino.h>
54 #include <stdint.h>
55 #include "Linduino.h"
56 #include "QuikEval_EEPROM.h"
57 #include "LT_SPI.h"
58 #include "UserInterface.h"
59 #include "LT_I2C.h"
60 #include <Wire.h>
61 #include <SPI.h>
62
63 // define a "spoof_board_id" to force the "i" command to return a specific ID string.
64 // This can be used to fake QuikEval into loading a specific GUI, even if the ID EEPROM
65 // is not present. A few examples are below. NOT defining will result in normal behavior,
66 // "i" command will cause EEPROM to be read.
67
68 //#define spoof_board_id "LTC4261,Cls,D4261,01,01,DC,DC998A,--------------"
69 //#define spoof_board_id "LTC2440,Cls,D2440,01,01,DC,DC570,---------------"
70 //#define spoof_board_id "LTC2946,Cls,D2946,01,01,DC,DC2156A,-------------"
71
72 // timeouts
73 #define READ_TIMEOUT 20
74 #define MISO_TIMEOUT 1000
75
76 // recording mode constants
77 #define RECORDING_SIZE 50
78 const byte off = 0;
79 const byte playback = 1;
80
81 // serial mode constants
82 const byte spi_mode = 0;
83 const byte i2c_mode = 1;
84 const byte i2c_auxiliary_mode = 2;
85
86 // hex conversion constants
87 char hex_digits[16]=
88 {
89 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
90 };
91
92 // spi clock divider
93 const char spi_divider = SPI_CLOCK_DIV32; // configure the spi port for 4MHz SCK (500kHz@div32??)
94
95 // global variables
96 byte serial_mode = spi_mode; // current serial mode
97 byte recording_mode = off; // recording mode off
98 ////////////////////////////////////////////////////
99 // CHANGED MAJOR VERSION to 2 FOR ENHANCED VERSION//
100 ////////////////////////////////////////////////////
101 char id_string[51]="USBSPI,PIC,02,01,DC,DC590,----------------------\n\0"; // id string
102 char hex_to_byte_buffer[5]=
103 {
104 '0', 'x', '0', '0', '\0'
105 }; // buffer for ASCII hex to byte conversion
106 char byte_to_hex_buffer[3]=
107 {
108 '\0','\0','\0'
109 }; // buffer for byte to ASCII hex conversion
110 char recording_buffer[RECORDING_SIZE]=
111 {
112 '\0'
113 }; // buffer for saving recording loop
114 byte recording_index = 0; // index to the recording buffer
115
116 char get_char();
117
118 void byte_to_hex(byte value)
119 // convert a byte to two hex characters
120 {
121 byte_to_hex_buffer[0]=hex_digits[value>>4]; // get upper nibble
122 byte_to_hex_buffer[1]=hex_digits[(value & 0x0F)]; // get lower nibble
123 byte_to_hex_buffer[2]='\0'; // add NULL at end
124 }
125
126 byte read_hex()
127 // read 2 hex characters from the serial buffer and convert
128 // them to a byte
129 {
130 byte data;
131 hex_to_byte_buffer[2]=get_char();
132 hex_to_byte_buffer[3]=get_char();
133 data = strtol(hex_to_byte_buffer, NULL, 0);
134 return(data);
135 }
136
137 char get_char()
138 // get the next character either from the serial port
139 // or the recording buffer
140 {
141 char command='\0';
142 if (recording_mode != playback)
143 {
144 // read a command from the serial port
145 while (Serial.available() <= 0);
146 return(Serial.read());
147 }
148 else
149 {
150 // read a command from the recording buffer
151 if (recording_index < RECORDING_SIZE)
152 {
153 command = recording_buffer[recording_index++];
154 // disregard loop commands during playback
155 if (command == 'w') command='\1';
156 if (command == 't') command='\1';
157 if (command == 'v') command='\1';
158 if (command == 'u') command='\1';
159 }
160 else
161 command = '\0';
162 if (command == '\0')
163 {
164 recording_index = 0;
165 recording_mode = off;
166 }
167 return(command);
168 }
169 }
170 int i = 0;
171 unsigned char pseudo_reset = 0;
172
173 void setup()
174 // Setup the program
175 {
176 digitalWrite(QUIKEVAL_GPIO, LOW);
177 digitalWrite(QUIKEVAL_CS, HIGH);
178 digitalWrite(2, LOW);
179 digitalWrite(3, LOW);
180 digitalWrite(4, LOW);
181 digitalWrite(5, LOW);
182 digitalWrite(6, LOW);
183 digitalWrite(7, LOW);
184 pinMode(QUIKEVAL_GPIO, OUTPUT);
185 pinMode(QUIKEVAL_CS, OUTPUT);
186 pinMode(2, OUTPUT);
187 pinMode(3, OUTPUT);
188 pinMode(4, OUTPUT);
189 pinMode(5, OUTPUT);
190 pinMode(6, OUTPUT);
191 pinMode(7, OUTPUT);
192
193 Serial.begin(115200); // enable the serial port for 115200 baud
194
195 quikeval_SPI_init();
196 quikeval_SPI_connect(); // Connect SPI to main data port
197
198 quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz SCK
199 Serial.print("hello\n");
200 Serial.flush();
201 }
202
203 void loop()
204 {
205 byte tx_data;
206 byte rx_data;
207 byte pin_value;
208 int delay_value;
209 int pin;
210 char command;
211 int byte_count;
212 long delay_count;
213 command = get_char();
214 switch (command)
215 {
216 case 'D':
217 // delay milliseconds
218 delay_value = read_hex();
219 delay_value<<=8;
220 delay_value|=read_hex();
221 delay(delay_value);
222 break;
223 case 'g':
224 // IO pin low
225 output_low(QUIKEVAL_GPIO);
226 break;
227 case 'G':
228 // IO pin high
229 output_high(QUIKEVAL_GPIO);
230 break;
231 case 'H': // wait for MISO to go high with a timeout
232 delay_count = 0;
233 while (1)
234 {
235 if (input(MISO)==1) break; // MISO is high so quit
236 if (delay_count++>MISO_TIMEOUT)
237 {
238 //Serial.print('T'); // timeout occurred. Print 'T'
239 break;
240 }
241 else delay(1);
242 }
243 break;
244 case 'i':
245 // send controller id string
246 pseudo_reset = 0;
247 Serial.print(id_string);
248 Serial.print('\0');
249 Serial.flush();
250 break;
251 case 'I':
252 #ifdef spoof_board_id
253 Serial.print(spoof_board_id);
254 Serial.print('\0');
255 Serial.print('\0');
256 #else
257 // get controller id string
258 quikeval_SPI_connect(); // Connect SPI to main data port
259 pseudo_reset = 0;
260 byte_count = read_quikeval_id_string(&ui_buffer[0]);
261 if (byte_count!=0)
262 {
263 Serial.print(ui_buffer);
264 Serial.print("\n\0");
265 Serial.flush();
266 }
267 #endif
268 break;
269 case 'K':
270 // Bang pin. The pin assignments are :
271 // 0: PIND2, Arduino 2
272 // 1: PIND3, Arduino 3
273 // 2: PIND4, Arduino 4
274 // 3: PIND5, Arduino 5
275 // 4: PIND6, Arduino 6
276 // 5: PIND6, Arduino 7
277
278 pin_value = get_char(); // read the value
279 // pin = get_char()-0x30; // read the pin
280 pin = get_char(); // read the pin
281 // if (pin_value == '0') digitalWrite(pin+2, LOW);
282 // else digitalWrite(pin+2, HIGH);
283
284 digitalWrite(pin-0x30+2, pin_value == '0' ? LOW : HIGH);
285 break;
286 case 'k':
287 // Get pin state. The digial pin assignments are the same as for 'K',
288 // Analog pin mappings as follows:
289 // 6: Analog A0 (read only)
290 // 7: Analog A1 (read only)
291 // 8: Analog A2 (read only)
292 // 9: Analog A3 (read only)
293 pin = get_char(); // read the pin
294 if (pin <= '5')
295 {
296 Serial.print(digitalRead(pin-0x30+2));
297 }
298 else if (pin == 'C') // To read MISO pin
299 {
300 int val;
301 //pin = read_hex();
302 val = digitalRead(12);
303 byte_to_hex(val);
304 Serial.print(byte_to_hex_buffer);
305 }
306 else
307 {
308 int val = analogRead(pin - '6');
309 if (val < 10)
310 {
311 Serial.print("000");
312 }
313 else if (val < 100)
314 {
315 Serial.print("00");
316 }
317 else if (val < 1000)
318 {
319 Serial.print("0");
320 }
321 Serial.print(val);
322 break;
323 }
324 break;
325 case 'j':
326 // Set pin mode. The pin assignments are the same as for 'K':
327 pin_value = get_char(); // read the value
328 pin = get_char(); // read the pin
329 pinMode(pin-0x30+2, pin_value == '0' ? INPUT : OUTPUT);
330 break;
331 case 'L':
332 // wait for MISO to go low with a timeout
333 delay_count = 0;
334 while (1)
335 {
336 if (input(MISO)==0) break; // MISO is low so quit
337 if (delay_count++>MISO_TIMEOUT)
338 {
339 //Serial.print('T'); // timeout occurred. Print 'T'
340 break;
341 }
342 else delay(1);
343 }
344 break;
345 case 'M':
346 // change the serial mode
347 command = get_char();
348 switch (command)
349 {
350 case 'I':
351 // I2C mode
352 serial_mode = i2c_mode;
353 // enable_main_I2C();
354 quikeval_I2C_connect();
355 break;
356 case 'S':
357 // spi mode
358 serial_mode = spi_mode;
359 // Need to send command to disable LTC4302
360 // enable_main_SPI();
361 quikeval_SPI_connect();
362 break;
363 case 'X': // axillary I2C mode - no hardware action necessary, always available.
364 serial_mode = i2c_auxiliary_mode;
365 quikeval_SPI_connect();
366 break;
367 case '0': // New for Enhanced version - set SPI mode on the fly. (Mainly for Altera SPI-Avalon MM bridge)
368 SPI.setDataMode(SPI_MODE0);
369 break;
370 case '1':
371 SPI.setDataMode(SPI_MODE1);
372 break;
373 case '2':
374 SPI.setDataMode(SPI_MODE2);
375 break;
376 case '3':
377 SPI.setDataMode(SPI_MODE3);
378 break;
379 case 'a':
380 SPI.setClockDivider(SPI_CLOCK_DIV2);
381 break;
382 case 'b':
383 SPI.setClockDivider(SPI_CLOCK_DIV4);
384 break;
385 case 'c':
386 SPI.setClockDivider(SPI_CLOCK_DIV8);
387 break;
388 case 'd':
389 SPI.setClockDivider(SPI_CLOCK_DIV16);
390 break;
391 case 'e':
392 SPI.setClockDivider(SPI_CLOCK_DIV32);
393 break;
394 case 'f':
395 SPI.setClockDivider(SPI_CLOCK_DIV64);
396 break;
397 case 'g':
398 SPI.setClockDivider(SPI_CLOCK_DIV128);
399 break;
400 }
401 //delay(1);
402 break;
403 case 'p':
404 // I2C stop
405 // Switching BACK to the i2c_stop() function call. See Rev 1405, LT_i2c.cpp, Linduino One branch
406 if (serial_mode!=spi_mode) i2c_stop(); // TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // I2C stop //i2c_stop();
407 // if(serial_mode == i2c_auxiliary_mode) i2c_stop();
408 break;
409 case 'P':
410 // ping
411 Serial.print('P');
412 delay(5);
413 break;
414 case 'Q':
415 // Read byte in I2C mode only. Add ACK
416 switch (serial_mode)
417 {
418 case i2c_mode:
419 rx_data = i2c_read(WITH_ACK);
420 byte_to_hex(rx_data);
421 Serial.print(byte_to_hex_buffer);
422 break;
423 case i2c_auxiliary_mode:
424 rx_data = i2c_read(WITH_ACK);
425 byte_to_hex(rx_data);
426 Serial.print(byte_to_hex_buffer);
427 break;
428 }
429 break;
430
431 case 'r':
432 rx_data = spi_read(0);
433 byte_to_hex(rx_data);
434 Serial.print(byte_to_hex_buffer);
435 break;
436
437 case 'R':
438 // Read byte, add NACK in I2C mode
439 switch (serial_mode)
440 {
441 case spi_mode:
442 rx_data = spi_read(0);
443 byte_to_hex(rx_data);
444 Serial.print(byte_to_hex_buffer);
445 break;
446 case i2c_mode:
447 rx_data = i2c_read(WITH_NACK);
448 byte_to_hex(rx_data);
449 Serial.print(byte_to_hex_buffer);
450 break;
451 case i2c_auxiliary_mode:
452 rx_data = i2c_read(WITH_NACK);
453 byte_to_hex(rx_data);
454 Serial.print(byte_to_hex_buffer);
455 break;
456 }
457 break;
458 case 's': // I2C start
459 if (serial_mode == i2c_mode) i2c_start();
460 if (serial_mode == i2c_auxiliary_mode) i2c_start();
461 break;
462 case 'S': // send byte
463 tx_data = read_hex();
464 switch (serial_mode)
465 {
466 case spi_mode:
467 spi_write(tx_data);
468 break;
469 case i2c_mode:
470 if (i2c_write(tx_data)==1) Serial.print('N');
471 break;
472 case i2c_auxiliary_mode:
473 if (i2c_write(tx_data)==1) Serial.print('N');
474 break;
475 }
476 break;
477 case 't': // recording loop
478 recording_index = 0;
479 do
480 {
481 command = get_char();
482 if (command == 'u') // stop recording
483 {
484 recording_buffer[recording_index]='\0';
485 recording_index = 0;
486 break;
487 }
488 else // add character to recording buffer
489 {
490 if (recording_index < RECORDING_SIZE) recording_buffer[recording_index++]=command;
491 }
492 }
493 while (1);
494 break;
495 case 'T': // transceive byte
496 tx_data = read_hex();
497 if (serial_mode == spi_mode)
498 {
499 rx_data = spi_read(tx_data);
500 byte_to_hex(rx_data);
501 Serial.print(byte_to_hex_buffer);
502 }
503 break;
504 case 'v': // echo recording loop
505 Serial.print(recording_buffer);
506 break;
507 case 'w':
508 recording_mode = playback;
509 break;
510 case 'x':
511 output_low(QUIKEVAL_CS);
512 break;
513 case 'X':
514 output_high(QUIKEVAL_CS);
515 break;
516 case 'Z': // line feed
517 Serial.print('\n');
518 Serial.flush();
519 break;
520 case 0x80: // Reset
521 if (pseudo_reset == 0)
522 {
523 delay(500); // The delay is needed for older GUI's
524 Serial.print("hello\n");
525 pseudo_reset = 1;
526 }
527 break;
528 }
529 }
recording_buffer
char recording_buffer[RECORDING_SIZE]
Definition: DC590B_enhanced.ino:110
id_string
char id_string[51]
Definition: DC590B_enhanced.ino:101
i2c_auxiliary_mode
const byte i2c_auxiliary_mode
Definition: DC590B_enhanced.ino:84
output_high
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
byte_to_hex
static void byte_to_hex(byte value)
Definition: DC590B_enhanced.ino:118
i
static int i
Definition: DC590B_enhanced.ino:170
Linduino.h
Header File for Linduino Libraries and Demo Code.
spi_write
void spi_write(int8_t data)
Write a data byte using the SPI hardware.
Definition: LT_SPI.cpp:176
serial_mode
byte serial_mode
Definition: DC590B_enhanced.ino:96
playback
const byte playback
Definition: DC590B_enhanced.ino:79
i2c_stop
void i2c_stop()
Write stop bit to the hardware I2C port.
Definition: LT_I2C.cpp:462
i2c_start
int8_t i2c_start()
Write start bit to the hardware I2C port.
Definition: LT_I2C.cpp:425
byte_to_hex_buffer
char byte_to_hex_buffer[3]
Definition: DC590B_enhanced.ino:106
recording_index
byte recording_index
Definition: DC590B_enhanced.ino:114
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
WITH_NACK
#define WITH_NACK
Use with i2c_read(WITH_NACK) to read without an acknowledge.
Definition: LT_I2C.h:91
pseudo_reset
unsigned char pseudo_reset
Definition: DC590B_enhanced.ino:171
i2c_mode
const byte i2c_mode
Definition: DC590B_enhanced.ino:83
setup
static void setup()
Definition: DC590B_enhanced.ino:173
QUIKEVAL_GPIO
#define QUIKEVAL_GPIO
Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9. ...
Definition: Linduino.h:56
read_hex
byte read_hex()
Definition: DC590B_enhanced.ino:126
i2c_write
int8_t i2c_write(uint8_t data)
Send a data byte to hardware I2C port.
Definition: LT_I2C.cpp:470
hex_digits
char hex_digits[16]
Definition: DC590B_enhanced.ino:87
output_low
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
QuikEval_EEPROM.h
QuikEval EEPROM Library.
input
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
spi_mode
const byte spi_mode
Definition: DC590B_enhanced.ino:82
get_char
char get_char()
Definition: DC590B_enhanced.ino:137
spi_divider
const char spi_divider
Definition: DC590B_enhanced.ino:93
loop
static void loop()
Definition: DC590B_enhanced.ino:203
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
hex_to_byte_buffer
char hex_to_byte_buffer[5]
Definition: DC590B_enhanced.ino:102
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
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
UserInterface.h
spi_read
int8_t spi_read(int8_t data)
The data byte to be written.
Definition: LT_SPI.cpp:189
MISO_TIMEOUT
#define MISO_TIMEOUT
Definition: DC590B_enhanced.ino:74
RECORDING_SIZE
#define RECORDING_SIZE
Definition: DC590B_enhanced.ino:77
i2c_read
uint8_t i2c_read(int8_t ack)
Read a data byte from the hardware I2C port.
Definition: LT_I2C.cpp:491
off
const byte off
Definition: DC590B_enhanced.ino:78
quikeval_I2C_init
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
quikeval_I2C_connect
void quikeval_I2C_connect(void)
Switch MUX to connect I2C pins to QuikEval connector.
Definition: LT_I2C.cpp:401
WITH_ACK
#define WITH_ACK
Use with i2c_read(WITH_ACK) to read with an acknowledge.
Definition: LT_I2C.h:90
QUIKEVAL_CS
#define QUIKEVAL_CS
QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin...
Definition: Linduino.h:57
read_quikeval_id_string
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...
Definition: QuikEval_EEPROM.cpp:77
ui_buffer
char ui_buffer[UI_BUFFER_SIZE]
Definition: UserInterface.cpp:46
recording_mode
byte recording_mode
Definition: DC590B_enhanced.ino:97