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