use crate::DisplayInterface;
macro_rules! pack {
($buf:ident, $cmd:expr,[]) => {
($cmd, &$buf[..0])
};
($buf:ident, $cmd:expr,[$arg0:expr]) => {{
$buf[0] = $arg0;
($cmd, &$buf[..1])
}};
($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr]) => {{
$buf[0] = $arg0;
$buf[1] = $arg1;
($cmd, &$buf[..2])
}};
($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr, $arg2:expr]) => {{
$buf[0] = $arg0;
$buf[1] = $arg1;
$buf[2] = $arg2;
($cmd, &$buf[..3])
}};
($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr]) => {{
$buf[0] = $arg0;
$buf[1] = $arg1;
$buf[2] = $arg2;
$buf[3] = $arg3;
($cmd, &$buf[..4])
}};
}
#[derive(Clone, Copy)]
pub enum IncrementAxis {
Horizontal,
Vertical,
}
#[derive(Clone, Copy)]
pub enum DataEntryMode {
DecrementXDecrementY,
IncrementXDecrementY,
DecrementXIncrementY,
IncrementYIncrementX,
}
#[derive(Clone, Copy)]
pub enum RamOption {
Normal = 0x00,
Bypass = 0x04,
Invert = 0x08,
}
#[derive(Clone, Copy)]
pub enum DeepSleepMode {
Normal,
PreserveRAM,
DiscardRAM,
}
#[derive(Clone, Copy)]
pub enum Command {
DriverOutputControl(u16, u8),
GateDrivingVoltage(u8),
SourceDrivingVoltage(u8, u8, u8),
BoosterSoftStart(u8, u8, u8, u8),
DeepSleepMode(DeepSleepMode),
DataEntryMode(DataEntryMode, IncrementAxis),
SoftReset,
ReadTemperatureSensor(u8),
WriteTemperatureSensor(u8),
MasterActivation,
DisplayUpdateControl1(u16),
DisplayUpdateControl2(u8),
WriteRamBW,
WriteRamRed,
WriteVCOM(u8),
BorderWaveform(u8),
StartEndXPosition(u8, u8),
StartEndYPosition(u16, u16),
XAddress(u8),
YAddress(u16),
Nop,
}
impl Command {
pub fn execute<I: DisplayInterface>(&self, interface: &mut I) -> Result<(), I::Error> {
use self::Command::*;
let mut buf = [0u8; 4];
let (command, data) = match *self {
DriverOutputControl(gate_lines, scanning_seq_and_dir) => {
let [upper, lower] = gate_lines.to_be_bytes();
pack!(buf, 0x01, [lower, upper, scanning_seq_and_dir])
}
GateDrivingVoltage(voltages) => pack!(buf, 0x03, [voltages]),
SourceDrivingVoltage(vsh1, vsh2, vsl) => pack!(buf, 0x04, [vsh1, vsh2, vsl]),
BoosterSoftStart(phase1, phase2, phase3, duration) => {
pack!(buf, 0x0C, [phase1, phase2, phase3, duration])
}
DeepSleepMode(mode) => {
let mode = match mode {
self::DeepSleepMode::Normal => 0b00,
self::DeepSleepMode::PreserveRAM => 0b01,
self::DeepSleepMode::DiscardRAM => 0b11,
};
pack!(buf, 0x10, [mode])
}
DataEntryMode(data_entry_mode, increment_axis) => {
let mode = match data_entry_mode {
self::DataEntryMode::DecrementXDecrementY => 0b00,
self::DataEntryMode::IncrementXDecrementY => 0b01,
self::DataEntryMode::DecrementXIncrementY => 0b10,
self::DataEntryMode::IncrementYIncrementX => 0b11,
};
let axis = match increment_axis {
IncrementAxis::Horizontal => 0b000,
IncrementAxis::Vertical => 0b100,
};
pack!(buf, 0x11, [axis | mode])
}
SoftReset => pack!(buf, 0x12, []),
ReadTemperatureSensor(data) => pack!(buf, 0x18, [data]),
WriteTemperatureSensor(data) => {
pack!(buf, 0x1A, [data])
}
MasterActivation => pack!(buf, 0x20, []),
DisplayUpdateControl1(data) => {
let [upper, lower] = data.to_be_bytes();
pack!(buf, 0x21, [upper, lower])
}
DisplayUpdateControl2(value) => pack!(buf, 0x22, [value]),
WriteRamBW => pack!(buf, 0x24, []),
WriteRamRed => pack!(buf, 0x26, []),
WriteVCOM(value) => pack!(buf, 0x2C, [value]),
BorderWaveform(border_waveform) => pack!(buf, 0x3C, [border_waveform]),
StartEndXPosition(start, end) => pack!(buf, 0x44, [start, end]),
StartEndYPosition(start, end) => {
let [start_upper, start_lower] = start.to_be_bytes();
let [end_upper, end_lower] = end.to_be_bytes();
pack!(buf, 0x45, [start_lower, start_upper, end_lower, end_upper])
}
XAddress(address) => pack!(buf, 0x4E, [address]),
YAddress(address) => {
let [upper, lower] = address.to_be_bytes();
pack!(buf, 0x4F, [lower, upper])
}
Nop => pack!(buf, 0x7F, []),
};
interface.send_command(command)?;
if data.is_empty() {
Ok(())
} else {
interface.send_data(data)
}
}
}