1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <string>
27 #include <mraa/common.hpp>
28 #include <mraa/i2c.hpp>
29 
30 #define HP20X_I2C_BUS 0
31 #define HP20X_DEFAULT_I2C_ADDR 0x76
32 
33 namespace upm {
34 
35   /**
36    * @brief HP20X I2C Barometer (High-Accuracy) library
37    * @defgroup hp20x libupm-hp20x
38    * @ingroup seeed i2c pressure
39    */
40 
41   /**
42    * @library hp20x
43    * @sensor hp20x
44    * @comname Grove Barometer (High-Accuracy)
45    * @altname HP20X Barometer (High-Accuracy)
46    * @type pressure
47    * @man seeed
48    * @web http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html
49    * @con i2c
50    *
51    * @brief API for the HP20X-based Grove Barometer (High-Accuracy)
52    *
53    * This is a high-accuracy barometer providing pressure, altitude,
54    * and temperature data. It can be calibrated for a given altitude
55    * offset, and a wide range of interrupt generating capabilities are
56    * supported. As usual, see the HP20X datasheet for more details.
57    *
58    * This module was developed using a Grove Barometer (High-Accuracy)
59    * based on an HP206C chip.
60    *
61    * @image html hp20x.jpg
62    * @snippet hp20x.cxx Interesting
63    */
64   class HP20X {
65   public:
66 
67     /**
68      * HP20X commands
69      */
70     typedef enum {
71       CMD_SOFT_RST              = 0x06,
72 
73       CMD_ADC_CVT               = 0x40, // mask - ANDed with DSR and CHNL bits
74 
75       CMD_READ_PT               = 0x10, // read pressure/temp
76       CMD_READ_AT               = 0x11, // read alt/temp
77 
78       CMD_READ_P                = 0x30, // read pressure only
79       CMD_READ_A                = 0x31, // read alt only
80       CMD_READ_T                = 0x32, // read temp only
81 
82       CMD_ANA_CAL               = 0x28, // recalibrate internal analog blocks
83 
84       CMD_READ_REG              = 0x80, // mask - ANDed with reg addr
85       CMD_WRITE_REG             = 0xc0  // mask - ANDed with reg addr
86     } HP20X_CMD_T;
87 
88     /**
89      * CHNL bits
90      */
91     typedef enum {
92       CHNL_PT                   = 0x00, // pressure and temperature
93       CHNL_T                    = 0x02, // temperature
94 
95       CHNL_SHIFT                = 0 // don't use, indicates position in REG
96     } CHNL_BITS_T;
97 
98     /**
99      * DSR bits
100      */
101     typedef enum {
102       DSR_4096                  = 0x00, // decimation rate of digital filter
103       DSR_2048                  = 0x01,
104       DSR_1024                  = 0x02,
105       DSR_512                   = 0x03,
106       DSR_256                   = 0x04,
107       DSR_128                   = 0x05,
108 
109       DSR_SHIFT                 = 2 // don't use, indicates position in REG
110     } DSR_BITS_T;
111 
112 
113     /**
114      * HP20X registers
115      */
116     typedef enum {
117       REG_ALT_OFF_LSB           = 0x00,
118       REG_ALT_OFF_MSB           = 0x01,
119 
120       REG_PA_H_TH_LSB           = 0x02, // Pres/Alt high threshold
121       REG_PA_H_TH_MSB           = 0x03,
122 
123       REG_PA_M_TH_LSB           = 0x04, // Pres/Alt medium threshold
124       REG_PA_M_TH_MSB           = 0x05,
125 
126       REG_PA_L_TH_LSB           = 0x06, // Pres/Alt low threshold
127       REG_PA_L_TH_MSB           = 0x07,
128 
129       REG_T_H_TH                = 0x08, // temperature high threshold
130       REG_T_M_TH                = 0x09,
131       REG_T_L_TH                = 0x0a,
132 
133       REG_INT_EN                = 0x0b, // interrupt enables
134       REG_INT_CFG               = 0x0c, // interrupt configuration
135       REG_INT_SRC               = 0x0d, // interrupt sources
136 
137       REG_PARA                  = 0x0e  // parameters config
138     } HP20X_REG_T;
139 
140     /**
141      * INT_EN bits
142      */
143     typedef enum {
144       INT_EN_T_WIN_EN           = 0x01,
145       INT_EN_PA_WIN_EN          = 0x02,
146 
147       INT_EN_T_TRAV_EN          = 0x04,
148       INT_EN_PA_TRAV_EN         = 0x08,
149 
150       INT_EN_T_RDY_EN           = 0x10,
151       INT_EN_PA_RDY_EN          = 0x20
152       // 0x40, 0x80 reserved
153     } INT_EN_BITS_T;
154 
155     /**
156      * INT_CFG bits
157      */
158     typedef enum {
159       INT_CFG_T_WIN_CFG          = 0x01,
160       INT_CFG_PA_WIN_CFG         = 0x02,
161 
162       INT_CFG_T_TRAV_CFG         = 0x04,
163       INT_CFG_PA_TRAV_CFG        = 0x08,
164 
165       INT_CFG_T_RDY_CFG          = 0x10,
166       INT_CFG_PA_RDY_CFG         = 0x20,
167 
168       INT_CFG_PA_MODE            = 0x40
169       // 0x80 reserved
170     } INT_CFG_BITS_T;
171 
172     /**
173      * INT_SRC bits
174      */
175     typedef enum {
176       INT_SRC_T_WIN              = 0x01,
177       INT_SRC_PA_WIN             = 0x02,
178 
179       INT_SRC_T_TRAV             = 0x04,
180       INT_SRC_PA_TRAV            = 0x08,
181 
182       INT_SRC_T_RDY              = 0x10,
183       INT_SRC_PA_RDY             = 0x20,
184 
185       INT_SRC_DEV_RDY            = 0x40, // device is ready
186 
187       INT_SRC_TH_ERR             = 0x80 // threshold error
188     } INT_SRC_BITS_T;
189 
190     /**
191      * PARA bits
192      */
193     typedef enum {
194       // 0x01-0x40 reserved
195       PARA_CMPS_EN               = 0x80 // compensation enable
196     } PARA_BITS_T;
197 
198     /**
199      * HP20X constructor
200      *
201      * @param bus I2C bus to use
202      * @param address Address for this device
203      */
204     HP20X(int bus=HP20X_I2C_BUS, uint8_t address=HP20X_DEFAULT_I2C_ADDR);
205 
206     /**
207      * HP20X destructor
208      */
209     ~HP20X();
210 
211     /**
212      * Sets up initial values and starts operation
213      *
214      * @param dsr Data sampling rate; one of the DSR_BITS_T values
215      * @return True if successful
216      */
217     bool init(DSR_BITS_T dsr=DSR_4096);
218 
219     /**
220      * Sends a command to the device
221      *
222      * @param cmd Command to send; usually, one of the HP20X_CMD_T values
223      * @return True if successful
224      */
225     bool writeCmd(uint8_t cmd);
226 
227     /**
228      * Writes a value to a register
229      *
230      * @param reg Register to write to; one of the HP20X_REG_T values
231      * @param data Value to write
232      * @return True if successful
233      */
234     bool writeReg(HP20X_REG_T reg, uint8_t data);
235 
236     /**
237      * Reads a register and returns its value
238      *
239      * @param reg Register to read; one of the HP20X_REG_T values
240      * @return Value of a specified register
241      */
242     uint8_t readReg(HP20X_REG_T reg);
243 
244     /**
245      * Reads 3 bytes of data in response to a conversion request, and
246      * converts it to an integer
247      *
248      * @return Value read back (temperature, pressure, etc.)
249      */
250     int readData();
251 
252     /**
253      * Checks to see if the DR_RDY bit is set, indicating the device
254      * can accept commands
255      *
256      * @return True if the device is ready, false otherwise
257      */
258     bool isReady();
259 
260     /**
261      * Checks to see if the device is ready, and sleeps/retries if not.
262      * Returns once the device indicates it's ready.
263      *
264      * @return True if the device is ready; false if retries are exhausted
265      */
266     bool waitforDeviceReady();
267 
268     /**
269      * Returns the temperature in Celsius
270      *
271      * @return Temperature
272      */
273     float getTemperature();
274 
275     /**
276      * Returns the pressure in millibars
277      *
278      * @return Pressure
279      */
280     float getPressure();
281 
282     /**
283      * Returns the computed altitude in meters
284      *
285      * @return Altitude
286      */
287     float getAltitude();
288 
289     /**
290      * Enables or disables the on-chip compensator. This allows the
291      * chip to filter and clean up the output data.
292      *
293      * @param enable True to enable, false otherwise
294      */
295     void compensationEnable(bool enable);
296 
297     /**
298      * Sets up the interrupt enable register. This register defines
299      * which events can cause a hardware interrupt pin to be pulled high
300      * (active).
301      *
302      * @param bits One or more of the INT_EN_BITS_T bits
303      * @return True if successful, false otherwise
304      */
305     bool setInterruptEnable(uint8_t bits);
306 
307     /**
308      * Sets up the interrupt configuration register. This register
309      * defines which events can cause an interrupt to be indicated.
310      *
311      * @param bits One or more of the INT_EN_BITS_T bits
312      * @return True if successful, false otherwise
313      */
314     bool setInterruptConfig(uint8_t bits);
315 
316     /**
317      * Gets the interrupt source register. This register indicates
318      * which interrupts have been triggered. In addition, it
319      * indicates when certain operations have been completed.
320      *
321      * @return One of more of the INT_SRC_BITS_T values
322      */
323     uint8_t getInterruptSource();
324 
325     /**
326      * Sets the data sampling rate. Higher rates are more precise, but
327      * take more time per measurement.
328      *
329      * @param dsr One of the DSR_BITS_T values
330      */
331     void setDSR(DSR_BITS_T dsr);
332 
333 
334     /**
335      * Starts an internal recalibration of analog blocks. This is
336      * faster than a soft reset.
337      */
338     void recalibrateInternal();
339 
340     /**
341      * Executes a soft reset. All register values are reset to power-on
342      * defaults. This function returns when the reset is
343      * complete and the device reports it is ready.
344      */
345     void softReset();
346 
347     /**
348      * Sets the altitude offset for your region. See the datasheet for
349      * more details. Setting this correctly for your region is
350      * required for accurate altitude data.
351      *
352      * @param off Offset
353      */
354     void setAltitudeOffset(int16_t off);
355 
356     /**
357      * Sets pressure/altitude thresholds for interrupt generation
358      *
359      * @param low Low threshold to generate an interrupt
360      * @param med Medium threshold to generate an interrupt
361      * @param high High threshold to generate an interrupt
362      */
363     void setPAThreshholds(int16_t low, int16_t med, int16_t high);
364 
365     /**
366      * Sets temperature thresholds for interrupt generation
367      *
368      * @param low Low threshold to generate an interrupt
369      * @param med Medium threshold to generate an interrupt
370      * @param high High threshold to generate an interrupt
371      */
372     void setTemperatureThreshholds(int8_t low, int8_t med, int8_t high);
373 
374 
375   protected:
376     mraa::I2c m_i2c;
377 
378   private:
379     uint8_t m_addr;
380     uint8_t m_dsr;
381 
382   };
383 }
384 
385 
386