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