Skip to main content

lcd_async/dcs/
set_address_mode.rs

1//! Module for the MADCTL instruction constructors
2
3use crate::options::{
4    ColorOrder, HorizontalRefreshOrder, MemoryMapping, ModelOptions, Orientation, RefreshOrder,
5    VerticalRefreshOrder,
6};
7
8use super::DcsCommand;
9
10/// Set Address Mode
11#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct SetAddressMode(u8);
14
15impl SetAddressMode {
16    /// Creates a new Set Address Mode command.
17    pub const fn new(
18        color_order: ColorOrder,
19        orientation: Orientation,
20        refresh_order: RefreshOrder,
21    ) -> Self {
22        Self(0)
23            .with_color_order(color_order)
24            .with_orientation(orientation)
25            .with_refresh_order(refresh_order)
26    }
27
28    /// Returns this Madctl with [ColorOrder] set to new value
29    #[must_use]
30    pub const fn with_color_order(self, color_order: ColorOrder) -> Self {
31        let mut result = self;
32        match color_order {
33            ColorOrder::Rgb => result.0 &= 0b1111_0111,
34            ColorOrder::Bgr => result.0 |= 0b0000_1000,
35        }
36
37        result
38    }
39
40    /// Returns this Madctl with [Orientation] set to new value
41    #[must_use]
42    pub const fn with_orientation(self, orientation: Orientation) -> Self {
43        let mut result = self.0;
44        result &= 0b0001_1111;
45
46        let mapping = MemoryMapping::from_orientation(orientation);
47        if mapping.reverse_rows {
48            result |= 1 << 7;
49        }
50        if mapping.reverse_columns {
51            result |= 1 << 6;
52        }
53        if mapping.swap_rows_and_columns {
54            result |= 1 << 5;
55        }
56
57        Self(result)
58    }
59
60    /// Returns this Madctl with [RefreshOrder] set to new value
61    #[must_use]
62    pub const fn with_refresh_order(self, refresh_order: RefreshOrder) -> Self {
63        let mut result = self;
64        let value = match (refresh_order.vertical, refresh_order.horizontal) {
65            (VerticalRefreshOrder::TopToBottom, HorizontalRefreshOrder::LeftToRight) => 0b0000_0000,
66            (VerticalRefreshOrder::TopToBottom, HorizontalRefreshOrder::RightToLeft) => 0b0000_0100,
67            (VerticalRefreshOrder::BottomToTop, HorizontalRefreshOrder::LeftToRight) => 0b0001_0000,
68            (VerticalRefreshOrder::BottomToTop, HorizontalRefreshOrder::RightToLeft) => 0b0001_0100,
69        };
70
71        result.0 = (result.0 & 0b1110_1011) | value;
72
73        result
74    }
75}
76
77impl DcsCommand for SetAddressMode {
78    fn instruction(&self) -> u8 {
79        0x36
80    }
81
82    fn fill_params_buf(&self, buffer: &mut [u8]) -> usize {
83        buffer[0] = self.0;
84        1
85    }
86}
87
88impl From<&ModelOptions> for SetAddressMode {
89    fn from(options: &ModelOptions) -> Self {
90        Self::default()
91            .with_color_order(options.color_order)
92            .with_orientation(options.orientation)
93            .with_refresh_order(options.refresh_order)
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use crate::options::Rotation;
100
101    use super::*;
102
103    #[test]
104    fn madctl_bit_operations() {
105        let madctl = SetAddressMode::default()
106            .with_color_order(ColorOrder::Bgr)
107            .with_refresh_order(RefreshOrder::new(
108                VerticalRefreshOrder::BottomToTop,
109                HorizontalRefreshOrder::RightToLeft,
110            ))
111            .with_orientation(Orientation::default().rotate(Rotation::Deg270));
112
113        let mut bytes = [0u8];
114        assert_eq!(madctl.fill_params_buf(&mut bytes), 1);
115        assert_eq!(bytes, [0b1011_1100u8]);
116
117        let madctl = madctl.with_orientation(Orientation::default());
118        assert_eq!(madctl.fill_params_buf(&mut bytes), 1);
119        assert_eq!(bytes, [0b0001_1100u8]);
120
121        let madctl = madctl.with_color_order(ColorOrder::Rgb);
122        assert_eq!(madctl.fill_params_buf(&mut bytes), 1);
123        assert_eq!(bytes, [0b0001_0100u8]);
124
125        let madctl = madctl.with_refresh_order(RefreshOrder::default());
126        assert_eq!(madctl.fill_params_buf(&mut bytes), 1);
127        assert_eq!(bytes, [0b0000_0000u8]);
128    }
129}