1#![doc = include_str!("../README.md")]
2use coefficients::Coefficients;
3use embedded_hal::delay::DelayNs;
4use embedded_hal::i2c::I2c;
5use error::CustomError;
6
7mod coefficients;
8pub mod error;
9
10#[derive(Copy, Clone)]
12pub enum Resolution {
13 UltraLowPower = 0,
14 Standard = 1,
15 HighResolution = 2,
16 UltraHighResolution = 3,
17}
18
19enum Register {
20 ChipId = 0xD0,
21 SoftReset = 0xE0,
22 MeasurementControl = 0xF4,
23 DataOutputStart = 0xF6,
24 CalibrationOutStart = 0xAA,
25}
26
27enum Command {
28 Temperature = 0x2E,
29 Pressure = 0x34,
30 SoftReset = 0xB6,
31}
32
33pub trait Common<T: I2c> {
35 fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>>;
39
40 fn check_connection(&mut self) -> Result<(), CustomError<T::Error>> {
44 match self.read_chip_id() {
45 Ok(0x55) => Ok(()),
46 Err(error) => Err(error),
47 _ => Err(CustomError::InvalidDeviceIdentifier),
48 }
49 }
50
51 fn reset(&mut self) -> Result<(), CustomError<T::Error>>;
53}
54
55pub struct BMP180<T, D> {
57 address: u8,
58 i2c: T,
59 delay: D,
60}
61
62pub struct InitializedBMP180<T, D> {
64 inner: BMP180<T, D>,
65 data: Coefficients,
66}
67
68impl<T: I2c, D: DelayNs> Common<T> for InitializedBMP180<T, D> {
69 fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>> {
73 self.inner.write_and_read_single_byte(&[Register::ChipId as u8])
74 }
75
76 fn reset(&mut self) -> Result<(), CustomError<T::Error>> {
78 self.inner.write(&[Register::SoftReset as u8, Command::SoftReset as u8])?;
79 self.inner.delay.delay_ms(5);
80
81 Ok(())
82 }
83}
84
85impl<T: I2c, D: DelayNs> Common<T> for BMP180<T, D> {
86 fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>> {
90 self.write_and_read_single_byte(&[Register::ChipId as u8])
91 }
92
93 fn reset(&mut self) -> Result<(), CustomError<T::Error>> {
95 self.write(&[Register::SoftReset as u8, Command::SoftReset as u8])?;
96 self.delay.delay_ms(5);
97
98 Ok(())
99 }
100}
101
102impl<T: I2c, D: DelayNs> InitializedBMP180<T, D> {
103 fn read_uncompensated_temperature(&mut self) -> Result<u16, CustomError<T::Error>> {
105 self.inner.write(&[Register::MeasurementControl as u8, Command::Temperature as u8])?;
106 self.inner.delay.delay_ms(5);
107
108 Ok(u16::from_be_bytes(self.inner.write_and_read_exact_bytes(&[Register::DataOutputStart as u8])?))
109 }
110
111 fn read_uncompensated_pressure(&mut self, resolution: Resolution) -> Result<i32, CustomError<T::Error>> {
113 let oss = resolution as u8;
114 let mut buffer = [0u8; 4];
115
116 self.inner.write(&[Register::MeasurementControl as u8, Command::Pressure as u8 + (oss << 6)])?;
117
118 self.inner.delay.delay_ms(match resolution {
119 Resolution::UltraLowPower => 5,
120 Resolution::Standard => 8,
121 Resolution::HighResolution => 14,
122 Resolution::UltraHighResolution => 26,
123 });
124
125 self.inner.write_and_read_range(&[Register::DataOutputStart as u8], &mut buffer[1..4])?;
126
127 Ok(i32::from_be_bytes(buffer) >> (8 - oss))
128 }
129
130 pub fn temperature(&mut self) -> Result<f32, CustomError<T::Error>> {
132 let uncompensated_temperature = self.read_uncompensated_temperature()?;
133 let (temperature, _) = self.data.calculate_temperature(uncompensated_temperature as i32);
134
135 Ok(temperature)
136 }
137
138 pub fn pressure(&mut self, resolution: Resolution) -> Result<i32, CustomError<T::Error>> {
140 let uncompensated_temperature = self.read_uncompensated_temperature()?;
141 let (_, b5) = self.data.calculate_temperature(uncompensated_temperature as i32);
142
143 let uncompensated_pressure = self.read_uncompensated_pressure(resolution)?;
144 let pressure = self.data.calculate_pressure(b5, uncompensated_pressure, resolution);
145
146 Ok(pressure)
147 }
148
149 pub fn altitude(&mut self, resolution: Resolution) -> Result<f32, CustomError<T::Error>> {
151 let pressure = self.pressure(resolution)?;
152
153 Ok(self.data.calculate_altitude(pressure))
154 }
155
156 pub fn read_all(&mut self, resolution: Resolution) -> Result<(f32, i32, f32), CustomError<T::Error>> {
158 let uncompensated_temperature = self.read_uncompensated_temperature()?;
159 let uncompensated_pressure = self.read_uncompensated_pressure(resolution)?;
160
161 let (temperature, b5) = self.data.calculate_temperature(uncompensated_temperature as i32);
162
163 let pressure = self.data.calculate_pressure(b5, uncompensated_pressure, resolution);
164 let altitude = self.data.calculate_altitude(pressure);
165
166 Ok((temperature, pressure, altitude))
167 }
168}
169
170impl<T: I2c, D: DelayNs> BMP180<T, D> {
171 pub fn new(i2c: T, delay: D) -> Self {
173 Self {
174 address: 0b111_0111,
175 delay,
176 i2c,
177 }
178 }
179
180 pub fn initialize(mut self) -> Result<InitializedBMP180<T, D>, CustomError<T::Error>> {
182 let mut buffer = [0u8; 22];
183
184 self.i2c.write_read(self.address, &[Register::CalibrationOutStart as u8], &mut buffer)?;
185
186 let calibration = Coefficients::new(buffer)?;
187
188 Ok(InitializedBMP180 {
189 inner: self,
190 data: calibration,
191 })
192 }
193
194 pub fn set_address(&mut self, address: u8) {
196 self.address = address;
197 }
198
199 pub fn write_and_read_exact_bytes<const BYTES: usize>(&mut self, command: &[u8]) -> Result<[u8; BYTES], CustomError<T::Error>> {
201 let mut buffer = [0u8; BYTES];
202
203 self.i2c.write_read(self.address, command, &mut buffer)?;
204
205 Ok(buffer)
206 }
207
208 pub fn write_and_read_range(&mut self, command: &[u8], buffer: &mut [u8]) -> Result<(), CustomError<T::Error>> {
210 self.i2c.write_read(self.address, command, buffer)?;
211
212 Ok(())
213 }
214
215 pub fn write_and_read_single_byte(&mut self, command: &[u8]) -> Result<u8, CustomError<T::Error>> {
217 let mut buffer = [0u8; 1];
218
219 self.i2c.write_read(self.address, command, &mut buffer)?;
220
221 Ok(buffer[0])
222 }
223
224 pub fn write(&mut self, command: &[u8]) -> Result<(), CustomError<T::Error>> {
226 self.i2c.write(self.address, command)?;
227
228 Ok(())
229 }
230}