embedded_graphics_framebuf/
backends.rs1use embedded_graphics::pixelcolor::{raw::RawU16, IntoStorage, PixelColor};
29
30pub trait FrameBufferBackend {
37 type Color: PixelColor;
38 fn set(&mut self, index: usize, color: Self::Color);
40
41 fn get(&self, index: usize) -> Self::Color;
43
44 fn nr_elements(&self) -> usize;
46}
47
48impl<'a, C: PixelColor, const N: usize> FrameBufferBackend for &'a mut [C; N] {
49 type Color = C;
50 fn set(&mut self, index: usize, color: C) {
51 self[index] = color
52 }
53
54 fn get(&self, index: usize) -> C {
55 self[index]
56 }
57
58 fn nr_elements(&self) -> usize {
59 self.len()
60 }
61}
62
63impl<C: PixelColor, const N: usize> FrameBufferBackend for [C; N] {
64 type Color = C;
65 fn set(&mut self, index: usize, color: C) {
66 self[index] = color
67 }
68
69 fn get(&self, index: usize) -> C {
70 self[index]
71 }
72
73 fn nr_elements(&self) -> usize {
74 self.len()
75 }
76}
77
78pub unsafe trait DMACapableFrameBufferBackend: FrameBufferBackend {
84 fn data_ptr(&self) -> *const Self::Color;
85}
86
87unsafe impl<'a, C: PixelColor, const N: usize> DMACapableFrameBufferBackend for &'a mut [C; N] {
93 fn data_ptr(&self) -> *const C {
94 self.as_ptr()
95 }
96}
97
98#[derive(PartialEq, Eq)]
100pub enum EndianCorrection {
101 ToLittleEndian,
102 ToBigEndian,
103}
104
105pub struct EndianCorrectedBuffer<'a, C: PixelColor> {
109 data: &'a mut [C],
110 endian: EndianCorrection,
111}
112impl<'a, C: PixelColor> EndianCorrectedBuffer<'a, C> {
113 pub fn new(data: &'a mut [C], endian: EndianCorrection) -> Self {
114 Self { data, endian }
115 }
116}
117impl<'a, C> FrameBufferBackend for EndianCorrectedBuffer<'a, C>
118where
119 C: IntoStorage<Storage = u16> + PixelColor,
123 RawU16: From<C>,
124 C: core::convert::From<RawU16>,
125{
126 type Color = C;
127 fn set(&mut self, index: usize, color: C) {
128 self.data[index] = match self.endian {
129 EndianCorrection::ToBigEndian => RawU16::new(color.into_storage().to_be()).into(),
130 EndianCorrection::ToLittleEndian => RawU16::new(color.into_storage().to_le()).into(),
131 }
132 }
133
134 fn get(&self, index: usize) -> C {
135 match self.endian {
136 EndianCorrection::ToBigEndian => {
137 C::from(RawU16::new(u16::from_be(self.data[index].into_storage())))
138 }
139 EndianCorrection::ToLittleEndian => {
140 C::from(RawU16::new(u16::from_le(self.data[index].into_storage())))
141 }
142 }
143 }
144
145 fn nr_elements(&self) -> usize {
146 self.data.len()
147 }
148}
149unsafe impl<'a, C> DMACapableFrameBufferBackend for EndianCorrectedBuffer<'a, C>
150where
151 C: IntoStorage<Storage = u16> + PixelColor,
152 RawU16: From<C>,
153 C: core::convert::From<RawU16>,
154{
155 fn data_ptr(&self) -> *const C {
156 self.data.as_ptr()
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 extern crate std;
163
164 use super::*;
165 use crate::FrameBuf;
166 use embedded_graphics::pixelcolor::{raw::RawU16, Rgb565};
167 use embedded_graphics::prelude::{Point, RawData, RgbColor};
168
169 #[test]
170 fn test_no_endian_correction() {
171 let mut data = [Rgb565::BLUE; 2 * 3];
172 let mut fbuf = FrameBuf::new(&mut data, 2, 3);
173 fbuf.set_color_at(Point::new(1, 0), Rgb565::RED);
174 fbuf.set_color_at(Point::new(2, 0), Rgb565::BLUE);
175 assert_eq!(RawU16::from(fbuf.data[0]).into_inner(), 0b00000000_00011111);
177 assert_eq!(RawU16::from(fbuf.data[1]).into_inner(), 0b11111000_00000000);
179 assert_eq!(RawU16::from(fbuf.data[2]).into_inner(), 0b00000000_00011111);
181 }
182
183 #[test]
184 fn test_big_endian_correction() {
185 let mut data = [Rgb565::BLUE; 2 * 3];
186 let mut fbuf = FrameBuf::new(
187 EndianCorrectedBuffer::new(&mut data, EndianCorrection::ToBigEndian),
188 2,
189 3,
190 );
191 fbuf.set_color_at(Point::new(1, 0), Rgb565::RED);
192 fbuf.set_color_at(Point::new(2, 0), Rgb565::BLUE);
193
194 assert_eq!(fbuf.get_color_at(Point::new(1, 0)), Rgb565::RED);
196 assert_eq!(fbuf.get_color_at(Point::new(2, 0)), Rgb565::BLUE);
197
198 assert_eq!(
200 RawU16::from(fbuf.data.data[1]).into_inner(),
201 0b00000000_11111000
202 );
203 assert_eq!(
205 RawU16::from(fbuf.data.data[2]).into_inner(),
206 0b00011111_00000000
207 );
208 }
209
210 #[test]
211 fn test_little_endian_correction() {
212 let mut data = [Rgb565::BLUE; 2 * 3];
213 let mut fbuf = FrameBuf::new(
214 EndianCorrectedBuffer::new(&mut data, EndianCorrection::ToLittleEndian),
215 2,
216 3,
217 );
218 fbuf.set_color_at(Point::new(1, 0), Rgb565::RED);
219 fbuf.set_color_at(Point::new(2, 0), Rgb565::BLUE);
220
221 assert_eq!(fbuf.get_color_at(Point::new(1, 0)), Rgb565::RED);
223 assert_eq!(fbuf.get_color_at(Point::new(2, 0)), Rgb565::BLUE);
224
225 assert_eq!(
227 RawU16::from(fbuf.data.data[1]).into_inner(),
228 0b11111000_00000000
229 );
230 assert_eq!(
232 RawU16::from(fbuf.data.data[2]).into_inner(),
233 0b00000000_00011111
234 );
235 }
236}