make lcd a lib

This commit is contained in:
Simon 2023-12-20 10:16:07 +01:00
parent de278aaa52
commit ceaeb97787
3 changed files with 88 additions and 64 deletions

81
lcd-writer/src/lcd.rs Normal file
View File

@ -0,0 +1,81 @@
use rppal::{i2c, i2c::I2c};
use std::io;
const C0: u8 = 7;
const A0: u8 = 6;
#[allow(unused)]
#[repr(u8)]
enum LcdCommand {
Clear = 1,
ReturnHome = 2,
DisplayOn = 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0,
FunctionSet = 1 << 5 | 1 << 4 | 1 << 3,
EntryModeSet = 1 << 2 | 1 << 1,
}
#[allow(unused)]
#[repr(u8)]
enum ControlByte {
Normal = 1 << C0,
Last = 0 << C0,
Data = 0 << C0 | 1 << A0,
}
fn i2c_err_to_io_err(err: i2c::Error) -> io::Error {
match err {
i2c::Error::Io(v) => v,
i2c::Error::InvalidSlaveAddress(addr) => io::Error::new(
io::ErrorKind::ConnectionRefused,
format!("invalid slave address {}", addr),
),
i2c::Error::FeatureNotSupported => io::Error::new(
io::ErrorKind::ConnectionRefused,
"invalid slave address {}".to_owned(),
),
i2c::Error::UnknownModel => io::Error::new(
io::ErrorKind::ConnectionRefused,
"invalid slave address {}".to_owned(),
),
}
}
pub struct Lcd {
bus: I2c,
}
impl Lcd {
pub fn new() -> io::Result<Self> {
let mut bus = I2c::with_bus(1).map_err(i2c_err_to_io_err)?;
bus.set_slave_address(60).map_err(i2c_err_to_io_err)?;
let setup = [
ControlByte::Last as u8,
LcdCommand::FunctionSet as u8,
LcdCommand::DisplayOn as u8,
LcdCommand::EntryModeSet as u8,
LcdCommand::Clear as u8,
];
bus.write(&setup).map_err(i2c_err_to_io_err)?;
Ok(Self { bus })
}
pub fn write(&mut self, value: &str) -> io::Result<()> {
let mut data = vec![ControlByte::Data as u8];
data.extend(value.bytes());
let _ = self.bus.write(&data).map_err(i2c_err_to_io_err)?;
Ok(())
}
pub fn set_cursor(&mut self, col: u8, row: u8) -> io::Result<()> {
let pos = col | (row * 0x40) | 1 << 7;
let data = vec![ControlByte::Last as u8, pos];
let _ = self.bus.write(&data).map_err(i2c_err_to_io_err)?;
Ok(())
}
pub fn clear(&mut self) -> io::Result<()> {
let data = vec![ControlByte::Last as u8, LcdCommand::Clear as u8];
let _ = self.bus.write(&data).map_err(i2c_err_to_io_err)?;
Ok(())
}
}

1
lcd-writer/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod lcd;

View File

@ -1,79 +1,21 @@
use rppal::{i2c, i2c::I2c};
use std::io::{self, stdin, stdout, BufRead, Write};
const C0: u8 = 7;
const A0: u8 = 6;
use lcd::Lcd;
#[allow(unused)]
#[repr(u8)]
enum LcdCommand {
Clear = 1,
ReturnHome = 2,
DisplayOn = 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0,
FunctionSet = 1 << 5 | 1 << 4 | 1 << 3,
EntryModeSet = 1 << 2 | 1 << 1,
}
#[allow(unused)]
#[repr(u8)]
enum ControlByte {
Normal = 1 << C0,
Last = 0 << C0,
Data = 0 << C0 | 1 << A0,
}
struct Lcd {
bus: I2c,
}
impl Lcd {
pub fn new() -> Result<Self, i2c::Error> {
let mut bus = I2c::with_bus(1)?;
bus.set_slave_address(60)?;
let setup = [
ControlByte::Last as u8,
LcdCommand::FunctionSet as u8,
LcdCommand::DisplayOn as u8,
LcdCommand::EntryModeSet as u8,
LcdCommand::Clear as u8,
];
bus.write(&setup)?;
Ok(Self { bus })
}
pub fn write(&mut self, value: &str) -> Result<(), i2c::Error> {
let mut data = vec![ControlByte::Data as u8];
data.extend(value.bytes());
let _ = self.bus.write(&data)?;
Ok(())
}
pub fn set_cursor(&mut self, col: u8, row: u8) -> Result<(), i2c::Error> {
let pos = col | (row * 0x40) | 1 << 7;
let data = vec![ControlByte::Last as u8, pos];
let _ = self.bus.write(&data)?;
Ok(())
}
pub fn clear(&mut self) -> Result<(), i2c::Error> {
let data = vec![ControlByte::Last as u8, LcdCommand::Clear as u8];
let _ = self.bus.write(&data)?;
Ok(())
}
}
mod lcd;
fn main() -> io::Result<()> {
let mut lcd = Lcd::new().unwrap();
let mut lcd = Lcd::new()?;
loop {
print!("> ");
stdout().lock().flush()?;
let mut line = String::new();
stdin().lock().read_line(&mut line)?;
if line.starts_with("clear") {
lcd.clear().unwrap();
lcd.set_cursor(0, 0).unwrap();
lcd.clear()?;
lcd.set_cursor(0, 0)?;
} else if line.starts_with("print") {
lcd.write(&line[6..]).unwrap();
lcd.write(&line[6..])?;
} else {
println!("unrecognized command \"{line}\"");
}