]> patrickod personal git archive - keywing-rs.git/blob - keywing/src/buffer.rs
Add nix & direnv rust environment configuration
[keywing-rs.git] / keywing / src / buffer.rs
1 use embedded_graphics::{
2     drawable::Pixel,
3     geometry::Size,
4     pixelcolor::{
5         raw::{RawData, RawU16},
6         Rgb565,
7     },
8     DrawTarget,
9 };
10
11 pub struct FrameBuffer<'a> {
12     buf: &'a mut [[u16; 320]; 240],
13     dirty: bool,
14 }
15
16 impl<'a> FrameBuffer<'a> {
17     pub fn new(raw: &'a mut [[u16; 320]; 240]) -> Self {
18         Self {
19             buf: raw,
20             dirty: false,
21         }
22     }
23
24     pub fn inner(&mut self) -> Option<&[u16]> {
25         if self.dirty {
26             self.dirty = false;
27             Some(unsafe {
28                 core::slice::from_raw_parts(
29                     self.buf.as_ptr().cast::<u16>(),
30                     (self.width() * self.height()) as usize,
31                 )
32             })
33         } else {
34             None
35         }
36     }
37
38     fn width(&self) -> u32 {
39         self.buf[0].len() as u32
40     }
41
42     fn height(&self) -> u32 {
43         self.buf.len() as u32
44     }
45 }
46
47 impl<'a> DrawTarget<Rgb565> for FrameBuffer<'a> {
48     type Error = ();
49
50     fn size(&self) -> Size {
51         Size::new(self.width(), self.height())
52     }
53
54     fn draw_pixel(&mut self, pixel: Pixel<Rgb565>) -> Result<(), Self::Error> {
55         let Pixel(pos, color) = pixel;
56
57         if pos.x < 0 || pos.y < 0 || pos.x >= self.width() as i32 || pos.y >= self.height() as i32 {
58             return Ok(());
59         }
60         self.dirty = true;
61         self.buf[pos.y as usize][pos.x as usize] = swap(RawU16::from(color).into_inner());
62         Ok(())
63     }
64 }
65
66 const fn swap(inp: u16) -> u16 {
67     (inp & 0x00FF) << 8 | (inp & 0xFF00) >> 8
68 }