forked from M-Labs/humpback-dds
spi mux: remove traits
This commit is contained in:
parent
f77013c290
commit
e834e6fcea
71
src/cpld.rs
71
src/cpld.rs
|
@ -23,12 +23,7 @@ pub struct CPLD<SPI, CS0, CS1, CS2, GPIO> {
|
||||||
pub(crate) data: cell::RefCell<CPLDData<SPI, CS0, CS1, CS2, GPIO>>,
|
pub(crate) data: cell::RefCell<CPLDData<SPI, CS0, CS1, CS2, GPIO>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SelectChip {
|
impl<SPI, CS0, CS1, CS2, GPIO, E> CPLDData<SPI, CS0, CS1, CS2, GPIO>
|
||||||
type Error;
|
|
||||||
fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO, E> SelectChip for CPLDData<SPI, CS0, CS1, CS2, GPIO>
|
|
||||||
where
|
where
|
||||||
SPI: Transfer<u8, Error = E>,
|
SPI: Transfer<u8, Error = E>,
|
||||||
CS0: OutputPin,
|
CS0: OutputPin,
|
||||||
|
@ -36,8 +31,7 @@ where
|
||||||
CS2: OutputPin,
|
CS2: OutputPin,
|
||||||
GPIO: OutputPin,
|
GPIO: OutputPin,
|
||||||
{
|
{
|
||||||
type Error = Error<E>;
|
pub(crate) fn select_chip(&mut self, chip: u8) -> Result<(), Error<E>> {
|
||||||
fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error> {
|
|
||||||
match chip & (1 << 0) {
|
match chip & (1 << 0) {
|
||||||
0 => self.chip_select.0.set_low(),
|
0 => self.chip_select.0.set_low(),
|
||||||
_ => self.chip_select.0.set_high(),
|
_ => self.chip_select.0.set_high(),
|
||||||
|
@ -52,49 +46,13 @@ where
|
||||||
}.map_err(|_| Error::CSError)?;
|
}.map_err(|_| Error::CSError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IssueIOUpdate {
|
pub(crate) fn issue_io_update(&mut self) -> Result<(), Error<E>> {
|
||||||
type Error;
|
|
||||||
fn issue_io_update(&mut self) -> Result<(), Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO, E> IssueIOUpdate for CPLDData<SPI, CS0, CS1, CS2, GPIO>
|
|
||||||
where
|
|
||||||
SPI: Transfer<u8>,
|
|
||||||
CS0: OutputPin,
|
|
||||||
CS1: OutputPin,
|
|
||||||
CS2: OutputPin,
|
|
||||||
GPIO: OutputPin<Error = E>,
|
|
||||||
{
|
|
||||||
type Error = Error<E>;
|
|
||||||
|
|
||||||
fn issue_io_update(&mut self) -> Result<(), Self::Error> {
|
|
||||||
self.io_update.set_high().map_err(|_| Error::IOUpdateError)?;
|
self.io_update.set_high().map_err(|_| Error::IOUpdateError)?;
|
||||||
self.io_update.set_low().map_err(|_| Error::IOUpdateError)
|
self.io_update.set_low().map_err(|_| Error::IOUpdateError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DoOnGetRefMutData<SPI, CS0, CS1, CS2, GPIO> {
|
|
||||||
fn do_on_get_ref_mut_data<R, E>(
|
|
||||||
&self,
|
|
||||||
f: impl FnOnce(cell::RefMut<CPLDData<SPI, CS0, CS1, CS2, GPIO>>) -> Result<R, Error<E>>,
|
|
||||||
) -> Result<R, Error<E>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO> DoOnGetRefMutData<SPI, CS0, CS1, CS2, GPIO> for CPLD<SPI, CS0, CS1, CS2, GPIO> {
|
|
||||||
fn do_on_get_ref_mut_data<R, E>(
|
|
||||||
&self,
|
|
||||||
f: impl FnOnce(cell::RefMut<CPLDData<SPI, CS0, CS1, CS2, GPIO>>) -> Result<R, Error<E>>,
|
|
||||||
) -> Result<R, Error<E>> {
|
|
||||||
let dev = self
|
|
||||||
.data
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| Error::GetRefMutDataError)?;
|
|
||||||
f(dev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO, E> Transfer<u8> for CPLD<SPI, CS0, CS1, CS2, GPIO>
|
impl<SPI, CS0, CS1, CS2, GPIO, E> Transfer<u8> for CPLD<SPI, CS0, CS1, CS2, GPIO>
|
||||||
where
|
where
|
||||||
SPI: Transfer<u8, Error = E>,
|
SPI: Transfer<u8, Error = E>,
|
||||||
|
@ -106,7 +64,7 @@ where
|
||||||
type Error = Error<E>;
|
type Error = Error<E>;
|
||||||
|
|
||||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||||
self.do_on_get_ref_mut_data(move |mut dev| dev.spi.transfer(words).map_err(Error::SPI))
|
self.data.try_borrow_mut().map_err(|_| Error::GetRefMutDataError)?.spi.transfer(words).map_err(Error::SPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,26 +98,7 @@ impl<SPI, CS0, CS1, CS2, GPIO, E> CPLD<SPI, CS0, CS1, CS2, GPIO> where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split SPI into chips, wrapped by Parts struct
|
// Split SPI into chips, wrapped by Parts struct
|
||||||
pub fn split<'a>(&'a self) -> Parts<'a, CPLD<SPI, CS0, CS1, CS2, GPIO>, SPI, CS0, CS1, CS2, GPIO> {
|
pub fn split<'a>(&'a self) -> Parts<'a, SPI, CS0, CS1, CS2, GPIO> {
|
||||||
Parts::new(&self)
|
Parts::new(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select Chip
|
|
||||||
pub fn select_chip(&mut self, channel: u8) -> Result<(), Error<E>> {
|
|
||||||
self.do_on_get_ref_mut_data(|mut dev| dev.select_chip(channel))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO, E> CPLD<SPI, CS0, CS1, CS2, GPIO>
|
|
||||||
where
|
|
||||||
SPI: Transfer<u8>,
|
|
||||||
CS0: OutputPin,
|
|
||||||
CS1: OutputPin,
|
|
||||||
CS2: OutputPin,
|
|
||||||
GPIO: OutputPin<Error = E>
|
|
||||||
{
|
|
||||||
// Issue I/O Update
|
|
||||||
pub fn issue_io_update(&mut self) -> Result<(), Error<E>> {
|
|
||||||
self.do_on_get_ref_mut_data(|mut dev| dev.issue_io_update())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,60 +4,60 @@ use embedded_hal::{
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::cpld::{DoOnGetRefMutData, SelectChip, IssueIOUpdate};
|
use crate::cpld::CPLD;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
pub struct SPISlave<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> (
|
pub struct SPISlave<'a, SPI, CS0, CS1, CS2, GPIO> (
|
||||||
&'a DEV,
|
// SPI device to be multiplexed
|
||||||
u8, // Channel of SPI slave
|
&'a CPLD<SPI, CS0, CS1, CS2, GPIO>,
|
||||||
bool, // Need I/O Update
|
// Channel of SPI slave
|
||||||
PhantomData<(SPI, CS0, CS1, CS2, GPIO)>,
|
u8,
|
||||||
|
// Need I/O Update
|
||||||
|
bool,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub struct Parts<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> {
|
pub struct Parts<'a, SPI, CS0, CS1, CS2, GPIO> {
|
||||||
pub spi1: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi1: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi2: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi2: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi3: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi3: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi4: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi4: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi5: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi5: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi6: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi6: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
pub spi7: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>,
|
pub spi7: SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DEV, SPI, CS0, CS1, CS2, GPIO> Parts<'a, DEV, SPI, CS0, CS1, CS2, GPIO> {
|
impl<'a, SPI, CS0, CS1, CS2, GPIO> Parts<'a, SPI, CS0, CS1, CS2, GPIO> {
|
||||||
pub(crate) fn new(cpld: &'a DEV) -> Self {
|
pub(crate) fn new(cpld: &'a CPLD<SPI, CS0, CS1, CS2, GPIO>) -> Self {
|
||||||
Parts {
|
Parts {
|
||||||
spi1: SPISlave(&cpld, 1, false, PhantomData),
|
spi1: SPISlave(&cpld, 1, false),
|
||||||
spi2: SPISlave(&cpld, 2, false, PhantomData),
|
spi2: SPISlave(&cpld, 2, false),
|
||||||
spi3: SPISlave(&cpld, 3, true, PhantomData),
|
spi3: SPISlave(&cpld, 3, true),
|
||||||
spi4: SPISlave(&cpld, 4, true, PhantomData),
|
spi4: SPISlave(&cpld, 4, true),
|
||||||
spi5: SPISlave(&cpld, 5, true, PhantomData),
|
spi5: SPISlave(&cpld, 5, true),
|
||||||
spi6: SPISlave(&cpld, 6, true, PhantomData),
|
spi6: SPISlave(&cpld, 6, true),
|
||||||
spi7: SPISlave(&cpld, 7, true, PhantomData),
|
spi7: SPISlave(&cpld, 7, true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DEV, SPI, CS0, CS1, CS2, GPIO, E> Transfer<u8> for SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>
|
impl<'a, SPI, CS0, CS1, CS2, GPIO, E> Transfer<u8> for SPISlave<'a, SPI, CS0, CS1, CS2, GPIO>
|
||||||
where
|
where
|
||||||
CS2: OutputPin,
|
CS2: OutputPin,
|
||||||
CS1: OutputPin,
|
CS1: OutputPin,
|
||||||
CS0: OutputPin,
|
CS0: OutputPin,
|
||||||
DEV: DoOnGetRefMutData<SPI, CS0, CS1, CS2, GPIO>,
|
|
||||||
SPI: Transfer<u8, Error = E>,
|
SPI: Transfer<u8, Error = E>,
|
||||||
GPIO: OutputPin,
|
GPIO: OutputPin,
|
||||||
{
|
{
|
||||||
type Error = Error<E>;
|
type Error = Error<E>;
|
||||||
|
|
||||||
fn transfer<'w>(&mut self, words: &'w mut[u8]) -> Result<&'w [u8], Self::Error> {
|
fn transfer<'w>(&mut self, words: &'w mut[u8]) -> Result<&'w [u8], Self::Error> {
|
||||||
self.0.do_on_get_ref_mut_data(move |mut dev| {
|
let mut dev = self.0.data.try_borrow_mut().map_err(|_| Error::GetRefMutDataError)?;
|
||||||
dev.select_chip(self.1).map_err(|_| Error::CSError)?;
|
dev.select_chip(self.1).map_err(|_| Error::CSError)?;
|
||||||
let result = dev.spi.transfer(words).map_err(Error::SPI)?;
|
let result = dev.spi.transfer(words).map_err(Error::SPI)?;
|
||||||
dev.select_chip(0).map_err(|_| Error::CSError)?;
|
dev.select_chip(0).map_err(|_| Error::CSError)?;
|
||||||
if self.2 {
|
if self.2 {
|
||||||
dev.issue_io_update().map_err(|_| Error::IOUpdateError)?;
|
dev.issue_io_update().map_err(|_| Error::IOUpdateError)?;
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue