Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SPI. #6

Merged
merged 3 commits into from Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions example/src/main.rs
@@ -1,8 +1,8 @@
extern crate linux_embedded_hal as hal;
extern crate bme280;
extern crate linux_embedded_hal as hal;

use bme280::i2c::BME280;
use hal::{Delay, I2cdev};
use bme280::BME280;
use std::thread;
use std::time::Duration;

Expand Down
115 changes: 115 additions & 0 deletions src/i2c.rs
@@ -0,0 +1,115 @@
//! BME280 driver for sensors attached via I2C.

use embedded_hal::blocking::delay::DelayMs;
use embedded_hal::blocking::i2c::{Read, Write, WriteRead};

use super::{
BME280Common, Error, Interface, Measurements, BME280_H_CALIB_DATA_LEN,
BME280_P_T_CALIB_DATA_LEN, BME280_P_T_H_DATA_LEN,
};

const BME280_I2C_ADDR_PRIMARY: u8 = 0x76;
const BME280_I2C_ADDR_SECONDARY: u8 = 0x77;

/// Representation of a BME280
#[derive(Debug, Default)]
pub struct BME280<I2C, D> {
common: BME280Common<I2CInterface<I2C>, D>,
}

impl<I2C, D, E> BME280<I2C, D>
where
I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
D: DelayMs<u8>,
{
/// Create a new BME280 struct using the primary I²C address `0x76`
pub fn new_primary(i2c: I2C, delay: D) -> Self {
Self::new(i2c, BME280_I2C_ADDR_PRIMARY, delay)
}

/// Create a new BME280 struct using the secondary I²C address `0x77`
pub fn new_secondary(i2c: I2C, delay: D) -> Self {
Self::new(i2c, BME280_I2C_ADDR_SECONDARY, delay)
}

/// Create a new BME280 struct using a custom I²C address
pub fn new(i2c: I2C, address: u8, delay: D) -> Self {
BME280 {
common: BME280Common {
interface: I2CInterface { i2c, address },
delay,
calibration: None,
},
}
}

/// Initializes the BME280
pub fn init(&mut self) -> Result<(), Error<E>> {
self.common.init()
}

/// Captures and processes sensor data for temperature, pressure, and humidity
pub fn measure(&mut self) -> Result<Measurements<E>, Error<E>> {
self.common.measure()
}
}

/// Register access functions for I2C
#[derive(Debug, Default)]
struct I2CInterface<I2C> {
/// concrete I²C device implementation
i2c: I2C,
/// I²C device address
address: u8,
}

impl<I2C, E> Interface for I2CInterface<I2C>
where
I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
{
type Error = E;

fn read_register(&mut self, register: u8) -> Result<u8, Error<E>> {
let mut data: [u8; 1] = [0];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::Bus)?;
Ok(data[0])
}

fn read_data(&mut self, register: u8) -> Result<[u8; BME280_P_T_H_DATA_LEN], Error<E>> {
let mut data: [u8; BME280_P_T_H_DATA_LEN] = [0; BME280_P_T_H_DATA_LEN];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::Bus)?;
Ok(data)
}

fn read_pt_calib_data(
&mut self,
register: u8,
) -> Result<[u8; BME280_P_T_CALIB_DATA_LEN], Error<E>> {
let mut data: [u8; BME280_P_T_CALIB_DATA_LEN] = [0; BME280_P_T_CALIB_DATA_LEN];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::Bus)?;
Ok(data)
}

fn read_h_calib_data(
&mut self,
register: u8,
) -> Result<[u8; BME280_H_CALIB_DATA_LEN], Error<E>> {
let mut data: [u8; BME280_H_CALIB_DATA_LEN] = [0; BME280_H_CALIB_DATA_LEN];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::Bus)?;
Ok(data)
}

fn write_register(&mut self, register: u8, payload: u8) -> Result<(), Error<E>> {
self.i2c
.write(self.address, &[register, payload])
.map_err(Error::Bus)
}
}