Skip to content
Draft
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 50 additions & 17 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ pub mod config {
}
}

#[derive(Copy, Clone)]
pub enum Chunk {
EightBits = 1,
SixteenBits = 2,
TwentyFourBits = 3,
ThirtyTwoBits = 4,
FourtyEightBits = 6,
SixtyFourBits = 8,
}

/// SPI Device configuration
#[derive(Copy, Clone)]
pub struct Config {
Expand All @@ -167,6 +177,10 @@ pub mod config {
pub write_only: bool,
pub duplex: Duplex,
pub cs_active_high: bool,
/// Number of bits in a transfer unit e.g 8bit 32bit.
/// A transfer unit is a continoues clkout signal without a gap.
/// Some Devices can only work with 8bit transfer units
pub chunk_size: Chunk,
}

impl Config {
Expand Down Expand Up @@ -200,6 +214,11 @@ pub mod config {
self.cs_active_high = true;
self
}

pub fn transfer_by_chunk(mut self, chunk_size: Chunk) -> Self {
self.chunk_size = chunk_size;
self
}
}

impl Default for Config {
Expand All @@ -210,6 +229,7 @@ pub mod config {
write_only: false,
cs_active_high: false,
duplex: Duplex::Full,
chunk_size: Chunk::SixtyFourBits,
}
}
}
Expand Down Expand Up @@ -342,7 +362,7 @@ impl<'d> SpiBus for SpiBusDriver<'d> {

pub struct SpiDriver<'d> {
host: u8,
max_transfer_size: usize,
dma: Dma,
_p: PhantomData<&'d mut ()>,
}

Expand All @@ -358,11 +378,11 @@ impl<'d> SpiDriver<'d> {
sdi: Option<impl Peripheral<P = crate::gpio::Gpio8> + 'd>,
dma: Dma,
) -> Result<Self, EspError> {
let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?;
Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?;

Ok(Self {
host: SPI1::device() as _,
max_transfer_size,
dma,
_p: PhantomData,
})
}
Expand All @@ -375,11 +395,11 @@ impl<'d> SpiDriver<'d> {
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
dma: Dma,
) -> Result<Self, EspError> {
let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?;
Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?;

Ok(Self {
host: SPI::device() as _,
max_transfer_size,
dma,
_p: PhantomData,
})
}
Expand All @@ -394,11 +414,10 @@ impl<'d> SpiDriver<'d> {
sdo: impl Peripheral<P = impl OutputPin> + 'd,
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
dma: Dma,
) -> Result<usize, EspError> {
) -> Result<(), EspError> {
crate::into_ref!(sclk, sdo);
let sdi = sdi.map(|sdi| sdi.into_ref());

let max_transfer_sz = dma.max_transfer_size();
let dma_chan: spi_dma_chan_t = dma.into();

#[cfg(not(esp_idf_version = "4.3"))]
Expand Down Expand Up @@ -426,7 +445,7 @@ impl<'d> SpiDriver<'d> {
quadhd_io_num: -1,
//data3_io_num: -1,
},
max_transfer_sz: max_transfer_sz as i32,
max_transfer_sz: dma.max_transfer_size() as i32,
..Default::default()
};

Expand All @@ -440,13 +459,13 @@ impl<'d> SpiDriver<'d> {
quadwp_io_num: -1,
quadhd_io_num: -1,

max_transfer_sz: max_transfer_sz as i32,
max_transfer_sz: dma.max_transfer_size() as i32,
..Default::default()
};

esp!(unsafe { spi_bus_initialize(host, &bus_config, dma_chan) })?;

Ok(max_transfer_sz)
Ok(())
}
}

Expand All @@ -464,6 +483,7 @@ pub struct SpiDeviceDriver<'d, T> {
handle: spi_device_handle_t,
driver: T,
with_cs_pin: bool,
transfer_unit_size: u8,
_p: PhantomData<&'d ()>,
}

Expand Down Expand Up @@ -505,6 +525,8 @@ where
) -> Result<Self, EspError> {
let cs = cs.map(|cs| cs.into_ref().pin()).unwrap_or(-1);

let transfer_unit_size = config.chunk_size as u8;

let conf = spi_device_interface_config_t {
spics_io_num: cs,
clock_speed_hz: config.baudrate.0 as i32,
Expand Down Expand Up @@ -532,6 +554,7 @@ where
handle,
driver,
with_cs_pin: cs >= 0,
transfer_unit_size,
_p: PhantomData,
})
}
Expand All @@ -548,7 +571,11 @@ where
E: From<EspError>,
{
// if DMA used -> get trans length info from driver
let trans_len = self.driver.borrow().max_transfer_size;
let trans_len = if self.driver.borrow().dma == Dma::Disabled {
self.transfer_unit_size as usize
} else {
self.driver.borrow().dma.max_transfer_size()
};

let mut bus = SpiBusDriver {
handle: self.handle,
Expand Down Expand Up @@ -630,9 +657,12 @@ where

fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
let _lock = self.lock_bus()?;
let mut chunks = words
.chunks_mut(self.driver.borrow().max_transfer_size)
.peekable();
let trans_len = if self.driver.borrow().dma == Dma::Disabled {
self.transfer_unit_size as usize
} else {
self.driver.borrow().dma.max_transfer_size()
};
let mut chunks = words.chunks_mut(trans_len).peekable();

while let Some(chunk) = chunks.next() {
let ptr = chunk.as_mut_ptr();
Expand All @@ -652,9 +682,12 @@ where

fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
let _lock = self.lock_bus()?;
let mut chunks = words
.chunks(self.driver.borrow().max_transfer_size)
.peekable();
let trans_len = if self.driver.borrow().dma == Dma::Disabled {
self.transfer_unit_size as usize
} else {
self.driver.borrow().dma.max_transfer_size()
};
let mut chunks = words.chunks(trans_len).peekable();

while let Some(chunk) = chunks.next() {
polling_transmit(
Expand Down