use bitfield::bitfield;
pub mod frame;
pub mod row;
pub use frame::DmaFrameBuffer;
pub(crate) use crate::{INTER_ROW_BLANK, LEAD_BLANK_DELAY, TRAIL_BLANK_DELAY};
#[cfg(not(feature = "invert-oe"))]
pub(crate) const OE_ACTIVE: u8 = 0b1000_0000;
#[cfg(not(feature = "invert-oe"))]
pub(crate) const OE_BLANK: u8 = 0;
#[cfg(feature = "invert-oe")]
pub(crate) const OE_ACTIVE: u8 = 0;
#[cfg(feature = "invert-oe")]
pub(crate) const OE_BLANK: u8 = 0b1000_0000;
bitfield! {
#[derive(Clone, Copy, Default, PartialEq, Eq)]
#[repr(transparent)]
pub(crate) struct Address(u8);
impl Debug;
pub(crate) output_enable, set_output_enable: 7;
pub(crate) latch, set_latch: 6;
pub(crate) addr, set_addr: 4, 0;
}
impl Address {
pub const fn new() -> Self {
Self(0)
}
}
bitfield! {
#[derive(Clone, Copy, Default, PartialEq)]
#[repr(transparent)]
pub(crate) struct Entry(u8);
impl Debug;
pub(crate) output_enable, set_output_enable: 7;
pub(crate) latch, set_latch: 6;
pub(crate) blu2, set_blu2: 5;
pub(crate) grn2, set_grn2: 4;
pub(crate) red2, set_red2: 3;
pub(crate) blu1, set_blu1: 2;
pub(crate) grn1, set_grn1: 1;
pub(crate) red1, set_red1: 0;
}
impl Entry {
pub const fn new() -> Self {
Self(0)
}
const COLOR0_MASK: u8 = 0b0000_0111;
const COLOR1_MASK: u8 = 0b0011_1000;
#[inline]
fn set_color0_bits(&mut self, bits: u8) {
self.0 = (self.0 & !Self::COLOR0_MASK) | (bits & Self::COLOR0_MASK);
}
#[inline]
fn set_color1_bits(&mut self, bits: u8) {
self.0 = (self.0 & !Self::COLOR1_MASK) | ((bits << 3) & Self::COLOR1_MASK);
}
}
#[inline]
pub(crate) const fn map_index(index: usize) -> usize {
#[cfg(feature = "esp32-ordering")]
{
index ^ 2
}
#[cfg(not(feature = "esp32-ordering"))]
{
index
}
}
pub(crate) const fn make_addr_table() -> [[Address; 4]; 32] {
let mut tbl = [[Address::new(); 4]; 32];
let mut addr = 0;
while addr < 32 {
tbl[addr][map_index(0)].0 = OE_BLANK | 1u8 << 6 | addr as u8;
tbl[addr][map_index(1)].0 = OE_BLANK | 1u8 << 6 | addr as u8;
tbl[addr][map_index(2)].0 = OE_BLANK | addr as u8;
tbl[addr][map_index(3)].0 = OE_BLANK;
addr += 1;
}
tbl
}
pub(crate) const ADDR_TABLE: [[Address; 4]; 32] = make_addr_table();
#[allow(clippy::absurd_extreme_comparisons)]
pub(crate) const fn make_data_template<const COLS: usize>() -> [Entry; COLS] {
let mut data = [Entry::new(); COLS];
let mut i = 0;
while i < COLS {
let mapped_i = map_index(i);
data[mapped_i].0 =
if i >= TRAIL_BLANK_DELAY && i < COLS.saturating_sub(LEAD_BLANK_DELAY + 1) {
OE_ACTIVE
} else {
OE_BLANK
};
i += 1;
}
data
}