#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use bindings::RGBLedMatrixOptions;
use std::{env, ffi::CString, ptr};
use crate::bindings::RGBLedRuntimeOptions;
pub mod bindings {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
impl Default for bindings::RGBLedMatrixOptions {
fn default() -> Self {
Self {
hardware_mapping: std::ptr::null(),
rows: 32,
cols: 0,
chain_length: 1,
parallel: 1,
pwm_bits: 0,
pwm_lsb_nanoseconds: 50,
pwm_dither_bits: 0,
brightness: 0,
scan_mode: 0,
row_address_type: 0,
multiplexing: 0,
disable_hardware_pulsing: 0,
show_refresh_rate: 1,
inverse_colors: 0,
led_rgb_sequence: std::ptr::null(),
pixel_mapper_config: std::ptr::null(),
panel_type: std::ptr::null(),
limit_refresh_rate_hz: 0,
}
}
}
impl bindings::RGBLedMatrixOptions {
pub fn new() -> Self {
Self::default()
}
pub fn hardware_mapping(mut self, mapping: &str) -> Self {
self.hardware_mapping = std::ffi::CString::new(mapping).unwrap().into_raw();
self
}
pub fn rows(mut self, rows: u16) -> Self {
self.rows = rows as i32;
self
}
pub fn cols(mut self, cols: u16) -> Self {
self.cols = cols as i32;
self
}
pub fn chain_length(mut self, length: u16) -> Self {
self.chain_length = length as i32;
self
}
pub fn parallel(mut self, parallel: u16) -> Self {
self.parallel = parallel as i32;
self
}
pub fn pwm_bits(mut self, bits: u16) -> Self {
self.pwm_bits = bits as i32;
self
}
pub fn pwm_lsb_nanoseconds(mut self, ns: u16) -> Self {
self.pwm_lsb_nanoseconds = ns as i32;
self
}
pub fn pwm_dither_bits(mut self, bits: u16) -> Self {
self.pwm_dither_bits = bits as i32;
self
}
pub fn brightness(mut self, brightness: u16) -> Self {
self.brightness = brightness as i32;
self
}
pub fn scan_mode(mut self, mode: u16) -> Self {
self.scan_mode = mode as i32;
self
}
pub fn row_address_type(mut self, address_type: u16) -> Self {
self.row_address_type = address_type as i32;
self
}
pub fn multiplexing(mut self, multiplexing: u16) -> Self {
self.multiplexing = multiplexing as i32;
self
}
pub fn disable_hardware_pulsing(mut self, disable: bool) -> Self {
self.disable_hardware_pulsing = disable.into();
self
}
pub fn show_refresh_rate(mut self, show: bool) -> Self {
self.show_refresh_rate = show.into();
self
}
pub fn inverse_colors(mut self, inverse: bool) -> Self {
self.inverse_colors = inverse.into();
self
}
pub fn led_rgb_sequence(mut self, sequence: &str) -> Self {
self.led_rgb_sequence = std::ffi::CString::new(sequence).unwrap().into_raw();
self
}
pub fn pixel_mapper_config(mut self, config: &str) -> Self {
self.pixel_mapper_config = std::ffi::CString::new(config).unwrap().into_raw();
self
}
pub fn panel_type(mut self, panel_type: &str) -> Self {
self.panel_type = std::ffi::CString::new(panel_type).unwrap().into_raw();
self
}
pub fn limit_refresh_rate_hz(mut self, hz: u32) -> Self {
self.limit_refresh_rate_hz = hz as i32;
self
}
pub fn build(mut self) -> Box<bindings::RGBLedMatrix> {
unsafe {
Box::from_raw(bindings::led_matrix_create_from_options(
&mut self as *mut bindings::RGBLedMatrixOptions,
std::ptr::null_mut(),
std::ptr::null_mut(),
))
}
}
pub fn build_with_rt_options(
mut self,
mut rt_options: RGBLedRuntimeOptions,
) -> Box<bindings::RGBLedMatrix> {
unsafe {
Box::from_raw(bindings::led_matrix_create_from_options_and_rt_options(
&mut self,
&mut rt_options,
))
}
}
}
impl Default for bindings::RGBLedRuntimeOptions {
fn default() -> Self {
Self {
gpio_slowdown: 1,
daemon: 0,
drop_privileges: 0,
do_gpio_init: true,
}
}
}
impl bindings::RGBLedRuntimeOptions {
pub fn new() -> Self {
Self::default()
}
pub fn gpio_slowdown(mut self, slowdown: u32) -> Self {
self.gpio_slowdown = slowdown as i32;
self
}
pub fn daemon(mut self, run_as_daemon: bool) -> Self {
self.daemon = run_as_daemon as i32;
self
}
pub fn drop_priviliges(mut self, do_drop_privileges: bool) -> Self {
self.drop_privileges = do_drop_privileges as i32;
self
}
pub fn do_gpio_init(mut self, do_gpio_init: bool) -> Self {
self.do_gpio_init = do_gpio_init;
self
}
}
impl bindings::RGBLedMatrix {
pub fn create_offscreen_canvas(&self) -> Box<bindings::LedCanvas> {
unsafe {
Box::from_raw(bindings::led_matrix_create_offscreen_canvas(
self as *const Self as *mut bindings::RGBLedMatrix,
))
}
}
pub fn swap_on_vsync(&mut self, canvas: &mut bindings::LedCanvas) -> Box<bindings::LedCanvas> {
unsafe {
Box::from_raw(bindings::led_matrix_swap_on_vsync(
self as *mut Self,
canvas as *mut bindings::LedCanvas,
))
}
}
}
impl bindings::LedCanvas {
pub fn clear(&mut self) {
unsafe {
bindings::led_canvas_clear(self);
}
}
pub fn set_pixel(&mut self, x: i32, y: i32, r: u8, g: u8, b: u8) {
unsafe {
bindings::led_canvas_set_pixel(self, x, y, r, g, b);
}
}
pub fn get_size(&self) -> (i32, i32) {
let mut width = 0;
let mut height = 0;
unsafe {
bindings::led_canvas_get_size(
self,
&mut width as *mut i32,
&mut height as *mut i32,
);
}
(width, height)
}
}
#[test]
fn test() {
let mut matrix = RGBLedMatrixOptions::new().build();
let mut canvas = matrix.create_offscreen_canvas();
canvas.clear();
loop {
for i in 0..255 {
for y in 0..32 {
for x in 0..32 {
canvas.set_pixel(x, y, i & 0xFF, x.try_into().unwrap(), y.try_into().unwrap());
}
}
canvas = matrix.swap_on_vsync(&mut canvas);
}
}
}