display_types/panel.rs
1/// Display technology type, decoded from Display Device Data Block (0x0C) byte 0 bits 7:4.
2///
3/// Identifies the physical display technology used by an embedded panel.
4#[non_exhaustive]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum DisplayTechnology {
8 /// Thin-film transistor LCD, unspecified sub-type (`0`).
9 Tft,
10 /// DSTN or STN (dual-scan or super-twisted nematic LCD) (`1`).
11 DstnStn,
12 /// TFT-IPS or super-TFT (in-plane switching) (`2`).
13 TftIps,
14 /// TFT-MVA or TFT-PVA (multi-domain / patterned vertical alignment) (`3`).
15 TftMva,
16 /// CRT (cathode ray tube) (`4`).
17 Crt,
18 /// PDP (plasma display panel) (`5`).
19 Pdp,
20 /// OLED or ELED (organic light emitting) (`6`).
21 Oled,
22 /// EL (electroluminescent) (`7`).
23 El,
24 /// FED or SED (field emission / surface-conduction electron emission) (`8`).
25 FedSed,
26 /// LCoS (liquid crystal on silicon) (`9`).
27 Lcos,
28 /// Reserved or undefined value (`10`–`15`).
29 Unknown(u8),
30}
31
32impl DisplayTechnology {
33 /// Decodes the display technology from a 4-bit nibble (bits 7:4 of byte 0).
34 pub fn from_nibble(nibble: u8) -> Self {
35 match nibble & 0x0F {
36 0 => Self::Tft,
37 1 => Self::DstnStn,
38 2 => Self::TftIps,
39 3 => Self::TftMva,
40 4 => Self::Crt,
41 5 => Self::Pdp,
42 6 => Self::Oled,
43 7 => Self::El,
44 8 => Self::FedSed,
45 9 => Self::Lcos,
46 v => Self::Unknown(v),
47 }
48 }
49}
50
51/// Panel operating mode, decoded from Display Device Data Block (0x0C) byte 1 bits 3:0.
52#[non_exhaustive]
53#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum OperatingMode {
56 /// Continuous (free-running) refresh (`0`).
57 Continuous,
58 /// Non-continuous (event-driven or line-at-a-time) refresh (`1`).
59 NonContinuous,
60 /// Reserved or undefined value (`2`–`15`).
61 Unknown(u8),
62}
63
64impl OperatingMode {
65 /// Decodes the operating mode from the lower 4 bits of byte 1.
66 pub fn from_nibble(nibble: u8) -> Self {
67 match nibble & 0x0F {
68 0 => Self::Continuous,
69 1 => Self::NonContinuous,
70 v => Self::Unknown(v),
71 }
72 }
73}
74
75/// Backlight type, decoded from Display Device Data Block (0x0C) byte 1 bits 5:4.
76#[non_exhaustive]
77#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub enum BacklightType {
80 /// No backlight, or not applicable (`0`).
81 None,
82 /// AC fluorescent (CCFL) backlight (`1`).
83 AcFluorescent,
84 /// DC-powered backlight (LED or other) (`2`).
85 Dc,
86 /// Reserved value (`3`).
87 Unknown(u8),
88}
89
90impl BacklightType {
91 /// Decodes the backlight type from a 2-bit value (bits 5:4 of byte 1).
92 pub fn from_bits(bits: u8) -> Self {
93 match bits & 0x03 {
94 0 => Self::None,
95 1 => Self::AcFluorescent,
96 2 => Self::Dc,
97 v => Self::Unknown(v),
98 }
99 }
100}
101
102/// Physical mounting orientation of the panel, decoded from Display Device Data Block (0x0C)
103/// byte 7 bits 1:0.
104#[non_exhaustive]
105#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum PhysicalOrientation {
108 /// Landscape — wider than tall (`0`).
109 Landscape,
110 /// Portrait — taller than wide (`1`).
111 Portrait,
112 /// Orientation not defined; may be freely rotated (`2`).
113 NotDefined,
114 /// Undefined / reserved encoding (`3`).
115 Undefined,
116}
117
118impl PhysicalOrientation {
119 /// Decodes the physical orientation from a 2-bit value (bits 1:0 of byte 7).
120 pub fn from_bits(bits: u8) -> Self {
121 match bits & 0x03 {
122 0 => Self::Landscape,
123 1 => Self::Portrait,
124 2 => Self::NotDefined,
125 _ => Self::Undefined,
126 }
127 }
128}
129
130/// Rotation capability, decoded from Display Device Data Block (0x0C) byte 7 bits 3:2.
131#[non_exhaustive]
132#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum RotationCapability {
135 /// No display rotation supported (`0`).
136 None,
137 /// 90° clockwise rotation supported (`1`).
138 Cw90,
139 /// 180° rotation supported (`2`).
140 Deg180,
141 /// 270° clockwise (90° counter-clockwise) rotation supported (`3`).
142 Cw270,
143}
144
145impl RotationCapability {
146 /// Decodes the rotation capability from a 2-bit value (bits 3:2 of byte 7).
147 pub fn from_bits(bits: u8) -> Self {
148 match bits & 0x03 {
149 0 => Self::None,
150 1 => Self::Cw90,
151 2 => Self::Deg180,
152 _ => Self::Cw270,
153 }
154 }
155}
156
157/// Location of the zero pixel (the upper-left pixel in the framebuffer), decoded from
158/// Display Device Data Block (0x0C) byte 7 bits 5:4.
159#[non_exhaustive]
160#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
161#[derive(Debug, Clone, Copy, PartialEq, Eq)]
162pub enum ZeroPixelLocation {
163 /// Zero pixel is at the upper-left corner (`0`).
164 UpperLeft,
165 /// Zero pixel is at the upper-right corner (`1`).
166 UpperRight,
167 /// Zero pixel is at the lower-left corner (`2`).
168 LowerLeft,
169 /// Zero pixel is at the lower-right corner (`3`).
170 LowerRight,
171}
172
173impl ZeroPixelLocation {
174 /// Decodes the zero pixel location from a 2-bit value (bits 5:4 of byte 7).
175 pub fn from_bits(bits: u8) -> Self {
176 match bits & 0x03 {
177 0 => Self::UpperLeft,
178 1 => Self::UpperRight,
179 2 => Self::LowerLeft,
180 _ => Self::LowerRight,
181 }
182 }
183}
184
185/// Scan direction of the fast (horizontal) scan relative to H-sync, decoded from
186/// Display Device Data Block (0x0C) byte 7 bits 7:6.
187#[non_exhaustive]
188#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub enum ScanDirection {
191 /// Scan direction not defined (`0`).
192 NotDefined,
193 /// Fast scan follows the H-sync direction; slow scan follows V-sync direction (`1`).
194 Normal,
195 /// Fast scan direction is opposite to H-sync; slow scan opposite to V-sync (`2`).
196 Reversed,
197 /// Reserved value (`3`).
198 Reserved,
199}
200
201impl ScanDirection {
202 /// Decodes the scan direction from a 2-bit value (bits 7:6 of byte 7).
203 pub fn from_bits(bits: u8) -> Self {
204 match bits & 0x03 {
205 0 => Self::NotDefined,
206 1 => Self::Normal,
207 2 => Self::Reversed,
208 _ => Self::Reserved,
209 }
210 }
211}
212
213/// Sub-pixel layout, decoded from Display Device Data Block (0x0C) byte 8.
214#[non_exhaustive]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum SubpixelLayout {
218 /// Sub-pixel arrangement not defined (`0x00`).
219 NotDefined,
220 /// RGB vertical stripes (`0x01`).
221 RgbVertical,
222 /// BGR vertical stripes (`0x02`).
223 BgrVertical,
224 /// RGB horizontal stripes (`0x03`).
225 RgbHorizontal,
226 /// BGR horizontal stripes (`0x04`).
227 BgrHorizontal,
228 /// Quad arrangement: RGBG (`0x05`).
229 QuadRgbg,
230 /// Quad arrangement: BGRG (`0x06`).
231 QuadBgrg,
232 /// Delta (triangular) RGB arrangement (`0x07`).
233 DeltaRgb,
234 /// Delta (triangular) BGR arrangement (`0x08`).
235 DeltaBgr,
236 /// Reserved or proprietary layout (`0x09`–`0xFF`).
237 Unknown(u8),
238}
239
240impl SubpixelLayout {
241 /// Decodes the sub-pixel layout from the raw byte 8 value.
242 pub fn from_byte(byte: u8) -> Self {
243 match byte {
244 0x00 => Self::NotDefined,
245 0x01 => Self::RgbVertical,
246 0x02 => Self::BgrVertical,
247 0x03 => Self::RgbHorizontal,
248 0x04 => Self::BgrHorizontal,
249 0x05 => Self::QuadRgbg,
250 0x06 => Self::QuadBgrg,
251 0x07 => Self::DeltaRgb,
252 0x08 => Self::DeltaBgr,
253 v => Self::Unknown(v),
254 }
255 }
256}
257
258/// Physical interface standard type, decoded from Display Interface Data Block (0x0F)
259/// byte 0 bits 3:0.
260#[non_exhaustive]
261#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
263pub enum DisplayInterfaceType {
264 /// Undefined / not specified (`0x0`).
265 Undefined,
266 /// Analog (VGA) interface (`0x1`).
267 Analog,
268 /// LVDS single link (`0x2`).
269 LvdsSingle,
270 /// LVDS dual link (`0x3`).
271 LvdsDual,
272 /// TMDS single link — DVI-D single or HDMI (`0x4`).
273 TmdsSingle,
274 /// TMDS dual link — DVI-DL or HDMI dual (`0x5`).
275 TmdsDual,
276 /// Embedded DisplayPort (eDP) (`0x6`).
277 EmbeddedDisplayPort,
278 /// External DisplayPort (DP) (`0x7`).
279 DisplayPort,
280 /// Proprietary interface (`0x8`).
281 Proprietary,
282 /// Reserved or unrecognized value (`0x9`–`0xF`).
283 Reserved(u8),
284}
285
286impl DisplayInterfaceType {
287 /// Decodes the interface type from the lower 4 bits of byte 0.
288 pub fn from_nibble(nibble: u8) -> Self {
289 match nibble & 0x0F {
290 0x0 => Self::Undefined,
291 0x1 => Self::Analog,
292 0x2 => Self::LvdsSingle,
293 0x3 => Self::LvdsDual,
294 0x4 => Self::TmdsSingle,
295 0x5 => Self::TmdsDual,
296 0x6 => Self::EmbeddedDisplayPort,
297 0x7 => Self::DisplayPort,
298 0x8 => Self::Proprietary,
299 v => Self::Reserved(v),
300 }
301 }
302}
303
304/// Content protection mechanism supported on the display interface, decoded from Display
305/// Interface Data Block (0x0F) byte 6 bits 1:0.
306#[non_exhaustive]
307#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309pub enum InterfaceContentProtection {
310 /// No content protection (`0`).
311 None,
312 /// High-bandwidth Digital Content Protection (HDCP) (`1`).
313 Hdcp,
314 /// DisplayPort Content Protection (DPCP) (`2`).
315 Dpcp,
316 /// Reserved or unrecognized value (`3`).
317 Reserved(u8),
318}
319
320impl InterfaceContentProtection {
321 /// Decodes the content protection type from a 2-bit value (bits 1:0 of byte 6).
322 pub fn from_bits(bits: u8) -> Self {
323 match bits & 0x03 {
324 0 => Self::None,
325 1 => Self::Hdcp,
326 2 => Self::Dpcp,
327 v => Self::Reserved(v),
328 }
329 }
330}
331
332/// Display interface capabilities, decoded from the Display Interface Data Block
333/// (DisplayID 1.x `0x0F`).
334///
335/// Identifies the physical interface type, link characteristics, pixel clock range,
336/// and supported content protection mechanism.
337///
338/// Stored in [`DisplayCapabilities::display_id_interface`][crate::DisplayCapabilities::display_id_interface].
339#[non_exhaustive]
340#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
341#[derive(Debug, Clone, Copy, PartialEq, Eq)]
342pub struct DisplayIdInterface {
343 /// Physical interface standard (LVDS, eDP, DisplayPort, TMDS, etc.).
344 pub interface_type: DisplayInterfaceType,
345 /// Whether spread-spectrum clocking is supported on this interface.
346 pub spread_spectrum: bool,
347 /// Number of data lanes or LVDS pairs (raw count from byte 1 bits 3:0).
348 pub num_lanes: u8,
349 /// Minimum pixel clock in units of 10 kHz (from bytes 2–3, LE uint16).
350 pub min_pixel_clock_10khz: u32,
351 /// Maximum pixel clock in units of 10 kHz (from bytes 4–5, LE uint16).
352 pub max_pixel_clock_10khz: u32,
353 /// Content protection mechanism supported on this interface.
354 pub content_protection: InterfaceContentProtection,
355}
356
357impl DisplayIdInterface {
358 /// Constructs a [`DisplayIdInterface`] from its decoded fields.
359 pub fn new(
360 interface_type: DisplayInterfaceType,
361 spread_spectrum: bool,
362 num_lanes: u8,
363 min_pixel_clock_10khz: u32,
364 max_pixel_clock_10khz: u32,
365 content_protection: InterfaceContentProtection,
366 ) -> Self {
367 Self {
368 interface_type,
369 spread_spectrum,
370 num_lanes,
371 min_pixel_clock_10khz,
372 max_pixel_clock_10khz,
373 content_protection,
374 }
375 }
376}
377
378/// Behavior when one or more tiles are missing from a tiled display, decoded from Tiled
379/// Display Topology Data Block (0x12) byte 0 bits 5:4.
380#[non_exhaustive]
381#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
383pub enum TileTopologyBehavior {
384 /// Behavior is undefined (`0`).
385 Undefined,
386 /// No image is shown until all tiles are present and operational (`1`).
387 RequireAllTiles,
388 /// The image is scaled to fit whatever tiles are currently present (`2`).
389 ScaleWhenMissing,
390 /// Reserved or unrecognized value (`3`).
391 Reserved(u8),
392}
393
394impl TileTopologyBehavior {
395 /// Decodes the topology behavior from a 2-bit value (bits 5:4 of byte 0).
396 pub fn from_bits(bits: u8) -> Self {
397 match bits & 0x03 {
398 0 => Self::Undefined,
399 1 => Self::RequireAllTiles,
400 2 => Self::ScaleWhenMissing,
401 v => Self::Reserved(v),
402 }
403 }
404}
405
406/// Bezel sizes around a single tile, decoded from the optional bezel bytes of the Tiled
407/// Display Topology Data Block (0x12) when the `has_bezel_info` flag is set.
408///
409/// Each field is the bezel width or height in pixels at the tile's native resolution.
410#[non_exhaustive]
411#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
412#[derive(Debug, Clone, Copy, PartialEq, Eq)]
413pub struct TileBezelInfo {
414 /// Top bezel height in pixels.
415 pub top_px: u8,
416 /// Bottom bezel height in pixels.
417 pub bottom_px: u8,
418 /// Right bezel width in pixels.
419 pub right_px: u8,
420 /// Left bezel width in pixels.
421 pub left_px: u8,
422}
423
424impl TileBezelInfo {
425 /// Constructs a [`TileBezelInfo`] from its decoded fields.
426 pub fn new(top_px: u8, bottom_px: u8, right_px: u8, left_px: u8) -> Self {
427 Self {
428 top_px,
429 bottom_px,
430 right_px,
431 left_px,
432 }
433 }
434}
435
436/// Tiled display topology, decoded from the Tiled Display Topology Data Block
437/// (DisplayID 1.x `0x12`).
438///
439/// A tiled display is composed of multiple physical panels (tiles) arranged in a
440/// rectangular grid. Each tile reports its own position and dimensions; the host
441/// assembles the full image across all tiles.
442///
443/// Stored in [`DisplayCapabilities::tiled_topology`][crate::DisplayCapabilities::tiled_topology].
444#[non_exhaustive]
445#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
446#[derive(Debug, Clone, Copy, PartialEq, Eq)]
447pub struct DisplayIdTiledTopology {
448 /// All tiles are housed in a single physical enclosure.
449 pub single_enclosure: bool,
450 /// How the display behaves when one or more tiles are missing.
451 pub topology_behavior: TileTopologyBehavior,
452 /// Total number of horizontal tiles in the grid (1–16).
453 pub h_tile_count: u8,
454 /// Total number of vertical tiles in the grid (1–16).
455 pub v_tile_count: u8,
456 /// Zero-based column index of this tile within the grid.
457 pub h_tile_location: u8,
458 /// Zero-based row index of this tile within the grid.
459 pub v_tile_location: u8,
460 /// Native pixel width of this tile.
461 pub tile_width_px: u16,
462 /// Native pixel height of this tile.
463 pub tile_height_px: u16,
464 /// Per-edge bezel sizes, present when the block's `has_bezel_info` flag is set.
465 pub bezel: Option<TileBezelInfo>,
466}
467
468impl DisplayIdTiledTopology {
469 /// Constructs a [`DisplayIdTiledTopology`] from its decoded fields.
470 #[allow(clippy::too_many_arguments)]
471 pub fn new(
472 single_enclosure: bool,
473 topology_behavior: TileTopologyBehavior,
474 h_tile_count: u8,
475 v_tile_count: u8,
476 h_tile_location: u8,
477 v_tile_location: u8,
478 tile_width_px: u16,
479 tile_height_px: u16,
480 bezel: Option<TileBezelInfo>,
481 ) -> Self {
482 Self {
483 single_enclosure,
484 topology_behavior,
485 h_tile_count,
486 v_tile_count,
487 h_tile_location,
488 v_tile_location,
489 tile_width_px,
490 tile_height_px,
491 bezel,
492 }
493 }
494}
495
496/// Stereo content format, decoded from Stereo Display Interface Data Block (0x10) byte 0
497/// bits 3:0.
498///
499/// Describes how left-eye and right-eye images are encoded in the video signal.
500#[non_exhaustive]
501#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
502#[derive(Debug, Clone, Copy, PartialEq, Eq)]
503pub enum StereoViewingMode {
504 /// Field sequential — left and right frames alternate at double frame rate (`0`).
505 ///
506 /// Requires an external sync signal to the glasses. The polarity of that signal
507 /// is encoded in [`DisplayIdStereoInterface::sync_polarity_positive`].
508 FieldSequential,
509 /// Side-by-side — left and right images packed horizontally at half width each (`1`).
510 SideBySide,
511 /// Top-and-bottom — left and right images packed vertically at half height each (`2`).
512 TopAndBottom,
513 /// Row interleaved — odd display rows carry the left eye, even rows the right eye (`3`).
514 RowInterleaved,
515 /// Column interleaved — odd display columns carry the left eye, even columns the right (`4`).
516 ColumnInterleaved,
517 /// Pixel interleaved / checkerboard — left and right pixels alternate in a
518 /// checkerboard pattern (`5`).
519 PixelInterleaved,
520 /// Reserved or unrecognized value (`6`–`15`).
521 Reserved(u8),
522}
523
524impl StereoViewingMode {
525 /// Decodes the stereo viewing mode from the lower 4 bits of byte 0.
526 pub fn from_nibble(nibble: u8) -> Self {
527 match nibble & 0x0F {
528 0 => Self::FieldSequential,
529 1 => Self::SideBySide,
530 2 => Self::TopAndBottom,
531 3 => Self::RowInterleaved,
532 4 => Self::ColumnInterleaved,
533 5 => Self::PixelInterleaved,
534 v => Self::Reserved(v),
535 }
536 }
537}
538
539/// Physical interface used to deliver stereo synchronization to the glasses, decoded from
540/// Stereo Display Interface Data Block (0x10) byte 1.
541#[non_exhaustive]
542#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
543#[derive(Debug, Clone, Copy, PartialEq, Eq)]
544pub enum StereoSyncInterface {
545 /// Sync delivered via the display's own video connector — no dedicated stereo port (`0`).
546 DisplayConnector,
547 /// VESA 3-pin DIN stereo connector (`1`).
548 VesaDin,
549 /// Infrared (IR) wireless sync (`2`).
550 Infrared,
551 /// Radio frequency (RF) wireless sync (`3`).
552 RadioFrequency,
553 /// Reserved or unrecognized value (`4`–`255`).
554 Reserved(u8),
555}
556
557impl StereoSyncInterface {
558 /// Decodes the stereo sync interface from the raw byte 1 value.
559 pub fn from_byte(byte: u8) -> Self {
560 match byte {
561 0 => Self::DisplayConnector,
562 1 => Self::VesaDin,
563 2 => Self::Infrared,
564 3 => Self::RadioFrequency,
565 v => Self::Reserved(v),
566 }
567 }
568}
569
570/// Stereo display interface parameters, decoded from the Stereo Display Interface Data Block
571/// (DisplayID 1.x `0x10`).
572///
573/// Describes how stereoscopic 3D content is encoded and how synchronization is delivered
574/// to active-shutter glasses.
575///
576/// Stored in [`DisplayCapabilities::stereo_interface`][crate::DisplayCapabilities::stereo_interface].
577#[non_exhaustive]
578#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
579#[derive(Debug, Clone, Copy, PartialEq, Eq)]
580pub struct DisplayIdStereoInterface {
581 /// How left-eye and right-eye images are encoded in the video signal.
582 pub viewing_mode: StereoViewingMode,
583 /// Polarity of the 3D sync signal sent to the glasses.
584 ///
585 /// `true` = positive (glasses open left eye on high); `false` = negative.
586 /// Only meaningful for [`StereoViewingMode::FieldSequential`].
587 pub sync_polarity_positive: bool,
588 /// Physical channel used to deliver the sync signal to the glasses.
589 pub sync_interface: StereoSyncInterface,
590}
591
592impl DisplayIdStereoInterface {
593 /// Constructs a [`DisplayIdStereoInterface`] from its decoded fields.
594 pub fn new(
595 viewing_mode: StereoViewingMode,
596 sync_polarity_positive: bool,
597 sync_interface: StereoSyncInterface,
598 ) -> Self {
599 Self {
600 viewing_mode,
601 sync_polarity_positive,
602 sync_interface,
603 }
604 }
605}
606
607/// Panel interface power sequencing timing parameters, decoded from the Interface Power
608/// Sequencing Block (DisplayID 1.x `0x0D`).
609///
610/// Describes the minimum delays required when powering the display panel on and off.
611/// All fields are raw counts in **2 ms units** per the DisplayID 1.x §4.11 specification;
612/// multiply by 2 to obtain milliseconds.
613///
614/// The six parameters (T1–T6) follow the standard LVDS/eDP power sequencing model:
615///
616/// ```text
617/// Power-on: [VCC on] →T1→ [Signal on] →T2→ [Backlight on]
618/// Power-off: [Backlight off] →T3→ [Signal off] →T4→ [VCC off]
619/// Minimum off time: T5 (VCC), T6 (Backlight)
620/// ```
621#[non_exhaustive]
622#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
623#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
624pub struct PowerSequencing {
625 /// T1: minimum delay from power supply enable to interface signal valid (2 ms units).
626 pub t1_power_to_signal: u8,
627 /// T2: minimum delay from interface signal enable to backlight enable (2 ms units).
628 pub t2_signal_to_backlight: u8,
629 /// T3: minimum delay from backlight disable to interface signal disable (2 ms units).
630 pub t3_backlight_to_signal_off: u8,
631 /// T4: minimum delay from interface signal disable to power supply disable (2 ms units).
632 pub t4_signal_to_power_off: u8,
633 /// T5: minimum power supply off time before power can be re-applied (2 ms units).
634 pub t5_power_off_min: u8,
635 /// T6: minimum backlight off time (2 ms units).
636 pub t6_backlight_off_min: u8,
637}
638
639impl PowerSequencing {
640 /// Constructs a [`PowerSequencing`] from its decoded T1–T6 timing fields.
641 pub fn new(
642 t1_power_to_signal: u8,
643 t2_signal_to_backlight: u8,
644 t3_backlight_to_signal_off: u8,
645 t4_signal_to_power_off: u8,
646 t5_power_off_min: u8,
647 t6_backlight_off_min: u8,
648 ) -> Self {
649 Self {
650 t1_power_to_signal,
651 t2_signal_to_backlight,
652 t3_backlight_to_signal_off,
653 t4_signal_to_power_off,
654 t5_power_off_min,
655 t6_backlight_off_min,
656 }
657 }
658}