use core::mem;
use hal::blocking::i2c;
use hal::blocking::spi;
use hal::digital::OutputPin;
use generic_array::typenum::consts::*;
use generic_array::{ArrayLength, GenericArray};
use Register;
pub trait Releasable {
type Released;
fn release(self) -> Self::Released;
}
pub trait Device: Releasable {
type Error;
fn read_many<N: ArrayLength<u8>>(
&mut self,
reg: Register)
-> Result<GenericArray<u8, N>, Self::Error>;
fn write(&mut self, reg: Register, val: u8) -> Result<(), Self::Error>;
fn read(&mut self, reg: Register) -> Result<u8, Self::Error> {
let buffer = self.read_many::<U2>(reg)?;
Ok(buffer[1])
}
fn modify<F>(&mut self, reg: Register, f: F) -> Result<(), Self::Error>
where F: FnOnce(u8) -> u8
{
let r = self.read(reg)?;
self.write(reg, f(r))?;
Ok(())
}
}
pub struct SpiDevice<SPI, GPIO> {
spi: SPI,
ncs: GPIO,
}
impl<SPI, NCS, E> SpiDevice<SPI, NCS>
where SPI: spi::Write<u8, Error = E> + spi::Transfer<u8, Error = E>,
NCS: OutputPin
{
pub fn new(spi: SPI, ncs: NCS) -> Self {
SpiDevice { spi,
ncs }
}
}
impl<SPI, NCS, E> Releasable for SpiDevice<SPI, NCS>
where SPI: spi::Write<u8, Error = E> + spi::Transfer<u8, Error = E>,
NCS: OutputPin
{
type Released = (SPI, NCS);
fn release(self) -> (SPI, NCS) {
(self.spi, self.ncs)
}
}
impl<SPI, NCS, E> Device for SpiDevice<SPI, NCS>
where SPI: spi::Write<u8, Error = E> + spi::Transfer<u8, Error = E>,
NCS: OutputPin
{
type Error = E;
fn read_many<N>(&mut self, reg: Register) -> Result<GenericArray<u8, N>, E>
where N: ArrayLength<u8>
{
let mut buffer: GenericArray<u8, N> = unsafe { mem::zeroed() };
{
let slice: &mut [u8] = &mut buffer;
slice[0] = reg.read_address();
self.ncs.set_low();
self.spi.transfer(slice)?;
self.ncs.set_high();
}
Ok(buffer)
}
#[inline(never)]
fn write(&mut self, reg: Register, val: u8) -> Result<(), E> {
self.ncs.set_low();
self.spi.write(&[reg.write_address(), val])?;
self.ncs.set_high();
Ok(())
}
}
pub struct I2cDevice<I2C> {
i2c: I2C,
}
impl<E, I2C> I2cDevice<I2C>
where I2C: i2c::Read<Error = E>
+ i2c::Write<Error = E>
+ i2c::WriteRead<Error = E>
{
pub fn new(i2c: I2C) -> Self {
I2cDevice { i2c }
}
}
impl<E, I2C> Releasable for I2cDevice<I2C>
where I2C: i2c::Read<Error = E>
+ i2c::Write<Error = E>
+ i2c::WriteRead<Error = E>
{
type Released = I2C;
fn release(self) -> I2C {
self.i2c
}
}
impl<E, I2C> Device for I2cDevice<I2C>
where I2C: i2c::Read<Error = E>
+ i2c::Write<Error = E>
+ i2c::WriteRead<Error = E>
{
type Error = E;
fn read_many<N: ArrayLength<u8>>(
&mut self,
reg: Register)
-> Result<GenericArray<u8, N>, Self::Error> {
let mut buffer: GenericArray<u8, N> = unsafe { mem::zeroed() };
{
let slice: &mut [u8] = &mut buffer;
self.i2c
.write_read(0x68, &[reg.read_address()], &mut slice[1..])?;
}
Ok(buffer)
}
fn write(&mut self, reg: Register, val: u8) -> Result<(), Self::Error> {
let buff: [u8; 2] = [reg.write_address(), val];
self.i2c.write(0x68, &buff)
}
}