turing_smart_screen/
screen.rs1use image::ImageBuffer;
2use serialport::SerialPort;
3
4pub const WIDTH: u16 = 320;
5pub const HEIGHT: u16 = 480;
6const SCREEN_SERIAL: &str = "USB35INCHIPSV2";
7
8#[allow(dead_code)]
9pub enum Orientation {
10 Portrait = 0,
11 ReversePortrait = 1,
12 Landscape = 2,
13 ReverseLandscape = 3,
14}
15
16#[allow(dead_code)]
17pub enum ScreenCommand {
18 Reset = 101,
19 Clear = 102,
20 ToBlack = 103,
21 ScreenOff = 108,
22 ScreenOn = 109,
23 SetBrigthness = 110,
24 SetOrientation = 121,
25 DisplayBitmap = 197,
26}
27
28pub struct Screen {
29 port: Box<dyn SerialPort>
30}
31
32impl Screen {
33 pub fn find_port() -> Result<String, serialport::Error> {
37 let ports = serialport::available_ports()?;
38 let mut port = "".to_string();
39 for p in ports {
40 match p.port_type {
41 serialport::SerialPortType::UsbPort(info) => {
42 let sn = info.serial_number.unwrap_or("--".to_string());
43 if sn == SCREEN_SERIAL {
44 port = p.port_name.clone();
45 }
46 }
47 _ => { }
48 }
49 }
50
51 Ok(port)
52 }
53
54 pub fn new(port_name: String) -> Result<Screen, serialport::Error> {
57 let port = serialport::new(&port_name, 115_200)
58 .timeout(std::time::Duration::from_secs(1))
59 .open()?;
60 Ok(Screen { port })
61 }
62}
63
64impl Screen {
65 fn send_command(&mut self, x: u16, y: u16, ex: u16, ey: u16, cmd: ScreenCommand) -> Result<(), crate::errors::ScreenError> {
66 let mut byte_buffer = [0u8; 6];
67 byte_buffer[0] = (x >> 2) as u8;
68 byte_buffer[1] = (((x & 3) << 6) + (y >> 4)) as u8;
69 byte_buffer[2] = (((y & 15) << 4) + (ex >> 6)) as u8;
70 byte_buffer[3] = (((ex & 63) << 2) + (ey >> 8)) as u8;
71 byte_buffer[4] = (ey & 255) as u8;
72 byte_buffer[5] = cmd as u8;
73
74 self.port.write(&byte_buffer).map_err(|_| crate::errors::ScreenError::WriteError)?;
75
76 Ok(())
77 }
78
79 #[allow(unused)]
81 pub fn orientation(&mut self, orientation: Orientation) -> Result<(), crate::errors::ScreenError> {
82 let bytes = vec![0, 0, 0, 0, 0, ScreenCommand::SetOrientation as u8, (orientation as u8) + 100, 3, 200, 4, 0];
83
84 self.port.write(&bytes).map_err(|_| crate::errors::ScreenError::WriteError)?;
85
86 Ok(())
87 }
88
89 #[allow(unused)]
90 pub fn clear(&mut self) -> Result<(), crate::errors::ScreenError> {
93 self.send_command(0, 0, 0, 0, ScreenCommand::Clear)
94 }
95
96 #[allow(unused)]
97 pub fn to_black(&mut self) -> Result<(), crate::errors::ScreenError> {
100 self.send_command(0, 0, 0, 0, ScreenCommand::ToBlack)
101 }
102
103 #[allow(unused)]
104 pub fn brightness(&mut self, level: u8) -> Result<(), crate::errors::ScreenError> {
107 let level = 255 - level; self.send_command(level as u16, 0, 0, 0, ScreenCommand::SetBrigthness)
109 }
110
111 #[allow(unused)]
112 pub fn screen_off(&mut self) -> Result<(), crate::errors::ScreenError> {
115 self.send_command(0, 0, 0, 0, ScreenCommand::ScreenOff)
116 }
117
118 #[allow(unused)]
119 pub fn screen_on(&mut self) -> Result<(), crate::errors::ScreenError> {
121 self.send_command(0, 0, 0, 0, ScreenCommand::ScreenOn)
122 }
123
124 #[allow(unused)]
139 pub fn draw(&mut self, img: ImageBuffer<image::Rgb<u8>, Vec<u8>>) -> Result<(), crate::errors::ScreenError> {
143 if !((img.width() == WIDTH.into() || img.height() == HEIGHT.into()) || (img.width() == HEIGHT.into() || img.height() == WIDTH.into())) {
144 return Err(crate::errors::ScreenError::WrongImageSize);
146 }
147
148 let width = img.width();
149 let height = img.height();
150
151 self.send_command(0, 0, (width - 1) as u16, (height - 1) as u16, ScreenCommand::DisplayBitmap)?;
153
154 let pixels: Vec<_> = img.pixels().collect();
155 let width = width as usize;
156
157 for (i, chunk) in pixels.chunks_exact(width * 8).enumerate() {
158 let mut bytes: Vec<u8> = Vec::with_capacity(chunk.len() * 2);
159 for pixel in chunk {
160 let r = (pixel[0] >> 3) as u16;
161 let g = (pixel[1] >> 2) as u16;
162 let b = (pixel[2] >> 3) as u16;
163 let rgb565 = (r << 11) | (g << 5) | b;
164 bytes.push((rgb565 & 0xFF) as u8); bytes.push((rgb565 >> 8) as u8); }
167 self.port.write(&bytes).map_err(|_| crate::errors::ScreenError::WriteError)?;
168 }
169
170 let remainder = pixels.chunks_exact(width * 8).remainder();
172 if !remainder.is_empty() {
173 let mut bytes: Vec<u8> = Vec::with_capacity(remainder.len() * 2);
174 for pixel in remainder {
175 let r = (pixel[0] >> 3) as u16;
176 let g = (pixel[1] >> 2) as u16;
177 let b = (pixel[2] >> 3) as u16;
178 let rgb565 = (r << 11) | (g << 5) | b;
179 bytes.push((rgb565 & 0xFF) as u8); bytes.push((rgb565 >> 8) as u8); }
182 self.port.write(&bytes).map_err(|_| crate::errors::ScreenError::WriteError)?;
183 }
184
185 Ok(())
186 }
187}