Skip to main content

lcd_async/
options.rs

1//! [ModelOptions] and other helper types.
2
3use crate::models::Model;
4
5mod orientation;
6pub(crate) use orientation::MemoryMapping;
7pub use orientation::{InvalidAngleError, Orientation, Rotation};
8
9/// [ModelOptions] are passed to the [`init`](Model::init) method of [Model]
10/// implementations.
11#[derive(Clone)]
12#[non_exhaustive]
13pub struct ModelOptions {
14    /// Subpixel order.
15    pub color_order: ColorOrder,
16    /// Initial display orientation.
17    pub orientation: Orientation,
18    /// Whether to invert colors for this display/model (INVON)
19    pub invert_colors: ColorInversion,
20    /// Display refresh order.
21    pub refresh_order: RefreshOrder,
22    /// Display size (w, h) for given display.
23    pub display_size: (u16, u16),
24    /// Display offset (x, y) for given display.
25    pub display_offset: (u16, u16),
26}
27
28impl ModelOptions {
29    /// Creates model options for the entire framebuffer.
30    pub fn full_size<M: Model>() -> Self {
31        Self {
32            color_order: ColorOrder::default(),
33            orientation: Orientation::default(),
34            invert_colors: ColorInversion::default(),
35            refresh_order: RefreshOrder::default(),
36            display_size: M::FRAMEBUFFER_SIZE,
37            display_offset: (0, 0),
38        }
39    }
40
41    /// Creates model options for the given size and offset.
42    pub fn with_all(display_size: (u16, u16), display_offset: (u16, u16)) -> Self {
43        Self {
44            color_order: ColorOrder::default(),
45            orientation: Orientation::default(),
46            invert_colors: ColorInversion::default(),
47            refresh_order: RefreshOrder::default(),
48            display_size,
49            display_offset,
50        }
51    }
52
53    /// Returns the display size based on current orientation and display options.
54    ///
55    /// Used by models.
56    #[allow(dead_code)]
57    pub(crate) fn display_size(&self) -> (u16, u16) {
58        if self.orientation.rotation.is_horizontal() {
59            self.display_size
60        } else {
61            (self.display_size.1, self.display_size.0)
62        }
63    }
64}
65
66/// Color inversion.
67#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
68pub enum ColorInversion {
69    /// Normal colors.
70    #[default]
71    Normal,
72    /// Inverted colors.
73    Inverted,
74}
75
76/// Vertical refresh order.
77#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
78pub enum VerticalRefreshOrder {
79    /// Refresh from top to bottom.
80    #[default]
81    TopToBottom,
82    /// Refresh from bottom to top.
83    BottomToTop,
84}
85
86impl VerticalRefreshOrder {
87    /// Returns the opposite refresh order.
88    #[must_use]
89    pub const fn flip(self) -> Self {
90        match self {
91            Self::TopToBottom => Self::BottomToTop,
92            Self::BottomToTop => Self::TopToBottom,
93        }
94    }
95}
96
97/// Horizontal refresh order.
98#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
99pub enum HorizontalRefreshOrder {
100    /// Refresh from left to right.
101    #[default]
102    LeftToRight,
103    /// Refresh from right to left.
104    RightToLeft,
105}
106
107impl HorizontalRefreshOrder {
108    /// Returns the opposite refresh order.
109    #[must_use]
110    pub const fn flip(self) -> Self {
111        match self {
112            Self::LeftToRight => Self::RightToLeft,
113            Self::RightToLeft => Self::LeftToRight,
114        }
115    }
116}
117
118/// Display refresh order.
119///
120/// Defaults to left to right, top to bottom.
121#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
122pub struct RefreshOrder {
123    /// Vertical refresh order.
124    pub vertical: VerticalRefreshOrder,
125    /// Horizontal refresh order.
126    pub horizontal: HorizontalRefreshOrder,
127}
128
129impl RefreshOrder {
130    /// Creates a new refresh order.
131    pub const fn new(vertical: VerticalRefreshOrder, horizontal: HorizontalRefreshOrder) -> Self {
132        Self {
133            vertical,
134            horizontal,
135        }
136    }
137
138    /// Returns a refresh order with flipped vertical refresh order.
139    #[must_use]
140    pub const fn flip_vertical(self) -> Self {
141        Self {
142            vertical: self.vertical.flip(),
143            ..self
144        }
145    }
146
147    /// Returns a refresh order with flipped horizontal refresh order.
148    #[must_use]
149    pub const fn flip_horizontal(self) -> Self {
150        Self {
151            horizontal: self.horizontal.flip(),
152            ..self
153        }
154    }
155}
156
157/// Tearing effect output setting.
158#[derive(Copy, Clone, Debug, PartialEq, Eq)]
159pub enum TearingEffect {
160    /// Disable output.
161    Off,
162    /// Output vertical blanking information.
163    Vertical,
164    /// Output horizontal and vertical blanking information.
165    HorizontalAndVertical,
166}
167
168/// Subpixel order.
169#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
170pub enum ColorOrder {
171    /// RGB subpixel order.
172    #[default]
173    Rgb,
174    /// BGR subpixel order.
175    Bgr,
176}