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
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
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  */
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  */
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  */
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  */
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 *******************************************************************************/
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 }
long ret
int32_t gpio_direction_input(gpio_desc *desc)
Enable the input direction of the specified GPIO.
void uartTX(char *buf)
Enable SPI, matches spi_enable.
uint8_t chip_select
#define GPIO_IN
uint32_t max_speed_hz
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
Header File for Linduino Libraries and Demo Code.
uint32_t max_speed_hz
#define QUIKEVAL_MUX_MODE_PIN
QUIKEVAL_MUX_MODE_PIN defines the control pin for the QuikEval MUX.
Definition: Linduino.h:58
int32_t gpio_direction_output(gpio_desc *desc, uint8_t value)
Enable the output direction of the specified GPIO.
int32_t i2c_write(i2c_desc *desc, uint8_t *data, uint8_t bytes_number, uint8_t stop_bit)
Write data to a slave device.
int32_t spi_init(spi_desc **desc, const struct spi_init_param *param)
Initialize the SPI communication peripheral.
#define GPIO_OUT
const byte spi_mode
static uint8_t address
Definition: DC2091A.ino:83
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
int32_t spi_write_and_read(spi_desc *desc, uint8_t *data, uint8_t bytes_number)
Write and read data to/from SPI.
uint8_t slave_address
uint8_t Wire_Write(unsigned char address, unsigned char *data, unsigned char length, unsigned char stop)
Write to I2C device.
i2c_type type
Header file of Generic Platform Drivers.
uint8_t Wire_Read(unsigned char address, unsigned char *data, unsigned char length, unsigned char stop)
Read from I2C device.
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
static float stop
int32_t spi_remove(spi_desc *desc)
Free the resources allocated by spi_init().
uint32_t max_speed_hz
gpio_type type
const uint8_t arduino_spi_modes[4]
void quikeval_set_mux(uint8_t mux)
Sets the Linduino MUX that selects SPI or I2C for the quikeval port.
uint8_t number
int32_t gpio_remove(gpio_desc *desc)
Free the resources allocated by gpio_get().
int32_t gpio_set_value(gpio_desc *desc, uint8_t value)
Set the value of the specified GPIO.
#define SUCCESS
Definition: LT_PMBus.h:62
#define MUX_SPI
int32_t gpio_get_direction(gpio_desc *desc, uint8_t *direction)
Get the direction of the specified GPIO.
static int i
Definition: DC2430A.ino:184
#define MUX_I2C
int32_t gpio_get(gpio_desc **desc, uint8_t gpio_number)
Obtain the GPIO decriptor.
uint8_t mode
int32_t i2c_remove(i2c_desc *desc)
Free the resources allocated by i2c_init().
int32_t i2c_read(i2c_desc *desc, uint8_t *data, uint8_t bytes_number, uint8_t stop_bit)
Read data from a slave device.
int32_t i2c_init(i2c_desc **desc, const struct i2c_init_param *param)
Initialize the I2C communication peripheral.
void mdelay(uint32_t msecs)
Generate miliseconds delay.
void Wire_Connect()
Connects to I2C device.
uint32_t id
int32_t gpio_get_value(gpio_desc *desc, uint8_t *value)
Get the value of the specified GPIO.