IoT-MBBR (masterthesis)
Masterthesis upgrading a Moving Bed BioReactor with extra sensors and cloud connectivity.
vl53l1_platform.c
Go to the documentation of this file.
1 /***************************************************************************//**
2  * @file vl53l1_platform.c
3  * @brief Platform-specific implementation for using the VL53L1X API on the EFM32HG322.
4  * @version 1.0
5  * @author Brecht Van Eeckhoudt
6  *
7  * ******************************************************************************
8  *
9  * @section Versions
10  *
11  * @li v1.0:
12  *
13  * ******************************************************************************
14  *
15  * @section License
16  *
17  * **Copyright (C) 2019 - Brecht Van Eeckhoudt**
18  *
19  * This program is free software: you can redistribute it and/or modify
20  * it under the terms of the **GNU General Public License** as published by
21  * the Free Software Foundation, either **version 3** of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * *A copy of the GNU General Public License can be found in the `LICENSE`
30  * file along with this source code.*
31  *
32  * @n
33  *
34  * Some methods use code obtained from examples from [Silicon Labs' GitHub](https://github.com/SiliconLabs/peripheral_examples).
35  * These sections are licensed under the Silabs License Agreement. See the file
36  * "Silabs_License_Agreement.txt" for details. Before using this software for
37  * any purpose, you must agree to the terms of that agreement.
38  *
39  * @n
40  *
41  * **This file is part of VL53L1 Platform**, the method names remained but
42  * they were filled in with code by Brecht Van Eeckhoudt.
43  *
44  * **Copyright (c) 2016, STMicroelectronics - All Rights Reserved**
45  *
46  * License terms: BSD 3-clause "New" or "Revised" License.
47  *
48  * Redistribution and use in source and binary forms, with or without
49  * modification, are permitted provided that the following conditions are met:
50  *
51  * 1. Redistributions of source code must retain the above copyright notice, this
52  * list of conditions and the following disclaimer.
53  *
54  * 2. Redistributions in binary form must reproduce the above copyright notice,
55  * this list of conditions and the following disclaimer in the documentation
56  * and/or other materials provided with the distribution.
57  *
58  * 3. Neither the name of the copyright holder nor the names of its contributors
59  * may be used to endorse or promote products derived from this software
60  * without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
63  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
65  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
68  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
69  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
70  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
71  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72  *
73  ******************************************************************************/
74 
75 
76 #include "vl53l1_platform.h"
77 #include <string.h>
78 #include <time.h>
79 #include <math.h>
80 
81 #include "em_cmu.h"
82 #include "em_gpio.h"
83 #include "em_i2c.h"
84 
85 #include "debug_dbprint.h"
86 #include "i2c.h" /* I2C initialisation */
87 
88 
89 /**************************************************************************//**
90  * @brief
91  * This method is not used by the API and thereby not implemented.
92  *****************************************************************************/
94 {
95  /* Not used */
96 
97 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
98  dbcrit("Method not implemented since it doesn't seem to be used!");
99 #endif /* DEBUG_DBPRINT */
100 
101  return (0);
102 }
103 
104 
105 /**************************************************************************//**
106  * @brief
107  * TODO
108  *
109  * @details
110  * This method also initializes i2C if necessary.@n
111  * This method is only used in `VL53L1X_GetResult`.
112  *
113  * @param[in] dev
114  * Device ID (`uint16_t`).
115  *
116  * @param[in] index
117  * Index (`uint16_t`).
118  *
119  * @param[in] pdata
120  * Pointer to the data (`uint8_t`) to put the read bytes in.
121  *
122  * @param[in] count
123  * Counter (`uint32_t`).
124  *
125  * @return
126  * @li `0` - TODO
127  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
128  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
129  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
130  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
131  * @li `-5` - `i2cTransferSwFault`, SW fault.
132  * @li `-6` - Coudldn't configure I2C.
133  *****************************************************************************/
135 {
136  /* Initialize I2C if not already the case */
137  if (initI2C() != 0) return (-6);
138 
139 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
140  dbcrit("Not yet implemented!");
141 #endif /* DEBUG_DBPRINT */
142 
143  return (0); // to be implemented
144 }
145 
146 
147 /**************************************************************************//**
148  * @brief
149  * Write a byte (8 bits) to the I2C bus.
150  *
151  * @details
152  * This method also initializes i2C if necessary.
153  *
154  * @param[in] dev
155  * Device ID (`uint16_t`).
156  *
157  * @param[in] index
158  * Index (`uint16_t`).
159  *
160  * @param[in] data
161  * The data (`uint8_t`) to put on the I2C bus.
162  *
163  * @return
164  * @return
165  * @li `0` - Byte written correctly.
166  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
167  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
168  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
169  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
170  * @li `-5` - `i2cTransferSwFault`, SW fault.
171  * @li `-6` - Coudldn't configure I2C.
172  *****************************************************************************/
174 {
175  /* Initialize I2C if not already the case */
176  if (initI2C() != 0) return (-6);
177 
178  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
179  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
180 
181  /* Separate data in bytes */
182  uint8_t data_buf[1] = {data};
183 
184  /* Transfer structure */
185  I2C_TransferSeq_TypeDef i2cTransfer;
186  I2C_TransferReturn_TypeDef result;
187 
188  /* Initializing I2C transfer */
189  i2cTransfer.addr = dev;
190  i2cTransfer.flags = I2C_FLAG_WRITE_WRITE; /* Data written from buf[0].data and buf[1].data */
191  i2cTransfer.buf[0].data = index_buf;
192  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
193  i2cTransfer.buf[1].data = data_buf;
194  i2cTransfer.buf[1].len = 1; /* Data itself is one byte */
195  result = I2C_TransferInit(I2C0, &i2cTransfer);
196 
197  /* Transmitting I2C data (busy-wait until transfer is complete) */
198  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
199 
200  return (result);
201 }
202 
203 
204 /**************************************************************************//**
205  * @brief
206  * Write a word (16 bits) to the I2C bus.
207  *
208  * @details
209  * This method also initializes i2C if necessary.
210  *
211  * @param[in] dev
212  * Device ID (`uint16_t`).
213  *
214  * @param[in] index
215  * Index (`uint16_t`).
216  *
217  * @param[in] data
218  * The data (`uint16_t`) to put on the I2C bus.
219  *
220  * @return
221  * @li `0` - Word written correctly.
222  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
223  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
224  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
225  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
226  * @li `-5` - `i2cTransferSwFault`, SW fault.
227  * @li `-6` - Coudldn't configure I2C.
228  *****************************************************************************/
230 {
231  /* Initialize I2C if not already the case */
232  if (initI2C() != 0) return (-6);
233 
234  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
235  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
236 
237  /* Separate data in bytes */
238  uint8_t data_buf[2] = {((data & 0xFF00) >> 8), (data & 0x00FF)};
239 
240  /* Transfer structure */
241  I2C_TransferSeq_TypeDef i2cTransfer;
242  I2C_TransferReturn_TypeDef result;
243 
244  /* Initializing I2C transfer */
245  i2cTransfer.addr = dev;
246  i2cTransfer.flags = I2C_FLAG_WRITE_WRITE; /* Data written from buf[0].data and buf[1].data */
247  i2cTransfer.buf[0].data = index_buf;
248  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
249  i2cTransfer.buf[1].data = data_buf;
250  i2cTransfer.buf[1].len = 2; /* Data itself is two byte */
251  result = I2C_TransferInit(I2C0, &i2cTransfer);
252 
253  /* Transmitting I2C data (busy-wait until transfer is complete) */
254  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
255 
256  return (result);
257 }
258 
259 
260 /**************************************************************************//**
261  * @brief
262  * Write a double word (32 bits) to the I2C bus.
263  *
264  * @details
265  * This method also initializes i2C if necessary.
266  *
267  * @param[in] dev
268  * Device ID (`uint16_t`).
269  *
270  * @param[in] index
271  * Index (`uint16_t`).
272  *
273  * @param[in] data
274  * The data (`uint32_t`) to put on the I2C bus.
275  *
276  * @return
277  * @li `0` - Double word written correctly.
278  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
279  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
280  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
281  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
282  * @li `-5` - `i2cTransferSwFault`, SW fault.
283  * @li `-6` - Coudldn't configure I2C.
284  *****************************************************************************/
286 {
287  /* Initialize I2C if not already the case */
288  if (initI2C() != 0) return (-6);
289 
290  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
291  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
292 
293  /* Separate data in bytes */
294  uint8_t data_buf[4] = {((data & 0xFF000000) >> 24), ((data & 0xFF0000) >> 16), ((data & 0xFF00) >> 8), (data & 0x00FF)};
295 
296  /* Transfer structure */
297  I2C_TransferSeq_TypeDef i2cTransfer;
298  I2C_TransferReturn_TypeDef result;
299 
300  /* Initializing I2C transfer */
301  i2cTransfer.addr = dev;
302  i2cTransfer.flags = I2C_FLAG_WRITE_WRITE; /* Data written from buf[0].data and buf[1].data */
303  i2cTransfer.buf[0].data = index_buf;
304  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
305  i2cTransfer.buf[1].data = data_buf;
306  i2cTransfer.buf[1].len = 4; /* Data itself is four byte */
307  result = I2C_TransferInit(I2C0, &i2cTransfer);
308 
309  /* Transmitting I2C data (busy-wait until transfer is complete) */
310  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
311 
312  return (result);
313 }
314 
315 
316 /**************************************************************************//**
317  * @brief
318  * Read a byte (8 bits) from the I2C bus.
319  *
320  * @details
321  * This method also initializes i2C if necessary.
322  *
323  * @param[in] dev
324  * Device ID (`uint16_t`).
325  *
326  * @param[in] index
327  * Index (`uint16_t`).
328  *
329  * @param[in] data
330  * Pointer to the data (`uint8_t`) to put the read byte in.
331  *
332  * @return
333  * @li `0` - Byte read correctly.
334  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
335  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
336  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
337  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
338  * @li `-5` - `i2cTransferSwFault`, SW fault.
339  * @li `-6` - Coudldn't configure I2C.
340  *****************************************************************************/
342 {
343  /* Initialize I2C if not already the case */
344  if (initI2C() != 0) return (-6);
345 
346  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
347  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
348 
349  /* Transfer structure */
350  I2C_TransferSeq_TypeDef i2cTransfer;
351  I2C_TransferReturn_TypeDef result;
352 
353  /* Initializing I2C transfer */
354  i2cTransfer.addr = dev;
355  i2cTransfer.flags = I2C_FLAG_WRITE_READ; /* Data written from buf[0].data and read into buf[1].data */
356  i2cTransfer.buf[0].data = index_buf;
357  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
358  i2cTransfer.buf[1].data = data;
359  i2cTransfer.buf[1].len = 1; /* Data itself is one byte */
360  result = I2C_TransferInit(I2C0, &i2cTransfer);
361 
362  /* Transmitting I2C data (busy-wait until transfer is complete) */
363  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
364 
365  return (result);
366 }
367 
368 
369 /**************************************************************************//**
370  * @brief
371  * Read a word (16 bits) from the I2C bus.
372  *
373  * @details
374  * This method also initializes i2C if necessary.
375  *
376  * @param[in] dev
377  * Device ID (`uint16_t`).
378  *
379  * @param[in] index
380  * Index (`uint16_t`).
381  *
382  * @param[in] data
383  * Pointer to the data (`uint16_t`) to put the read word in.
384  *
385  * @return
386  * @li `0` - Word read correctly.
387  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
388  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
389  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
390  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
391  * @li `-5` - `i2cTransferSwFault`, SW fault.
392  * @li `-6` - Coudldn't configure I2C.
393  *****************************************************************************/
395 {
396  /* Initialize I2C if not already the case */
397  if (initI2C() != 0) return (-6);
398 
399  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
400  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
401 
402  /* Create buffer for received bytes */
403  uint8_t data_buf[2] = {0, 0};
404 
405  /* Transfer structure */
406  I2C_TransferSeq_TypeDef i2cTransfer;
407  I2C_TransferReturn_TypeDef result;
408 
409  /* Initializing I2C transfer */
410  i2cTransfer.addr = dev;
411  i2cTransfer.flags = I2C_FLAG_WRITE_READ; /* Data written from buf[0].data and read into buf[1].data */
412  i2cTransfer.buf[0].data = index_buf;
413  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
414  i2cTransfer.buf[1].data = data_buf;
415  i2cTransfer.buf[1].len = 2; /* Data itself is two bytes */
416  result = I2C_TransferInit(I2C0, &i2cTransfer);
417 
418  /* Transmitting I2C data (busy-wait until transfer is complete) */
419  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
420 
421  /* Store received bytes correctly in given data location */
422  (*data) = ((uint16_t)data_buf[0] << 8) | data_buf[1];
423 
424  return (result);
425 }
426 
427 
428 /**************************************************************************//**
429  * @brief
430  * Read a double word (32 bits) from the I2C bus.
431  *
432  * @details
433  * This method also initializes i2C if necessary.
434  *
435  * @param[in] dev
436  * Device ID (`uint16_t`).
437  *
438  * @param[in] index
439  * Index (`uint16_t`).
440  *
441  * @param[in] data
442  * Pointer to the data (`uint32_t`) to put the read double word in.
443  *
444  * @return
445  * @li `0` - Double word read correctly.
446  * @li `-1` - `i2cTransferNack`, NACK received during transfer.
447  * @li `-2` - `i2cTransferBusErr`, Bus error during transfer (misplaced START/STOP).
448  * @li `-3` - `i2cTransferArbLost`, Arbitration lost during transfer.
449  * @li `-4` - `i2cTransferUsageFault`, Usage fault.
450  * @li `-5` - `i2cTransferSwFault`, SW fault.
451  * @li `-6` - Coudldn't configure I2C.
452  *****************************************************************************/
454 {
455  /* Initialize I2C if not already the case */
456  if (initI2C() != 0) return (-6);
457 
458  /* Separate index in two bytes (ANDing with a mask and shifting one byte (8 bits) per position) */
459  uint8_t index_buf[2] = {((index & 0xFF00) >> 8), (index & 0x00FF)};
460 
461  /* Create buffer for received bytes */
462  uint8_t data_buf[4] = {0, 0, 0, 0};
463 
464  /* Transfer structure */
465  I2C_TransferSeq_TypeDef i2cTransfer;
466  I2C_TransferReturn_TypeDef result;
467 
468  /* Initializing I2C transfer */
469  i2cTransfer.addr = dev;
470  i2cTransfer.flags = I2C_FLAG_WRITE_READ; /* Data written from buf[0].data and read into buf[1].data */
471  i2cTransfer.buf[0].data = index_buf;
472  i2cTransfer.buf[0].len = 2; /* Index is two bytes */
473  i2cTransfer.buf[1].data = data_buf;
474  i2cTransfer.buf[1].len = 4; /* Data itself is four bytes */
475  result = I2C_TransferInit(I2C0, &i2cTransfer);
476 
477  /* Transmitting I2C data (busy-wait until transfer is complete) */
478  while (result == i2cTransferInProgress) result = I2C_Transfer(I2C0);
479 
480  /* Store received bytes correctly in given data location */
481  (*data) = ((uint32_t)data_buf[0] << 24) | ((uint32_t)data_buf[1] << 16) | ((uint32_t)data_buf[2] << 8) | data_buf[3];
482 
483  return (result);
484 }
485 
486 
487 /**************************************************************************//**
488  * @brief
489  * This method is not used by the API and thereby not implemented.
490  *****************************************************************************/
492 {
493  /* Not used */
494 
495 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
496  dbcrit("Method not implemented since it doesn't seem to be used!");
497 #endif /* DEBUG_DBPRINT */
498 
499  return (0);
500 }
int8_t VL53L1_WrWord(uint16_t dev, uint16_t index, uint16_t data)
Write a word (16 bits) to the I2C bus.
Those platform functions are platform dependent and have to be implemented by the user...
int8_t VL53L1_WrDWord(uint16_t dev, uint16_t index, uint32_t data)
Write a double word (32 bits) to the I2C bus.
signed char int8_t
Typedef defining 8 bit char type. The developer should modify this to suit the platform being deploye...
Definition: vl53l1_types.h:103
int8_t VL53L1_WriteMulti(uint16_t dev, uint16_t index, uint8_t *pdata, uint32_t count)
This method is not used by the API and thereby not implemented.
MeasurementData_t data
Definition: main.c:86
int8_t VL53L1_RdByte(uint16_t dev, uint16_t index, uint8_t *data)
Read a byte (8 bits) from the I2C bus.
int8_t VL53L1_RdWord(uint16_t dev, uint16_t index, uint16_t *data)
Read a word (16 bits) from the I2C bus.
int8_t VL53L1_RdDWord(uint16_t dev, uint16_t index, uint32_t *data)
Read a double word (32 bits) from the I2C bus.
int8_t VL53L1_WrByte(uint16_t dev, uint16_t index, uint8_t data)
Write a byte (8 bits) to the I2C bus.
int int32_t
Typedef defining 32 bit int type. The developer should modify this to suit the platform being deploye...
Definition: vl53l1_types.h:83
Enable or disable printing to UART with dbprint.
int8_t initI2C(void)
I2C initialization (if not already initialized).
Definition: i2c.c:66
int8_t VL53L1_WaitMs(uint16_t dev, int32_t wait_ms)
This method is not used by the API and thereby not implemented.
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:541
unsigned short uint16_t
Typedef defining 16 bit unsigned short type. The developer should modify this to suit the platform be...
Definition: vl53l1_types.h:88
int8_t VL53L1_ReadMulti(uint16_t dev, uint16_t index, uint8_t *pdata, uint32_t count)
TODO.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:98
unsigned int uint32_t
Typedef defining 32 bit unsigned int type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:78
I2C functionality.