Skip to main content

display_types/cea861/
vtdb.rs

1use crate::VideoMode;
2#[cfg(any(feature = "alloc", feature = "std"))]
3use crate::prelude::Vec;
4
5/// A decoded DisplayID Type VII Video Timing Data Block (T7VTDB, extended tag `0x22`).
6///
7/// Each CTA T7VTDB carries exactly one 20-byte DisplayID-style timing descriptor.
8/// Unlike an 18-byte EDID DTD, the pixel clock is expressed in kHz (not 10 kHz units)
9/// and all horizontal/vertical fields are 16-bit rather than packed.
10///
11/// Multiple T7VTDBs are permitted per CTA extension block (one timing per block).
12/// Per CTA-861, `interlaced` shall always be `false`; `y420` reflects the T7Y420 flag.
13#[non_exhaustive]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[derive(Debug, Clone, PartialEq)]
16pub struct T7VtdbBlock {
17    /// Block revision (`Block_Rev` field, bits 2:0 of the descriptor header byte).
18    /// CTA-861 expects revision `0x02`.
19    pub version: u8,
20    /// Decoded video timing for this descriptor.
21    pub mode: VideoMode,
22    /// When `true`, this timing also supports YCbCr 4:2:0 sampling (T7Y420 flag).
23    pub y420: bool,
24}
25
26impl T7VtdbBlock {
27    /// Constructs a `T7VtdbBlock`.
28    pub fn new(version: u8, mode: VideoMode, y420: bool) -> Self {
29        Self {
30            version,
31            mode,
32            y420,
33        }
34    }
35}
36
37/// A decoded DisplayID Type VIII Video Timing Data Block (T8VTDB, extended tag `0x23`).
38///
39/// Contains a list of VESA DMT (Display Monitor Timings) ID codes referencing
40/// standardised monitor timings. Only `Code_Type = 0x00` (DMT) is defined by
41/// CTA-861; other code types are returned as `None` by the parser.
42///
43/// Codes whose DMT IDs are not in the standard table are stored in `codes` but
44/// omitted from `timings`.
45#[non_exhaustive]
46#[cfg(any(feature = "alloc", feature = "std"))]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48#[derive(Debug, Clone, PartialEq)]
49pub struct T8VtdbBlock {
50    /// Block revision (`Block_Rev` field, bits 2:0).
51    pub version: u8,
52    /// When `true`, all timings also support YCbCr 4:2:0 sampling (T8Y420 flag).
53    pub y420: bool,
54    /// Raw DMT timing codes as they appear in the block (1-byte or 2-byte each).
55    pub codes: Vec<u16>,
56    /// `VideoMode` values resolved from the DMT codes. Entries for unrecognised
57    /// or reserved DMT IDs are omitted.
58    pub timings: Vec<VideoMode>,
59}
60
61#[cfg(any(feature = "alloc", feature = "std"))]
62impl T8VtdbBlock {
63    /// Constructs a `T8VtdbBlock`.
64    pub fn new(version: u8, y420: bool, codes: Vec<u16>, timings: Vec<VideoMode>) -> Self {
65        Self {
66            version,
67            y420,
68            codes,
69            timings,
70        }
71    }
72}
73
74/// A single timing entry from a T10VTDB block.
75///
76/// Type X timings use a CVT formula to derive the full signal, but only the
77/// display-facing parameters (resolution and refresh rate) are exposed here.
78#[non_exhaustive]
79#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct T10VtdbEntry {
82    /// Horizontal active pixels.
83    pub width: u16,
84    /// Vertical active lines.
85    pub height: u16,
86    /// Vertical refresh rate in Hz (1–1024).
87    ///
88    /// Values above 255 are only possible when the block uses 7- or 8-byte
89    /// descriptors (M ≥ 1 in the `rev` byte).
90    pub refresh_hz: u16,
91    /// When `true`, this timing also supports YCbCr 4:2:0 sampling (YCC420 flag).
92    pub y420: bool,
93}
94
95impl T10VtdbEntry {
96    /// Constructs a `T10VtdbEntry`.
97    pub fn new(width: u16, height: u16, refresh_hz: u16, y420: bool) -> Self {
98        Self {
99            width,
100            height,
101            refresh_hz,
102            y420,
103        }
104    }
105}
106
107/// A decoded DisplayID Type X Video Timing Data Block (T10VTDB, extended tag `0x2A`).
108///
109/// Type X timings are CVT formula-based: each descriptor encodes the active
110/// resolution and refresh rate directly, with blanking derived by the display.
111/// A block may contain 1–4 descriptors (limited by the 30-byte CTA extended
112/// block payload cap).
113#[non_exhaustive]
114#[cfg(any(feature = "alloc", feature = "std"))]
115#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct T10VtdbBlock {
118    /// Decoded timing entries. Each entry corresponds to one descriptor in the block.
119    pub entries: Vec<T10VtdbEntry>,
120}
121
122#[cfg(any(feature = "alloc", feature = "std"))]
123impl T10VtdbBlock {
124    /// Constructs a `T10VtdbBlock`.
125    pub fn new(entries: Vec<T10VtdbEntry>) -> Self {
126        Self { entries }
127    }
128}
129
130/// Decoded VESA Video Timing Block Extension (extended tag `0x03`).
131///
132/// Carries additional video timing modes beyond what fits in the base EDID block.
133/// Each block may contain Detailed Timing Descriptors (DTBs), Coordinated Video
134/// Timings (CVTs), and Standard Timing (ST) entries, per the VESA VTB-EXT Standard,
135/// Release A.
136#[non_exhaustive]
137#[cfg(any(feature = "alloc", feature = "std"))]
138#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
139#[derive(Debug, Clone, PartialEq)]
140pub struct VtbExtBlock {
141    /// VTB-EXT version byte (expected `0x01`).
142    pub version: u8,
143    /// All video modes decoded from this block (DTBs, CVTs, and STs combined).
144    pub timings: Vec<VideoMode>,
145}
146
147#[cfg(any(feature = "alloc", feature = "std"))]
148impl VtbExtBlock {
149    /// Constructs a `VtbExtBlock`.
150    pub fn new(version: u8, timings: Vec<VideoMode>) -> Self {
151        Self { version, timings }
152    }
153}