hd44780_controller/device/
i2c_expander_device.rs

1use core::marker::PhantomData;
2
3use super::*;
4
5pub trait I2cPacketAssembler {
6    type Payload: AsRef<[u8]>;
7
8    fn assemble_i2c_packet(state: &State) -> Self::Payload;
9}
10
11pub struct I2cExpanderDevice<I, D, P> {
12    i2c: I,
13    i2c_address: u8,
14    delay: D,
15    state: State,
16    _packet_assembler: PhantomData<P>,
17}
18
19#[derive(Copy, Clone, Eq, PartialEq, Debug)]
20pub struct State {
21    // register select
22    pub rs: bool,
23    // read/write
24    pub rw: bool,
25    // enable
26    pub e: bool,
27    // backlight
28    pub bl: bool,
29    // 4 bit data
30    pub data: u8,
31}
32
33impl<I, D, P> I2cExpanderDevice<I, D, P> {
34    pub fn new(i2c: I, i2c_address: u8, delay: D) -> Self {
35        let state = State {
36            rs: false,
37            rw: false,
38            e: false,
39            bl: true,
40            data: 0,
41        };
42        Self {
43            i2c,
44            i2c_address,
45            delay,
46            state,
47            _packet_assembler: PhantomData,
48        }
49    }
50
51    pub fn release(self) -> (I, D) {
52        (self.i2c, self.delay)
53    }
54
55    pub fn i2c_address(&self) -> u8 {
56        self.i2c_address
57    }
58}
59
60impl<I, D, P> Device for I2cExpanderDevice<I, D, P> {
61    fn set_register_select(&mut self, mode: RegisterSelectMode) {
62        self.state.rs = match mode {
63            RegisterSelectMode::Command => false,
64            RegisterSelectMode::Data => true,
65        };
66    }
67
68    fn set_rw(&mut self, mode: RWMode) {
69        self.state.rw = match mode {
70            RWMode::Read => true,
71            RWMode::Write => false,
72        };
73    }
74
75    fn set_enable(&mut self, enabled: bool) {
76        self.state.e = enabled;
77    }
78
79    fn set_backlight(&mut self, enabled: bool) {
80        self.state.bl = enabled;
81    }
82
83    fn set_data_nibble(&mut self, data: u8) {
84        self.state.data = data;
85    }
86}
87
88#[cfg(all(feature = "async", feature = "i2c-expander-device-async"))]
89#[cfg_attr(
90    docsrs,
91    doc(cfg(all(feature = "async", feature = "i2c-expander-device-async")))
92)]
93impl<I, D, P> AsyncDevice for I2cExpanderDevice<I, D, P>
94where
95    I: embedded_hal_async::i2c::I2c,
96    D: embedded_hal_async::delay::DelayNs,
97    P: I2cPacketAssembler,
98{
99    type Err = I::Error;
100
101    async fn delay_us_async(&mut self, us: u32) {
102        self.delay.delay_us(us).await;
103    }
104
105    async fn flush_async(&mut self) -> Result<(), Self::Err> {
106        let packet = P::assemble_i2c_packet(&self.state);
107        self.i2c.write(self.i2c_address, packet.as_ref()).await
108    }
109}
110
111#[cfg(feature = "i2c-expander-device")]
112#[cfg_attr(docsrs, doc(cfg(feature = "i2c-expander-device")))]
113impl<I, D, P> SyncDevice for I2cExpanderDevice<I, D, P>
114where
115    I: embedded_hal::i2c::I2c,
116    D: embedded_hal::delay::DelayNs,
117    P: I2cPacketAssembler,
118{
119    type Err = I::Error;
120
121    fn delay_us(&mut self, us: u32) {
122        self.delay.delay_us(us);
123    }
124
125    fn flush(&mut self) -> Result<(), Self::Err> {
126        let packet = P::assemble_i2c_packet(&self.state);
127        self.i2c.write(self.i2c_address, packet.as_ref())
128    }
129}