use embedded_hal::delay::DelayNs;
use embedded_hal::digital::{InputPin, OutputPin};
use embedded_hal::spi::SpiDevice;
use crate::bus::{EpdBusError, SpiBusWrapper};
use crate::traits::{ColorChannel, EpdController};
pub mod cmd {
pub const PANEL_SETTING: u8 = 0x00;
pub const POWER_SETTING: u8 = 0x01;
pub const POWER_OFF: u8 = 0x02;
pub const POWER_OFFSET: u8 = 0x03;
pub const POWER_ON: u8 = 0x04;
pub const BOOSTER_SOFT_START: u8 = 0x06;
pub const DEEP_SLEEP: u8 = 0x07;
pub const DATA_START_TRANSMISSION: u8 = 0x10;
pub const DISPLAY_REFRESH: u8 = 0x12;
pub const VCOM_CONTROL: u8 = 0x30;
pub const MAGIC_KEY: u8 = 0x4D;
pub const CDI: u8 = 0x50;
pub const TCON: u8 = 0x60;
pub const RESOLUTION: u8 = 0x61;
}
#[derive(Debug, Clone, Copy)]
pub struct Jd79661Controller {
width: u32,
height: u32,
}
impl Jd79661Controller {
pub fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
}
impl<SPI, DC, RST, BUSY> EpdController<SpiBusWrapper<SPI, DC, RST, BUSY>> for Jd79661Controller
where
SPI: SpiDevice,
DC: OutputPin,
RST: OutputPin,
BUSY: InputPin,
{
type Error = EpdBusError<SPI::Error, DC::Error, RST::Error, BUSY::Error>;
fn init_sequence<DELAY: DelayNs>(
&mut self,
bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
delay: &mut DELAY,
) -> Result<(), Self::Error> {
bus.hard_reset(delay, 10)?;
bus.wait_busy(false)?;
bus.send_command_with_data(cmd::POWER_SETTING, &[])?;
bus.wait_busy(false)?;
bus.send_command_with_data(cmd::MAGIC_KEY, &[0x78])?;
bus.send_command_with_data(cmd::PANEL_SETTING, &[0x8F, 0x29])?;
bus.send_command_with_data(cmd::POWER_SETTING, &[0x07, 0x00])?;
bus.send_command_with_data(cmd::POWER_OFFSET, &[0x10, 0x54, 0x44])?;
bus.send_command_with_data(
cmd::BOOSTER_SOFT_START,
&[0x05, 0x00, 0x3F, 0x0A, 0x25, 0x12, 0x1A],
)?;
bus.send_command_with_data(cmd::CDI, &[0x37])?;
bus.send_command_with_data(cmd::TCON, &[0x02, 0x02, 0x02])?;
let ram_width = self.width.div_ceil(8) * 8;
let w_high = ((ram_width >> 8) & 0xFF) as u8;
let w_low = (ram_width & 0xFF) as u8;
let h_high = ((self.height >> 8) & 0xFF) as u8;
let h_low = (self.height & 0xFF) as u8;
bus.send_command_with_data(cmd::RESOLUTION, &[w_high, w_low, h_high, h_low])?;
bus.send_command_with_data(0xE7, &[0x1C])?;
bus.send_command_with_data(0xE3, &[0x22])?;
bus.send_command_with_data(0xB4, &[0xD0])?;
bus.send_command_with_data(0xB5, &[0x03])?;
bus.send_command_with_data(0xE9, &[0x01])?;
bus.send_command_with_data(cmd::VCOM_CONTROL, &[0x08])?;
bus.send_command(cmd::POWER_ON)?;
bus.wait_busy(false)?;
Ok(())
}
fn set_window(
&mut self,
_bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_x_start: u32,
_y_start: u32,
_x_end: u32,
_y_end: u32,
) -> Result<(), Self::Error> {
Ok(())
}
fn set_cursor(
&mut self,
_bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_x: u32,
_y: u32,
) -> Result<(), Self::Error> {
Ok(())
}
fn write_frame(
&mut self,
bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_channel: ColorChannel,
data: &[u8],
) -> Result<(), Self::Error> {
bus.send_command_with_data(cmd::DATA_START_TRANSMISSION, data)
}
fn write_frame_pattern(
&mut self,
bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_channel: ColorChannel,
byte: u8,
count: usize,
) -> Result<(), Self::Error> {
bus.send_command(cmd::DATA_START_TRANSMISSION)?;
bus.send_data_repeated(byte, count)
}
fn trigger_refresh<DELAY: DelayNs>(
&mut self,
bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_delay: &mut DELAY,
) -> Result<(), Self::Error> {
bus.send_command(cmd::DISPLAY_REFRESH)?;
bus.wait_busy(false)
}
fn sleep<DELAY: DelayNs>(
&mut self,
bus: &mut SpiBusWrapper<SPI, DC, RST, BUSY>,
_delay: &mut DELAY,
) -> Result<(), Self::Error> {
bus.send_command(cmd::POWER_OFF)?;
bus.wait_busy(false)?;
bus.send_command_with_data(cmd::DEEP_SLEEP, &[0xA5])
}
}