1#![no_std]
2use bitfield::bitfield;
3use embedded_hal::i2c::{ErrorType, I2c};
4
5pub struct Driver<I2C> {
6 i2c: I2C,
7 integration_time: IntegrationTimes,
8 gain: Gain,
9}
10
11impl<E> From<E> for Error<E> {
12 fn from(error: E) -> Self {
13 Error::I2cError(error)
14 }
15}
16
17impl<I2C> Driver<I2C>
18where
19 I2C: I2c + ErrorType,
20{
21 pub fn new(i2c: I2C) -> Result<Driver<I2C>, Error<I2C::Error>> {
22 let mut driver = Driver {
23 i2c,
24 integration_time: IntegrationTimes::_200MS,
25 gain: Gain::MED,
26 };
27 let id = driver.get_id()?;
28 if id != chip::ID {
29 return Err(Error::IdMismatch(id));
30 }
31
32 driver.set_gain(driver.gain)?;
33 driver.set_timing(driver.integration_time)?;
34
35 Ok(driver)
36 }
37
38 pub fn new_define_integration(
39 i2c: I2C,
40 integration_time: IntegrationTimes,
41 gain: Gain,
42 ) -> Result<Driver<I2C>, Error<I2C::Error>> {
43 let mut driver = Driver {
44 i2c,
45 integration_time,
46 gain,
47 };
48 let id = driver.get_id()?;
49 if id != chip::ID {
50 return Err(Error::IdMismatch(id));
51 }
52
53 driver.set_gain(gain)?;
54 driver.set_timing(integration_time)?;
55
56 Ok(driver)
57 }
58
59 fn get_id(&mut self) -> Result<u8, Error<I2C::Error>> {
60 let mut buffer = [0u8; 1];
61 self.i2c.write_read(
62 chip::I2C_ADDR,
63 &[chip::COMMAND_BIT | chip::ID_ADDR],
64 &mut buffer,
65 )?;
66 Ok(buffer[0])
67 }
68
69 pub fn set_gain(&mut self, gain: Gain) -> Result<(), Error<I2C::Error>> {
70 self.i2c.write(
71 chip::I2C_ADDR,
72 &[
73 chip::COMMAND_BIT | chip::CONTROL,
74 self.integration_time as u8 | gain as u8,
75 ],
76 )?;
77 self.gain = gain;
78
79 Ok(())
80 }
81
82 pub fn set_timing(
83 &mut self,
84 integration_time: IntegrationTimes,
85 ) -> Result<(), Error<I2C::Error>> {
86 self.i2c.write(
87 chip::I2C_ADDR,
88 &[
89 chip::COMMAND_BIT | chip::CONTROL,
90 integration_time as u8 | self.gain as u8,
91 ],
92 )?;
93 self.integration_time = integration_time;
94
95 Ok(())
96 }
97
98 pub fn disable(&mut self) -> Result<(), Error<I2C::Error>> {
99 self.i2c.write(
100 chip::I2C_ADDR,
101 &[chip::COMMAND_BIT | chip::ENABLE, chip::ENABLE_POWEROFF],
102 )?;
103 Ok(())
104 }
105
106 pub fn enable(&mut self) -> Result<(), Error<I2C::Error>> {
107 self.i2c.write(
108 chip::I2C_ADDR,
109 &[
110 chip::COMMAND_BIT | chip::ENABLE,
111 chip::ENABLE_POWERON | chip::ENABLE_AEN | chip::ENABLE_AIEN | chip::ENABLE_NPIEN,
112 ],
113 )?;
114 Ok(())
115 }
116
117 pub fn get_enable(&mut self) -> Result<Enable, Error<I2C::Error>> {
118 let mut status = [0u8; 1];
119 self.i2c.write_read(
120 chip::I2C_ADDR,
121 &[chip::COMMAND_BIT | chip::ENABLE],
122 &mut status,
123 )?;
124 Ok(Enable(status[0]))
125 }
126
127 pub fn get_status(&mut self) -> Result<Status, Error<I2C::Error>> {
128 let mut status = [0u8; 1];
129 self.i2c.write_read(
130 chip::I2C_ADDR,
131 &[chip::COMMAND_BIT | chip::STATUS],
132 &mut status,
133 )?;
134 Ok(Status(status[0]))
135 }
136
137 pub fn get_channel_data(&mut self) -> Result<(u16, u16), Error<I2C::Error>> {
138 let mut buffer_1 = [0u8; 2];
139 let mut buffer_2 = [0u8; 2];
140 self.i2c.write_read(
141 chip::I2C_ADDR,
142 &[chip::COMMAND_BIT | chip::CHAN0_LOW],
143 &mut buffer_1,
144 )?;
145 self.i2c.write_read(
146 chip::I2C_ADDR,
147 &[chip::COMMAND_BIT | chip::CHAN1_LOW],
148 &mut buffer_2,
149 )?;
150 let channel_0 = ((buffer_1[1] as u16) << 8) | buffer_1[0] as u16;
151 let channel_1 = ((buffer_2[1] as u16) << 8) | buffer_2[0] as u16;
152 Ok((channel_0, channel_1))
153 }
154
155 pub fn get_luminosity(&mut self, mode: Mode) -> Result<u16, Error<I2C::Error>> {
156 let (channel_0, channel_1) = self.get_channel_data()?;
157 self.get_luminosity_from_channel_data(mode, channel_0, channel_1)
158 }
159
160 fn get_integration_in_ms(&self) -> f32 {
161 match self.integration_time {
162 IntegrationTimes::_100MS => 100.,
163 IntegrationTimes::_200MS => 200.,
164 IntegrationTimes::_300MS => 300.,
165 IntegrationTimes::_400MS => 400.,
166 IntegrationTimes::_500MS => 500.,
167 IntegrationTimes::_600MS => 600.,
168 }
169 }
170
171 fn get_gain_multiplier(&self) -> f32 {
172 match self.gain {
173 Gain::LOW => 1.,
174 Gain::MED => 25.,
175 Gain::HIGH => 428.,
176 Gain::MAX => 9876.,
177 }
178 }
179
180 pub fn calculate_lux(&mut self, ch_0: u16, ch_1: u16) -> Result<f32, Error<I2C::Error>> {
181 let max_count = match self.integration_time {
182 IntegrationTimes::_100MS => 0x8FFF,
183 _ => 0xFFFF,
184 };
185
186 if (ch_0 == max_count) | (ch_1 == max_count) {
187 return Err(Error::SignalOverflow());
189 }
190
191 let a_time = self.get_integration_in_ms();
192 let a_gain = self.get_gain_multiplier();
193 let cpl = (a_time * a_gain) / 408.0;
194 let lux = (ch_0 as f32 - ch_1 as f32) * (1.0 - (ch_1 as f32 / ch_0 as f32)) / cpl;
195
196 Ok(lux)
197 }
198
199 pub fn get_luminosity_from_channel_data(&mut self, mode: Mode, ch_0: u16, ch_1: u16) -> Result<u16, Error<I2C::Error>> {
200 let full_luminosity: u32 = ((ch_1 as u32) << 16) | ch_0 as u32;
201
202 match mode {
203 Mode::FullSpectrum => Ok((full_luminosity & 0xFFFF) as u16),
204 Mode::Infrared => Ok((full_luminosity >> 16) as u16),
205 Mode::Visible => {
206 let infrared_and_visible = full_luminosity & 0xFFFF;
207 let infrared = full_luminosity >> 16;
208 if infrared > infrared_and_visible {
209 Err(Error::InfraredOverflow())
210 } else {
211 Ok((infrared_and_visible - infrared) as u16)
212 }
213 }
214 }
215 }
216}
217
218pub enum Mode {
219 Infrared,
220 Visible,
221 FullSpectrum,
222}
223
224#[derive(Clone, Copy)]
225pub enum IntegrationTimes {
226 _100MS = 0x00, _200MS = 0x01, _300MS = 0x02, _400MS = 0x03, _500MS = 0x04, _600MS = 0x05, }
233
234#[derive(Clone, Copy)]
235pub enum Gain {
236 LOW = 0x00, MED = 0x10, HIGH = 0x20, MAX = 0x30, }
241
242#[allow(dead_code)]
243mod chip {
244 pub const I2C_ADDR: u8 = 0x29;
245 pub const ID: u8 = 0x50;
246 pub const ID_ADDR: u8 = 0x12;
247 pub const COMMAND_BIT: u8 = 0xA0;
248 pub const ENABLE_POWERON: u8 = 0x01;
249 pub const ENABLE_AEN: u8 = 0x02;
250 pub const ENABLE_AIEN: u8 = 0x10;
251 pub const ENABLE_POWEROFF: u8 = 0x00;
252 pub const ENABLE_NPIEN: u8 = 0x80;
253 pub const CHAN0_LOW: u8 = 0x14;
254 pub const CHAN1_LOW: u8 = 0x16;
255 pub const ENABLE: u8 = 0x00;
256 pub const CONTROL: u8 = 0x01;
257 pub const STATUS: u8 = 0x13;
258 pub const TSL2591_THRESHOLD_AILTH: u8 = 0x05; pub const TSL2591_THRESHOLD_AIHTL: u8 = 0x06; pub const TSL2591_THRESHOLD_AIHTH: u8 = 0x07; pub const TSL2591_THRESHOLD_NPAILTL: u8 = 0x08; pub const TSL2591_THRESHOLD_NPAILTH: u8 = 0x09; pub const TSL2591_THRESHOLD_NPAIHTL: u8 = 0x0A; pub const TSL2591_THRESHOLD_NPAIHTH: u8 = 0x0B; pub const TSL2591_PERSIST_FILTER: u8 = 0x0C; }
267
268#[derive(Clone, Copy, Debug)]
269pub enum Error<I2cError> {
270 I2cError(I2cError),
271 IdMismatch(u8),
272 SignalOverflow(),
273 InfraredOverflow(),
274}
275
276bitfield! {
298 pub struct Enable(u8);
299 impl Debug;
300 pub npien, _: 6;
301 pub sai, _: 5;
302 pub res, _: 4,3;
303 pub aen, _: 1;
304 pub pon, _: 0;
305}
306
307bitfield! {
308 pub struct Status(u8);
309 impl Debug;
310 pub npintr,_: 6,4;
311 pub aint, _: 4;
312 pub res, _: 3,3;
313 pub avalid, _: 0;
314}