#![no_std]
mod command;
mod error;
mod mode;
use command::{Booster, Command};
use error::Error;
use mode::{BasicMode, BufferedGraphicsMode};
use display_interface::{DataFormat::U8, DisplayError, WriteOnlyDataCommand};
use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin};
#[derive(Copy, Clone, Debug)]
pub struct Ist7920<DI, MODE> {
interface: DI,
mode: MODE,
}
impl<DI> Ist7920<DI, BasicMode>
where
DI: WriteOnlyDataCommand,
{
pub fn new(interface: DI) -> Self {
Self {
interface,
mode: BasicMode,
}
}
}
impl<DI, MODE> Ist7920<DI, MODE>
where
DI: WriteOnlyDataCommand,
{
fn into_mode<MODE2>(self, mode: MODE2) -> Ist7920<DI, MODE2> {
Ist7920 {
interface: self.interface,
mode,
}
}
pub fn into_buffered_graphics_mode(self) -> Ist7920<DI, BufferedGraphicsMode> {
self.into_mode(BufferedGraphicsMode::new())
}
pub fn init<DELAY>(&mut self, delay: &mut DELAY) -> Result<(), DisplayError>
where
DELAY: DelayMs<u8>,
{
Command::SWReset.send(&mut self.interface)?;
delay.delay_ms(50);
Command::DisplayOn(false).send(&mut self.interface)?;
Command::Duty(128).send(&mut self.interface)?;
Command::Bias(16).send(&mut self.interface)?;
Command::VoltageClock(0x3f).send(&mut self.interface)?;
Command::PowerControl(0x20).send(&mut self.interface)?;
delay.delay_ms(100);
Command::PowerControl(0x2c).send(&mut self.interface)?;
delay.delay_ms(100);
Command::Booster(Booster::VddX3).send(&mut self.interface)?;
delay.delay_ms(100);
Command::PowerControl(0x2f).send(&mut self.interface)?;
delay.delay_ms(200);
Command::DisplayControl(false, true, false, false).send(&mut self.interface)?;
Command::AYWindow(0x0, 0xf).send(&mut self.interface)?;
Command::AXWindow(0x0, 0x7f).send(&mut self.interface)?;
Command::StartLine(64).send(&mut self.interface)?;
Command::AYAddress(0).send(&mut self.interface)?;
Command::AXAddress(0).send(&mut self.interface)?;
Command::Contrast(110).send(&mut self.interface)?;
Command::DisplayOn(true).send(&mut self.interface)?;
Ok(())
}
pub fn draw(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
self.interface.send_data(U8(&buffer))
}
pub fn set_display_on(&mut self, on: bool) -> Result<(), DisplayError> {
Command::DisplayOn(on).send(&mut self.interface)
}
pub fn set_draw_area(&mut self, start: (u8, u8), end: (u8, u8)) -> Result<(), DisplayError> {
Command::AYWindow(start.0 / 8, end.0 / 8).send(&mut self.interface)?;
Command::AXWindow(start.0, end.0).send(&mut self.interface)?;
Command::AXAddress(start.1).send(&mut self.interface)?;
Command::AYAddress(start.0 / 8).send(&mut self.interface)?;
Ok(())
}
fn flush_buffer_chunks(interface: &mut DI, buffer: &[u8]) -> Result<(), DisplayError> {
interface.send_data(U8(&buffer))
}
pub fn reset<RST, DELAY, PinE>(
&mut self,
rst: &mut RST,
delay: &mut DELAY,
) -> Result<(), Error<(), PinE>>
where
RST: OutputPin<Error = PinE>,
DELAY: DelayMs<u8>,
{
inner_reset(rst, delay)
}
}
fn inner_reset<RST, DELAY, PinE>(rst: &mut RST, delay: &mut DELAY) -> Result<(), Error<(), PinE>>
where
RST: OutputPin<Error = PinE>,
DELAY: DelayMs<u8>,
{
rst.set_high().map_err(Error::Pin)?;
delay.delay_ms(1);
rst.set_low().map_err(Error::Pin)?;
delay.delay_ms(10);
rst.set_high().map_err(Error::Pin)?;
delay.delay_ms(20);
Ok(())
}