mod buffering;
mod draw_target;
pub use buffering::{
framebuffer_size, Buffered, DoubleBuffered, Framebuffer, Unbuffered,
};
use core::marker::PhantomData;
use embedded_graphics_core::pixelcolor::raw::{RawData, RawU16};
use embedded_graphics_core::pixelcolor::{Gray8, GrayColor, Rgb565, Rgb888, RgbColor};
use embedded_graphics_core::prelude::PixelColor;
use embedded_hal::delay::DelayNs;
use crate::{
ColorMode, ControllerInterface, DriverResult, ResetInterface, St77916, St77916Builder,
};
pub trait St77916Color: PixelColor + Copy {
const BYTES_PER_PIXEL: usize;
fn encode(self, out: &mut [u8]);
fn fill_row(color: Self, row: &mut [u8]) {
let bpp = Self::BYTES_PER_PIXEL;
let mut tmp = [0u8; 4];
color.encode(&mut tmp[..bpp]);
for chunk in row.chunks_exact_mut(bpp) {
chunk.copy_from_slice(&tmp[..bpp]);
}
}
fn fill_buf(color: Self, buf: &mut [u8]) {
Self::fill_row(color, buf);
}
}
impl St77916Color for Rgb565 {
const BYTES_PER_PIXEL: usize = 2;
#[inline]
fn encode(self, out: &mut [u8]) {
let raw = RawU16::from(self).into_inner();
out[0] = (raw >> 8) as u8;
out[1] = raw as u8;
}
fn fill_buf(color: Self, buf: &mut [u8]) {
let raw = RawU16::from(color).into_inner();
let hi = (raw >> 8) as u8;
let lo = raw as u8;
if hi == lo {
buf.fill(hi);
} else {
for chunk in buf.chunks_exact_mut(2) {
chunk[0] = hi;
chunk[1] = lo;
}
}
}
}
impl St77916Color for Rgb888 {
const BYTES_PER_PIXEL: usize = 3;
#[inline]
fn encode(self, out: &mut [u8]) {
out[0] = self.r();
out[1] = self.g();
out[2] = self.b();
}
fn fill_buf(color: Self, buf: &mut [u8]) {
let r = color.r();
let g = color.g();
let b = color.b();
if r == g && r == b {
buf.fill(r);
} else {
for chunk in buf.chunks_exact_mut(3) {
chunk[0] = r;
chunk[1] = g;
chunk[2] = b;
}
}
}
}
impl St77916Color for Gray8 {
const BYTES_PER_PIXEL: usize = 1;
#[inline]
fn encode(self, out: &mut [u8]) {
out[0] = self.luma();
}
fn fill_buf(color: Self, buf: &mut [u8]) {
buf.fill(color.luma());
}
}
impl<IFACE, RST> St77916Builder<IFACE, RST, ()>
where
IFACE: ControllerInterface,
RST: ResetInterface,
{
pub fn buffered<COLOR: St77916Color>(
self,
framebuffer: Framebuffer,
) -> St77916Builder<IFACE, RST, Buffered<COLOR>> {
St77916Builder {
interface: self.interface,
reset: self.reset,
config: self.config,
init_commands: self.init_commands,
buffer: Buffered {
data: framebuffer,
dirty: buffering::DirtyBand::clean(),
_color: PhantomData,
},
}
}
pub fn double_buffered<COLOR: St77916Color>(
self,
fb1: Framebuffer,
fb2: Framebuffer,
) -> St77916Builder<IFACE, RST, DoubleBuffered<COLOR>> {
St77916Builder {
interface: self.interface,
reset: self.reset,
config: self.config,
init_commands: self.init_commands,
buffer: DoubleBuffered {
bufs: [fb1, fb2],
back_idx: 0,
_color: PhantomData,
},
}
}
pub fn unbuffered<COLOR: St77916Color>(
self,
) -> St77916Builder<IFACE, RST, Unbuffered<COLOR>> {
St77916Builder {
interface: self.interface,
reset: self.reset,
config: self.config,
init_commands: self.init_commands,
buffer: Unbuffered {
_color: PhantomData,
},
}
}
}
impl<IFACE, RST, COLOR: St77916Color> St77916Builder<IFACE, RST, Unbuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
{
pub fn build<DELAY>(
self,
color: ColorMode,
delay: &mut DELAY,
) -> DriverResult<St77916<IFACE, RST, Unbuffered<COLOR>>, IFACE, RST>
where
DELAY: DelayNs,
{
crate::build_driver(
self.interface,
self.reset,
self.config,
self.init_commands,
self.buffer,
delay,
color,
)
}
}
impl<IFACE, RST, COLOR: St77916Color> St77916Builder<IFACE, RST, Buffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
{
pub fn build<DELAY>(
self,
color: ColorMode,
delay: &mut DELAY,
) -> DriverResult<St77916<IFACE, RST, Buffered<COLOR>>, IFACE, RST>
where
DELAY: DelayNs,
{
crate::build_driver(
self.interface,
self.reset,
self.config,
self.init_commands,
self.buffer,
delay,
color,
)
}
}
impl<IFACE, RST, COLOR: St77916Color> St77916Builder<IFACE, RST, DoubleBuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
{
pub fn build<DELAY>(
self,
color: ColorMode,
delay: &mut DELAY,
) -> DriverResult<St77916<IFACE, RST, DoubleBuffered<COLOR>>, IFACE, RST>
where
DELAY: DelayNs,
{
crate::build_driver(
self.interface,
self.reset,
self.config,
self.init_commands,
self.buffer,
delay,
color,
)
}
}