1use crate::ffi;
2use crate::{LedCanvas, LedMatrixOptions, LedRuntimeOptions};
3#[cfg(feature = "embeddedgraphics")]
4use embedded_graphics_core::{
5 draw_target::DrawTarget,
6 geometry::{Dimensions, Point, Size},
7 pixelcolor::Rgb888,
8 primitives::Rectangle,
9 Pixel,
10};
11
12pub struct LedMatrix {
19 handle: *mut ffi::CLedMatrix,
20 _options: LedMatrixOptions,
21}
22
23impl LedMatrix {
24 pub fn new(
37 options: Option<LedMatrixOptions>,
38 rt_options: Option<LedRuntimeOptions>,
39 ) -> Result<Self, &'static str> {
40 let mut options = options.unwrap_or_default();
41 let mut rt_options = rt_options.unwrap_or_default();
42
43 let handle = unsafe {
44 ffi::led_matrix_create_from_options_and_rt_options(
45 &mut options.0 as *mut ffi::CLedMatrixOptions,
46 &mut rt_options.0 as *mut ffi::CLedRuntimeOptions,
47 )
48 };
49
50 if handle.is_null() {
51 Err("Couldn't create LedMatrix")
52 } else {
53 Ok(Self {
54 handle,
55 _options: options,
56 })
57 }
58 }
59
60 #[must_use]
62 pub fn canvas(&self) -> LedCanvas {
63 let handle = unsafe { ffi::led_matrix_get_canvas(self.handle) };
64
65 LedCanvas { handle }
66 }
67
68 #[must_use]
70 pub fn offscreen_canvas(&self) -> LedCanvas {
71 let handle = unsafe { ffi::led_matrix_create_offscreen_canvas(self.handle) };
72
73 LedCanvas { handle }
74 }
75
76 #[must_use]
90 #[allow(clippy::needless_pass_by_value)]
91 pub fn swap(&self, canvas: LedCanvas) -> LedCanvas {
92 let handle = unsafe { ffi::led_matrix_swap_on_vsync(self.handle, canvas.handle) };
93
94 LedCanvas { handle }
95 }
96}
97
98impl Drop for LedMatrix {
99 fn drop(&mut self) {
100 unsafe {
101 ffi::led_matrix_delete(self.handle);
102 }
103 }
104}
105
106#[cfg(feature = "embeddedgraphics")]
107impl DrawTarget for LedCanvas {
108 type Color = Rgb888;
109 type Error = core::convert::Infallible;
110
111 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
112 where
113 I: IntoIterator<Item = Pixel<Self::Color>>,
114 {
115 for px in pixels {
116 self.set(px.0.x, px.0.y, &px.1.into());
117 }
118 Ok(())
119 }
120
121 fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
122 self.fill(&color.into());
123 Ok(())
124 }
125}
126
127#[cfg(feature = "embeddedgraphics")]
128impl Dimensions for LedCanvas {
129 fn bounding_box(&self) -> Rectangle {
130 let size = self.canvas_size();
131 Rectangle::new(Point::new(0, 0), Size::new(size.0 as u32, size.1 as u32))
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 fn led_matrix() -> LedMatrix {
140 let mut options = LedMatrixOptions::new();
141 let mut rt_options = LedRuntimeOptions::new();
142 options.set_hardware_mapping("adafruit-hat-pwm");
143 options.set_chain_length(2);
144 options.set_hardware_pulsing(false);
145 options.set_refresh_rate(true);
146 options.set_brightness(10).unwrap();
147 rt_options.set_gpio_slowdown(2);
148 LedMatrix::new(Some(options), Some(rt_options)).unwrap()
149 }
150
151 #[test]
152 #[serial_test::serial]
153 fn matrix_create() {
154 let _matrix = led_matrix();
155 }
156}