µracoli Manual Version foo

- µracoli
- User Guide
- Reference Guide

tsl2550.h
1 /* Copyright (c) 2013 Axel Wachtler
2 All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of the authors nor the names of its contributors
14 may be used to endorse or promote products derived from this software
15 without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE. */
28
29 #ifndef TSL2550_H
30 #define TSL2550_H
31
42 /* === includes ============================================================ */
43 #include <avr/pgmspace.h>
44 #include "sensor_defs.h"
45
46 /* === macros ============================================================== */
48 #define TSL2550_ADDR (0x39)
49
50 #define TSL2550_PWR_DOWN (0x00)
51
52 #define TSL2550_RD_CMD (0x03)
53
54 #define TSL2550_EXT_RANGE (0x1D)
55
56 #define TSL2550_STD_RANGE (0x18)
57
58 #define TSL2550_RD_ADC0 (0x43)
59
60 #define TSL2550_RD_ADC1 (0x83)
61
62 #define ADC_VALID_MASK (0x80)
63
64 #define TSL2550_ADC_VALID(a) (a & ADC_VALID_MASK)
65 #define TSL2550_MAX_LUX (1846)
66
67 /* === types =============================================================== */
68 typedef struct {
69 sensor_driver_t g;
70 uint8_t addr;
71 } tsl2550_ctx_t;
72
73
74 /* === prototypes ========================================================== */
75 #ifdef __cplusplus
76 extern "C" {
77 #endif
78 static inline uint8_t tsl2550_init(void)
79 {
80 uint8_t rv;
81 rv = i2c_probe(TSL2550_ADDR);
82 return rv;
83 }
84
85 static inline void tsl2550_set_command(uint8_t cmd)
86 {
87 i2c_master_writeread(TSL2550_ADDR, &cmd, 1, NULL, 0);
88 }
89
93 static inline uint8_t tsl2550_get(uint8_t adc)
94 {
95 uint8_t rv;
96 uint8_t cmd;
97 cmd = (adc == 0) ? TSL2550_RD_ADC0 : TSL2550_RD_ADC1;
98
99 i2c_master_writeread(TSL2550_ADDR, &cmd, 1, &rv, 1);
100 return rv;
101 }
102
103
105 static inline uint16_t tsl2550_scale(uint8_t adc0, uint8_t adc1)
106 {
107
108 // Lookup table for channel ratio (i.e. channel1 / channel0)
109 static const unsigned char ratioLut[129] = {
110 100,100,100,100,100,100,100,100,
111 100,100,100,100,100,100,99,99,
112 99,99,99,99,99,99,99,99,
113 99,99,99,98,98,98,98,98,
114 98,98,97,97,97,97,97,96,
115 96,96,96,95,95,95,94,94,
116 93,93,93,92,92,91,91,90,
117 89,89,88,87,87,86,85,84,
118 83,82,81,80,79,78,77,75,
119 74,73,71,69,68,66,64,62,
120 60,58,56,54,52,49,47,44,
121 42,41,40,40,39,39,38,38,
122 37,37,37,36,36,36,35,35,
123 35,35,34,34,34,34,33,33,
124 33,33,32,32,32,32,32,31,
125 31,31,31,31,30,30,30,30,
126 30
127 };
128 // Lookup table to convert channel values to counts
129 static const unsigned short countLut[128] = {
130 0, 1, 2, 3, 4, 5, 6, 7,
131 8, 9, 10, 11, 12, 13, 14, 15,
132 16, 18, 20, 22, 24, 26, 28, 30,
133 32, 34, 36, 38, 40, 42, 44, 46,
134 49, 53, 57, 61, 65, 69, 73, 77,
135 81, 85, 89, 93, 97, 101, 105, 109,
136 115, 123, 131, 139, 147, 155, 163, 171,
137 179, 187, 195, 203, 211, 219, 227, 235,
138 247, 263, 279, 295, 311, 327, 343, 359,
139 375, 391, 407, 423, 439, 455, 471, 487,
140 511, 543, 575, 607, 639, 671, 703, 735,
141 767, 799, 831, 863, 895, 927, 959, 991,
142 1039,1103,1167,1231,1295,1359,1423,1487,
143 1551,1615,1679,1743,1807,1871,1935,1999,
144 2095,2223,2351,2479,2607,2735,2863,2991,
145 3119,3247,3375,3503,3631,3759,3887,4015
146 };
147
148 /* lookup count from channel value */
149 uint16_t count0 = countLut[adc0 & ~ADC_VALID_MASK];
150 uint16_t count1 = countLut[adc1 & ~ADC_VALID_MASK];
151
152
153 /* calculate ratio
154 * Note: the "128" is a scaling factor
155 */
156 uint8_t ratio = 128;
157
158 /* avoid division by zero and count1 cannot be greater than count0 */
159 if ((count0) && (count1 <= count0))
160 {
161 ratio = (count1 * 128 / count0);
162 }
163 /* calculate lux
164 * Note: the "256" is a scaling factor
165 */
166 unsigned long lux = ((count0 - count1) * ratioLut[ratio]) / 256;
167 /* range check lux */
168 if (lux > TSL2550_MAX_LUX)
169 {
170 lux = TSL2550_MAX_LUX;
171 }
172 return lux;
173 }
174
175 /* highlevel interface */
176
177 static inline void tsl2550_trigger(void *pctx, bool one_shot)
178 {
179 tsl2550_set_command(TSL2550_RD_CMD);
180 }
181
182 static inline uint8_t tsl2550_get_val(void *pctx, uint8_t *pdata)
183 {
184 uint16_t lv_f;
185 uint8_t adc0, adc1;
186 sensor_light_t *p = (sensor_light_t*)pdata;
187
188 if(p)
189 {
190 adc0 = tsl2550_get(0);
191 /* a time gap between two reads is needed, todo: check datasheet */
192 DELAY_US(10);
193 adc1 = tsl2550_get(1);
194 if ( TSL2550_ADC_VALID(adc0) && TSL2550_ADC_VALID(adc1))
195 {
196 lv_f = tsl2550_scale( adc0 , adc1);
197 }
198 else
199 {
200 lv_f = 0xaaaa;
201 }
202 p->type = SENSOR_DATA_LIGHT;
203 p->sensor = SENSOR_LEDPS;
204 p->light = lv_f;
205 }
206 return sizeof(sensor_light_t);
207 }
208
209 static inline uint8_t tsl2550_get_raw(void *pctx, uint8_t *pdata)
210 {
211 uint8_t rv;
212 rv = sizeof(sensor_raw_t) - 1 + 2*sizeof(uint8_t);
213 if (pdata != NULL)
214 {
215 ((sensor_raw_t*)pdata)->type = SENSOR_DATA_RAW | 2*sizeof(uint8_t);
216 ((sensor_raw_t*)pdata)->sensor = SENSOR_TSL2550;
217 ((sensor_raw_t*)pdata)->data[0] = tsl2550_get(0);
218 ((sensor_raw_t*)pdata)->data[1] = tsl2550_get(1);
219 }
220 return rv;
221 }
222 static inline uint8_t sensor_create_tsl2550(void *pdata, bool raw)
223 {
224 uint8_t rv = sizeof(tsl2550_ctx_t);
225 tsl2550_ctx_t *pcfg;
226 uint8_t tst;
227
228 if (pdata != NULL)
229 {
230 /* init generic sensor data */
231 pcfg = (tsl2550_ctx_t *)pdata;
232 pcfg->g.id = SENSOR_TSL2550;
233 pcfg->g.f_trigger = tsl2550_trigger;
234 pcfg->g.f_get_val = raw ? tsl2550_get_raw : tsl2550_get_val;
235 pcfg->g.f_sleep = NULL;
236
237 /* initialize sensor */
238 tst = i2c_probe(TSL2550_ADDR);
239 pcfg->g.last_error = tst ? SENSOR_ERR_OK : SENSOR_ERR_INIT;
240 }
241 return rv;
242 }
243
244 #ifdef __cplusplus
245 } /* extern "C" */
246 #endif
247
248 #endif /* #ifndef TSL2550_H */
DELAY_US
#define DELAY_US(x)
Macro for delays with us resolution.
Definition: board.h:89
i2c_probe
uint8_t i2c_probe(uint8_t devaddr)
TSL2550_ADDR
#define TSL2550_ADDR
Definition: tsl2550.h:48
sensor_light_t
Definition: sensor_defs.h:77
i2c_master_writeread
uint8_t i2c_master_writeread(uint8_t devaddr, uint8_t *writebuf, uint8_t bytestowrite, uint8_t *readbuf, uint8_t bytestoread)
tsl2550_scale
static uint16_t tsl2550_scale(uint8_t adc0, uint8_t adc1)
Definition: tsl2550.h:105
TSL2550_RD_ADC1
#define TSL2550_RD_ADC1
Definition: tsl2550.h:60
TSL2550_RD_CMD
#define TSL2550_RD_CMD
Definition: tsl2550.h:52
sensor_driver_t
Definition: sensor_defs.h:59
tsl2550_get
static uint8_t tsl2550_get(uint8_t adc)
Definition: tsl2550.h:93
TSL2550_RD_ADC0
#define TSL2550_RD_ADC0
Definition: tsl2550.h:58
sensor_raw_t
Definition: sensor_defs.h:104