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]
|
#![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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user