imxrt_hal/common/
lpspi.rs

1//! Low-power serial peripheral interface.
2//!
3//! [`Lpspi`] implements select embedded HAL SPI traits for coordinating SPI I/O.
4//! When using the trait implementations, make sure that [`set_bit_order`](Lpspi::set_bit_order)
5//! is correct for your device. These settings apply when the driver internally defines the transaction.
6//!
7//! This driver also exposes the peripheral's lower-level, hardware-dependent transaction interface.
8//! Create a [`Transaction`], then [`enqueue_transaction`](Lpspi::enqueue_transaction) before
9//! sending data with [`enqueue_data`](Lpspi::enqueue_data). When using the transaction interface,
10//! you're responsible for serializing your data into `u32` SPI words.
11//!
12//! # Chip selects (CS) for SPI peripherals
13//!
14//! The iMXRT SPI peripherals have one or more peripheral-controlled chip selects (CS). Using
15//! the peripheral-controlled CS means that you do not need a GPIO to coordinate SPI operations.
16//! Blocking full-duplex transfers and writes will observe an asserted chip select while data
17//! frames are exchanged / written.
18//!
19//! This driver generally assumes that you're using the peripheral-controlled chip select. If
20//! you instead want to manage chip select in software, you should be able to multiplex your own
21//! pins, then construct the driver [`without_pins`](Lpspi::without_pins).
22//!
23//! # Device support
24//!
25//! By default, the driver behaves as a SPI controller, coordinating I/O for other SPI peripherals.
26//! To behave like a peripheral, use [`set_peripheral_enable`](Disabled::set_peripheral_enable).
27//!
28//! As of this writing, you're expected to use the lower-level interface to perform device I/O.
29//!
30//! # Example
31//!
32//! Initialize an LPSPI controller with a 1MHz SCK. To understand how to configure the LPSPI
33//! peripheral clock, see the [`ccm::lpspi_clk`](crate::ccm::lpspi_clk) documentation.
34//!
35//! ```no_run
36//! use imxrt_hal as hal;
37//! use imxrt_ral as ral;
38//! # use eh02 as embedded_hal;
39//! use embedded_hal::blocking::spi::Transfer;
40//! use hal::lpspi::{Lpspi, Pins, SamplePoint};
41//! use ral::lpspi::LPSPI4;
42//!
43//! let mut pads = // Handle to all processor pads...
44//!     # unsafe { imxrt_iomuxc::imxrt1060::Pads::new() };
45//!
46//! # || -> Option<()> {
47//! let spi_pins = Pins {
48//!     sdo: pads.gpio_b0.p02,
49//!     sdi: pads.gpio_b0.p01,
50//!     sck: pads.gpio_b0.p03,
51//!     pcs0: pads.gpio_b0.p00,
52//! };
53//!
54//! let mut spi4 = unsafe { LPSPI4::instance() };
55//! let mut spi = Lpspi::new(
56//!     spi4,
57//!     spi_pins,
58//! );
59//!
60//! # const LPSPI_CLK_HZ: u32 = 1;
61//! spi.disabled(|spi| {
62//!     spi.set_clock_hz(LPSPI_CLK_HZ, 1_000_000);
63//!     spi.set_sample_point(SamplePoint::Edge);
64//! });
65//!
66//! let mut buffer: [u8; 3] = [1, 2, 3];
67//! spi.transfer(&mut buffer).ok()?;
68//!
69//! let (spi4, pins) = spi.release();
70//!
71//! // Re-construct without pins:
72//! let mut spi = Lpspi::without_pins(spi4);
73//! # Some(()) }();
74//! ```
75//!
76//! # Limitations
77//!
78//! Due to [a hardware defect][1], this driver does not yet support the EH02 SPI transaction API.
79//! An early iteration of this driver reproduced the issue discussed in that forum. This driver may
80//! be able to work around the defect in software, but it hasn't been explored.
81//!
82//! [1]: https://community.nxp.com/t5/i-MX-RT/RT1050-LPSPI-last-bit-not-completing-in-continuous-mode/m-p/898460
83//!
84//! [`Transaction`] exposes the continuous / continuing flags, so you're free to model advanced
85//! transactions. However, keep in mind that disabling the receiver during a continuous transaction
86//! may not work as expected.
87
88use core::marker::PhantomData;
89use core::task::Poll;
90
91use crate::iomuxc::{consts, lpspi};
92use crate::ral;
93
94pub use eh02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
95
96/// Data direction.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum Direction {
99    /// Transmit direction (leaving the peripheral).
100    Tx,
101    /// Receive direction (entering the peripheral).
102    Rx,
103}
104
105/// Bit order.
106#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
107#[repr(u32)]
108pub enum BitOrder {
109    /// Data is transferred most significant bit first (default).
110    #[default]
111    Msb,
112    /// Data is transferred least significant bit first.
113    Lsb,
114}
115
116/// Receive sample point behavior.
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum SamplePoint {
119    /// Input data is sampled on SCK edge.
120    Edge,
121    /// Input data is sampled on delayed SCK edge.
122    DelayedEdge,
123}
124
125/// Possible errors when interfacing the LPSPI.
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum LpspiError {
128    /// The transaction frame size is incorrect.
129    ///
130    /// The frame size, in bits, must be between 8 bits and
131    /// 4095 bits.
132    FrameSize,
133    /// FIFO error in the given direction.
134    Fifo(Direction),
135    /// Bus is busy at the start of a transfer.
136    Busy,
137    /// Caller provided no data.
138    NoData,
139}
140
141/// An LPSPI transaction definition.
142///
143/// The transaction defines how many bits the driver sends or recieves.
144/// It also describes
145///
146/// - endianness
147/// - bit order
148/// - transmit and receive masking
149/// - continuous and continuing transfers (default: both disabled)
150///
151/// The LPSPI enqueues the transaction data into the transmit
152/// FIFO. When it pops the values from the FIFO, the values take
153/// effect immediately. This may affect, or abort, any ongoing
154/// transactions. Consult the reference manual to understand when
155/// you should enqueue transaction definitions, since it may only
156/// be supported on word / frame boundaries.
157///
158/// Construct `Transaction` with [`new`](Self::new), and supply
159/// the number of **bits** to transmit per frame.
160///
161/// ```
162/// use imxrt_hal as hal;
163/// use hal::lpspi::Transaction;
164///
165/// // Send one u32.
166/// let mut transaction
167///     = Transaction::new(8 * core::mem::size_of::<u32>() as u16);
168/// ```
169///
170/// Once constructed, manipulate the public members to change the
171/// configuration.
172///
173/// # Continuous transactions
174///
175/// The pseudo-code below shows how to set [`continuous`](Self::continuous) and
176/// [`continuing`](Self::continuing) to model a continuous transaction. Keep in
177/// mind the hardware limitations; see the [module-level docs](crate::lpspi#limitations) for
178/// details.
179///
180/// ```
181/// use imxrt_hal as hal;
182/// use hal::lpspi::Transaction;
183///
184/// // Skipping LPSPI initialization; see module-level example.
185///
186/// // Start byte exchange as a continuous transaction. Each frame
187/// // exchanges one byte (eight bits) with a device.
188/// # || -> Result<(), hal::lpspi::LpspiError> {
189/// let mut transaction = Transaction::new(8)?;
190/// transaction.continuous = true;
191/// // Enqueue transaction with LPSPI...
192/// // Enqueue one byte with LPSPI...   <-- PCS asserts here.
193///
194/// # let buffer: [u8; 5] = [0; 5];
195/// for byte in buffer {
196///     // Set 'continuing' to indicate that the next
197///     // transaction continues the previous one...
198///     transaction.continuing = true;
199///
200///     // Enqueue transaction with LPSPI...
201///     // Enqueue byte with LPSPI...
202/// }
203///
204/// transaction.continuous = false;
205/// transaction.continuing = false;
206/// // Enqueue transaction with LPSPI... <-- PCS de-asserts here.
207/// # Ok(()) }().unwrap();
208/// ```
209pub struct Transaction {
210    /// Enable byte swap.
211    ///
212    /// When enabled (`true`), swap bytes within the `u32` word. This allows
213    /// you to change the endianness of the 32-bit word transfer. The
214    /// default is `false`.
215    pub byte_swap: bool,
216    /// Bit order.
217    ///
218    /// See [`BitOrder`] for details. The default is [`BitOrder::Msb`].
219    pub bit_order: BitOrder,
220    /// Mask the received data.
221    ///
222    /// If `true`, the peripheral discards received data. Use this
223    /// when you only care about sending data. The default is `false`;
224    /// the peripheral puts received data in the receive FIFO.
225    pub receive_data_mask: bool,
226    /// Mask the transmit data.
227    ///
228    /// If `true`, the peripheral doesn't send any data. Use this when
229    /// you only care about receiving data. The default is `false`;
230    /// the peripheral expects to send data using the transmit FIFO.
231    pub transmit_data_mask: bool,
232    /// Indicates (`true`) the start of a continuous transfer.
233    ///
234    /// If set, the peripherals chip select will remain asserted after
235    /// exchanging the frame. This allows you to enqueue new commands
236    /// and data words within the same transaction. Those new commands
237    /// should have [`continuing`](Self::continuing) set to `true`.
238    ///
239    /// The default is `false`; chip select de-asserts after exchanging
240    /// the frame. To stop a continuous transfer, enqueue a new `Transaction`
241    /// in which this flag, and `continuing`, is false.
242    pub continuous: bool,
243    /// Indicates (`true`) that this command belongs to a previous transaction.
244    ///
245    /// Set this to indicate that this new `Transaction` belongs to a previous
246    /// `Transaction`, one that had [`continuous`](Self::continuous) set.
247    /// The default value is `false`.
248    pub continuing: bool,
249
250    frame_size: u16,
251}
252
253impl Transaction {
254    /// Defines a transaction for a `u32` buffer.
255    ///
256    /// After successfully defining a transaction of this buffer,
257    /// supply it to the LPSPI driver, then start sending the
258    /// data.
259    ///
260    /// Returns an error if any are true:
261    ///
262    /// - the buffer is empty.
263    /// - there's more than 128 elements in the buffer.
264    pub fn new_u32s(data: &[u32]) -> Result<Self, LpspiError> {
265        Transaction::new_words(data)
266    }
267
268    fn new_words<W>(data: &[W]) -> Result<Self, LpspiError> {
269        if let Ok(frame_size) = u16::try_from(8 * core::mem::size_of_val(data)) {
270            Transaction::new(frame_size)
271        } else {
272            Err(LpspiError::FrameSize)
273        }
274    }
275
276    fn frame_size_valid(frame_size: u16) -> bool {
277        const MIN_FRAME_SIZE: u16 = 8;
278        const MAX_FRAME_SIZE: u16 = 1 << 12;
279        const WORD_SIZE: u16 = 32;
280
281        let last_frame_size = frame_size % WORD_SIZE;
282
283        (MIN_FRAME_SIZE..=MAX_FRAME_SIZE).contains(&frame_size) && (1 != last_frame_size)
284    }
285
286    /// Define a transaction by specifying the frame size, in bits.
287    ///
288    /// The frame size describes the number of bits that will be transferred and
289    /// received during the next transaction. Specifically, it describes the number
290    /// of bits for which the PCS pin signals a transaction.
291    ///
292    /// # Requirements
293    ///
294    /// - `frame_size` fits within 12 bits; the implementation enforces this maximum value.
295    /// - The minimum value for `frame_size` is 8; the implementation enforces this minimum
296    ///   value.
297    /// - The last 32-bit word in the frame is at least 2 bits long.
298    pub fn new(frame_size: u16) -> Result<Self, LpspiError> {
299        if Self::frame_size_valid(frame_size) {
300            Ok(Self {
301                byte_swap: false,
302                bit_order: Default::default(),
303                receive_data_mask: false,
304                transmit_data_mask: false,
305                frame_size: frame_size - 1,
306                continuing: false,
307                continuous: false,
308            })
309        } else {
310            Err(LpspiError::FrameSize)
311        }
312    }
313}
314
315/// Sets the clock speed parameters.
316///
317/// This should only happen when the LPSPI peripheral is disabled.
318fn set_spi_clock(source_clock_hz: u32, spi_clock_hz: u32, reg: &ral::lpspi::RegisterBlock) {
319    // Round up, so we always get a resulting SPI clock that is
320    // equal or less than the requested frequency.
321    let half_div =
322        u32::try_from(1 + u64::from(source_clock_hz - 1) / (u64::from(spi_clock_hz) * 2)).unwrap();
323
324    // Make sure SCKDIV is between 0 and 255
325    // For some reason SCK starts to misbehave in between frames
326    // if half_div is less than 3.
327    let half_div = half_div.clamp(3, 128);
328    // Because half_div is in range [3,128], sckdiv is in range [4, 254].
329    let sckdiv = 2 * (half_div - 1);
330
331    ral::write_reg!(ral::lpspi, reg, CCR,
332        // Delay between two clock transitions of two consecutive transfers
333        // is exactly sckdiv/2, which causes the transfer to be seamless.
334        DBT: half_div - 1,
335        // Add one sckdiv/2 setup and hold time before and after the transfer,
336        // to make sure the signal is stable at sample time
337        PCSSCK: half_div - 1,
338        SCKPCS: half_div - 1,
339        SCKDIV: sckdiv
340    );
341}
342
343/// LPSPI clock configurations.
344///
345/// This is a low-level API. You should prefer [`set_clock_hz`](Disabled::set_clock_hz)
346/// if you're not sure how to use these configurations.
347///
348/// All delays and dividers are in terms of the LPSPI functional clock cycles. They're
349/// written directly to the corresponding clock configuration register fields. See inline
350/// documentation to understand what values of zero represent.
351#[derive(Clone, Copy, PartialEq, Eq)]
352pub struct ClockConfigs {
353    /// SCK-to-PCS delay.
354    ///
355    /// This value is off-by-one: a value of zero indicates one cycle.
356    pub sckpcs: u8,
357    /// PCS-to-SCK delay.
358    ///
359    /// This value is off-by-one: a value of zero indicates one cycle.
360    pub pcssck: u8,
361    /// Delay between transfers.
362    ///
363    /// For normal transactions, this affects the PCS negation duration. In this
364    /// configuration, this value is off-by-two: a value of zero indicates two cycle.
365    ///
366    /// For continuous transactions, this affects the clock delay between words.
367    /// In this configuration, this value is off-by-one.
368    pub dbt: u8,
369    /// SCK divider.
370    ///
371    /// This value is off-by-two: a value of zero indicates two cycles.
372    pub sckdiv: u8,
373}
374
375/// An LPSPI driver.
376///
377/// The driver exposes low-level methods for coordinating
378/// DMA transfers. However, you may find it easier to use the
379/// [`dma`](crate::dma) interface to coordinate DMA transfers.
380///
381/// The driver implements `embedded-hal` SPI traits. You should prefer
382/// these implementations for their ease of use.
383///
384/// See the [module-level documentation](crate::lpspi) for an example
385/// of how to construct this driver.
386pub struct Lpspi<P, const N: u8> {
387    lpspi: ral::lpspi::Instance<N>,
388    pins: P,
389    bit_order: BitOrder,
390    mode: Mode,
391}
392
393/// Pins for a LPSPI device.
394///
395/// Consider using type aliases to simplify your usage:
396///
397/// ```no_run
398/// use imxrt_hal as hal;
399/// use imxrt_iomuxc::imxrt1060::gpio_b0::*;
400///
401/// // SPI pins used in my application
402/// type LpspiPins = hal::lpspi::Pins<
403///     GPIO_B0_02,
404///     GPIO_B0_01,
405///     GPIO_B0_03,
406///     GPIO_B0_00,
407/// >;
408///
409/// // Helper type for your SPI peripheral
410/// type Lpspi<const N: u8> = hal::lpspi::Lpspi<LpspiPins, N>;
411/// ```
412pub struct Pins<SDO, SDI, SCK, PCS0> {
413    /// Serial data out
414    ///
415    /// Data travels from the SPI host controller to the SPI device.
416    pub sdo: SDO,
417    /// Serial data in
418    ///
419    /// Data travels from the SPI device to the SPI host controller.
420    pub sdi: SDI,
421    /// Serial clock
422    pub sck: SCK,
423    /// Chip select 0
424    ///
425    /// (PCSx) convention matches the hardware.
426    pub pcs0: PCS0,
427}
428
429impl<SDO, SDI, SCK, PCS0, const N: u8> Lpspi<Pins<SDO, SDI, SCK, PCS0>, N>
430where
431    SDO: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sdo>,
432    SDI: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sdi>,
433    SCK: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Sck>,
434    PCS0: lpspi::Pin<Module = consts::Const<N>, Signal = lpspi::Pcs0>,
435{
436    /// Create a new LPSPI driver from the RAL LPSPI instance and a set of pins.
437    ///
438    /// When this call returns, the LPSPI pins are configured for their function.
439    /// The peripheral is enabled after reset. The LPSPI clock speed is unspecified.
440    /// The mode is [`MODE_0`]. The sample point is [`SamplePoint::DelayedEdge`].
441    pub fn new(lpspi: ral::lpspi::Instance<N>, mut pins: Pins<SDO, SDI, SCK, PCS0>) -> Self {
442        lpspi::prepare(&mut pins.sdo);
443        lpspi::prepare(&mut pins.sdi);
444        lpspi::prepare(&mut pins.sck);
445        lpspi::prepare(&mut pins.pcs0);
446        Self::init(lpspi, pins)
447    }
448}
449
450impl<const N: u8> Lpspi<(), N> {
451    /// Create a new LPSPI driver from the RAL LPSPI instance.
452    ///
453    /// This is similar to [`new()`](Self::new), but it does not configure
454    /// pins. You're responsible for configuring pins, and for making sure
455    /// the pin configuration doesn't change while this driver is in use.
456    pub fn without_pins(lpspi: ral::lpspi::Instance<N>) -> Self {
457        Self::init(lpspi, ())
458    }
459}
460
461impl<P, const N: u8> Lpspi<P, N> {
462    /// The peripheral instance.
463    pub const N: u8 = N;
464
465    fn init(lpspi: ral::lpspi::Instance<N>, pins: P) -> Self {
466        let spi = Lpspi {
467            lpspi,
468            pins,
469            bit_order: BitOrder::default(),
470            mode: MODE_0,
471        };
472
473        // Reset and disable
474        ral::modify_reg!(ral::lpspi, spi.lpspi, CR, MEN: MEN_0, RST: RST_1);
475        while spi.is_enabled() {}
476        ral::modify_reg!(ral::lpspi, spi.lpspi, CR, RST: RST_0);
477
478        // Reset Fifos
479        ral::modify_reg!(ral::lpspi, spi.lpspi, CR, RTF: RTF_1, RRF: RRF_1);
480
481        // Configure master mode
482        ral::write_reg!(
483            ral::lpspi,
484            spi.lpspi,
485            CFGR1,
486            MASTER: MASTER_1,
487            SAMPLE: SAMPLE_1
488        );
489
490        let tx_fifo_size = spi.max_watermark(Direction::Tx);
491        // Configure watermarks
492        ral::write_reg!(ral::lpspi, spi.lpspi, FCR,
493            RXWATER: 0,               // Notify when we have any data available
494            TXWATER: u32::from(tx_fifo_size) / 2 // Nofify when we have at least tx_fifo_size/2 space available
495        );
496
497        ral::write_reg!(ral::lpspi, spi.lpspi, CR, MEN: MEN_1);
498
499        spi
500    }
501
502    /// Indicates if the driver is (`true`) or is not (`false`) enabled.
503    pub fn is_enabled(&self) -> bool {
504        ral::read_reg!(ral::lpspi, self.lpspi, CR, MEN == MEN_1)
505    }
506
507    /// Enable (`true`) or disable (`false`) the peripheral.
508    ///
509    /// Note that disabling does not take effect immediately; instead the
510    /// peripheral finishes the current transfer and then disables itself.
511    /// It is required to check [`is_enabled()`](Self::is_enabled) repeatedly until the
512    /// peripheral is actually disabled.
513    pub fn set_enable(&mut self, enable: bool) {
514        ral::modify_reg!(ral::lpspi, self.lpspi, CR, MEN: enable as u32)
515    }
516
517    /// Reset the driver.
518    ///
519    /// Note that this may not not reset all peripheral state, like the
520    /// enabled state.
521    pub fn reset(&mut self) {
522        ral::modify_reg!(ral::lpspi, self.lpspi, CR, RST: RST_1);
523        while ral::read_reg!(ral::lpspi, self.lpspi, CR, RST == RST_1) {
524            ral::modify_reg!(ral::lpspi, self.lpspi, CR, RST: RST_0);
525        }
526    }
527
528    /// Release the SPI driver components.
529    ///
530    /// This does not change any component state; it releases the components as-is.
531    /// If you need to obtain the registers in a known, good state, consider calling
532    /// methods like [`reset()`](Self::reset) before releasing the registers.
533    pub fn release(self) -> (ral::lpspi::Instance<N>, P) {
534        (self.lpspi, self.pins)
535    }
536
537    /// Returns the bit order configuration.
538    ///
539    /// See notes in [`set_bit_order`](Lpspi::set_bit_order) to
540    /// understand when this configuration takes effect.
541    pub fn bit_order(&self) -> BitOrder {
542        self.bit_order
543    }
544
545    /// Set the bit order configuration.
546    ///
547    /// This applies to all higher-level write and transfer operations.
548    /// If you're using the [`Transaction`] API with manual word reads
549    /// and writes, set the configuration as part of the transaction.
550    pub fn set_bit_order(&mut self, bit_order: BitOrder) {
551        self.bit_order = bit_order;
552    }
553
554    /// Temporarily disable the LPSPI peripheral.
555    ///
556    /// The handle to a [`Disabled`](crate::lpspi::Disabled) driver lets you modify
557    /// LPSPI settings that require a fully disabled peripheral.
558    pub fn disabled<R>(&mut self, func: impl FnOnce(&mut Disabled<N>) -> R) -> R {
559        let mut disabled = Disabled::new(&mut self.lpspi, &mut self.mode);
560        func(&mut disabled)
561    }
562
563    /// Read the status register.
564    pub fn status(&self) -> Status {
565        Status::from_bits_truncate(ral::read_reg!(ral::lpspi, self.lpspi, SR))
566    }
567
568    /// Clear the status flags.
569    ///
570    /// To clear status flags, set them high, then call `clear_status()`.
571    ///
572    /// The implementation will ensure that only the W1C bits are written, so it's
573    /// OK to supply `Status::all()` to clear all bits.
574    pub fn clear_status(&self, flags: Status) {
575        let flags = flags & Status::W1C;
576        ral::write_reg!(ral::lpspi, self.lpspi, SR, flags.bits());
577    }
578
579    /// Read the interrupt enable bits.
580    pub fn interrupts(&self) -> Interrupts {
581        Interrupts::from_bits_truncate(ral::read_reg!(ral::lpspi, self.lpspi, IER))
582    }
583
584    /// Set the interrupt enable bits.
585    ///
586    /// This writes the bits described by `interrupts` as is to the register.
587    /// To modify the existing interrupts flags, you should first call [`interrupts`](Lpspi::interrupts)
588    /// to get the current state, then modify that state.
589    pub fn set_interrupts(&self, interrupts: Interrupts) {
590        ral::write_reg!(ral::lpspi, self.lpspi, IER, interrupts.bits());
591    }
592
593    /// Clear any existing data in the SPI receive or transfer FIFOs.
594    #[inline]
595    pub fn clear_fifo(&mut self, direction: Direction) {
596        match direction {
597            Direction::Tx => ral::modify_reg!(ral::lpspi, self.lpspi, CR, RTF: RTF_1),
598            Direction::Rx => ral::modify_reg!(ral::lpspi, self.lpspi, CR, RRF: RRF_1),
599        }
600    }
601
602    /// Clear both FIFOs.
603    pub fn clear_fifos(&mut self) {
604        ral::modify_reg!(ral::lpspi, self.lpspi, CR, RTF: RTF_1, RRF: RRF_1);
605    }
606
607    /// Returns the watermark level for the given direction.
608    #[inline]
609    pub fn watermark(&self, direction: Direction) -> u8 {
610        (match direction {
611            Direction::Rx => ral::read_reg!(ral::lpspi, self.lpspi, FCR, RXWATER),
612            Direction::Tx => ral::read_reg!(ral::lpspi, self.lpspi, FCR, TXWATER),
613        }) as u8
614    }
615
616    /// Returns the FIFO status.
617    #[inline]
618    pub fn fifo_status(&self) -> FifoStatus {
619        let (rxcount, txcount) = ral::read_reg!(ral::lpspi, self.lpspi, FSR, RXCOUNT, TXCOUNT);
620        FifoStatus {
621            rxcount: rxcount as u16,
622            txcount: txcount as u16,
623        }
624    }
625
626    /// Simply read whatever is in the receiver data register.
627    fn read_data_unchecked(&self) -> u32 {
628        ral::read_reg!(ral::lpspi, self.lpspi, RDR)
629    }
630
631    /// Read the data register.
632    ///
633    /// Returns `None` if the receive FIFO is empty. Otherwise, returns the complete
634    /// read of the register. You're reponsible for interpreting the raw value as
635    /// a data word, depending on the frame size.
636    pub fn read_data(&mut self) -> Option<u32> {
637        if ral::read_reg!(ral::lpspi, self.lpspi, RSR, RXEMPTY == RXEMPTY_0) {
638            Some(self.read_data_unchecked())
639        } else {
640            None
641        }
642    }
643
644    /// Place `word` into the transmit FIFO.
645    ///
646    /// This will result in the value being sent from the LPSPI.
647    /// You're responsible for making sure that the transmit FIFO can
648    /// fit this word.
649    pub fn enqueue_data(&self, word: u32) {
650        ral::write_reg!(ral::lpspi, self.lpspi, TDR, word);
651    }
652
653    /// Wait for transmit FIFO space in a (concurrent) spin loop.
654    ///
655    /// This future does not care about the TX FIFO watermark. Instead, it
656    /// checks the FIFO's size with an additional read.
657    pub(crate) async fn spin_for_fifo_space(&self) -> Result<(), LpspiError> {
658        core::future::poll_fn(|_| {
659            let status = self.status();
660            if status.intersects(Status::TRANSMIT_ERROR) {
661                return Poll::Ready(Err(LpspiError::Fifo(Direction::Tx)));
662            }
663            let fifo_status = self.fifo_status();
664            if !fifo_status.is_full(Direction::Tx) {
665                Poll::Ready(Ok(()))
666            } else {
667                Poll::Pending
668            }
669        })
670        .await
671    }
672
673    pub(crate) fn wait_for_transmit_fifo_space(&self) -> Result<(), LpspiError> {
674        crate::spin_on(self.spin_for_fifo_space())
675    }
676
677    /// Wait for receive data in a (concurrent) spin loop.
678    ///
679    /// This future does not care about the RX FIFO watermark. Instead, it
680    /// checks the FIFO's size with an additional read.
681    async fn spin_for_word(&self) -> Result<u32, LpspiError> {
682        core::future::poll_fn(|_| {
683            let status = self.status();
684            if status.intersects(Status::RECEIVE_ERROR) {
685                return Poll::Ready(Err(LpspiError::Fifo(Direction::Rx)));
686            }
687
688            let fifo_status = self.fifo_status();
689            if !fifo_status.is_empty(Direction::Rx) {
690                let data = self.read_data_unchecked();
691                Poll::Ready(Ok(data))
692            } else {
693                Poll::Pending
694            }
695        })
696        .await
697    }
698
699    /// Send `len` LPSPI words (u32s) out of the peripheral.
700    ///
701    /// Expected to run in a (concurrent) spin loop, possibly with
702    /// `spin_receive`.
703    async fn spin_transmit(
704        &self,
705        mut data: impl TransmitData,
706        len: usize,
707    ) -> Result<(), LpspiError> {
708        for _ in 0..len {
709            self.spin_for_fifo_space().await?;
710            let word = data.next_word(self.bit_order);
711            self.enqueue_data(word);
712        }
713        Ok(())
714    }
715
716    /// Accept `len` LPSPI words (u32s) from the peripheral.
717    ///
718    /// Expected to run in a (concurrent) spin loop, possibly with
719    /// `spin_transmit`.
720    async fn spin_receive(&self, mut data: impl ReceiveData, len: usize) -> Result<(), LpspiError> {
721        for _ in 0..len {
722            let word = self.spin_for_word().await?;
723            data.next_word(self.bit_order, word);
724        }
725        Ok(())
726    }
727
728    /// Set the SPI mode for the peripheral.
729    ///
730    /// This only affects the next transfer; ongoing transfers
731    /// will not be influenced.
732    pub fn set_mode(&mut self, mode: Mode) {
733        self.mode = mode;
734    }
735
736    /// Place a transaction definition into the transmit FIFO.
737    ///
738    /// Once this definition is popped from the transmit FIFO, this may
739    /// affect, or abort, any ongoing transactions.
740    ///
741    /// You're responsible for making sure there's space in the transmit
742    /// FIFO for this transaction command.
743    pub fn enqueue_transaction(&mut self, transaction: &Transaction) {
744        ral::write_reg!(ral::lpspi, self.lpspi, TCR,
745            CPOL: if self.mode.polarity == Polarity::IdleHigh { CPOL_1 } else { CPOL_0 },
746            CPHA: if self.mode.phase == Phase::CaptureOnSecondTransition { CPHA_1 } else { CPHA_0 },
747            PRESCALE: PRESCALE_0,
748            PCS: PCS_0,
749            WIDTH: WIDTH_0,
750            LSBF: transaction.bit_order as u32,
751            BYSW: transaction.byte_swap as u32,
752            RXMSK: transaction.receive_data_mask as u32,
753            TXMSK: transaction.transmit_data_mask as u32,
754            FRAMESZ: transaction.frame_size as u32,
755            CONT: transaction.continuous as u32,
756            CONTC: transaction.continuing as u32
757        );
758    }
759
760    /// Wait for all ongoing transactions to be finished.
761    pub fn flush(&mut self) -> Result<(), LpspiError> {
762        loop {
763            let status = self.status();
764
765            if status.intersects(Status::RECEIVE_ERROR) {
766                return Err(LpspiError::Fifo(Direction::Rx));
767            }
768            if status.intersects(Status::TRANSMIT_ERROR) {
769                return Err(LpspiError::Fifo(Direction::Tx));
770            }
771
772            // Contributor testing reveals that the busy flag may not set once
773            // the TX FIFO is filled. This means a sequence like
774            //
775            //     lpspi.write(&[...])?;
776            //     lpspi.flush()?;
777            //
778            // could pass through flush without observing busy. Therefore, we
779            // also check the FIFO contents. Even if the peripheral isn't
780            // busy, the FIFO should be non-empty.
781            //
782            // We can't just rely on the FIFO contents, since the FIFO could be
783            // empty while the transaction is completing. (There's data in the
784            // shift register, and PCS is still asserted.)
785            if !status.intersects(Status::BUSY) && self.fifo_status().is_empty(Direction::Tx) {
786                return Ok(());
787            }
788        }
789    }
790
791    fn exchange<W: Word>(&mut self, data: &mut [W]) -> Result<(), LpspiError> {
792        if data.is_empty() {
793            return Ok(());
794        }
795
796        let mut transaction = Transaction::new_words(data)?;
797        transaction.bit_order = self.bit_order();
798
799        self.wait_for_transmit_fifo_space()?;
800        self.enqueue_transaction(&transaction);
801
802        let word_count = word_count(data);
803        let (tx, rx) = transfer_in_place(data);
804
805        crate::spin_on(futures::future::try_join(
806            self.spin_transmit(tx, word_count),
807            self.spin_receive(rx, word_count),
808        ))
809        .inspect_err(|_| self.recover_from_error())?;
810
811        self.flush()?;
812
813        Ok(())
814    }
815
816    fn write_no_read<W: Word>(&mut self, data: &[W]) -> Result<(), LpspiError> {
817        if data.is_empty() {
818            return Ok(());
819        }
820
821        let mut transaction = Transaction::new_words(data)?;
822        transaction.receive_data_mask = true;
823        transaction.bit_order = self.bit_order();
824
825        self.wait_for_transmit_fifo_space()?;
826        self.enqueue_transaction(&transaction);
827
828        let word_count = word_count(data);
829        let tx = TransmitBuffer::new(data);
830
831        crate::spin_on(self.spin_transmit(tx, word_count)).inspect_err(|_| {
832            self.recover_from_error();
833        })?;
834
835        self.flush()?;
836
837        Ok(())
838    }
839
840    /// Let the peripheral act as a DMA source.
841    ///
842    /// After this call, the peripheral will signal to the DMA engine whenever
843    /// it has data available to read.
844    pub fn enable_dma_receive(&mut self) {
845        ral::modify_reg!(ral::lpspi, self.lpspi, FCR, RXWATER: 0); // No watermarks; affects DMA signaling
846        ral::modify_reg!(ral::lpspi, self.lpspi, DER, RDDE: 1);
847    }
848
849    /// Stop the peripheral from acting as a DMA source.
850    ///
851    /// See the DMA chapter in the reference manual to understand when this
852    /// should be called in the DMA transfer lifecycle.
853    pub fn disable_dma_receive(&mut self) {
854        while ral::read_reg!(ral::lpspi, self.lpspi, DER, RDDE == 1) {
855            ral::modify_reg!(ral::lpspi, self.lpspi, DER, RDDE: 0);
856        }
857    }
858
859    /// Let the peripheral act as a DMA destination.
860    ///
861    /// After this call, the peripheral will signal to the DMA engine whenever
862    /// it has free space in its transfer buffer.
863    pub fn enable_dma_transmit(&mut self) {
864        ral::modify_reg!(ral::lpspi, self.lpspi, FCR, TXWATER: 0); // No watermarks; affects DMA signaling
865        ral::modify_reg!(ral::lpspi, self.lpspi, DER, TDDE: 1);
866    }
867
868    /// Stop the peripheral from acting as a DMA destination.
869    ///
870    /// See the DMA chapter in the reference manual to understand when this
871    /// should be called in the DMA transfer lifecycle.
872    pub fn disable_dma_transmit(&mut self) {
873        while ral::read_reg!(ral::lpspi, self.lpspi, DER, TDDE == 1) {
874            ral::modify_reg!(ral::lpspi, self.lpspi, DER, TDDE: 0);
875        }
876    }
877
878    /// Produces a pointer to the receiver data register.
879    ///
880    /// You should use this pointer when coordinating a DMA transfer.
881    /// You're not expected to read from this pointer in software.
882    pub fn rdr(&self) -> *const ral::RORegister<u32> {
883        core::ptr::addr_of!(self.lpspi.RDR)
884    }
885
886    /// Produces a pointer to the transfer data register.
887    ///
888    /// You should use this pointer when coordinating a DMA transfer.
889    /// You're not expected to read from this pointer in software.
890    pub fn tdr(&self) -> *const ral::WORegister<u32> {
891        core::ptr::addr_of!(self.lpspi.TDR)
892    }
893
894    fn max_watermark(&self, direction: Direction) -> u8 {
895        (match direction {
896            Direction::Rx => 1 << ral::read_reg!(ral::lpspi, self.lpspi, PARAM, RXFIFO),
897            Direction::Tx => 1 << ral::read_reg!(ral::lpspi, self.lpspi, PARAM, TXFIFO),
898        }) as u8
899    }
900
901    /// Reset all internal logic while preserving the driver's configurations.
902    ///
903    /// Unlike [`reset()`](Self::reset), this preserves all peripheral registers.
904    pub fn soft_reset(&mut self) {
905        // Backup previous registers
906        let ier = ral::read_reg!(ral::lpspi, self.lpspi, IER);
907        let der = ral::read_reg!(ral::lpspi, self.lpspi, DER);
908        let cfgr0 = ral::read_reg!(ral::lpspi, self.lpspi, CFGR0);
909        let cfgr1 = ral::read_reg!(ral::lpspi, self.lpspi, CFGR1);
910        let dmr0 = ral::read_reg!(ral::lpspi, self.lpspi, DMR0);
911        let dmr1 = ral::read_reg!(ral::lpspi, self.lpspi, DMR1);
912        let ccr = ral::read_reg!(ral::lpspi, self.lpspi, CCR);
913        let fcr = ral::read_reg!(ral::lpspi, self.lpspi, FCR);
914
915        // Backup enabled state
916        let enabled = self.is_enabled();
917
918        // Reset and disable
919        ral::modify_reg!(ral::lpspi, self.lpspi, CR, MEN: MEN_0, RST: RST_1);
920        while self.is_enabled() {}
921        ral::modify_reg!(ral::lpspi, self.lpspi, CR, RST: RST_0);
922
923        // Reset fifos
924        ral::modify_reg!(ral::lpspi, self.lpspi, CR, RTF: RTF_1, RRF: RRF_1);
925
926        // Restore settings
927        ral::write_reg!(ral::lpspi, self.lpspi, IER, ier);
928        ral::write_reg!(ral::lpspi, self.lpspi, DER, der);
929        ral::write_reg!(ral::lpspi, self.lpspi, CFGR0, cfgr0);
930        ral::write_reg!(ral::lpspi, self.lpspi, CFGR1, cfgr1);
931        ral::write_reg!(ral::lpspi, self.lpspi, DMR0, dmr0);
932        ral::write_reg!(ral::lpspi, self.lpspi, DMR1, dmr1);
933        ral::write_reg!(ral::lpspi, self.lpspi, CCR, ccr);
934        ral::write_reg!(ral::lpspi, self.lpspi, FCR, fcr);
935
936        // Restore enabled state
937        self.set_enable(enabled);
938    }
939
940    /// Set the watermark level for a given direction.
941    ///
942    /// Returns the watermark level committed to the hardware. This may be different
943    /// than the supplied `watermark`, since it's limited by the hardware.
944    ///
945    /// When `direction == Direction::Rx`, the receive data flag is set whenever the
946    /// number of words in the receive FIFO is greater than `watermark`.
947    ///
948    /// When `direction == Direction::Tx`, the transmit data flag is set whenever the
949    /// the number of words in the transmit FIFO is less than, or equal, to `watermark`.
950    #[inline]
951    pub fn set_watermark(&mut self, direction: Direction, watermark: u8) -> u8 {
952        set_watermark(&self.lpspi, direction, watermark)
953    }
954
955    /// Recover from a transaction error.
956    fn recover_from_error(&mut self) {
957        // Resets the peripheral and flushes whatever is in the FIFOs.
958        self.soft_reset();
959
960        // Reset the status flags, clearing the error condition for the next use.
961        self.clear_status(Status::TRANSMIT_ERROR | Status::RECEIVE_ERROR);
962    }
963
964    /// Return the driver's clock configurations.
965    ///
966    /// These values are decided by calls to [`set_clock_hz`](Disabled::set_clock_hz)
967    /// and [`set_clock_configs`](Disabled::set_clock_configs).
968    pub fn clock_configs(&self) -> ClockConfigs {
969        let (sckpcs, pcssck, dbt, sckdiv) =
970            ral::read_reg!(ral::lpspi, self.lpspi, CCR, SCKPCS, PCSSCK, DBT, SCKDIV);
971        ClockConfigs {
972            sckpcs: sckpcs as u8,
973            pcssck: pcssck as u8,
974            dbt: dbt as u8,
975            sckdiv: sckdiv as u8,
976        }
977    }
978}
979
980bitflags::bitflags! {
981    /// Status flags for the LPSPI interface.
982    pub struct Status : u32 {
983        /// Module busy flag.
984        ///
985        /// This flag is read only.
986        const BUSY = 1 << 24;
987
988        //
989        // Start W1C bits.
990        //
991
992        /// Data match flag.
993        ///
994        /// Indicates that received data has matched one or both of the match
995        /// fields. To clear this flag, write this bit to the status register
996        /// (W1C).
997        const DATA_MATCH = 1 << 13;
998        /// Receive error flag.
999        ///
1000        /// Set when the receive FIFO has overflowed. Before clearing this bit,
1001        /// empty the receive FIFO. Then, write this bit to clear the flag (W1C).
1002        const RECEIVE_ERROR = 1 << 12;
1003        /// Transmit error flag.
1004        ///
1005        /// Set when the transmit FIFO has underruns. Before clearing this bit,
1006        /// end the transfer. Then, write this bit to clear the flag (W1C).
1007        const TRANSMIT_ERROR = 1 << 11;
1008        /// Transfer complete flag.
1009        ///
1010        /// Set when the LPSPI returns to an idle state, and the transmit FIFO
1011        /// is empty. To clear this flag, write this bit (W1C).
1012        const TRANSFER_COMPLETE = 1 << 10;
1013        /// Frame complete flag.
1014        ///
1015        /// Set at the end of each frame transfer, when PCS negates. To clear this
1016        /// flag, write this bit (W1C).
1017        const FRAME_COMPLETE = 1 << 9;
1018        /// Word complete flag.
1019        ///
1020        /// Set when the last bit of a received word is sampled. To clear this flag, write
1021        /// this bit (W1C).
1022        const WORD_COMPLETE = 1 << 8;
1023
1024        //
1025        // End W1C bits.
1026        //
1027
1028        /// Receive data flag.
1029        ///
1030        /// Set when the number of words in the receive FIFO is greater than the watermark.
1031        /// This flag is read only. To clear the flag, exhaust the receive FIFO.
1032        const RECEIVE_DATA = 1 << 1;
1033        /// Transmit data flag.
1034        ///
1035        /// Set when the number of words in the transmit FIFO is less than or equal to the
1036        /// watermark. This flag is read only. TO clear the flag, fill the transmit FIFO.
1037        const TRANSMIT_DATA = 1 << 0;
1038    }
1039}
1040
1041impl Status {
1042    const W1C: Self = Self::from_bits_truncate(
1043        Self::DATA_MATCH.bits()
1044            | Self::RECEIVE_ERROR.bits()
1045            | Self::TRANSMIT_ERROR.bits()
1046            | Self::TRANSFER_COMPLETE.bits()
1047            | Self::FRAME_COMPLETE.bits()
1048            | Self::WORD_COMPLETE.bits(),
1049    );
1050}
1051
1052/// The number of words in each FIFO.
1053#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1054pub struct FifoStatus {
1055    /// Number of words in the receive FIFO.
1056    pub rxcount: u16,
1057    /// Number of words in the transmit FIFO.
1058    pub txcount: u16,
1059}
1060
1061impl FifoStatus {
1062    /// Indicates if the FIFO is full for the given direction.
1063    #[inline]
1064    pub const fn is_full(self, direction: Direction) -> bool {
1065        /// See PARAM register docs.
1066        const MAX_FIFO_SIZE: u16 = 16;
1067        let count = match direction {
1068            Direction::Tx => self.txcount,
1069            Direction::Rx => self.rxcount,
1070        };
1071        count >= MAX_FIFO_SIZE
1072    }
1073    /// Indicates if the FIFO is empty for the given direction.
1074    #[inline]
1075    const fn is_empty(self, direction: Direction) -> bool {
1076        0 == match direction {
1077            Direction::Tx => self.txcount,
1078            Direction::Rx => self.rxcount,
1079        }
1080    }
1081}
1082
1083bitflags::bitflags! {
1084    /// Interrupt flags.
1085    ///
1086    /// A high bit indicates that the condition generates an interrupt.
1087    /// See the status bits for more information.
1088    pub struct Interrupts : u32 {
1089        /// Data match interrupt enable.
1090        const DATA_MATCH = 1 << 13;
1091        /// Receive error interrupt enable.
1092        const RECEIVE_ERROR = 1 << 12;
1093        /// Transmit error interrupt enable.
1094        const TRANSMIT_ERROR = 1 << 11;
1095        /// Transmit complete interrupt enable.
1096        const TRANSMIT_COMPLETE = 1 << 10;
1097        /// Frame complete interrupt enable.
1098        const FRAME_COMPLETE = 1 << 9;
1099        /// Word complete interrupt enable.
1100        const WORD_COMPLETE = 1 << 8;
1101
1102        /// Receive data interrupt enable.
1103        const RECEIVE_DATA = 1 << 1;
1104        /// Transmit data interrupt enable.
1105        const TRANSMIT_DATA = 1 << 0;
1106    }
1107}
1108
1109#[inline]
1110fn set_watermark(lpspi: &ral::lpspi::RegisterBlock, direction: Direction, watermark: u8) -> u8 {
1111    let max_watermark = match direction {
1112        Direction::Rx => 1 << ral::read_reg!(ral::lpspi, lpspi, PARAM, RXFIFO),
1113        Direction::Tx => 1 << ral::read_reg!(ral::lpspi, lpspi, PARAM, TXFIFO),
1114    };
1115
1116    let watermark = watermark.min(max_watermark - 1);
1117
1118    match direction {
1119        Direction::Rx => {
1120            ral::modify_reg!(ral::lpspi, lpspi, FCR, RXWATER: watermark as u32)
1121        }
1122        Direction::Tx => {
1123            ral::modify_reg!(ral::lpspi, lpspi, FCR, TXWATER: watermark as u32)
1124        }
1125    }
1126
1127    watermark
1128}
1129
1130/// An LPSPI peripheral which is temporarily disabled.
1131pub struct Disabled<'a, const N: u8> {
1132    lpspi: &'a ral::lpspi::Instance<N>,
1133    mode: &'a mut Mode,
1134    men: bool,
1135}
1136
1137impl<'a, const N: u8> Disabled<'a, N> {
1138    fn new(lpspi: &'a mut ral::lpspi::Instance<N>, mode: &'a mut Mode) -> Self {
1139        let men = ral::read_reg!(ral::lpspi, lpspi, CR, MEN == MEN_1);
1140
1141        // Request disable
1142        ral::modify_reg!(ral::lpspi, lpspi, CR, MEN: MEN_0);
1143        // Wait for the driver to finish its current transfer
1144        // and enter disabled state
1145        while ral::read_reg!(ral::lpspi, lpspi, CR, MEN == MEN_1) {}
1146        Self { lpspi, mode, men }
1147    }
1148
1149    /// Set the SPI mode for the peripheral
1150    #[deprecated(
1151        since = "0.5.5",
1152        note = "Use Lpspi::set_mode to change modes while enabled."
1153    )]
1154    pub fn set_mode(&mut self, mode: Mode) {
1155        *self.mode = mode;
1156    }
1157
1158    /// Set the LPSPI clock speed (Hz).
1159    ///
1160    /// `source_clock_hz` is the LPSPI peripheral clock speed. To specify the
1161    /// peripheral clock, see the [`ccm::lpspi_clk`](crate::ccm::lpspi_clk) documentation.
1162    pub fn set_clock_hz(&mut self, source_clock_hz: u32, clock_hz: u32) {
1163        set_spi_clock(source_clock_hz, clock_hz, self.lpspi);
1164    }
1165
1166    /// Set LPSPI timing configurations.
1167    ///
1168    /// If you're not sure how to select these timing values, prefer
1169    /// [`set_clock_hz`](Self::set_clock_hz).
1170    pub fn set_clock_configs(&mut self, timing: ClockConfigs) {
1171        ral::write_reg!(ral::lpspi, self.lpspi, CCR,
1172            SCKPCS: timing.sckpcs as u32,
1173            PCSSCK: timing.pcssck as u32,
1174            DBT: timing.dbt as u32,
1175            SCKDIV: timing.sckdiv as u32,
1176        );
1177    }
1178
1179    /// Set the watermark level for a given direction.
1180    ///
1181    /// Returns the watermark level committed to the hardware. This may be different
1182    /// than the supplied `watermark`, since it's limited by the hardware.
1183    ///
1184    /// When `direction == Direction::Rx`, the receive data flag is set whenever the
1185    /// number of words in the receive FIFO is greater than `watermark`.
1186    ///
1187    /// When `direction == Direction::Tx`, the transmit data flag is set whenever the
1188    /// the number of words in the transmit FIFO is less than, or equal, to `watermark`.
1189    #[inline]
1190    #[deprecated(
1191        since = "0.5.5",
1192        note = "Use Lpspi::set_watermark to change watermark while enabled"
1193    )]
1194    pub fn set_watermark(&mut self, direction: Direction, watermark: u8) -> u8 {
1195        set_watermark(self.lpspi, direction, watermark)
1196    }
1197
1198    /// Set the sampling point of the LPSPI peripheral.
1199    ///
1200    /// When set to `SamplePoint::DelayedEdge`, the LPSPI will sample the input data
1201    /// on a delayed LPSPI_SCK edge, which improves the setup time when sampling data.
1202    #[inline]
1203    pub fn set_sample_point(&mut self, sample_point: SamplePoint) {
1204        match sample_point {
1205            SamplePoint::Edge => ral::modify_reg!(ral::lpspi, self.lpspi, CFGR1, SAMPLE: SAMPLE_0),
1206            SamplePoint::DelayedEdge => {
1207                ral::modify_reg!(ral::lpspi, self.lpspi, CFGR1, SAMPLE: SAMPLE_1)
1208            }
1209        }
1210    }
1211
1212    /// Become an LPSPI peripheral.
1213    ///
1214    /// By default, the LPSPI driver acts as a controller, driving I/O.
1215    /// By enabling peripheral functions (`true`), you can accept
1216    /// and react to another controller's I/O. When you're acting as a
1217    /// peripheral, you don't control the clock and chip select lines.
1218    #[inline]
1219    pub fn set_peripheral_enable(&mut self, enable: bool) {
1220        ral::modify_reg!(ral::lpspi, self.lpspi, CFGR1, MASTER: !enable as u32);
1221    }
1222}
1223
1224impl<const N: u8> Drop for Disabled<'_, N> {
1225    fn drop(&mut self) {
1226        ral::modify_reg!(ral::lpspi, self.lpspi, CR, MEN: self.men as u32);
1227    }
1228}
1229
1230impl<P, const N: u8> eh02::blocking::spi::Transfer<u8> for Lpspi<P, N> {
1231    type Error = LpspiError;
1232
1233    fn transfer<'a>(&mut self, words: &'a mut [u8]) -> Result<&'a [u8], Self::Error> {
1234        self.exchange(words)?;
1235        Ok(words)
1236    }
1237}
1238
1239impl<P, const N: u8> eh02::blocking::spi::Transfer<u16> for Lpspi<P, N> {
1240    type Error = LpspiError;
1241
1242    fn transfer<'a>(&mut self, words: &'a mut [u16]) -> Result<&'a [u16], Self::Error> {
1243        self.exchange(words)?;
1244        Ok(words)
1245    }
1246}
1247
1248impl<P, const N: u8> eh02::blocking::spi::Transfer<u32> for Lpspi<P, N> {
1249    type Error = LpspiError;
1250
1251    fn transfer<'a>(&mut self, words: &'a mut [u32]) -> Result<&'a [u32], Self::Error> {
1252        self.exchange(words)?;
1253        Ok(words)
1254    }
1255}
1256
1257impl<P, const N: u8> eh02::blocking::spi::Write<u8> for Lpspi<P, N> {
1258    type Error = LpspiError;
1259
1260    fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
1261        self.write_no_read(words)
1262    }
1263}
1264
1265impl<P, const N: u8> eh02::blocking::spi::Write<u16> for Lpspi<P, N> {
1266    type Error = LpspiError;
1267
1268    fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
1269        self.write_no_read(words)
1270    }
1271}
1272
1273impl<P, const N: u8> eh02::blocking::spi::Write<u32> for Lpspi<P, N> {
1274    type Error = LpspiError;
1275
1276    fn write(&mut self, words: &[u32]) -> Result<(), Self::Error> {
1277        self.write_no_read(words)
1278    }
1279}
1280
1281// Not supporting WriteIter right now. Since we don't know how many bytes we're
1282// going to write, we can't specify the frame size. There might be ways around
1283// this by playing with CONTC and CONT bits, but we can evaluate that later.
1284
1285/// Describes SPI words that can participate in transactions.
1286trait Word: Copy + Into<u32> + TryFrom<u32> {
1287    /// Repeatedly call `provider` to produce yourself,
1288    /// then turn yourself into a LPSPI word.
1289    fn pack_word(bit_order: BitOrder, provider: impl FnMut() -> Option<Self>) -> u32;
1290
1291    /// Given a word, deconstruct the word and call the
1292    /// `sink` with those components. `valid_bytes` conveys
1293    /// how many bytes in `word` are valid. It's never more
1294    /// than four, and it's never zero.
1295    fn unpack_word(word: u32, bit_order: BitOrder, valid_bytes: usize, sink: impl FnMut(Self));
1296}
1297
1298impl Word for u8 {
1299    fn pack_word(bit_order: BitOrder, mut provider: impl FnMut() -> Option<Self>) -> u32 {
1300        let mut word = 0;
1301        match bit_order {
1302            BitOrder::Msb => {
1303                for _ in 0..4 {
1304                    if let Some(byte) = provider() {
1305                        word <<= 8;
1306                        word |= u32::from(byte);
1307                    }
1308                }
1309            }
1310            BitOrder::Lsb => {
1311                for offset in 0..4 {
1312                    if let Some(byte) = provider() {
1313                        word |= u32::from(byte) << (8 * offset);
1314                    }
1315                }
1316            }
1317        }
1318
1319        word
1320    }
1321    fn unpack_word(word: u32, bit_order: BitOrder, valid_bytes: usize, mut sink: impl FnMut(Self)) {
1322        let mut offsets = [0usize, 8, 16, 24];
1323        let valid = &mut offsets[..valid_bytes];
1324        if matches!(bit_order, BitOrder::Msb) {
1325            valid.reverse();
1326        }
1327        for offset in valid {
1328            sink((word >> *offset) as u8);
1329        }
1330    }
1331}
1332
1333impl Word for u16 {
1334    fn pack_word(bit_order: BitOrder, mut provider: impl FnMut() -> Option<Self>) -> u32 {
1335        let mut word = 0;
1336        match bit_order {
1337            BitOrder::Msb => {
1338                for _ in 0..2 {
1339                    if let Some(half) = provider() {
1340                        word <<= 16;
1341                        word |= u32::from(half);
1342                    }
1343                }
1344            }
1345            BitOrder::Lsb => {
1346                for offset in 0..2 {
1347                    if let Some(half) = provider() {
1348                        word |= u32::from(half) << (16 * offset);
1349                    }
1350                }
1351            }
1352        }
1353
1354        word
1355    }
1356    fn unpack_word(word: u32, bit_order: BitOrder, valid_bytes: usize, mut sink: impl FnMut(Self)) {
1357        let mut offsets = [0usize, 16];
1358        let valid = &mut offsets[..valid_bytes / 2];
1359
1360        if matches!(bit_order, BitOrder::Msb) {
1361            valid.reverse();
1362        }
1363
1364        for offset in valid {
1365            sink((word >> *offset) as u16);
1366        }
1367    }
1368}
1369
1370impl Word for u32 {
1371    fn pack_word(_: BitOrder, mut provider: impl FnMut() -> Option<Self>) -> u32 {
1372        provider().unwrap_or(0)
1373    }
1374    fn unpack_word(word: u32, _: BitOrder, _: usize, mut sink: impl FnMut(Self)) {
1375        sink(word)
1376    }
1377}
1378
1379/// Generalizes how we prepare LPSPI words for transmit.
1380trait TransmitData {
1381    /// Get the next word for the transmit FIFO.
1382    ///
1383    /// If you're out of words, return 0.
1384    fn next_word(&mut self, bit_order: BitOrder) -> u32;
1385}
1386
1387/// Generalizes how we save LPSPI data into memory.
1388trait ReceiveData {
1389    /// Invoked each time we read data from the queue.
1390    fn next_word(&mut self, bit_order: BitOrder, word: u32);
1391}
1392
1393/// Transmit data from a buffer.
1394struct TransmitBuffer<'a, W> {
1395    /// The read position.
1396    ptr: *const W,
1397    /// At the end of the buffer.
1398    end: *const W,
1399    _buffer: PhantomData<&'a [W]>,
1400}
1401
1402impl<'a, W> TransmitBuffer<'a, W>
1403where
1404    W: Word,
1405{
1406    fn new(buffer: &'a [W]) -> Self {
1407        // Safety: pointer offset math meets expectations.
1408        unsafe { Self::from_raw(buffer.as_ptr(), buffer.len()) }
1409    }
1410
1411    /// # Safety
1412    ///
1413    /// `ptr + len` must be in bounds, or at the end of the
1414    /// allocation.
1415    unsafe fn from_raw(ptr: *const W, len: usize) -> Self {
1416        Self {
1417            ptr,
1418            // Safety: caller upholds contract that ptr + len
1419            // must be in bounds, or at the end.
1420            end: unsafe { ptr.add(len) },
1421            _buffer: PhantomData,
1422        }
1423    }
1424
1425    /// Read the next element from the buffer.
1426    fn next_read(&mut self) -> Option<W> {
1427        // Safety: read the next word only if we're in bounds.
1428        unsafe {
1429            (!core::ptr::eq(self.ptr, self.end)).then(|| {
1430                let word = self.ptr.read();
1431                self.ptr = self.ptr.add(1);
1432                word
1433            })
1434        }
1435    }
1436}
1437
1438impl<W> TransmitData for TransmitBuffer<'_, W>
1439where
1440    W: Word,
1441{
1442    fn next_word(&mut self, bit_order: BitOrder) -> u32 {
1443        W::pack_word(bit_order, || self.next_read())
1444    }
1445}
1446
1447/// Receive data into a buffer.
1448struct ReceiveBuffer<'a, W> {
1449    /// The write position.
1450    ptr: *mut W,
1451    /// At the end of the buffer.
1452    end: *const W,
1453    _buffer: PhantomData<&'a [W]>,
1454}
1455
1456impl<W> ReceiveBuffer<'_, W>
1457where
1458    W: Word,
1459{
1460    #[cfg(test)] // TODO(mciantyre) remove once needed in non-test code.
1461    fn new(buffer: &mut [W]) -> Self {
1462        // Safety: pointer offset math meets expectations.
1463        unsafe { Self::from_raw(buffer.as_mut_ptr(), buffer.len()) }
1464    }
1465
1466    /// # Safety
1467    ///
1468    /// `ptr + len` must be in bounds, or at the end of the
1469    /// allocation.
1470    unsafe fn from_raw(ptr: *mut W, len: usize) -> Self {
1471        Self {
1472            ptr,
1473            // Safety: caller upholds contract that ptr + len
1474            // must be in bounds, or at the end.
1475            end: unsafe { ptr.cast_const().add(len) },
1476            _buffer: PhantomData,
1477        }
1478    }
1479
1480    /// Put the next element into the buffer.
1481    fn next_write(&mut self, elem: W) {
1482        // Safety: write the next word only if we're in bounds.
1483        // Words are primitive types; we don't need to execute
1484        // a drop when we overwrite a value in memory.
1485        unsafe {
1486            if !core::ptr::eq(self.ptr.cast_const(), self.end) {
1487                self.ptr.write(elem);
1488                self.ptr = self.ptr.add(1);
1489            }
1490        }
1491    }
1492
1493    fn array_len(&self) -> usize {
1494        // Safety: end and ptr derive from the same allocation.
1495        // We always update ptr in multiples of it's object type.
1496        // The end pointer is always at a higher address in memory.
1497        unsafe { self.end.byte_offset_from(self.ptr) as _ }
1498    }
1499}
1500
1501impl<W> ReceiveData for ReceiveBuffer<'_, W>
1502where
1503    W: Word,
1504{
1505    fn next_word(&mut self, bit_order: BitOrder, word: u32) {
1506        let valid_bytes = self.array_len().min(size_of_val(&word));
1507        W::unpack_word(word, bit_order, valid_bytes, |elem| self.next_write(elem));
1508    }
1509}
1510
1511/// Computes how may Ws fit inside a LPSPI word.
1512const fn per_word<W: Word>() -> usize {
1513    core::mem::size_of::<u32>() / core::mem::size_of::<W>()
1514}
1515
1516/// Computes how many u32 words we need to transact this buffer.
1517const fn word_count<W: Word>(words: &[W]) -> usize {
1518    words.len().div_ceil(per_word::<W>())
1519}
1520
1521/// Creates the transmit and receive buffer objects for an
1522/// in-place transfer.
1523fn transfer_in_place<W: Word>(buffer: &mut [W]) -> (TransmitBuffer<'_, W>, ReceiveBuffer<'_, W>) {
1524    // Safety: pointer math meets expectation. This produces
1525    // a mutable and immutable pointer to the same mutable buffer.
1526    // Module inspection shows that these pointers never become
1527    // references. We maintain the lifetime across both objects,
1528    // so the buffer isn't dropped.
1529    unsafe {
1530        let len = buffer.len();
1531        let ptr = buffer.as_mut_ptr();
1532        (
1533            TransmitBuffer::from_raw(ptr, len),
1534            ReceiveBuffer::from_raw(ptr, len),
1535        )
1536    }
1537}
1538
1539/// Tests try to approximate the way we'll use TransmitBuffer and ReceiveBuffer
1540/// in firmware. Consider running these with miri to evaluate unsafe usages.
1541#[cfg(test)]
1542mod tests {
1543    #[test]
1544    fn transfer_in_place_interleaved_read_write_u32() {
1545        const BUFFER: [u32; 9] = [42u32, 43, 44, 45, 46, 47, 48, 49, 50];
1546        let mut buffer = BUFFER;
1547        let (mut tx, mut rx) = super::transfer_in_place(&mut buffer);
1548
1549        for elem in BUFFER {
1550            assert_eq!(elem, tx.next_read().unwrap());
1551            rx.next_write(elem + 1);
1552        }
1553
1554        assert_eq!(buffer, [43, 44, 45, 46, 47, 48, 49, 50, 51]);
1555    }
1556
1557    #[test]
1558    fn transfer_in_place_interleaved_write_read_u32() {
1559        const BUFFER: [u32; 9] = [42u32, 43, 44, 45, 46, 47, 48, 49, 50];
1560        let mut buffer = BUFFER;
1561        let (mut tx, mut rx) = super::transfer_in_place(&mut buffer);
1562
1563        for elem in BUFFER {
1564            rx.next_write(elem + 1);
1565            assert_eq!(elem + 1, tx.next_read().unwrap());
1566        }
1567
1568        assert_eq!(buffer, [43, 44, 45, 46, 47, 48, 49, 50, 51]);
1569    }
1570
1571    #[test]
1572    fn transfer_in_place_bulk_read_write_u32() {
1573        const BUFFER: [u32; 9] = [42u32, 43, 44, 45, 46, 47, 48, 49, 50];
1574        let mut buffer = BUFFER;
1575        let (mut tx, mut rx) = super::transfer_in_place(&mut buffer);
1576
1577        for elem in BUFFER {
1578            assert_eq!(elem, tx.next_read().unwrap());
1579        }
1580        for elem in BUFFER {
1581            rx.next_write(elem + 1);
1582        }
1583
1584        assert_eq!(buffer, [43, 44, 45, 46, 47, 48, 49, 50, 51]);
1585    }
1586
1587    #[test]
1588    fn transfer_in_place_bulk_write_read_u32() {
1589        const BUFFER: [u32; 9] = [42u32, 43, 44, 45, 46, 47, 48, 49, 50];
1590        let mut buffer = BUFFER;
1591        let (mut tx, mut rx) = super::transfer_in_place(&mut buffer);
1592
1593        for elem in BUFFER {
1594            rx.next_write(elem + 1);
1595        }
1596        for elem in BUFFER {
1597            assert_eq!(elem + 1, tx.next_read().unwrap());
1598        }
1599
1600        assert_eq!(buffer, [43, 44, 45, 46, 47, 48, 49, 50, 51]);
1601    }
1602
1603    #[test]
1604    fn transmit_buffer() {
1605        use super::{BitOrder::*, TransmitBuffer, TransmitData};
1606
1607        //
1608        // u32
1609        //
1610        // This is the easiest to understand w.r.t. the bit order, since this is the natural word
1611        // size of the peripheral. No matter the bit order, we produce the same word for the TX
1612        // FIFO. The hardware handles the MSB or LSB transform.
1613
1614        let mut tx = TransmitBuffer::new(&[0xDEADBEEFu32, 0xAD1CAC1D]);
1615        assert_eq!(tx.next_word(Msb), 0xDEADBEEF);
1616        assert_eq!(tx.next_word(Msb), 0xAD1CAC1D);
1617        assert_eq!(tx.next_word(Msb), 0);
1618
1619        let mut tx = TransmitBuffer::new(&[0xDEADBEEFu32, 0xAD1CAC1D]);
1620        assert_eq!(tx.next_word(Lsb), 0xDEADBEEF);
1621        assert_eq!(tx.next_word(Lsb), 0xAD1CAC1D);
1622        assert_eq!(tx.next_word(Lsb), 0);
1623
1624        //
1625        // u8
1626        //
1627        // If the user prefers u8 words, then we should pack the bytes into a u32 such that the
1628        // hardware's MSB/LSB transform maintains the (literal) byte order.
1629
1630        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE, 0xEF, 0xA5, 0x00, 0x1D]);
1631        assert_eq!(tx.next_word(Msb), 0xDEADBEEF);
1632        assert_eq!(tx.next_word(Msb), 0x00A5001D);
1633        assert_eq!(tx.next_word(Msb), 0);
1634        assert_eq!(tx.next_word(Msb), 0);
1635
1636        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE, 0xEF, 0xA5, 0x00, 0x1D]);
1637        assert_eq!(tx.next_word(Lsb), 0xEFBEADDE);
1638        assert_eq!(tx.next_word(Lsb), 0x001D00A5);
1639        assert_eq!(tx.next_word(Lsb), 0);
1640        assert_eq!(tx.next_word(Lsb), 0);
1641
1642        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE, 0xEF]);
1643        assert_eq!(tx.next_word(Msb), 0xDEADBEEF);
1644        assert_eq!(tx.next_word(Msb), 0);
1645        assert_eq!(tx.next_word(Msb), 0);
1646
1647        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE, 0xEF]);
1648        assert_eq!(tx.next_word(Lsb), 0xEFBEADDE);
1649        assert_eq!(tx.next_word(Lsb), 0);
1650        assert_eq!(tx.next_word(Lsb), 0);
1651
1652        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE]);
1653        assert_eq!(tx.next_word(Msb), 0x00DEADBE);
1654        assert_eq!(tx.next_word(Msb), 0);
1655        assert_eq!(tx.next_word(Msb), 0);
1656
1657        let mut tx = TransmitBuffer::new(&[0xDEu8, 0xAD, 0xBE]);
1658        assert_eq!(tx.next_word(Lsb), 0x00BEADDE);
1659        assert_eq!(tx.next_word(Lsb), 0);
1660        assert_eq!(tx.next_word(Lsb), 0);
1661
1662        //
1663        // u16
1664        //
1665        // Same goes here: we should combine u16s such that the hardware transfers elements
1666        // in order while applying the MSB/LSB transform on each u16.
1667
1668        let mut tx = TransmitBuffer::new(&[0xDEADu16, 0xBEEF, 0xA5A5]);
1669        assert_eq!(tx.next_word(Msb), 0xDEADBEEF);
1670        assert_eq!(tx.next_word(Msb), 0x0000A5A5);
1671        assert_eq!(tx.next_word(Msb), 0);
1672        assert_eq!(tx.next_word(Msb), 0);
1673
1674        let mut tx = TransmitBuffer::new(&[0xDEADu16, 0xBEEF, 0xA5A5]);
1675        assert_eq!(tx.next_word(Lsb), 0xBEEFDEAD);
1676        assert_eq!(tx.next_word(Lsb), 0x0000A5A5);
1677        assert_eq!(tx.next_word(Lsb), 0);
1678        assert_eq!(tx.next_word(Lsb), 0);
1679
1680        let mut tx = TransmitBuffer::new(&[0xDEADu16, 0xBEEF]);
1681        assert_eq!(tx.next_word(Msb), 0xDEADBEEF);
1682        assert_eq!(tx.next_word(Msb), 0);
1683        assert_eq!(tx.next_word(Msb), 0);
1684
1685        let mut tx = TransmitBuffer::new(&[0xDEADu16, 0xBEEF]);
1686        assert_eq!(tx.next_word(Lsb), 0xBEEFDEAD);
1687        assert_eq!(tx.next_word(Lsb), 0);
1688        assert_eq!(tx.next_word(Lsb), 0);
1689
1690        let mut tx = TransmitBuffer::new(&[0xDEADu16]);
1691        assert_eq!(tx.next_word(Msb), 0x0000DEAD);
1692        assert_eq!(tx.next_word(Msb), 0);
1693        assert_eq!(tx.next_word(Msb), 0);
1694
1695        let mut tx = TransmitBuffer::new(&[0xDEADu16]);
1696        assert_eq!(tx.next_word(Lsb), 0x0000DEAD);
1697        assert_eq!(tx.next_word(Lsb), 0);
1698        assert_eq!(tx.next_word(Lsb), 0);
1699    }
1700
1701    #[test]
1702    fn receive_buffer() {
1703        // See notes in transmit_buffer test to understand MSB and LSB
1704        // transformations.
1705
1706        use super::{BitOrder::*, ReceiveBuffer, ReceiveData};
1707
1708        //
1709        // u8
1710        //
1711
1712        let mut buffer = [0u8; 9];
1713        let mut rx = ReceiveBuffer::new(&mut buffer);
1714        rx.next_word(Msb, 0xDEADBEEF);
1715        rx.next_word(Msb, 0xAD1CAC1D);
1716        rx.next_word(Msb, 0x04030201);
1717        rx.next_word(Msb, 0x55555555);
1718        assert_eq!(
1719            buffer,
1720            [0xDE, 0xAD, 0xBE, 0xEF, 0xAD, 0x1C, 0xAC, 0x1D, 0x01]
1721        );
1722
1723        let mut buffer = [0u8; 9];
1724        let mut rx = ReceiveBuffer::new(&mut buffer);
1725        rx.next_word(Lsb, 0xDEADBEEF);
1726        rx.next_word(Lsb, 0xAD1CAC1D);
1727        rx.next_word(Lsb, 0x04030201);
1728        rx.next_word(Lsb, 0x55555555);
1729        assert_eq!(
1730            buffer,
1731            [0xEF, 0xBE, 0xAD, 0xDE, 0x1D, 0xAC, 0x1C, 0xAD, 0x01]
1732        );
1733
1734        //
1735        // u16
1736        //
1737
1738        let mut buffer = [0u16; 5];
1739        let mut rx = ReceiveBuffer::new(&mut buffer);
1740        rx.next_word(Msb, 0xDEADBEEF);
1741        rx.next_word(Msb, 0xAD1CAC1D);
1742        rx.next_word(Msb, 0x04030201);
1743        rx.next_word(Msb, 0x55555555);
1744        assert_eq!(buffer, [0xDEAD, 0xBEEF, 0xAD1C, 0xAC1D, 0x0201]);
1745
1746        let mut buffer = [0u16; 5];
1747        let mut rx = ReceiveBuffer::new(&mut buffer);
1748        rx.next_word(Lsb, 0xDEADBEEF);
1749        rx.next_word(Lsb, 0xAD1CAC1D);
1750        rx.next_word(Lsb, 0x04030201);
1751        rx.next_word(Lsb, 0x55555555);
1752        assert_eq!(buffer, [0xBEEF, 0xDEAD, 0xAC1D, 0xAD1C, 0x0201]);
1753
1754        //
1755        // u32
1756        //
1757
1758        let mut buffer = [0u32; 3];
1759        let mut rx = ReceiveBuffer::new(&mut buffer);
1760        rx.next_word(Msb, 0xDEADBEEF);
1761        rx.next_word(Msb, 0xAD1CAC1D);
1762        rx.next_word(Msb, 0x77777777);
1763        rx.next_word(Msb, 0x55555555);
1764        assert_eq!(buffer, [0xDEADBEEF, 0xAD1CAC1D, 0x77777777]);
1765
1766        let mut buffer = [0u32; 3];
1767        let mut rx = ReceiveBuffer::new(&mut buffer);
1768        rx.next_word(Lsb, 0xDEADBEEF);
1769        rx.next_word(Lsb, 0xAD1CAC1D);
1770        rx.next_word(Lsb, 0x77777777);
1771        rx.next_word(Lsb, 0x55555555);
1772        assert_eq!(buffer, [0xDEADBEEF, 0xAD1CAC1D, 0x77777777]);
1773    }
1774
1775    #[test]
1776    fn transaction_frame_sizes() {
1777        assert!(super::Transaction::new_words(&[1u8]).is_ok());
1778        assert!(super::Transaction::new_words(&[1u8, 2]).is_ok());
1779        assert!(super::Transaction::new_words(&[1u8, 2, 3]).is_ok());
1780        assert!(super::Transaction::new_words(&[1u8, 2, 3, 4]).is_ok());
1781        assert!(super::Transaction::new_words(&[1u8, 2, 3, 4, 5]).is_ok());
1782
1783        assert!(super::Transaction::new_words(&[1u16]).is_ok());
1784        assert!(super::Transaction::new_words(&[1u16, 2]).is_ok());
1785        assert!(super::Transaction::new_words(&[1u16, 2, 3]).is_ok());
1786        assert!(super::Transaction::new_words(&[1u16, 2, 3, 4]).is_ok());
1787        assert!(super::Transaction::new_words(&[1u16, 2, 3, 4, 5]).is_ok());
1788
1789        assert!(super::Transaction::new_words(&[1u32]).is_ok());
1790        assert!(super::Transaction::new_words(&[1u32, 2]).is_ok());
1791        assert!(super::Transaction::new_words(&[1u32, 2, 3]).is_ok());
1792        assert!(super::Transaction::new_words(&[1u32, 2, 3, 4]).is_ok());
1793        assert!(super::Transaction::new_words(&[1u32, 2, 3, 4, 5]).is_ok());
1794
1795        assert!(super::Transaction::new(7).is_err());
1796        assert!(super::Transaction::new(8).is_ok());
1797        assert!(super::Transaction::new(9).is_ok());
1798        assert!(super::Transaction::new(31).is_ok());
1799        assert!(super::Transaction::new(32).is_ok());
1800        assert!(super::Transaction::new(33).is_err());
1801        assert!(super::Transaction::new(34).is_ok());
1802        assert!(super::Transaction::new(95).is_ok());
1803        assert!(super::Transaction::new(96).is_ok());
1804        assert!(super::Transaction::new(97).is_err());
1805        assert!(super::Transaction::new(98).is_ok());
1806    }
1807}