aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c')
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c b/lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c
new file mode 100644
index 000000000..4b22ea9f3
--- /dev/null
+++ b/lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c
@@ -0,0 +1,207 @@
1/*
2 MCP9808 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#define I2C_HELPERS_AUTOMATIC_DRV TRUE
18
19#include "hal.h"
20#include "i2c_helpers.h"
21#include "mcp9808.h"
22
23// http://www.mouser.com/ds/2/268/25095A-15487.pdf
24// http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf
25
26
27/*===========================================================================*/
28/* Driver local definitions. */
29/*===========================================================================*/
30
31/* I2C Register */
32#define MCP9808_REG_CONFIG 0x01
33#define MCP9808_REG_UPPER_TEMP 0x02
34#define MCP9808_REG_LOWER_TEMP 0x03
35#define MCP9808_REG_CRIT_TEMP 0x04
36#define MCP9808_REG_AMBIENT_TEMP 0x05
37#define MCP9808_REG_MANUF_ID 0x06
38#define MCP9808_REG_DEVICE_ID 0x07
39#define MCP9808_REG_RESOLUTION 0x08
40
41/* Config */
42#define MCP9808_REG_CONFIG_SHUTDOWN 0x0100
43#define MCP9808_REG_CONFIG_CRITLOCKED 0x0080
44#define MCP9808_REG_CONFIG_WINLOCKED 0x0040
45#define MCP9808_REG_CONFIG_INTCLR 0x0020
46#define MCP9808_REG_CONFIG_ALERTSTAT 0x0010
47#define MCP9808_REG_CONFIG_ALERTCTRL 0x0008
48#define MCP9808_REG_CONFIG_ALERTSEL 0x0002
49#define MCP9808_REG_CONFIG_ALERTPOL 0x0002
50#define MCP9808_REG_CONFIG_ALERTMODE 0x0001
51
52/* Device Id */
53#define MCP9808_MANUF_ID 0x0054
54#define MCP9808_DEVICE_ID 0x0400
55
56/* Resolution */
57#define MCP9808_RES_2 0x00 /* 1/2 = 0.5 */
58#define MCP9808_RES_4 0x01 /* 1/4 = 0.25 */
59#define MCP9808_RES_8 0x10 /* 1/8 = 0.125 */
60#define MCP9808_RES_16 0x11 /* 1/16 = 0.0625 */
61
62/* Time in milli-seconds */
63#define MCP9808_DELAY_ACQUIRE_RES_2 30
64#define MCP9808_DELAY_ACQUIRE_RES_4 65
65#define MCP9808_DELAY_ACQUIRE_RES_8 130
66#define MCP9808_DELAY_ACQUIRE_RES_16 250
67
68/*===========================================================================*/
69/* Driver exported variables. */
70/*===========================================================================*/
71
72/*===========================================================================*/
73/* Driver local variables and types. */
74/*===========================================================================*/
75
76/*===========================================================================*/
77/* Driver local functions. */
78/*===========================================================================*/
79
80static inline msg_t
81_apply_config(MCP9808_drv *drv) {
82 struct __attribute__((packed)) {
83 uint8_t reg;
84 uint16_t conf;
85 } tx = { MCP9808_REG_CONFIG, cpu_to_be16(drv->cfg) };
86
87 return i2c_send((uint8_t*)&tx, sizeof(tx));
88}
89
90static inline msg_t
91_decode_measure(MCP9808_drv *drv,
92 uint16_t val, float *temperature) {
93
94 /* Temperature */
95 if (temperature) {
96 float temp = val & 0x0fff;
97 if (val & 0x1000) temp -= 0x1000;
98
99 float factor = 16.0F;
100 switch(drv->resolution) {
101 case RES_2 : factor = 2.0F; break;
102 case RES_4 : factor = 4.0F; break;
103 case RES_8 : factor = 8.0F; break;
104 case RES_16: factor = 16.0F; break;
105 }
106
107 *temperature = temp / factor;
108 }
109
110 /* Ok */
111 return MSG_OK;
112}
113
114
115/*===========================================================================*/
116/* Driver exported functions. */
117/*===========================================================================*/
118
119void
120MCP9808_init(MCP9808_drv *drv, MCP9808_config *config) {
121 drv->config = config;
122 drv->cfg = 0;
123 drv->resolution = RES_16; /* power up default */
124 drv->state = SENSOR_INIT;
125}
126
127msg_t
128MCP9808_check(MCP9808_drv *drv) {
129 uint16_t manuf, device;
130
131 msg_t msg;
132 if (((msg = i2c_reg_recv16_be(MCP9808_REG_MANUF_ID, &manuf )) < MSG_OK) ||
133 ((msg = i2c_reg_recv16_be(MCP9808_REG_DEVICE_ID, &device)) < MSG_OK))
134 return msg;
135
136 if ((manuf != MCP9808_MANUF_ID) || (device != MCP9808_DEVICE_ID))
137 return SENSOR_NOTFOUND;
138
139 return MSG_OK;
140}
141
142msg_t
143MCP9808_setResolution(MCP9808_drv *drv, MCP9808_resolution_t res) {
144 struct __attribute__((packed)) {
145 uint8_t reg;
146 uint8_t resolution;
147 } tx = { MCP9808_REG_RESOLUTION, res };
148
149 msg_t msg;
150 if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
151 return msg;
152
153 drv->resolution = res;
154 return MSG_OK;
155}
156
157msg_t
158MCP9808_start(MCP9808_drv *drv) {
159 drv->cfg &= ~(MCP9808_REG_CONFIG_SHUTDOWN);
160 return _apply_config(drv);
161}
162
163msg_t
164MCP9808_stop(MCP9808_drv *drv) {
165 drv->cfg |= (MCP9808_REG_CONFIG_SHUTDOWN);
166 return _apply_config(drv);
167}
168
169unsigned int
170MCP9808_getAcquisitionTime(MCP9808_drv *drv) {
171 switch(drv->resolution) {
172 case RES_2 : return MCP9808_DELAY_ACQUIRE_RES_2;
173 case RES_4 : return MCP9808_DELAY_ACQUIRE_RES_4;
174 case RES_8 : return MCP9808_DELAY_ACQUIRE_RES_8;
175 case RES_16: return MCP9808_DELAY_ACQUIRE_RES_16;
176 }
177 osalDbgAssert(false, "OOPS");
178 return 0;
179}
180
181msg_t
182MCP9808_readMeasure(MCP9808_drv *drv,
183 float *temperature) {
184
185 msg_t msg;
186 uint16_t val;
187
188 if ((msg = i2c_reg_recv16_be(MCP9808_REG_AMBIENT_TEMP, &val)) < MSG_OK)
189 return msg;
190
191 return _decode_measure(drv, val, temperature);
192}
193
194
195msg_t
196MCP9808_readTemperature(MCP9808_drv *drv,
197 float *temperature) {
198 osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
199
200 msg_t msg;
201 uint16_t val;
202
203 if ((msg = i2c_reg_recv16_be(MCP9808_REG_AMBIENT_TEMP, &val)) < MSG_OK)
204 return msg;
205
206 return _decode_measure(drv, val, temperature);
207}