use display_interface::DisplayError;
use embedded_graphics::{
pixelcolor::{BinaryColor, Gray2},
prelude::*,
};
use crate::graphics::buffer_len;
use crate::graphics::DisplayRotation;
pub const WIDTH: u16 = 128;
pub const HEIGHT: u16 = 296;
pub struct Display2in9Gray2 {
high_buffer: [u8; buffer_len(WIDTH as usize, HEIGHT as usize)],
low_buffer: [u8; buffer_len(WIDTH as usize, HEIGHT as usize)],
rotation: DisplayRotation,
}
impl Default for Display2in9Gray2 {
fn default() -> Self {
Self::new()
}
}
impl Display2in9Gray2 {
pub fn new() -> Self {
Self {
high_buffer: [0xFF; buffer_len(WIDTH as usize, HEIGHT as usize)],
low_buffer: [0xFF; buffer_len(WIDTH as usize, HEIGHT as usize)],
rotation: DisplayRotation::Rotate270,
}
}
pub fn high_buffer(&self) -> &[u8] {
&self.high_buffer
}
pub fn low_buffer(&self) -> &[u8] {
&self.low_buffer
}
pub fn get_mut_high_buffer(&mut self) -> &mut [u8] {
&mut self.high_buffer
}
pub fn get_mut_low_buffer(&mut self) -> &mut [u8] {
&mut self.low_buffer
}
pub fn set_rotation(&mut self, rotation: DisplayRotation) {
self.rotation = rotation;
}
pub fn rotation(&self) -> DisplayRotation {
self.rotation
}
pub fn clear_buffer(&mut self, level: Gray2) {
let storage = level.into_storage();
let dtm1_byte = if (storage & 0b01) != 0 { 0xFF } else { 0x00 };
let dtm2_byte = if (storage & 0b10) != 0 { 0xFF } else { 0x00 };
self.high_buffer.fill(dtm1_byte);
self.low_buffer.fill(dtm2_byte);
}
pub fn set_pixel(&mut self, x: i32, y: i32, level: Gray2) {
if super::outside_display(Point::new(x, y), WIDTH.into(), HEIGHT.into(), self.rotation) {
return;
}
let (idx_u32, bit) = super::find_position(
x as u32,
y as u32,
WIDTH.into(),
HEIGHT.into(),
self.rotation,
);
let idx = idx_u32 as usize;
let storage = level.into_storage();
let dtm1_val = (storage & 0b01) != 0;
let dtm2_val = (storage & 0b10) != 0;
if dtm1_val {
self.high_buffer[idx] |= bit;
} else {
self.high_buffer[idx] &= !bit;
}
if dtm2_val {
self.low_buffer[idx] |= bit;
} else {
self.low_buffer[idx] &= !bit;
}
}
pub fn as_binary_draw_target(&mut self) -> BinaryDrawTarget<'_> {
BinaryDrawTarget::new(self)
}
}
impl DrawTarget for Display2in9Gray2 {
type Error = DisplayError;
type Color = Gray2;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for Pixel(point, color) in pixels {
self.set_pixel(point.x, point.y, color);
}
Ok(())
}
}
impl OriginDimensions for Display2in9Gray2 {
fn size(&self) -> Size {
match self.rotation {
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => {
Size::new(WIDTH.into(), HEIGHT.into())
}
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => {
Size::new(HEIGHT.into(), WIDTH.into())
}
}
}
}
pub struct BinaryDrawTarget<'a>(&'a mut Display2in9Gray2);
impl<'a> BinaryDrawTarget<'a> {
pub fn new(display: &'a mut Display2in9Gray2) -> Self {
Self(display)
}
}
impl DrawTarget for BinaryDrawTarget<'_> {
type Color = BinaryColor;
type Error = DisplayError;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for Pixel(point, color) in pixels {
let level = match color {
BinaryColor::On => Gray2::WHITE,
BinaryColor::Off => Gray2::BLACK,
};
self.0.set_pixel(point.x, point.y, level);
}
Ok(())
}
}
impl OriginDimensions for BinaryDrawTarget<'_> {
fn size(&self) -> Size {
match self.0.rotation {
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => {
Size::new(WIDTH.into(), HEIGHT.into())
}
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => {
Size::new(HEIGHT.into(), WIDTH.into())
}
}
}
}