1use anyhow::{bail, Result};
5
6pub const LEN: usize = panelspec::RECORD01_LEN;
8
9pub mod off {
11 pub const MODULE_W: usize = 0x000;
12 pub const MODULE_H_HALF: usize = 0x001;
13 pub const GAMMA: usize = 0x01C;
14 pub const SCAN: usize = 0x020;
15 pub const SERIAL_CLOCK: usize = 0x021;
16 pub const GRAY: usize = 0x023;
17 pub const LUMINANCE: usize = 0x024;
18 pub const LUMINANCE_LEVEL: usize = 0x026;
19 pub const PACK_HEAD3: usize = 0x028;
21 pub const COLOR_SWAP: usize = 0x02B;
22 pub const COLOR_SOURCE: usize = 0x02C;
23 pub const GCLOCK: usize = 0x031;
24 pub const GAINS: usize = 0x032;
25 pub const CHIP_LO: usize = 0x036;
26 pub const LINE_DIR: usize = 0x03C;
27 pub const SPLIT: usize = 0x03E;
28 pub const DATA_GROUPS: usize = 0x044;
29 pub const SERIAL_CLOCK_HALF: usize = 0x049;
30 pub const SERIAL_CLOCK_DUP: usize = 0x04B;
31 pub const OE_8NS: usize = 0x050;
33 pub const GRID_W_LO: usize = 0x057;
34 pub const GRID_H_LO: usize = 0x058;
35 pub const HR_STYLE: usize = 0x059;
36 pub const CHIP_CUSTOM: usize = 0x06A;
37 pub const REFRESH: usize = 0x0AA;
38 pub const MIN_OE: usize = 0x0AE;
39 pub const HR_SCAN_STYLE: usize = 0x0B2;
40 pub const CURRENT_PCT: usize = 0x0B4;
41 pub const MAX_W: usize = 0x0C0;
42 pub const MAX_H: usize = 0x0C2;
43 pub const SEGMENTS_MINUS_1: usize = 0x0E5;
44 pub const SUB_CHIP_LO: usize = 0x0E9;
46 pub const SUB_CHIP_HI: usize = 0x205;
47 pub const SWAP_RAMP: usize = 0x19A;
48 pub const CHIP_HI: usize = 0x204;
49 pub const GRID_W_HI: usize = 0x24E;
50 pub const GRID_H_HI: usize = 0x24F;
51}
52
53#[derive(Clone, Copy)]
55pub struct View<'a>(&'a [u8]);
56
57impl<'a> View<'a> {
58 pub fn new(payload: &'a [u8]) -> Result<Self> {
61 if payload.len() < LEN {
62 bail!("record 0x01 payload is {} bytes, need {LEN}", payload.len());
63 }
64 Ok(Self(payload))
65 }
66
67 #[must_use]
68 pub fn bytes(&self) -> &'a [u8] {
69 self.0
70 }
71 #[must_use]
72 pub fn u8(&self, at: usize) -> u8 {
73 self.0[at]
74 }
75 #[must_use]
76 pub fn u16_le(&self, at: usize) -> u16 {
77 u16::from_le_bytes([self.0[at], self.0[at + 1]])
78 }
79 #[must_use]
80 pub fn f32_le(&self, at: usize) -> f32 {
81 f32::from_le_bytes([self.0[at], self.0[at + 1], self.0[at + 2], self.0[at + 3]])
82 }
83
84 #[must_use]
85 pub fn module_width(&self) -> u16 {
86 u16::from(self.u8(off::MODULE_W))
87 }
88 #[must_use]
90 pub fn module_height_stored(&self) -> u16 {
91 u16::from(self.u8(off::MODULE_H_HALF))
92 }
93 #[must_use]
94 pub fn scan(&self) -> u8 {
95 self.u8(off::SCAN)
96 }
97 #[must_use]
98 pub fn serial_clock(&self) -> u16 {
99 self.u16_le(off::SERIAL_CLOCK)
100 }
101 #[must_use]
102 pub fn gray(&self) -> u8 {
103 self.u8(off::GRAY)
104 }
105 #[must_use]
106 pub fn luminance_level(&self) -> u16 {
107 self.u16_le(off::LUMINANCE_LEVEL)
108 }
109 #[must_use]
110 pub fn max_width(&self) -> u16 {
111 self.u16_le(off::MAX_W)
112 }
113 #[must_use]
114 pub fn max_height(&self) -> u16 {
115 self.u16_le(off::MAX_H)
116 }
117 #[must_use]
120 pub fn grid(&self) -> (u16, u16) {
121 (
122 u16::from_le_bytes([self.u8(off::GRID_W_LO), self.u8(off::GRID_W_HI)]),
123 u16::from_le_bytes([self.u8(off::GRID_H_LO), self.u8(off::GRID_H_HI)]),
124 )
125 }
126 #[must_use]
128 pub fn line_dir(&self) -> u8 {
129 self.u8(off::LINE_DIR)
130 }
131 #[must_use]
133 pub fn split_segment(&self) -> u8 {
134 let c = self.u8(off::SPLIT);
135 if c & 4 != 0 {
136 4
137 } else if c & 1 == 0 {
138 1
139 } else if c < 8 {
140 2
141 } else {
142 c >> 3
143 }
144 }
145 #[must_use]
147 pub fn segments(&self) -> u32 {
148 u32::from(self.u8(off::SEGMENTS_MINUS_1)) + 1
149 }
150 #[must_use]
151 pub fn min_oe(&self) -> f32 {
152 self.f32_le(off::MIN_OE)
153 }
154 #[must_use]
156 pub fn hr_style(&self) -> u8 {
157 self.u8(off::HR_STYLE) & !0x20
158 }
159 #[must_use]
160 pub fn hr_scan_style(&self) -> u8 {
161 self.u8(off::HR_SCAN_STYLE)
162 }
163 #[must_use]
164 pub fn swap_ramp(&self) -> &'a [u8] {
165 &self.0[off::SWAP_RAMP..off::SWAP_RAMP + 64]
166 }
167 #[must_use]
168 pub fn chip_custom(&self) -> &'a [u8] {
169 &self.0[off::CHIP_CUSTOM..off::CHIP_CUSTOM + 16]
170 }
171 #[must_use]
172 pub fn chip_id(&self) -> u16 {
173 u16::from(self.u8(off::CHIP_HI)) << 8 | u16::from(self.u8(off::CHIP_LO))
174 }
175}