| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

DC590B.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
64 // timeouts
65 #define READ_TIMEOUT 20
66 #define MISO_TIMEOUT 1000
67
68 // recording mode constants
69 #define RECORDING_SIZE 50
70 const byte off = 0;
71 const byte playback = 1;
72
73 // serial mode constants
74 const byte spi_mode = 0;
75 const byte i2c_mode = 1;
76 const byte i2c_auxiliary_mode = 2;
77
78 // hex conversion constants
79 char hex_digits[16]=
80 {
81 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
82 };
83
84 // spi clock divider
85 const char spi_divider = SPI_CLOCK_DIV32; // configure the spi port for 4MHz SCK (500kHz@div32??)
86
87 // global variables
88 byte serial_mode = spi_mode; // current serial mode
89 byte recording_mode = off; // recording mode off
90 char id_string[51]="USBSPI,PIC,01,01,DC,DC590,----------------------\n\0"; // id string
91 char hex_to_byte_buffer[5]=
92 {
93 '0', 'x', '0', '0', '\0'
94 }; // buffer for ASCII hex to byte conversion
95 char byte_to_hex_buffer[3]=
96 {
97 '\0','\0','\0'
98 }; // buffer for byte to ASCII hex conversion
99 char recording_buffer[RECORDING_SIZE]=
100 {
101 '\0'
102 }; // buffer for saving recording loop
103 byte recording_index = 0; // index to the recording buffer
104
105 char get_char();
106
107 void byte_to_hex(byte value)
108 // convert a byte to two hex characters
109 {
110 byte_to_hex_buffer[0]=hex_digits[value>>4]; // get upper nibble
111 byte_to_hex_buffer[1]=hex_digits[(value & 0x0F)]; // get lower nibble
112 byte_to_hex_buffer[2]='\0'; // add NULL at end
113 }
114
115 byte read_hex()
116 // read 2 hex characters from the serial buffer and convert
117 // them to a byte
118 {
119 byte data;
120 hex_to_byte_buffer[2]=get_char();
121 hex_to_byte_buffer[3]=get_char();
122 data = strtol(hex_to_byte_buffer, NULL, 0);
123 return(data);
124 }
125
126 char get_char()
127 // get the next character either from the serial port
128 // or the recording buffer
129 {
130 char command='\0';
131 if (recording_mode != playback)
132 {
133 // read a command from the serial port
134 while (Serial.available() <= 0);
135 return(Serial.read());
136 }
137 else
138 {
139 // read a command from the recording buffer
140 if (recording_index < RECORDING_SIZE)
141 {
142 command = recording_buffer[recording_index++];
143 // disregard loop commands during playback
144 if (command == 'w') command='\1';
145 if (command == 't') command='\1';
146 if (command == 'v') command='\1';
147 if (command == 'u') command='\1';
148 }
149 else
150 command = '\0';
151 if (command == '\0')
152 {
153 recording_index = 0;
154 recording_mode = off;
155 }
156 return(command);
157 }
158 }
159 int i = 0;
160 unsigned char pseudo_reset = 0;
161
162 void setup()
163 // Setup the program
164 {
165 digitalWrite(QUIKEVAL_GPIO, LOW);
166 digitalWrite(QUIKEVAL_CS, HIGH);
167 digitalWrite(2, LOW);
168 digitalWrite(3, LOW);
169 digitalWrite(4, LOW);
170 digitalWrite(5, LOW);
171 digitalWrite(6, LOW);
172 digitalWrite(7, LOW);
173 pinMode(QUIKEVAL_GPIO, OUTPUT);
174 pinMode(QUIKEVAL_CS, OUTPUT);
175 pinMode(2, OUTPUT);
176 pinMode(3, OUTPUT);
177 pinMode(4, OUTPUT);
178 pinMode(5, OUTPUT);
179 pinMode(6, OUTPUT);
180 pinMode(7, OUTPUT);
181
182 Serial.begin(115200); // enable the serial port for 115200 baud
183
184 quikeval_SPI_init();
185 quikeval_SPI_connect(); // Connect SPI to main data port
186
187 quikeval_I2C_init(); // Configure the EEPROM I2C port for 100kHz SCK
188 Serial.print("hello\n");
189 Serial.flush();
190 }
191
192 void loop()
193 {
194 byte tx_data;
195 byte rx_data;
196 byte pin_value;
197 int delay_value;
198 int pin;
199 char command;
200 int byte_count;
201 long delay_count;
202 command = get_char();
203 switch (command)
204 {
205 case 'D':
206 // delay milliseconds
207 delay_value = read_hex();
208 delay_value<<=8;
209 delay_value|=read_hex();
210 delay(delay_value);
211 break;
212 case 'g':
213 // IO pin low
214 output_low(QUIKEVAL_GPIO);
215 break;
216 case 'G':
217 // IO pin high
218 output_high(QUIKEVAL_GPIO);
219 break;
220 case 'H': // wait for MISO to go high with a timeout
221 delay_count = 0;
222 while (1)
223 {
224 if (input(MISO)==1) break; // MISO is high so quit
225 if (delay_count++>MISO_TIMEOUT)
226 {
227 //Serial.print('T'); // timeout occurred. Print 'T'
228 break;
229 }
230 else delay(1);
231 }
232 break;
233 case 'i':
234 // send controller id string
235 pseudo_reset = 0;
236 Serial.print(id_string);
237 Serial.print('\0');
238 Serial.flush();
239 break;
240 case 'I':
241 // get controller id string
242 quikeval_SPI_connect(); // Connect SPI to main data port
243 pseudo_reset = 0;
244 byte_count = read_quikeval_id_string(&ui_buffer[0]);
245 if (byte_count!=0)
246 {
247 Serial.print(ui_buffer);
248 //Serial.print("LTC4261,Cls,D4261,01,01,DC,DC998A,--------------\n\0");
249 Serial.print('\0');
250 Serial.flush();
251 }
252 break;
253 case 'K':
254 // Bang pin. The pin assignments are :
255 // 0: PIND2, Arduino 2
256 // 1: PIND3, Arduino 3
257 // 2: PIND4, Arduino 4
258 // 3: PIND5, Arduino 5
259 // 4: PIND6, Arduino 6
260 // 5: PIND6, Arduino 7
261 pin_value = get_char(); // read the value
262 pin = get_char()-0x30; // read the pin
263 if (pin_value == '0') digitalWrite(pin+2, LOW);
264 else digitalWrite(pin+2, HIGH);
265 break;
266 case 'L':
267 // wait for MISO to go low with a timeout
268 delay_count = 0;
269 while (1)
270 {
271 if (input(MISO)==0) break; // MISO is low so quit
272 if (delay_count++>MISO_TIMEOUT)
273 {
274 //Serial.print('T'); // timeout occurred. Print 'T'
275 break;
276 }
277 else delay(1);
278 }
279 break;
280 case 'M':
281 // change the serial mode
282 command = get_char();
283 switch (command)
284 {
285 case 'I':
286 // I2C mode
287 serial_mode = i2c_mode;
288 // enable_main_I2C();
289 quikeval_I2C_connect();
290 break;
291 case 'S':
292 // spi mode
293 serial_mode = spi_mode;
294 // Need to send command to disable LTC4302
295 // enable_main_SPI();
296 quikeval_SPI_connect();
297 break;
298 case 'X':
299 // axillary I2C mode - no hardware action necessary, always available.
300 serial_mode = i2c_auxiliary_mode;
301 quikeval_SPI_connect();
302 break;
303 }
304 //delay(1);
305 break;
306 case 'p':
307 // I2C stop
308 if (serial_mode!=spi_mode) TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // I2C stop //i2c_stop();
309 // if(serial_mode == i2c_auxiliary_mode) i2c_stop();
310 break;
311 case 'P':
312 // ping
313 Serial.print('P');
314 delay(5);
315 break;
316 case 'Q':
317 // Read byte in I2C mode only. Add ACK
318 switch (serial_mode)
319 {
320 case i2c_mode:
321 rx_data = i2c_read(WITH_ACK);
322 byte_to_hex(rx_data);
323 Serial.print(byte_to_hex_buffer);
324 break;
325 case i2c_auxiliary_mode:
326 rx_data = i2c_read(WITH_ACK);
327 byte_to_hex(rx_data);
328 Serial.print(byte_to_hex_buffer);
329 break;
330 }
331 break;
332
333 case 'r':
334 rx_data = spi_read(0);
335 byte_to_hex(rx_data);
336 Serial.print(byte_to_hex_buffer);
337 break;
338
339 case 'R':
340 // Read byte, add NACK in I2C mode
341 switch (serial_mode)
342 {
343 case spi_mode:
344 rx_data = spi_read(0);
345 byte_to_hex(rx_data);
346 Serial.print(byte_to_hex_buffer);
347 break;
348 case i2c_mode:
349 rx_data = i2c_read(WITH_NACK);
350 byte_to_hex(rx_data);
351 Serial.print(byte_to_hex_buffer);
352 break;
353 case i2c_auxiliary_mode:
354 rx_data = i2c_read(WITH_NACK);
355 byte_to_hex(rx_data);
356 Serial.print(byte_to_hex_buffer);
357 break;
358 }
359 break;
360 case 's': // I2C start
361 if (serial_mode == i2c_mode) i2c_start();
362 if (serial_mode == i2c_auxiliary_mode) i2c_start();
363 break;
364 case 'S': // send byte
365 tx_data = read_hex();
366 switch (serial_mode)
367 {
368 case spi_mode:
369 spi_write(tx_data);
370 break;
371 case i2c_mode:
372 if (i2c_write(tx_data)==1) Serial.print('N');
373 break;
374 case i2c_auxiliary_mode:
375 if (i2c_write(tx_data)==1) Serial.print('N');
376 break;
377 }
378 break;
379 case 't': // recording loop
380 recording_index = 0;
381 do
382 {
383 command = get_char();
384 if (command == 'u') // stop recording
385 {
386 recording_buffer[recording_index]='\0';
387 recording_index = 0;
388 break;
389 }
390 else // add character to recording buffer
391 {
392 if (recording_index < RECORDING_SIZE) recording_buffer[recording_index++]=command;
393 }
394 }
395 while (1);
396 break;
397 case 'T': // transceive byte
398 tx_data = read_hex();
399 if (serial_mode == spi_mode)
400 {
401 rx_data = spi_read(tx_data);
402 byte_to_hex(rx_data);
403 Serial.print(byte_to_hex_buffer);
404 }
405 break;
406 case 'v': // echo recording loop
407 Serial.print(recording_buffer);
408 break;
409 case 'w':
410 recording_mode = playback;
411 break;
412 case 'x':
413 output_low(QUIKEVAL_CS);
414 break;
415 case 'X':
416 output_high(QUIKEVAL_CS);
417 break;
418 case 'Z': // line feed
419 Serial.print('\n');
420 Serial.flush();
421 break;
422 case 0x80: // Reset
423 if (pseudo_reset == 0)
424 {
425 delay(500); // The delay is needed for older GUI's
426 Serial.print("hello\n");
427 pseudo_reset = 1;
428 }
429 break;
430 }
431 }
playback
const byte playback
Definition: DC590B.ino:71
recording_mode
byte recording_mode
Definition: DC590B.ino:89
get_char
char get_char()
Definition: DC590B.ino:126
loop
static void loop()
Definition: DC590B.ino:192
byte_to_hex_buffer
char byte_to_hex_buffer[3]
Definition: DC590B.ino:95
output_high
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
RECORDING_SIZE
#define RECORDING_SIZE
Definition: DC590B.ino:69
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
i
static int i
Definition: DC590B.ino:159
recording_buffer
char recording_buffer[RECORDING_SIZE]
Definition: DC590B.ino:99
i2c_mode
const byte i2c_mode
Definition: DC590B.ino:75
off
const byte off
Definition: DC590B.ino:70
i2c_start
int8_t i2c_start()
Write start bit to the hardware I2C port.
Definition: LT_I2C.cpp:425
byte_to_hex
static void byte_to_hex(byte value)
Definition: DC590B.ino:107
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
i2c_auxiliary_mode
const byte i2c_auxiliary_mode
Definition: DC590B.ino:76
QUIKEVAL_GPIO
#define QUIKEVAL_GPIO
Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9. ...
Definition: Linduino.h:56
serial_mode
byte serial_mode
Definition: DC590B.ino:88
i2c_write
int8_t i2c_write(uint8_t data)
Send a data byte to hardware I2C port.
Definition: LT_I2C.cpp:470
output_low
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
QuikEval_EEPROM.h
QuikEval EEPROM Library.
spi_divider
const char spi_divider
Definition: DC590B.ino:85
input
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
spi_mode
const byte spi_mode
Definition: DC590B.ino:74
hex_digits
char hex_digits[16]
Definition: DC590B.ino:79
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
read_hex
byte read_hex()
Definition: DC590B.ino:115
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
pseudo_reset
unsigned char pseudo_reset
Definition: DC590B.ino:160
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
recording_index
byte recording_index
Definition: DC590B.ino:103
UserInterface.h
spi_read
int8_t spi_read(int8_t data)
The data byte to be written.
Definition: LT_SPI.cpp:189
setup
static void setup()
Definition: DC590B.ino:162
i2c_read
uint8_t i2c_read(int8_t ack)
Read a data byte from the hardware I2C port.
Definition: LT_I2C.cpp:491
MISO_TIMEOUT
#define MISO_TIMEOUT
Definition: DC590B.ino:66
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
hex_to_byte_buffer
char hex_to_byte_buffer[5]
Definition: DC590B.ino:91
id_string
char id_string[51]
Definition: DC590B.ino:90