#![allow(dead_code)]
#![allow(unused_imports)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use crate::setup::Max7219;
#[cfg(feature = "std")]
use std::{thread::sleep, time::Duration};
use crate::encoding::encode_string;
use crate::mappings::SingleDisplayData;
use max7219::DecodeMode;
pub const LED_SQUARE_MATRIX_DIM: usize = 8;
pub const MAX_DISPLAYS: usize = 16;
pub mod encoding;
pub mod mappings;
#[cfg(feature = "std")]
mod setup;
#[cfg(feature = "std")]
pub use setup::{setup as setup_adapter, Max7219 as Max7219Adapter};
pub fn shift_all_rows_one_bit_left(moving_bits: &mut [SingleDisplayData], ) {
let len = moving_bits.len();
for display_i in 0..len {
for row_i in 0..8 {
if moving_bits[display_i][row_i] & 0b10000000 != 0 {
if display_i == 0
{
moving_bits[len - 1][row_i] |= 1;
} else {
moving_bits[display_i - 1][row_i] |= 1;
}
}
moving_bits[display_i][row_i] <<= 1;
}
}
}
#[cfg(feature = "std")]
pub fn prepare_display(display: &mut Max7219, display_count: usize, intensity: u8) {
let display_count = display_count % MAX_DISPLAYS;
display.power_on().unwrap();
for i in 0..display_count {
display.set_decode_mode(i, DecodeMode::NoDecode).unwrap();
display.clear_display(i).unwrap();
display.set_intensity(i, intensity).unwrap();
}
}
#[cfg(feature = "std")]
pub fn show_moving_text_in_loop(
display: &mut Max7219,
text: &str,
display_count: usize,
ms_sleep: u64,
max_gap_width: usize,
) {
let display_count = display_count % MAX_DISPLAYS;
let raw_bits = encode_string(text);
let mut display_bits;
if max_gap_width > 0 {
display_bits = remove_gaps_in_display_text(&raw_bits, max_gap_width);
} else {
display_bits = raw_bits;
}
loop {
for i in 0..display_count {
display.write_raw(i, &display_bits[i]).unwrap();
}
sleep(Duration::from_millis(ms_sleep));
shift_all_rows_one_bit_left(&mut display_bits);
}
}
pub fn remove_gaps_in_display_text(display_data: &[SingleDisplayData], max_gap_size: usize) -> Vec<SingleDisplayData> {
let display_data: Vec<SingleDisplayData> = display_data.iter()
.map(|x| transpose_single_display_data(x.clone()))
.collect();
let mut display_data_expanded = vec![];
for x in &display_data {
for y in x {
display_data_expanded.push(y);
}
}
let mut preserve_at_begin = 0;
let mut preserve_at_end = 0;
for i in 0..display_data_expanded.len() {
if *display_data_expanded[i] == 0 {
preserve_at_begin += 1;
} else {
break;
}
}
for i in 0..display_data_expanded.len() {
let i = display_data_expanded.len() - 1 - i;
if *display_data_expanded[i] == 0 {
preserve_at_end += 1;
} else {
break;
}
}
let mut shrinked_display_data_expanded = vec![0 as u8; preserve_at_begin];
let mut count_since_last_not_empty = 0;
for i in preserve_at_begin..display_data_expanded.len() - preserve_at_end {
if *display_data_expanded[i] == 0 {
count_since_last_not_empty += 1;
} else {
count_since_last_not_empty = 0;
}
if count_since_last_not_empty <= max_gap_size {
shrinked_display_data_expanded.push(*display_data_expanded[i]);
}
}
shrinked_display_data_expanded.extend_from_slice(&vec![0; preserve_at_end]);
let add_to_be_divider_of_8 = 8 - (shrinked_display_data_expanded.len() % 8);
shrinked_display_data_expanded.extend_from_slice(&vec![0; add_to_be_divider_of_8]);
let mut shrinked_display_data_transposed: Vec<SingleDisplayData> = vec![];
for i in (0..shrinked_display_data_expanded.len()).step_by(8) {
let mut slice: SingleDisplayData = [0; 8];
for j in 0..8 {
slice[j] = shrinked_display_data_expanded[i + j];
}
shrinked_display_data_transposed.push(slice);
}
let shrinked_display_data: Vec<SingleDisplayData> = shrinked_display_data_transposed.into_iter()
.map(|x| transpose_single_display_data(x))
.collect();
shrinked_display_data
}
pub fn transpose_single_display_data(data: SingleDisplayData) -> SingleDisplayData {
let mut transposed_data: SingleDisplayData = [0; 8];
for col_i in 0..8 {
let mut col = 0;
for row_i in 0..8 {
let col_bit = (data[row_i] >> (7 - col_i)) & 1;
col = (col << 1) | col_bit;
}
transposed_data[col_i] = col;
}
transposed_data
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_move_all_bits_one_col_left() {
let data_dis_0 = [
0b01000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000,
];
let data_dis_1 = [
0b11000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000,
];
let mut data = Vec::new();
data.push(data_dis_0);
data.push(data_dis_1);
shift_all_rows_one_bit_left(&mut data);
let first_row_dis_0_expected = 0b10000001;
let first_row_dis_1_expected = 0b10000000;
let first_row_dis_0_actual = data[0][0];
let first_row_dis_1_actual = data[1][0];
assert_eq!(first_row_dis_0_actual, first_row_dis_0_expected);
assert_eq!(first_row_dis_1_actual, first_row_dis_1_expected);
}
#[test]
fn test_transpose_single_display_data() {
let input = [
0b0100_0000,
0b0100_0000,
0b0100_0000,
0b0100_0000,
0b0000_0011,
0b0000_0011,
0b0000_0011,
0b0000_0011,
];
let expected = [
0b0000_0000,
0b1111_0000,
0b0000_0000,
0b0000_0000,
0b0000_0000,
0b0000_0000,
0b0000_1111,
0b0000_1111,
];
let actual = transpose_single_display_data( input);
for i in 0..input.len() {
assert_eq!(
actual[i], expected[i],
"swap_cols_to_rows() doesn't transposed the matrix properly at index {}! is={:#b}, expected={:#b}",
i, actual[i], expected[i]
);
}
}
#[test]
fn test_remove_gaps_in_display_text() {
let vec = vec![
[
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
],
[
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
]
];
let expected = vec![
[
0b10010000,
0b10010000,
0b10010000,
0b10010000,
0b10010000,
0b10010000,
0b10010000,
0b10010000,
],[
0,
0,
0,
0,
0,
0,
0,
0,
]
];
let actual = remove_gaps_in_display_text(&vec, 2);
for i in 0..2 {
for j in 0..8 {
assert_eq!(actual[i][j], expected[i][j], "expected: {:#b}, is: {:#b}", expected[i][j], vec[i][j]);
}
}
}
}