hd44780_controller/device/
i2c_expander_device.rs1use 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 pub rs: bool,
23 pub rw: bool,
25 pub e: bool,
27 pub bl: bool,
29 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}