#![no_std]
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
use embedded_hal::blocking::i2c;
use embedded_hal::digital::v2::OutputPin;
pub mod bus;
use bus::{DataBus, EightBitBus, FourBitBus, I2CBus};
pub mod error;
use error::Result;
pub mod entry_mode;
use entry_mode::{CursorMode, EntryMode};
pub mod display_mode;
pub use display_mode::DisplayMode;
pub struct HD44780<B: DataBus> {
bus: B,
entry_mode: EntryMode,
display_mode: DisplayMode,
}
pub enum Direction {
Left,
Right,
}
pub enum Display {
On,
Off,
}
pub enum Cursor {
Visible,
Invisible,
}
pub enum CursorBlink {
On,
Off,
}
impl<
RS: OutputPin,
EN: OutputPin,
D0: OutputPin,
D1: OutputPin,
D2: OutputPin,
D3: OutputPin,
D4: OutputPin,
D5: OutputPin,
D6: OutputPin,
D7: OutputPin,
> HD44780<EightBitBus<RS, EN, D0, D1, D2, D3, D4, D5, D6, D7>>
{
pub fn new_8bit<D: DelayUs<u16> + DelayMs<u8>>(
rs: RS,
en: EN,
d0: D0,
d1: D1,
d2: D2,
d3: D3,
d4: D4,
d5: D5,
d6: D6,
d7: D7,
delay: &mut D,
) -> Result<HD44780<EightBitBus<RS, EN, D0, D1, D2, D3, D4, D5, D6, D7>>> {
let mut hd = HD44780 {
bus: EightBitBus::from_pins(rs, en, d0, d1, d2, d3, d4, d5, d6, d7),
entry_mode: EntryMode::default(),
display_mode: DisplayMode::default(),
};
hd.init_8bit(delay)?;
return Ok(hd);
}
}
impl<RS: OutputPin, EN: OutputPin, D4: OutputPin, D5: OutputPin, D6: OutputPin, D7: OutputPin>
HD44780<FourBitBus<RS, EN, D4, D5, D6, D7>>
{
pub fn new_4bit<D: DelayUs<u16> + DelayMs<u8>>(
rs: RS,
en: EN,
d4: D4,
d5: D5,
d6: D6,
d7: D7,
delay: &mut D,
) -> Result<HD44780<FourBitBus<RS, EN, D4, D5, D6, D7>>> {
let mut hd = HD44780 {
bus: FourBitBus::from_pins(rs, en, d4, d5, d6, d7),
entry_mode: EntryMode::default(),
display_mode: DisplayMode::default(),
};
hd.init_4bit(delay)?;
return Ok(hd);
}
}
impl<I2C: i2c::Write> HD44780<I2CBus<I2C>> {
pub fn new_i2c<D: DelayUs<u16> + DelayMs<u8>>(
i2c_bus: I2C,
address: u8,
delay: &mut D,
) -> Result<HD44780<I2CBus<I2C>>> {
let mut hd = HD44780 {
bus: I2CBus::new(i2c_bus, address),
entry_mode: EntryMode::default(),
display_mode: DisplayMode::default(),
};
hd.init_4bit(delay)?;
return Ok(hd);
}
}
impl<B> HD44780<B>
where
B: DataBus,
{
pub fn reset<D: DelayUs<u16> + DelayMs<u8>>(&mut self, delay: &mut D) -> Result<()> {
self.write_command(0b0000_0010, delay)?;
Ok(())
}
pub fn set_display_mode<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
display_mode: DisplayMode,
delay: &mut D,
) -> Result<()> {
self.display_mode = display_mode;
let cmd_byte = self.display_mode.as_byte();
self.write_command(cmd_byte, delay)?;
Ok(())
}
pub fn clear<D: DelayUs<u16> + DelayMs<u8>>(&mut self, delay: &mut D) -> Result<()> {
self.write_command(0b0000_0001, delay)?;
Ok(())
}
pub fn set_autoscroll<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
enabled: bool,
delay: &mut D,
) -> Result<()> {
self.entry_mode.shift_mode = enabled.into();
let cmd = self.entry_mode.as_byte();
self.write_command(cmd, delay)?;
Ok(())
}
pub fn set_cursor_visibility<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
visibility: Cursor,
delay: &mut D,
) -> Result<()> {
self.display_mode.cursor_visibility = visibility;
let cmd = self.display_mode.as_byte();
self.write_command(cmd, delay)?;
Ok(())
}
pub fn set_display<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
display: Display,
delay: &mut D,
) -> Result<()> {
self.display_mode.display = display;
let cmd = self.display_mode.as_byte();
self.write_command(cmd, delay)?;
Ok(())
}
pub fn set_cursor_blink<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
blink: CursorBlink,
delay: &mut D,
) -> Result<()> {
self.display_mode.cursor_blink = blink;
let cmd = self.display_mode.as_byte();
self.write_command(cmd, delay)?;
Ok(())
}
pub fn set_cursor_mode<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
mode: CursorMode,
delay: &mut D,
) -> Result<()> {
self.entry_mode.cursor_mode = mode;
let cmd = self.entry_mode.as_byte();
self.write_command(cmd, delay)?;
Ok(())
}
pub fn set_cursor_pos<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
position: u8,
delay: &mut D,
) -> Result<()> {
let lower_7_bits = 0b0111_1111 & position;
self.write_command(0b1000_0000 | lower_7_bits, delay)?;
Ok(())
}
pub fn shift_cursor<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
dir: Direction,
delay: &mut D,
) -> Result<()> {
let bits = match dir {
Direction::Left => 0b0000_0000,
Direction::Right => 0b0000_0100,
};
self.write_command(0b0001_0000 | bits | bits, delay)?;
Ok(())
}
pub fn shift_display<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
dir: Direction,
delay: &mut D,
) -> Result<()> {
let bits = match dir {
Direction::Left => 0b0000_0000,
Direction::Right => 0b0000_0100,
};
self.write_command(0b0001_1000 | bits, delay)?;
Ok(())
}
pub fn write_char<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
data: char,
delay: &mut D,
) -> Result<()> {
self.write_byte(data as u8, delay)
}
fn write_command<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
cmd: u8,
delay: &mut D,
) -> Result<()> {
self.bus.write(cmd, false, delay)?;
delay.delay_us(100);
Ok(())
}
fn init_4bit<D: DelayUs<u16> + DelayMs<u8>>(&mut self, delay: &mut D) -> Result<()> {
delay.delay_ms(15u8);
self.bus.write(0x33, false, delay)?;
delay.delay_ms(5u8);
self.bus.write(0x32, false, delay)?;
delay.delay_us(100);
self.bus.write(0x28, false, delay)?;
delay.delay_us(100);
self.bus.write(0x0E, false, delay)?;
delay.delay_us(100);
self.bus.write(0x01, false, delay)?;
delay.delay_us(100);
self.bus.write(self.entry_mode.as_byte(), false, delay)?;
delay.delay_us(100);
self.bus.write(0x80, false, delay)?;
delay.delay_us(100);
Ok(())
}
fn init_8bit<D: DelayUs<u16> + DelayMs<u8>>(&mut self, delay: &mut D) -> Result<()> {
delay.delay_ms(15u8);
self.bus.write(0b0011_0000, false, delay)?;
delay.delay_ms(5u8);
self.bus.write(0b0011_1000, false, delay)?;
delay.delay_us(100);
self.bus.write(0b0000_1110, false, delay)?;
delay.delay_us(100);
self.bus.write(0b0000_0001, false, delay)?;
delay.delay_us(100);
self.bus.write(0b000_0111, false, delay)?;
delay.delay_us(100);
self.bus.write(self.entry_mode.as_byte(), false, delay)?;
delay.delay_us(100);
Ok(())
}
pub fn write_str<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
string: &str,
delay: &mut D,
) -> Result<()> {
self.write_bytes(string.as_bytes(), delay)
}
pub fn write_bytes<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
string: &[u8],
delay: &mut D,
) -> Result<()> {
for &b in string {
self.write_byte(b, delay)?;
}
Ok(())
}
pub fn write_byte<D: DelayUs<u16> + DelayMs<u8>>(
&mut self,
data: u8,
delay: &mut D
) -> Result<()> {
self.bus.write(data, true, delay)?;
delay.delay_us(100);
Ok(())
}
}