Skip to main content

led_matrix_rs/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use bindings::RGBLedMatrixOptions;
6use std::{env, ffi::CString, ptr};
7
8use crate::bindings::RGBLedRuntimeOptions;
9
10pub mod bindings {
11    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
12}
13
14impl Default for bindings::RGBLedMatrixOptions {
15    fn default() -> Self {
16        Self {
17            hardware_mapping: std::ptr::null(),
18            rows: 32,
19            cols: 0,
20            chain_length: 1,
21            parallel: 1,
22            pwm_bits: 0,
23            pwm_lsb_nanoseconds: 50,
24            pwm_dither_bits: 0,
25            brightness: 0,
26            scan_mode: 0,
27            row_address_type: 0,
28            multiplexing: 0,
29            disable_hardware_pulsing: 0,
30            show_refresh_rate: 1,
31            inverse_colors: 0,
32            led_rgb_sequence: std::ptr::null(),
33            pixel_mapper_config: std::ptr::null(),
34            panel_type: std::ptr::null(),
35            limit_refresh_rate_hz: 0,
36        }
37    }
38}
39
40impl bindings::RGBLedMatrixOptions {
41    pub fn new() -> Self {
42        Self::default()
43    }
44
45    pub fn hardware_mapping(mut self, mapping: &str) -> Self {
46        self.hardware_mapping = std::ffi::CString::new(mapping).unwrap().into_raw();
47        self
48    }
49
50    pub fn rows(mut self, rows: u16) -> Self {
51        self.rows = rows as i32;
52        self
53    }
54    pub fn cols(mut self, cols: u16) -> Self {
55        self.cols = cols as i32;
56        self
57    }
58    pub fn chain_length(mut self, length: u16) -> Self {
59        self.chain_length = length as i32;
60        self
61    }
62    pub fn parallel(mut self, parallel: u16) -> Self {
63        self.parallel = parallel as i32;
64        self
65    }
66    pub fn pwm_bits(mut self, bits: u16) -> Self {
67        self.pwm_bits = bits as i32;
68        self
69    }
70    pub fn pwm_lsb_nanoseconds(mut self, ns: u16) -> Self {
71        self.pwm_lsb_nanoseconds = ns as i32;
72        self
73    }
74    pub fn pwm_dither_bits(mut self, bits: u16) -> Self {
75        self.pwm_dither_bits = bits as i32;
76        self
77    }
78    pub fn brightness(mut self, brightness: u16) -> Self {
79        self.brightness = brightness as i32;
80        self
81    }
82    pub fn scan_mode(mut self, mode: u16) -> Self {
83        self.scan_mode = mode as i32;
84        self
85    }
86    pub fn row_address_type(mut self, address_type: u16) -> Self {
87        self.row_address_type = address_type as i32;
88        self
89    }
90    pub fn multiplexing(mut self, multiplexing: u16) -> Self {
91        self.multiplexing = multiplexing as i32;
92        self
93    }
94    pub fn disable_hardware_pulsing(mut self, disable: bool) -> Self {
95        self.disable_hardware_pulsing = disable.into();
96        self
97    }
98    pub fn show_refresh_rate(mut self, show: bool) -> Self {
99        self.show_refresh_rate = show.into();
100        self
101    }
102    pub fn inverse_colors(mut self, inverse: bool) -> Self {
103        self.inverse_colors = inverse.into();
104        self
105    }
106    pub fn led_rgb_sequence(mut self, sequence: &str) -> Self {
107        self.led_rgb_sequence = std::ffi::CString::new(sequence).unwrap().into_raw();
108        self
109    }
110    pub fn pixel_mapper_config(mut self, config: &str) -> Self {
111        self.pixel_mapper_config = std::ffi::CString::new(config).unwrap().into_raw();
112        self
113    }
114    pub fn panel_type(mut self, panel_type: &str) -> Self {
115        self.panel_type = std::ffi::CString::new(panel_type).unwrap().into_raw();
116        self
117    }
118    pub fn limit_refresh_rate_hz(mut self, hz: u32) -> Self {
119        self.limit_refresh_rate_hz = hz as i32;
120        self
121    }
122
123    pub fn build(mut self) -> Box<bindings::RGBLedMatrix> {
124        unsafe {
125            Box::from_raw(bindings::led_matrix_create_from_options(
126                &mut self as *mut bindings::RGBLedMatrixOptions,
127                std::ptr::null_mut(),
128                std::ptr::null_mut(),
129            ))
130        }
131    }
132
133    pub fn build_with_rt_options(
134        mut self,
135        mut rt_options: RGBLedRuntimeOptions,
136    ) -> Box<bindings::RGBLedMatrix> {
137        unsafe {
138            Box::from_raw(bindings::led_matrix_create_from_options_and_rt_options(
139                &mut self,
140                &mut rt_options,
141            ))
142        }
143    }
144}
145
146impl Default for bindings::RGBLedRuntimeOptions {
147    fn default() -> Self {
148        Self {
149            gpio_slowdown: 1,
150            daemon: 0,
151            drop_privileges: 0,
152            do_gpio_init: true,
153        }
154    }
155}
156
157impl bindings::RGBLedRuntimeOptions {
158    pub fn new() -> Self {
159        Self::default()
160    }
161    pub fn gpio_slowdown(mut self, slowdown: u32) -> Self {
162        self.gpio_slowdown = slowdown as i32;
163        self
164    }
165
166    pub fn daemon(mut self, run_as_daemon: bool) -> Self {
167        self.daemon = run_as_daemon as i32;
168        self
169    }
170
171    pub fn drop_priviliges(mut self, do_drop_privileges: bool) -> Self {
172        self.drop_privileges = do_drop_privileges as i32;
173        self
174    }
175
176    pub fn do_gpio_init(mut self, do_gpio_init: bool) -> Self {
177        self.do_gpio_init = do_gpio_init;
178        self
179    }
180}
181
182impl bindings::RGBLedMatrix {
183    pub fn create_offscreen_canvas(&self) -> Box<bindings::LedCanvas> {
184        unsafe {
185            Box::from_raw(bindings::led_matrix_create_offscreen_canvas(
186                self as *const Self as *mut bindings::RGBLedMatrix,
187            ))
188        }
189    }
190
191    pub fn swap_on_vsync(&mut self, canvas: &mut bindings::LedCanvas) -> Box<bindings::LedCanvas> {
192        unsafe {
193            Box::from_raw(bindings::led_matrix_swap_on_vsync(
194                self as *mut Self,
195                canvas as *mut bindings::LedCanvas,
196            ))
197        }
198    }
199}
200
201impl bindings::LedCanvas {
202    pub fn clear(&mut self) {
203        unsafe {
204            bindings::led_canvas_clear(self);
205        }
206    }
207
208    pub fn set_pixel(&mut self, x: i32, y: i32, r: u8, g: u8, b: u8) {
209        unsafe {
210            bindings::led_canvas_set_pixel(self, x, y, r, g, b);
211        }
212    }
213
214    pub fn get_size(&self) -> (i32, i32) {
215        let mut width = 0;
216        let mut height = 0;
217        unsafe {
218            bindings::led_canvas_get_size(
219                self,
220                &mut width as *mut i32,
221                &mut height as *mut i32,
222            );
223        }
224        (width, height)
225    }
226}
227
228#[test]
229fn test() {
230    let mut matrix = RGBLedMatrixOptions::new().build();
231
232    let mut canvas = matrix.create_offscreen_canvas();
233
234    canvas.clear();
235
236    loop {
237        for i in 0..255 {
238            for y in 0..32 {
239                for x in 0..32 {
240                    canvas.set_pixel(x, y, i & 0xFF, x.try_into().unwrap(), y.try_into().unwrap());
241                }
242            }
243            canvas = matrix.swap_on_vsync(&mut canvas);
244        }
245    }
246}