use embedded_hal::{delay::DelayNs, digital::*, spi::SpiDevice};
use crate::interface::DisplayInterface;
use crate::traits::{EEIDisplay, EEIInit};
pub const WIDTH: u32 = 56;
pub const HEIGHT: u32 = 256;
pub const DEFAULT_BACKGROUND_COLOR: Color = Color::Dark;
const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8;
use crate::color::Color;
pub(crate) mod command;
#[cfg(feature = "graphics")]
mod graphics;
use self::command::Command;
#[cfg(feature = "graphics")]
pub use self::graphics::Display256x50;
pub struct VFD256x50<SPI, CS, RST, DELAY> {
interface: DisplayInterface<SPI, CS, RST, DELAY>,
}
impl<SPI, CS, RST, DELAY> EEIInit<SPI, CS, RST, DELAY> for VFD256x50<SPI, CS, RST, DELAY>
where
SPI: SpiDevice,
CS: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
self.interface.reset(delay, 1);
self.command(spi, Command::Reset)?;
self.cmd_with_args(spi, Command::VFDModeSetting, [0x02, 0x00])?;
self.cmd_with_args(
spi,
Command::DisplayAreaSetting,
[0xFF, 0x31, 0x00, 0x20, 0x00, 0x00, 0x80],
)?;
self.cmd_with_args(spi, Command::InternalSpeedSetting, [0x20, 0x3F, 0x00, 0x01])?;
self.set_brightness(spi, 0x30)?;
self.command(spi, Command::ClearGRAM)?;
delay.delay_ms(10);
self.cmd_with_args(spi, Command::DisplayPosition1Offset, [0x00, 0x04])?;
self.cmd_with_args(spi, Command::DisplayPosition2Offset, [0x00, 0x3c])?;
self.cmd_with_args(spi, Command::UnknownInit, [0x00])?;
self.cmd_with_args(spi, Command::DisplayModeSetting, [0x00])?;
self.cmd_with_args(spi, Command::FrameSyncSetting, [0x00])
}
}
impl<SPI, CS, RST, DELAY> EEIDisplay<SPI, CS, RST, DELAY> for VFD256x50<SPI, CS, RST, DELAY>
where
SPI: SpiDevice,
CS: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
type DisplayColor = Color;
fn new(spi: &mut SPI, cs: CS, rst: RST, delay: &mut DELAY) -> Result<Self, SPI::Error> {
let interface = DisplayInterface::new(cs, rst);
let mut vfd = VFD256x50 { interface };
vfd.init(spi, delay)?;
Ok(vfd)
}
fn set_brightness(&mut self, spi: &mut SPI, val: u32) -> Result<(), SPI::Error> {
self.cmd_with_args(
spi,
Command::BrightnessSetting,
[((val >> 8) as u8) & 0b11, val as u8],
)
}
fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> {
self.command(spi, Command::Sleep)
}
fn wake_up(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> {
self.command(spi, Command::WakeUp)
}
fn width(&self) -> u32 {
WIDTH
}
fn height(&self) -> u32 {
HEIGHT
}
fn update_frame(
&mut self,
spi: &mut SPI,
buffer: &[u8],
_delay: &mut DELAY,
) -> Result<(), SPI::Error> {
self.cmd_with_data(
spi,
Command::WriteGRAM,
[0x00, 0x04, 0x37],
buffer.iter().copied(),
)
}
#[allow(unused)]
fn update_partial_frame(
&mut self,
spi: &mut SPI,
buffer: &[u8],
x: u32,
y: u32,
width: u32,
height: u32,
) -> Result<(), SPI::Error> {
unimplemented!()
}
fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
self.command(spi, Command::ClearGRAM)?;
delay.delay_ms(10);
Ok(())
}
}
impl<SPI, CS, RST, DELAY> VFD256x50<SPI, CS, RST, DELAY>
where
SPI: SpiDevice,
CS: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
self.cmd_with_args(spi, command, [])
}
fn cmd_with_args(
&mut self,
spi: &mut SPI,
command: Command,
args: impl IntoIterator<Item = u8>,
) -> Result<(), SPI::Error> {
self.interface.cmd_with_arg(spi, command, args)
}
fn cmd_with_data(
&mut self,
spi: &mut SPI,
command: Command,
args: impl IntoIterator<Item = u8>,
data: impl IntoIterator<Item = u8>,
) -> Result<(), SPI::Error> {
self.interface.cmd_with_data(spi, command, args, data)
}
}