use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
use embedded_graphics_core::{
prelude::{DrawTarget, GrayColor, OriginDimensions, Point, Size},
Pixel,
};
use embedded_hal_1::{delay::DelayUs, digital::OutputPin};
use crate::pixelcolor::Gray5;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SSD1357<DI> {
di: DI,
}
impl<DI> SSD1357<DI>
where
DI: WriteOnlyDataCommand,
{
pub fn new(di: DI) -> Self {
Self { di }
}
pub fn hard_reset(
&mut self,
reset: &mut impl OutputPin,
delay: &mut impl DelayUs,
) -> Result<(), ()> {
reset.set_low();
delay.delay_ms(10);
reset.set_high();
delay.delay_ms(200);
Ok(())
}
pub fn reset(&mut self, delay: &mut impl DelayUs) -> Result<(), ()> {
Ok(())
}
pub fn init(&mut self, delay: &mut impl DelayUs) -> Result<(), DisplayError> {
self.di.send_commands(DataFormat::U8(&[0xFD]))?;
self.di.send_data(DataFormat::U8(&[0x12]))?;
self.di.send_commands(DataFormat::U8(&[0xAE]))?;
self.di.send_commands(DataFormat::U8(&[0xB1]))?; self.di.send_data(DataFormat::U8(&[0xff]))?;
self.di.send_commands(DataFormat::U8(&[0xB3]))?; self.di.send_data(DataFormat::U8(&[0xF0]))?;
self.di.send_commands(DataFormat::U8(&[0xB6]))?; self.di.send_data(DataFormat::U8(&[0b1000]))?;
self.di.send_commands(DataFormat::U8(&[0xC1]))?; self.di.send_data(DataFormat::U8(&[0x7f, 0x7f, 0x7f]))?;
self.di.send_commands(DataFormat::U8(&[0xC7]))?; self.di.send_data(DataFormat::U8(&[0x0F]))?;
self.di.send_commands(DataFormat::U8(&[0xB8]))?; self.di.send_data(DataFormat::U8(&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x25,
0x27, 0x2A, 0x2D, 0x30, 0x33, 0x36, 0x39, 0x3C, 0x3F, 0x42, 0x45, 0x48, 0x4C, 0x50,
0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74, 0x78, 0x7D, 0x82, 0x87, 0x8C,
0x91, 0x96, 0x9B, 0xA0, 0xA5, 0xAA, 0xAF,
]))?;
self.di.send_commands(DataFormat::U8(&[0xBB]))?;
self.di.send_data(DataFormat::U8(&[0x1E]))?;
self.di.send_commands(DataFormat::U8(&[0xBE]))?;
self.di.send_data(DataFormat::U8(&[0x07]))?;
self.di.send_commands(DataFormat::U8(&[0x15]))?;
self.di.send_data(DataFormat::U8(&[0x00, 0x7F]))?;
self.di.send_commands(DataFormat::U8(&[0x75]))?;
self.di.send_data(DataFormat::U8(&[0x00, 0x7F]))?;
self.di.send_commands(DataFormat::U8(&[0xCA]))?; self.di.send_data(DataFormat::U8(&[95]))?;
self.di.send_commands(DataFormat::U8(&[0xA1]))?; self.di.send_data(DataFormat::U8(&[0x00]))?;
self.di.send_commands(DataFormat::U8(&[0xA2]))?; self.di.send_data(DataFormat::U8(&[0x00]))?;
self.di.send_commands(DataFormat::U8(&[0xA0]))?;
self.di.send_data(DataFormat::U8(&[0b01_1_00000, 0x00]))?;
self.di.send_commands(DataFormat::U8(&[0xA6]))?;
self.di.send_commands(DataFormat::U8(&[0xAF]))?;
Ok(())
}
pub fn update(&mut self, fb: &Framebuffer565) -> Result<(), DisplayError> {
self.di.send_commands(DataFormat::U8(&[0x15]))?;
self.di.send_data(DataFormat::U8(&[32, 32 + 66 - 1]))?;
self.di.send_commands(DataFormat::U8(&[0x75]))?;
self.di.send_data(DataFormat::U8(&[0, 96 - 1]))?;
self.di.send_commands(DataFormat::U8(&[0x5C]))?;
self.di.send_data(DataFormat::U8(&fb.data[..]))?;
Ok(())
}
}
const WIDTH: usize = 66 * 3; const HEIGHT: usize = 96;
const WIDTH_UNCOMPRESSED: usize = 66;
pub struct Framebuffer565 {
data: [u8; WIDTH_UNCOMPRESSED * HEIGHT * 2],
}
impl Framebuffer565 {
pub fn new() -> Self {
Self {
data: [0; WIDTH_UNCOMPRESSED * HEIGHT * 2],
}
}
}
impl OriginDimensions for Framebuffer565 {
fn size(&self) -> Size {
Size::new(196, HEIGHT as _)
}
}
impl DrawTarget for Framebuffer565 {
type Color = Gray5;
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for Pixel(Point { x, y }, color) in pixels.into_iter() {
let x = x as usize;
let y = y as usize;
if y >= HEIGHT {
continue;
}
if x >= WIDTH {
continue;
}
let color = color.luma() as u8;
let index = (y * WIDTH_UNCOMPRESSED + x / 3) * 2;
if x % 3 == 2 {
let raw_pix = self.data[index];
self.data[index] = (raw_pix & 0b00000_111) | (color << 3);
} else if x % 3 == 1 {
let raw_pix_h = self.data[index];
self.data[index] = (raw_pix_h & 0b11111_000) | (color >> 2);
let raw_pix_l = self.data[index + 1];
self.data[index + 1] = (raw_pix_l & 0b000_11111) | (color << 6);
} else {
let raw_pix = self.data[index + 1];
self.data[index + 1] = (raw_pix & 0b111_00000) | color;
}
}
Ok(())
}
}