/
Adafruit_LTR329_LTR303.cpp
368 lines (314 loc) · 11.1 KB
/
Adafruit_LTR329_LTR303.cpp
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/*!
* @file Adafruit_LTR329_LTR303.cpp
*
* @mainpage Adafruit LTR329 and LTR303 I2C Light Sensorso_sec Introduction
*
* I2C Driver for the LTR329 and LTR303 I2C Light Sensors
*
* This is a library for the Adafruit LTR329 & LTR303 breakouts:
* https://www.adafruit.com/product/5591
* https://www.adafruit.com/product/5610
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
* @section author Author
*
* Limor Fried (Adafruit Industries)
*
* @section license License
*
* BSD (see license.txt)
*
* @section HISTORY
*
* v1.0 - First release
*/
#include "Arduino.h"
#include <Wire.h>
#include "Adafruit_LTR329_LTR303.h"
/*!
* @brief Instantiates a new LTR329 class
*/
Adafruit_LTR329::Adafruit_LTR329(void) {}
/*!
* @brief Instantiates a new LTR303 class
*/
Adafruit_LTR303::Adafruit_LTR303(void) {}
/*!
* @brief Setups the hardware for talking to the LTR329
* @param theWire An optional pointer to an I2C interface
* @return True if initialization was successful, otherwise false.
*/
bool Adafruit_LTR329::begin(TwoWire *theWire) {
delete i2c_dev;
i2c_dev = new Adafruit_I2CDevice(LTR329_I2CADDR_DEFAULT, theWire);
if (!i2c_dev->begin()) {
return false;
}
// check part ID!
Adafruit_I2CRegister idreg = Adafruit_I2CRegister(i2c_dev, LTR329_PART_ID);
if (idreg.read() != 0xA0) {
return false;
}
Adafruit_I2CRegister manreg = Adafruit_I2CRegister(i2c_dev, LTR329_MANU_ID);
if (manreg.read() != 0x05) {
return false;
}
// OK now we can do a soft reset
if (!reset()) {
return false;
}
// main screen turn on
enable(true);
if (!enabled()) {
return false;
}
StatusReg = new Adafruit_I2CRegister(i2c_dev, LTR329_STATUS);
DataReadyBit = new Adafruit_I2CRegisterBits(StatusReg, 1, 2);
DataInvalidBit = new Adafruit_I2CRegisterBits(StatusReg, 1, 7);
return true;
}
/*!
* @brief Perform a soft reset with 10ms delay.
* @returns True on success
*/
bool Adafruit_LTR329::reset(void) {
Adafruit_I2CRegister ctrlreg = Adafruit_I2CRegister(i2c_dev, LTR329_ALS_CTRL);
Adafruit_I2CRegisterBits softreset =
Adafruit_I2CRegisterBits(&ctrlreg, 1, 1); // # bits, bit_shift
if (!softreset.write(1))
return false;
delay(10);
return true;
}
/*!
* @brief Enable or disable the light sensor
* @param en True to enable, False to disable
*/
void Adafruit_LTR329::enable(bool en) {
Adafruit_I2CRegister alsctrl = Adafruit_I2CRegister(i2c_dev, LTR329_ALS_CTRL);
Adafruit_I2CRegisterBits active_mode =
Adafruit_I2CRegisterBits(&alsctrl, 1, 0); // # bits, bit_shift
active_mode.write(en);
}
/*!
* @brief Read the enabled-bit from the sensor
* @returns True if enabled
*/
bool Adafruit_LTR329::enabled(void) {
Adafruit_I2CRegister alsctrl = Adafruit_I2CRegister(i2c_dev, LTR329_ALS_CTRL);
Adafruit_I2CRegisterBits active_mode =
Adafruit_I2CRegisterBits(&alsctrl, 1, 0); // # bits, bit_shift
return active_mode.read();
}
/*!
* @brief Set the sensor gain
* @param gain The desired gain: LTR3XX_GAIN_1, LTR3XX_GAIN_2, LTR3XX_GAIN_4
* LTR3XX_GAIN_8, LTR3XX_GAIN_48 or LTR3XX_GAIN_96
*/
void Adafruit_LTR329::setGain(ltr329_gain_t gain) {
Adafruit_I2CRegister ctrlreg = Adafruit_I2CRegister(i2c_dev, LTR329_ALS_CTRL);
Adafruit_I2CRegisterBits gainbits =
Adafruit_I2CRegisterBits(&ctrlreg, 3, 2); // # bits, bit_shift
gainbits.write(gain);
}
/*!
* @brief Get the sensor's gain
* @returns gain The current gain: LTR3XX_GAIN_1, LTR3XX_GAIN_2, LTR3XX_GAIN_4
* LTR3XX_GAIN_8, LTR3XX_GAIN_48 or LTR3XX_GAIN_96
*/
ltr329_gain_t Adafruit_LTR329::getGain(void) {
Adafruit_I2CRegister ctrlreg = Adafruit_I2CRegister(i2c_dev, LTR329_ALS_CTRL);
Adafruit_I2CRegisterBits gainbits =
Adafruit_I2CRegisterBits(&ctrlreg, 3, 2); // # bits, bit_shift
return (ltr329_gain_t)gainbits.read();
}
/*!
* @brief Set the sensor integration time. Longer times are more sensitive but
* take longer to read!
* @param inttime The desired integration time (in millis):
* LTR3XX_INTEGTIME_50, LTR3XX_INTEGTIME_100, LTR3XX_INTEGTIME_150,
* LTR3XX_INTEGTIME_200,LTR3XX_INTEGTIME_250, LTR3XX_INTEGTIME_300,
* LTR3XX_INTEGTIME_350, LTR3XX_INTEGTIME_400,
*/
void Adafruit_LTR329::setIntegrationTime(ltr329_integrationtime_t inttime) {
Adafruit_I2CRegister ratereg =
Adafruit_I2CRegister(i2c_dev, LTR329_MEAS_RATE);
Adafruit_I2CRegisterBits intbits =
Adafruit_I2CRegisterBits(&ratereg, 3, 3); // # bits, bit_shift
intbits.write(inttime);
}
/*!
* @brief Get the sensor's integration time for light sensing
* @returns The current integration time, in milliseconds.
* LTR3XX_INTEGTIME_50, LTR3XX_INTEGTIME_100, LTR3XX_INTEGTIME_150,
* LTR3XX_INTEGTIME_200,LTR3XX_INTEGTIME_250, LTR3XX_INTEGTIME_300,
* LTR3XX_INTEGTIME_350, LTR3XX_INTEGTIME_400,
*/
ltr329_integrationtime_t Adafruit_LTR329::getIntegrationTime(void) {
Adafruit_I2CRegister ratereg =
Adafruit_I2CRegister(i2c_dev, LTR329_MEAS_RATE);
Adafruit_I2CRegisterBits intbits =
Adafruit_I2CRegisterBits(&ratereg, 3, 3); // # bits, bit_shift
return (ltr329_integrationtime_t)intbits.read();
}
/*!
* @brief Set the sensor measurement rate. Longer times are needed when
* the integration time is longer OR if you want to have lower power usage
* @param rate The desired measurement rate (in millis):
* LTR3XX_MEASRATE_50, LTR3XX_MEASRATE_100, LTR3XX_MEASRATE_200,
* LTR3XX_MEASRATE_500, LTR3XX_MEASRATE_1000, or LTR3XX_MEASRATE_2000
*/
void Adafruit_LTR329::setMeasurementRate(ltr329_measurerate_t rate) {
Adafruit_I2CRegister ratereg =
Adafruit_I2CRegister(i2c_dev, LTR329_MEAS_RATE);
Adafruit_I2CRegisterBits measbits =
Adafruit_I2CRegisterBits(&ratereg, 3, 0); // # bits, bit_shift
measbits.write(rate);
}
/*!
* @brief Get the sensor's measurement rate.
* @returns The current measurement rate (in millis):
* LTR3XX_MEASRATE_50, LTR3XX_MEASRATE_100, LTR3XX_MEASRATE_200,
* LTR3XX_MEASRATE_500, LTR3XX_MEASRATE_1000, or LTR3XX_MEASRATE_2000
*/
ltr329_measurerate_t Adafruit_LTR329::getMeasurementRate(void) {
Adafruit_I2CRegister ratereg =
Adafruit_I2CRegister(i2c_dev, LTR329_MEAS_RATE);
Adafruit_I2CRegisterBits measbits =
Adafruit_I2CRegisterBits(&ratereg, 3, 0); // # bits, bit_shift
return (ltr329_measurerate_t)measbits.read();
}
/*!
* @brief Checks if new data is available in data register
* @returns True on new data available
*/
bool Adafruit_LTR329::newDataAvailable(void) { return DataReadyBit->read(); }
/*!
* @brief Read both 16-bit channels at once, and place data into argument
* pointers
* @param ch0 Reference to uint16_t where visible+IR data will be stored
* @param ch1 Reference to uint16_t where IR-only data will be stored
* @returns True if data is valid (no over-run), false on bad data
*/
bool Adafruit_LTR329::readBothChannels(uint16_t &ch0, uint16_t &ch1) {
Adafruit_I2CRegister datareg =
Adafruit_I2CRegister(i2c_dev, LTR329_CH1DATA, 4, LSBFIRST);
uint32_t both = datareg.read();
ch0 = both >> 16;
ch1 = both & 0xFFFF;
return !DataInvalidBit->read();
}
/*!
* @brief Read both 16-bit channels at once, and subract to get visible light
* @returns 16-bit visible data, or 0xFFFF if invalid data (overrun)
*/
uint16_t Adafruit_LTR329::readVisible(void) {
uint16_t visible_plus_ir, infrared;
if (!readBothChannels(visible_plus_ir, infrared)) {
return 0xFFFF;
}
return visible_plus_ir - infrared;
}
/*!
* @brief Enables the interrupt output pin
* @param en Pass in 'true' to enable the output pin, false to tri-state
*/
void Adafruit_LTR303::enableInterrupt(bool en) {
// we must be in non-active mode to change this register!
bool curr_mode = enabled();
enable(false);
// now change the bit...
Adafruit_I2CRegister intreg =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_INTERRUPT);
Adafruit_I2CRegisterBits enbit =
Adafruit_I2CRegisterBits(&intreg, 1, 1); // # bits, bit_shift
enbit.write(en);
// and reset the mode
enable(curr_mode);
}
/*!
* @brief The INT pin has a polarity setting for active low or high!
* @param pol For active LOW set to 'false', for active HIGH set to 'true'
*/
void Adafruit_LTR303::setInterruptPolarity(bool pol) {
// we must be in non-active mode to change this register!
bool curr_mode = enabled();
enable(false);
// now change the bit...
Adafruit_I2CRegister intreg =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_INTERRUPT);
Adafruit_I2CRegisterBits polbit =
Adafruit_I2CRegisterBits(&intreg, 1, 2); // # bits, bit_shift
polbit.write(pol);
// and reset the mode
enable(curr_mode);
}
/*!
* @brief The low threshold for ALS reading interrupts : values BELOW this
* trigger an interrupt
* @param value This number is compared against the 'visible + IR' data
* register
*/
void Adafruit_LTR303::setLowThreshold(uint16_t value) {
Adafruit_I2CRegister thresh =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_THRESHLOW_LSB, 2, LSBFIRST);
thresh.write(value);
}
/*!
* @brief The low threshold for ALS reading interrupt getter
* @returns The value that ALS compares for low-value interrupts
*/
uint16_t Adafruit_LTR303::getLowThreshold(void) {
Adafruit_I2CRegister thresh =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_THRESHLOW_LSB, 2, LSBFIRST);
return thresh.read();
}
/*!
* @brief The high threshold for ALS reading interrupts : values ABOVE this
* trigger an interrupt
* @param value This number is compared against the 'visible + IR' data
* register
*/
void Adafruit_LTR303::setHighThreshold(uint16_t value) {
Adafruit_I2CRegister thresh =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_THRESHHIGH_LSB, 2, LSBFIRST);
thresh.write(value);
}
/*!
* @brief The high threshold for ALS reading interrupt getter
* @returns The value that ALS compares for high-value interrupts
*/
uint16_t Adafruit_LTR303::getHighThreshold(void) {
Adafruit_I2CRegister thresh =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_THRESHHIGH_LSB, 2, LSBFIRST);
return thresh.read();
}
/*!
* @brief The default behavior is an interrupt on every value that is
* under/over the threshold ranges. However, you're more likely to get spurious
* IRQs, so we can set it to require "N counts in a row" before an IRQ.
* @param counts 1 count is IRQ for each reading, 2 counts means we need two
* outside readings in a row, etc up to 16.
*/
void Adafruit_LTR303::setIntPersistance(uint8_t counts) {
Adafruit_I2CRegister persistreg =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_INTPERSIST);
Adafruit_I2CRegisterBits persist =
Adafruit_I2CRegisterBits(&persistreg, 4, 0); // # bits, bit_shift
persist.write(counts - 1);
}
/*!
* @brief Getter for the number of counts required to trigger IRQ
* @returns 1 count is IRQ for each reading, 2 counts means we need two outside
* readings in a row, etc up to 16.
*/
uint8_t Adafruit_LTR303::getIntPersistance(void) {
Adafruit_I2CRegister persistreg =
Adafruit_I2CRegister(i2c_dev, LTR303_REG_INTPERSIST);
Adafruit_I2CRegisterBits persist =
Adafruit_I2CRegisterBits(&persistreg, 4, 0); // # bits, bit_shift
return persist.read() + 1;
}