ISSDK  1.7
IoT Sensing Software Development Kit
driver_MPL3115.c
Go to the documentation of this file.
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  * that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  * of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  * list of conditions and the following disclaimer in the documentation and/or
16  * other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from this
20  * software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*! \file driver_MPL3115.c
36  \brief Provides init() and read() functions for the MPL3115 pressure sensor/altimeter.
37 */
38 
39 #include "board.h" // generated by Kinetis Expert. Long term - merge sensor_board.h into this file
40 #include "sensor_fusion.h" // Sensor fusion structures and types
41 #include "sensor_io_i2c.h" // Required for registerreadlist_t / registerwritelist_t declarations
42 #include "mpl3115_drv.h" // Low level IS-SDK prototype driver
43 #include "drivers.h" // Device specific drivers supplied by NXP (can be replaced with user drivers)
44 #define MPL3115_MPERCOUNT 0.0000152587890625F // Convert 32-bit Altitude value to meters
45 #define MPL3115_CPERCOUNT 0.00390625F // Convert 16-bit Temperature value to Celcius
46 #define MPL3115_ACCEL_FIFO_SIZE 32
47 
48 #if F_USING_PRESSURE // driver is only pulled in if the appropriate flag is set in build.h
49 
50 // Command definition to read the WHO_AM_I value.
51 const registerreadlist_t MPL3115_WHO_AM_I_READ[] =
52 {
53  { .readFrom = MPL3115_WHO_AM_I, .numBytes = 1 }, __END_READ_DATA__
54 };
55 
56 // Command definition to read the number of entries in the accel FIFO.
57 const registerreadlist_t MPL3115_F_STATUS_READ[] =
58 {
59  { .readFrom = MPL3115_STATUS, .numBytes = 1 }, __END_READ_DATA__
60 };
61 
62 // Command definition to read the number of entries in the accel FIFO.
63 registerreadlist_t MPL3115_DATA_READ[] =
64 {
65  { .readFrom = MPL3115_OUT_P_MSB, .numBytes = 5 }, __END_READ_DATA__
66 };
67 
68 // Each entry in a RegisterWriteList is composed of: register address, value to write, bit-mask to apply to write (0 enables)
69 const registerwritelist_t MPL3115_Initialization[] =
70 {
71  // write 0000 0000 = 0x00 to MPL3115_CTRL_REG1 to place the MPL3115 in Standby
72  // [7]: ALT=0
73  // [6]: RAW=0
74  // [5-3]: OS=000
75  // [2]: RST=0
76  // [1]: OST=0
77  // [0]: SBYB=0 to enter standby
78  { MPL3115_CTRL_REG1, 0x00, 0x00 },
79 
80  // write 1011 1001 = 0xB9 to configure MPL3115 and enter Active mode in Auto Acquisition mode and 1Hz ODR
81  // [7]: ALT=1 for altitude measurements
82  // [6]: RAW=0 to disable raw measurements
83  // [5-3]: OS=111 for OS ratio=128
84  // [2]: RST=0 do not enter reset
85  // [1]: OST=0 do not initiate a reading
86  // [0]: SBYB=1 to enter active mode
87  { MPL3115_CTRL_REG1, 0xB9, 0x00 },
89 };
90 
91 // All sensor drivers and initialization functions have the same prototype.
92 // sfg is a pointer to the master "global" sensor fusion structure.
93 // sensor = pointer to linked list element used by the sensor fusion subsystem to specify required sensors
94 int8_t MPL3115_Init(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
95 {
97  uint8_t reg;
98  status = Register_I2C_Read(sensor->bus_driver, &sensor->deviceInfo, sensor->addr, MPL3115_WHO_AM_I, 1, &reg);
99  if (status==SENSOR_ERROR_NONE) {
100  sfg->Pressure.iWhoAmI = reg;
101  if (reg!=MPL3115_WHOAMI_VALUE) {
102  // return with error, whoAmI will retain default value of zero
103  return(SENSOR_ERROR_INIT);
104  }
105  } else {
106  // whoAmI will retain default value of zero
107  return(status);
108  }
109 
110  // Configure and start the MPL3115 sensor. This does multiple register writes
111  // (see MPL3115_Initialization definition above)
112  status = Sensor_I2C_Write(sensor->bus_driver, &sensor->deviceInfo, sensor->addr, MPL3115_Initialization );
113 
114  // Stash some needed constants in the SF data structure for this sensor
115  sfg->Pressure.fmPerCount = MPL3115_MPERCOUNT; // Convert 32-bit Altitude value to meters
116  sfg->Pressure.fCPerCount = MPL3115_CPERCOUNT; // Convert 16-bit Temperature value to Celcius
117 
119  sfg->Pressure.isEnabled = true;
120 
121  return (status);
122 }
123 
124 int8_t MPL3115_Read(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
125 {
126  uint8_t I2C_Buffer[6 * MPL3115_ACCEL_FIFO_SIZE]; // I2C read buffer
127  int8_t status; // I2C transaction status
128 
130  {
131  return SENSOR_ERROR_INIT;
132  }
133 
134  status = Sensor_I2C_Read(sensor->bus_driver, &sensor->deviceInfo, sensor->addr, MPL3115_DATA_READ, I2C_Buffer );
135 
136  if (status==SENSOR_ERROR_NONE) {
137  // place the read buffer into the 32 bit altitude and 16 bit temperature
138  sfg->Pressure.iH = (I2C_Buffer[0] << 24) | (I2C_Buffer[1] << 16) | (I2C_Buffer[2] << 8);
139  sfg->Pressure.iT = (I2C_Buffer[3] << 8) | I2C_Buffer[4];
140 
141  // convert from counts to metres altitude and C
142  sfg->Pressure.fH = (float) sfg->Pressure.iH * sfg->Pressure.fmPerCount;
143  sfg->Pressure.fT = (float) sfg->Pressure.iT * sfg->Pressure.fCPerCount;
144  } else {
145  sfg->Pressure.fH = 0.0;
146  sfg->Pressure.fT = 0.0;
147  }
148 
149  return (status);
150 }
151 
152 
153 // Each entry in a RegisterWriteList is composed of: register address, value to write, bit-mask to apply to write (0 enables)
154 const registerwritelist_t MPL3115_IDLE[] =
155 {
156  // Set ACTIVE = other bits unchanged
157  { MPL3115_CTRL_REG1, 0x00, 0x01 },
159 };
160 
161 // MPL3115_Idle places the sensor into Standby mode (wakeup time = 1 second)
162 int8_t MPL3115_Idle(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
163 {
164  int32_t status;
166  status = Sensor_I2C_Write(sensor->bus_driver, &sensor->deviceInfo, sensor->addr, MPL3115_IDLE );
167  sensor->isInitialized = 0;
168  sfg->Pressure.isEnabled = false;
169  } else {
170  return SENSOR_ERROR_INIT;
171  }
172  return status;
173 }
174 #endif
#define MPL3115_ACCEL_FIFO_SIZE
#define __END_WRITE_DATA__
Definition: sensor_drv.h:71
void * bus_driver
should be of type (ARM_DRIVER_I2C* for I2C-based sensors, ARM_DRIVER_SPI* for SPI) ...
SensorFusionGlobals sfg
#define F_USING_PRESSURE
nominally 0x0008 if altimeter is to be used, 0x0000 otherwise
int32_t status
int8_t MPL3115_Read(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int32_t Sensor_I2C_Read(ARM_DRIVER_I2C *pCommDrv, registerDeviceInfo_t *devInfo, uint16_t slaveAddress, const registerreadlist_t *pReadList, uint8_t *pOutBuffer)
Read register data from a sensor.
#define __END_READ_DATA__
Definition: sensor_drv.h:77
The top level fusion structure.
#define MPL3115_WHOAMI_VALUE
Definition: mpl3115.h:65
int8_t MPL3115_Init(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
uint16_t addr
I2C address if applicable.
#define MPL3115_MPERCOUNT
#define MPL3115_CPERCOUNT
The sensor_fusion.h file implements the top level programming interface.
uint16_t isInitialized
Bitfields to indicate sensor is active (use SensorBitFields from build.h)
registerDeviceInfo_t deviceInfo
I2C device context.
Provides function prototypes for driver level interfaces.
#define F_USING_TEMPERATURE
nominally 0x0010 if temp sensor is to be used, 0x0000 otherwise
typedef int32_t(DATA_FORMAT_Append_t))(void *pData
The interface function to append the data on the formated stream.
int8_t MPL3115_Idle(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
The mpl3115_drv.h file describes the MPL3115 driver interface and structures.
int32_t Register_I2C_Read(ARM_DRIVER_I2C *pCommDrv, registerDeviceInfo_t *devInfo, uint16_t slaveAddress, uint8_t offset, uint8_t length, uint8_t *pOutBuffer)
The interface function to read a sensor register.
This structure defines the Write command List.
Definition: sensor_drv.h:94
This structure defines the Read command List.
Definition: sensor_drv.h:104
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
The sensor_io_i2c.h file declares low-level interface functions for reading and writing sensor regist...
int32_t Sensor_I2C_Write(ARM_DRIVER_I2C *pCommDrv, registerDeviceInfo_t *devInfo, uint16_t slaveAddress, const registerwritelist_t *pRegWriteList)
Write register data to a sensor.
Definition: sensor_io_i2c.c:97