lcd1602_rs/
lcd1602.rs

1use crate::error::Error;
2use crate::LCD1602;
3
4use crate::error::Error::UnsupportedBusWidth;
5use crate::lcd1602::BusWidth::FourBits;
6use crate::lcd1602::Direction::RightToLeft;
7use core::time::Duration;
8use embedded_hal::digital::v2::OutputPin;
9use embedded_hal::timer::CountDown;
10use nb::block;
11
12impl<EN, RS, D4, D5, D6, D7, Timer, E> LCD1602<EN, RS, D4, D5, D6, D7, Timer>
13where
14    EN: OutputPin<Error = E>,
15    RS: OutputPin<Error = E>,
16    D4: OutputPin<Error = E>,
17    D5: OutputPin<Error = E>,
18    D6: OutputPin<Error = E>,
19    D7: OutputPin<Error = E>,
20    Timer: CountDown<Time = Duration>,
21{
22    pub fn new(
23        en: EN,
24        rs: RS,
25        d4: D4,
26        d5: D5,
27        d6: D6,
28        d7: D7,
29        timer: Timer,
30    ) -> Result<LCD1602<EN, RS, D4, D5, D6, D7, Timer>, Error<E>> {
31        let mut lcd = LCD1602 {
32            en,
33            rs,
34            d4,
35            d5,
36            d6,
37            d7,
38            timer,
39        };
40        lcd.init()?;
41        Ok(lcd)
42    }
43
44    fn init(&mut self) -> Result<(), Error<E>> {
45        self.delay(50000)?;
46        self.set_bus_width(FourBits)?;
47
48        self.command(0x0C)?; // Display mode
49        self.clear()?;
50        self.set_entry_mode(RightToLeft, false)?;
51        Ok(())
52    }
53
54    pub fn set_bus_width(&mut self, bus_width: BusWidth) -> Result<(), Error<E>> {
55        match bus_width {
56            FourBits => {
57                self.write_bus(0x02)?;
58                self.delay(39)
59            }
60            _ => Err(UnsupportedBusWidth),
61        }
62    }
63    pub fn set_entry_mode(
64        &mut self,
65        text_direction: Direction,
66        screen_edge_tracking: bool,
67    ) -> Result<(), Error<E>> {
68        let mut cmd = 0x04;
69        if text_direction == Direction::RightToLeft {
70            cmd |= 0x02;
71        }
72        if screen_edge_tracking {
73            cmd |= 0x01;
74        }
75        self.command(cmd)?;
76        self.delay(39)
77    }
78
79    pub fn clear(&mut self) -> Result<(), Error<E>> {
80        self.command(0x01)?;
81        self.delay(1530)
82    }
83
84    pub fn home(&mut self) -> Result<(), Error<E>> {
85        self.command(0x02)?;
86        self.delay(1530)
87    }
88
89    fn command(&mut self, cmd: u8) -> Result<(), Error<E>> {
90        self.rs.set_low()?;
91        self.write_bus((cmd & 0xF0) >> 4)?;
92        self.write_bus(cmd & 0x0F)?; // 4bit writes send end pulses
93        Ok(())
94    }
95
96    fn write_char(&mut self, ch: u8) -> Result<(), Error<E>> {
97        self.rs.set_high()?;
98        self.write_bus((ch & 0xF0) >> 4)?;
99        self.write_bus(ch & 0x0F)?; // 4bit writes send end pulses
100        Ok(())
101    }
102
103    pub fn print(&mut self, s: &str) -> Result<(), Error<E>> {
104        for ch in s.chars() {
105            self.delay(320)?; // per char delay
106            self.write_char(ch as u8)?;
107        }
108        Ok(())
109    }
110
111    fn write_bus(&mut self, data: u8) -> Result<(), Error<E>> {
112        self.en.set_low()?;
113        match (data & 0x1) > 0 {
114            true => self.d4.set_high()?,
115            false => self.d4.set_low()?,
116        };
117        match (data & 0x2) > 0 {
118            true => self.d5.set_high()?,
119            false => self.d5.set_low()?,
120        };
121        match (data & 0x4) > 0 {
122            true => self.d6.set_high()?,
123            false => self.d6.set_low()?,
124        };
125        match (data & 0x8) > 0 {
126            true => self.d7.set_high()?,
127            false => self.d7.set_low()?,
128        };
129        self.en.set_high()?;
130        self.en.set_low()?;
131        Ok(())
132    }
133
134    pub fn delay(&mut self, interval_us: u64) -> Result<(), Error<E>> {
135        self.timer.start(Duration::from_micros(interval_us));
136        match block!(self.timer.wait()) {
137            Ok(_) => Ok(()),
138            Err(_) => Err(Error::TimerError),
139        }
140    }
141}
142
143#[derive(PartialEq)]
144pub enum Direction {
145    LeftToRight,
146    RightToLeft,
147}
148
149#[derive(PartialEq)]
150pub enum BusWidth {
151    FourBits,
152    EightBits,
153}