use nrf51::TWI1;
use gpio::gpio::PIN;
use gpio::{Input, OpenDrain};
use hal::blocking::i2c::{Write, WriteRead};
pub struct I2c<I2C> {
i2c: I2C,
sdapin: PIN<Input<OpenDrain>>,
sclpin: PIN<Input<OpenDrain>>,
}
#[derive(Debug)]
pub enum Error {
OVERRUN,
NACK,
}
impl I2c<TWI1> {
pub fn i2c1(i2c: TWI1, sdapin: PIN<Input<OpenDrain>>, sclpin: PIN<Input<OpenDrain>>) -> Self {
i2c.pselscl
.write(|w| unsafe { w.bits(sclpin.get_id().into()) });
i2c.pselsda
.write(|w| unsafe { w.bits(sdapin.get_id().into()) });
i2c.enable.write(|w| w.enable().enabled());
I2c {
i2c,
sdapin,
sclpin,
}
}
pub fn release(self) -> (TWI1, PIN<Input<OpenDrain>>, PIN<Input<OpenDrain>>) {
(self.i2c, self.sdapin, self.sclpin)
}
fn send_byte(&self, byte: &u8) -> Result<(), Error> {
let twi = &self.i2c;
twi.events_txdsent.write(|w| unsafe { w.bits(0) });
twi.txd.write(|w| unsafe { w.bits(u32::from(*byte)) });
twi.tasks_starttx.write(|w| unsafe { w.bits(1) });
while twi.events_txdsent.read().bits() == 0 {
if twi.events_error.read().bits() != 0 {
twi.events_error.write(|w| unsafe { w.bits(0) });
return Err(Error::NACK);
}
}
twi.events_txdsent.write(|w| unsafe { w.bits(0) });
Ok(())
}
fn recv_byte(&self) -> Result<u8, Error> {
let twi = &self.i2c;
twi.events_rxdready.write(|w| unsafe { w.bits(0) });
twi.tasks_startrx.write(|w| unsafe { w.bits(1) });
while twi.events_rxdready.read().bits() == 0 {
if twi.events_error.read().bits() != 0 {
twi.events_error.write(|w| unsafe { w.bits(0) });
return Err(Error::OVERRUN);
}
}
let out = twi.rxd.read().bits() as u8;
twi.events_rxdready.write(|w| unsafe { w.bits(0) });
Ok(out)
}
fn send_stop(&self) -> Result<(), Error> {
let twi = &self.i2c;
twi.events_stopped.write(|w| unsafe { w.bits(0) });
twi.tasks_stop.write(|w| unsafe { w.bits(1) });
while twi.events_stopped.read().bits() == 0 {
if twi.events_error.read().bits() != 0 {
twi.events_error.write(|w| unsafe { w.bits(0) });
return Err(Error::NACK);
}
}
Ok(())
}
}
impl WriteRead for I2c<TWI1> {
type Error = Error;
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
let twi = &self.i2c;
twi.shorts
.write(|w| w.bb_stop().disabled().bb_suspend().disabled());
twi.address.write(|w| unsafe { w.address().bits(addr) });
for out in bytes {
self.send_byte(out)?;
}
if let Some((last, before)) = buffer.split_last_mut() {
if !before.is_empty() {
twi.shorts.write(|w| w.bb_suspend().enabled());
}
for in_ in &mut before.into_iter() {
*in_ = self.recv_byte()?;
twi.tasks_resume.write(|w| unsafe { w.bits(1) });
}
twi.shorts
.write(|w| w.bb_suspend().disabled().bb_stop().enabled());
*last = self.recv_byte()?;
}
self.send_stop()?;
Ok(())
}
}
impl Write for I2c<TWI1> {
type Error = Error;
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
let twi = &self.i2c;
twi.shorts
.write(|w| w.bb_stop().disabled().bb_suspend().disabled());
twi.address.write(|w| unsafe { w.address().bits(addr) });
for in_ in bytes {
self.send_byte(in_)?;
}
self.send_stop()?;
Ok(())
}
}