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
92 {
93  '0', 'x', '0', '0', '\0'
94 }; // buffer for ASCII hex to byte conversion
96 {
97  '\0','\0','\0'
98 }; // buffer for byte to ASCII hex conversion
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;
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
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;
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 
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
215  break;
216  case 'G':
217  // IO pin high
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
288  // enable_main_I2C();
290  break;
291  case 'S':
292  // spi mode
294  // Need to send command to disable LTC4302
295  // enable_main_SPI();
297  break;
298  case 'X':
299  // axillary I2C mode - no hardware action necessary, always available.
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();
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  {
387  recording_index = 0;
388  break;
389  }
390  else // add character to recording buffer
391  {
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':
411  break;
412  case 'x':
414  break;
415  case 'X':
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 }
const byte playback
Definition: DC590B.ino:71
byte recording_mode
Definition: DC590B.ino:89
char get_char()
Definition: DC590B.ino:126
static void loop()
Definition: DC590B.ino:192
char byte_to_hex_buffer[3]
Definition: DC590B.ino:95
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
#define RECORDING_SIZE
Definition: DC590B.ino:69
Header File for Linduino Libraries and Demo Code.
void spi_write(int8_t data)
Write a data byte using the SPI hardware.
Definition: LT_SPI.cpp:176
static int i
Definition: DC590B.ino:159
char recording_buffer[RECORDING_SIZE]
Definition: DC590B.ino:99
const byte i2c_mode
Definition: DC590B.ino:75
const byte off
Definition: DC590B.ino:70
int8_t i2c_start()
Write start bit to the hardware I2C port.
Definition: LT_I2C.cpp:425
static void byte_to_hex(byte value)
Definition: DC590B.ino:107
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
#define WITH_NACK
Use with i2c_read(WITH_NACK) to read without an acknowledge.
Definition: LT_I2C.h:91
const byte i2c_auxiliary_mode
Definition: DC590B.ino:76
#define QUIKEVAL_GPIO
Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9. ...
Definition: Linduino.h:56
byte serial_mode
Definition: DC590B.ino:88
int8_t i2c_write(uint8_t data)
Send a data byte to hardware I2C port.
Definition: LT_I2C.cpp:470
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
QuikEval EEPROM Library.
const char spi_divider
Definition: DC590B.ino:85
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
const byte spi_mode
Definition: DC590B.ino:74
char hex_digits[16]
Definition: DC590B.ino:79
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
byte read_hex()
Definition: DC590B.ino:115
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
unsigned char pseudo_reset
Definition: DC590B.ino:160
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
byte recording_index
Definition: DC590B.ino:103
int8_t spi_read(int8_t data)
The data byte to be written.
Definition: LT_SPI.cpp:189
static void setup()
Definition: DC590B.ino:162
uint8_t i2c_read(int8_t ack)
Read a data byte from the hardware I2C port.
Definition: LT_I2C.cpp:491
#define MISO_TIMEOUT
Definition: DC590B.ino:66
void quikeval_I2C_init(void)
Initializes Linduino I2C port.
Definition: LT_I2C.cpp:394
void quikeval_I2C_connect(void)
Switch MUX to connect I2C pins to QuikEval connector.
Definition: LT_I2C.cpp:401
#define WITH_ACK
Use with i2c_read(WITH_ACK) to read with an acknowledge.
Definition: LT_I2C.h:90
#define QUIKEVAL_CS
QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin...
Definition: Linduino.h:57
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...
char ui_buffer[UI_BUFFER_SIZE]
char hex_to_byte_buffer[5]
Definition: DC590B.ino:91
char id_string[51]
Definition: DC590B.ino:90