use hal::blocking::delay::DelayMs;
use hal::digital::OutputPin;
use crate::displayrotation::DisplayRotation;
use crate::displaysize::DisplaySize;
use crate::interface::DisplayInterface;
use crate::mode::displaymode::DisplayModeTrait;
use crate::properties::DisplayProperties;
pub struct GraphicsMode<DI>
where
DI: DisplayInterface,
{
properties: DisplayProperties<DI>,
buffer: [u8; 1024],
}
impl<DI> DisplayModeTrait<DI> for GraphicsMode<DI>
where
DI: DisplayInterface,
{
fn new(properties: DisplayProperties<DI>) -> Self {
GraphicsMode {
properties,
buffer: [0; 1024],
}
}
fn release(self) -> DisplayProperties<DI> {
self.properties
}
}
impl<DI> GraphicsMode<DI>
where
DI: DisplayInterface,
{
pub fn clear(&mut self) {
self.buffer = [0; 1024];
}
pub fn reset<RST, DELAY>(&mut self, rst: &mut RST, delay: &mut DELAY)
where
RST: OutputPin,
DELAY: DelayMs<u8>,
{
rst.set_high();
delay.delay_ms(1);
rst.set_low();
delay.delay_ms(10);
rst.set_high();
}
pub fn flush(&mut self) -> Result<(), ()> {
let display_size = self.properties.get_size();
let (display_width, display_height) = display_size.dimensions();
self.properties
.set_draw_area((0, 0), (display_width, display_height))?;
match display_size {
DisplaySize::Display128x64 => self.properties.draw(&self.buffer),
DisplaySize::Display128x32 => self.properties.draw(&self.buffer[0..512]),
DisplaySize::Display96x16 => self.properties.draw(&self.buffer[0..192]),
}
}
pub fn set_pixel(&mut self, x: u32, y: u32, value: u8) {
let (display_width, _) = self.properties.get_size().dimensions();
let display_rotation = self.properties.get_rotation();
let idx = match display_rotation {
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => {
if x >= display_width as u32 {
return;
}
((y as usize) / 8 * display_width as usize) + (x as usize)
}
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => {
if y >= display_width as u32 {
return;
}
((x as usize) / 8 * display_width as usize) + (y as usize)
}
};
if idx >= self.buffer.len() {
return;
}
let (byte, bit) = match display_rotation {
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => {
let byte =
&mut self.buffer[((y as usize) / 8 * display_width as usize) + (x as usize)];
let bit = 1 << (y % 8);
(byte, bit)
}
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => {
let byte =
&mut self.buffer[((x as usize) / 8 * display_width as usize) + (y as usize)];
let bit = 1 << (x % 8);
(byte, bit)
}
};
if value == 0 {
*byte &= !bit;
} else {
*byte |= bit;
}
}
pub fn init(&mut self) -> Result<(), ()> {
self.properties.init_column_mode()?;
Ok(())
}
pub fn get_dimensions(&self) -> (u8, u8) {
self.properties.get_dimensions()
}
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), ()> {
self.properties.set_rotation(rot)
}
}
#[cfg(feature = "graphics")]
extern crate embedded_graphics;
#[cfg(feature = "graphics")]
use self::embedded_graphics::{drawable, pixelcolor::PixelColorU8, Drawing};
#[cfg(feature = "graphics")]
impl<DI> Drawing<PixelColorU8> for GraphicsMode<DI>
where
DI: DisplayInterface,
{
fn draw<T>(&mut self, item_pixels: T)
where
T: Iterator<Item = drawable::Pixel<PixelColorU8>>,
{
for pixel in item_pixels {
self.set_pixel((pixel.0).0, (pixel.0).1, pixel.1.into_inner());
}
}
}
#[cfg(test)]
mod tests {
}