Skip to main content

bmp38x_ya/
lib.rs

1#![no_std]
2#![allow(dead_code)]
3#![allow(unused_variables)]
4
5//#![feature(inherent_associated_types)]
6pub mod error;
7
8
9use crate::data::{Bmp3Configuration, ControlFrameEnum, FifoConfig1, FifoConfig2, SensorFrameEnum, TandPtype};
10use crate::error::Error;
11
12pub mod data;
13// ojs  use crate::data::{DeviceInfo, DeviceModel, CalibrationPars};
14
15pub mod constants;
16
17use crate::constants::DeviceAddress::{Primary, Secondary};
18
19
20
21use constants::{BMP3_REG_CHIP_ID, BMP3_REG_ERR, BMP3_REG_SENS_STATUS, BMP3_REG_PRESS_DATA, BMP3_REG_TEMP_DATA,
22                BMP3_REG_SENSOR_TIME, BMP3_REG_EVENT, BMP3_REG_INT_STATUS, BMP3_REG_FIFO_LENGTH, BMP3_REG_FIFO_DATA,
23                BMP3_REG_FIFO_WM, BMP3_REG_FIFO_CONFIG_1, BMP3_REG_FIFO_CONFIG_2, BMP3_REG_INT_CTRL, 
24                BMP3_REG_IF_CONF, BMP3_REG_PWR_CTRL, BMP3_REG_OSR, BMP3_REG_ODR, BMP3_REG_CONFIG, BMP3_REG_CALIB_DATA,
25                BMP3_REG_CMD, BMP3_SOFT_RESET, BMP3_FIFO_FLUSH};
26                
27use data::{DeviceInfo, DeviceModel, Measurements, PWR_CTRL, PowerMode, Status, ErrorReg, IntStatus, Odr, Over_Sampling,
28           OSR, FilterCoef, CalibrationPars, InterruptPinControl, Fifo_Config, FifoFrame};
29
30#[cfg(not(feature = "async"))]
31use embedded_hal::{i2c::I2c, delay::DelayNs};
32#[cfg(feature = "async")]
33use embedded_hal_async::{i2c::I2c as AsyncI2c, delay::DelayNs as AsyncDelayNs};
34
35use log::{debug, info};
36use libm::{pow, truncf};
37
38const STANDARD_SEA_LEVEL_AIR_PRESSURE: f64 = 101325.0;  // Pa
39
40
41/// the BMP38x device
42pub struct BMP38x<I2C, D> {
43    /// I²C interface
44    i2c: I2C,
45    /// I²C device address
46    address: u8,
47    delayer: D,
48    pub device_info: DeviceInfo,
49    cal_pars: CalibrationPars,
50    fifo_config:  Fifo_Config,
51    /// altitude in metres above sealevel, used for sealevel equivalent air pressure calculation
52    pub altitude_m: f64,
53}
54
55#[cfg(not(feature = "async"))]
56impl<I2C, D, E> BMP38x<I2C, D>
57where  
58    I2C: I2c<Error = E>,
59    D: DelayNs,
60{
61    
62    //type Error = Error;
63    /// create new BMP38x driver with default I2C address: ADDR pin low
64    pub fn new(i2c: I2C, address: u8, delayer: D) -> Self {
65        log::debug!("new called");
66        Self {
67            i2c,
68            address: address,
69            delayer,
70            device_info: DeviceInfo { ..Default::default()},
71            cal_pars: CalibrationPars { .. Default::default()},
72            fifo_config:  Fifo_Config { .. Default::default()},
73            altitude_m : 0.0,
74        }
75    }
76
77    pub fn new_with_altitude(i2c: I2C, address: u8, delayer: D, altitude: f64) -> Self {
78        log::debug!("new_with_altitude called");
79        Self {
80            i2c,
81            address: address,
82            delayer,
83            device_info: DeviceInfo { ..Default::default()},
84            cal_pars: CalibrationPars { .. Default::default()},
85            fifo_config:  Fifo_Config { ..Default::default()},
86            altitude_m : altitude,
87        }
88    }
89
90    /// give back the I2C interface
91    pub fn release(self) -> I2C {
92        self.i2c
93    }
94
95}
96
97#[cfg(feature = "async")]
98impl<I2C, D, E> BMP38x<I2C, D>
99where  
100    I2C: AsyncI2c<Error = E>,
101    D: AsyncDelayNs,
102{
103    //type Error = Error;
104    /// create new BMP38x driver with default I2C address: ADDR pin low
105    pub fn new(i2c: I2C, address: u8, delayer: D) -> Self {
106        debug!("new called");
107        Self {
108            i2c,
109            address: address,
110            delayer,
111            device_info: DeviceInfo { ..Default::default()},
112            cal_pars: CalibrationPars::default(),
113        }
114    }
115
116    /// give back the I2C interface
117    pub fn release(self) -> I2C {
118        self.i2c
119    }
120
121}
122
123#[maybe_async_cfg::maybe(
124    sync(
125        cfg(not(feature = "async")),
126        self = "BMP38x",
127        idents(AsyncI2c(sync = "I2c"), AsyncDelayNs(sync = "DelayNs"))
128    ),
129    async(feature = "async", keep_self)
130)]
131
132impl<I2C, D, E> BMP38x<I2C, D>
133where  
134    I2C: AsyncI2c<Error = E>,
135    D: AsyncDelayNs,
136{
137
138    // command_buf is an u8 array that starts with command byte followed by command data byte(s)
139    async fn write_command<const N: usize>(&mut self, command_buf: [u8; N] ) -> Result<(), Error<E>> {
140        // debug!("write_command : {:#?}", command_buf);
141        self.i2c
142            .write(self.address, &command_buf).await
143            .map_err(Error::I2c)?;
144        Ok(())
145    }
146
147    async fn read_register( &mut self, register_address: u8, buffer: &mut [u8] ) -> Result<(), Error<E>> {
148        let mut command_buffer = [0u8; 1];
149        command_buffer[0] = register_address;
150        // let mut result_buffer = [0u8; N];
151        self.i2c
152            .write_read(self.address, &command_buffer, buffer).await
153            .map_err(Error::I2c)?;
154        Ok(())
155    }
156
157
158
159
160    /// reset BMP38x soft reset 
161    pub async fn reset_device(&mut self) -> Result<(), Error<E>> {
162        debug!("in reset_device()");
163        // check for (new) command ready
164        let mut result_buf: [u8; 1] = [0; 1];
165        self.read_register(BMP3_REG_SENS_STATUS, &mut result_buf).await?;
166        let status = Status(result_buf[0]);
167        if (status.get_cmd_ready()) {
168            //let write_buf: [u8; 2] = [BMP3_REG_CMD, BMP3_SOFT_RESET];
169            self.write_command([BMP3_REG_CMD, BMP3_SOFT_RESET]).await?;
170
171            // self.i2c.write(self.address, &write_buf).await
172            //         .map_err(Error::I2c);
173
174            //self.write_command([BMP3_REG_CMD, write_buf]).await? ; 
175            self.delayer.delay_ms(5).await;
176            self.read_register(BMP3_REG_EVENT, &mut result_buf).await?;  // clear the stuff
177            self.read_register(BMP3_REG_ERR, &mut result_buf).await?;
178            let error_value = ErrorReg(result_buf[0]);
179            if ( error_value.get_cfg_error() || error_value.get_cmd_error() || error_value.get_fatal_error() ) {
180                return Err(Error::CommandError);
181            } 
182            return Ok(());
183        }
184        Err(Error::NotReadyForCommand)   
185    }
186
187
188    /// initial BMP38x device, setting Normal PWR_CTRL mode, and enabling pressure and temperature sensing
189    ///                        also, using default output data rates
190    pub async fn init_device(&mut self) -> Result<bool, Error<E>> {
191        // set default calibration values
192        // check chip ID
193        debug!("in init_device(), doing reset_device");
194        self.reset_device().await?;
195        //#[allow(unused_parens)]
196
197        if (self.get_chip_id().await? == DeviceModel::NotRead) {
198            debug!("device model is not read");
199            return Ok(false);
200        }
201        debug!("reading calibration pars");
202        self.read_calibration_pars()?;
203        self.set_power_control_mode(PowerMode::Normal)?;
204        let pwr_ctrl_now = self.get_power_mode().await?;
205        debug!("  power_control_mode is now {:?}", pwr_ctrl_now);
206        self.set_pressure_enable(true)?;
207        self.set_temperature_enable(true)?;
208        let pwr_ctrl_now = self.get_power_mode().await?;
209        debug!("  power_control_mode is after press and temp enabled {:?}", pwr_ctrl_now);
210        Ok(true)
211    }
212
213
214    /// read device model 
215    pub async fn get_chip_id(&mut self) -> Result<DeviceModel, Error<E>> {
216        let mut result_buf: [u8; 1] = [0; 1];
217        let mut command_buffer: [u8; 1] = [BMP3_REG_CHIP_ID];
218        self.i2c
219            .write_read(self.address, &command_buffer, &mut result_buf).await
220            .map_err(Error::I2c)?;
221        self.device_info.id = DeviceModel::from(result_buf[0]);
222          
223        Ok(DeviceModel::from(result_buf[0]))
224    }
225
226    /// get status
227    pub async fn get_status(&mut self) -> Result<Status, Error<E>> {
228        debug!("in get_status()");
229        // check for (new) command ready
230        let mut result_buf: [u8; 1] = [0; 1];
231        self.read_register(BMP3_REG_SENS_STATUS, &mut result_buf).await?;
232        //info!("  get_status returned {:#b}", result_buf[0]);
233        let status = Status(result_buf[0]);
234        Ok(status)
235    }
236
237    /// set Power Mode
238    pub async fn set_power_mode(&mut self, power_mode: PowerMode) -> Result<(), Error<E>> {
239        debug!("in set_power_mode( {:?} )", power_mode);
240        let mut result_buf: [u8; 1] = [0; 1];
241        self.read_register(BMP3_REG_PWR_CTRL, &mut result_buf).await?;
242        let mut pwr_ctrl: PWR_CTRL = PWR_CTRL(result_buf[0]);
243        pwr_ctrl.set_power_mode(power_mode as u8);
244        self.write_command([BMP3_REG_PWR_CTRL, pwr_ctrl.0]).await?;
245        self.delayer.delay_ms(20).await;
246        Ok(())
247    }
248
249    /// set air pressure enable state
250    pub async fn set_pressure_enable(&mut self, enable: bool) -> Result<(), Error<E>> {
251        debug!("in set_pressure_enable()");
252        let mut result_buf: [u8; 1] = [0; 1];
253        self.read_register(BMP3_REG_PWR_CTRL, & mut result_buf).await?;
254        debug!("  read BMP3_REG_PWR_CTRL = {:b}", result_buf[0]);
255        let mut pwr_ctrl: PWR_CTRL = PWR_CTRL(result_buf[0]);
256        pwr_ctrl.set_press_en(enable);
257        debug!("  writing pwr_ctrl {:#b}", pwr_ctrl.0);
258        self.write_command([BMP3_REG_PWR_CTRL, pwr_ctrl.0]).await?;
259        self.delayer.delay_ms(20).await;
260        Ok(())
261    }
262    
263    /// set temperature enable state
264    pub async fn set_temperature_enable(&mut self, enable: bool) -> Result<(), Error<E>> {
265        debug!("in set_temperature_enable()");
266        let mut result_buf: [u8; 1] = [0; 1];
267        self.read_register(BMP3_REG_PWR_CTRL, &mut result_buf).await?;
268        debug!("  read BMP3_REG_PWR_CTRL = {:b}", result_buf[0]);
269        let mut pwr_ctrl: PWR_CTRL = PWR_CTRL(result_buf[0]);
270        debug!(" read PWR_CTRL reg = {:#b}", pwr_ctrl.0);
271        pwr_ctrl.set_temp_en(enable);
272        
273        // line below should not be needed, but it is?
274        //pwr_ctrl.set_power_mode(PowerMode::Normal as u8);
275
276
277        debug!(" writing PWR_CTRL reg = {:#b} or {:?}", pwr_ctrl.0, pwr_ctrl);
278
279        // pwr_ctrl.set_temp_en(false);
280        // info!("  set_temp_en(false) = {:?}  ({:#b})", pwr_ctrl, pwr_ctrl.0);
281        // pwr_ctrl.set_press_en(false);
282        // info!("  set_press_en(false) = {:?}  ({:#b})", pwr_ctrl, pwr_ctrl.0);
283        // pwr_ctrl.set_power_mode(PowerMode::Normal as u8);
284        // info!("  set_power_mode(PowerMode::Normal) = {:?}  ({:#b})", pwr_ctrl, pwr_ctrl.0);
285
286
287        self.write_command([BMP3_REG_PWR_CTRL, pwr_ctrl.0]).await?;
288        self.delayer.delay_ms(20).await;
289        Ok(())
290    }
291
292    /// set BMP38x configuration
293    pub async fn set_bmp3_configuration(&mut self, config:  Bmp3Configuration) -> Result<(), Error<E>> {
294        // not using the bitfield struct because it does not support const builder
295        debug!("in set_bmp3_configuration({:?})", config);
296        // set power mode
297        self.set_power_control_mode(config.power_mode).await?;
298        debug!("  set_power_control_mode to {:?}", config.power_mode);
299        // set temperature ans pressure enable states
300        self.set_temperature_enable(config.temperature_enable).await?;
301        self.set_pressure_enable(config.pressure_enable).await?;
302        // set oversampling
303        let osp: u8 = config.over_sampling_press as u8;
304        let ost: u8 = (config.over_sampling_temp as u8) << 3;
305        let osr: u8 = ost | osp;
306        debug!("  writing REG_OSR to {:#b}", osr);
307        self.write_command([BMP3_REG_OSR, osr]).await?;
308        self.delayer.delay_ms(20);
309        // set output data rate
310        let odr: u8 = config.output_data_rate as u8;
311        debug!("  writing REG_ODR to {:#b}", odr);
312        self.write_command([BMP3_REG_ODR, odr]).await?;
313        self.delayer.delay_ms(20);
314        // set IIR filter
315        let iir_coef: u8 = (config.iir_filter_coef as u8) << 1;
316        debug!("  writing REG_CONFIG (IIR) to {:#b}", iir_coef);
317        self.write_command([BMP3_REG_CONFIG, iir_coef]).await?;
318        self.delayer.delay_ms(20).await;
319        Ok(())
320    }
321
322    /// get BMP38x configuration:  control(power mode, pressure enable and temperature enable), over sampling, ODR, filter, interrupt control.
323    pub async fn get_bmp3_configuration(&mut self) -> Result<Bmp3Configuration, Error<E>> {
324        debug!("in get_bmp3_configuration");
325        let mut result_buf: [u8; 7] = [0; 7];
326        // first result_buf is INT_CONF, then IF_CONF(skip), PWR_CTRL, OSR, ODR, skip byte, IIR_CONFIG
327        self.read_register(BMP3_REG_INT_CTRL, &mut result_buf).await?;
328        debug!(" read config = {:?}", result_buf);
329        let _int_pin = result_buf[0];
330        //info!(" int_pin = {:?}", int_pin);
331        let pwr_ctrl: PWR_CTRL = PWR_CTRL(result_buf[2]); // power_mode bit are not set correctly
332        debug!(" pwr_ctrl = {:?}", pwr_ctrl);
333        let pwr_mode = self.get_power_mode().await?;  // must read PWR_CTRL register separately for this
334        let temp_enable = pwr_ctrl.get_temp_en();
335        let press_enable = pwr_ctrl.get_press_en();
336        let osr_p = Over_Sampling::from(result_buf[3] & 0x07);
337        //info!(" osr_p = {:?}", osr_p);
338        let osr_t = Over_Sampling::from((result_buf[3] & 0x38) >> 3);
339        //info!(" osr_t = {:?}", osr_t);
340        let odr: Odr = Odr::from(result_buf[4] & 0x3f);
341        //info!(" odr = {:?}", odr);
342        let iir_filter = FilterCoef::from(result_buf[6]>>1);
343        //info!(" iir_filter = {:?}", iir_filter);
344
345        Ok(Bmp3Configuration {
346            power_mode:  pwr_mode,
347            temperature_enable: temp_enable,
348            pressure_enable: press_enable,
349            over_sampling_temp: osr_t,
350            over_sampling_press: osr_p,
351            output_data_rate: odr,
352            iir_filter_coef: iir_filter,
353        })
354
355    }
356
357        
358
359    /// set interrupt pin configuration
360    pub async fn set_interrupt_pin_config(&mut self, intpin_config: InterruptPinControl) -> Result<(), Error<E>> {
361        debug!("in set_interrupt_pin_config()");
362        let status = self.get_status().await?;
363        if (status.get_cmd_ready()) {
364            self.write_command([BMP3_REG_INT_CTRL, intpin_config.0] ).await?;
365            self.delayer.delay_ms(20);
366            Ok(())
367        } else {
368            Err(Error::NotReadyForCommand)
369        }
370    }
371
372    /// get interrupt pin configuration
373    pub async fn get_interrupt_pin_configuration(&mut self) -> Result<InterruptPinControl, Error<E>> {
374        debug!("in get_interrupt_pin_configuration");
375        let mut result_buf: [u8; 1] = [0; 1];
376        self.read_register(BMP3_REG_INT_CTRL, &mut result_buf).await?;
377        info!("  raw value is {:b}", result_buf[0]);
378        Ok(InterruptPinControl(result_buf[0]))
379    }
380
381
382    /// get interrupt status INT_STATUS, register cleared after this called by BMP38x
383    pub async fn get_interrupt_status(&mut self) -> Result<IntStatus, Error<E>> {
384        debug!("in get_interrupt_status");
385        let mut result_buf: [u8; 1] = [0; 1];
386        self.read_register(BMP3_REG_INT_STATUS, &mut result_buf).await?;
387        Ok(IntStatus(result_buf[0]))
388    }
389    
390    /// read calibration registers and save into device property
391    pub async fn read_calibration_pars(&mut self) -> Result<(), Error<E>> {
392        let mut result_buf: [u8; 21] = [0; 21];
393        self.read_register(BMP3_REG_CALIB_DATA+1, &mut result_buf).await;
394
395        let nvm_par_t1:  u16 = result_buf[0] as u16 | ( (result_buf[1] as u16) << 8 );
396        let nvm_par_t2:  u16 = result_buf[2] as u16 | ( (result_buf[3] as u16) << 8 );
397        let nvm_par_t3:  i8 = result_buf[4] as i8;
398        // convert to usable calibration pars
399        self.cal_pars.par_t1_f = (nvm_par_t1 as f64) / 0.003_906_25;
400        self.cal_pars.par_t2_f = (nvm_par_t2 as f64) / 1_073_741_824.0;
401        self.cal_pars.par_t3_f = (nvm_par_t3 as f64) / 281_474_976_710_656.0;
402 
403        let nvm_par_p1:  i16  = ( (result_buf[6] as i16) << 8 ) | result_buf[5]  as i16 ;
404        let nvm_par_p2:  i16  = ( (result_buf[8] as i16) << 8 ) | result_buf[7]  as i16 ;
405        let nvm_par_p3:  i8  = result_buf[9]  as i8;
406        let nvm_par_p4:  i8  = result_buf[10] as i8;
407        let nvm_par_p5:  u16  = ( (result_buf[12] as u16) << 8 ) | result_buf[11] as u16 ;
408        let nvm_par_p6:  u16  = ( (result_buf[14] as u16) << 8 ) | result_buf[13] as u16 ;
409
410
411        let nvm_par_p7:  i8  = result_buf[15] as i8;
412        let nvm_par_p8:  i8  = result_buf[16] as i8;
413        let nvm_par_p9:  i16  = ( (result_buf[18] as i16) << 8 ) | result_buf[17] as i16 ;
414        let nvm_par_p10: i8 = result_buf[19] as i8;
415        let nvm_par_p11: i8 = result_buf[20] as i8;
416
417        // info!("nvm_par_p1 = {}", nvm_par_p1);
418        // info!("nvm_par_p2 = {}", nvm_par_p2);
419        // info!("nvm_par_p3 = {}", nvm_par_p3);
420        // info!("nvm_par_p4 = {}", nvm_par_p4);
421        // info!("nvm_par_p5 = {}", nvm_par_p5);
422        // info!("nvm_par_p6 = {}", nvm_par_p6);
423        // info!("nvm_par_p7 = {}", nvm_par_p7);
424        // info!("nvm_par_p8 = {}", nvm_par_p8);
425        // info!("nvm_par_p9 = {}", nvm_par_p9);
426        // info!("nvm_par_p10 = {}", nvm_par_p10);
427        // info!("nvm_par_p11 = {}", nvm_par_p11);
428
429        // convert to usable calibration pars
430        self.cal_pars.par_p1_f =  (nvm_par_p1 as f64 - 16384.0) / 1048576.0;
431        self.cal_pars.par_p2_f =  (nvm_par_p2 as f64 - 16384.0) / 536870912.0;
432        self.cal_pars.par_p3_f =  (nvm_par_p3 as f64) / 4294967296.0;
433        self.cal_pars.par_p4_f =  (nvm_par_p4 as f64) / 137438953472.0;
434        self.cal_pars.par_p5_f =  (nvm_par_p5 as f64) / 0.125; 
435        self.cal_pars.par_p6_f =  (nvm_par_p6 as f64) / 64.0;
436        self.cal_pars.par_p7_f =  (nvm_par_p7 as f64) / 256.0;
437        self.cal_pars.par_p8_f =  (nvm_par_p8 as f64) / 32768.0;
438        self.cal_pars.par_p9_f =  (nvm_par_p9 as f64) / 281474976710656.0;
439        self.cal_pars.par_p10_f = (nvm_par_p10 as f64) / 281474976710656.0;
440        self.cal_pars.par_p11_f = (nvm_par_p11 as f64) / 36893488147419103232.0;
441    
442        Ok(())
443    }
444    
445    pub fn compensate_temperature(&self,  raw_temperature: u32) -> f64 {      
446        let temp_1 = (raw_temperature as f64) - self.cal_pars.par_t1_f;
447        let temp_2 = (temp_1 as f64) * self.cal_pars.par_t2_f;
448        let temperature = temp_2 + (temp_1 * temp_1) * self.cal_pars.par_t3_f;
449        
450        // temp_1 = temp_1 * self.cal_pars.par_t2_f;
451        // temp_1 = (temp_1 * temp_1) * self.cal_pars.par_t3_f;
452        temperature
453    }
454    
455    pub fn compensate_pressure(&self, raw_pressure: f64, temperature: f64) -> f64 {
456        debug!("in compensate_pressure({})", temperature);
457        // roughly translated from Bosch manual's C code
458
459        let calc_part1 = self.cal_pars.par_p6_f * temperature;
460        let calc_part2 = self.cal_pars.par_p7_f * (temperature * temperature);
461        let calc_part3 = self.cal_pars.par_p8_f * (temperature * temperature * temperature);
462        let partial_1 = self.cal_pars.par_p5_f + calc_part1 + calc_part2 + calc_part3;
463        debug!("  partial_1  _out1 = {}", partial_1);
464
465        let calc_part1 = self.cal_pars.par_p2_f * temperature;
466        let calc_part2 = self.cal_pars.par_p3_f * (temperature * temperature);
467        
468        let calc_part3 = self.cal_pars.par_p4_f * (temperature * temperature * temperature);
469        let partial_2 = raw_pressure * ( self.cal_pars.par_p1_f + calc_part1 + calc_part2 + calc_part3);
470        debug!("  partial_2   out2= {}", partial_2);
471        
472        let calc_part1 = raw_pressure * raw_pressure ;
473        let calc_part2 = self.cal_pars.par_p9_f + self.cal_pars.par_p10_f * temperature;
474        let calc_part3 = calc_part1 * calc_part2;
475        
476        let partial_3 = calc_part3 + (raw_pressure * raw_pressure * raw_pressure) * self.cal_pars.par_p11_f;
477        debug!("  partial_3  partial_data4 = {}", partial_3);
478
479        partial_1 + partial_2 + partial_3
480      
481
482        
483
484    }
485    /// get equivalent sealevel air pressure for given altitude (in metres)
486    pub fn get_sealevel_airpressure(&self, air_pressure: f64, temperature: f64, altitude_m: f64) -> f64 {
487         
488        let exponent = -9.80665 * 0.028964 * altitude_m / (8.31432 * (temperature + 273.15));
489        let base: f64 = 2.71828175f64;
490        let air_press_at_sealevel = (air_pressure / 100.0) / pow(base, exponent) * 100.00;
491         // kind-a silly to /100.0 and * 100.0 again, just more reabable
492        air_press_at_sealevel
493    }
494    
495    /// read the temperature and air pressure measurements with a specifica altitude of BMP38x device
496    pub async fn read_measurements_with_altitude(&mut self, altitude: f64) -> Result<Measurements, Error<E>> {
497        debug!("in read_measurements_with_altitude");
498        let mut result_buf: [u8; 6] = [0; 6];
499        let command_buf: [u8; 1] = [BMP3_REG_PRESS_DATA];
500        // self.i2c
501        //     .write_read(self.address, &command_buf, &mut result_buf).await
502        //     .map_err(Error::I2c)?;
503        self.read_register(BMP3_REG_PRESS_DATA, &mut result_buf).await?;
504        let raw_pressure = result_buf[0] as u32 | ((result_buf[1] as u32) << 8) | (result_buf[2] as u32) << 16;
505        let raw_temperature = result_buf[3] as u32 | ((result_buf[4] as u32) << 8) | (result_buf[5] as u32) << 16;
506        debug!(" read_measurement_with..");
507        debug!(" raw_pressure = {:?}", raw_pressure);
508        //info!(" raw_temperature = {:?}", raw_temperature);
509        
510        let compensated_temp = self.compensate_temperature(raw_temperature);
511        let compensated_press = self.compensate_pressure(raw_pressure as f64, compensated_temp as f64);
512        
513        let sealevel_press = self.get_sealevel_airpressure(compensated_press as f64, compensated_temp, altitude);
514        self.altitude_m = altitude;
515
516        Ok(Measurements { temperature_c: compensated_temp, air_pressure_pa: compensated_press , 
517                air_pressure_sealevel_pa: sealevel_press })
518        
519    }
520
521    /// read the temperature and air pressure measurements new ( 0 m) or new_with_altitude initialized altitude value 
522    pub async fn read_measurements(&mut self) ->  Result<Measurements, Error<E>> {
523        debug!("in read_measurements");
524        let mut result_buf: [u8; 6] = [0; 6];
525        let command_buf: [u8; 1] = [BMP3_REG_PRESS_DATA];
526        self.i2c
527            .write_read(self.address, &command_buf, &mut result_buf).await
528            .map_err(Error::I2c)?;
529        let raw_pressure = result_buf[0] as u32 | ((result_buf[1] as u32) << 8) | (result_buf[2] as u32) << 16;
530        let raw_temperature = result_buf[3] as u32 | ((result_buf[4] as u32) << 8) | (result_buf[5] as u32) << 16;
531        
532        let compensated_temp = self.compensate_temperature(raw_temperature);
533        let compensated_press = self.compensate_pressure(raw_pressure as f64, compensated_temp as f64);
534  
535        let sealevel_press = self.get_sealevel_airpressure(compensated_press, compensated_temp, self.altitude_m);
536
537        Ok(Measurements { temperature_c: compensated_temp, air_pressure_pa: compensated_press , 
538                air_pressure_sealevel_pa: sealevel_press })
539
540     
541
542    }
543
544    /// get the power cotrol mode register value
545    pub async fn get_power_mode(&mut self) -> Result<PowerMode, Error<E>> {
546        debug!("in get_power_control_mode");
547        let mut result_buf: [u8; 1] = [ 0; 1];
548        self.read_register(BMP3_REG_PWR_CTRL, &mut result_buf).await?;
549        debug!(" get_power_control_mode = {:#b}", result_buf[0] & 0b110000 >> 4);
550        Ok(PowerMode::from(result_buf[0] & 0b110000 >> 4))
551    }
552
553    /// set power control mode
554    pub async fn set_power_control_mode(&mut self, pwr_mode: PowerMode) -> Result<(), Error<E>> {
555        debug!("in set_power_control_mode");
556        let mut result_buf: [u8; 1] = [0; 1];
557        let mut command_buf: [u8; 1] = [0; 1];
558        // read the power control mode register first, it clears a flag there
559        self.read_register(BMP3_REG_PWR_CTRL, &mut result_buf).await?;
560        command_buf[0] = ((pwr_mode as u8) << 4) | (result_buf[0] & 0x03);  // preserve temp and press enable bits
561        self.write_command( [BMP3_REG_PWR_CTRL, command_buf[0]] ).await?;
562        self.delayer.delay_ms(10).await;
563        debug!(" set_power_control_mode(), writing  PWR_CTRL reg = {:?} ({:#b})", pwr_mode, command_buf[0]);
564        Ok(())
565
566
567    }
568
569    /// set FIFO configuration
570    pub async fn set_fifo_config(&mut self, fifo_config: Fifo_Config) -> Result<(), Error<E>> {
571        debug!("in set_fifo_config");
572        self.write_command([BMP3_REG_FIFO_CONFIG_1, fifo_config.fifo_config_1.0] ).await?;
573        self.delayer.delay_ms(5);
574        self.write_command([BMP3_REG_FIFO_CONFIG_2, fifo_config.fifo_config_2.0] ).await?;
575        self.fifo_config = fifo_config;
576
577        Ok(())
578    }
579
580    /// get FIFO configuration
581    pub async fn get_fifo_config(&mut self) -> Result<Fifo_Config, Error<E>> {
582        debug!("in get_fifo_config");
583        let mut result_buf: [u8; 2] = [0; 2];
584        self.read_register(BMP3_REG_FIFO_CONFIG_1, &mut result_buf).await?;
585        debug!("  result_buf[0] = {:#b}", result_buf[0]);
586        debug!("  result_buf[1] = {:#b}", result_buf[1]);
587
588        let config_1s: FifoConfig1 = FifoConfig1(result_buf[0]);  // FifoConfig1 does not impl Copy trait
589        self.fifo_config.fifo_config_1 = config_1s;  // save in BMP38x properties
590        let config_1: FifoConfig1 = FifoConfig1(result_buf[0]); 
591        debug!("  config_1 = {:?}", config_1);
592
593        self.delayer.delay_ms(5);
594        let config_2s: FifoConfig2 = FifoConfig2(result_buf[1]);   // FifoConfi21 does not impl Copy trait
595        self.fifo_config.fifo_config_2 = config_2s;  // save in BMP38x properties
596        let config_2: FifoConfig2 = FifoConfig2(result_buf[1]);
597        
598        debug!("  config_2 = {:?}", config_2);
599        let fifo_config: Fifo_Config = Fifo_Config { fifo_config_1: config_1, fifo_config_2: config_2 };
600        
601        Ok(fifo_config)
602        
603    }
604
605    /// fifo set watermark
606    pub async fn fifo_set_watermark_frames(&mut self, frames: u16) -> Result<(), Error<E>> {
607        let length_bytes = self.get_fifo_frames_to_bytes(frames);
608        if (length_bytes > 0) {
609            let length: [u8; 2] = length_bytes.to_le_bytes();
610            self.write_command([BMP3_REG_FIFO_WM, length[0], length[1]]).await?;
611
612        } else {
613            return Err(Error::CommandError);
614        }
615        Ok(())
616    }
617
618    fn get_fifo_frames_to_bytes(&self, num_frames: u16) -> u16 {
619        let mut wm_length: u16 = 0;
620        if ((num_frames == 0) || (num_frames > 73))  {
621            wm_length = 0;
622
623        } else {
624            if (self.fifo_config.fifo_config_1.get_fifo_temp_enable() && (self.fifo_config.fifo_config_1.get_fifo_press_enable())) {
625                wm_length = num_frames * 7 ;  // 7 bytes per frame
626            } else if ( (self.fifo_config.fifo_config_1.get_fifo_temp_enable()) || 
627                            (self.fifo_config.fifo_config_1.get_fifo_press_enable()) ) {
628                wm_length = num_frames * 4;  // 4 bytes per frame
629            }
630            return wm_length;
631        }
632
633        return wm_length;
634    }
635
636    pub fn get_fifo_watermark_in_frames(&mut self) -> Result<u16, Error<E>> {
637        let mut result_buf: [u8; 2] = [0; 2];
638        self.read_register(BMP3_REG_FIFO_WM, &mut result_buf).await?;
639        let length:u16 = u16::from_le_bytes(result_buf);
640        let mut wm_frames : u16 = 0;
641        if length < 4 {
642            return Ok(0);
643        } else {
644            if (self.fifo_config.fifo_config_1.get_fifo_temp_enable() && (self.fifo_config.fifo_config_1.get_fifo_press_enable())) {
645                wm_frames = length / 7 ;  // 7 bytes per frame
646            } else if ( (self.fifo_config.fifo_config_1.get_fifo_temp_enable()) || 
647                            (self.fifo_config.fifo_config_1.get_fifo_press_enable()) ) {
648                wm_frames = length / 4;  // 4 bytes per frame
649            }
650        }
651
652        return (Ok(wm_frames));
653    }
654
655    /// flush fifo buffer
656    pub async fn fifo_flush(&mut self) -> Result<(), Error<E>> {
657        debug!("in fifo_flush");
658        // check for (new) command ready
659        let mut result_buf: [u8; 1] = [0; 1];
660        let status = self.get_status().await?;
661        if (status.get_cmd_ready()) {
662            //let mut write_buf: [u8; 2] = [BMP3_REG_CMD, BMP3_FIFO_FLUSH];
663            self.write_command([BMP3_REG_CMD, BMP3_FIFO_FLUSH]).await?;
664
665            // self.i2c.write(self.address, &write_buf).await
666            //         .map_err(Error::I2c);
667
668            //self.write_command([BMP3_REG_CMD, write_buf]).await? ; 
669            self.delayer.delay_ms(5).await;
670            self.read_register(BMP3_REG_ERR, &mut result_buf).await?;
671            let error_value = ErrorReg(result_buf[0]);
672            debug!("  write CMD returned {:x}", result_buf[0]);
673            if ( error_value.get_cfg_error() || error_value.get_cmd_error() || error_value.get_fatal_error() ) {
674                return Err(Error::CommandError);
675            } 
676            return Ok(());
677        }
678        Err(Error::NotReadyForCommand)   
679
680    }
681
682    /// get FIFO number of frames
683    pub async fn get_fifo_number_frames(&mut self) -> Result<u16, Error<E>> {
684        debug!("in get_fifo_number_frames");
685        let mut result_buf: [u8; 2] = [ 0; 2];
686        self.read_register(BMP3_REG_FIFO_LENGTH, &mut result_buf).await?;  // in bytes
687        let fifo_length_bytes: u16 = u16::from_le_bytes(result_buf);
688        debug!("  fifo_length_bytes = {}", fifo_length_bytes);
689        // Determine the number of bytes per data frame.
690        // 1 byte for header, 3 bytes for each sensor data if enabled
691    
692        let bytes_per_frame: u16 = 1 + 3 * (self.fifo_config.fifo_config_1.get_fifo_press_enable() as u16 + 
693                                        self.fifo_config.fifo_config_1.get_fifo_temp_enable() as u16);
694
695        // Set number of data frames
696        Ok(fifo_length_bytes / bytes_per_frame)
697    }
698    
699    /// get FIFO frame:  could be a control frame, sensor data frame or empty frame
700    pub async fn get_fifo_frame(&mut self) -> Result<FifoFrame, Error<E>> {
701        debug!("in get_fifo_frame");
702        let mut result_buf: [u8; 1] = [0; 1];
703        self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;  // read Fifo header
704        //  MSB 7,6 = 0b10 sensor frame, check bits s,t and p (5,4 and 2)
705        //          = 0b01 Control frame
706        //              then if bits 5,4,3,2 = 0b0001 = Control frame config error
707        //              or if bits 5,4,3,2 = 0b0010 = Control frame config changed
708        //      1,0 = 0b00 always
709        let fh = result_buf[0];
710        debug!("  header = {:b}", fh);
711        if (fh & 0b1000_0000 != 0x00)  {
712            // sensor data frame:  could be data or time frame
713            // was if (fh & 0b10100000 != 0x00)  {  // a time frame
714            if (fh & 0x20 == 0x20)  {  // a time frame
715                debug!("  a time frame");
716                let mut result_buf: [u8; 4] = [0; 4];
717                self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;
718                let time_stamp: u32 = u32::from_le_bytes([result_buf[1], result_buf[2], result_buf[3], 0]);
719                return Ok( FifoFrame::SensorDataFrame(SensorFrameEnum::Time(time_stamp)) )  
720
721            } else if (fh & 0x14 == 0x14) {  // a temperature and pressure frame, check for this first otherwise result is just 
722                                             // temp or press
723                debug!("  a temperature and pressure frame");
724                let mut result_buf: [u8; 7] = [0; 7];
725                self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;
726                let raw_temperature = result_buf[1] as u32 | ((result_buf[2] as u32) << 8) | (result_buf[3] as u32) << 16;
727                let compensated_temp = self.compensate_temperature(raw_temperature);
728                let raw_pressure: u32 = result_buf[4] as u32 | ((result_buf[5] as u32) << 8) | (result_buf[6] as u32) << 16;
729                let compensated_press = self.compensate_pressure(raw_pressure as f64, compensated_temp);
730                let tandP: TandPtype = TandPtype{temperature: compensated_temp, pressure: compensated_press };
731                return Ok( FifoFrame::SensorDataFrame(SensorFrameEnum::TemperatureAndPressureData(tandP)) )    
732
733            } else if (fh & 0x10 == 0x10)  {  // a temperature frame
734                debug!("  a temperature frame");
735                let mut result_buf: [u8; 4] = [0; 4];
736                self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;
737                let raw_temperature = result_buf[1] as u32 | ((result_buf[2] as u32) << 8) | (result_buf[3] as u32) << 16;
738                let compensated_temp = self.compensate_temperature(raw_temperature);
739                return Ok( FifoFrame::SensorDataFrame(SensorFrameEnum::TemperatureData(compensated_temp)) )
740
741            } else if (fh & 0x04 == 0x04) { // a pressure frame
742                debug!("  a pressure frame");
743                let mut result_buf: [u8; 4] = [0; 4];
744                self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;
745                let raw_pressure: u32 = result_buf[1] as u32 | ((result_buf[2] as u32) << 8) | (result_buf[3] as u32) << 16;
746
747                let compensated_press = self.compensate_pressure(raw_pressure as f64, 0.0);  // set unknown temp to 0 for compensation
748                return Ok( FifoFrame::SensorDataFrame(SensorFrameEnum::PressureData(compensated_press)) )
749
750  
751            } else {
752                debug!("  an empty frame");
753                return Ok(FifoFrame::SensorDataFrame(SensorFrameEnum::Empty))
754            }
755
756
757        }
758        else if (fh & 0b01000000 != 0x00) {
759            // control frame
760            debug!("  a control frame");
761            let mut result_buf: [u8; 2] = [ 0; 2];
762            self.read_register(BMP3_REG_FIFO_DATA, &mut result_buf).await?;  // read but ignore result_buf
763            if (fh & 0b01000100 == 0x44) { 
764                // control frame fifo config error
765                debug!("   a configuration error");
766                return Ok(FifoFrame::ControlFrame(ControlFrameEnum::ConfigurationError))
767                
768            } else if (fh & 0b01001000 == 0x48) {
769                debug!("   a configuration change");
770                return Ok(FifoFrame::ControlFrame(ControlFrameEnum::ConfigurationChange))
771            } else {
772                debug!("   an unknown control frame, header =  {:x}", fh);
773                return Err(Error::FifoUnknownContent)
774            }
775        } else {
776                return Err(Error::FifoUnknownContent)
777        }
778        
779
780        // 
781
782    }
783
784
785
786}