272 lines
12 KiB
Rust
272 lines
12 KiB
Rust
use crate::{AdControl, Ads1256, BlockingDelay, CalibrationCommand, Conversion,
|
|
DataRate, Multiplexer, Status,
|
|
};
|
|
use core::ops::DerefMut;
|
|
use embassy_sync::blocking_mutex::raw::RawMutex;
|
|
|
|
use physical_node::GPIO_ERROR_MSG;
|
|
use physical_node::spi::end_spi;
|
|
use embassy_sync::mutex::Mutex;
|
|
use embedded_hal::digital::OutputPin;
|
|
use embedded_hal::spi;
|
|
use embedded_hal::spi::SpiBus;
|
|
use embedded_hal_async::digital::Wait;
|
|
|
|
impl<DelayerT, SST, DrdyT> Ads1256<DelayerT, SST, DrdyT>
|
|
where
|
|
DelayerT: BlockingDelay,
|
|
SST: OutputPin,
|
|
DrdyT: Wait,
|
|
{
|
|
/// Functionally the same as [Ads1256::cmd_read_data] but exercises fine-grained control
|
|
/// over the [Mutex] of a [SpiBus] in cases where one is used. This function will unlock the
|
|
/// [Mutex] while it is waiting for data from the ADS1256.
|
|
///
|
|
/// Action sequence:
|
|
/// 1. Wait for data_ready to go low
|
|
/// 1. Lock mutex, mutably borrow SPI
|
|
/// 1. Read the conversion value
|
|
#[inline]
|
|
pub async fn cmd_read_data_m<MutexT: RawMutex, SpiT: SpiBus>(
|
|
&mut self,
|
|
spi: &Mutex<MutexT, SpiT>,
|
|
) -> Result<Conversion, <SpiT as spi::ErrorType>::Error> {
|
|
self.data_ready.wait_for_low().await.expect(GPIO_ERROR_MSG);
|
|
let mut spi_guard = spi.lock().await;
|
|
let spi = spi_guard.deref_mut();
|
|
self.slave_select.set_low().expect(GPIO_ERROR_MSG);
|
|
let spi_op_result = self.raw_cmd_read_data(spi);
|
|
|
|
end_spi(&mut self.slave_select, spi, spi_op_result)
|
|
}
|
|
|
|
/// Functionally the same as [Ads1256::autocal_convert] but exercises fine-grained control
|
|
/// over the [Mutex] of a [SpiBus] in cases where one is used. This function will unlock the
|
|
/// [Mutex] while it is waiting for data from the ADS1256.
|
|
///
|
|
/// Action sequence:
|
|
/// 1. Switch inputs and optionally adjust different configuration parameters.
|
|
/// 1. If only the input was switched without configuration changes.
|
|
/// 1. Issue sync command followed by wakeup command
|
|
/// 1. Else, auto-calibration will take place
|
|
/// 1. Wait for data_ready low
|
|
/// 1. RDATA command (read the conversion value)
|
|
/// 1. Optionally enter standby mode
|
|
///
|
|
/// **WARNING:** Auto-calibration must be enabled for intended functionality when changing
|
|
/// [Status], [AdControl], or [DataRate]. Furthermore if setting [Status] or [AdControl], their
|
|
/// [Buffer] and [Gain] settings must be modified respectively to trigger auto-calibration.
|
|
#[inline]
|
|
pub async fn autocal_convert_m<MutexT: RawMutex, SpiT: SpiBus>(
|
|
&mut self,
|
|
spi_mutex: &Mutex<MutexT, SpiT>,
|
|
input: Multiplexer,
|
|
status: Option<Status>,
|
|
ad_control: Option<AdControl>,
|
|
data_rate: Option<DataRate>,
|
|
standby: bool,
|
|
) -> Result<Conversion, <SpiT as spi::ErrorType>::Error> {
|
|
// Acquire SPI lock
|
|
let mut spi_guard = spi_mutex.lock().await;
|
|
let spi = spi_guard.deref_mut();
|
|
// Slave select low
|
|
self.slave_select.set_low().expect(GPIO_ERROR_MSG);
|
|
match (status, ad_control, data_rate) {
|
|
// Only modifying the multiplexer, not changing any configuration
|
|
(None, None, None) => {
|
|
self._none_config(spi, input)?;
|
|
self._manual_conversion_init(spi)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer) and changing multiplexer
|
|
(Some(status), None, None) => {
|
|
self._status_config(spi, input, status)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying AD control (gain) and changing multiplexer
|
|
(None, Some(ad_control), None) => {
|
|
self._ad_config(spi, input, ad_control)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying data rate and change multiplexer
|
|
(None, None, Some(data_rate)) => {
|
|
self._drate_config(spi, input, data_rate)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), AD control (gain), and changing multiplexer
|
|
(Some(status), Some(ad_control), None) => {
|
|
self._status_ad_config(spi, input, status, ad_control)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), data rate, and changing multiplexer
|
|
(Some(status), None, Some(data_rate)) => {
|
|
self._status_drate_config(spi, input, status, data_rate)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying AD control (gain), data rate, and changing multiplexer
|
|
(None, Some(ad_control), Some(data_rate)) => {
|
|
self._ad_drate_config(spi, input, ad_control, data_rate)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), AD control (gain), data rate, and changing
|
|
// multiplexer
|
|
(Some(status), Some(ad_control), Some(data_rate)) => {
|
|
self._all_config(spi, input, status, ad_control, data_rate)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Functionally the same as [Ads1256::loadcal_convert] but exercises fine-grained control
|
|
/// over the [Mutex] of a [SpiBus] in cases where one is used. This function will unlock the
|
|
/// [Mutex] while it is waiting for data from the ADS1256.
|
|
///
|
|
/// Action sequence:
|
|
/// 1. Switch inputs and optionally adjust different configuration parameters.
|
|
/// 1. Issue sync command followed by wakeup command
|
|
/// 1. Wait for data_ready low
|
|
/// 1. RDATA command (read the conversion value)
|
|
/// 1. Optionally enter standby mode
|
|
///
|
|
/// **WARNING:** Auto-calibration must be disabled for intended functionality when changing
|
|
/// [Status], [AdControl], or [DataRate].
|
|
#[inline]
|
|
pub async fn loadcal_convert_m<MutexT: RawMutex, SpiT: SpiBus>(
|
|
&mut self,
|
|
spi_mutex: &Mutex<MutexT, SpiT>,
|
|
input: Multiplexer,
|
|
calibration: Option<&CalibrationCommand>,
|
|
status: Option<Status>,
|
|
ad_control: Option<AdControl>,
|
|
data_rate: Option<DataRate>,
|
|
standby: bool,
|
|
) -> Result<Conversion, <SpiT as spi::ErrorType>::Error> {
|
|
// Acquire SPI lock
|
|
let mut spi_guard = spi_mutex.lock().await;
|
|
let spi = spi_guard.deref_mut();
|
|
// Slave select low
|
|
self.slave_select.set_low().expect(GPIO_ERROR_MSG);
|
|
match (status, ad_control, data_rate) {
|
|
// Only modifying the multiplexer, not changing any configuration
|
|
(None, None, None) => {
|
|
self._none_config(spi, input)?;
|
|
self._manual_conversion_init(spi)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer) and changing multiplexer
|
|
(Some(status), None, None) => {
|
|
self._status_config(spi, input, status)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying AD control (gain) and changing multiplexer
|
|
(None, Some(ad_control), None) => {
|
|
self._ad_config(spi, input, ad_control)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying data rate and change multiplexer
|
|
(None, None, Some(data_rate)) => {
|
|
self._drate_config(spi, input, data_rate)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), AD control (gain), and changing multiplexer
|
|
(Some(status), Some(ad_control), None) => {
|
|
self._status_ad_config(spi, input, status, ad_control)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), data rate, and changing multiplexer
|
|
(Some(status), None, Some(data_rate)) => {
|
|
self._status_drate_config(spi, input, status, data_rate)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying AD control (gain), data rate, and changing multiplexer
|
|
(None, Some(ad_control), Some(data_rate)) => {
|
|
self._ad_drate_config(spi, input, ad_control, data_rate)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
// Modifying status (toggle buffer), AD control (gain), data rate, and changing
|
|
// multiplexer
|
|
(Some(status), Some(ad_control), Some(data_rate)) => {
|
|
self._all_config(spi, input, status, ad_control, data_rate)?;
|
|
self._loadcal_init(spi, calibration)?;
|
|
spi.flush()?;
|
|
drop(spi_guard);
|
|
self._read_when_rdy_m(spi_mutex, standby).await
|
|
},
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub async fn loadcal_convert_next_m<MutexT: RawMutex, SpiT: SpiBus>(
|
|
&mut self,
|
|
spi_mutex: &Mutex<MutexT, SpiT>,
|
|
next_input: Multiplexer,
|
|
next_calibration: Option<&CalibrationCommand>,
|
|
next_status: Option<Status>,
|
|
next_ad_control: Option<AdControl>,
|
|
next_data_rate: Option<DataRate>,
|
|
standby: bool,
|
|
) -> Result<Conversion, <SpiT as spi::ErrorType>::Error> {
|
|
self.data_ready.wait_for_low().await.expect(GPIO_ERROR_MSG);
|
|
self._loadcal_convert_next(
|
|
spi_mutex.lock().await.deref_mut(),
|
|
next_input,
|
|
next_calibration,
|
|
next_status,
|
|
next_ad_control,
|
|
next_data_rate,
|
|
standby,
|
|
)
|
|
.await
|
|
}
|
|
|
|
#[inline]
|
|
async fn _read_when_rdy_m<MutexT: RawMutex, SpiT: SpiBus>(
|
|
&mut self,
|
|
spi_mutex: &Mutex<MutexT, SpiT>,
|
|
standby: bool,
|
|
) -> Result<Conversion, <SpiT as spi::ErrorType>::Error> {
|
|
self.slave_select.set_high().expect(GPIO_ERROR_MSG);
|
|
// Wait for data ready low
|
|
self.data_ready.wait_for_low().await.expect(GPIO_ERROR_MSG);
|
|
self.slave_select.set_low().expect(GPIO_ERROR_MSG);
|
|
// Reacquire lock on SPI mutex and read mux conversion
|
|
self._read_mux_conversion(spi_mutex.lock().await.deref_mut(), standby)
|
|
}
|
|
}
|