1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  *
4  *
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "aos/kernel.h"
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13 
14 /* ST BARO SENSOR REGISTER MAP */
15 #define LPS22HB_BIT(x) ((uint8_t)x)
16 #define LPS22HB_ADDRESS (uint8_t)0xB8
17 #define LPS22HB_DriverVersion_Major (uint8_t)1
18 #define LPS22HB_DriverVersion_Minor (uint8_t)0
19 #define LPS22HB_DriverVersion_Point (uint8_t)0
20 #define LPS22HB_WHO_AM_I_REG (uint8_t)0x0F
21 #define LPS22HB_WHO_AM_I_VAL (uint8_t)0xB1
22 #define LPS22HB_REF_P_XL_REG (uint8_t)0x15
23 #define LPS22HB_REF_P_L_REG (uint8_t)0x16
24 #define LPS22HB_REF_P_H_REG (uint8_t)0x17
25 #define LPS22HB_RES_CONF_REG (uint8_t)0x1A
26 #define LPS22HB_RES_CONF_REG (uint8_t)0x1A
27 #define LPS22HB_RES_CONF_REG (uint8_t)0x1A
28 #define LPS22HB_LCEN_MASK (uint8_t)0x01
29 #define LPS22HB_LCEN_POWERON (uint8_t)0x00
30 #define LPS22HB_LCEN_LOWPOWER (uint8_t)0x01
31 #define LPS22HB_CTRL_REG1 (uint8_t)0x10
32 #define LPS22HB_ODR_MASK (uint8_t)0x70
33 #define LPS22HB_LPFP_MASK (uint8_t)0x08
34 #define LPS22HB_LPFP_CUTOFF_MASK (uint8_t)0x04
35 #define LPS22HB_BDU_MASK (uint8_t)0x02
36 #define LPS22HB_SIM_MASK (uint8_t)0x01
37 #define LPS22HB_LPFP_BIT LPS22HB_BIT(3)
38 #define LPS22HB_CTRL_REG2 (uint8_t)0x11
39 #define LPS22HB_BOOT_BIT LPS22HB_BIT(7)
40 #define LPS22HB_FIFO_EN_BIT LPS22HB_BIT(6)
41 #define LPS22HB_WTM_EN_BIT LPS22HB_BIT(5)
42 #define LPS22HB_ADD_INC_BIT LPS22HB_BIT(4)
43 #define LPS22HB_I2C_BIT LPS22HB_BIT(3)
44 #define LPS22HB_SW_RESET_BIT LPS22HB_BIT(2)
45 #define LPS22HB_FIFO_EN_MASK (uint8_t)0x40
46 #define LPS22HB_WTM_EN_MASK (uint8_t)0x20
47 #define LPS22HB_ADD_INC_MASK (uint8_t)0x10
48 #define LPS22HB_I2C_MASK (uint8_t)0x08
49 #define LPS22HB_ONE_SHOT_MASK (uint8_t)0x01
50 #define LPS22HB_CTRL_REG3 (uint8_t)0x12
51 #define LPS22HB_PP_OD_BIT LPS22HB_BIT(6)
52 #define LPS22HB_FIFO_FULL_BIT LPS22HB_BIT(5)
53 #define LPS22HB_FIFO_FTH_BIT LPS22HB_BIT(4)
54 #define LPS22HB_FIFO_OVR_BIT LPS22HB_BIT(3)
55 #define LPS22HB_DRDY_BIT LPS22HB_BIT(2)
56 #define LPS22HB_INT_H_L_MASK (uint8_t)0x80
57 #define LPS22HB_PP_OD_MASK (uint8_t)0x40
58 #define LPS22HB_FIFO_FULL_MASK (uint8_t)0x20
59 #define LPS22HB_FIFO_FTH_MASK (uint8_t)0x10
60 #define LPS22HB_FIFO_OVR_MASK (uint8_t)0x08
61 #define LPS22HB_DRDY_MASK (uint8_t)0x04
62 #define LPS22HB_INT_S12_MASK (uint8_t)0x03
63 #define LPS22HB_INTERRUPT_CFG_REG (uint8_t)0x0B
64 #define LPS22HB_DIFF_EN_BIT LPS22HB_BIT(3)
65 #define LPS22HB_LIR_BIT LPS22HB_BIT(2)
66 #define LPS22HB_PLE_BIT LPS22HB_BIT(1)
67 #define LPS22HB_PHE_BIT LPS22HB_BIT(0)
68 #define LPS22HB_AUTORIFP_MASK (uint8_t)0x80
69 #define LPS22HB_RESET_ARP_MASK (uint8_t)0x40
70 #define LPS22HB_AUTOZERO_MASK (uint8_t)0x20
71 #define LPS22HB_RESET_AZ_MASK (uint8_t)0x10
72 #define LPS22HB_DIFF_EN_MASK (uint8_t)0x08
73 #define LPS22HB_LIR_MASK (uint8_t)0x04
74 #define LPS22HB_PLE_MASK (uint8_t)0x02
75 #define LPS22HB_PHE_MASK (uint8_t)0x01
76 #define LPS22HB_INTERRUPT_SOURCE_REG (uint8_t)0x25
77 #define LPS22HB_BOOT_STATUS_BIT LPS22HB_BIT(7)
78 #define LPS22HB_IA_BIT LPS22HB_BIT(2)
79 #define LPS22HB_PL_BIT LPS22HB_BIT(1)
80 #define LPS22HB_PH_BIT LPS22HB_BIT(0)
81 #define LPS22HB_BOOT_STATUS_MASK (uint8_t)0x80
82 #define LPS22HB_IA_MASK (uint8_t)0x04
83 #define LPS22HB_PL_MASK (uint8_t)0x02
84 #define LPS22HB_PH_MASK (uint8_t)0x01
85 #define LPS22HB_STATUS_REG (uint8_t)0x27
86 #define LPS22HB_TOR_BIT LPS22HB_BIT(5)
87 #define LPS22HB_POR_BIT LPS22HB_BIT(4)
88 #define LPS22HB_TDA_BIT LPS22HB_BIT(1)
89 #define LPS22HB_PDA_BIT LPS22HB_BIT(0)
90 #define LPS22HB_TOR_MASK (uint8_t)0x20
91 #define LPS22HB_POR_MASK (uint8_t)0x10
92 #define LPS22HB_TDA_MASK (uint8_t)0x02
93 #define LPS22HB_PDA_MASK (uint8_t)0x01
94 #define LPS22HB_PRESS_OUT_XL_REG (uint8_t)0x28
95 #define LPS22HB_PRESS_OUT_L_REG (uint8_t)0x29
96 #define LPS22HB_PRESS_OUT_H_REG (uint8_t)0x2A
97 #define LPS22HB_TEMP_OUT_L_REG (uint8_t)0x2B
98 #define LPS22HBH_TEMP_OUT_H_REG (uint8_t)0x2C
99 #define LPS22HB_THS_P_LOW_REG (uint8_t)0x0C
100 #define LPS22HB_THS_P_HIGH_REG (uint8_t)0x0D
101 #define LPS22HB_CTRL_FIFO_REG (uint8_t)0x14
102 #define LPS22HB_FIFO_MODE_MASK (uint8_t)0xE0
103 #define LPS22HB_WTM_POINT_MASK (uint8_t)0x1F
104 #define LPS22HB_STATUS_FIFO_REG (uint8_t)0x26
105 #define LPS22HB_FTH_FIFO_BIT LPS22HB_BIT(7)
106 #define LPS22HB_OVR_FIFO_BIT LPS22HB_BIT(6)
107 #define LPS22HB_FTH_FIFO_MASK (uint8_t)0x80
108 #define LPS22HB_OVR_FIFO_MASK (uint8_t)0x40
109 #define LPS22HB_LEVEL_FIFO_MASK (uint8_t)0x3F
110 #define LPS22HB_FIFO_EMPTY (uint8_t)0x00
111 #define LPS22HB_FIFO_FULL (uint8_t)0x18
112 #define LPS22HB_RPDS_H_REG (uint8_t)0x19
113 #define LPS22HB_CLOCK_TREE_CONFIG (uint8_t)0x43
114 #define LPS22HB_CTE_MASK (uint8_t)0x20
115 
116 #define LPS22HB_I2C_ADDR1_R (uint8_t)0xB9
117 #define LPS22HB_I2C_ADDR1_W (uint8_t)0xB8
118 #define LPS22HB_I2C_ADDR2_R (uint8_t)0xBB
119 #define LPS22HB_I2C_ADDR2_W (uint8_t)0xBZ
120 
121 #define LPS22HB_I2C_ADDR1 (0x5C)
122 #define LPS22HB_I2C_ADDR2 (0x5D)
123 #define LPS22HB_I2C_ADDR_TRANS(n) ((n) << 1)
124 #define LPS22HB_I2C_ADDR LPS22HB_I2C_ADDR_TRANS(LPS22HB_I2C_ADDR2)
125 
126 
127 typedef enum
128 {
129     LPS22HB_ODR_ONE_SHOT = (uint8_t)0x00, /*!< Output Data Rate: one shot */
130     LPS22HB_ODR_1HZ      = (uint8_t)0x10, /*!< Output Data Rate: 1Hz */
131     LPS22HB_ODR_10HZ     = (uint8_t)0x20, /*!< Output Data Rate: 10Hz */
132     LPS22HB_ODR_25HZ     = (uint8_t)0x30, /*!< Output Data Rate: 25Hz */
133     LPS22HB_ODR_50HZ     = (uint8_t)0x40, /*!< Output Data Rate: 50Hz */
134     LPS22HB_ODR_75HZ     = (uint8_t)0x50  /*!< Output Data Rate: 75Hz */
135 } lps22hb_odr_e;
136 
137 typedef enum
138 {
139     LPS22HB_BDU_CONTINUOUS_UPDATE =
140       (uint8_t)0x00, /*!< Data updated continuously */
141     LPS22HB_BDU_NO_UPDATE =
142       (uint8_t)0x02 /*!< Data updated after a read operation */
143 } lps22hb_bdu_e;
144 
145 i2c_dev_t lps22hb_ctx = {
146     .port                 = 1,
147     .config.address_width = 8,
148     .config.freq          = 400000,
149     .config.dev_addr      = LPS22HB_I2C_ADDR,
150 };
151 
drv_baro_st_lps22hb_hz2odr(int hz)152 static lps22hb_odr_e drv_baro_st_lps22hb_hz2odr(int hz)
153 {
154     if (hz > 50)
155         return LPS22HB_ODR_75HZ;
156     else if (hz > 25)
157         return LPS22HB_ODR_50HZ;
158     else if (hz > 10)
159         return LPS22HB_ODR_25HZ;
160     else if (hz > 1)
161         return LPS22HB_ODR_10HZ;
162     else
163         return LPS22HB_ODR_1HZ;
164 }
165 
drv_baro_st_lps22hb_validate_id(i2c_dev_t * drv,uint8_t id_value)166 static int drv_baro_st_lps22hb_validate_id(i2c_dev_t *drv, uint8_t id_value)
167 {
168     uint8_t value = 0x00;
169     int     ret   = 0;
170 
171     if (drv == NULL) {
172         return -1;
173     }
174 
175     ret = sensor_i2c_read(drv, LPS22HB_WHO_AM_I_REG, &value, I2C_DATA_LEN,
176                           I2C_OP_RETRIES);
177     if (unlikely(ret)) {
178         return ret;
179     }
180 
181     if (id_value != value) {
182         return -1;
183     }
184     return 0;
185 }
186 
drv_baro_st_lps22hb_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)187 static int drv_baro_st_lps22hb_set_power_mode(i2c_dev_t *      drv,
188                                               dev_power_mode_e mode)
189 {
190     uint8_t value = 0x00;
191     int     ret   = 0;
192 
193     ret = sensor_i2c_read(drv, LPS22HB_RES_CONF_REG, &value, I2C_DATA_LEN,
194                           I2C_OP_RETRIES);
195     if (unlikely(ret)) {
196         return ret;
197     }
198 
199     switch (mode) {
200         case DEV_POWER_ON: {
201             value &= ~LPS22HB_LCEN_MASK;
202             value |= LPS22HB_LCEN_POWERON;
203             ret = sensor_i2c_write(drv, LPS22HB_RES_CONF_REG, &value,
204                                    I2C_DATA_LEN, I2C_OP_RETRIES);
205             if (unlikely(ret)) {
206                 return ret;
207             }
208         } break;
209 
210         case DEV_POWER_OFF: {
211             value |= LPS22HB_LCEN_LOWPOWER;
212             ret = sensor_i2c_write(drv, LPS22HB_RES_CONF_REG, &value,
213                                    I2C_DATA_LEN, I2C_OP_RETRIES);
214             if (unlikely(ret)) {
215                 return ret;
216             }
217         } break;
218 
219         default:
220             break;
221     }
222     return 0;
223 }
224 
drv_baro_st_lps22hb_set_odr(i2c_dev_t * drv,lps22hb_odr_e odr)225 static int drv_baro_st_lps22hb_set_odr(i2c_dev_t *drv, lps22hb_odr_e odr)
226 {
227     uint8_t value = 0x00;
228     int     ret   = 0;
229 
230     ret = sensor_i2c_read(drv, LPS22HB_CTRL_REG1, &value, I2C_DATA_LEN,
231                           I2C_OP_RETRIES);
232     if (unlikely(ret)) {
233         return ret;
234     }
235     value &= ~LPS22HB_ODR_MASK;
236     value |= (uint8_t)odr;
237 
238     ret = sensor_i2c_write(drv, LPS22HB_CTRL_REG1, &value, I2C_DATA_LEN,
239                            I2C_OP_RETRIES);
240     if (unlikely(ret)) {
241         return ret;
242     }
243     return 0;
244 }
245 
drv_baro_st_lps22hb_set_bdu(i2c_dev_t * drv,lps22hb_bdu_e bdu)246 static int drv_baro_st_lps22hb_set_bdu(i2c_dev_t *drv, lps22hb_bdu_e bdu)
247 {
248     uint8_t value = 0x00;
249     int     ret   = 0;
250 
251     ret = sensor_i2c_read(drv, LPS22HB_CTRL_REG1, &value, I2C_DATA_LEN,
252                           I2C_OP_RETRIES);
253     if (unlikely(ret)) {
254         return ret;
255     }
256     value &= ~LPS22HB_BDU_MASK;
257     value |= (uint8_t)bdu;
258 
259     ret = sensor_i2c_write(drv, LPS22HB_CTRL_REG1, &value, I2C_DATA_LEN,
260                            I2C_OP_RETRIES);
261     if (unlikely(ret)) {
262         return ret;
263     }
264     return 0;
265 }
266 
drv_baro_st_lps22hb_set_default_config(i2c_dev_t * drv)267 static int drv_baro_st_lps22hb_set_default_config(i2c_dev_t *drv)
268 {
269     int     ret   = 0;
270     ret           = drv_baro_st_lps22hb_set_power_mode(drv, DEV_POWER_OFF);
271     if (unlikely(ret)) {
272         return ret;
273     }
274     ret = drv_baro_st_lps22hb_set_odr(drv, LPS22HB_ODR_25HZ);
275     if (unlikely(ret)) {
276         return ret;
277     }
278     ret = drv_baro_st_lps22hb_set_bdu(drv, LPS22HB_BDU_NO_UPDATE);
279     if (unlikely(ret)) {
280         return ret;
281     }
282     /* you also can set the low-pass filter and cut off config here */
283     return 0;
284 }
285 
286 
drv_baro_st_lps22hb_irq_handle(void)287 static void drv_baro_st_lps22hb_irq_handle(void)
288 {
289     /* no handle so far */
290 }
291 
drv_baro_st_lps22hb_open(void)292 static int drv_baro_st_lps22hb_open(void)
293 {
294     int ret = 0;
295     ret     = drv_baro_st_lps22hb_set_power_mode(&lps22hb_ctx, DEV_POWER_ON);
296     if (unlikely(ret)) {
297         return -1;
298     }
299     LOG("%s %s successfully \n", SENSOR_STR, __func__);
300     return 0;
301 }
302 
drv_baro_st_lps22hb_close(void)303 static int drv_baro_st_lps22hb_close(void)
304 {
305     int ret = 0;
306     ret     = drv_baro_st_lps22hb_set_power_mode(&lps22hb_ctx, DEV_POWER_OFF);
307     if (unlikely(ret)) {
308         return -1;
309     }
310     LOG("%s %s successfully \n", SENSOR_STR, __func__);
311     return 0;
312 }
313 
314 
drv_baro_st_lps22hb_read(void * buf,size_t len)315 static int drv_baro_st_lps22hb_read(void *buf, size_t len)
316 {
317     int               ret = 0;
318     size_t            size;
319     uint8_t           data[3];
320     barometer_data_t *pdata = (barometer_data_t *)buf;
321     if (buf == NULL) {
322         return -1;
323     }
324 
325     size = sizeof(barometer_data_t);
326     if (len < size) {
327         return -1;
328     }
329 
330     ret = sensor_i2c_read(&lps22hb_ctx, LPS22HB_PRESS_OUT_XL_REG, &data[0],
331                           I2C_DATA_LEN, I2C_OP_RETRIES);
332     ret |= sensor_i2c_read(&lps22hb_ctx, LPS22HB_PRESS_OUT_L_REG, &data[1],
333                            I2C_DATA_LEN, I2C_OP_RETRIES);
334     ret |= sensor_i2c_read(&lps22hb_ctx, LPS22HB_PRESS_OUT_H_REG, &data[2],
335                            I2C_DATA_LEN, I2C_OP_RETRIES);
336     if (unlikely(ret)) {
337         return -1;
338     }
339 
340     /* hatch the baro data here*/
341     for (int i = 0; i < 3; i++) {
342         pdata->p |= (((uint32_t)data[i]) << (8 * i));
343     }
344 
345     /* convert the 2's complement 24 bit to 2's complement 32 bit */
346     if ((pdata->p & 0x00800000) != 0) {
347         pdata->p |= 0xFF000000;
348     }
349     pdata->p = ((pdata->p) * 100) / 4096;
350     // pdata->p = pdata->p/100;
351     pdata->timestamp = aos_now_ms();
352 
353     return (int)size;
354 }
355 
drv_baro_st_lps22hb_write(const void * buf,size_t len)356 static int drv_baro_st_lps22hb_write(const void *buf, size_t len)
357 {
358     return 0;
359 }
360 
drv_baro_st_lps22hb_ioctl(int cmd,unsigned long arg)361 static int drv_baro_st_lps22hb_ioctl(int cmd, unsigned long arg)
362 {
363     int ret = 0;
364 
365     switch (cmd) {
366         case SENSOR_IOCTL_ODR_SET: {
367             lps22hb_odr_e odr = drv_baro_st_lps22hb_hz2odr(arg);
368             ret               = drv_baro_st_lps22hb_set_odr(&lps22hb_ctx, odr);
369             if (unlikely(ret)) {
370                 return -1;
371             }
372         } break;
373         case SENSOR_IOCTL_SET_POWER: {
374             ret = drv_baro_st_lps22hb_set_power_mode(&lps22hb_ctx, arg);
375             if (unlikely(ret)) {
376                 return -1;
377             }
378         } break;
379         case SENSOR_IOCTL_GET_INFO: {
380             /* fill the dev info here */
381             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
382             info->model             = "LPS22HB";
383             info->range_max         = 1260;
384             info->range_min         = 260;
385             info->unit              = pa;
386 
387         } break;
388 
389         default:
390             break;
391     }
392 
393     LOG("%s %s successfully \n", SENSOR_STR, __func__);
394     return 0;
395 }
396 
drv_baro_st_lps22hb_init(void)397 int drv_baro_st_lps22hb_init(void)
398 {
399     int          ret = 0;
400     sensor_obj_t sensor;
401 
402     memset(&sensor, 0, sizeof(sensor));
403 
404     /* fill the sensor obj parameters here */
405     sensor.tag        = TAG_DEV_BARO;
406     sensor.path       = dev_baro_path;
407     sensor.io_port    = I2C_PORT;
408     sensor.open       = drv_baro_st_lps22hb_open;
409     sensor.close      = drv_baro_st_lps22hb_close;
410     sensor.read       = drv_baro_st_lps22hb_read;
411     sensor.write      = drv_baro_st_lps22hb_write;
412     sensor.ioctl      = drv_baro_st_lps22hb_ioctl;
413     sensor.irq_handle = drv_baro_st_lps22hb_irq_handle;
414 
415 
416     ret = sensor_create_obj(&sensor);
417     if (unlikely(ret)) {
418         return -1;
419     }
420 
421     ret = drv_baro_st_lps22hb_validate_id(&lps22hb_ctx, LPS22HB_WHO_AM_I_VAL);
422     if (unlikely(ret)) {
423         return -1;
424     }
425     /* set the default config for the sensor here */
426     ret = drv_baro_st_lps22hb_set_default_config(&lps22hb_ctx);
427     if (unlikely(ret)) {
428         return -1;
429     }
430 
431     LOG("%s %s successfully \n", SENSOR_STR, __func__);
432     return 0;
433 }
434 
435 SENSOR_DRV_ADD(drv_baro_st_lps22hb_init);
436 
437