forked from M-Labs/humpback-dds
cpld: detach from lib.rs
This commit is contained in:
parent
0816220065
commit
4852fc54ea
|
@ -15,7 +15,6 @@ stm32h7xx-hal = {version = "0.6.0", features = [ "stm32h743v", "rt", "unproven"
|
||||||
stm32h7-ethernet = { version = "0.2.0", features = [ "phy_lan8742a", "stm32h743v" ] }
|
stm32h7-ethernet = { version = "0.2.0", features = [ "phy_lan8742a", "stm32h743v" ] }
|
||||||
smoltcp = { version = "0.6.0", default-features = false, features = [ "ethernet", "proto-ipv4", "proto-ipv6", "socket-raw" ] }
|
smoltcp = { version = "0.6.0", default-features = false, features = [ "ethernet", "proto-ipv4", "proto-ipv6", "socket-raw" ] }
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
# scpi = {path = "../scpi-rs/scpi", version = "0.3.4"}
|
|
||||||
scpi = { git = "https://github.com/occheung/scpi-rs", branch = "issue-4" }
|
scpi = { git = "https://github.com/occheung/scpi-rs", branch = "issue-4" }
|
||||||
lexical-core = { version="0.7.1", features=["radix"], default-features=false }
|
lexical-core = { version="0.7.1", features=["radix"], default-features=false }
|
||||||
libm = { version = "0.2.0" }
|
libm = { version = "0.2.0" }
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
use crate::Error;
|
||||||
|
use crate::spi_slave::Parts;
|
||||||
|
|
||||||
|
use embedded_hal::{
|
||||||
|
digital::v2::OutputPin,
|
||||||
|
blocking::spi::Transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
use core::cell;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic structure for CPLD signal multiplexing
|
||||||
|
*/
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CPLDData<SPI, CS0, CS1, CS2, GPIO> {
|
||||||
|
pub(crate) spi: SPI,
|
||||||
|
pub(crate) chip_select: (CS0, CS1, CS2),
|
||||||
|
pub(crate) io_update: GPIO,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CPLD<SPI, CS0, CS1, CS2, GPIO> {
|
||||||
|
pub(crate) data: cell::RefCell<CPLDData<SPI, CS0, CS1, CS2, GPIO>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SelectChip {
|
||||||
|
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
|
||||||
|
SPI: Transfer<u8, Error = E>,
|
||||||
|
CS0: OutputPin,
|
||||||
|
CS1: OutputPin,
|
||||||
|
CS2: OutputPin,
|
||||||
|
GPIO: OutputPin,
|
||||||
|
{
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub 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> {
|
||||||
|
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>
|
||||||
|
where
|
||||||
|
SPI: Transfer<u8, Error = E>,
|
||||||
|
CS0: OutputPin,
|
||||||
|
CS1: OutputPin,
|
||||||
|
CS2: OutputPin,
|
||||||
|
GPIO: OutputPin,
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SPI, CS0, CS1, CS2, GPIO, E> CPLD<SPI, CS0, CS1, CS2, GPIO> where
|
||||||
|
SPI: Transfer<u8, Error = E>,
|
||||||
|
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>, SPI, CS0, CS1, CS2, GPIO> {
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
163
src/lib.rs
163
src/lib.rs
|
@ -1,9 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
extern crate embedded_hal;
|
extern crate embedded_hal;
|
||||||
use embedded_hal::{
|
|
||||||
digital::v2::OutputPin,
|
|
||||||
blocking::spi::Transfer,
|
|
||||||
};
|
|
||||||
|
|
||||||
use core::cell;
|
use core::cell;
|
||||||
|
|
||||||
|
@ -16,6 +12,8 @@ pub mod bitmask_macro;
|
||||||
pub mod spi_slave;
|
pub mod spi_slave;
|
||||||
use crate::spi_slave::Parts;
|
use crate::spi_slave::Parts;
|
||||||
|
|
||||||
|
pub mod cpld;
|
||||||
|
|
||||||
pub mod config_register;
|
pub mod config_register;
|
||||||
pub mod attenuator;
|
pub mod attenuator;
|
||||||
pub mod dds;
|
pub mod dds;
|
||||||
|
@ -33,160 +31,3 @@ pub enum Error<E> {
|
||||||
IOUpdateError,
|
IOUpdateError,
|
||||||
DDSError,
|
DDSError,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Basic structure for CPLD signal multiplexing
|
|
||||||
*/
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CPLDData<SPI, CS0, CS1, CS2, GPIO> {
|
|
||||||
pub(crate) spi: SPI,
|
|
||||||
pub(crate) chip_select: (CS0, CS1, CS2),
|
|
||||||
pub(crate) io_update: GPIO,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CPLD<SPI, CS0, CS1, CS2, GPIO> {
|
|
||||||
pub(crate) data: cell::RefCell<CPLDData<SPI, CS0, CS1, CS2, GPIO>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait SelectChip {
|
|
||||||
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
|
|
||||||
SPI: Transfer<u8, Error = E>,
|
|
||||||
CS0: OutputPin,
|
|
||||||
CS1: OutputPin,
|
|
||||||
CS2: OutputPin,
|
|
||||||
GPIO: OutputPin,
|
|
||||||
{
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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> {
|
|
||||||
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>
|
|
||||||
where
|
|
||||||
SPI: Transfer<u8, Error = E>,
|
|
||||||
CS0: OutputPin,
|
|
||||||
CS1: OutputPin,
|
|
||||||
CS2: OutputPin,
|
|
||||||
GPIO: OutputPin,
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SPI, CS0, CS1, CS2, GPIO, E> CPLD<SPI, CS0, CS1, CS2, GPIO> where
|
|
||||||
SPI: Transfer<u8, Error = E>,
|
|
||||||
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>, SPI, CS0, CS1, CS2, GPIO> {
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ use cortex_m_semihosting::hprintln;
|
||||||
|
|
||||||
use firmware;
|
use firmware;
|
||||||
use firmware::{
|
use firmware::{
|
||||||
CPLD,
|
|
||||||
attenuator::Attenuator,
|
attenuator::Attenuator,
|
||||||
config_register::{
|
config_register::{
|
||||||
ConfigRegister,
|
ConfigRegister,
|
||||||
|
@ -26,6 +25,9 @@ use firmware::{
|
||||||
DDS,
|
DDS,
|
||||||
DDSCFRMask,
|
DDSCFRMask,
|
||||||
},
|
},
|
||||||
|
cpld::{
|
||||||
|
CPLD,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
|
|
|
@ -4,7 +4,8 @@ use embedded_hal::{
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{DoOnGetRefMutData, Error, SelectChip, IssueIOUpdate};
|
use crate::cpld::{DoOnGetRefMutData, SelectChip, IssueIOUpdate};
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
pub struct SPISlave<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> (
|
pub struct SPISlave<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> (
|
||||||
&'a DEV,
|
&'a DEV,
|
||||||
|
|
Loading…
Reference in New Issue