st7735_async_low/
command_structs.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use paste::paste;
16
17macro_rules! define_pub_bit_type {
18    ($name:ident, zero: $zero_value:ident, one: $one_value:ident,
19                  doc: $doc:literal) => {
20        #[doc = $doc]
21        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
22        pub enum $name {
23            $zero_value = 0,
24            $one_value = 1,
25        }
26        impl $name {
27            fn from_bool(b: bool) -> Self {  // Private.
28                if b { Self::$zero_value } else { Self::$one_value }
29            }
30            fn to_bool(&self) -> bool {  // Private.
31                match *self {
32                    Self::$zero_value => false,
33                    Self::$one_value => true,
34                }
35            }
36        }
37        impl Default for $name {
38            fn default() -> Self { Self::$zero_value }
39        }
40        impl ::core::fmt::Display for $name {
41            fn fmt(&self, f: &mut ::core::fmt::Formatter)
42                    -> ::core::fmt::Result {
43                <Self as core::fmt::Debug>::fmt(self, f)
44            }
45        }
46    };
47}
48macro_rules! bit_field {
49    ($name:ident, type: $type:ty, bit_offset: $i:expr) => {
50        pub fn $name(&self) -> $type {
51            <$type>::from_bool((self.data >> $i) & 1 == 1)
52        }
53        paste! {
54            pub fn [<set_ $name>](&mut self, value: $type) -> &mut Self {
55                if value.to_bool() {
56                    self.data &= !(1 << $i);
57                } else {
58                    self.data |= 1 << $i;
59                }
60                self
61            }
62        }
63    }
64}
65
66/// Defines the orientation parameters of the screen.
67///
68/// # Example
69///
70/// ```
71/// # use st7735_async_low::*;
72/// let mut mctl = Madctl::default();
73/// mctl.set_row_address_order(RowOrder::TopToBottom)
74///     .set_column_address_order(ColumnOrder::LeftToRight)
75///     .set_row_column_swap(RowColumnSwap::Swapped)
76///     .set_vertical_refresh_order(RowOrder::BottomToTop)
77///     .set_horizontal_refresh_order(ColumnOrder::RightToLeft)
78///     .set_rgb_order(ColorComponentOrder::BlueGreenRed);
79/// assert_eq!(mctl.row_address_order(), RowOrder::TopToBottom);
80/// assert_eq!(mctl.row_column_swap(), RowColumnSwap::Swapped);
81/// // Can invoke `Commands::madctl(mctl)` to send it to the LCD.
82/// ```
83#[derive(Clone, Copy, Debug, Default)]
84pub struct Madctl {
85    data: u8,
86}
87impl Madctl {
88    bit_field!(row_address_order, type: RowOrder, bit_offset: 7);
89    bit_field!(column_address_order, type: ColumnOrder, bit_offset: 6);
90    bit_field!(row_column_swap, type: RowColumnSwap, bit_offset: 5);
91    bit_field!(vertical_refresh_order, type: RowOrder, bit_offset: 4);
92    bit_field!(horizontal_refresh_order, type: ColumnOrder, bit_offset: 2);
93    bit_field!(rgb_order, type: ColorComponentOrder, bit_offset: 3);
94}
95impl From<Madctl> for u8 {
96    fn from(mctl: Madctl) -> u8 { mctl.data }
97}
98impl ::core::fmt::Display for Madctl {
99    fn fmt(&self, f: &mut ::core::fmt::Formatter)
100            -> ::core::fmt::Result {
101        <Self as core::fmt::Debug>::fmt(self, f)
102    }
103}
104
105define_pub_bit_type!(RowOrder, zero: TopToBottom, one: BottomToTop,
106                     doc: "The row order of the LCD pixels.");
107
108define_pub_bit_type!(ColumnOrder, zero: LeftToRight, one: RightToLeft,
109                     doc: "The column order of the LCD pixels.");
110define_pub_bit_type!(RowColumnSwap, zero: Unswapped, one: Swapped,
111                     doc: "Whether to swap the row and column definitions, \
112                     i.e., to switch between the portrait and landscape mode.");
113define_pub_bit_type!(ColorComponentOrder, zero: RedGreenBlue, one: BlueGreenRed,
114                     doc: "R/G/B component order inside a pixel.");
115
116/// Color mode (the bit widths of the R, G and B components of a pixel).
117///
118/// The native format is 6-bit for each component. When another (smaller) mode
119/// is used, the LCD will internally translate each component into the 6-bit
120/// format with a lookup table. See Sec 9.18 "Color Depth Conversion Look Up
121/// Tables" of the ST7735S datasheet for the lookup table (LUT).
122#[derive(Clone, Copy, Debug)]
123pub enum Colmod {
124    /// Each component has 4 bits. LUT will be used.
125    R4G4B4 = 0b011,
126    /// Red has 5 bits; green has 6 bits; blue has 5 bits. LUT will be used.
127    R5G6B5 = 0b101,
128    /// Each compoment has 6 bits. This is the native format; LUT will **not**
129    /// be used.
130    R6G6B6 = 0b110,
131    /// No idea when this value can be used.
132    Unknown = 0b111,
133}
134impl Default for Colmod {
135    fn default() -> Self { Self::Unknown }
136}
137impl From<Colmod> for u8 {
138    fn from(colmod: Colmod) -> u8 { colmod as u8 }
139}
140impl From<u8> for Colmod {
141    fn from(raw: u8) -> Self {
142        use Colmod::*;
143        const R4G4B4_VALUE: u8 = R4G4B4 as u8;
144        const R5G6B5_VALUE: u8 = R5G6B5 as u8;
145        const R6G6B6_VALUE: u8 = R6G6B6 as u8;
146        match raw {
147            R4G4B4_VALUE => R4G4B4,
148            R5G6B5_VALUE => R5G6B5,
149            R6G6B6_VALUE => R6G6B6,
150            _ => Unknown,
151        }
152    }
153}
154impl ::core::fmt::Display for Colmod {
155    fn fmt(&self, f: &mut ::core::fmt::Formatter)
156            -> ::core::fmt::Result {
157        <Self as core::fmt::Debug>::fmt(self, f)
158    }
159}