use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
use crate::{
command::Command, displayrotation::DisplayRotation, displaysize::DisplaySize,
};
pub struct DisplayProperties<DI> {
iface: DI,
display_size: DisplaySize,
display_rotation: DisplayRotation,
draw_area_start: (u8, u8),
draw_area_end: (u8, u8),
draw_column: u8,
draw_row: u8,
}
impl<DI> DisplayProperties<DI>
where
DI: WriteOnlyDataCommand,
{
pub fn new(
iface: DI,
display_size: DisplaySize,
display_rotation: DisplayRotation,
) -> DisplayProperties<DI> {
DisplayProperties {
iface,
display_size,
display_rotation,
draw_area_start: (0, 0),
draw_area_end: (0, 0),
draw_column: 0,
draw_row: 0,
}
}
pub fn init_column_mode(&mut self) -> Result<(), DisplayError> {
let display_rotation = self.display_rotation;
Command::DisplayClockDiv(0xa, 0x0).send(&mut self.iface)?;
self.set_rotation(display_rotation)?;
Command::Contrast(0x6f).send(&mut self.iface)?;
Command::PreChargePeriod(0x3, 0xd).send(&mut self.iface)?;
Command::ScrollActive(false).send(&mut self.iface)?;
Command::DisplayOn(true).send(&mut self.iface)?;
Ok(())
}
pub fn set_draw_area(&mut self, start: (u8, u8), end: (u8, u8)) -> Result<(), DisplayError> {
self.draw_area_start = start;
self.draw_area_end = end;
self.draw_column = start.0;
self.draw_row = start.1;
self.send_draw_address()
}
pub fn draw(&mut self, mut buffer: &[u8]) -> Result<(), DisplayError> {
while !buffer.is_empty() {
let count = self.draw_area_end.0 - self.draw_column;
self.iface.send_data(DataFormat::U8(&buffer[..count as usize]))?;
self.draw_column += count;
if self.draw_column >= self.draw_area_end.0 {
self.draw_column = self.draw_area_start.0;
self.draw_row += 8;
if self.draw_row >= self.draw_area_end.1 {
self.draw_row = self.draw_area_start.1;
}
self.send_draw_address()?;
}
buffer = &buffer[count as usize..];
}
Ok(())
}
fn send_draw_address(&mut self) -> Result<(), DisplayError> {
Command::PageAddress(self.draw_row.into()).send(&mut self.iface)?;
Command::ColumnAddressLow(0xF & self.draw_column).send(&mut self.iface)?;
Command::ColumnAddressHigh(0xF & (self.draw_column >> 4)).send(&mut self.iface)
}
pub fn get_size(&self) -> DisplaySize {
self.display_size
}
pub fn get_dimensions(&self) -> (u8, u8) {
let (w, h) = self.display_size.dimensions();
match self.display_rotation {
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => (w, h),
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => (h, w),
}
}
pub fn get_rotation(&self) -> DisplayRotation {
self.display_rotation
}
pub fn set_rotation(&mut self, display_rotation: DisplayRotation) -> Result<(), DisplayError> {
self.display_rotation = display_rotation;
match display_rotation {
DisplayRotation::Rotate0 => {
Command::SegmentRemap(true).send(&mut self.iface)?;
Command::ReverseComDir(true).send(&mut self.iface)
}
DisplayRotation::Rotate90 => {
Command::SegmentRemap(false).send(&mut self.iface)?;
Command::ReverseComDir(true).send(&mut self.iface)
}
DisplayRotation::Rotate180 => {
Command::SegmentRemap(false).send(&mut self.iface)?;
Command::ReverseComDir(false).send(&mut self.iface)
}
DisplayRotation::Rotate270 => {
Command::SegmentRemap(true).send(&mut self.iface)?;
Command::ReverseComDir(false).send(&mut self.iface)
}
}
}
pub fn display_on(&mut self, on: bool) -> Result<(), DisplayError> {
Command::DisplayOn(on).send(&mut self.iface)
}
pub fn set_contrast(&mut self, contrast: u8) -> Result<(), DisplayError> {
Command::Contrast(contrast).send(&mut self.iface)
}
}