#[cfg(feature = "embassy")]
use enumset::EnumSet;
#[cfg(feature = "embassy")]
use super::future::EventFuture;
use super::hal::sealed::WAIT_FLAG_TIMEOUT;
use super::{Error, Event, Instance};
use crate::delay::wait_for_true_timeout_block;
#[cfg(feature = "embassy")]
use crate::mode::Async;
use crate::{
clock::peripheral::PeripheralInterrupt,
mode::{Blocking, Mode},
};
use core::marker::PhantomData;
pub struct Master<'d, T: Instance, M: Mode> {
_t: PhantomData<(&'d T, M)>,
}
impl<'d, T: Instance, M: Mode> Master<'d, T, M> {
pub(super) fn new() -> Self {
if M::is_async() {
T::id().enable_interrupt();
}
Self { _t: PhantomData }
}
}
impl<'d, T: Instance, M: Mode> Drop for Master<'d, T, M> {
fn drop(&mut self) {
if M::is_async() {
T::id().disable_interrupt();
}
}
}
impl<'d, T: Instance> Master<'d, T, Blocking> {
pub fn write_block(&self, address: u8, buf: &[u8]) -> Result<usize, Error> {
T::clear_pos();
T::start();
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::SB)).map_err(
|_| {
T::event_clear(Event::ARLO);
Error::Start
},
)?;
T::transmit(address << 1);
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::ADD)).map_err(
|_| {
T::event_clear(Event::AF);
T::stop();
Error::Address
},
)?;
T::event_clear(Event::ADD);
let mut iter = buf.iter();
if let Some(d) = iter.next() {
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::TXE))
.map_err(|_| Error::Tx)?;
T::transmit(*d);
}
for t in iter {
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::TXE)).map_err(
|_| {
T::stop();
Error::Tx
},
)?;
T::transmit(*t);
}
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::TXE)).map_err(
|_| {
T::stop();
Error::Tx
},
)?;
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::TXE)).map_err(
|_| {
T::stop();
Error::Tx
},
)?;
wait_for_true_timeout_block(WAIT_FLAG_TIMEOUT, || T::event_flag(Event::BTF)).map_err(
|_| {
T::stop();
Error::Tx
},
)?;
T::stop();
Ok(buf.len())
}
pub fn read_block(&self, address: u8, buf: &mut [u8]) -> Result<usize, Error> {
T::master_receive_block(address, buf)
}
}
impl<'d, T: Instance> embedded_hal::blocking::i2c::Write for Master<'d, T, Blocking> {
type Error = Error;
fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.write_block(address, bytes)
.map_or_else(Err, |_| Ok(()))
}
}
impl<'d, T: Instance> embedded_hal::blocking::i2c::Read for Master<'d, T, Blocking> {
type Error = Error;
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.read_block(address, buffer)
.map_or_else(Err, |_| Ok(()))
}
}
impl<'d, T: Instance> embedded_hal::blocking::i2c::WriteRead for Master<'d, T, Blocking> {
type Error = Error;
fn write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
self.write_block(address, bytes)
.map_or_else(Err, |_| Ok(()))?;
self.read_block(address, buffer)
.map_or_else(Err, |_| Ok(()))
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> Master<'d, T, Async> {
pub async fn read(&self, address: u8, buf: &mut [u8]) -> Result<usize, Error> {
let block = T::block();
T::start();
EventFuture::<T>::new(EnumSet::empty() | Event::SB).await?;
T::transmit((address << 1) | 1);
EventFuture::<T>::new(EnumSet::empty() | Event::ADD).await?;
let len = buf.len();
let mut enumerate = buf.iter_mut().enumerate();
while let Some((idx, p)) = enumerate.next() {
let remain = len - idx;
if remain > 2 {
T::ack(true);
EventFuture::<T>::new(EnumSet::empty() | Event::RXNE).await?;
*p = block.dr.read().dr().bits();
if T::event_flag(Event::BTF) {
T::ack(true);
let (_, p) = enumerate.next().unwrap();
*p = block.dr.read().dr().bits();
}
} else if remain == 2 {
T::ack(false);
EventFuture::<T>::new(EnumSet::empty() | Event::RXNE).await?;
*p = block.dr.read().dr().bits();
if T::event_flag(Event::BTF) {
T::ack(false);
let (_, p) = enumerate.next().unwrap();
*p = block.dr.read().dr().bits();
}
} else if remain == 1 {
T::ack(false);
EventFuture::<T>::new(EnumSet::empty() | Event::RXNE).await?;
*p = block.dr.read().dr().bits();
}
}
T::stop();
Ok(buf.len())
}
pub async fn write(&mut self, address: u8, buf: &[u8]) -> Result<usize, Error> {
T::clear_pos();
T::start();
EventFuture::<T>::new(EnumSet::empty() | Event::SB).await?;
T::transmit(address << 1);
EventFuture::<T>::new(EnumSet::empty() | Event::ADD)
.await
.inspect_err(|_| {
T::event_clear(Event::AF);
T::stop();
})?;
T::event_clear(Event::ADD);
let mut iter = buf.iter();
if let Some(d) = iter.next() {
EventFuture::<T>::new(EnumSet::empty() | Event::TXE).await?;
T::transmit(*d);
}
for t in iter {
EventFuture::<T>::new(EnumSet::empty() | Event::TXE | Event::BTF)
.await
.inspect_err(|_| {
T::stop();
})?;
T::transmit(*t);
}
EventFuture::<T>::new(EnumSet::empty() | Event::TXE)
.await
.inspect_err(|_| {
T::stop();
})?;
EventFuture::<T>::new(EnumSet::empty() | Event::TXE)
.await
.inspect_err(|_| {
T::stop();
})?;
EventFuture::<T>::new(EnumSet::empty() | Event::BTF)
.await
.inspect_err(|_| {
T::stop();
})?;
T::stop();
Ok(buf.len())
}
}
impl embedded_hal_async::i2c::Error for Error {
fn kind(&self) -> embedded_hal_async::i2c::ErrorKind {
match *self {
Self::Address => embedded_hal_async::i2c::ErrorKind::NoAcknowledge(
embedded_hal_async::i2c::NoAcknowledgeSource::Address,
),
Self::Busy => embedded_hal_async::i2c::ErrorKind::Other,
Self::PClock => embedded_hal_async::i2c::ErrorKind::Other,
Self::RX => embedded_hal_async::i2c::ErrorKind::Other,
Self::SpeedMode => embedded_hal_async::i2c::ErrorKind::Other,
Self::Start => embedded_hal_async::i2c::ErrorKind::Other,
Self::Stop => embedded_hal_async::i2c::ErrorKind::Other,
Self::Tx => embedded_hal_async::i2c::ErrorKind::Other,
}
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_hal_async::i2c::ErrorType for Master<'d, T, Async> {
type Error = Error;
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Master<'d, T, Async> {
async fn read(&mut self, _address: u8, _read: &mut [u8]) -> Result<(), Self::Error> {
todo!()
}
async fn transaction(
&mut self,
_address: u8,
_operations: &mut [embedded_hal_async::i2c::Operation<'_>],
) -> Result<(), Self::Error> {
todo!()
}
async fn write(&mut self, _address: u8, _write: &[u8]) -> Result<(), Self::Error> {
todo!()
}
}