add Chip Select handling
This commit is contained in:
parent
b3a16aab15
commit
db80221815
100
src/lib.rs
100
src/lib.rs
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user