diff --git a/src/spi/mod.rs b/src/spi/mod.rs index 80e5f3a..f75e2db 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -142,6 +142,8 @@ pub struct Config { pub frequency: Hertz, /// Timings pub timing: Timings, + // Half-duplex mode + half_duplex: bool, } impl Default for Config { @@ -151,6 +153,7 @@ impl Default for Config { mode: MODE_0, frequency: Hertz(10_000_000), timing: Timings::default(), + half_duplex: false, } } } @@ -253,6 +256,36 @@ impl<'d> Spi<'d, Blocking> { ) } + pub fn new_blocking_half_duplex( + peri: impl Peripheral

+ 'd, + sclk: impl Peripheral

> + 'd, + mosi: impl Peripheral

> + 'd, + mut config: Config, + ) -> Self { + into_ref!(sclk, mosi); + + T::add_resource_group(0); + + mosi.set_as_alt(mosi.alt_num()); + sclk.ioc_pad().func_ctl().modify(|w| { + w.set_alt_select(sclk.alt_num()); + w.set_loop_back(true); + }); + config.half_duplex = true; + + Self::new_inner( + peri, + Some(sclk.map_into()), + Some(mosi.map_into()), + None, + None, + None, + None, + None, + config, + ) + } + pub fn new_blocking_rxonly( peri: impl Peripheral

+ 'd, sclk: impl Peripheral

> + 'd, @@ -406,6 +439,39 @@ impl<'d> Spi<'d, Async> { ) } + pub fn new_half_duplex( + peri: impl Peripheral

+ 'd, + sclk: impl Peripheral

> + 'd, + mosi: impl Peripheral

> + 'd, + tx_dma: impl Peripheral

> + 'd, + rx_dma: impl Peripheral

> + 'd, + mut config: Config, + ) -> Self { + into_ref!(sclk, mosi); + + T::add_resource_group(0); + + mosi.set_as_alt(mosi.alt_num()); + sclk.ioc_pad().func_ctl().modify(|w| { + w.set_alt_select(sclk.alt_num()); + w.set_loop_back(true); + }); + + config.half_duplex = true; + + Self::new_inner( + peri, + Some(sclk.map_into()), + Some(mosi.map_into()), + None, + None, + None, + new_dma!(tx_dma), + new_dma!(rx_dma), + config, + ) + } + pub fn new_rxonly( peri: impl Peripheral

+ 'd, sclk: impl Peripheral

> + 'd, @@ -690,7 +756,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { // 32 bit data length only works when the data is 32bit aligned w.set_datalen(::CONFIG); w.set_datamerge(false); - w.set_mosibidir(false); + if config.half_duplex { + w.set_mosibidir(true); + } else { + w.set_mosibidir(false); + } w.set_lsb(config.bit_order == BitOrder::LsbFirst); w.set_slvmode(false); // default master mode w.set_cpha(cpha);