Skip to main content

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}