1use crate::{
2 command::{WriteCommand, no_param_command},
3 instr::Instr,
4};
5
6no_param_command!(
7 Nop => NOP
9);
10no_param_command!(
11 SoftReset => SWRESET
14);
15no_param_command!(
16 SleepIn => SLPIN
19);
20no_param_command!(
21 SleepOut => SLPOUT
24);
25no_param_command!(
26 PartialOn => PTLON
28);
29no_param_command!(
30 PartialOff => PTLOFF
32);
33no_param_command!(
34 DisplayInversionOff => INVOFF
36);
37no_param_command!(
38 DisplayInversionOn => INVON
40);
41no_param_command!(
42 DisplayOff => DISPOFF
44);
45no_param_command!(
46 DisplayOn => DISPON
48);
49no_param_command!(
50 TearingEffectLineOff => TEOFF
52);
53no_param_command!(
54 HighPowerModeOn => HPM
58);
59no_param_command!(
60 LowPowerModeOn => LPM
63);
64
65#[derive(Clone, Copy, Debug, PartialEq, Eq)]
71pub struct ColumnAddressSet {
72 xs: u8,
73 xe: u8,
74}
75
76impl ColumnAddressSet {
77 pub const DEFAULT: Self = Self { xs: 0, xe: 0 };
79
80 pub const fn new(xs: u8, xe: u8) -> Self {
86 assert!(xs <= xe, "X start must be less or equal than X end");
87 assert!(xe < 64, "X end out of range");
88 Self { xs, xe }
89 }
90}
91
92impl Default for ColumnAddressSet {
93 fn default() -> Self {
94 Self::DEFAULT
95 }
96}
97
98impl WriteCommand for ColumnAddressSet {
99 const OPCODE: Instr = Instr::CASET;
100 type Params = [u8; 2];
101 fn params(&self) -> Self::Params {
102 [self.xs, self.xe]
103 }
104}
105
106#[derive(Clone, Copy, Debug, PartialEq, Eq)]
114pub struct RowAddressSet {
115 ys: u8,
116 ye: u8,
117}
118
119impl RowAddressSet {
120 pub const DEFAULT: Self = Self { ys: 0, ye: 0 };
122
123 pub const fn new(ys: u8, ye: u8) -> Self {
129 assert!(ys <= ye, "Y start must be less or equal than Y end");
130 Self { ys, ye }
131 }
132}
133
134impl Default for RowAddressSet {
135 fn default() -> Self {
136 Self::DEFAULT
137 }
138}
139
140impl WriteCommand for RowAddressSet {
141 const OPCODE: Instr = Instr::RASET;
142 type Params = [u8; 2];
143 fn params(&self) -> Self::Params {
144 [self.ys, self.ye]
145 }
146}
147
148#[derive(Clone, Copy, Debug, PartialEq, Eq)]
151pub struct TearingEffectLineOn {
152 tem: TearingEffectMode,
154}
155
156impl TearingEffectLineOn {
157 pub const DEFAULT: Self = Self {
159 tem: TearingEffectMode::VBlanking,
160 };
161
162 pub const fn new(tem: TearingEffectMode) -> Self {
164 Self { tem }
165 }
166
167 const fn bytes(&self) -> [u8; 1] {
168 [self.tem as u8]
169 }
170}
171
172impl Default for TearingEffectLineOn {
173 fn default() -> Self {
174 Self::DEFAULT
175 }
176}
177
178impl WriteCommand for TearingEffectLineOn {
179 const OPCODE: Instr = Instr::TEON;
180 type Params = [u8; 1];
181 fn params(&self) -> Self::Params {
182 self.bytes()
183 }
184}
185
186#[derive(Clone, Copy, Debug, PartialEq, Eq)]
188pub enum TearingEffectMode {
189 VBlanking = 0,
191 Both = 1,
193}
194
195const _: () = assert!(matches!(TearingEffectLineOn::DEFAULT.bytes(), [0x00]));
196
197#[derive(Clone, Copy, Debug, PartialEq, Eq)]
204pub struct MemoryDataAccessControl {
205 my: PageAddressOrder,
207 mx: ColumnAddressOrder,
209 mv: PageOrColumnOrder,
211 gs: GateScanOrder,
214}
215
216impl MemoryDataAccessControl {
217 pub const DEFAULT: Self = Self {
220 my: PageAddressOrder::TopToBottom,
221 mx: ColumnAddressOrder::LeftToRight,
222 mv: PageOrColumnOrder::ColumnDirectionMode,
223 gs: GateScanOrder::TopToBottom,
224 };
225
226 #[must_use]
228 pub const fn with_page_order(mut self, v: PageAddressOrder) -> Self {
229 self.my = v;
230 self
231 }
232
233 #[must_use]
235 pub const fn with_column_order(mut self, v: ColumnAddressOrder) -> Self {
236 self.mx = v;
237 self
238 }
239
240 #[must_use]
242 pub const fn with_page_or_column_order(mut self, v: PageOrColumnOrder) -> Self {
243 self.mv = v;
244 self
245 }
246
247 #[must_use]
249 pub const fn with_gate_scan_order(mut self, v: GateScanOrder) -> Self {
250 self.gs = v;
251 self
252 }
253}
254
255impl Default for MemoryDataAccessControl {
256 fn default() -> Self {
257 Self::DEFAULT
258 }
259}
260
261impl WriteCommand for MemoryDataAccessControl {
262 const OPCODE: Instr = Instr::MADCTL;
263 type Params = [u8; 1];
264 fn params(&self) -> Self::Params {
265 let byte = (self.my as u8) << 7
266 | (self.mx as u8) << 6
267 | (self.mv as u8) << 5
268 | (self.mx as u8) << 3
269 | (self.gs as u8) << 2;
270 [byte]
271 }
272}
273
274#[derive(Clone, Copy, Debug, PartialEq, Eq)]
276pub enum PageAddressOrder {
277 TopToBottom = 0,
279 BottomToTop = 1,
281}
282
283#[derive(Clone, Copy, Debug, PartialEq, Eq)]
285pub enum ColumnAddressOrder {
286 LeftToRight = 0,
288 RightToLeft = 1,
290}
291
292#[derive(Clone, Copy, Debug, PartialEq, Eq)]
294pub enum PageOrColumnOrder {
295 ColumnDirectionMode = 0,
297 PageDirectionMode = 1,
299}
300
301#[derive(Clone, Copy, Debug, PartialEq, Eq)]
303pub enum GateScanOrder {
304 TopToBottom = 0,
306 BottomToTop = 1,
308}
309
310#[derive(Clone, Copy, Debug, PartialEq, Eq)]
313pub struct VerticalScrollStartAddressOfRam {
314 vsp: u16, }
316
317impl VerticalScrollStartAddressOfRam {
318 pub const DEFAULT: Self = Self { vsp: 0 };
320
321 pub const fn new(vsp: u16) -> Self {
327 assert!(vsp >> 9 == 0, "VSP out of range");
328 Self { vsp }
329 }
330}
331
332impl Default for VerticalScrollStartAddressOfRam {
333 fn default() -> Self {
334 Self::DEFAULT
335 }
336}
337
338impl WriteCommand for VerticalScrollStartAddressOfRam {
339 const OPCODE: Instr = Instr::VSCSAD;
340 type Params = [u8; 2];
341 fn params(&self) -> Self::Params {
342 [(self.vsp >> 8) as u8, self.vsp as u8]
343 }
344}
345
346#[derive(Clone, Copy, Debug, PartialEq, Eq)]
348pub struct DataFormatSelect {
349 xde: DataUpDownSwitch,
350 bps: BytesPerPixelSelect,
351}
352
353impl DataFormatSelect {
354 pub const DEFAULT: Self = Self {
356 xde: DataUpDownSwitch::On,
357 bps: BytesPerPixelSelect::FourWriteOps,
358 };
359
360 #[must_use]
362 pub const fn with_data_up_down_switch(mut self, p: DataUpDownSwitch) -> Self {
363 self.xde = p;
364 self
365 }
366
367 #[must_use]
369 pub const fn with_bytes_per_pixel(mut self, p: BytesPerPixelSelect) -> Self {
370 self.bps = p;
371 self
372 }
373
374 const fn bytes(&self) -> [u8; 1] {
375 [(self.xde as u8) << 4 | self.bps as u8]
376 }
377}
378
379impl Default for DataFormatSelect {
380 fn default() -> Self {
381 Self::DEFAULT
382 }
383}
384
385impl WriteCommand for DataFormatSelect {
386 const OPCODE: Instr = Instr::DTFORM;
387 type Params = [u8; 1];
388 fn params(&self) -> Self::Params {
389 self.bytes()
390 }
391}
392
393#[derive(Clone, Copy, Debug, PartialEq, Eq)]
395pub enum DataUpDownSwitch {
396 On = 0,
398 Off = 1,
400}
401
402#[derive(Clone, Copy, Debug, PartialEq, Eq)]
404pub enum BytesPerPixelSelect {
405 FourWriteOps = 0,
407 ThreeWriteOps = 1,
409}
410
411const _: () = assert!(matches!(DataFormatSelect::DEFAULT.bytes(), [0x00]));
412
413#[derive(Clone, Copy, Debug, PartialEq, Eq)]
417pub struct SetTearScanline {
418 n: u16, }
420
421impl SetTearScanline {
422 pub const DEFAULT: Self = Self { n: 0 };
424
425 pub const fn new(n: u16) -> Self {
431 assert!(n >> 9 == 0, "N out of range");
432 Self { n }
433 }
434}
435
436impl Default for SetTearScanline {
437 fn default() -> Self {
438 Self::DEFAULT
439 }
440}
441
442impl WriteCommand for SetTearScanline {
443 const OPCODE: Instr = Instr::TESCAN;
444 type Params = [u8; 2];
445 fn params(&self) -> Self::Params {
446 [(self.n >> 8) as u8, self.n as u8]
447 }
448}