aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c')
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c b/lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c
new file mode 100644
index 000000000..c0bbee0ce
--- /dev/null
+++ b/lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c
@@ -0,0 +1,272 @@
1/*
2 TSL2591 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/**
18 *
19 * DOC: http://ams.com/eng/content/download/389383/1251117/221235
20 */
21
22#define I2C_HELPERS_AUTOMATIC_DRV TRUE
23
24#include "hal.h"
25#include "i2c_helpers.h"
26#include "tsl2591.h"
27
28/*===========================================================================*/
29/* Driver local definitions. */
30/*===========================================================================*/
31
32#define TSL2591_LUX_DF (408.0F)
33#define TSL2591_LUX_COEFB (1.64F) // CH0 coefficient
34#define TSL2591_LUX_COEFC (0.59F) // CH1 coefficient A
35#define TSL2591_LUX_COEFD (0.86F) // CH2 coefficient B
36
37/* I2C registers */
38#define TSL2591_REG_ENABLE 0x00
39#define TSL2591_REG_CONFIG 0x01 /**< @brief gain and integration */
40#define TSL2591_REG_AILTL 0x04
41#define TSL2591_REG_AILTH 0x05
42#define TSL2591_REG_AIHTL 0x06
43#define TSL2591_REG_AIHTH 0x07
44#define TSL2591_REG_NPAILTL 0x08
45#define TSL2591_REG_NPAILTH 0x09
46#define TSL2591_REG_NPAIHTL 0x0A
47#define TSL2591_REG_NPAIHTH 0x0B
48#define TSL2591_REG_PERSIST 0x0C
49#define TSL2591_REG_PID 0x11 /**< @brief Package ID */
50#define TSL2591_REG_ID 0x12 /**< @brief Device ID */
51#define TSL2591_REG_STATUS 0x13 /**< @brief Device status */
52#define TSL2591_REG_C0DATAL 0x14 /**< @brief CH0 ADC low data byte */
53#define TSL2591_REG_C0DATAH 0x15 /**< @brief CH0 ADC high data byte */
54#define TSL2591_REG_C1DATAL 0x16 /**< @brief CH1 ADC low data byte */
55#define TSL2591_REG_C1DATAH 0x17 /**< @brief CH1 ADC high data byte */
56
57#define TSL2591_REG_COMMAND 0x80 /**< @brief Select command register */
58#define TSL2591_REG_NORMAL 0x20 /**< @brief Normal opearation */
59#define TSL2591_REG_SPECIAL 0x60 /**< @brief Special function */
60
61#define TSL2591_ID_TSL2591 0x50
62
63#define TSL2591_VISIBLE (2) // channel 0 - channel 1
64#define TSL2591_INFRARED (1) // channel 1
65#define TSL2591_FULLSPECTRUM (0) // channel 0
66
67#define TSL2591_ENABLE_POWERON (0x01)
68#define TSL2591_ENABLE_POWEROFF (0x00)
69#define TSL2591_ENABLE_AEN (0x02)
70#define TSL2591_ENABLE_AIEN (0x10)
71
72#define TSL2591_CONTROL_RESET (0x80)
73
74
75/*===========================================================================*/
76/* Driver exported variables. */
77/*===========================================================================*/
78
79/*===========================================================================*/
80/* Driver local variables and types. */
81/*===========================================================================*/
82
83/*===========================================================================*/
84/* Driver local functions. */
85/*===========================================================================*/
86
87static inline uint32_t
88calculateIlluminance(TSL2591_integration_time_t integration_time,
89 TSL2591_gain_t gain,
90 uint16_t broadband, uint16_t ir) {
91 uint16_t atime, again;
92
93 /* Check for overflow conditions first */
94 if ((broadband == 0xFFFF) | (ir == 0xFFFF)) {
95 return 0xFFFFFFFF; /* Signal overflow */
96 }
97
98 switch (integration_time) {
99 case TSL2591_INTEGRATIONTIME_100MS : atime = 100; break;
100 case TSL2591_INTEGRATIONTIME_200MS : atime = 200; break;
101 case TSL2591_INTEGRATIONTIME_300MS : atime = 300; break;
102 case TSL2591_INTEGRATIONTIME_400MS : atime = 400; break;
103 case TSL2591_INTEGRATIONTIME_500MS : atime = 500; break;
104 case TSL2591_INTEGRATIONTIME_600MS : atime = 600; break;
105 }
106
107 switch (gain) {
108 case TSL2591_GAIN_1X : again = 1; break;
109 case TSL2591_GAIN_25X : again = 25; break;
110 case TSL2591_GAIN_415X : again = 415; break;
111 case TSL2591_GAIN_10000X : again = 10000; break;
112 }
113
114 // cpl = (ATIME * AGAIN) / DF
115 float cpl = ((float)(atime * again)) / ((float)TSL2591_LUX_DF);
116 float lux1 = ( ((float)broadband) - (TSL2591_LUX_COEFB * (float)ir) ) / cpl;
117 float lux2 = ( (TSL2591_LUX_COEFC * (float)broadband) -
118 (TSL2591_LUX_COEFD * (float)ir ) ) / cpl;
119
120 return (uint32_t) (lux1 > lux2 ? lux1 : lux2);
121}
122
123static inline msg_t
124_readChannel(TSL2591_drv *drv, uint16_t *broadband, uint16_t *ir) {
125 msg_t msg;
126 if (((msg = i2c_reg_recv16_le(
127 TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_C0DATAL,
128 broadband)) < MSG_OK) ||
129 ((msg = i2c_reg_recv16_le(
130 TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_C1DATAL,
131 ir )) < MSG_OK))
132 return msg;
133
134 return MSG_OK;
135}
136
137/*===========================================================================*/
138/* Driver exported functions. */
139/*===========================================================================*/
140
141void
142TSL2591_init(TSL2591_drv *drv, TSL2591_config *config) {
143 drv->config = config;
144 drv->gain = TSL2591_GAIN_1X;
145 drv->integration_time = TSL2591_INTEGRATIONTIME_100MS;
146 drv->state = SENSOR_INIT;
147}
148
149msg_t
150TSL2591_check(TSL2591_drv *drv) {
151 uint8_t id;
152
153 msg_t msg;
154 if ((msg = i2c_reg_recv8(TSL2591_REG_COMMAND | TSL2591_REG_NORMAL |
155 TSL2591_REG_ID, &id)) < MSG_OK)
156 return msg;
157
158 if (id != TSL2591_ID_TSL2591)
159 return SENSOR_NOTFOUND;
160
161 return MSG_OK;
162}
163
164msg_t
165TSL2591_start(TSL2591_drv *drv) {
166 struct __attribute__((packed)) {
167 uint8_t reg;
168 uint8_t conf;
169 } tx_config = {
170 TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
171 (uint8_t)(drv->integration_time | drv->gain) };
172
173 struct __attribute__((packed)) {
174 uint8_t reg;
175 uint8_t conf;
176 } tx_start = {
177 TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_ENABLE,
178 TSL2591_ENABLE_POWERON };
179
180 msg_t msg;
181
182 if (((msg = i2c_send((uint8_t*)&tx_config, sizeof(tx_config))) < MSG_OK) ||
183 ((msg = i2c_send((uint8_t*)&tx_start, sizeof(tx_start ))) < MSG_OK)) {
184 drv->state = SENSOR_ERROR;
185 return msg;
186 }
187
188 drv->state = SENSOR_STARTED;
189 return MSG_OK;
190}
191
192msg_t
193TSL2591_stop(TSL2591_drv *drv) {
194 struct __attribute__((packed)) {
195 uint8_t reg;
196 uint8_t conf;
197 } tx_stop = {
198 TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_ENABLE,
199 TSL2591_ENABLE_POWEROFF };
200
201 return i2c_send((uint8_t*)&tx_stop, sizeof(tx_stop));
202}
203
204msg_t
205TSL2591_setIntegrationTime(TSL2591_drv *drv,
206 TSL2591_integration_time_t time) {
207 struct __attribute__((packed)) {
208 uint8_t reg;
209 uint8_t conf;
210 } tx = { TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
211 (uint8_t)(time | drv->gain) };
212
213 msg_t msg;
214 if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
215 return msg;
216
217 drv->integration_time = time;
218
219 return MSG_OK;
220}
221
222msg_t
223TSL2591_setGain(TSL2591_drv *drv,
224 TSL2591_gain_t gain) {
225 struct __attribute__((packed)) {
226 uint8_t reg;
227 uint8_t conf;
228 } tx = { TSL2591_REG_COMMAND | TSL2591_REG_NORMAL | TSL2591_REG_CONFIG,
229 (uint8_t)(drv->integration_time | gain) };
230
231 msg_t msg;
232 if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
233 return msg;
234
235 drv->gain = gain;
236
237 return MSG_OK;
238}
239
240unsigned int
241TSL2591_getAcquisitionTime(TSL2591_drv *drv) {
242 switch (drv->integration_time) {
243 case TSL2591_INTEGRATIONTIME_100MS : return 100;
244 case TSL2591_INTEGRATIONTIME_200MS : return 200;
245 case TSL2591_INTEGRATIONTIME_300MS : return 300;
246 case TSL2591_INTEGRATIONTIME_400MS : return 400;
247 case TSL2591_INTEGRATIONTIME_500MS : return 500;
248 case TSL2591_INTEGRATIONTIME_600MS : return 600;
249 }
250 return -1;
251}
252
253
254msg_t
255TSL2591_readIlluminance(TSL2591_drv *drv,
256 unsigned int *illuminance) {
257 uint16_t broadband;
258 uint16_t ir;
259
260 /* Read channels */
261 msg_t msg;
262 if ((msg = _readChannel(drv, &broadband, &ir)) < MSG_OK)
263 return msg;
264
265 /* Calculate illuminance */
266 *illuminance =
267 calculateIlluminance(drv->integration_time, drv->gain,
268 broadband, ir);
269 /* Ok */
270 return SENSOR_OK;
271}
272