lcd1602_driver/sender/
i2c_sender.rs1use embedded_hal::{
18 delay::DelayNs,
19 i2c::{AddressMode, I2c},
20};
21
22use crate::{
23 command::{Bits, Command, ReadWriteOp, RegisterSelection, State},
24 utils::{BitOps, BitState},
25};
26
27use super::SendCommand;
28
29pub struct I2cSender<'a, I2cLcd: I2c<A>, A: AddressMode + Clone> {
31 i2c: &'a mut I2cLcd,
32 addr: A,
33 first_command: bool,
34 backlight_state: State,
35}
36
37impl<'a, I2cLcd: I2c<A>, A: AddressMode + Clone> I2cSender<'a, I2cLcd, A> {
38 pub fn new(i2c: &'a mut I2cLcd, addr: A) -> Self {
40 Self {
41 i2c,
42 addr,
43 first_command: true,
44 backlight_state: State::Off,
45 }
46 }
47}
48
49impl<'a, I2cLcd, A, Delayer> SendCommand<Delayer, true> for I2cSender<'a, I2cLcd, A>
50where
51 I2cLcd: I2c<A>,
52 A: AddressMode + Clone,
53 Delayer: DelayNs,
54{
55 fn set_actual_backlight(&mut self, state: State) {
57 let mut i2c_raw_seq: u8 = 0b1111_1011;
60
61 match state {
62 State::On => i2c_raw_seq.set_bit(3),
63 State::Off => i2c_raw_seq.clear_bit(3),
64 };
65
66 self.i2c.write(self.addr.clone(), &[i2c_raw_seq]).unwrap();
67 self.backlight_state = state;
68 }
69
70 fn get_actual_backlight(&mut self) -> State {
71 let mut buf = [0u8];
72 self.i2c.read(self.addr.clone(), &mut buf).unwrap();
74 match buf[0].check_bit(3) {
75 BitState::Clear => State::Off,
76 BitState::Set => State::On,
77 }
78 }
79
80 fn send(&mut self, lcd_command: Command) -> Option<u8> {
81 if self.first_command {
82 assert!(
83 lcd_command.get_data().is_some(),
84 "first command should has some data to write"
85 );
86
87 match lcd_command.get_data().unwrap() {
88 Bits::Bit8(_) => panic!("first command should be 4 bit"),
89
90 Bits::Bit4(_) => {
91 let i2c_command = I2cCommand::gen_i2c_cmd(lcd_command, self.backlight_state);
92
93 assert!(
94 i2c_command.0 == 0b0010_0000 || i2c_command.0 == 0b0010_1000,
95 "first command should be Function set, and should set to 4 bit mode"
96 );
97
98 let I2cRawSeq(len, raw_seq) = i2c_command.into();
99
100 self.i2c
101 .write(self.addr.clone(), &raw_seq[0..len as usize])
102 .unwrap();
103 }
104 }
105
106 self.first_command = false;
107 } else {
108 if let Some(Bits::Bit4(_)) = lcd_command.get_data() {
111 panic!("Only first command is 4 bit long, other command should be 8 bit long")
112 }
113
114 match lcd_command.get_read_write_op() {
115 ReadWriteOp::Write => {
116 assert!(
117 lcd_command.get_data().is_some(),
118 "first command should has some data to write"
119 );
120
121 if lcd_command.get_register_selection() == RegisterSelection::Command {
122 match lcd_command.get_data().unwrap() {
123 Bits::Bit8(lcd_command_data) => {
124 if (lcd_command_data >> 4) == 0b0011 {
125 panic!("This I2C driver doesn't support 8 bit Data Width Mode")
126 }
127 }
128 _ => unreachable!(),
129 }
130 }
131
132 let i2c_command = I2cCommand::gen_i2c_cmd(lcd_command, self.backlight_state);
133 let I2cRawSeq(len, raw_seq) = i2c_command.into();
134 self.i2c
135 .write(self.addr.clone(), &raw_seq[0..len as usize])
136 .unwrap();
137 }
138
139 ReadWriteOp::Read => {
140 let mut concat_buf = [0u8; 2];
141 let mut buf = [0u8];
142
143 let i2c_command = I2cCommand::gen_i2c_cmd(lcd_command, self.backlight_state);
144 let I2cRawSeq(len, raw_seq) = i2c_command.into();
145
146 assert_eq!(
147 len, 6,
148 "Read command will always need to send 6 I2C sequence"
149 );
150
151 self.i2c
158 .write_read(self.addr.clone(), &raw_seq[0..2], &mut buf)
159 .unwrap();
160 concat_buf[0] = buf[0];
161
162 self.i2c
163 .write_read(self.addr.clone(), &raw_seq[2..5], &mut buf)
164 .unwrap();
165 self.i2c.write(self.addr.clone(), &raw_seq[5..6]).unwrap();
166 concat_buf[1] = buf[0];
167
168 return Some((concat_buf[0] & 0b1111_0000) | (concat_buf[1] >> 4));
170 }
171 };
172 }
173
174 None
175 }
176}
177
178struct I2cCommand(u8, Option<u8>);
183
184impl Default for I2cCommand {
185 fn default() -> Self {
186 Self(0, Some(0))
187 }
188}
189
190impl I2cCommand {
191 fn gen_i2c_cmd(lcd_command: Command, backlight_state: State) -> Self {
192 let mut i2c_raw_data = I2cCommand::default();
193 let i2c_raw_data_1_inner = i2c_raw_data.1.as_mut().unwrap();
194
195 if lcd_command.get_register_selection() == RegisterSelection::Data {
196 i2c_raw_data.0.set_bit(0);
197 i2c_raw_data_1_inner.set_bit(0);
198 }
199
200 match backlight_state {
202 State::Off => {
203 i2c_raw_data.0.clear_bit(3);
206 i2c_raw_data_1_inner.clear_bit(3);
207 }
208 State::On => {
209 i2c_raw_data.0.set_bit(3);
212 i2c_raw_data_1_inner.set_bit(3);
213 }
214 }
215
216 match lcd_command.get_read_write_op() {
217 ReadWriteOp::Write => match lcd_command.get_data() {
218 None => panic!("Write command should have some data to be send"),
219 Some(command_data) => match command_data {
220 Bits::Bit4(raw_data) => {
221 assert!(raw_data < (1 << 4), "data is overflow 4 bit");
222 i2c_raw_data.0 |= raw_data << 4;
223 i2c_raw_data.1 = None;
224 }
225 Bits::Bit8(raw_data) => {
226 i2c_raw_data.0 |= raw_data & 0b1111_0000;
227 *i2c_raw_data_1_inner |= (raw_data & 0b0000_1111) << 4
228 }
229 },
230 },
231 ReadWriteOp::Read => {
232 i2c_raw_data.0.set_bit(1);
234 i2c_raw_data.0 |= 0b1111 << 4; i2c_raw_data_1_inner.set_bit(1);
237 *i2c_raw_data_1_inner |= 0b1111 << 4; }
239 }
240
241 i2c_raw_data
242 }
243}
244
245struct I2cRawSeq(u8, [u8; 6]);
247
248impl From<I2cCommand> for I2cRawSeq {
249 fn from(i2c_command: I2cCommand) -> Self {
251 let mut seq = [0u8; 6];
252 let mut len = 3;
253
254 let mut disable_0 = i2c_command.0;
255 disable_0.clear_bit(2);
256 let mut enable_0 = disable_0;
257 enable_0.set_bit(2);
258
259 seq[0] = disable_0;
260 seq[1] = enable_0;
261 seq[2] = disable_0;
262
263 if i2c_command.1.is_some() {
264 let mut disable_1 = i2c_command.1.unwrap();
265 disable_1.clear_bit(2);
266 let mut enable_1 = disable_1;
267 enable_1.set_bit(2);
268
269 seq[3] = disable_1;
270 seq[4] = enable_1;
271 seq[5] = disable_1;
272
273 len = 6;
274 }
275
276 Self(len, seq)
277 }
278}