Skip to content
This repository has been archived by the owner on Dec 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #35 from CBJamo/SpiDevice
Browse files Browse the repository at this point in the history
SpiBus -> SpiDevice
  • Loading branch information
lucasgranberg authored Oct 25, 2023
2 parents 2f16293 + 0c3e31e commit a9bd8de
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 220 deletions.
172 changes: 40 additions & 132 deletions src/interface.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use defmt::trace;
use embedded_hal_async::spi::SpiBus;
use embedded_hal_async::spi::{Operation, SpiDevice};

use crate::mod_params::RadioError;
use crate::mod_params::RadioError::*;
use crate::mod_params::RadioError::{self, SPI};
use crate::mod_traits::InterfaceVariant;

pub(crate) struct SpiInterface<SPI, IV> {
Expand All @@ -12,168 +11,77 @@ pub(crate) struct SpiInterface<SPI, IV> {

impl<SPI, IV> SpiInterface<SPI, IV>
where
SPI: SpiBus<u8>,
SPI: SpiDevice<u8>,
IV: InterfaceVariant,
{
pub fn new(spi: SPI, iv: IV) -> Self {
Self { spi, iv }
}

// Write one or more buffers to the radio.
pub async fn write(&mut self, write_buffers: &[&[u8]], is_sleep_command: bool) -> Result<(), RadioError> {
self.iv.set_nss_low().await?;
for buffer in write_buffers {
let write_result = self.spi.write(buffer).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if write_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
write_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}
}
self.iv.set_nss_high().await?;
// Write a buffer to the radio.
pub async fn write(&mut self, write_buffer: &[u8], is_sleep_command: bool) -> Result<(), RadioError> {
self.spi.write(write_buffer).await.map_err(|_| SPI)?;

if !is_sleep_command {
self.iv.wait_on_busy().await?;
}

match write_buffers.len() {
1 => trace!("write: 0x{:x}", write_buffers[0]),
2 => trace!("write: 0x{:x} 0x{:x}", write_buffers[0], write_buffers[1]),
3 => trace!(
"write: 0x{:x} 0x{:x} 0x{:x}",
write_buffers[0],
write_buffers[1],
write_buffers[2]
),
_ => trace!("write: too many buffers"),
}
trace!("write: 0x{:x}", write_buffer);

Ok(())
}

// Request a read, filling the provided buffer.
pub async fn read(
// Write
pub async fn write_with_payload(
&mut self,
write_buffers: &[&[u8]],
read_buffer: &mut [u8],
read_length: Option<u8>,
write_buffer: &[u8],
payload: &[u8],
is_sleep_command: bool,
) -> Result<(), RadioError> {
let mut input = [0u8];

self.iv.set_nss_low().await?;
for buffer in write_buffers {
let write_result = self.spi.write(buffer).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if write_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
write_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}
let mut ops = [Operation::Write(write_buffer), Operation::Write(payload)];
self.spi.transaction(&mut ops).await.map_err(|_| SPI)?;

if !is_sleep_command {
self.iv.wait_on_busy().await?;
}

let number_to_read = match read_length {
Some(len) => len as usize,
None => read_buffer.len(),
};

#[allow(clippy::needless_range_loop)]
for i in 0..number_to_read {
let transfer_result = self.spi.transfer(&mut input, &[0x00]).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if transfer_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
transfer_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}
read_buffer[i] = input[0];
trace!("write: 0x{:x}", write_buffer);

Ok(())
}

// Request a read, filling the provided buffer.
pub async fn read(&mut self, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<(), RadioError> {
{
let mut ops = [Operation::Write(write_buffer), Operation::Read(read_buffer)];

self.spi.transaction(&mut ops).await.map_err(|_| SPI)?;
}
self.iv.set_nss_high().await?;

self.iv.wait_on_busy().await?;

match write_buffers.len() {
1 => trace!("write: 0x{:x}", write_buffers[0]),
2 => trace!("write: 0x{:x} 0x{:x}", write_buffers[0], write_buffers[1]),
3 => trace!(
"write: 0x{:x} 0x{:x} 0x{:x}",
write_buffers[0],
write_buffers[1],
write_buffers[2]
),
_ => trace!("write: too many buffers"),
}
trace!("read {}: 0x{:x}", number_to_read, read_buffer);
trace!("write: 0x{:x}", write_buffer);
trace!("read {}: 0x{:x}", read_buffer.len(), read_buffer);

Ok(())
}

// Request a read with status, filling the provided buffer and returning the status.
pub async fn read_with_status(
&mut self,
write_buffers: &[&[u8]],
read_buffer: &mut [u8],
) -> Result<u8, RadioError> {
pub async fn read_with_status(&mut self, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<u8, RadioError> {
let mut status = [0u8];
let mut input = [0u8];

self.iv.set_nss_low().await?;
for buffer in write_buffers {
let write_result = self.spi.write(buffer).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if write_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
write_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}
{
let mut ops = [
Operation::Write(write_buffer),
Operation::Read(&mut status),
Operation::Read(read_buffer),
];

self.spi.transaction(&mut ops).await.map_err(|_| SPI)?;
}

let transfer_result = self.spi.transfer(&mut status, &[0x00]).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if transfer_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
transfer_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}

#[allow(clippy::needless_range_loop)]
for i in 0..read_buffer.len() {
let transfer_result = self.spi.transfer(&mut input, &[0x00]).await.map_err(|_| SPI);
let flush_result = self.spi.flush().await.map_err(|_| SPI);
if transfer_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
transfer_result?;
} else if flush_result != Ok(()) {
let _err = self.iv.set_nss_high().await;
flush_result?;
}
read_buffer[i] = input[0];
}
self.iv.set_nss_high().await?;

self.iv.wait_on_busy().await?;

match write_buffers.len() {
1 => trace!("write: 0x{:x}", write_buffers[0]),
2 => trace!("write: 0x{:x} 0x{:x}", write_buffers[0], write_buffers[1]),
3 => trace!(
"write: 0x{:x} 0x{:x} 0x{:x}",
write_buffers[0],
write_buffers[1],
write_buffers[2]
),
_ => trace!("write: too many buffers"),
}
trace!("write: 0x{:x}", write_buffer);
trace!(
"read {} status 0x{:x}: 0x{:x}",
read_buffer.len(),
Expand Down
1 change: 0 additions & 1 deletion src/mod_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pub use lora_modulation::{Bandwidth, CodingRate, SpreadingFactor};
#[allow(dead_code, missing_docs)]
pub enum RadioError {
SPI,
NSS,
Reset,
RfSwitchRx,
RfSwitchTx,
Expand Down
4 changes: 0 additions & 4 deletions src/mod_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ use crate::mod_params::*;
pub trait InterfaceVariant {
/// Set the LoRa board type
fn set_board_type(&mut self, board_type: BoardType);
/// Select the LoRa chip for an operation
async fn set_nss_low(&mut self) -> Result<(), RadioError>;
/// De-select the LoRa chip after an operation
async fn set_nss_high(&mut self) -> Result<(), RadioError>;
/// Reset the LoRa chip
async fn reset(&mut self, delay: &mut impl DelayUs) -> Result<(), RadioError>;
/// Wait for the LoRa chip to become available for an operation
Expand Down
Loading

0 comments on commit a9bd8de

Please sign in to comment.