bh1750_embedded/types.rs
1//! Public configuration types for the BH1750 driver.
2//!
3//! This module contains the core types used to configure and interact with
4//! the BH1750 sensor:
5//!
6//! - [`Address`] - I2C address selection based on the ADDR pin
7//! - [`Resolution`] - Measurement resolution and mode selection
8//! - [`MeasurementTime`] - Sensitivity adjustment via the MTreg register
9//!
10//! # Address Configuration
11//!
12//! The BH1750 can have one of two I2C addresses depending on the ADDR pin state:
13//!
14//! ```
15//! use bh1750_embedded::Address;
16//!
17//! // ADDR pin connected to GND (or floating)
18//! let addr_low = Address::Low; // 0x23
19//!
20//! // ADDR pin connected to VCC
21//! let addr_high = Address::High; // 0x5C
22//!
23//! // Custom address (for unusual configurations)
24//! let addr_custom = Address::Custom(0x24);
25//! ```
26//!
27//! # Resolution Modes
28//!
29//! The sensor provides three resolution modes with different accuracy
30//! and measurement times:
31//!
32//! ```
33//! use bh1750_embedded::Resolution;
34//!
35//! // High resolution mode: 1 lx resolution, ~120ms measurement time
36//! let high = Resolution::High;
37//!
38//! // High resolution mode 2: 0.5 lx resolution, ~120ms measurement time
39//! let high2 = Resolution::High2;
40//!
41//! // Low resolution mode: 4 lx resolution, ~16ms measurement time (faster)
42//! let low = Resolution::Low;
43//! ```
44//!
45//! # Measurement Time (MTreg)
46//!
47//! The MTreg register (31..=254) adjusts the sensor's sensitivity and
48//! measurement time. Higher values increase sensitivity for low-light
49//! conditions, while lower values reduce sensitivity for bright conditions.
50//!
51//! ```
52//! use bh1750_embedded::MeasurementTime;
53//!
54//! // Default value (69)
55//! let default_mt = MeasurementTime::DEFAULT;
56//!
57//! // High sensitivity for low light (254)
58//! let high_sensitivity = MeasurementTime::new(254).unwrap();
59//!
60//! // Low sensitivity for bright light (31)
61//! let low_sensitivity = MeasurementTime::new(31).unwrap();
62//!
63//! // Values outside the range return None
64//! assert!(MeasurementTime::new(10).is_none());
65//! assert!(MeasurementTime::new(255).is_none());
66//! ```
67//!
68//! # Complete Example
69//!
70//! ```
71//! use bh1750_embedded::{Address, Bh1750, MeasurementTime, Resolution};
72//!
73//! # fn example<I2C, D, E>(i2c: I2C, delay: D) -> Result<(), bh1750_embedded::Error<E>>
74//! # where
75//! # I2C: embedded_hal::i2c::I2c<Error = E>,
76//! # D: embedded_hal::delay::DelayNs,
77//! # E: embedded_hal::i2c::Error,
78//! # {
79//! let mut sensor = Bh1750::new(i2c, delay, Address::Low);
80//!
81//! // Configure for low-light conditions
82//! sensor.set_measurement_time(MeasurementTime::new(200).unwrap())?;
83//!
84//! // Use high resolution for maximum accuracy
85//! let lux = sensor.one_time_measurement(Resolution::High2)?;
86//! # Ok(())
87//! # }
88//! ```
89
90/// I2C address selection for the BH1750.
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum Address {
93 /// Address pin low: `0x23`.
94 Low,
95 /// Address pin high: `0x5C`.
96 High,
97 /// A custom 7-bit I2C address.
98 Custom(u8),
99}
100
101impl Address {
102 /// Resolve into a 7-bit I2C address.
103 #[must_use]
104 pub const fn addr(self) -> u8 {
105 match self {
106 Self::Low => 0x23,
107 Self::High => 0x5C,
108 Self::Custom(a) => a,
109 }
110 }
111}
112
113/// Resolution / measurement mode.
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum Resolution {
116 /// 1 lx resolution, typical measurement time ~120ms.
117 High,
118 /// 0.5 lx resolution, typical measurement time ~120ms.
119 High2,
120 /// 4 lx resolution, typical measurement time ~16ms.
121 Low,
122}
123
124impl Resolution {
125 pub(crate) const fn one_time_cmd(self) -> u8 {
126 match self {
127 Self::High => 0b0010_0000,
128 Self::High2 => 0b0010_0001,
129 Self::Low => 0b0010_0011,
130 }
131 }
132
133 pub(crate) const fn continuous_cmd(self) -> u8 {
134 match self {
135 Self::High => 0b0001_0000,
136 Self::High2 => 0b0001_0001,
137 Self::Low => 0b0001_0011,
138 }
139 }
140
141 pub(crate) const fn typical_delay_ms(self) -> u32 {
142 match self {
143 Self::High | Self::High2 => 120,
144 Self::Low => 16,
145 }
146 }
147
148 pub(crate) const fn resolution_divisor(self) -> f32 {
149 match self {
150 Self::High => 1.0,
151 Self::High2 => 2.0,
152 Self::Low => 1.0,
153 }
154 }
155}
156
157/// Measurement time register value.
158///
159/// Allowed range is 31..=254. Default is 69.
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub struct MeasurementTime(u8);
162
163impl MeasurementTime {
164 /// Default MTreg value (69).
165 pub const DEFAULT: Self = Self(69);
166 /// Minimum MTreg value (31).
167 pub const MIN: u8 = 31;
168 /// Maximum MTreg value (254).
169 pub const MAX: u8 = 254;
170
171 /// Create a new measurement time.
172 pub const fn new(value: u8) -> Option<Self> {
173 if value >= Self::MIN && value <= Self::MAX {
174 Some(Self(value))
175 } else {
176 None
177 }
178 }
179
180 /// Get the raw MTreg value.
181 #[must_use]
182 pub const fn value(self) -> u8 {
183 self.0
184 }
185}
186
187impl From<MeasurementTime> for u8 {
188 fn from(mt: MeasurementTime) -> Self {
189 mt.value()
190 }
191}
192
193impl From<u8> for MeasurementTime {
194 fn from(value: u8) -> Self {
195 Self::new(value).expect("MeasurementTime value out of range")
196 }
197}