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)]
12pub struct SetAddressMode(u8);
13
14impl SetAddressMode {
15 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 #[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 #[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 #[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}