ev3dev_lang_rust/
screen.rs

1#[cfg(feature = "screen")]
2use framebuffer::Framebuffer;
3
4#[cfg(feature = "screen")]
5use image::{Rgb, RgbImage};
6
7use crate::Ev3Result;
8
9/// Represents the device screen.
10/// Advanced drawing operations can be performed with the `imageproc` crate.
11#[cfg(feature = "screen")]
12#[derive(Debug)]
13pub struct Screen {
14    /// Direct reference to the framebuffer
15    pub buffer: Framebuffer,
16    /// Convenience layer to access the framebuffer
17    /// For drawing operations the `imageproc` crate can be used.
18    pub image: RgbImage,
19}
20
21#[cfg(feature = "screen")]
22impl Screen {
23    /// Create a reference to the device screen
24    pub fn new() -> Ev3Result<Self> {
25        let buffer = Framebuffer::new("/dev/fb0")?;
26
27        let image = RgbImage::from_pixel(
28            buffer.fix_screen_info.line_length * 8 / buffer.var_screen_info.bits_per_pixel,
29            buffer.var_screen_info.yres,
30            Rgb([255, 255, 255]),
31        );
32
33        Ok(Self { buffer, image })
34    }
35
36    /// Horizontal screen resolution
37    pub fn xres(&self) -> u32 {
38        self.buffer.var_screen_info.xres
39    }
40
41    /// Vertical screen resolution
42    pub fn yres(&self) -> u32 {
43        self.buffer.var_screen_info.yres
44    }
45
46    /// Dimensions of the screen.
47    pub fn shape(&self) -> (u32, u32) {
48        (self.xres(), self.yres())
49    }
50
51    /// Clears the screen
52    pub fn clear(&mut self) {
53        for (_, _, pixel) in self.image.enumerate_pixels_mut() {
54            *pixel = Rgb([255, 255, 255]);
55        }
56    }
57
58    fn update_1bpp(&mut self) {
59        let mut buffer = vec![0u8; ((self.xres() * self.yres() + 7) / 8) as usize];
60
61        let mut byte: usize = 0;
62        let mut bit: u8 = 0x80;
63        for (_, _, pixel) in self.image.enumerate_pixels() {
64            let sum = pixel.0[0] as u32 + pixel.0[1] as u32 + pixel.0[2] as u32;
65
66            buffer[byte] |= if sum >= 0x30 { bit } else { 0x00 };
67
68            bit >>= 1;
69            if bit == 0 {
70                byte += 1;
71                bit = 0x80;
72            }
73        }
74
75        self.buffer.write_frame(&buffer);
76    }
77
78    /// Convert red, green, blue components to a 16-bit 565 RGB value. Components
79    /// should be values 0 to 255.
80    fn color565(r: u8, g: u8, b: u8) -> (u8, u8) {
81        let c = (((r as u16) & 0xF8) << 8) | (((g as u16) & 0xFC) << 3) | ((b as u16) >> 3);
82        ((c >> 8) as u8, c as u8)
83    }
84
85    fn update_16bpp(&mut self) {
86        let mut buffer = vec![0u8; (2 * self.xres() * self.yres()) as usize];
87
88        let mut byte: usize = 0;
89        for (_, _, pixel) in self.image.enumerate_pixels() {
90            let (p1, p2) = Screen::color565(pixel.0[0], pixel.0[1], pixel.0[2]);
91            buffer[byte] = p1;
92            buffer[byte + 1] = p2;
93            byte += 2;
94        }
95
96        self.buffer.write_frame(&buffer);
97    }
98
99    fn update_32bpp(&mut self) {
100        let mut buffer = vec![0u8; (4 * self.xres() * self.yres()) as usize];
101
102        let mut byte: usize = 1;
103        for (_, _, pixel) in self.image.enumerate_pixels() {
104            buffer[byte..(byte + 2)].copy_from_slice(&pixel.0[0..2]);
105            byte += 4;
106        }
107
108        self.buffer.write_frame(&buffer);
109    }
110
111    /// Applies pending changes to the screen.
112    /// Nothing will be drawn on the screen until this function is called.
113    pub fn update(&mut self) {
114        if self.buffer.var_screen_info.bits_per_pixel == 1 {
115            self.update_1bpp();
116        } else if self.buffer.var_screen_info.bits_per_pixel == 16 {
117            self.update_16bpp();
118        } else if self.buffer.var_screen_info.bits_per_pixel == 32 {
119            self.update_32bpp();
120        }
121    }
122}