add Chip Select handling

This commit is contained in:
Robin Müller 2021-12-12 20:56:23 +01:00
parent b3a16aab15
commit db80221815
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
1 changed files with 57 additions and 43 deletions

View File

@ -1,6 +1,10 @@
#![no_std]
use core::{marker::PhantomData, slice::IterMut};
use embedded_hal::{blocking::spi::Transfer, digital::v2::InputPin, spi::FullDuplex};
use embedded_hal::{
blocking::spi::Transfer,
digital::v2::{InputPin, OutputPin},
spi::FullDuplex,
};
//==================================================================================================
// Type-level support
@ -152,23 +156,13 @@ pub enum AdcError {
}
#[derive(Debug)]
pub enum Error<SpiE> {
pub enum Error<SpiE, PinE> {
Adc(AdcError),
Spi(SpiE),
}
pub enum ErrorWithEoc<SpiE, PinE> {
Error(Error<SpiE>),
Pin(PinE),
}
impl<SpiE, PinE> From<AdcError> for ErrorWithEoc<SpiE, PinE> {
fn from(other: AdcError) -> Self {
ErrorWithEoc::Error(Error::Adc(other))
}
}
impl<SpiE> From<AdcError> for Error<SpiE> {
impl<SpiE, PinE> From<AdcError> for Error<SpiE, PinE> {
fn from(other: AdcError) -> Self {
Error::Adc(other)
}
@ -180,29 +174,34 @@ impl<SpiE> From<AdcError> for Error<SpiE> {
pub struct Max116xx10Bit<
SPI,
CS,
MAX: HasChannels,
CLOCKED = ExternallyClocked,
DELAY = WithoutWakeupDelay,
> {
pub clk_mode: ClockMode,
pub ref_mode: RefMode,
clk_mode: ClockMode,
ref_mode: RefMode,
spi: SPI,
cs: CS,
pending_op: PendingOp,
max: PhantomData<MAX>,
clocked: PhantomData<CLOCKED>,
delay: PhantomData<DELAY>,
}
impl<SpiE, SPI, MAX: HasChannels, CLOCKED: Clocked, DELAY> Max116xx10Bit<SPI, MAX, CLOCKED, DELAY>
impl<SpiE, PinE, CS, SPI, MAX: HasChannels, CLOCKED: Clocked, DELAY>
Max116xx10Bit<SPI, CS, MAX, CLOCKED, DELAY>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
/// Create a new generic MAX116xx instance.
pub fn new(spi: SPI, ref_mode: RefMode) -> Result<Self, Error<SpiE>> {
let mut max_dev: Max116xx10Bit<SPI, MAX, CLOCKED, DELAY> = Max116xx10Bit {
pub fn new(spi: SPI, cs: CS, ref_mode: RefMode) -> Result<Self, Error<SpiE, PinE>> {
let mut max_dev = Max116xx10Bit {
clk_mode: CLOCKED::CLK_SEL,
ref_mode,
spi,
cs,
pending_op: PendingOp::None,
max: PhantomData,
delay: PhantomData,
@ -213,12 +212,15 @@ where
}
#[inline]
fn send_wrapper(&mut self, byte: u8) -> Result<(), Error<SpiE>> {
nb::block!(self.spi.send(byte)).map_err(|e| Error::Spi(e))
fn send_wrapper(&mut self, byte: u8) -> Result<(), Error<SpiE, PinE>> {
self.cs.set_low().map_err(|e| Error::Pin(e))?;
nb::block!(self.spi.send(byte)).map_err(|e| Error::Spi(e))?;
self.cs.set_high().map_err(|e| Error::Pin(e))?;
Ok(())
}
#[inline]
pub fn setup(&mut self) -> Result<(), Error<SpiE>> {
pub fn setup(&mut self) -> Result<(), Error<SpiE, PinE>> {
self.send_wrapper(self.get_setup_byte())
}
@ -227,12 +229,12 @@ where
&mut self,
avg_conv: AveragingConversions,
avg_res: AveragingResults,
) -> Result<(), Error<SpiE>> {
) -> Result<(), Error<SpiE, PinE>> {
self.send_wrapper(Self::get_averaging_byte(avg_conv, avg_res))
}
#[inline]
pub fn reset_adc(&mut self, fifo_only: bool) -> Result<(), Error<SpiE>> {
pub fn reset_adc(&mut self, fifo_only: bool) -> Result<(), Error<SpiE, PinE>> {
let mut reset_byte = 0b0001_0000;
if fifo_only {
reset_byte |= 1 << 3;
@ -258,10 +260,11 @@ where
Ok((1 << 7) | (channel_num << 3) | ((scan_mode as u8) << 1))
}
}
impl<SpiE, SPI, MAX: HasChannels>
Max116xx10Bit<SPI, MAX, InternallyClockedInternallyTimedSerialInterface, WithoutWakeupDelay>
impl<SpiE, PinE, SPI, CS, MAX: HasChannels>
Max116xx10Bit<SPI, CS, MAX, InternallyClockedInternallyTimedSerialInterface, WithoutWakeupDelay>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
#[inline]
fn request_wrapper(
@ -269,7 +272,7 @@ where
channel_num: u8,
scan_mode: ScanMode,
op_type: PendingOp,
) -> Result<(), Error<SpiE>> {
) -> Result<(), Error<SpiE, PinE>> {
if self.pending_op != PendingOp::None {
return Err(Error::Adc(AdcError::PendingOperation));
}
@ -280,7 +283,7 @@ where
Ok(())
}
pub fn request_single_channel(&mut self, channel_num: u8) -> Result<(), Error<SpiE>> {
pub fn request_single_channel(&mut self, channel_num: u8) -> Result<(), Error<SpiE, PinE>> {
self.request_wrapper(
channel_num,
ScanMode::ConvertChannelNOnce,
@ -288,37 +291,41 @@ where
)
}
pub fn request_multiple_channels_0_to_n(&mut self, n: u8) -> Result<(), Error<SpiE>> {
pub fn request_multiple_channels_0_to_n(&mut self, n: u8) -> Result<(), Error<SpiE, PinE>> {
self.request_wrapper(n, ScanMode::Scan0ToChannelN, PendingOp::MultiChannel)
}
pub fn request_multiple_channels_n_to_highest(&mut self, n: u8) -> Result<(), Error<SpiE>> {
pub fn request_multiple_channels_n_to_highest(
&mut self,
n: u8,
) -> Result<(), Error<SpiE, PinE>> {
self.request_wrapper(n, ScanMode::ScanChannelNToHighest, PendingOp::MultiChannel)
}
pub fn get_single_channel<I: InputPin>(
pub fn get_single_channel<I: InputPin<Error = PinE>>(
&mut self,
eoc_pin: &mut I,
) -> nb::Result<u16, ErrorWithEoc<SpiE, I::Error>> {
) -> nb::Result<u16, Error<SpiE, PinE>> {
if self.pending_op != PendingOp::SingleChannel {
return Err(nb::Error::Other(ErrorWithEoc::Error(Error::Adc(
AdcError::NoPendingOperation,
))));
return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation)));
}
let is_low = match eoc_pin.is_low() {
Ok(low) => low,
Err(e) => {
return Err(nb::Error::Other(ErrorWithEoc::Pin(e)));
return Err(nb::Error::Other(Error::Pin(e)));
}
};
if is_low {
let mut dummy_cmd: [u8; 2] = [0; 2];
match self.spi.transfer(&mut dummy_cmd) {
self.cs.set_low().map_err(|e| Error::Pin(e))?;
let transfer_result = self.spi.transfer(&mut dummy_cmd);
self.cs.set_high().map_err(|e| Error::Pin(e))?;
match transfer_result {
Ok(reply) => {
self.pending_op = PendingOp::None;
Ok(((reply[0] as u16) << 6) | (reply[1] as u16 >> 2))
}
Err(e) => Err(nb::Error::Other(ErrorWithEoc::Error(Error::Spi(e)))),
Err(e) => Err(nb::Error::Other(Error::Spi(e))),
}
} else {
Err(nb::Error::WouldBlock)
@ -326,15 +333,17 @@ where
}
}
impl<SpiE, SPI, MAX: HasChannels> Max116xx10Bit<SPI, MAX, ExternallyClocked, WithoutWakeupDelay>
impl<SpiE, PinE, SPI, CS, MAX: HasChannels>
Max116xx10Bit<SPI, CS, MAX, ExternallyClocked, WithoutWakeupDelay>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
pub fn read_single_channel(
&mut self,
buf: &mut [u8],
channel_num: u8,
) -> Result<u16, Error<SpiE>> {
) -> Result<u16, Error<SpiE, PinE>> {
if buf.len() < 3 {
return Err(Error::Adc(AdcError::CmdBufTooSmall));
}
@ -347,7 +356,9 @@ where
};
buf[1] = 0x00;
buf[2] = 0x00;
self.cs.set_low().map_err(|e| Error::Pin(e))?;
let reply = self.spi.transfer(&mut buf[0..3]).ok().unwrap();
self.cs.set_high().map_err(|e| Error::Pin(e))?;
Ok(((reply[1] as u16) << 6) | (reply[2] as u16 >> 2))
}
@ -356,7 +367,7 @@ where
buf: &mut [u8],
result_iter: &mut IterMut<u16>,
n: u8,
) -> Result<(), Error<SpiE>> {
) -> Result<(), Error<SpiE, PinE>> {
let mut iter = buf.iter_mut();
let mut next_byte: &mut u8;
for idx in 0..n + 1 {
@ -367,10 +378,12 @@ where
}
next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?;
*next_byte = 0x00;
self.cs.set_low().map_err(|e| Error::Pin(e))?;
let reply = self
.spi
.transfer(&mut buf[0..((n + 1) * 2 + 1) as usize])
.map_err(|e| Error::Spi(e))?;
self.cs.set_high().map_err(|e| Error::Pin(e))?;
let mut reply_iter = reply.iter();
// Skip first reply byte
reply_iter.next().unwrap();
@ -389,7 +402,7 @@ where
buf: &mut [u8],
result_iter: &mut IterMut<u16>,
n: u8,
) -> Result<(), Error<SpiE>> {
) -> Result<(), Error<SpiE, PinE>> {
let mut iter = buf.iter_mut();
let mut next_byte: &mut u8;
if n > MAX::NUM - 1 {
@ -404,11 +417,12 @@ where
}
next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?;
*next_byte = 0x00;
self.cs.set_low().map_err(|e| Error::Pin(e))?;
let reply = self
.spi
.transfer(&mut buf[0..(conversions * 2 + 1) as usize])
.ok()
.unwrap();
.map_err(|e| Error::Spi(e))?;
self.cs.set_high().map_err(|e| Error::Pin(e))?;
let mut reply_iter = reply.iter();
// Skip first reply byte
reply_iter.next().unwrap();