lcd_async/dcs/
set_address_mode.rs1use crate::options::{
4 ColorOrder, HorizontalRefreshOrder, MemoryMapping, ModelOptions, Orientation, RefreshOrder,
5 VerticalRefreshOrder,
6};
7
8use super::DcsCommand;
9
10#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct SetAddressMode(u8);
14
15impl SetAddressMode {
16 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 #[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 #[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 #[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}