use crate::utils::BitOps;
#[derive(Clone, Copy, PartialEq)]
#[allow(missing_docs)]
pub enum CommandSet {
ClearDisplay,
ReturnHome,
EntryModeSet(MoveDirection, ShiftType),
DisplayOnOff {
display: State,
cursor: State,
cursor_blink: State,
},
CursorOrDisplayShift(ShiftType, MoveDirection),
HalfFunctionSet,
FunctionSet(DataWidth, LineMode, Font),
SetCGRAM(u8),
SetDDRAM(u8),
ReadBusyFlagAndAddress,
WriteDataToRAM(u8),
ReadDataFromRAM,
}
#[derive(Clone, Copy, PartialEq, Default)]
pub enum MoveDirection {
#[allow(missing_docs)]
RightToLeft,
#[allow(missing_docs)]
#[default]
LeftToRight,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum ShiftType {
#[allow(missing_docs)]
#[default]
CursorOnly,
#[allow(missing_docs)]
CursorAndDisplay,
}
#[derive(Clone, Copy, PartialEq, Default)]
pub enum State {
#[allow(missing_docs)]
Off,
#[allow(missing_docs)]
#[default]
On,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum DataWidth {
#[allow(missing_docs)]
#[default]
Bit4,
#[allow(missing_docs)]
Bit8,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum LineMode {
#[allow(missing_docs)]
OneLine,
#[allow(missing_docs)]
#[default]
TwoLine,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum Font {
#[allow(missing_docs)]
#[default]
Font5x8,
#[allow(missing_docs)]
Font5x11,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum RAMType {
#[default]
DDRam,
CGRam,
}
pub struct Command {
rs: RegisterSelection,
rw: ReadWriteOp,
data: Option<Bits>, }
#[derive(Clone, Copy, PartialEq)]
pub enum RegisterSelection {
Command,
Data,
}
#[derive(Clone, Copy, PartialEq)]
pub enum ReadWriteOp {
Write,
Read,
}
#[derive(Clone, Copy, PartialEq)]
pub enum Bits {
Bit4(u8),
Bit8(u8),
}
#[allow(dead_code)]
impl Command {
pub(crate) fn new(rs: RegisterSelection, rw: ReadWriteOp, data: Option<Bits>) -> Self {
if (rw == ReadWriteOp::Write) && (data.is_none()) {
panic!("Write Operation Should have Data");
}
Self { rs, rw, data }
}
pub(crate) fn get_register_selection(&self) -> RegisterSelection {
self.rs
}
pub(crate) fn set_register_selection(&mut self, rs: RegisterSelection) {
self.rs = rs
}
pub(crate) fn get_read_write_op(&self) -> ReadWriteOp {
self.rw
}
pub(crate) fn set_read_write_op(&mut self, rw: ReadWriteOp) {
self.rw = rw
}
pub(crate) fn get_data(&self) -> Option<Bits> {
self.data
}
pub(crate) fn set_data(&mut self, data: Option<Bits>) {
self.data = data
}
}
impl From<CommandSet> for Command {
fn from(command: CommandSet) -> Self {
match command {
CommandSet::ClearDisplay => {
let raw_bits: u8 = 0b0000_0001;
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::ReturnHome => {
let raw_bits: u8 = 0b0000_0010;
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::EntryModeSet(dir, st) => {
let mut raw_bits: u8 = 0b0000_0100;
match dir {
MoveDirection::RightToLeft => raw_bits.clear_bit(1),
MoveDirection::LeftToRight => raw_bits.set_bit(1),
};
match st {
ShiftType::CursorOnly => raw_bits.clear_bit(0),
ShiftType::CursorAndDisplay => raw_bits.set_bit(0),
};
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::DisplayOnOff {
display,
cursor,
cursor_blink,
} => {
let mut raw_bits = 0b0000_1000;
match display {
State::Off => raw_bits.clear_bit(2),
State::On => raw_bits.set_bit(2),
};
match cursor {
State::Off => raw_bits.clear_bit(1),
State::On => raw_bits.set_bit(1),
};
match cursor_blink {
State::Off => raw_bits.clear_bit(0),
State::On => raw_bits.set_bit(0),
};
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::CursorOrDisplayShift(st, dir) => {
let mut raw_bits = 0b0001_0000;
match st {
ShiftType::CursorOnly => raw_bits.clear_bit(3),
ShiftType::CursorAndDisplay => raw_bits.set_bit(3),
};
match dir {
MoveDirection::RightToLeft => raw_bits.clear_bit(2),
MoveDirection::LeftToRight => raw_bits.set_bit(2),
};
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::HalfFunctionSet => Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit4(0b0010)),
),
CommandSet::FunctionSet(width, line, font) => {
let mut raw_bits = 0b0010_0000;
match width {
DataWidth::Bit4 => raw_bits.clear_bit(4),
DataWidth::Bit8 => raw_bits.set_bit(4),
};
match line {
LineMode::OneLine => raw_bits.clear_bit(3),
LineMode::TwoLine => raw_bits.set_bit(3),
};
match font {
Font::Font5x8 => raw_bits.clear_bit(2),
Font::Font5x11 => raw_bits.set_bit(2),
};
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::SetCGRAM(addr) => {
let mut raw_bits = 0b0100_0000;
assert!(addr < 2u8.pow(6), "CGRAM address out of range");
raw_bits += addr;
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::SetDDRAM(addr) => {
let mut raw_bits = 0b1000_0000;
assert!(addr < 2u8.pow(7), "DDRAM address out of range");
raw_bits += addr;
Self::new(
RegisterSelection::Command,
ReadWriteOp::Write,
Some(Bits::Bit8(raw_bits)),
)
}
CommandSet::ReadBusyFlagAndAddress => {
Self::new(RegisterSelection::Command, ReadWriteOp::Read, None)
}
CommandSet::WriteDataToRAM(data) => Self::new(
RegisterSelection::Data,
ReadWriteOp::Write,
Some(Bits::Bit8(data)),
),
CommandSet::ReadDataFromRAM => {
Self::new(RegisterSelection::Data, ReadWriteOp::Read, None)
}
}
}
}