You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.1 KiB
Rust

//! Driver for LiquidCrystal Displays plugs to the GPIO of the board.
//! The LCD need to be an Hitachi HD44780 chipset compatible.
//!
//! This driver inspired from the one from the arduino libriaries
//! (https://github.com/arduino-libraries/LiquidCrystal) and the
//! documentation from wikipedia (https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller)
use crate::gpio;
// TODO: change USIZE to a Pin struct (and implement the Pin struct :'( )
/// The structure handling the LCD periferic
pub struct Lcd {
/// The Register Select pinout.
rs_pin: usize,
/// The Read/Write pinout.
///
/// If set to None, assumes the rw pin of the lcd is connected to the ground (write state)
rw_pin: Option<usize>,
/// The Enable pinout.
///
/// TODO: wiki says falling-edge triggered, arduino comment says activated by a HIGH pulse.
e_pin: usize,
/// First 4 data bits pins.
///
/// Set to None if the lcd is in 4-bit mode.
first_data_bits_pins: Option<[usize; 4]>,
/// Last 4 data bits pins.
last_data_bits_pins: [usize; 4],
/// The number of line of the LCD.
nb_lines: usize,
/// The number of row of the LCD.
nb_rows: usize,
/// Weither or not the LCD has been initialized in the rigth state.
initialized: bool,
}
impl Lcd {
/// Instanciate a [`Lcd`] object in 4 bits mode.
pub const fn new_4bits_mode(
rs_pin: usize,
rw_pin: Option<usize>,
e_pin: usize,
db4: usize,
db5: usize,
db6: usize,
db7: usize,
nb_lines: usize,
nb_rows: usize,
) -> Self {
Self {
rs_pin,
rw_pin,
e_pin,
first_data_bits_pins: None,
last_data_bits_pins: [db4, db5, db6, db7],
nb_lines,
nb_rows,
initialized: false,
}
}
/// Instanciate a [`Lcd`] object in 8 bits mode.
pub const fn new_8bits_mode(
rs_pin: usize,
rw_pin: Option<usize>,
e_pin: usize,
db0: usize,
db1: usize,
db2: usize,
db3: usize,
db4: usize,
db5: usize,
db6: usize,
db7: usize,
nb_lines: usize,
nb_rows: usize,
) -> Self {
Self {
rs_pin,
rw_pin,
e_pin,
first_data_bits_pins: Some([db0, db1, db2, db3]),
last_data_bits_pins: [db4, db5, db6, db7],
nb_lines,
nb_rows,
initialized: false,
}
}
/// Initialize the LCD.
pub fn init(&mut self) -> Result::<(), &str> {
gpio::set_pin_fonction(self.rs_pin, gpio::PinFunction::Output)?;
gpio::set_pin_output_state(self.rs_pin, gpio::PinOutputState::Low)?;
if let Some(rw_pin) = self.rw_pin {
gpio::set_pin_fonction(rw_pin, gpio::PinFunction::Output)?;
gpio::set_pin_output_state(rw_pin, gpio::PinOutputState::Low)?;
}
gpio::set_pin_fonction(self.e_pin, gpio::PinFunction::Output)?;
gpio::set_pin_output_state(self.e_pin, gpio::PinOutputState::Low)?;
if let Some(first_data_bits_pins) = self.first_data_bits_pins {
for pin in first_data_bits_pins.into_iter() {
gpio::set_pin_fonction(pin, gpio::PinFunction::Output)?;
}
}
for pin in self.last_data_bits_pins.into_iter() {
gpio::set_pin_fonction(pin, gpio::PinFunction::Output)?;
}
// TODO: send 0b0011 3 times to make sure to be in 8bits mode 5x8 characters
// TODO: set the new mode with Function set (2 times if 4 bits modes, 1 to set DL=0,
// then the actual one)
self.initialized = true;
todo!();
}
/// Send an 'enable' signal.
fn enable(&self) {
todo!()
}
/// Send a Function Set instruction.
fn function_set(&self) {
todo!()
}
/// Send data to the lcd.
fn send_data(&self) {
todo!()
}
/// Send 8 bits of data.
fn send_8bit(&self) {
todo!()
}
/// Send 4 bits of data.
fn send_4bits(&self) {
// TODO: type?
todo!()
}
}