diff --git a/src/cpld.rs b/src/cpld.rs index 504bf04..9e705e4 100644 --- a/src/cpld.rs +++ b/src/cpld.rs @@ -11,155 +11,155 @@ use core::cell; /* * Basic structure for CPLD signal multiplexing */ - #[derive(Debug)] - pub struct CPLDData { - pub(crate) spi: SPI, - pub(crate) chip_select: (CS0, CS1, CS2), - pub(crate) io_update: GPIO, - } - - #[derive(Debug)] - pub struct CPLD { - pub(crate) data: cell::RefCell>, - } - - pub trait SelectChip { - type Error; - fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error>; - } - - impl SelectChip for CPLDData - where - SPI: Transfer, - CS0: OutputPin, - CS1: OutputPin, - CS2: OutputPin, - GPIO: OutputPin, - { - type Error = Error; - fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error> { - match chip & (1 << 0) { - 0 => self.chip_select.0.set_low(), - _ => self.chip_select.0.set_high(), - }.map_err(|_| Error::CSError)?; - match chip & (1 << 1) { - 0 => self.chip_select.1.set_low(), - _ => self.chip_select.1.set_high(), - }.map_err(|_| Error::CSError)?; - match chip & (1 << 2) { - 0 => self.chip_select.2.set_low(), - _ => self.chip_select.2.set_high(), - }.map_err(|_| Error::CSError)?; - Ok(()) - } - } - - pub trait IssueIOUpdate { - type Error; - fn issue_io_update(&mut self) -> Result<(), Self::Error>; - } - - impl IssueIOUpdate for CPLDData - where - SPI: Transfer, - CS0: OutputPin, - CS1: OutputPin, - CS2: OutputPin, - GPIO: OutputPin, - { - type Error = Error; - - fn issue_io_update(&mut self) -> Result<(), Self::Error> { - self.io_update.set_high().map_err(|_| Error::IOUpdateError)?; - self.io_update.set_low().map_err(|_| Error::IOUpdateError) - } - } - - pub trait DoOnGetRefMutData { - fn do_on_get_ref_mut_data( - &self, - f: impl FnOnce(cell::RefMut>) -> Result>, - ) -> Result>; - } - - impl DoOnGetRefMutData for CPLD { - fn do_on_get_ref_mut_data( - &self, - f: impl FnOnce(cell::RefMut>) -> Result>, - ) -> Result> { - let dev = self - .data - .try_borrow_mut() - .map_err(|_| Error::GetRefMutDataError)?; - f(dev) - } - } - - impl Transfer for CPLD - where - SPI: Transfer, - CS0: OutputPin, - CS1: OutputPin, - CS2: OutputPin, - GPIO: OutputPin, - { - type Error = 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)) - } - } - - impl CPLD where - SPI: Transfer, - CS0: OutputPin, - CS1: OutputPin, - CS2: OutputPin, - GPIO: OutputPin - { - // Constructor for CPLD - pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2), io_update: GPIO) -> Self { - - // Init data - let data = CPLDData { - spi, - chip_select, - io_update, - }; - - // Init CPLD - CPLD { - data: cell::RefCell::new(data), - } - } - - // Destroy the wrapper, return the CPLD data - pub fn destroy(self) -> (SPI, (CS0, CS1, CS2), GPIO) { - let cpld = self.data.into_inner(); - (cpld.spi, cpld.chip_select, cpld.io_update) - } - - // Split SPI into chips, wrapped by Parts struct - pub fn split<'a>(&'a self) -> Parts<'a, CPLD, SPI, CS0, CS1, CS2, GPIO> { - Parts::new(&self) - } - - // Select Chip - pub fn select_chip(&mut self, channel: u8) -> Result<(), Error> { - self.do_on_get_ref_mut_data(|mut dev| dev.select_chip(channel)) - } - } - - impl CPLD - where - SPI: Transfer, - CS0: OutputPin, - CS1: OutputPin, - CS2: OutputPin, - GPIO: OutputPin - { - // Issue I/O Update - pub fn issue_io_update(&mut self) -> Result<(), Error> { - self.do_on_get_ref_mut_data(|mut dev| dev.issue_io_update()) - } - } \ No newline at end of file +#[derive(Debug)] +pub struct CPLDData { + pub(crate) spi: SPI, + pub(crate) chip_select: (CS0, CS1, CS2), + pub(crate) io_update: GPIO, +} + +#[derive(Debug)] +pub struct CPLD { + pub(crate) data: cell::RefCell>, +} + +pub trait SelectChip { + type Error; + fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error>; +} + +impl SelectChip for CPLDData +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin, +{ + type Error = Error; + fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error> { + match chip & (1 << 0) { + 0 => self.chip_select.0.set_low(), + _ => self.chip_select.0.set_high(), + }.map_err(|_| Error::CSError)?; + match chip & (1 << 1) { + 0 => self.chip_select.1.set_low(), + _ => self.chip_select.1.set_high(), + }.map_err(|_| Error::CSError)?; + match chip & (1 << 2) { + 0 => self.chip_select.2.set_low(), + _ => self.chip_select.2.set_high(), + }.map_err(|_| Error::CSError)?; + Ok(()) + } +} + +pub trait IssueIOUpdate { + type Error; + fn issue_io_update(&mut self) -> Result<(), Self::Error>; +} + +impl IssueIOUpdate for CPLDData +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin, +{ + type Error = Error; + + fn issue_io_update(&mut self) -> Result<(), Self::Error> { + self.io_update.set_high().map_err(|_| Error::IOUpdateError)?; + self.io_update.set_low().map_err(|_| Error::IOUpdateError) + } +} + +pub trait DoOnGetRefMutData { + fn do_on_get_ref_mut_data( + &self, + f: impl FnOnce(cell::RefMut>) -> Result>, + ) -> Result>; +} + +impl DoOnGetRefMutData for CPLD { + fn do_on_get_ref_mut_data( + &self, + f: impl FnOnce(cell::RefMut>) -> Result>, + ) -> Result> { + let dev = self + .data + .try_borrow_mut() + .map_err(|_| Error::GetRefMutDataError)?; + f(dev) + } +} + +impl Transfer for CPLD +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin, +{ + type Error = 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)) + } +} + +impl CPLD where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin +{ + // Constructor for CPLD + pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2), io_update: GPIO) -> Self { + + // Init data + let data = CPLDData { + spi, + chip_select, + io_update, + }; + + // Init CPLD + CPLD { + data: cell::RefCell::new(data), + } + } + + // Destroy the wrapper, return the CPLD data + pub fn destroy(self) -> (SPI, (CS0, CS1, CS2), GPIO) { + let cpld = self.data.into_inner(); + (cpld.spi, cpld.chip_select, cpld.io_update) + } + + // Split SPI into chips, wrapped by Parts struct + pub fn split<'a>(&'a self) -> Parts<'a, CPLD, SPI, CS0, CS1, CS2, GPIO> { + Parts::new(&self) + } + + // Select Chip + pub fn select_chip(&mut self, channel: u8) -> Result<(), Error> { + self.do_on_get_ref_mut_data(|mut dev| dev.select_chip(channel)) + } +} + +impl CPLD +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin +{ + // Issue I/O Update + pub fn issue_io_update(&mut self) -> Result<(), Error> { + self.do_on_get_ref_mut_data(|mut dev| dev.issue_io_update()) + } +} \ No newline at end of file