use embedded_graphics::pixelcolor::{Gray2, Gray4};
use embedded_hal::blocking::delay::DelayUs;
use crate::interface::{self, DisplayInterface};
use super::{Driver, GrayScaleDriver};
pub struct SSD1608;
impl Driver for SSD1608 {
type Error = interface::DisplayError;
fn wake_up<DI: DisplayInterface, DELAY: DelayUs<u32>>(
di: &mut DI,
delay: &mut DELAY,
) -> Result<(), Self::Error> {
di.reset(delay, 200_000, 200_000);
di.busy_wait();
defmt::debug!("wake up");
di.send_command(0x12)?; di.busy_wait();
di.send_command_data(0x0c, &[0xd7, 0xd6, 0x9d])?;
di.send_command_data(0x2c, &[0x7c])?;
di.send_command_data(0x3a, &[0x1a])?;
di.send_command_data(0x3b, &[0x08])?;
di.send_command_data(0x3c, &[0b1_1_10_00_00])?;
di.send_command_data(0x11, &[0x03])?;
#[rustfmt::skip]
const EPD_2_IN13_LUT_FULL_UPDATE: [u8; 30] = [
0x50, 0xAA, 0x55, 0xAA, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x1F, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
#[rustfmt::skip]
const EPD_2_IN13_LUT_PARTIAL_UPDATE: [u8; 30] = [
0b10_01_10_01,
0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
];
di.send_command_data(0x32, &EPD_2_IN13_LUT_PARTIAL_UPDATE)?;
Ok(())
}
fn set_shape<DI: DisplayInterface>(di: &mut DI, x: u16, y: u16) -> Result<(), Self::Error> {
di.send_command_data(0x01, &[((y - 1) & 0xff) as u8, ((y - 1) >> 8) as u8, 0])?;
di.send_command_data(0x44, &[0, ((x - 1) >> 3) as u8])?;
di.send_command_data(0x45, &[0, 0, ((y - 1) & 0xff) as u8, ((y - 1) >> 8) as u8])?;
Ok(())
}
fn update_frame<'a, DI: DisplayInterface, I>(di: &mut DI, buffer: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = &'a u8>,
{
di.send_command_data(0x4E, &[0])?;
di.send_command_data(0x4f, &[0, 0])?;
di.send_command(0x24)?;
di.send_data_from_iter(buffer)?;
di.send_command(0xff)?;
Ok(())
}
fn turn_on_display<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
di.send_command_data(0x22, &[0xc4])?; di.send_command(0x20)?;
di.send_command(0xff)?;
di.busy_wait();
Ok(())
}
fn sleep<DI: DisplayInterface, DELAY: DelayUs<u32>>(
di: &mut DI,
_delay: &mut DELAY,
) -> Result<(), Self::Error> {
di.send_command_data(0x10, &[0x01])?;
Ok(())
}
}
pub struct SSD1608Fast;
impl Driver for SSD1608Fast {
type Error = interface::DisplayError;
fn wake_up<DI: DisplayInterface, DELAY: DelayUs<u32>>(
di: &mut DI,
delay: &mut DELAY,
) -> Result<(), Self::Error> {
#[rustfmt::skip]
const LUT_FAST_UPDATE: [u8; 30] = [
0b10_01_10_01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
];
SSD1608::wake_up(di, delay)?;
di.send_command_data(0x32, &LUT_FAST_UPDATE)?;
Ok(())
}
fn set_shape<DI: DisplayInterface>(di: &mut DI, x: u16, y: u16) -> Result<(), Self::Error> {
SSD1608::set_shape(di, x, y)
}
fn update_frame<'a, DI: DisplayInterface, I>(di: &mut DI, buffer: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = &'a u8>,
{
SSD1608::update_frame(di, buffer)
}
fn turn_on_display<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
SSD1608::turn_on_display(di)
}
}
impl GrayScaleDriver<Gray2> for SSD1608 {
fn setup_gray_scale<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
#[rustfmt::skip]
const LUT_INCREMENTAL_DIV_2: [u8; 30] = [
0b00_01_00_00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
];
di.send_command_data(0x32, &LUT_INCREMENTAL_DIV_2)?;
Ok(())
}
fn restore_normal_mode<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
#[rustfmt::skip]
const LUT_FULL_UPDATE: [u8; 30] = [
0x50, 0xAA, 0x55, 0xAA, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x1F, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
di.send_command_data(0x32, &LUT_FULL_UPDATE)?;
Ok(())
}
}
impl GrayScaleDriver<Gray4> for SSD1608 {
fn setup_gray_scale<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
#[rustfmt::skip]
const LUT_INCREMENTAL_DIV_2: [u8; 30] = [
0b00_01_00_01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00
];
di.send_command_data(0x2c, &[0xb8])?;
di.send_command_data(0x04, &[0b0000])?;
di.send_command_data(0x3b, &[0b0000])?;
di.send_command_data(0x32, &LUT_INCREMENTAL_DIV_2)?;
Ok(())
}
fn restore_normal_mode<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
#[rustfmt::skip]
const LUT_FULL_UPDATE: [u8; 30] = [
0x50, 0xAA, 0x55, 0xAA, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x1F, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
di.send_command_data(0x32, &LUT_FULL_UPDATE)?;
Ok(())
}
}