Skip to content

Commit

Permalink
#12: Using new HAL SPI device interface [WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
marius-meissner committed Dec 2, 2024
1 parent 6c44070 commit 6f32c86
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 169 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ readme = "README.md"
documentation = "https://docs.rs/ltc681x"

[dependencies]
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-hal = "1.0.0"
heapless = "0.8.0"
fixed = "1.15.0"

Expand Down
83 changes: 50 additions & 33 deletions src/example.rs
Original file line number Diff line number Diff line change
@@ -1,58 +1,75 @@
//! SPI bus mock for doc examples
use core::convert::Infallible;
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::digital::OutputPin;
use embedded_hal::spi::{ErrorType, Operation, SpiDevice};

#[derive(Default)]
pub struct ExampleSPIBus {
poll_count: usize,
command: u8,
}

impl Transfer<u8> for ExampleSPIBus {
impl ErrorType for ExampleSPIBus {
type Error = Infallible;
}

fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
// Poll call
if words.len() == 1 {
self.poll_count += 1;

return if self.poll_count >= 2 { Ok(&[0xff]) } else { Ok(&[0x0]) };
impl SpiDevice<u8> for ExampleSPIBus {
fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
if operations.len() != 1 {
panic!("Only one operation supported by example SPI client");
}

if words[1] == 0xff {
return match self.command {
// Status register A
0b0001_0000 => Ok(&[0x12, 0x62, 0xA8, 0x62, 0x00, 0x7D, 0x31, 0x8A]),
// Status register B
0b0001_0010 => Ok(&[0x00, 0xC8, 0x00, 0x66, 0x00, 0x1B, 0xF1, 0x40]),
// Cell voltage register B
0b0000_0100 => Ok(&[0x93, 0x61, 0xBB, 0x1E, 0xAE, 0x22, 0x9A, 0x1C]),
// Cell voltage register B
0b0000_0110 => Ok(&[0xDD, 0x66, 0x72, 0x1D, 0xA2, 0x1C, 0x11, 0x94]),
// Cell voltage register C
0b0000_1000 => Ok(&[0x61, 0x63, 0xBD, 0x1E, 0xE4, 0x22, 0x3F, 0x42]),
// Cell voltage register E
0b0000_1001 => Ok(&[0xDE, 0x64, 0x8F, 0x21, 0x8A, 0x21, 0x8F, 0xDA]),
// Aux voltage register A
0b0000_1100 => Ok(&[0x93, 0x61, 0xBB, 0x1E, 0xAE, 0x22, 0x9A, 0x1C]),
// Aux voltage register C
0b0000_1101 => Ok(&[0x61, 0x63, 0xBD, 0x1E, 0xE4, 0x22, 0x3F, 0x42]),
_ => Ok(&[0x0; 8]),
};
match &mut operations[0] {
Operation::Read(buffer) => {
// Poll call
if buffer.len() == 1 {
self.poll_count += 1;
if self.poll_count >= 2 {
buffer[0] = 0xff
} else {
buffer[0] = 0x0
};
}

match self.command {
// Status register A
0b0001_0000 => buffer.copy_from_slice(&[0x12, 0x62, 0xA8, 0x62, 0x00, 0x7D, 0x31, 0x8A]),
// Status register B
0b0001_0010 => buffer.copy_from_slice(&[0x00, 0xC8, 0x00, 0x66, 0x00, 0x1B, 0xF1, 0x40]),
// Cell voltage register B
0b0000_0100 => buffer.copy_from_slice(&[0x93, 0x61, 0xBB, 0x1E, 0xAE, 0x22, 0x9A, 0x1C]),
// Cell voltage register B
0b0000_0110 => buffer.copy_from_slice(&[0xDD, 0x66, 0x72, 0x1D, 0xA2, 0x1C, 0x11, 0x94]),
// Cell voltage register C
0b0000_1000 => buffer.copy_from_slice(&[0x61, 0x63, 0xBD, 0x1E, 0xE4, 0x22, 0x3F, 0x42]),
// Cell voltage register E
0b0000_1001 => buffer.copy_from_slice(&[0xDE, 0x64, 0x8F, 0x21, 0x8A, 0x21, 0x8F, 0xDA]),
// Aux voltage register A
0b0000_1100 => buffer.copy_from_slice(&[0x93, 0x61, 0xBB, 0x1E, 0xAE, 0x22, 0x9A, 0x1C]),
// Aux voltage register C
0b0000_1101 => buffer.copy_from_slice(&[0x61, 0x63, 0xBD, 0x1E, 0xE4, 0x22, 0x3F, 0x42]),
_ => buffer.copy_from_slice(&[0x0; 8]),
};
}
Operation::Write(words) => {
self.command = words[1];
}
Operation::Transfer(_, _) => panic!("Transfer operation not supported by example SPI client"),
Operation::TransferInPlace(_) => panic!("TransferInPlace operation not supported by example SPI client"),
Operation::DelayNs(_) => panic!("DelayNs operation not supported by example SPI client"),
}

// Remember command for next read
self.command = words[1];
Ok(&[0x0])
Ok(())
}
}

pub struct ExampleCSPin {}

impl OutputPin for ExampleCSPin {
impl embedded_hal::digital::ErrorType for ExampleCSPin {
type Error = Infallible;
}

impl OutputPin for ExampleCSPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ pub(crate) mod pec15;

#[cfg(test)]
mod mocks;
mod spi;
#[cfg(test)]
mod tests;
12 changes: 5 additions & 7 deletions src/ltc6810.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use crate::monitor::{
RegisterAddress, RegisterLocator, ToCommandBitmap, ToCommandTiming, ToFullCommand, LTC681X,
};
use core::slice::Iter;
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::SpiDevice;

/// Cell selection for ADC conversion
///
Expand Down Expand Up @@ -94,14 +93,13 @@ impl DeviceTypes for LTC6810 {
const REG_CONF_B: Option<Self::Register> = None;
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6810, L>
impl<B, const L: usize> LTC681X<B, NoPolling, LTC6810, L>
where
B: Transfer<u8>,
CS: OutputPin,
B: SpiDevice<u8>,
{
/// Creates a client instant for LTC6810 variant
pub fn ltc6810(bus: B, cs: CS) -> Self {
LTC681X::new(bus, cs)
pub fn ltc6810(bus: B) -> Self {
LTC681X::new(bus)
}
}

Expand Down
12 changes: 5 additions & 7 deletions src/ltc6811.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use crate::monitor::{
RegisterAddress, RegisterLocator, ToCommandBitmap, ToCommandTiming, ToFullCommand, LTC681X,
};
use core::slice::Iter;
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::SpiDevice;

/// Cell selection for ADC conversion
///
Expand Down Expand Up @@ -109,14 +108,13 @@ impl DeviceTypes for LTC6811 {
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6811, L>
impl<B, const L: usize> LTC681X<B, NoPolling, LTC6811, L>
where
B: Transfer<u8>,
CS: OutputPin,
B: SpiDevice<u8>,
{
/// Creates a client instant for LTC6811 variant
pub fn ltc6811(bus: B, cs: CS) -> Self {
LTC681X::new(bus, cs)
pub fn ltc6811(bus: B) -> Self {
LTC681X::new(bus)
}
}

Expand Down
12 changes: 5 additions & 7 deletions src/ltc6812.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ use crate::monitor::{
RegisterAddress, RegisterLocator, ToCommandBitmap, ToCommandTiming, ToFullCommand, LTC681X,
};
use core::slice::Iter;
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::SpiDevice;

/// Cell selection for ADC conversion
///
Expand Down Expand Up @@ -124,14 +123,13 @@ impl DeviceTypes for LTC6812 {
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6812, L>
impl<B, const L: usize> LTC681X<B, NoPolling, LTC6812, L>
where
B: Transfer<u8>,
CS: OutputPin,
B: SpiDevice<u8>,
{
/// Creates a client instant for LTC6812 variant
pub fn ltc6812(bus: B, cs: CS) -> Self {
LTC681X::new(bus, cs)
pub fn ltc6812(bus: B) -> Self {
LTC681X::new(bus)
}
}

Expand Down
12 changes: 5 additions & 7 deletions src/ltc6813.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use crate::monitor::{
RegisterAddress, RegisterLocator, ToCommandBitmap, ToCommandTiming, ToFullCommand, LTC681X,
};
use core::slice::Iter;
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::SpiDevice;

/// Cell selection for ADC conversion
///
Expand Down Expand Up @@ -127,14 +126,13 @@ impl DeviceTypes for LTC6813 {
const REG_CONF_B: Option<Self::Register> = Some(Register::ConfigurationB);
}

impl<B, CS, const L: usize> LTC681X<B, CS, NoPolling, LTC6813, L>
impl<B, const L: usize> LTC681X<B, NoPolling, LTC6813, L>
where
B: Transfer<u8>,
CS: OutputPin,
B: SpiDevice<u8>,
{
/// Creates a client instant for LTC6813 variant
pub fn ltc6813(bus: B, cs: CS) -> Self {
LTC681X::new(bus, cs)
pub fn ltc6813(bus: B) -> Self {
LTC681X::new(bus)
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/mocks.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use embedded_hal::blocking::spi::Transfer;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::digital::{ErrorType, OutputPin};
use embedded_hal::spi::{Operation, SpiDevice};
use mockall::mock;

#[derive(Debug, PartialEq, Eq)]
Expand All @@ -10,10 +10,10 @@ pub enum BusError {
mock! {
pub SPIBus {}

impl Transfer<u8> for SPIBus{
type Error = BusError;
impl embedded_hal::spi::ErrorType for SPIBus { type Error = BusError; }

fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'static [u8], BusError>;
impl SpiDevice<u8> for SPIBus{
fn transaction(&mut self, operations: &mut [Operation<'static, u8>]) -> Result<(), Self::Error>;
}
}

Expand All @@ -25,9 +25,9 @@ pub enum PinError {
mock! {
pub Pin {}

impl OutputPin for Pin {
type Error = PinError;
impl ErrorType for Pin { type Error = PinError; }

impl OutputPin for Pin {
fn set_low(&mut self) -> Result<(), PinError>;
fn set_high(&mut self) -> Result<(), PinError>;
}
Expand Down
Loading

0 comments on commit 6f32c86

Please sign in to comment.