1use core::cell::Cell;
14use kernel::debug;
15use kernel::hil;
16use kernel::hil::i2c;
17use kernel::hil::time::{Alarm, ConvertTicks};
18use kernel::utilities::cells::{OptionalCell, TakeCell};
19use kernel::ErrorCode;
20
21pub static BASE_ADDR: u8 = 0x76;
22
23pub const BUFFER_SIZE: usize = 6;
25
26#[allow(non_camel_case_types)]
27#[allow(dead_code)]
28enum Register {
29 DIG_T1 = 0x88,
32 DIG_T2 = 0x8a,
33 DIG_T3 = 0x8c,
34 ID = 0xd0,
35 RESET = 0xe0,
36 STATUS = 0xf3,
39 CTRL_MEAS = 0xf4,
43 CONFIG = 0xf5,
47 PRESS_MSB = 0xf7,
48 PRESS_LSB = 0xf8,
49 PRESS_XLSB = 0xf9,
51 TEMP_MSB = 0xfa,
52 TEMP_LSB = 0xfb,
53 TEMP_XLSB = 0xfc,
55}
56
57#[derive(Clone, Copy, PartialEq, Debug)]
58struct CalibrationData {
59 dig_t1: u16,
60 dig_t2: i16,
61 dig_t3: i16,
62 }
64
65fn twobyte(lsb: u8, msb: u8) -> u16 {
68 u16::from_be_bytes([msb, lsb])
69}
70
71impl CalibrationData {
72 fn new(i2c_raw: &[u8]) -> Self {
73 CalibrationData {
74 dig_t1: twobyte(i2c_raw[0], i2c_raw[1]),
75 dig_t2: twobyte(i2c_raw[2], i2c_raw[3]) as i16,
76 dig_t3: twobyte(i2c_raw[4], i2c_raw[5]) as i16,
77 }
78 }
79
80 fn temp_from_raw(&self, temp: i32) -> i32 {
81 let dig_t1 = self.dig_t1 as i32; let dig_t2 = self.dig_t2 as i32; let dig_t3 = self.dig_t3 as i32; let var1 = (((temp >> 3) - (dig_t1 << 1)) * dig_t2) >> 11;
86 let a = (temp >> 4) - dig_t1;
87 let var2 = (((a * a) >> 12) * dig_t3) >> 14;
88 let t_fine = var1 + var2;
89 ((t_fine * 5) + 128) >> 8
90 }
91}
92
93#[derive(Clone, Copy, PartialEq, Debug)]
96enum State {
97 Uninitialized,
98 InitId,
99 InitResetting,
102 InitWaitingReady,
103 InitReadingCalibration,
104
105 Idle(CalibrationData),
106
107 Configuring(CalibrationData),
110 WaitingForAlarm(CalibrationData),
112 Waiting(CalibrationData),
114 Reading(CalibrationData),
117
118 IrrecoverableError,
121 Error,
124 Bug,
128}
129
130impl State {
131 fn to_bug(self) -> Self {
133 match self {
134 State::IrrecoverableError => State::IrrecoverableError,
136 _ => State::Bug,
137 }
138 }
139}
140
141struct I2cWrapper<'a, I: i2c::I2CDevice> {
143 i2c: &'a I,
144}
145
146impl<I: i2c::I2CDevice> I2cWrapper<'_, I> {
147 fn write<const COUNT: usize>(
148 &self,
149 buffer: &'static mut [u8],
150 addr: Register,
151 data: [u8; COUNT],
152 ) -> Result<(), (i2c::Error, &'static mut [u8])> {
153 buffer[0] = addr as u8;
154 buffer[1..][..COUNT].copy_from_slice(&data);
155 self.i2c.enable();
156 self.i2c.write(buffer, COUNT + 1)
157 }
158
159 fn read(
162 &self,
163 buffer: &'static mut [u8],
164 addr: Register,
165 count: usize,
166 ) -> Result<(), (i2c::Error, &'static mut [u8])> {
167 buffer[0] = addr as u8;
168 self.i2c.enable();
169 self.i2c.write_read(buffer, 1, count)
170 }
171
172 fn disable(&self) {
173 self.i2c.disable()
174 }
175
176 fn parse_read(buffer: &[u8], count: u8) -> &[u8] {
177 &buffer[..(count as usize)]
178 }
179}
180
181pub struct Bmp280<'a, A: Alarm<'a>, I: i2c::I2CDevice> {
182 i2c: I2cWrapper<'a, I>,
183 temperature_client: OptionalCell<&'a dyn hil::sensors::TemperatureClient>,
184 state: Cell<State>,
190 buffer: TakeCell<'static, [u8]>,
192 alarm: &'a A,
195}
196
197impl<'a, A: Alarm<'a>, I: i2c::I2CDevice> Bmp280<'a, A, I> {
198 pub fn new(i2c: &'a I, buffer: &'static mut [u8], alarm: &'a A) -> Self {
199 Self {
200 i2c: I2cWrapper { i2c },
201 temperature_client: OptionalCell::empty(),
202 state: Cell::new(State::Uninitialized),
203 buffer: TakeCell::new(buffer),
204 alarm,
205 }
206 }
207
208 pub fn begin_reset(&self) -> Result<(), ErrorCode> {
210 self.buffer
211 .take()
212 .map_or(Err(ErrorCode::NOMEM), |buffer| match self.state.get() {
213 State::Uninitialized | State::Error | State::Bug => {
214 let (ret, new_state) = match self.i2c.read(buffer, Register::ID, 1) {
215 Ok(()) => (Ok(()), State::InitId),
216 Err((_e, buffer)) => {
217 self.i2c.disable();
218 self.buffer.replace(buffer);
219 (Err(ErrorCode::FAIL), State::IrrecoverableError)
220 }
221 };
222 self.state.set(new_state);
223 ret
224 }
225 State::IrrecoverableError => Err(ErrorCode::NODEVICE),
226 _ => Err(ErrorCode::ALREADY),
227 })
228 }
229
230 pub fn read_temperature(&self) -> Result<(), ErrorCode> {
231 match self.state.get() {
232 State::Uninitialized => Err(ErrorCode::OFF),
234 State::InitId
235 | State::InitResetting
236 | State::InitWaitingReady
237 | State::InitReadingCalibration => Err(ErrorCode::BUSY),
238 State::Idle(calibration) => {
239 self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buffer| {
240 let val = 0b00100001;
243 let (ret, new_state) = match self.i2c.write(buffer, Register::CTRL_MEAS, [val])
244 {
245 Ok(()) => (Ok(()), State::Configuring(calibration)),
246 Err((_e, buffer)) => {
247 self.i2c.disable();
248 self.buffer.replace(buffer);
249 (Err(ErrorCode::FAIL), State::Idle(calibration))
250 }
251 };
252 self.state.set(new_state);
253 ret
254 })
255 }
256 State::Configuring(_)
257 | State::WaitingForAlarm(_)
258 | State::Waiting(_)
259 | State::Reading(_) => Err(ErrorCode::BUSY),
260 State::Error | State::Bug => Err(ErrorCode::FAIL),
261 State::IrrecoverableError => Err(ErrorCode::NODEVICE),
262 }
263 }
264
265 fn handle_alarm(&self) {
266 match self.state.get() {
267 State::WaitingForAlarm(calibration) => self.buffer.take().map_or_else(
268 || {
269 debug!("BMP280 No buffer available!");
270 self.state.set(State::IrrecoverableError)
271 },
272 |buffer| {
273 let new_state = match self.check_ready(buffer) {
274 Ok(()) => State::Waiting(calibration),
275 Err((_e, buffer)) => {
276 self.i2c.disable();
277 self.buffer.replace(buffer);
278 State::Idle(calibration)
279 }
280 };
281 self.state.set(new_state)
282 },
283 ),
284 State::IrrecoverableError => {}
285 other => {
286 debug!("BMP280 received unexpected alarm in state {:?}", other);
287 self.state.set(other.to_bug())
288 }
289 }
290 }
291
292 fn arm_alarm(&self) {
293 let delay = self.alarm.ticks_from_us(6400);
296 self.alarm.set_alarm(self.alarm.now(), delay);
297 }
298
299 fn check_ready(
300 &self,
301 buffer: &'static mut [u8],
302 ) -> Result<(), (i2c::Error, &'static mut [u8])> {
303 self.i2c.read(buffer, Register::STATUS, 1)
304 }
305}
306
307enum I2cOperation {
308 Read {
309 addr: Register,
310 count: usize,
311 fail_state: State,
312 },
313 Write {
314 addr: Register,
315 data: u8,
316 fail_state: State,
317 },
318 Disable,
319}
320
321impl I2cOperation {
322 fn check_ready(fail_state: State) -> Self {
323 Self::Read {
324 addr: Register::STATUS,
325 count: 1,
326 fail_state,
327 }
328 }
329}
330
331impl<'a, A: Alarm<'a>, I: i2c::I2CDevice> i2c::I2CClient for Bmp280<'a, A, I> {
332 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
333 let mut temp_readout = None;
334 let mut i2c_op = I2cOperation::Disable;
335
336 let new_state = match status {
337 Ok(()) => match self.state.get() {
338 State::InitId => {
339 let id = I2cWrapper::<I>::parse_read(buffer, 1);
340 if id[0] == 0x58 {
341 i2c_op = I2cOperation::Write {
342 addr: Register::RESET,
343 data: 0xb6,
344 fail_state: State::IrrecoverableError,
345 };
346 State::InitResetting
347 } else {
348 State::IrrecoverableError
349 }
350 }
351 State::InitResetting => {
352 i2c_op = I2cOperation::check_ready(State::Error);
353 State::InitWaitingReady
354 }
355 State::InitWaitingReady => {
356 let waiting = I2cWrapper::<I>::parse_read(buffer, 1)[0];
357 if waiting & 0b1 == 0 {
358 i2c_op = I2cOperation::Read {
360 addr: Register::DIG_T1,
361 count: 6,
362 fail_state: State::Error,
363 };
364 State::InitReadingCalibration
365 } else {
366 i2c_op = I2cOperation::check_ready(State::Error);
367 State::InitWaitingReady
368 }
369 }
370 State::InitReadingCalibration => {
371 let data = I2cWrapper::<I>::parse_read(buffer, 6);
372 let calibration = CalibrationData::new(data);
373 State::Idle(calibration)
374 }
375 State::Configuring(calibration) => {
377 self.arm_alarm();
378 State::WaitingForAlarm(calibration)
379 }
380 State::Waiting(calibration) => {
381 let waiting_value = I2cWrapper::<I>::parse_read(buffer, 1);
382 if waiting_value[0] & 0b1000 == 0 {
384 i2c_op = I2cOperation::Read {
385 addr: Register::TEMP_MSB,
386 count: 3,
387 fail_state: State::Idle(calibration),
388 };
389 State::Reading(calibration)
390 } else {
391 i2c_op = I2cOperation::check_ready(State::Idle(calibration));
392 State::Waiting(calibration)
393 }
394 }
395 State::Reading(calibration) => {
396 let readout = I2cWrapper::<I>::parse_read(buffer, 3);
397 let msb = readout[0] as u32;
398 let lsb = readout[1] as u32;
399 let xlsb = readout[2] as u32;
400 let raw_temp: i32 =
401 ((((msb << 12) + (lsb << 4) + (xlsb >> 4)) << 12) as i32) >> 12; temp_readout = Some(Ok(calibration.temp_from_raw(raw_temp)));
403 State::Idle(calibration)
404 }
405 other => {
406 debug!("BMP280 received unexpected i2c reply in state {:?}", other);
407 other.to_bug()
408 }
409 },
410 Err(i2c_err) => match self.state.get() {
411 State::Configuring(calibration)
412 | State::Waiting(calibration)
413 | State::Reading(calibration) => {
414 temp_readout = Some(Err(i2c_err.into()));
415 State::Idle(calibration)
416 }
417 State::InitId
418 | State::InitResetting
419 | State::InitWaitingReady
420 | State::InitReadingCalibration => State::Error,
421 other => {
422 debug!("BMP280 received unexpected i2c reply in state {:?}", other);
423 other.to_bug()
424 }
425 },
426 };
427
428 let new_state = match i2c_op {
430 I2cOperation::Disable => {
431 self.i2c.disable();
432 self.buffer.replace(buffer);
433 new_state
434 }
435 I2cOperation::Read {
436 addr,
437 count,
438 fail_state,
439 } => {
440 if let Err((_e, buffer)) = self.i2c.read(buffer, addr, count) {
441 self.i2c.disable();
442 self.buffer.replace(buffer);
443 fail_state
444 } else {
445 new_state
446 }
447 }
448 I2cOperation::Write {
449 addr,
450 data,
451 fail_state,
452 } => {
453 if let Err((_e, buffer)) = self.i2c.write(buffer, addr, [data]) {
454 self.i2c.disable();
455 self.buffer.replace(buffer);
456 fail_state
457 } else {
458 new_state
459 }
460 }
461 };
462
463 self.state.set(new_state);
466 if let Some(temp) = temp_readout {
467 self.temperature_client.map(|cb| cb.callback(temp));
468 }
469 }
470}
471
472impl<'a, A: Alarm<'a>, I: i2c::I2CDevice> hil::sensors::TemperatureDriver<'a> for Bmp280<'a, A, I> {
473 fn set_client(&self, client: &'a dyn hil::sensors::TemperatureClient) {
474 self.temperature_client.set(client)
475 }
476
477 fn read_temperature(&self) -> Result<(), ErrorCode> {
478 self.read_temperature()
479 }
480}
481
482impl<'a, A: hil::time::Alarm<'a>, I: i2c::I2CDevice> hil::time::AlarmClient for Bmp280<'a, A, I> {
483 fn alarm(&self) {
484 self.handle_alarm()
485 }
486}