1#[cfg(feature = "lux_as_f32")]
2use crate::calculate_raw_threshold_value;
3#[cfg(feature = "lux_as_f32")]
4use crate::correction::{correct_high_lux, get_lux_raw_conversion_factor};
5use crate::{
6 Config, Error, FaultCount, Gain, IntegrationTime, InterruptStatus, PowerSavingMode, Veml7700,
7 DEVICE_ADDRESS,
8};
9#[cfg(feature = "is_sync")]
10use embedded_hal::i2c::{ErrorType, I2c, SevenBitAddress};
11#[cfg(not(feature = "is_sync"))]
12use embedded_hal_async::i2c::{ErrorType, I2c, SevenBitAddress};
13use maybe_async::maybe_async;
14
15struct Register;
16impl Register {
17 const ALS_CONF: u8 = 0x00;
18 const ALS_WH: u8 = 0x01;
19 const ALS_WL: u8 = 0x02;
20 const PSM: u8 = 0x03;
21 const ALS: u8 = 0x04;
22 const WHITE: u8 = 0x05;
23 const ALS_INT: u8 = 0x06;
24}
25
26struct BitFlags;
27impl BitFlags {
28 const ALS_SD: u16 = 0x01;
29 const ALS_INT_EN: u16 = 0x02;
30 const PSM_EN: u16 = 0x01;
31 const INT_TH_LOW: u16 = 1 << 15;
32 const INT_TH_HIGH: u16 = 1 << 14;
33}
34
35impl Config {
36 fn with_high(self, mask: u16) -> Self {
37 Config {
38 bits: self.bits | mask,
39 }
40 }
41 fn with_low(self, mask: u16) -> Self {
42 Config {
43 bits: self.bits & !mask,
44 }
45 }
46}
47
48impl<I2C> Veml7700<I2C>
49where
50 I2C: I2c<SevenBitAddress>,
51 I2C::Error: Into<Error<I2C::Error>>,
52{
53 pub fn new(i2c: I2C) -> Self {
55 Veml7700 {
56 i2c,
57 config: Config {
58 bits: BitFlags::ALS_SD,
59 },
60 gain: Gain::One,
61 it: IntegrationTime::_100ms,
62 }
63 }
64
65 pub fn destroy(self) -> I2C {
67 self.i2c
68 }
69}
70
71impl<I2C> Veml7700<I2C>
72where
73 I2C: I2c<SevenBitAddress>,
74 I2C::Error: Into<Error<I2C::Error>>,
75{
76 #[maybe_async]
82 pub async fn enable(&mut self) -> Result<(), Error<I2C::Error>> {
83 let config = self.config.with_low(BitFlags::ALS_SD);
84 self.set_config(config).await
85 }
86
87 #[maybe_async]
89 pub async fn disable(&mut self) -> Result<(), Error<I2C::Error>> {
90 let config = self.config.with_high(BitFlags::ALS_SD);
91 self.set_config(config).await
92 }
93
94 #[maybe_async]
96 pub async fn set_integration_time(&mut self, it: IntegrationTime) -> Result<(), Error<I2C::Error>> {
97 let mask = match it {
98 IntegrationTime::_25ms => 0b1100,
99 IntegrationTime::_50ms => 0b1000,
100 IntegrationTime::_100ms => 0b0000,
101 IntegrationTime::_200ms => 0b0001,
102 IntegrationTime::_400ms => 0b0010,
103 IntegrationTime::_800ms => 0b0011,
104 };
105 let config = self.config.bits & !(0b1111 << 6) | (mask << 6);
106 self.set_config(Config { bits: config }).await?;
107 self.it = it;
108 Ok(())
109 }
110
111 #[maybe_async]
113 pub async fn set_gain(&mut self, gain: Gain) -> Result<(), Error<I2C::Error>> {
114 let mask = match gain {
115 Gain::One => 0,
116 Gain::Two => 1,
117 Gain::OneEighth => 2,
118 Gain::OneQuarter => 3,
119 };
120 let config = self.config.bits & !(0b11 << 11) | mask << 11;
121 self.set_config(Config { bits: config }).await?;
122 self.gain = gain;
123 Ok(())
124 }
125
126 #[maybe_async]
129 pub async fn set_fault_count(&mut self, fc: FaultCount) -> Result<(), Error<I2C::Error>> {
130 let mask = match fc {
131 FaultCount::One => 0,
132 FaultCount::Two => 1,
133 FaultCount::Four => 2,
134 FaultCount::Eight => 3,
135 };
136 let config = self.config.bits & !(0b11 << 4) | mask << 4;
137 self.set_config(Config { bits: config }).await
138 }
139
140 #[maybe_async]
142 pub async fn enable_interrupts(&mut self) -> Result<(), Error<I2C::Error>> {
143 let config = self.config.with_high(BitFlags::ALS_INT_EN);
144 self.set_config(config).await
145 }
146
147 #[maybe_async]
149 pub async fn disable_interrupts(&mut self) -> Result<(), Error<I2C::Error>> {
150 let config = self.config.with_low(BitFlags::ALS_INT_EN);
151 self.set_config(config).await
152 }
153
154 #[maybe_async]
156 pub async fn set_high_threshold_raw(&mut self, threshold: u16) -> Result<(), Error<I2C::Error>> {
157 Ok(self.write_register(Register::ALS_WH, threshold).await?)
158 }
159
160 #[maybe_async]
162 pub async fn set_low_threshold_raw(&mut self, threshold: u16) -> Result<(), Error<I2C::Error>> {
163 Ok(self.write_register(Register::ALS_WL, threshold).await?)
164 }
165
166 #[cfg(feature = "lux_as_f32")]
172 #[maybe_async]
173 pub async fn set_high_threshold_lux(&mut self, lux: f32) -> Result<(), Error<I2C::Error>> {
174 let raw = self.calculate_raw_threshold_value(lux);
175 self.set_high_threshold_raw(raw).await
176 }
177 #[cfg(feature = "lux_as_f32")]
185 #[maybe_async]
186 pub async fn set_low_threshold_lux(&mut self, lux: f32) -> Result<(), Error<I2C::Error>> {
187 let raw = self.calculate_raw_threshold_value(lux);
188 self.set_low_threshold_raw(raw).await
189 }
190
191 #[cfg(feature = "lux_as_f32")]
200 pub fn calculate_raw_threshold_value(&self, lux: f32) -> u16 {
201 calculate_raw_threshold_value(self.it, self.gain, lux)
202 }
203
204 #[maybe_async]
206 pub async fn enable_power_saving(&mut self, psm: PowerSavingMode) -> Result<(), Error<I2C::Error>> {
207 let mask = match psm {
208 PowerSavingMode::One => 0,
209 PowerSavingMode::Two => 1,
210 PowerSavingMode::Three => 2,
211 PowerSavingMode::Four => 3,
212 };
213 let value = BitFlags::PSM_EN | mask << 1;
214 Ok(self.write_register(Register::PSM, value).await?)
215 }
216
217 #[maybe_async]
219 pub async fn disable_power_saving(&mut self) -> Result<(), Error<I2C::Error>> {
220 Ok(self.write_register(Register::PSM, 0).await?)
221 }
222
223 #[maybe_async]
224 async fn set_config(&mut self, config: Config) -> Result<(), Error<I2C::Error>> {
225 self.write_register(Register::ALS_CONF, config.bits).await?;
226 self.config = config;
227 Ok(())
228 }
229
230 #[maybe_async]
231 async fn write_register(
232 &mut self,
233 register: u8,
234 value: u16,
235 ) -> Result<(), <I2C as ErrorType>::Error> {
236 self.i2c
237 .write(DEVICE_ADDRESS, &[register, value as u8, (value >> 8) as u8]).await
238 }
239}
240
241impl<I2C> Veml7700<I2C>
242where
243 I2C: I2c<SevenBitAddress>,
244 I2C::Error: Into<Error<I2C::Error>>,
245{
246 #[maybe_async]
252 pub async fn read_interrupt_status(&mut self) -> Result<InterruptStatus, Error<I2C::Error>> {
253 let data = self.read_register(Register::ALS_INT).await?;
254 Ok(InterruptStatus {
255 was_too_low: (data & BitFlags::INT_TH_LOW) != 0,
256 was_too_high: (data & BitFlags::INT_TH_HIGH) != 0,
257 })
258 }
259
260 #[maybe_async]
262 pub async fn read_raw(&mut self) -> Result<u16, Error<I2C::Error>> {
263 self.read_register(Register::ALS).await
264 }
265
266 #[cfg(feature = "lux_as_f32")]
272 #[maybe_async]
273 pub async fn read_lux(&mut self) -> Result<f32, Error<I2C::Error>> {
274 let raw = self.read_register(Register::ALS).await?;
275 Ok(self.convert_raw_als_to_lux(raw))
276 }
277
278 #[cfg(feature = "lux_as_f32")]
287 pub fn convert_raw_als_to_lux(&self, raw_als: u16) -> f32 {
288 convert_raw_als_to_lux(self.it, self.gain, raw_als)
289 }
290
291 #[maybe_async]
293 pub async fn read_white(&mut self) -> Result<u16, Error<I2C::Error>> {
294 self.read_register(Register::WHITE).await
295 }
296
297 #[maybe_async]
298 async fn read_register(&mut self, register: u8) -> Result<u16, Error<I2C::Error>> {
299 let mut data = [0; 2];
300 self.i2c
301 .write_read(DEVICE_ADDRESS, &[register], &mut data).await
302 .map_err(Error::I2C)
303 .and(Ok(u16::from(data[0]) | u16::from(data[1]) << 8))
304 }
305}
306
307#[cfg(feature = "lux_as_f32")]
313pub fn convert_raw_als_to_lux(it: IntegrationTime, gain: Gain, raw_als: u16) -> f32 {
314 let factor = get_lux_raw_conversion_factor(it, gain);
315 let lux = f32::from(raw_als) * factor;
316 if (gain == Gain::OneQuarter || gain == Gain::OneEighth) && lux > 1000.0 {
317 correct_high_lux(lux)
318 } else {
319 lux
320 }
321}