1#![no_std]
2
3use embedded_hal::blocking::{i2c, delay::DelayMs};
30
31#[derive(Copy, Clone, Debug)]
34pub enum Cursor {
35 On = 0x02,
37 Off = 0x00,
39}
40
41#[derive(Copy, Clone, Debug)]
43pub enum Blink {
44 On = 0x01,
46 Off = 0x00,
48}
49
50#[derive(Copy, Clone, Debug)]
52pub enum Display {
53 On = 0x04,
55 Off = 0x00,
57}
58
59#[derive(Copy, Clone, Debug)]
61pub enum Backlight {
62 On = 0x08,
64 Off = 0x00,
66}
67
68#[derive(Copy, Clone, Debug)]
70pub enum Mode {
71 COMMAND = 0x00,
72 CLEARDISPLAY = 0x01,
73 RETURNHOME = 0x02,
74 ENTRYMODESET = 0x04,
75 DISPLAYCONTROL = 0x08,
76 CURSORSHIFT = 0x10,
77 FUNCTIONSET = 0x20,
78 SETCGRAMADDR = 0x40,
79 SETDDRAMADDR = 0x80,
80}
81
82#[derive(Copy, Clone, Debug)]
84pub enum Entries {
85 RIGHT = 0x00,
86 LEFT = 0x02,
87}
88
89#[derive(Copy, Clone, Debug)]
91pub enum MoveSelect {
92 DISPLAY = 0x08,
93 CURSOR = 0x00,
94}
95
96#[derive(Copy, Clone, Debug)]
98pub enum Direction {
99 RIGHT = 0x04,
100 LEFT = 0x00,
101}
102
103
104#[derive(Copy, Clone, Debug)]
105pub enum Shift {
106 INCREMENT = 0x01,
107 DECREMENT = 0x00,
108}
109
110#[derive(Copy, Clone, Debug)]
111pub enum BitMode {
112 Bit4 = 0x00,
113 Bit8 = 0x10,
114}
115
116#[derive(Copy, Clone, Debug)]
117pub enum Dots {
118 Dots5x8 = 0x00,
119 Dots5x10 = 0x04,
120}
121
122#[derive(Copy, Clone, Debug)]
123pub enum Lines {
124 OneLine = 0x00,
125 TwoLine = 0x08,
126}
127
128#[derive(Copy, Clone, Debug)]
129pub enum BitAction {
130 Command = 0x00,
131 Enable = 0x04,
132 ReadWrite = 0x02,
133 RegisterSelect = 0x01
134}
135
136
137pub struct DisplayControl {
138 pub cursor: Cursor,
139 pub display: Display,
140 pub blink: Blink,
141 pub backlight: Backlight,
142 pub direction: Direction,
143}
144
145impl DisplayControl {
146 pub fn new() -> Self {
147 DisplayControl {
148 cursor: Cursor::Off,
149 display: Display::Off,
150 blink: Blink::Off,
151 backlight: Backlight::On,
152 direction: Direction::LEFT,
153 }
154 }
155
156 pub fn value(&self) -> u8 {
157 self.blink as u8 |
158 self.cursor as u8 |
159 self.display as u8 |
160 self.backlight as u8
161 }
162}
163
164
165
166pub struct Lcd<'a, I, D>
167where
168 I: i2c::Write,
169 D: DelayMs<u8>,
170{
171 i2c: &'a mut I,
172 control: DisplayControl,
173 address: u8,
174 delay: &'a mut D,
175}
176
177impl<'a, I, D> Lcd<'a, I, D>
178where
179 I: i2c::Write,
180 D: DelayMs<u8>,
181 {
182
183 pub fn new(i2c: &'a mut I, address: u8, delay: &'a mut D) -> Result<Self, <I as i2c::Write>::Error> {
184 let mut display = Lcd {
185 i2c,
186 control: DisplayControl::new(),
187 address,
188 delay
189 };
190 display.init()?;
191 Ok(display)
192 }
193
194 fn init(&mut self) -> Result<(), <I as i2c::Write>::Error>
196 {
197
198 self.delay.delay_ms(50);
202
203 self.expander_write(self.control.backlight as u8)?;
204 self.delay.delay_ms(1);
205
206
207 let mode_8bit = Mode::FUNCTIONSET as u8 | BitMode::Bit8 as u8;
209 self.write4bits(mode_8bit)?;
210 self.delay.delay_ms(5);
211
212 self.write4bits(mode_8bit)?;
213 self.delay.delay_ms(5);
214
215 self.write4bits(mode_8bit)?;
216 self.delay.delay_ms(5);
217
218 let mode_4bit = Mode::FUNCTIONSET as u8 | BitMode::Bit4 as u8;
219 self.write4bits(mode_4bit)?;
220 self.delay.delay_ms(5);
221
222
223 let lines_font = Mode::FUNCTIONSET as u8 | BitMode::Bit4 as u8 | Dots::Dots5x8 as u8 | Lines::TwoLine as u8;
224 self.command(lines_font)?;
225
226 self.clear()?;
227
228 let entry_mode = Mode::ENTRYMODESET as u8 | Entries::LEFT as u8 | Shift::DECREMENT as u8;
229 self.command(entry_mode)?;
230
231 Ok(())
232 }
233
234
235 pub fn clear(&mut self) -> Result<(), <I as i2c::Write>::Error> {
245 self.command(Mode::CLEARDISPLAY as u8)?;
246 self.delay.delay_ms(2);
247 Ok(())
248 }
249
250 pub fn home(&mut self) -> Result<(), <I as i2c::Write>::Error> {
258 self.command(Mode::RETURNHOME as u8)?;
259 self.delay.delay_ms(2);
260 Ok(())
261 }
262
263 pub fn set_cursor_position(&mut self, col: u8, row: u8) -> Result<(), <I as i2c::Write>::Error> {
271 self.command(Mode::SETDDRAMADDR as u8 | (col + row *0x40))?;
278 Ok(())
279 }
280
281 pub fn set_display(&mut self, display: Display) -> Result<(), <I as i2c::Write>::Error> {
289 self.control.display = display;
290 self.write_display_control()
291 }
292
293 pub fn set_cursor(&mut self, cursor: Cursor) -> Result<(), <I as i2c::Write>::Error> {
301 self.control.cursor = cursor;
302 self.write_display_control()
303 }
304
305 pub fn set_blink(&mut self, blink: Blink) -> Result<(), <I as i2c::Write>::Error> {
313 self.control.blink = blink;
314 self.write_display_control()
315 }
316
317
318 pub fn set_backlight(&mut self, backlight: Backlight)-> Result<(), <I as i2c::Write>::Error> {
319 self.control.backlight = backlight;
320 self.expander_write(0)
321 }
322
323
324
325
326
327
328 pub fn print(&mut self, s: &str) -> Result<(), <I as i2c::Write>::Error> {
337 for c in s.chars() {
338 self.write(c as u8)?;
339 }
340
341 Ok(())
342 }
343
344 fn write_display_control(&mut self) -> Result<(), <I as i2c::Write>::Error> {
346 self.command(Mode::DISPLAYCONTROL as u8 | self.control.value())
347 }
348
349
350 fn write(&mut self, value: u8) -> Result<(), <I as i2c::Write>::Error> {
352 self.send(value, BitAction::RegisterSelect)
353 }
354
355 fn command(&mut self, value: u8) -> Result<(), <I as i2c::Write>::Error> {
356 self.send(value, BitAction::Command)
357 }
358
359 fn send(&mut self, data: u8, mode: BitAction) -> Result<(), <I as i2c::Write>::Error> {
363 let high_bits: u8 = data & 0xf0;
364 let low_bits: u8 = (data << 4) & 0xf0;
365 self.write4bits(high_bits | mode as u8)?;
366 self.write4bits(low_bits | mode as u8)?;
367 Ok(())
368 }
369
370 fn write4bits(&mut self, value: u8) -> Result<(), <I as i2c::Write>::Error> {
371 self.expander_write(value)?;
372 self.pulse_enable(value)?;
373 Ok(())
374 }
375
376 fn expander_write(&mut self, data: u8) -> Result<(), <I as i2c::Write>::Error> {
377 self.i2c.write(self.address, &[data | self.control.backlight as u8])
378 }
379
380 fn pulse_enable(&mut self, data: u8) -> Result<(), <I as i2c::Write>::Error> {
381 self.expander_write(data | BitAction::Enable as u8)?; self.delay.delay_ms(1);
383
384 self.expander_write(data & !(BitAction::Enable as u8))?; self.delay.delay_ms(1);
386
387 Ok(())
388 }
389
390
391
392
393}