1#![no_std]
4#![allow(incomplete_features)]
5#![feature(generic_const_exprs)]
6
7use core::ops::{Deref, DerefMut};
8
9use crate::error::Error;
10use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiBus};
11use framebuffer::FramebufferType;
12
13pub mod displays;
14pub mod error;
15pub mod framebuffer;
16pub mod pixelcolor;
17
18pub trait DisplaySpec {
20 const WIDTH: u16;
21 const HEIGHT: u16;
22
23 type Framebuffer: FramebufferType;
24}
25
26pub const CMD_NO_UPDATE: u8 = 0x00;
29pub const CMD_BLINKING_BLACK: u8 = 0x10;
30pub const CMD_BLINKING_INVERSION: u8 = 0x14;
31pub const CMD_BLINKING_WHITE: u8 = 0x18;
32pub const CMD_ALL_CLEAR: u8 = 0x20;
33pub const CMD_VCOM: u8 = 0x40;
34pub const CMD_UPDATE_4BIT: u8 = 0x90;
37pub const CMD_UPDATE_1BIT: u8 = 0x88;
39
40pub struct MemoryLCD<SPEC: DisplaySpec, SPI, CS> {
41 spi: SPI,
43 cs: CS,
44 framebuffer: SPEC::Framebuffer,
45}
46
47impl<SPEC, SPI, CS> MemoryLCD<SPEC, SPI, CS>
48where
49 SPI: SpiBus<u8>,
50 CS: OutputPin,
51 SPEC: DisplaySpec,
52{
53 pub fn new(spi: SPI, cs: CS) -> Self {
54 Self {
55 spi,
56 cs,
57 framebuffer: SPEC::Framebuffer::default(),
58 }
59 }
60
61 pub fn turn_on_display<DISP: OutputPin>(&mut self, disp: &mut DISP) -> Result<(), Error<SPI::Error>> {
62 disp.set_high().map_err(|_| Error::Gpio)?;
63 Ok(())
64 }
65
66 pub fn turn_off_display<DISP: OutputPin>(&mut self, disp: &mut DISP) -> Result<(), Error<SPI::Error>> {
67 disp.set_low().map_err(|_| Error::Gpio)?;
68 Ok(())
69 }
70
71 pub fn init(&mut self) -> Result<(), Error<SPI::Error>> {
72 self.cs.set_high().map_err(|_| Error::Gpio)?;
73 self.spi.write(&[CMD_ALL_CLEAR, 0x00]).map_err(Error::Spi)?;
74 self.cs.set_low().map_err(|_| Error::Gpio)?;
75 Ok(())
76 }
77
78 pub fn update<D: DelayNs>(&mut self, _delay: &mut D) -> Result<(), Error<SPI::Error>> {
79 use crate::framebuffer::sealed::FramebufferSpiUpdate;
80
81 self.cs.set_high().map_err(|_| Error::Gpio)?;
82 self.framebuffer.update(&mut self.spi).map_err(Error::Spi)?;
83 self.cs.set_low().map_err(|_| Error::Gpio)?;
84 Ok(())
85 }
86}
87
88impl<SPEC, SPI, CS> Deref for MemoryLCD<SPEC, SPI, CS>
89where
90 SPEC: DisplaySpec,
91{
92 type Target = SPEC::Framebuffer;
93
94 fn deref(&self) -> &Self::Target {
95 &self.framebuffer
96 }
97}
98
99impl<SPEC, SPI, CS> DerefMut for MemoryLCD<SPEC, SPI, CS>
100where
101 SPEC: DisplaySpec,
102{
103 fn deref_mut(&mut self) -> &mut Self::Target {
104 &mut self.framebuffer
105 }
106}