driver_74hc595/
lib.rs

1#![no_std]
2#![warn(missing_docs)]
3
4//! An embedded async driver for 74hc595 (compatible) shift registers.
5//!
6//! For efficient data transfer, an SPI bus peripheral is used. The SPI bus should be configured in SPI Mode 0 (clock
7//! idle state low, data sampled on rising edge). Because the 74hc595 does not have a CS line, the SPI bus cannot be
8//! shared with other devices (at least not without additional circuitry).
9
10use embedded_hal::digital::OutputPin;
11use embedded_hal_async::delay::DelayNs;
12use embedded_hal_async::spi::SpiBus;
13
14/// A 74hc595 (compatible) shift register.
15pub struct ShiftRegister<SPI, OE, CLR, LATCH, D> {
16    spi: SPI,
17    not_oe: OE,
18    not_clr: CLR,
19    latch: LATCH,
20    delay: D,
21}
22
23impl<SPI, OE, CLR, LATCH, D> ShiftRegister<SPI, OE, CLR, LATCH, D>
24where
25    SPI: SpiBus,
26    OE: OutputPin,
27    CLR: OutputPin,
28    LATCH: OutputPin,
29    D: DelayNs,
30{
31    /// Creates a new `ShiftRegister`.
32    pub fn new(spi: SPI, not_oe: OE, not_clr: CLR, latch: LATCH, delay: D) -> Self {
33        ShiftRegister {
34            spi,
35            not_oe,
36            not_clr,
37            latch,
38            delay,
39        }
40    }
41
42    /// Enables or disables the shift register output drivers.
43    pub fn output_enable(&mut self, enable: bool) -> Result<(), OE::Error> {
44        self.not_oe.set_state((!enable).into())
45    }
46
47    /// Clears the shift register.
48    ///
49    /// This does not change the value of the output latches. Use [`Self::latch()`]
50    /// after clearing if you want the outputs to be reset.
51    pub async fn clear(&mut self) -> Result<(), CLR::Error> {
52        self.not_clr.set_low()?;
53        self.delay.delay_us(1).await;
54        self.not_clr.set_high()
55    }
56
57    /// Latches the current values in the shift register into the output latches.
58    pub async fn latch(&mut self) -> Result<(), LATCH::Error> {
59        self.latch.set_high()?;
60        self.delay.delay_us(1).await;
61        self.latch.set_low()
62    }
63
64    /// Loads `data` into the shift register.
65    pub async fn load(&mut self, data: &[u8]) -> Result<(), SPI::Error> {
66        self.spi.write(data).await
67    }
68
69    /// Loads `write` into the shift register and writes the data shifted out of the shift register
70    /// into `read`.
71    pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), SPI::Error> {
72        self.spi.transfer(read, write).await
73    }
74}