1 /*
2  * Author: William Penner <william.penner@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE.
22  */
23 
24 #pragma once
25 
26 #include <string>
27 #include <mraa/i2c.hpp>
28 #include <math.h>
29 
30 #define MPL3115A2_NAME        "mpl3115a2"
31 
32 #define MPL3115A2_I2C_ADDRESS   0x60
33 #define MPL3115A2_DEVICE_ID     0xc4
34 
35 #define MPL3115A2_STATUS        0x00
36 #define MPL3115A2_OUT_PRESS     0x01  /* MSB first, 20 bit */
37 #define MPL3115A2_OUT_TEMP      0x04  /* MSB first, 12 bit */
38 #define MPL3115A2_WHO_AM_I      0x0c
39 #define MPL3115A2_PT_DATA_CFG   0x13
40 #define MPL3115A2_P_MIN         0x1C
41 #define MPL3115A2_T_MIN         0x1F
42 #define MPL3115A2_P_MAX         0x21
43 #define MPL3115A2_T_MAX         0x24
44 #define MPL3115A2_CTRL_REG1     0x26
45 
46 // CTRL_REG1
47 #define MPL3115A2_CTRL_SBYB     0x01  /* Standby (not) */
48 #define MPL3115A2_CTRL_OST      0x02  /* One-shot trigger */
49 #define MPL3115A2_CTRL_RESET    0x04  /* RESET device */
50 #define MPL3115A2_CTRL_ALT_MODE 0x80  /* Altitude mode */
51 
52 #define MPL3115A2_SETOVERSAMPLE(a) ((a & 7) << 3)
53 #define MPL3115A2_GETOVERSAMPLE(a) ((a >> 3) & 7)
54 #define MPL3115A2_MAXOVERSAMPLE   7
55 
56 namespace upm {
57 
58 /**
59  * @brief MPL3115A2 Atmospheric Pressure Sensor library
60  * @defgroup mpl3115a2 libupm-mpl3115a2
61  * @ingroup freescale i2c pressure
62  */
63 /**
64  * @library mpl3115a2
65  * @sensor mpl3115a2
66  * @comname MPL3115A2 Atmospheric Pressure Sensor
67  * @type pressure
68  * @man freescale
69  * @web http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL3115A2
70  * @con i2c
71  *
72  * @brief API for the MPL3115A2 Atmospheric Pressure Sensor
73  *
74  * Freescale Semiconductor* [MPL3115A2]
75  * (http://cache.freescale.com/files/sensors/doc/data_sheet/MPL3115A2.pdf)
76  * is a high-precision, ultra-low power consumption pressure sensor. Its operating
77  * range is 50-110 kPa.
78  *
79  * @image html mpl3115a2.jpg
80  * @snippet mpl3115a2.cxx Interesting
81  */
82 class MPL3115A2 {
83     public:
84         /**
85          * Instantiates an MPL3115A2 object
86          *
87          * @param bus Number of the used bus
88          * @param devAddr Address of the used I2C device
89          * @param mode MPL3115A2 oversampling (6 = 64x)
90          */
91         MPL3115A2(int bus, int devAddr=MPL3115A2_I2C_ADDRESS, uint8_t mode=6);
92 
93         /**
94          * MPL3115A2 object destructor; basically, it closes the I2C connection.
95          * ~MPL3115A2();
96          * no need for this here, as the I2c connection will be closed when the
97          * m_i2ControlCtx variable will go out of scope
98          **/
99 
100         /**
101          * Tests the sensor and tries to determine if the sensor is operating by looking
102          * for small variations in the value
103          */
104         int testSensor(void);
105 
106         /**
107          * Performs a soft reset of the MPL3115A2 device to ensure
108          * it is in a known state. This function can be used to reset
109          * the min/max temperature and pressure values.
110          */
111         int resetSensor(void);
112 
113         /**
114          * Dumps out the I2C register block to stdout
115          */
116         void dumpSensor(void);
117 
118         /**
119          * Initiates a temperature/pressure mesasurement and waits for the function
120          * to complete. Temperature and pressure registers can be read
121          * after this call.
122          */
123         int sampleData(void);
124 
125         /**
126          * Reads the pressure value from MPL3115A2 [Pa * 100]
127          *
128          * @param reg Base address of the pressure register
129          */
130         int32_t getPressureReg(int reg);
131 
132         /**
133          * Reads the temperature value from MPL3115A2 [degC * 1000]
134          *
135          * @param reg Base address of the temperature register
136          */
137         int32_t getTempReg(int reg);
138 
139         /**
140          * Reads the current pressure value from MPL3115A2 [Pa]
141          *
142          * @param bSampleData Sets non-zero to a sample reading
143          */
144         float getPressure(int bSampleData = true);
145 
146         /**
147          * Reads the current temperature value from MPL3115A2 [degC]
148          *
149          * @param bSampleData Sets non-zero to a sample reading
150          */
151         float getTemperature(int bSampleData = true);
152 
153         /**
154          * Reads the current pressure and, using a known altitude, calculates
155          * the sea level pressure value [Pa]
156          * This function should be preceded by the sampleData() call
157          *
158          * @param altitudeMeters Altitude in meters
159          */
160         float getSealevelPressure(float altitudeMeters = 0.0);
161 
162         /**
163          * Reads the current pressure and, using a known sea level pressure,
164          * calculates the altitude value [m]
165          * This function should be preceded by the sampleData() call
166          *
167          * @param sealevelPressure Current sea level pressure
168          */
169         float getAltitude (float sealevelPressure = 101325.0);
170 
171         /**
172          * Defines the oversampling setting (ranges from 0 to 7). The
173          * value represents 2^n samples (ranging from 1 to 128). The
174          * time to calculate a sample is approximately (2^n * 4 + 2) ms
175          *
176          * @param oversampling New oversampling value
177          */
178         void setOversampling(uint8_t oversampling);
179 
180         /**
181          * Returns the current oversampling value
182          */
183         uint8_t getOversampling(void);
184 
185         /**
186          * Reads the maximum measured temperature [degC]
187          */
188         float getTemperatureMax(void);
189 
190         /**
191          * Reads the minimum measured temperature [degC]
192          */
193         float getTemperatureMin(void);
194 
195         /**
196          * Reads the maximum measured pressure [Pa]
197          */
198         float getPressureMax (void);
199 
200         /**
201          * Reads the minimum measured pressure [Pa]
202          */
203         float getPressureMin (void);
204 
205         /**
206          * Converts temperature from degC*1000 to degF*1000
207          *
208          * @param iTemp Temperature in degC
209          */
210         float convertTempCtoF(float fTemp);
211 
212         /**
213          * Converts pressure from Pa*100 to inHg*10000
214          * This is set for 15degC (Pa = 0.0002961 in Hg)
215          * TODO: Change the function to add temperature calibration
216          *
217          * @param iPressure Pressure in Pa
218          */
219         float convertPaToinHg(float fPressure);
220 
221         /**
222          * Writes one byte to an I2C register
223          *
224          * @param reg Address of the register
225          * @param value Byte to be written
226          */
227         mraa::Result i2cWriteReg (uint8_t reg, uint8_t value);
228 
229         /**
230          * Reads two bytes from an I2C register
231          *
232          * @param reg Address of the register
233          */
234         uint16_t i2cReadReg_16 (int reg);
235 
236         /**
237          * Reads a one-byte register
238          *
239          * @param reg Address of the register
240          */
241         uint8_t i2cReadReg_8 (int reg);
242 
243     private:
244         std::string m_name;
245 
246         int m_controlAddr;
247         int m_bus;
248         mraa::I2c m_i2ControlCtx;
249 
250         uint8_t m_oversampling;
251         int32_t m_iPressure;
252         int32_t m_iTemperature;
253 };
254 
255 }
256 
257