| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

platform_drivers.cpp
Go to the documentation of this file.
1 /***************************************************************************//**
2 * @file platform_drivers.c
3 * @brief Implementation of Generic Platform Drivers.
4 * @author DBogdan (dragos.bogdan@analog.com)
5 ********************************************************************************
6 * Copyright 2017(c) Analog Devices, Inc.
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * - Neither the name of Analog Devices, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 * - The use of this software may or may not infringe the patent rights
22 * of one or more patent holders. This license does not release you
23 * from the requirement that you obtain separate licenses from these
24 * patent holders to use this software.
25 * - Use of the software either in source or binary form, must be run
26 * on or directly connected to an Analog Devices Inc. component.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
30 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *******************************************************************************/
39
40 /******************************************************************************/
41 /***************************** Include Files **********************************/
42 /******************************************************************************/
43 #include <Arduino.h>
44 #include <stdint.h>
45 #include <Linduino.h>
46 #include <SPI.h>
47 #include <Wire.h>
48 #include "platform_drivers.h"
49
50 /******************************************************************************/
51 /************************ Functions Definitions *******************************/
52 /******************************************************************************/
53
54 /**
55 * @brief Initialize the I2C communication peripheral.
56 * @param desc - The I2C descriptor.
57 * @param init_param - The structure that contains the I2C parameters.
58 * @return SUCCESS in case of success, FAILURE otherwise.
59 */
60 int32_t i2c_init(i2c_desc **desc,
61 const struct i2c_init_param *param)
62 {
63 // Create the i2c description object for the device
64 i2c_desc * new_desc = (i2c_desc*) malloc(sizeof(*new_desc));
65 new_desc->type = param->type;
66 new_desc->id = param->id;
67 new_desc->max_speed_hz = param->max_speed_hz;
68 new_desc->slave_address = param->slave_address;
69
70 *desc = new_desc;
71
72 // Set the mux to use I2C
73 quikeval_set_mux(MUX_I2C);
74
75 // Enable the I2C Wire functionality
76 Wire_Connect();
77
78 // Set clock speed
79 Wire.setClock(new_desc->max_speed_hz);
80
81 return SUCCESS;
82 }
83
84 /**
85 * @brief Free the resources allocated by i2c_init().
86 * @param desc - The I2C descriptor.
87 * @return SUCCESS in case of success, FAILURE otherwise.
88 */
89 int32_t i2c_remove(i2c_desc *desc)
90 {
91 return SUCCESS;
92 }
93
94 /**
95 * @brief Write data to a slave device.
96 * @param desc - The I2C descriptor.
97 * @param data - Buffer that stores the transmission data.
98 * @param bytes_number - Number of bytes to write.
99 * @param stop_bit - Stop condition control.
100 * Example: 0 - A stop condition will not be generated;
101 * 1 - A stop condition will be generated.
102 * @return SUCCESS in case of success, FAILURE otherwise.
103 */
104 int32_t i2c_write(i2c_desc *desc,
105 uint8_t *data,
106 uint8_t bytes_number,
107 uint8_t stop_bit)
108 {
109 return Wire_Write(desc->slave_address, data, bytes_number, stop_bit);
110 }
111
112 /**
113 * @brief Read data from a slave device.
114 * @param desc - The I2C descriptor.
115 * @param data - Buffer that will store the received data.
116 * @param bytes_number - Number of bytes to read.
117 * @param stop_bit - Stop condition control.
118 * Example: 0 - A stop condition will not be generated;
119 * 1 - A stop condition will be generated.
120 * @return SUCCESS in case of success, FAILURE otherwise.
121 */
122 int32_t i2c_read(i2c_desc *desc,
123 uint8_t *data,
124 uint8_t bytes_number,
125 uint8_t stop_bit)
126 {
127 return Wire_Read(desc->slave_address, data, bytes_number, stop_bit);
128 }
129
130
131 // Converts 1-3 into arduino SPI codes
132 const uint8_t arduino_spi_modes[4] = {
133 SPI_MODE0, //0x00, //SPI_MODE0
134 SPI_MODE1, //0x04, //SPI_MODE1
135 SPI_MODE2, //0x08, //SPI_MODE2
136 SPI_MODE3 //0x0C //SPI_MODE3
137 };
138
139
140
141 /**
142 * @brief Initialize the SPI communication peripheral.
143 * @param desc - The SPI descriptor.
144 * @param init_param - The structure that contains the SPI parameters.
145 * @return SUCCESS in case of success, FAILURE otherwise.
146 */
147 int32_t spi_init(spi_desc **desc,
148 const struct spi_init_param *param)
149 {
150 // Create the spi description object for the device
151 spi_desc * new_desc = (spi_desc*) malloc(sizeof(*new_desc));
152 new_desc->chip_select = param->chip_select;
153 new_desc->mode = param->mode;
154 new_desc->max_speed_hz = param->max_speed_hz;
155
156 *desc = new_desc;
157
158 // Set the Quikeval mux pin to use SPI
159 quikeval_set_mux(MUX_SPI);
160
161 // Get SPI initialization settings from the description
162 uint8_t spi_mode = arduino_spi_modes[new_desc->mode];
163 uint32_t spi_speed = new_desc->max_speed_hz;
164
165 // Create initialization object
166 SPISettings * spi_settings = new SPISettings(spi_speed, MSBFIRST, spi_mode);
167
168 // Set the SPI bus to use our settings
169 SPI.beginTransaction(*spi_settings);
170 SPI.endTransaction();
171
172 // Connect to the bus
173 SPI.begin();
174
175 // Pull Chip Select High
176 output_high(new_desc->chip_select);
177
178 return SUCCESS;
179 }
180
181 /**
182 * @brief Free the resources allocated by spi_init().
183 * @param desc - The SPI descriptor.
184 * @return SUCCESS in case of success, FAILURE otherwise.
185 */
186 int32_t spi_remove(spi_desc *desc)
187 {
188 SPI.end();
189
190 return SUCCESS;
191 }
192
193 /**
194 * @brief Write and read data to/from SPI.
195 * @param desc - The SPI descriptor.
196 * @param data - The buffer with the transmitted/received data.
197 * @param bytes_number - Number of bytes to write/read.
198 * @return SUCCESS in case of success, FAILURE otherwise.
199 */
200 int32_t spi_write_and_read(spi_desc *desc,
201 uint8_t *data,
202 uint8_t bytes_number)
203 {
204 // Set chip select
205 uint8_t id = desc->chip_select;
206
207 // transfer & read arrays
208 uint8_t tx[bytes_number];
209 uint8_t rx[bytes_number];
210
211 // Copy data to tx
212 for(int i = 0; i < bytes_number; i++)
213 {
214 tx[i] = data[i];
215 }
216
217 // if(false)
218 // {
219 // Serial.print(F("SPI writing: "));
220 // Serial.print(tx[0], HEX);
221 // Serial.print(tx[1], HEX);
222 // Serial.println(tx[2], HEX);
223 // }
224
225 // Lin_SPI_Transfer_Block(id, tx, rx, bytes_number);
226
227 // Copy rx back into data
228 // Serial.println(F("read from SPI"));
229 // for(int i = 0; i < bytes_number; i++)
230 // {
231 // data[i] = rx[i];
232 // Serial.print(data[i], HEX);
233 // }
234
235
236
237 output_low(id); //! 1) Pull CS low
238
239 //for (i = length; i > 0; i--)
240 for (int i = 0; i < bytes_number; i++)
241 {
242 data[i] = SPI.transfer(tx[i]); //! 2) Read and send byte array
243 }
244
245 output_high(id); //! 3) Pull CS high
246
247
248
249 return SUCCESS;
250 }
251
252 /**
253 * @brief Obtain the GPIO decriptor.
254 * @param desc - The GPIO descriptor.
255 * @param gpio_number - The number of the GPIO.
256 * @return SUCCESS in case of success, FAILURE otherwise.
257 */
258 int32_t gpio_get(gpio_desc **desc,
259 uint8_t gpio_number)
260 {
261 gpio_desc * new_gpio = new gpio_desc;
262 new_gpio->type = GENERIC_GPIO;
263 new_gpio->id = 0;
264 new_gpio->number = gpio_number;
265
266 *desc = new_gpio;
267
268 return 0;
269 }
270
271 /**
272 * @brief Free the resources allocated by gpio_get().
273 * @param desc - The SPI descriptor.
274 * @return SUCCESS in case of success, FAILURE otherwise.
275 */
276 int32_t gpio_remove(gpio_desc *desc)
277 {
278 if (desc) {
279 // Unused variable - fix compiler warning
280 }
281
282 return SUCCESS;
283 }
284
285 /**
286 * @brief Enable the input direction of the specified GPIO.
287 * @param desc - The GPIO descriptor.
288 * @return SUCCESS in case of success, FAILURE otherwise.
289 */
290 int32_t gpio_direction_input(gpio_desc *desc)
291 {
292 pinMode(desc->number, GPIO_IN);
293
294 return SUCCESS;
295 }
296
297 /**
298 * @brief Enable the output direction of the specified GPIO.
299 * @param desc - The GPIO descriptor.
300 * @param value - The value.
301 * Example: GPIO_HIGH
302 * GPIO_LOW
303 * @return SUCCESS in case of success, FAILURE otherwise.
304 */
305 int32_t gpio_direction_output(gpio_desc *desc,
306 uint8_t value)
307 {
308 pinMode(desc->number, GPIO_OUT);
309 digitalWrite(desc->number, value);
310
311 return SUCCESS;
312 }
313
314 /**
315 * @brief Get the direction of the specified GPIO.
316 * @param desc - The GPIO descriptor.
317 * @param direction - The direction.
318 * Example: GPIO_OUT
319 * GPIO_IN
320 * @return SUCCESS in case of success, FAILURE otherwise.
321 */
322 int32_t gpio_get_direction(gpio_desc *desc,
323 uint8_t *direction)
324 {
325 if (desc) {
326 // Unused variable - fix compiler warning
327 }
328
329 if (direction) {
330 // Unused variable - fix compiler warning
331 }
332
333 return 0;
334 }
335
336 /**
337 * @brief Set the value of the specified GPIO.
338 * @param desc - The GPIO descriptor.
339 * @param value - The value.
340 * Example: GPIO_HIGH
341 * GPIO_LOW
342 * @return SUCCESS in case of success, FAILURE otherwise.
343 */
344 int32_t gpio_set_value(gpio_desc *desc,
345 uint8_t value)
346 {
347 digitalWrite(desc->number, value);
348
349 return 0;
350 }
351
352 /**
353 * @brief Get the value of the specified GPIO.
354 * @param desc - The GPIO descriptor.
355 * @param value - The value.
356 * Example: GPIO_HIGH
357 * GPIO_LOW
358 * @return SUCCESS in case of success, FAILURE otherwise.
359 */
360 int32_t gpio_get_value(gpio_desc *desc,
361 uint8_t *value)
362 {
363 uint8_t ret = digitalRead(desc->number);
364 *value = ret;
365
366 return SUCCESS;
367 }
368
369 /**
370 * @brief Generate miliseconds delay.
371 * @param msecs - Delay in miliseconds.
372 * @return None.
373 */
374 void mdelay(uint32_t msecs)
375 {
376 if (msecs) {
377 delay(msecs);
378 }
379 }
380
381 /***************************************************************************************************
382 * *************************************************************************************************
383 * LINDUINO WIRE I2C FUNCTIONS
384 */
385
386 /***************************************************************************/ /**
387 * @brief Connects to I2C device
388 *
389 *******************************************************************************/
390 void Wire_Connect()
391 {
392 Wire.begin();
393 }
394
395 /***************************************************************************/ /**
396 * @brief Write to I2C device.
397 *
398 * @param address - Address of device
399 * @param data - Data to write, includes command
400 * @param length - Length of data byte array
401 * @param stop - Stop bit
402 *
403 * @return Transmission acknowledged by device
404 *
405 *******************************************************************************/
406 uint8_t Wire_Write(unsigned char address, unsigned char* data, unsigned char length, unsigned char stop)
407 {
408 Wire.beginTransmission(address);
409
410 //Serial.print(F("Wire Writing Data:"));
411 for(int i = 0; i < length; i++)
412 {
413 //Serial.print(data[i]);
414 Wire.write(data[i]);
415 }
416 //Serial.println("");
417
418 bool wireStop = (stop > 0);
419
420 uint8_t ack = Wire.endTransmission(wireStop);
421
422 return ack;
423 }
424
425 /***************************************************************************/ /**
426 * @brief Read from I2C device.
427 *
428 * @param address - Address of device
429 * @param data - Data read back
430 * @param length - Length of data byte array to read
431 * @param stop - Stop bit
432 *
433 * @return Number of read bytes
434 *
435 *******************************************************************************/
436 uint8_t Wire_Read(unsigned char address, unsigned char* data, unsigned char length, unsigned char stop)
437 {
438 Wire.requestFrom(address, length, stop);
439
440 uint8_t i = 0;
441
442 while(Wire.available())
443 {
444 data[i] = Wire.read();
445 i++;
446 }
447
448 return i;
449 }
450
451 /***************************************************************************************************
452 * *************************************************************************************************
453 * LINDUINO SPI FUNCTIONS
454 */
455
456 /***************************************************************************/ /**
457 * @brief Sets the Linduino MUX that selects SPI or I2C for the
458 * quikeval port
459 *
460 * @param mux - New mux selection
461 * Example: MUX_I2C - Enable I2C
462 * MUX_SPI - Enable SPI
463 *
464 *******************************************************************************/
465 void quikeval_set_mux(uint8_t mux)
466 {
467
468 pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT);
469
470 if(mux == MUX_I2C)
471 {
472 digitalWrite(QUIKEVAL_MUX_MODE_PIN, HIGH);
473 delay(50);
474 }
475 else
476 {
477 digitalWrite(QUIKEVAL_MUX_MODE_PIN, LOW);
478 delay(1);
479 }
480 }
481
482 // Simple wrapper around Arduino Serial.print method.
483 void uartTX(char *buf)
484 {
485 Serial.print(buf);
486 }
i2c_desc
Definition: platform_drivers.h:84
ret
long ret
Definition: EVAL-AD7124-8.ino:145
gpio_direction_input
int32_t gpio_direction_input(gpio_desc *desc)
Enable the input direction of the specified GPIO.
Definition: platform_drivers.cpp:290
uartTX
void uartTX(char *buf)
Enable SPI, matches spi_enable.
Definition: platform_drivers.cpp:483
spi_desc::chip_select
uint8_t chip_select
Definition: platform_drivers.h:117
gpio_desc
Definition: platform_drivers.h:124
GPIO_IN
#define GPIO_IN
Definition: platform_drivers.h:61
i2c_init_param::max_speed_hz
uint32_t max_speed_hz
Definition: platform_drivers.h:80
i2c_init_param
Definition: platform_drivers.h:77
output_high
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
Linduino.h
Header File for Linduino Libraries and Demo Code.
spi_desc::max_speed_hz
uint32_t max_speed_hz
Definition: platform_drivers.h:115
spi_init_param
Definition: platform_drivers.h:104
GENERIC_GPIO
Definition: platform_drivers.h:121
QUIKEVAL_MUX_MODE_PIN
#define QUIKEVAL_MUX_MODE_PIN
QUIKEVAL_MUX_MODE_PIN defines the control pin for the QuikEval MUX.
Definition: Linduino.h:58
gpio_direction_output
int32_t gpio_direction_output(gpio_desc *desc, uint8_t value)
Enable the output direction of the specified GPIO.
Definition: platform_drivers.cpp:305
spi_init_param::max_speed_hz
uint32_t max_speed_hz
Definition: platform_drivers.h:107
i2c_init_param::slave_address
uint8_t slave_address
Definition: platform_drivers.h:81
i2c_write
int32_t i2c_write(i2c_desc *desc, uint8_t *data, uint8_t bytes_number, uint8_t stop_bit)
Write data to a slave device.
Definition: platform_drivers.cpp:104
spi_init
int32_t spi_init(spi_desc **desc, const struct spi_init_param *param)
Initialize the SPI communication peripheral.
Definition: platform_drivers.cpp:147
GPIO_OUT
#define GPIO_OUT
Definition: platform_drivers.h:60
spi_mode
const byte spi_mode
Definition: DC590_subset.ino:104
address
static uint8_t address
Definition: DC2091A.ino:83
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
spi_init_param::mode
uint8_t mode
Definition: platform_drivers.h:108
spi_write_and_read
int32_t spi_write_and_read(spi_desc *desc, uint8_t *data, uint8_t bytes_number)
Write and read data to/from SPI.
Definition: platform_drivers.cpp:200
i2c_desc::slave_address
uint8_t slave_address
Definition: platform_drivers.h:88
Wire_Write
uint8_t Wire_Write(unsigned char address, unsigned char *data, unsigned char length, unsigned char stop)
Write to I2C device.
Definition: platform_drivers.cpp:406
gpio_desc::id
uint32_t id
Definition: platform_drivers.h:126
i2c_init_param::type
i2c_type type
Definition: platform_drivers.h:78
i2c_desc::type
i2c_type type
Definition: platform_drivers.h:85
platform_drivers.h
Header file of Generic Platform Drivers.
Wire_Read
uint8_t Wire_Read(unsigned char address, unsigned char *data, unsigned char length, unsigned char stop)
Read from I2C device.
Definition: platform_drivers.cpp:436
output_low
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
i2c_init_param::id
uint32_t id
Definition: platform_drivers.h:79
stop
static float stop
Definition: Audio_Spectrum_Analyzer.ino:19
spi_remove
int32_t spi_remove(spi_desc *desc)
Free the resources allocated by spi_init().
Definition: platform_drivers.cpp:186
i2c_desc::max_speed_hz
uint32_t max_speed_hz
Definition: platform_drivers.h:87
gpio_desc::type
gpio_type type
Definition: platform_drivers.h:125
arduino_spi_modes
const uint8_t arduino_spi_modes[4]
Definition: platform_drivers.cpp:132
quikeval_set_mux
void quikeval_set_mux(uint8_t mux)
Sets the Linduino MUX that selects SPI or I2C for the quikeval port.
Definition: platform_drivers.cpp:465
gpio_desc::number
uint8_t number
Definition: platform_drivers.h:127
gpio_remove
int32_t gpio_remove(gpio_desc *desc)
Free the resources allocated by gpio_get().
Definition: platform_drivers.cpp:276
gpio_set_value
int32_t gpio_set_value(gpio_desc *desc, uint8_t value)
Set the value of the specified GPIO.
Definition: platform_drivers.cpp:344
SUCCESS
#define SUCCESS
Definition: LT_PMBus.h:62
MUX_SPI
#define MUX_SPI
Definition: platform_drivers.h:67
gpio_get_direction
int32_t gpio_get_direction(gpio_desc *desc, uint8_t *direction)
Get the direction of the specified GPIO.
Definition: platform_drivers.cpp:322
i
static int i
Definition: DC2430A.ino:184
spi_desc
Definition: platform_drivers.h:112
MUX_I2C
#define MUX_I2C
Definition: platform_drivers.h:66
gpio_get
int32_t gpio_get(gpio_desc **desc, uint8_t gpio_number)
Obtain the GPIO decriptor.
Definition: platform_drivers.cpp:258
spi_init_param::chip_select
uint8_t chip_select
Definition: platform_drivers.h:109
spi_desc::mode
uint8_t mode
Definition: platform_drivers.h:116
i2c_remove
int32_t i2c_remove(i2c_desc *desc)
Free the resources allocated by i2c_init().
Definition: platform_drivers.cpp:89
i2c_read
int32_t i2c_read(i2c_desc *desc, uint8_t *data, uint8_t bytes_number, uint8_t stop_bit)
Read data from a slave device.
Definition: platform_drivers.cpp:122
i2c_init
int32_t i2c_init(i2c_desc **desc, const struct i2c_init_param *param)
Initialize the I2C communication peripheral.
Definition: platform_drivers.cpp:60
mdelay
void mdelay(uint32_t msecs)
Generate miliseconds delay.
Definition: platform_drivers.cpp:374
Wire_Connect
void Wire_Connect()
Connects to I2C device.
Definition: platform_drivers.cpp:390
i2c_desc::id
uint32_t id
Definition: platform_drivers.h:86
gpio_get_value
int32_t gpio_get_value(gpio_desc *desc, uint8_t *value)
Get the value of the specified GPIO.
Definition: platform_drivers.cpp:360