Add the possibility to reconfigure Spi mode and bit order configuration on the fly.
This commit is contained in:
parent
167af01211
commit
66e46d8012
@ -34,7 +34,8 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO move upwards in the tree
|
// TODO move upwards in the tree
|
||||||
pub enum ByteOrder {
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum BitOrder {
|
||||||
LsbFirst,
|
LsbFirst,
|
||||||
MsbFirst,
|
MsbFirst,
|
||||||
}
|
}
|
||||||
@ -88,16 +89,40 @@ impl WordSize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub byte_order: ByteOrder,
|
pub bit_order: BitOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
mode: MODE_0,
|
mode: MODE_0,
|
||||||
byte_order: ByteOrder::MsbFirst,
|
bit_order: BitOrder::MsbFirst,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
fn raw_phase(&self) -> vals::Cpha {
|
||||||
|
match self.mode.phase {
|
||||||
|
Phase::CaptureOnSecondTransition => vals::Cpha::SECONDEDGE,
|
||||||
|
Phase::CaptureOnFirstTransition => vals::Cpha::FIRSTEDGE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_polarity(&self) -> vals::Cpol {
|
||||||
|
match self.mode.polarity {
|
||||||
|
Polarity::IdleHigh => vals::Cpol::IDLEHIGH,
|
||||||
|
Polarity::IdleLow => vals::Cpol::IDLELOW,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_byte_order(&self) -> vals::Lsbfirst {
|
||||||
|
match self.bit_order {
|
||||||
|
BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST,
|
||||||
|
BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,24 +181,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
let pclk = T::frequency();
|
let pclk = T::frequency();
|
||||||
let br = compute_baud_rate(pclk, freq.into());
|
let br = compute_baud_rate(pclk, freq.into());
|
||||||
|
|
||||||
let cpha = match config.mode.phase {
|
let cpha = config.raw_phase();
|
||||||
Phase::CaptureOnSecondTransition => vals::Cpha::SECONDEDGE,
|
let cpol = config.raw_polarity();
|
||||||
Phase::CaptureOnFirstTransition => vals::Cpha::FIRSTEDGE,
|
|
||||||
};
|
|
||||||
let cpol = match config.mode.polarity {
|
|
||||||
Polarity::IdleHigh => vals::Cpol::IDLEHIGH,
|
|
||||||
Polarity::IdleLow => vals::Cpol::IDLELOW,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(spi_v3))]
|
let lsbfirst = config.raw_byte_order();
|
||||||
use vals::Lsbfirst;
|
|
||||||
#[cfg(spi_v3)]
|
|
||||||
use vals::Lsbfrst as Lsbfirst;
|
|
||||||
|
|
||||||
let lsbfirst = match config.byte_order {
|
|
||||||
ByteOrder::LsbFirst => Lsbfirst::LSBFIRST,
|
|
||||||
ByteOrder::MsbFirst => Lsbfirst::MSBFIRST,
|
|
||||||
};
|
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
@ -230,7 +241,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
w.set_ssoe(false);
|
w.set_ssoe(false);
|
||||||
w.set_cpha(cpha);
|
w.set_cpha(cpha);
|
||||||
w.set_cpol(cpol);
|
w.set_cpol(cpol);
|
||||||
w.set_lsbfrst(lsbfirst);
|
w.set_lsbfirst(lsbfirst);
|
||||||
w.set_ssm(true);
|
w.set_ssm(true);
|
||||||
w.set_master(vals::Master::MASTER);
|
w.set_master(vals::Master::MASTER);
|
||||||
w.set_comm(vals::Comm::FULLDUPLEX);
|
w.set_comm(vals::Comm::FULLDUPLEX);
|
||||||
@ -266,6 +277,60 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reconfigures it with the supplied config.
|
||||||
|
pub fn reconfigure(&mut self, config: Config) {
|
||||||
|
let cpha = config.raw_phase();
|
||||||
|
let cpol = config.raw_polarity();
|
||||||
|
|
||||||
|
let lsbfirst = config.raw_byte_order();
|
||||||
|
|
||||||
|
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
||||||
|
unsafe {
|
||||||
|
T::regs().cr1().modify(|w| {
|
||||||
|
w.set_cpha(cpha);
|
||||||
|
w.set_cpol(cpol);
|
||||||
|
w.set_lsbfirst(lsbfirst);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(spi_v3)]
|
||||||
|
unsafe {
|
||||||
|
T::regs().cfg2().modify(|w| {
|
||||||
|
w.set_cpha(cpha);
|
||||||
|
w.set_cpol(cpol);
|
||||||
|
w.set_lsbfirst(lsbfirst);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_config(&self) -> Config {
|
||||||
|
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
||||||
|
let cfg = unsafe { T::regs().cr1().read() };
|
||||||
|
#[cfg(spi_v3)]
|
||||||
|
let cfg = unsafe { T::regs().cfg2().read() };
|
||||||
|
let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
|
||||||
|
Polarity::IdleLow
|
||||||
|
} else {
|
||||||
|
Polarity::IdleHigh
|
||||||
|
};
|
||||||
|
let phase = if cfg.cpha() == vals::Cpha::FIRSTEDGE {
|
||||||
|
Phase::CaptureOnFirstTransition
|
||||||
|
} else {
|
||||||
|
Phase::CaptureOnSecondTransition
|
||||||
|
};
|
||||||
|
|
||||||
|
let bit_order = if cfg.lsbfirst() == vals::Lsbfirst::LSBFIRST {
|
||||||
|
BitOrder::LsbFirst
|
||||||
|
} else {
|
||||||
|
BitOrder::MsbFirst
|
||||||
|
};
|
||||||
|
|
||||||
|
Config {
|
||||||
|
mode: Mode { polarity, phase },
|
||||||
|
bit_order,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_word_size(&mut self, word_size: WordSize) {
|
fn set_word_size(&mut self, word_size: WordSize) {
|
||||||
if self.current_word_size == word_size {
|
if self.current_word_size == word_size {
|
||||||
return;
|
return;
|
||||||
|
@ -82,7 +82,7 @@ use crate::{
|
|||||||
pac,
|
pac,
|
||||||
peripherals::SUBGHZSPI,
|
peripherals::SUBGHZSPI,
|
||||||
rcc::sealed::RccPeripheral,
|
rcc::sealed::RccPeripheral,
|
||||||
spi::{ByteOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi},
|
spi::{BitOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi},
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
};
|
};
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
@ -233,7 +233,7 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> {
|
|||||||
let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000));
|
let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000));
|
||||||
let mut config = SpiConfig::default();
|
let mut config = SpiConfig::default();
|
||||||
config.mode = MODE_0;
|
config.mode = MODE_0;
|
||||||
config.byte_order = ByteOrder::MsbFirst;
|
config.bit_order = BitOrder::MsbFirst;
|
||||||
let spi = Spi::new(peri, sck, mosi, miso, txdma, rxdma, clk, config);
|
let spi = Spi::new(peri, sck, mosi, miso, txdma, rxdma, clk, config);
|
||||||
|
|
||||||
unsafe { wakeup() };
|
unsafe { wakeup() };
|
||||||
|
Loading…
Reference in New Issue
Block a user