use paste::paste;
macro_rules! define_pub_bit_type {
($name:ident, zero: $zero_value:ident, one: $one_value:ident,
doc: $doc:literal) => {
#[doc = $doc]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum $name {
$zero_value = 0,
$one_value = 1,
}
impl $name {
fn from_bool(b: bool) -> Self { if b { Self::$zero_value } else { Self::$one_value }
}
fn to_bool(&self) -> bool { match *self {
Self::$zero_value => false,
Self::$one_value => true,
}
}
}
impl Default for $name {
fn default() -> Self { Self::$zero_value }
}
impl ::core::fmt::Display for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
<Self as core::fmt::Debug>::fmt(self, f)
}
}
};
}
macro_rules! bit_field {
($name:ident, type: $type:ty, bit_offset: $i:expr) => {
pub fn $name(&self) -> $type {
<$type>::from_bool((self.data >> $i) & 1 == 1)
}
paste! {
pub fn [<set_ $name>](&mut self, value: $type) -> &mut Self {
if value.to_bool() {
self.data &= !(1 << $i);
} else {
self.data |= 1 << $i;
}
self
}
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Madctl {
data: u8,
}
impl Madctl {
bit_field!(row_address_order, type: RowOrder, bit_offset: 7);
bit_field!(column_address_order, type: ColumnOrder, bit_offset: 6);
bit_field!(row_column_swap, type: RowColumnSwap, bit_offset: 5);
bit_field!(vertical_refresh_order, type: RowOrder, bit_offset: 4);
bit_field!(horizontal_refresh_order, type: ColumnOrder, bit_offset: 2);
bit_field!(rgb_order, type: ColorComponentOrder, bit_offset: 3);
}
impl From<Madctl> for u8 {
fn from(mctl: Madctl) -> u8 { mctl.data }
}
impl ::core::fmt::Display for Madctl {
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
<Self as core::fmt::Debug>::fmt(self, f)
}
}
define_pub_bit_type!(RowOrder, zero: TopToBottom, one: BottomToTop,
doc: "The row order of the LCD pixels.");
define_pub_bit_type!(ColumnOrder, zero: LeftToRight, one: RightToLeft,
doc: "The column order of the LCD pixels.");
define_pub_bit_type!(RowColumnSwap, zero: Unswapped, one: Swapped,
doc: "Whether to swap the row and column definitions, \
i.e., to switch between the portrait and landscape mode.");
define_pub_bit_type!(ColorComponentOrder, zero: RedGreenBlue, one: BlueGreenRed,
doc: "R/G/B component order inside a pixel.");
#[derive(Clone, Copy, Debug)]
pub enum Colmod {
R4G4B4 = 0b011,
R5G6B5 = 0b101,
R6G6B6 = 0b110,
Unknown = 0b111,
}
impl Default for Colmod {
fn default() -> Self { Self::Unknown }
}
impl From<Colmod> for u8 {
fn from(colmod: Colmod) -> u8 { colmod as u8 }
}
impl From<u8> for Colmod {
fn from(raw: u8) -> Self {
use Colmod::*;
const R4G4B4_VALUE: u8 = R4G4B4 as u8;
const R5G6B5_VALUE: u8 = R5G6B5 as u8;
const R6G6B6_VALUE: u8 = R6G6B6 as u8;
match raw {
R4G4B4_VALUE => R4G4B4,
R5G6B5_VALUE => R5G6B5,
R6G6B6_VALUE => R6G6B6,
_ => Unknown,
}
}
}
impl ::core::fmt::Display for Colmod {
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
<Self as core::fmt::Debug>::fmt(self, f)
}
}