1#![forbid(unsafe_code)]
2
3#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4pub struct Color {
5 pub r: u8,
6 pub g: u8,
7 pub b: u8,
8}
9
10impl Color {
11 pub const BLACK: Self = Self::rgb(0, 0, 0);
12 pub const WHITE: Self = Self::rgb(255, 255, 255);
13 pub const RED: Self = Self::rgb(255, 0, 0);
14 pub const GREEN: Self = Self::rgb(0, 255, 0);
15 pub const BLUE: Self = Self::rgb(0, 0, 255);
16
17 pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
18 Self { r, g, b }
19 }
20
21 pub fn luminance(self) -> u8 {
22 ((self.r as u16 * 30 + self.g as u16 * 59 + self.b as u16 * 11) / 100) as u8
23 }
24
25 pub fn to_rgb565(self) -> u16 {
26 let r = (self.r as u16 >> 3) & 0x1F;
27 let g = (self.g as u16 >> 2) & 0x3F;
28 let b = (self.b as u16 >> 3) & 0x1F;
29 (r << 11) | (g << 5) | b
30 }
31
32 pub fn from_rgb565(value: u16) -> Self {
33 let r = ((value >> 11) & 0x1F) as u8;
34 let g = ((value >> 5) & 0x3F) as u8;
35 let b = (value & 0x1F) as u8;
36
37 Self {
38 r: (r << 3) | (r >> 2),
39 g: (g << 2) | (g >> 4),
40 b: (b << 3) | (b >> 2),
41 }
42 }
43
44 pub fn to_gray8(self) -> u8 {
45 self.luminance()
46 }
47}
48
49#[derive(Clone, Copy, Debug, PartialEq, Eq)]
50pub enum PinId {
51 Cs,
52 Dc,
53 Rst,
54 Wr,
55 Rd,
56 Clk,
57 Mosi,
58 Miso,
59 Bl,
60}
61
62impl PinId {
63 pub const ALL: [Self; 9] = [
64 Self::Cs,
65 Self::Dc,
66 Self::Rst,
67 Self::Wr,
68 Self::Rd,
69 Self::Clk,
70 Self::Mosi,
71 Self::Miso,
72 Self::Bl,
73 ];
74
75 pub const fn index(self) -> usize {
76 match self {
77 Self::Cs => 0,
78 Self::Dc => 1,
79 Self::Rst => 2,
80 Self::Wr => 3,
81 Self::Rd => 4,
82 Self::Clk => 5,
83 Self::Mosi => 6,
84 Self::Miso => 7,
85 Self::Bl => 8,
86 }
87 }
88}
89
90pub trait Lcd {
91 type Error;
92
93 fn init(&mut self) -> Result<(), Self::Error>;
94 fn clear(&mut self, color: Color) -> Result<(), Self::Error>;
95 fn draw_pixel(&mut self, x: u16, y: u16, color: Color) -> Result<(), Self::Error>;
96 fn fill_rect(
97 &mut self,
98 x: u16,
99 y: u16,
100 width: u16,
101 height: u16,
102 color: Color,
103 ) -> Result<(), Self::Error>;
104 fn present(&mut self) -> Result<(), Self::Error>;
105}
106
107pub trait LcdBus {
108 type Error;
109
110 fn set_pin(&mut self, pin: PinId, value: bool) -> Result<(), Self::Error>;
111 fn write_command(&mut self, cmd: u8) -> Result<(), Self::Error>;
112 fn write_data(&mut self, data: &[u8]) -> Result<(), Self::Error>;
113 fn read_data(&mut self, len: usize) -> Result<Vec<u8>, Self::Error>;
114}
115
116#[cfg(test)]
117mod tests {
118 use super::Color;
119
120 #[test]
121 fn rgb565_roundtrip_preserves_primary_signal() {
122 let red = Color::RED;
123 let encoded = red.to_rgb565();
124 let decoded = Color::from_rgb565(encoded);
125
126 assert!(decoded.r > 200);
127 assert!(decoded.g < 20);
128 assert!(decoded.b < 20);
129 }
130}