bmp581 0.1.0

Platform-agnostic Rust driver for the Bosch BMP581 pressure sensor.
Documentation
use crate::types::Error;
use embedded_hal::i2c::{I2c, SevenBitAddress};
use embedded_hal::spi::SpiDevice;

/// Default I2C address of BMP581
pub const I2C_ADDRESS: u8 = 0x46;
/// Alternative I2C address when SDO is pulled high
pub const I2C_ADDRESS_ALT: u8 = 0x47;

pub struct I2cInterface<I2C> {
    pub i2c: I2C,
    pub address: u8,
}

pub struct SpiInterface<SPI> {
    pub spi: SPI,
}

#[derive(Debug, Default, Clone, Copy)]
pub enum I2cAddr {
    #[default]
    Default,
    Alternative,
}

impl I2cAddr {
    pub fn addr(self) -> SevenBitAddress {
        match self {
            I2cAddr::Default => I2C_ADDRESS,
            I2cAddr::Alternative => I2C_ADDRESS_ALT,
        }
    }
}

pub trait WriteData {
    type Error;
    fn write(&mut self, payload: &mut [u8]) -> Result<(), Self::Error>;
    fn write_reg(&mut self, register: u8, data: u8) -> Result<(), Self::Error>;
}

pub trait ReadData {
    type Error;
    fn read(&mut self, payload: &mut [u8]) -> Result<(), Self::Error>;
    fn read_reg(&mut self, register: u8) -> Result<u8, Self::Error>;
}

impl<I2C> WriteData for I2cInterface<I2C>
where
    I2C: I2c,
{
    type Error = Error<I2C::Error>;
    fn write(&mut self, payload: &mut [u8]) -> Result<(), Self::Error> {
        self.i2c
            .write(self.address as SevenBitAddress, payload)
            .map_err(Error::Comm)
    }

    fn write_reg(&mut self, register: u8, data: u8) -> Result<(), Self::Error> {
        let payload: [u8; 2] = [register, data];
        self.i2c
            .write(self.address as SevenBitAddress, &payload)
            .map_err(Error::Comm)
    }
}

impl<I2C> ReadData for I2cInterface<I2C>
where
    I2C: I2c,
{
    type Error = Error<I2C::Error>;
    fn read(&mut self, payload: &mut [u8]) -> Result<(), Self::Error> {
        self.i2c
            .write_read(
                self.address as SevenBitAddress,
                &[payload[0]],
                &mut payload[1..],
            )
            .map_err(Error::Comm)
    }

    fn read_reg(&mut self, register: u8) -> Result<u8, Self::Error> {
        let mut data = [0];
        self.i2c
            .write_read(self.address as SevenBitAddress, &[register], &mut data)
            .map_err(Error::Comm)
            .and(Ok(data[0]))
    }
}

impl<SPI, CommE> WriteData for SpiInterface<SPI>
where
    SPI: SpiDevice<Error = CommE>,
{
    type Error = Error<CommE>;
    fn write(&mut self, payload: &mut [u8]) -> Result<(), Self::Error> {
        payload[0] += 0x80;

        // `write` asserts and deasserts CS for us. No need to do it manually!
        let res = self.spi.write(&payload).map_err(Error::Comm);

        res
    }

    fn write_reg(&mut self, register: u8, data: u8) -> Result<(), Self::Error> {
        let payload: [u8; 2] = [register + 0x80, data];

        // `write` asserts and deasserts CS for us. No need to do it manually!
        let res = self.spi.write(&payload).map_err(Error::Comm);

        res
    }
}

impl<SPI, CommE> ReadData for SpiInterface<SPI>
where
    SPI: SpiDevice<Error = CommE>,
{
    type Error = Error<CommE>;
    fn read(&mut self, payload: &mut [u8]) -> Result<(), Self::Error> {
        // `read` asserts and deasserts CS for us. No need to do it manually!
        let res = self.spi.read(payload).map_err(Error::Comm);

        res?;
        Ok(())
    }

    fn read_reg(&mut self, register: u8) -> Result<u8, Self::Error> {
        let mut payload = [register, 0];

        // `read` asserts and deasserts CS for us. No need to do it manually!
        let res = self.spi.read(&mut payload).map_err(Error::Comm);

        match res {
                Ok(_) => Ok(payload[1]),
                Err(e) => Err(e)
        }   
    }
}