1pub const I2C_ADDRESS_PRIMARY: u8 = 0x76;
19pub const I2C_ADDRESS_SECONDARY: u8 = 0x77;
21pub const CHIP_ID: u8 = 0x58;
23pub const RESET_WORD: u8 = 0xB6;
25pub const SKIPPED_OUTPUT: u32 = 0x80000;
27pub const CALIBRATION_LEN: usize = 24;
29pub const DATA_LEN: usize = 6;
31
32pub mod register {
34 pub const CALIBRATION: u8 = 0x88;
36 pub const CHIP_ID: u8 = 0xD0;
38 pub const RESET: u8 = 0xE0;
40 pub const STATUS: u8 = 0xF3;
42 pub const CTRL_MEAS: u8 = 0xF4;
44 pub const CONFIG: u8 = 0xF5;
46 pub const DATA: u8 = 0xF7;
48}
49
50pub fn measuring(status: u8) -> bool {
61 status & 0x08 != 0
62}
63
64pub fn image_updating(status: u8) -> bool {
75 status & 0x01 != 0
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
82pub enum Oversampling {
83 #[default]
85 Skipped,
86 X1,
88 X2,
90 X4,
92 X8,
94 X16,
96}
97
98impl Oversampling {
99 pub fn code(self) -> u8 {
101 match self {
102 Oversampling::Skipped => 0b000,
103 Oversampling::X1 => 0b001,
104 Oversampling::X2 => 0b010,
105 Oversampling::X4 => 0b011,
106 Oversampling::X8 => 0b100,
107 Oversampling::X16 => 0b101,
108 }
109 }
110
111 pub fn from_code(code: u8) -> Oversampling {
123 match code & 0b111 {
124 0b000 => Oversampling::Skipped,
125 0b001 => Oversampling::X1,
126 0b010 => Oversampling::X2,
127 0b011 => Oversampling::X4,
128 0b100 => Oversampling::X8,
129 _ => Oversampling::X16,
130 }
131 }
132
133 pub fn factor(self) -> u8 {
135 match self {
136 Oversampling::Skipped => 0,
137 Oversampling::X1 => 1,
138 Oversampling::X2 => 2,
139 Oversampling::X4 => 4,
140 Oversampling::X8 => 8,
141 Oversampling::X16 => 16,
142 }
143 }
144}
145
146#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
148pub enum Mode {
149 #[default]
151 Sleep,
152 Forced,
154 Normal,
156}
157
158impl Mode {
159 pub fn code(self) -> u8 {
161 match self {
162 Mode::Sleep => 0b00,
163 Mode::Forced => 0b01,
164 Mode::Normal => 0b11,
165 }
166 }
167
168 pub fn from_code(code: u8) -> Mode {
178 match code & 0b11 {
179 0b00 => Mode::Sleep,
180 0b11 => Mode::Normal,
181 _ => Mode::Forced,
182 }
183 }
184}
185
186#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
188pub enum Standby {
189 #[default]
191 Ms0_5,
192 Ms62_5,
194 Ms125,
196 Ms250,
198 Ms500,
200 Ms1000,
202 Ms2000,
204 Ms4000,
206}
207
208impl Standby {
209 pub fn code(self) -> u8 {
211 match self {
212 Standby::Ms0_5 => 0b000,
213 Standby::Ms62_5 => 0b001,
214 Standby::Ms125 => 0b010,
215 Standby::Ms250 => 0b011,
216 Standby::Ms500 => 0b100,
217 Standby::Ms1000 => 0b101,
218 Standby::Ms2000 => 0b110,
219 Standby::Ms4000 => 0b111,
220 }
221 }
222
223 pub fn from_code(code: u8) -> Standby {
233 match code & 0b111 {
234 0b000 => Standby::Ms0_5,
235 0b001 => Standby::Ms62_5,
236 0b010 => Standby::Ms125,
237 0b011 => Standby::Ms250,
238 0b100 => Standby::Ms500,
239 0b101 => Standby::Ms1000,
240 0b110 => Standby::Ms2000,
241 _ => Standby::Ms4000,
242 }
243 }
244
245 pub fn microseconds(self) -> u32 {
247 match self {
248 Standby::Ms0_5 => 500,
249 Standby::Ms62_5 => 62_500,
250 Standby::Ms125 => 125_000,
251 Standby::Ms250 => 250_000,
252 Standby::Ms500 => 500_000,
253 Standby::Ms1000 => 1_000_000,
254 Standby::Ms2000 => 2_000_000,
255 Standby::Ms4000 => 4_000_000,
256 }
257 }
258}
259
260#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
265pub struct CtrlMeas {
266 pub temperature: Oversampling,
268 pub pressure: Oversampling,
270 pub mode: Mode,
272}
273
274impl CtrlMeas {
275 pub fn bits(self) -> u8 {
281 (self.temperature.code() << 5) | (self.pressure.code() << 2) | self.mode.code()
282 }
283
284 pub fn from_bits(bits: u8) -> CtrlMeas {
294 CtrlMeas {
295 temperature: Oversampling::from_code(bits >> 5),
296 pressure: Oversampling::from_code(bits >> 2),
297 mode: Mode::from_code(bits),
298 }
299 }
300}
301
302#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
311pub struct Config {
312 pub standby: Standby,
314 pub filter: u8,
316 pub spi_3wire: bool,
318}
319
320impl Config {
321 pub fn bits(self) -> u8 {
328 (self.standby.code() << 5) | ((self.filter & 0b111) << 2) | u8::from(self.spi_3wire)
329 }
330
331 pub fn from_bits(bits: u8) -> Config {
341 Config {
342 standby: Standby::from_code(bits >> 5),
343 filter: (bits >> 2) & 0b111,
344 spi_3wire: bits & 0x01 != 0,
345 }
346 }
347}
348
349#[derive(Clone, Copy, Debug, PartialEq, Eq)]
355pub struct Calibration {
356 pub dig_t1: u16,
358 pub dig_t2: i16,
360 pub dig_t3: i16,
362 pub dig_p1: u16,
364 pub dig_p2: i16,
366 pub dig_p3: i16,
368 pub dig_p4: i16,
370 pub dig_p5: i16,
372 pub dig_p6: i16,
374 pub dig_p7: i16,
376 pub dig_p8: i16,
378 pub dig_p9: i16,
380}
381
382impl Calibration {
383 pub fn parse(bytes: &[u8; CALIBRATION_LEN]) -> Calibration {
393 let b = bytes;
394 Calibration {
395 dig_t1: u16::from_le_bytes([b[0], b[1]]),
396 dig_t2: i16::from_le_bytes([b[2], b[3]]),
397 dig_t3: i16::from_le_bytes([b[4], b[5]]),
398 dig_p1: u16::from_le_bytes([b[6], b[7]]),
399 dig_p2: i16::from_le_bytes([b[8], b[9]]),
400 dig_p3: i16::from_le_bytes([b[10], b[11]]),
401 dig_p4: i16::from_le_bytes([b[12], b[13]]),
402 dig_p5: i16::from_le_bytes([b[14], b[15]]),
403 dig_p6: i16::from_le_bytes([b[16], b[17]]),
404 dig_p7: i16::from_le_bytes([b[18], b[19]]),
405 dig_p8: i16::from_le_bytes([b[20], b[21]]),
406 dig_p9: i16::from_le_bytes([b[22], b[23]]),
407 }
408 }
409
410 pub fn to_bytes(&self) -> [u8; CALIBRATION_LEN] {
416 let mut out = [0u8; CALIBRATION_LEN];
417 let words = [
418 self.dig_t1,
419 self.dig_t2 as u16,
420 self.dig_t3 as u16,
421 self.dig_p1,
422 self.dig_p2 as u16,
423 self.dig_p3 as u16,
424 self.dig_p4 as u16,
425 self.dig_p5 as u16,
426 self.dig_p6 as u16,
427 self.dig_p7 as u16,
428 self.dig_p8 as u16,
429 self.dig_p9 as u16,
430 ];
431 for (chunk, word) in out.as_chunks_mut::<2>().0.iter_mut().zip(words) {
432 *chunk = word.to_le_bytes();
433 }
434 out
435 }
436
437 pub fn compensate(&self, raw: &Measurement) -> Reading {
450 let t_fine = self.t_fine(raw.temperature);
451 Reading {
452 temperature_centi_celsius: compensate_temperature(t_fine),
453 pressure_q24_8: self.compensate_pressure(raw.pressure, t_fine),
454 }
455 }
456
457 fn t_fine(&self, adc_t: u32) -> i32 {
460 let adc_t = i64::from(adc_t);
461 let dig_t1 = i64::from(self.dig_t1);
462 let var1 = (((adc_t >> 3) - (dig_t1 << 1)) * i64::from(self.dig_t2)) >> 11;
463 let near = (adc_t >> 4) - dig_t1;
464 let var2 = (((near * near) >> 12) * i64::from(self.dig_t3)) >> 14;
465 (var1 + var2) as i32
466 }
467
468 fn compensate_pressure(&self, adc_p: u32, t_fine: i32) -> u32 {
470 let mut var1 = i64::from(t_fine) - 128000;
471 let mut var2 = var1 * var1 * i64::from(self.dig_p6);
472 var2 += (var1 * i64::from(self.dig_p5)) << 17;
473 var2 += i64::from(self.dig_p4) << 35;
474 var1 =
475 ((var1 * var1 * i64::from(self.dig_p3)) >> 8) + ((var1 * i64::from(self.dig_p2)) << 12);
476 var1 = (((1i64 << 47) + var1) * i64::from(self.dig_p1)) >> 33;
477 if var1 == 0 {
478 return 0;
479 }
480 let mut p = 1048576 - i64::from(adc_p);
481 p = (((p << 31) - var2) * 3125) / var1;
482 var1 = (i64::from(self.dig_p9) * (p >> 13) * (p >> 13)) >> 25;
483 var2 = (i64::from(self.dig_p8) * p) >> 19;
484 p = ((p + var1 + var2) >> 8) + (i64::from(self.dig_p7) << 4);
485 p as u32
486 }
487}
488
489fn compensate_temperature(t_fine: i32) -> i32 {
491 ((i64::from(t_fine) * 5 + 128) >> 8) as i32
492}
493
494#[derive(Clone, Copy, Debug, PartialEq, Eq)]
496pub struct Measurement {
497 pub pressure: u32,
499 pub temperature: u32,
501}
502
503impl Measurement {
504 pub fn parse(data: &[u8; DATA_LEN]) -> Measurement {
517 let unpack = |msb: u8, lsb: u8, xlsb: u8| {
518 (u32::from(msb) << 12) | (u32::from(lsb) << 4) | (u32::from(xlsb) >> 4)
519 };
520 Measurement {
521 pressure: unpack(data[0], data[1], data[2]),
522 temperature: unpack(data[3], data[4], data[5]),
523 }
524 }
525
526 pub fn to_bytes(&self) -> [u8; DATA_LEN] {
533 let pack = |code: u32| {
534 [
535 ((code >> 12) & 0xFF) as u8,
536 ((code >> 4) & 0xFF) as u8,
537 ((code & 0x0F) << 4) as u8,
538 ]
539 };
540 let p = pack(self.pressure);
541 let t = pack(self.temperature);
542 [p[0], p[1], p[2], t[0], t[1], t[2]]
543 }
544
545 pub fn pressure_skipped(&self) -> bool {
547 self.pressure == SKIPPED_OUTPUT
548 }
549
550 pub fn temperature_skipped(&self) -> bool {
552 self.temperature == SKIPPED_OUTPUT
553 }
554}
555
556#[derive(Clone, Copy, Debug, PartialEq, Eq)]
561pub struct Reading {
562 pub temperature_centi_celsius: i32,
564 pub pressure_q24_8: u32,
566}
567
568impl Reading {
569 pub fn celsius(&self) -> f32 {
571 self.temperature_centi_celsius as f32 / 100.0
572 }
573
574 pub fn pascals(&self) -> u32 {
576 self.pressure_q24_8 >> 8
577 }
578
579 pub fn hectopascals(&self) -> f32 {
581 (f64::from(self.pressure_q24_8) / 25_600.0) as f32
582 }
583}
584
585#[cfg(test)]
586mod tests {
587 use super::*;
588
589 fn sample_calibration() -> Calibration {
593 Calibration {
594 dig_t1: 28485,
595 dig_t2: 26735,
596 dig_t3: 50,
597 dig_p1: 37190,
598 dig_p2: -10646,
599 dig_p3: 3024,
600 dig_p4: 7758,
601 dig_p5: -120,
602 dig_p6: -7,
603 dig_p7: 9900,
604 dig_p8: -10230,
605 dig_p9: 4285,
606 }
607 }
608
609 fn worked_example_calibration() -> Calibration {
613 Calibration {
614 dig_t1: 27504,
615 dig_t2: 26435,
616 dig_t3: -1000,
617 ..sample_calibration()
618 }
619 }
620
621 #[test]
622 fn register_map_matches_table_18() {
623 assert_eq!(register::CALIBRATION, 0x88);
624 assert_eq!(register::CHIP_ID, 0xD0);
625 assert_eq!(register::RESET, 0xE0);
626 assert_eq!(register::STATUS, 0xF3);
627 assert_eq!(register::CTRL_MEAS, 0xF4);
628 assert_eq!(register::CONFIG, 0xF5);
629 assert_eq!(register::DATA, 0xF7);
630 assert_eq!(CHIP_ID, 0x58);
632 assert_eq!(RESET_WORD, 0xB6);
633 assert_eq!(CALIBRATION_LEN, 0x9F - 0x88 + 1);
635 assert_eq!(DATA_LEN, 0xFC - 0xF7 + 1);
636 }
637
638 #[test]
639 fn i2c_address_follows_the_sdo_pin() {
640 assert_eq!(I2C_ADDRESS_PRIMARY, 0b1110110);
642 assert_eq!(I2C_ADDRESS_SECONDARY, 0b1110111);
643 }
644
645 #[test]
646 fn status_flags_sit_in_bits_3_and_0() {
647 assert!(measuring(0x08));
649 assert!(!measuring(0x01));
650 assert!(image_updating(0x01));
651 assert!(!image_updating(0x08));
652 assert!(!measuring(0x00) && !image_updating(0x00));
653 }
654
655 #[test]
656 fn oversampling_codes_and_factors_match_tables_21_and_22() {
657 let table = [
658 (0b000, Oversampling::Skipped, 0),
659 (0b001, Oversampling::X1, 1),
660 (0b010, Oversampling::X2, 2),
661 (0b011, Oversampling::X4, 4),
662 (0b100, Oversampling::X8, 8),
663 (0b101, Oversampling::X16, 16),
664 ];
665 for (code, setting, factor) in table {
666 assert_eq!(setting.code(), code);
667 assert_eq!(Oversampling::from_code(code), setting);
668 assert_eq!(setting.factor(), factor);
669 }
670 assert_eq!(Oversampling::from_code(0b110), Oversampling::X16);
672 assert_eq!(Oversampling::from_code(0b111), Oversampling::X16);
673 }
674
675 #[test]
676 fn mode_codes_match_table_10() {
677 assert_eq!(Mode::Sleep.code(), 0b00);
678 assert_eq!(Mode::Forced.code(), 0b01);
679 assert_eq!(Mode::Normal.code(), 0b11);
680 assert_eq!(Mode::from_code(0b00), Mode::Sleep);
681 assert_eq!(Mode::from_code(0b01), Mode::Forced);
683 assert_eq!(Mode::from_code(0b10), Mode::Forced);
684 assert_eq!(Mode::from_code(0b11), Mode::Normal);
685 }
686
687 #[test]
688 fn standby_codes_and_periods_match_table_11() {
689 let table = [
690 (0b000, Standby::Ms0_5, 500),
691 (0b001, Standby::Ms62_5, 62_500),
692 (0b010, Standby::Ms125, 125_000),
693 (0b011, Standby::Ms250, 250_000),
694 (0b100, Standby::Ms500, 500_000),
695 (0b101, Standby::Ms1000, 1_000_000),
696 (0b110, Standby::Ms2000, 2_000_000),
697 (0b111, Standby::Ms4000, 4_000_000),
698 ];
699 for (code, standby, micros) in table {
700 assert_eq!(standby.code(), code);
701 assert_eq!(Standby::from_code(code), standby);
702 assert_eq!(standby.microseconds(), micros);
703 }
704 }
705
706 #[test]
707 fn ctrl_meas_packs_the_fields_of_table_20() {
708 let ctrl = CtrlMeas {
711 temperature: Oversampling::X2,
712 pressure: Oversampling::X16,
713 mode: Mode::Normal,
714 };
715 assert_eq!(ctrl.bits(), 0b0101_0111);
716 assert_eq!(CtrlMeas::from_bits(0x57), ctrl);
717 assert_eq!(CtrlMeas::default().bits(), 0x00);
719 assert_eq!(CtrlMeas::from_bits(0x00), CtrlMeas::default());
720 for bits in 0..=u8::MAX {
721 let decoded = CtrlMeas::from_bits(bits);
722 assert_eq!(CtrlMeas::from_bits(decoded.bits()), decoded);
723 }
724 }
725
726 #[test]
727 fn config_packs_the_fields_of_table_23() {
728 let config = Config {
730 standby: Standby::Ms62_5,
731 filter: 0b100,
732 spi_3wire: true,
733 };
734 assert_eq!(config.bits(), 0b0011_0001);
735 assert_eq!(Config::from_bits(0x31), config);
736 assert_eq!(Config::default().bits(), 0x00);
737 assert_eq!(Config::from_bits(0x02), Config::default());
739 for bits in 0..=u8::MAX {
740 let decoded = Config::from_bits(bits);
741 assert_eq!(Config::from_bits(decoded.bits()), decoded);
742 }
743 }
744
745 #[test]
746 fn calibration_parses_the_table_17_layout_and_round_trips() {
747 let bytes: [u8; 24] = [
750 0x70, 0x6B, 0x43, 0x67, 0x18, 0xFC, 0x7D, 0x8E, 0x43, 0xD6, 0xD0, 0x0B, 0x27, 0x0B,
751 0x8C, 0x00, 0xF9, 0xFF, 0x8C, 0x3C, 0xF8, 0xC6, 0x70, 0x17,
752 ];
753 let calib = Calibration::parse(&bytes);
754 assert_eq!(
755 calib,
756 Calibration {
757 dig_t1: 27504,
758 dig_t2: 26435,
759 dig_t3: -1000,
760 dig_p1: 36477,
761 dig_p2: -10685,
762 dig_p3: 3024,
763 dig_p4: 2855,
764 dig_p5: 140,
765 dig_p6: -7,
766 dig_p7: 15500,
767 dig_p8: -14600,
768 dig_p9: 6000,
769 }
770 );
771 assert_eq!(calib.to_bytes(), bytes);
772 let sample = sample_calibration();
773 assert_eq!(Calibration::parse(&sample.to_bytes()), sample);
774 }
775
776 #[test]
777 fn measurement_parses_the_burst_read_and_round_trips() {
778 let data = [0x65, 0x5A, 0xC0, 0x7E, 0xED, 0x00];
781 let raw = Measurement::parse(&data);
782 assert_eq!(raw.pressure, 415_148);
783 assert_eq!(raw.temperature, 519_888);
784 assert_eq!(raw.to_bytes(), data);
785 assert_eq!(
787 Measurement::parse(&[0x65, 0x5A, 0xCF, 0x7E, 0xED, 0x0F]),
788 raw
789 );
790 assert_eq!(
791 Measurement::parse(&[0xFF; 6]).to_bytes(),
792 [0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xF0]
793 );
794 }
795
796 #[test]
797 fn skipped_measurements_read_as_0x80000() {
798 let raw = Measurement::parse(&[0x80, 0x00, 0x00, 0x80, 0x00, 0x00]);
801 assert_eq!(raw.pressure, SKIPPED_OUTPUT);
802 assert!(raw.pressure_skipped() && raw.temperature_skipped());
803 assert!(!Measurement::parse(&[0x65, 0x5A, 0xC0, 0x7E, 0xED, 0x00]).pressure_skipped());
804 }
805
806 #[test]
807 fn temperature_matches_the_worked_example() {
808 let calib = worked_example_calibration();
812 let t_fine = calib.t_fine(519_888);
813 assert_eq!(t_fine, 128_422);
814 assert_eq!(compensate_temperature(t_fine), 2508);
815 let reading = calib.compensate(&Measurement {
816 pressure: 415_148,
817 temperature: 519_888,
818 });
819 assert_eq!(reading.temperature_centi_celsius, 2508);
820 assert!((reading.celsius() - 25.08).abs() < 0.001);
821 }
822
823 #[test]
824 fn reference_vector_pins_the_integer_output() {
825 let calib = Calibration {
831 dig_t1: 27504,
832 dig_t2: 26435,
833 dig_t3: -1000,
834 dig_p1: 36477,
835 dig_p2: -10685,
836 dig_p3: 3024,
837 dig_p4: 2855,
838 dig_p5: 140,
839 dig_p6: -7,
840 dig_p7: 15500,
841 dig_p8: -14600,
842 dig_p9: 6000,
843 };
844 let raw = Measurement::parse(&[0x65, 0x5A, 0xC0, 0x7E, 0xED, 0x00]);
845 let reading = calib.compensate(&raw);
846 assert_eq!(reading.temperature_centi_celsius, 2508);
847 assert_eq!(reading.pressure_q24_8, 25_767_233);
848 assert_eq!(reading.pascals(), 100_653);
849 let (_, t_fine_ref) = reference_temperature(&calib, raw.temperature);
850 assert_eq!(calib.t_fine(raw.temperature), 128_422);
851 assert_eq!(t_fine_ref, 128_422);
852 let p_ref = reference_pressure(&calib, raw.pressure, t_fine_ref);
853 assert!((f64::from(reading.pressure_q24_8) / 256.0 - p_ref).abs() < 0.01);
854 }
855
856 #[test]
857 fn integer_compensation_tracks_the_floating_point_reference() {
858 for calib in [sample_calibration(), worked_example_calibration()] {
866 for adc_t in [400_000, 450_000, 500_000, 519_888, 540_000, 600_000] {
867 let t_fine = calib.t_fine(adc_t);
868 let t_int = compensate_temperature(t_fine);
869 let (t_ref, t_fine_ref) = reference_temperature(&calib, adc_t);
870 assert!(
871 (t_fine - t_fine_ref).abs() <= 3,
872 "t_fine {t_fine} vs {t_fine_ref}"
873 );
874 assert!(
875 (f64::from(t_int) / 100.0 - t_ref).abs() < 0.02,
876 "temperature {t_int} vs {t_ref}"
877 );
878 for adc_p in [300_000, 350_000, 415_148, 450_000, 512_000] {
879 let p_int = calib.compensate_pressure(adc_p, t_fine);
880 let p_ref = reference_pressure(&calib, adc_p, t_fine);
881 assert!(
882 (f64::from(p_int) / 256.0 - p_ref).abs() < 0.05,
883 "pressure {p_int} (Q24.8) vs {p_ref} Pa"
884 );
885 }
886 }
887 }
888 }
889
890 #[test]
891 fn any_20_bit_code_pair_compensates_without_overflow() {
892 let calib = sample_calibration();
893 for adc_t in (0..=0xF_FFFF).step_by(0x1_0000).chain([0xF_FFFF]) {
894 for adc_p in (0..=0xF_FFFF).step_by(0x1_0000).chain([0xF_FFFF]) {
895 let _ = calib.compensate(&Measurement {
896 pressure: adc_p,
897 temperature: adc_t,
898 });
899 }
900 }
901 }
902
903 #[test]
904 fn zero_dig_p1_takes_the_division_guard() {
905 let base = sample_calibration();
909 let calib = Calibration { dig_p1: 0, ..base };
910 let raw = Measurement::parse(&[0x65, 0x5A, 0xC0, 0x7E, 0xED, 0x00]);
911 let reading = calib.compensate(&raw);
912 assert_eq!(reading.pressure_q24_8, 0);
913 assert_eq!(reading.pascals(), 0);
914 let expected = base.compensate(&raw).temperature_centi_celsius;
915 assert_eq!(reading.temperature_centi_celsius, expected);
916 let t_fine = calib.t_fine(raw.temperature);
917 assert_eq!(reference_pressure(&calib, raw.pressure, t_fine), 0.0);
918 }
919
920 #[test]
921 fn reading_unit_helpers_match_the_reference_code_comments() {
922 let reading = Reading {
925 temperature_centi_celsius: 5123,
926 pressure_q24_8: 24_674_867,
927 };
928 assert!((reading.celsius() - 51.23).abs() < 0.001);
929 assert_eq!(reading.pascals(), 96_386);
930 assert!((reading.hectopascals() - 963.862).abs() < 0.001);
931 }
932
933 fn reference_temperature(c: &Calibration, adc_t: u32) -> (f64, i32) {
937 let adc_t = f64::from(adc_t);
938 let var1 = (adc_t / 16384.0 - f64::from(c.dig_t1) / 1024.0) * f64::from(c.dig_t2);
939 let var2 = {
940 let v = adc_t / 131072.0 - f64::from(c.dig_t1) / 8192.0;
941 v * v * f64::from(c.dig_t3)
942 };
943 ((var1 + var2) / 5120.0, (var1 + var2) as i32)
944 }
945
946 fn reference_pressure(c: &Calibration, adc_p: u32, t_fine: i32) -> f64 {
949 let mut var1 = (f64::from(t_fine) / 2.0) - 64000.0;
950 let mut var2 = var1 * var1 * f64::from(c.dig_p6) / 32768.0;
951 var2 += var1 * f64::from(c.dig_p5) * 2.0;
952 var2 = (var2 / 4.0) + (f64::from(c.dig_p4) * 65536.0);
953 var1 =
954 (f64::from(c.dig_p3) * var1 * var1 / 524288.0 + f64::from(c.dig_p2) * var1) / 524288.0;
955 var1 = (1.0 + var1 / 32768.0) * f64::from(c.dig_p1);
956 if var1 == 0.0 {
957 return 0.0;
958 }
959 let mut p = 1048576.0 - f64::from(adc_p);
960 p = (p - (var2 / 4096.0)) * 6250.0 / var1;
961 var1 = f64::from(c.dig_p9) * p * p / 2147483648.0;
962 var2 = p * f64::from(c.dig_p8) / 32768.0;
963 p + (var1 + var2 + f64::from(c.dig_p7)) / 16.0
964 }
965}