lps331ap.c
3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_lps331ap
* @{
*
* @file
* @brief Device driver implementation for the LPS331AP pressure sensor
*
* @note The current driver implementation is very basic and allows only for polling the
* devices temperature and pressure values. Threshold values and interrupts are not
* used.
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
*
* @}
*/
#include <stdint.h>
#include "periph/i2c.h"
#include "lps331ap.h"
#include "lps331ap-internal.h"
/**
* @brief default I2C bus speed for this sensor
*/
#define BUS_SPEED I2C_SPEED_FAST
/**
* @brief pressure divider for norming pressure output
*/
#define PRES_DIVIDER (4096U)
/**
* @brief temperature base value and divider for norming temperature output
*/
#define TEMP_BASE (42.5f)
#define TEMP_DIVIDER (480U)
int lps331ap_init(lps331ap_t *dev, i2c_t i2c, uint8_t address, lps331ap_rate_t rate)
{
uint8_t tmp;
/* save device specifics */
dev->i2c = i2c;
dev->address = address;
/* Acquire exclusive access to the bus. */
i2c_acquire(dev->i2c);
/* initialize underlying I2C bus */
if (i2c_init_master(dev->i2c, BUS_SPEED) < 0) {
/* Release the bus for other threads. */
i2c_release(dev->i2c);
return -1;
}
/* configure device, for simple operation only CTRL_REG1 needs to be touched */
tmp = LPS331AP_CTRL_REG1_DBDU | LPS331AP_CTRL_REG1_PD |
(rate << LPS331AP_CTRL_REG1_ODR_POS);
if (i2c_write_reg(dev->i2c, dev->address, LPS331AP_REG_CTRL_REG1, tmp) != 1) {
i2c_release(dev->i2c);
return -1;
}
i2c_release(dev->i2c);
return 0;
}
int lps331ap_read_temp(const lps331ap_t *dev)
{
uint8_t tmp;
int16_t val = 0;
float res = TEMP_BASE; /* reference value -> see datasheet */
i2c_acquire(dev->i2c);
i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_TEMP_OUT_L, &tmp);
val |= tmp;
i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_TEMP_OUT_H, &tmp);
i2c_release(dev->i2c);
val |= ((uint16_t)tmp << 8);
/* compute actual temperature value in °C */
res += ((float)val) / TEMP_DIVIDER;
/* return temperature in m°C */
return (int)(res * 1000);
}
int lps331ap_read_pres(const lps331ap_t *dev)
{
uint8_t tmp;
int32_t val = 0;
float res;
i2c_acquire(dev->i2c);
i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_PRESS_OUT_XL, &tmp);
val |= tmp;
i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_PRESS_OUT_L, &tmp);
val |= ((uint32_t)tmp << 8);
i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_PRESS_OUT_H, &tmp);
i2c_release(dev->i2c);
val |= ((uint32_t)tmp << 16);
/* see if value is negative */
if (tmp & 0x80) {
val |= ((uint32_t)0xff << 24);
}
/* compute actual pressure value in mbar */
res = ((float)val) / PRES_DIVIDER;
return (int)res;
}
int lps331ap_enable(const lps331ap_t *dev)
{
uint8_t tmp;
int status;
i2c_acquire(dev->i2c);
if (i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_CTRL_REG1, &tmp) != 1) {
i2c_release(dev->i2c);
return -1;
}
tmp |= (LPS331AP_CTRL_REG1_PD);
status = i2c_write_reg(dev->i2c, dev->address, LPS331AP_REG_CTRL_REG1, tmp);
i2c_release(dev->i2c);
return status;
}
int lps331ap_disable(const lps331ap_t *dev)
{
uint8_t tmp;
int status;
i2c_acquire(dev->i2c);
if (i2c_read_reg(dev->i2c, dev->address, LPS331AP_REG_CTRL_REG1, &tmp) != 1) {
i2c_release(dev->i2c);
return -1;
}
tmp &= ~(LPS331AP_CTRL_REG1_PD);
status = i2c_write_reg(dev->i2c, dev->address, LPS331AP_REG_CTRL_REG1, tmp);
i2c_release(dev->i2c);
return status;
}