humpback-dds/src/lib.rs

193 lines
4.4 KiB
Rust
Raw Normal View History

2020-08-10 17:04:40 +08:00
#![no_std]
2020-08-11 00:07:07 +08:00
extern crate embedded_hal;
use embedded_hal::{
digital::v2::OutputPin,
blocking::spi::Transfer,
2020-08-10 18:06:15 +08:00
};
2020-08-10 17:04:40 +08:00
2020-08-10 18:06:15 +08:00
use core::cell;
2020-08-26 11:04:39 +08:00
use core::mem::size_of;
2020-08-10 18:06:15 +08:00
use cortex_m;
use cortex_m::asm::nop;
use cortex_m_semihosting::hprintln;
2020-08-13 16:51:08 +08:00
#[macro_use]
pub mod bitmask_macro;
2020-08-10 18:06:15 +08:00
pub mod spi_slave;
2020-08-11 00:07:07 +08:00
use crate::spi_slave::Parts;
2020-08-11 16:51:17 +08:00
pub mod config_register;
2020-08-11 00:07:07 +08:00
pub mod attenuator;
2020-08-17 12:15:11 +08:00
pub mod dds;
2020-08-13 16:51:08 +08:00
2020-08-10 18:06:15 +08:00
/*
* Enum for structuring error
*/
#[derive(Debug)]
pub enum Error<E> {
SPI(E),
CSError,
GetRefMutDataError,
2020-08-11 11:29:47 +08:00
AttenuatorError,
2020-08-24 17:03:44 +08:00
IOUpdateError,
2020-08-10 18:06:15 +08:00
}
/*
* Basic structure for CPLD signal multiplexing
*/
#[derive(Debug)]
2020-08-24 17:03:44 +08:00
pub struct CPLDData<SPI, CS0, CS1, CS2, GPIO> {
2020-08-10 18:06:15 +08:00
pub(crate) spi: SPI,
pub(crate) chip_select: (CS0, CS1, CS2),
2020-08-24 17:03:44 +08:00
pub(crate) io_update: GPIO,
2020-08-10 18:06:15 +08:00
}
#[derive(Debug)]
2020-08-24 17:03:44 +08:00
pub struct CPLD<SPI, CS0, CS1, CS2, GPIO> {
pub(crate) data: cell::RefCell<CPLDData<SPI, CS0, CS1, CS2, GPIO>>,
2020-08-10 18:06:15 +08:00
}
pub trait SelectChip {
type Error;
fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error>;
}
2020-08-24 17:03:44 +08:00
impl<SPI, CS0, CS1, CS2, GPIO, E> SelectChip for CPLDData<SPI, CS0, CS1, CS2, GPIO>
2020-08-10 18:06:15 +08:00
where
SPI: Transfer<u8, Error = E>,
CS0: OutputPin,
CS1: OutputPin,
CS2: OutputPin,
2020-08-24 17:03:44 +08:00
GPIO: OutputPin,
2020-08-10 18:06:15 +08:00
{
type Error = Error<E>;
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(())
}
}
2020-08-24 17:03:44 +08:00
trait IssueIOUpdate {
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_low().map_err(|_| Error::IOUpdateError)
}
}
pub trait DoOnGetRefMutData<SPI, CS0, CS1, CS2, GPIO> {
2020-08-10 18:06:15 +08:00
fn do_on_get_ref_mut_data<R, E>(
&self,
2020-08-24 17:03:44 +08:00
f: impl FnOnce(cell::RefMut<CPLDData<SPI, CS0, CS1, CS2, GPIO>>) -> Result<R, Error<E>>,
2020-08-10 18:06:15 +08:00
) -> Result<R, Error<E>>;
}
2020-08-24 17:03:44 +08:00
impl<SPI, CS0, CS1, CS2, GPIO> DoOnGetRefMutData<SPI, CS0, CS1, CS2, GPIO> for CPLD<SPI, CS0, CS1, CS2, GPIO> {
2020-08-10 18:06:15 +08:00
fn do_on_get_ref_mut_data<R, E>(
&self,
2020-08-24 17:03:44 +08:00
f: impl FnOnce(cell::RefMut<CPLDData<SPI, CS0, CS1, CS2, GPIO>>) -> Result<R, Error<E>>,
2020-08-10 18:06:15 +08:00
) -> Result<R, Error<E>> {
let dev = self
.data
.try_borrow_mut()
.map_err(|_| Error::GetRefMutDataError)?;
f(dev)
}
}
2020-08-24 17:03:44 +08:00
impl<SPI, CS0, CS1, CS2, GPIO, E> Transfer<u8> for CPLD<SPI, CS0, CS1, CS2, GPIO>
2020-08-10 18:06:15 +08:00
where
SPI: Transfer<u8, Error = E>,
CS0: OutputPin,
CS1: OutputPin,
CS2: OutputPin,
2020-08-24 17:03:44 +08:00
GPIO: OutputPin,
2020-08-10 18:06:15 +08:00
{
type Error = Error<E>;
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))
}
}
2020-08-24 17:03:44 +08:00
impl<SPI, CS0, CS1, CS2, GPIO, E> CPLD<SPI, CS0, CS1, CS2, GPIO> where
2020-08-10 18:06:15 +08:00
SPI: Transfer<u8, Error = E>,
CS0: OutputPin,
CS1: OutputPin,
CS2: OutputPin,
2020-08-24 17:03:44 +08:00
GPIO: OutputPin
2020-08-10 18:06:15 +08:00
{
// Constructor for CPLD
2020-08-24 17:03:44 +08:00
pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2), io_update: GPIO) -> Self {
2020-08-10 18:06:15 +08:00
// Init data
let data = CPLDData {
spi,
chip_select,
2020-08-24 17:03:44 +08:00
io_update,
2020-08-10 18:06:15 +08:00
};
// Init CPLD
CPLD {
data: cell::RefCell::new(data),
}
}
// Destroy the wrapper, return the CPLD data
2020-08-24 17:03:44 +08:00
pub fn destroy(self) -> (SPI, (CS0, CS1, CS2), GPIO) {
2020-08-10 18:06:15 +08:00
let cpld = self.data.into_inner();
2020-08-24 17:03:44 +08:00
(cpld.spi, cpld.chip_select, cpld.io_update)
2020-08-10 18:06:15 +08:00
}
// Split SPI into chips, wrapped by Parts struct
2020-08-24 17:03:44 +08:00
pub fn split<'a>(&'a self) -> Parts<'a, CPLD<SPI, CS0, CS1, CS2, GPIO>, SPI, CS0, CS1, CS2, GPIO> {
2020-08-10 18:06:15 +08:00
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))
}
}
2020-08-24 17:03:44 +08:00
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())
}
}