gc9a01/
command.rs

1#![allow(clippy::doc_markdown)]
2#![allow(clippy::match_same_arms)]
3//! Commands
4
5use display_interface::{DataFormat::U8, DisplayError, WriteOnlyDataCommand};
6
7/// GC9A01 Commands
8#[derive(Debug, Copy, Clone)]
9pub enum Command {
10    /// Set Sleep mode (10h/11h)
11    ///
12    /// This command turns on/off sleep mode.
13    ///
14    /// ## Description
15    ///
16    /// This command causes the LCD module to enter the minimum power consumption mode.
17    /// In this mode e.g. the DC/DC converter is stopped, Internal oscillator is stopped, and panel scanning is stopped
18    ///
19    /// ## Restriction
20    ///
21    /// ## On Logical On (10h)
22    ///
23    /// It will be necessary to wait 5msec before sending next to command,
24    /// this is to allow time for the supply voltages and clock circuits to
25    /// stabilize.
26    ///
27    /// ## On Logical Off (11h)
28    ///
29    /// It will be necessary to wait 120msec after sending Sleep Out command (when in
30    /// Sleep In Mode) before Sleep In command can be sent.
31    ///
32    SleepMode(Logical),
33
34    /// Set Partial mode (12h)
35    ///
36    /// This command turns on Partial mode.
37    ///
38    /// ## Description
39    ///
40    /// This command turns on partial mode. The Partial mode window is described by the Partial
41    /// Area command (30h). To leave Partial mode, the Normal Display Mode On command (13h) should be written.
42    ///
43    /// ## Restriction
44    ///
45    /// This command has no effect when Partial mode is active.
46    ///
47    PartialMode,
48
49    /// Set Normal Display mode (13h)
50    ///
51    /// This command turns on Normal Display mode.
52    ///
53    /// ## Description
54    ///
55    /// Normal display mode on means Partial mode off.
56    /// Exit from NORON by the Partial mode On command (12h)
57    ///
58    /// ## Restriction
59    ///
60    /// This command has no effect when Normal Display mode is active.
61    ///
62    NormalDisplayMode,
63
64    /// Set Display Inversion (20h/21h)
65    ///
66    /// This command turns on/off Display Inversion
67    ///
68    /// ## Description
69    ///
70    /// This command is used to recover from display inversion mode.
71    /// This command makes no change of the content of frame memory.
72    /// This command doesn't change any other status.
73    ///
74    /// ## Restriction
75    ///
76    /// This command has no effect when module already is inversion OFF mode.
77    ///
78    DisplayInversion(Logical),
79
80    /// Set Display State (28h/29h)
81    ///
82    /// This command turns on/off Display
83    ///
84    /// ## Description
85    ///
86    /// In this mode, the output from Frame Memory is disabled and blank page inserted.
87    ///
88    /// ## Restriction
89    ///
90    /// This command has no effect when module is already in display OFF mode.
91    ///
92    DisplayState(Logical),
93
94    /// Set Column Address (start, end) (2Ah)
95    ///
96    /// ## Parameters
97    ///
98    ///  * SC `.0` => Start Column
99    /// * EC `.1` => End Column
100    ///
101    /// This command is used to defined area of frame memory where MCU can access.
102    ///
103    /// ## Description
104    ///
105    /// This command makes no change on the other driver status.
106    /// The values of SC [15:0] and EC [15:0] are referred when RAMWR command comes.
107    /// Each value represents one column line in the frame memory.
108    ///
109    /// ## Restriction
110    ///
111    /// SC [15:0] always must be equal to or less than EC [15:0].
112    ///
113    /// __NOTE__: When SC [15:0] or EC [15:0] is greater than 013Fh (When MADCTL's B5 = 0)
114    /// or 00EFh (When MADCTL's B5 = 1), data of out of range will be ignored.
115    ///
116    ColumnAddressSet(u16, u16),
117
118    /// Set Row Address (start, end) (2Bh)
119    ///
120    /// ## Parameters
121    ///
122    ///  * SP `.0` => Start Page/Row
123    /// * EP `.1` => End Page/Row
124    ///
125    /// This command is used to define area of frame memory where MCU can access.
126    ///
127    /// ## Description
128    ///
129    /// This command makes no change on the other driver status.
130    /// The values of SP [15:0] and EP [15:0] are referred when RAMWR command comes.
131    /// Each value represents one Page line in the Frame Memory
132    ///
133    /// ## Restriction
134    ///
135    /// SP [15:0] always must be equal to or less than EP [15:0]
136    ///
137    /// __NOTE__:When SP [15:0] or EP [15:0] is greater than 00EFh (When MADCTL’s B5 = 0)
138    /// or 013Fh (When MADCTL’s B5 = 1), data of out of range will be ignored.
139    ///
140    RowAddressSet(u16, u16),
141    // Partial Area (start, end) (30)
142    // TODO:>
143    // TODO: PartialArea(u16, u16),
144    //
145    /// Vertical Scrolling Definition (33h)
146    ///
147    /// ## Parameters
148    ///
149    /// * TFA `.0` => Top Fixed Area
150    /// * VSA `.1` => Vertical Scrolling Area
151    ///
152    /// This command is used to define area of frame memory where MCU can access.
153    ///
154    /// ## Description
155    ///
156    /// This command defines the Vertical Scrolling Area of the display.
157    ///
158    /// ## When MADCTL B4=0
159    ///
160    /// The 1st & 2nd parameter TFA [15...0] describes the Top Fixed Area (in No. of lines from
161    /// Top of the Frame Memory and Display).
162    /// The 3rd & 4th parameter VSA [15...0] describes the height of the Vertical Scrolling Area
163    /// (in No. of lines of the Frame Memory [not the display]
164    /// from the Vertical Scrolling Start Address).
165    /// The first line read from Frame Memory appears immediately after the bottom most line of the Top Fixed Area.
166    ///
167    /// ## When MADCTL B4=1
168    ///
169    /// The 1st & 2nd parameter TFA [15...0] describes the Top Fixed Area (in No. of lines from
170    /// Bottom of the Frame Memory and Display).
171    /// The 3rd & 4th parameter VSA [15...0] describes the height of the Vertical Scrolling Area
172    /// (in No. of lines of the Frame
173    /// Memory [not the display] from the Vertical Scrolling Start Address). The first line read
174    /// from Frame Memory appears
175    /// immediately after the top most line of the Top Fixed Area
176    ///
177    VertialScrollDef(u16, u16),
178
179    /// Tearing Effect Line OFF (35h)
180    /// Tearing Effect Line OFF (34h)
181    ///
182    /// This command turns on tearing effect line with a parameters.
183    ///
184    /// ## Parameters
185    ///
186    /// * M `.0` => Mode (Logical)
187    ///
188    /// ## Description
189    ///
190    /// This command is used to turn ON the Tearing Effect output signal from the TE signal line.
191    /// This output is not affected by changing MADCTL bit B4. The Tearing Effect Line On has one parameter which describes
192    /// the mode of the Tearing Effect Output Line.
193    ///
194    /// This command is used to turn OFF
195    /// (Active Low) the Tearing Effect output signal from the TE signal line.
196    ///
197    ///
198    /// ## Restriction
199    ///
200    /// This command has no effect when Tearing Effect output is already ON
201    ///
202    TearingEffectLine(Logical),
203
204    /// Memory Access Control (36h)
205    ///
206    /// This command defines read/write scanning direction of frame memory.
207    /// This command makes no change on the other driver status
208    /// ## Parameters
209    ///
210    /// * MY Row Address Order
211    /// * MX Column Address Order These 3 bits control MCU to memory write/read direction.
212    /// * MV Row / Column Exchange
213    /// * ML Vertical Refresh Order LCD vertical refresh direction control.
214    /// * BGR RGB-BGR Order
215    /// * Color selector switch control (0=RGB color filter panel, 1=BGR color filter panel)
216    /// * MH Horizontal Refresh ORDER LCD horizontal refreshing direction control.
217    ///
218    /// ## Description
219    ///
220    /// Note: When BGR bit is changed, the new setting is active immediately without update the content in
221    /// Frame Memory again.
222    ///
223    /// ## Restriction
224    ///
225    /// This command has no effect when Tearing Effect output is already ON
226    ///
227    MemoryAccessControl(Logical, Logical, Logical, Logical, Logical, Logical),
228
229    /// Vertical Scrolling Start Address (37h)
230    ///
231    /// ## Parameters
232    /// * VSP `.0` => Vertical Start Page
233    ///
234    /// ## Description
235    ///
236    /// This command is used together with Vertical Scrolling Definition (33h). These two commands
237    /// describe the scrolling area and the scrolling mode.
238    ///
239    /// The Vertical Scrolling Start Address command has one parameter
240    /// which describes the address of the line in the Frame Memory that will be written as the first line after
241    /// the last line of the Top Fixed Area (TFA) on the display.
242    ///
243    /// ## Restriction
244    ///
245    /// This command has no effect when Tearing Effect output is already ON.
246    ///
247    VerticalScrollStartAddresss(u16),
248
249    /// Set Idle Mode (38h/39h)
250    ///
251    /// This command turns on/off Idle Mode
252    ///
253    /// ## Parameters
254    /// * State `.0` => On/Off
255    ///
256    /// ## Description
257    ///
258    /// In the idle off mode, LCD can display maximum 262,144 colors.
259    ///
260    /// ## Restriction
261    ///
262    /// This command has no effect when module is already in idle same mode.
263    ///
264    IdleMode(Logical),
265
266    /// Pixel Format Set (3Ah) COLMOD
267    ///
268    /// ## Parameters
269    /// * DBI `.0` => MCU Interface Format
270    /// * DPI `.1` => RGB Interface Format
271    ///
272    /// ## Description
273    ///
274    /// This command sets the pixel format for the RGB image data used by the interface. DPI [2:0] is
275    /// the pixel format select of RGB interface and DBI [2:0] is the pixel format of MCU interface. If
276    /// a particular interface, either RGB interface or MCU interface, is not used then the
277    /// corresponding bits in the parameter are ignored. The pixel format is shown in the table below.
278    ///
279    /// ## Restriction
280    ///
281    /// This command has no effect when module is already in idle off mode.
282    PixelFormatSet(Dbi, Dpi),
283
284    /// Set Tear Scanline (44h)
285    ///
286    /// ## Parameters
287    /// * STS => Set Tear Scanline 0-239
288    ///
289    /// ## Description
290    ///
291    /// This command turns on the display Tearing Effect output signal on the TE signal line when the
292    /// display reaches line equal the value of STS[8:0].
293    ///
294    /// __NOTE__: that set_tear_scanline with STS is equivalent to set_tear_on with 8+GateN(N=1、2、3...240)
295    SetTearScanline(u16),
296
297    /// Write Display Brightness (51h)
298    ///
299    /// This command is used to adjust the brightness value of the display
300    ///
301    /// ## Parameters
302    ///
303    /// * DBV `.0` =>
304    ///
305    /// ## Description
306    ///
307    /// It should be checked what is the relationship between this written value and output brightness of the display.
308    /// This relationship between this written value and output brightness of the display. This relationship is defined on the display module specification.
309    /// In principle relationship is that 00h value means the lowest brightness and FFh value means the highest brightness.
310    ///
311    /// ## Math
312    ///
313    /// * DBV[7:0]/255 x period (affected by OSC frequency)
314    ///
315    /// For example: LEDPWM period = 3ms, and DBV[7:0] = ‘200DEC’. Then LEDPWM duty = 200 / 255=78.1%.
316    /// Correspond to the LEDPWM period = 3 ms, the high-level of LEDPWM (high effective) = 2.344ms, and the
317    /// low-level of LEDPWM = 0.656ms.
318    ///
319    DisplayBrightness(u8),
320
321    /// Write CTRL Display (53h)
322    ///
323    /// ## Parameters
324    ///
325    /// * BCTRL `.0` => Brightness Control Block On/Off
326    /// * DD `.1` => Display Dimming On/Off
327    /// * BL `.2` => Backlight On/Off
328    ///
329    /// ## Restriction
330    ///
331    /// The display module is sending 2nd parameter value on the data line if the MCU
332    /// wants to read more than one parameters
333    /// (=more than 2 RDX Cyle) on DBI
334    /// Only 2nd parameter is sent on DSI (The 1st parameter is not sent).
335    CtrlDisplay(Logical, Logical, Logical),
336
337    /// RGB Interface Signal Control (B0h)
338    ///
339    /// ## Parameters
340    ///
341    /// * EPL `.0` => DE polarity (“0”= High enable for RGB interface, “1”= Low enable for RGB interface)
342    /// * DP `.1` => DOTCLK polarity set (“0”= data fetched at the rising time, “1”= data fetched at the falling time)
343    /// * HSP `.2` => HSYNC polarity (“0”= Low level sync clock, “1”= High level sync clock)
344    /// * VSP `.3` => VSYNC polarity (“0”= Low level sync clock, “1”= High level sync clock)
345    /// * RCM `.4` => RGB interface selection (refer to the RGB interface section).
346    ///
347    RGBInterfaceSignalCtrl(DEPolarity, DOTClk, XSpl, XSpl, RCMMode),
348
349    /// Blanking Porch Control (B5h)
350    ///
351    /// ## Parameters
352    ///
353    /// * VFP `.0` => The line number of Vertical Front Porch
354    /// * VBP `.1` => The line number of Vertical Back Porch
355    /// * HBP `.2` => The line number of Horizontal Back Porch
356    ///
357    /// ## Description
358    ///
359    /// __NOTE__: The Third parameter must write,but it is not valid
360    ///
361    BlankingPorchControl(u8, u8, u8),
362
363    /// Display Function Control (B6h)
364    ///
365    /// ## Parameters
366    ///
367    /// * GS `.0` => Sets the direction of scan by the gate driver in the range determined by SCN [4:0]
368    /// * SS `.1` => Select the shift direction of outputs from the source driver.
369    /// * SM `.2` => Sets the gate driver pin arrangement in combination with the GS bit to select the optimal scan mode for the module
370    /// * NL `.3` =>  Sets the number of lines to drive the LCD at an interval of 8 lines.
371    ///
372    /// ## Restriction
373    ///
374    /// EXTC should be high to enable this command
375    ///
376    DispalyFunctionControl(GSMode, SSMode, u8, u8),
377
378    /// TE Control (BAh)
379    ///
380    /// ## Parameters
381    ///
382    /// * te_pol `.0` => [`TEPolarity`] is used to adjust the Tearing Effect output signal pulse polarity
383    /// * te_width `.1` => TODO
384    ///
385    /// ## Restriction
386    ///
387    /// __NOTE__: During Sleep In Mode with Tearing Effect Line On, Tearing Effect Output pin will be active Low
388    /// This command has no effect when Tearing Effect output is already ON
389    ///
390    TEControl(TEPolarity, u8),
391
392    /// Interface Control (F6h)
393    ///
394    /// ## Parameters
395    ///
396    /// * DM `.0` => TODO
397    /// * RM `.1` => TODO
398    /// * RIM `.2` => TODO
399    ///
400    /// ## Restriction
401    ///
402    /// EXTC should be high to enable this command
403    ///
404    Interface(DMMode, RMMode, RIMMode),
405
406    /// Power Criterion Control (C1h)
407    ///
408    /// ## Parameters
409    ///
410    /// * vcire `.0` => TODO
411    ///
412    PowerCriterioControl(VCIRe),
413
414    /// VCore Voltage Control (A7h)
415    ///
416    /// ## Parameters
417    ///
418    /// * vdd_ad `.0` => TODO
419    ///
420    VCoreVoltageControl(VddAd),
421
422    /// Vreg 1a Voltage Control (C3h)
423    ///
424    /// ## Parameters
425    ///
426    /// * vreg1_vbp_d `.0` => TODO
427    ///
428    /// ## Description
429    ///
430    /// Set the voltage level value to output the VREG1A and VREG1B OUT level, which is a
431    /// reference level for the grayscale voltage level.(Table is valid when vrh=0x28)
432    /// VREG1A=(vrh+vbp_d)*0.02+4
433    /// VREG1B=vbp_d*0.02+0.3
434    ///
435    Vreg1aVoltageControl(u8),
436
437    /// Vreg 1b Voltage Control (C4h)
438    ///
439    /// ## Parameters
440    ///
441    /// * vreg1_vbn_d `.0` => TODO
442    ///
443    /// ## Description
444    ///
445    /// Set the voltage level value to output the VREG2A OUT level, which is a reference level for
446    /// the grayscale voltage level(Table is valid when vrh=0x28)
447    /// VREG2A=(vbn_d-vrh)*0.02-3.4
448    /// VREG2B=vbn_d*0.02+0.3
449    ///
450    Vreg1bVoltageControl(u8),
451
452    /// Vreg 2a Voltage Control (C9h)
453    ///
454    /// ## Parameters
455    ///
456    /// * vrh `.0` => TODO
457    ///
458    /// ## Description
459    ///
460    /// Set the voltage level value to output the VREG1A OUT level, which is a reference level for
461    /// the grayscale voltage level. (Table is valid when vbp_d=0x3C and vbn_d=0x3C)
462    /// VREG1A=(vrh+vbp_d)*0.02+4
463    /// VREG2A=(vbn_d-vrh)*0.02-3.4
464    ///
465    Vreg2aVoltageControl(u8),
466
467    /// Frame Rate (E8h)
468    ///
469    /// ## Parameters
470    ///
471    /// * DINV `.0` => [`DINVMode`]
472    /// * (unused) RTN1 `.1` => TODO
473    /// * (undocumented) RTN2 `.2` => TODO (Misleading information)
474    ///
475    FrameRate(DINVMode),
476
477    /// SPI 2data Control (E9h)
478    ///
479    /// ## Parameters
480    ///
481    /// * 2data_en `.0` => [`Data2EN`]
482    /// * 2data_mdt `.1` => [`DataFormatMDT`]
483    ///
484    /// ## Restriction
485    ///
486    /// Inter command should be set high to enable this command
487    ///
488    Spi2dataControl(Data2EN, DataFormatMDT),
489
490    /// Charge Pump Frequent Control (ECh)
491    ///
492    /// ## Parameters
493    ///
494    /// * avdd_clk_ad `.0` => TODO / Undocumented
495    /// * avee_clk_ad `.1` => TODO / Undocumented
496    /// * vcl_clk_ad `.2` => TODO / Undocumented
497    /// * vgh_clk_ad `.3` => TODO / Undocumented
498    /// * vgl_clk_ad `.4` => TODO / Undocumented
499    ///
500    ChargePumpFrequentControl(u8, u8, u8, u8, u8),
501
502    /// Inner Register Enable 1 (FEh)
503    ///
504    /// ## Description
505    ///
506    /// This command is used for Inter_command controlling.
507    /// To set Inter_command high ,you should write Inter register enable 1 (FEh) and Inter register
508    /// enable 2 (EFh) continuously.
509    /// Once Inter_command is set high, only hardware or software reset can turn it to low.
510    ///
511    InnerRegisterEnable1,
512
513    /// Inner Register Enable 2 (EFh)
514    ///
515    /// ## Description
516    ///
517    /// This command is used for Inter_command controlling.
518    /// To set Inter_command high ,you should write Inter register enable 1 (FEh) and Inter register
519    /// enable 2 (EFh) continuously.
520    /// Once Inter_command is set high, only hardware or software reset can turn it to low.
521    ///
522    InnerRegisterEnable2,
523
524    /// Set GAMMA 1 (F0h)
525    ///
526    /// ## Parameters
527    ///
528    /// * Gamma1 `.0`
529    ///
530    /// ## Restriction
531    ///
532    /// Inter_command should be set high to enable this command
533    ///
534    SetGamma1(Gamma1),
535
536    /// Set GAMMA 2 (F1h)
537    ///
538    /// ## Parameters
539    ///
540    /// * Gamma2 `.0`
541    ///
542    /// ## Restriction
543    ///
544    /// Inter_command should be set high to enable this command
545    ///
546    SetGamma2(Gamma2),
547
548    /// Set GAMMA 3 (F2h)
549    ///
550    /// ## Parameters
551    ///
552    /// * Gamma3 `.0`
553    ///
554    /// ## Restriction
555    ///
556    /// Inter_command should be set high to enable this command
557    ///
558    SetGamma3(Gamma3),
559
560    /// Set GAMMA 4 (F3h)
561    ///
562    /// ## Parameters
563    ///
564    /// * Gamma4 `.0`
565    ///
566    /// ## Restriction
567    ///
568    /// Inter_command should be set high to enable this command
569    ///
570    SetGamma4(Gamma4),
571
572    /// Set Undocumented EBh (EBh)
573    ///
574    SetUndocumented0EBh(u8),
575
576    /// Set Undocumented 084h (084h)
577    ///
578    SetUndocumented084h(u8),
579
580    /// Set Undocumented 085h (085h)
581    ///
582    SetUndocumented085h(u8),
583
584    /// Set Undocumented 086h (086h)
585    ///
586    SetUndocumented086h(u8),
587
588    /// Set Undocumented 087h (087h)
589    ///
590    SetUndocumented087h(u8),
591
592    /// Set Undocumented 088h (088h)
593    ///
594    SetUndocumented088h(u8),
595
596    /// Set Undocumented 089h (089h)
597    ///
598    SetUndocumented089h(u8),
599
600    /// Set Undocumented 08Ah (08Ah)
601    ///
602    SetUndocumented08Ah(u8),
603
604    /// Set Undocumented 08Bh (08Bh)
605    ///
606    SetUndocumented08Bh(u8),
607
608    /// Set Undocumented 08Ch (08Ch)
609    ///
610    SetUndocumented08Ch(u8),
611
612    /// Set Undocumented 08Dh (08Dh)
613    ///
614    SetUndocumented08Dh(u8),
615
616    /// Set Undocumented 08Eh (08Eh)
617    ///
618    SetUndocumented08Eh(u8),
619
620    /// Set Undocumented 08Fh (08Fh)
621    ///
622    SetUndocumented08Fh(u8),
623
624    /// Set Undocumented 090h (090h)
625    ///
626    SetUndocumented090h,
627
628    /// Set Undocumented 062h (0x62h)
629    ///
630    SetUndocumented062h,
631
632    /// Set Undocumented 063h (0x63h)
633    ///
634    SetUndocumented063h,
635
636    /// Set Undocumented 064h (0x64h)
637    ///
638    SetUndocumented064h,
639
640    /// Set Undocumented 066h (0x66h)
641    ///
642    SetUndocumented066h,
643
644    /// Set Undocumented 067h (0x67h)
645    ///
646    SetUndocumented067h,
647
648    /// Set Undocumented 074h (0x74h)
649    ///
650    SetUndocumented074h,
651
652    /// Set Undocumented 098h (0x98h)
653    ///
654    SetUndocumented098h,
655
656    ///Set SUndocumented 0BEh (0xBEh)
657    SetUndocumented0BEh,
658    ///Set SUndocumented 0BCh (0xBCh)
659    SetUndocumented0BCh,
660    ///Set SUndocumented 0BDh (0xBDh)
661    SetUndocumented0BDh,
662    ///Set SUndocumented 0E1h (0xE1h)
663    SetUndocumented0E1h,
664    ///Set SUndocumented 0DFh (0xDFh)
665    SetUndocumented0DFh,
666    ///Set SUndocumented 0EDh (0xEDh)
667    SetUndocumented0EDh,
668    ///Set SUndocumented 0AEh (0xAEh)
669    SetUndocumented0AEh,
670    ///Set SUndocumented 0CDh (0xCDh)
671    SetUndocumented0CDh,
672    ///Set SUndocumented 070h (0x70h)
673    SetUndocumented070h,
674    ///Set SUndocumented 0FFh (0xFFh)
675    SetUndocumented0FFh,
676
677    /// Memory Write (F2Ch)
678    ///
679    /// ## Description
680    ///
681    /// change to the other driver
682    /// status. When this command is accepted, the column register and the page register are reset to
683    /// the Start Column/Start
684    /// Page positions. The Start Column/Start Page positions are different in accordance with
685    /// MADCTL setting.) Then D [17:0] isstored in frame memory and the column register and the
686    /// page register incremented. Sending any other command can stop frame Write. X = Don’t care
687    ///
688    /// ## Restriction
689    ///
690    /// In all color modes, there is no restriction on length of parameters.
691    ///
692    ///
693    MemoryWrite,
694
695    /// Write Memory Contiue (3Ch)
696    ///
697    /// ## Description
698    ///
699    /// This command transfers image data from the host processor to the display module’s frame
700    /// memory continuing from the pixel location following the previous write_memory_continue or write_memory_start
701    /// command.
702    ///
703    /// ### If set_address_mode B5 = 0:
704    /// Data is written continuing from the pixel location after the write range of the previous
705    /// write_memory_start or write_memory_continue. The column register is then incremented and pixels are written to the
706    /// frame memory until the column register equals the End Column (EC) value. The column register is then reset to SC and the page register is
707    /// incremented. Pixels are written to the frame memory until the page register equals the End Page
708    /// (EP) value and the column register equals the EC value, or the host processor sends another command. If the
709    /// number of pixels exceeds (EC –SC + 1) * (EP – SP + 1) the extra pixels are ignored.
710    ///
711    /// ### If set_address_mode B5 = 1:
712    /// Data is written continuing from the pixel location after the write range of the previous
713    /// write_memory_start or write_memory_continue. The page register is then incremented and pixels are written to the
714    /// frame memory until the page register equals the End Page (EP) value. The page register is then
715    /// reset to SP and the column register is incremented. Pixels are written to the frame memory until
716    /// the column register equals the End column (EC) value and the page register equals the EP value,
717    /// or the host processor sends another command. If the number of pixels exceeds (EC – SC + 1) *
718    /// (EP –SP + 1) the extra pixels are ignored.
719    /// Sending any other command can stop frame Write.
720    /// Frame Memory Access and Interface setting (B3h), WEMODE=0
721    /// When the transfer number of data exceeds (EC-SC+1)*(EP-SP+1), the exceeding data will be ignored.
722    /// Frame Memory Access and Interface setting (B3h), WEMODE=1
723    ///
724    /// When the transfer number of data exceeds (EC-SC+1)*(EP-SP+1), the column and page number
725    /// will be reset, and the
726    /// exceeding data will be written into the following column and page
727    ///
728    /// ## Restriction
729    ///
730    /// A write_memory_start should follow a set_column_address, set_page_address or
731    /// set_address_mode to define the write
732    /// address. Otherwise, data written with write_memory_continue is written to undefined addresses
733    MemoryWriteContinue,
734}
735
736impl Command {
737    /// Send command to [`Gc9a01`]
738    ///
739    /// # Errors
740    ///
741    /// This method may return an error if there are communication issues with the display.
742    #[allow(clippy::too_many_lines)]
743    pub fn send<DI>(self, iface: &mut DI) -> Result<(), DisplayError>
744    where
745        DI: WriteOnlyDataCommand,
746    {
747        // 16bits command (2bytes)
748        // 16bits param_1 (2bytes)
749        // 16bits param_2 (2bytes)
750        // 16bits param_3 (2bytes)
751        // 16bits param_4 (2bytes)
752        // Maximum 10 bytes
753        // Array Size 5
754        // Transform everything in 10 bytes array
755        let (data, len): ([u8; 13], usize) = match self {
756            Self::SleepMode(level) => (
757                [
758                    match level {
759                        Logical::Off => 0x11,
760                        Logical::On => 0x10,
761                    },
762                    0,
763                    0,
764                    0,
765                    0,
766                    0,
767                    0,
768                    0,
769                    0,
770                    0,
771                    0,
772                    0,
773                    0,
774                ],
775                1,
776            ),
777            Self::PartialMode => ([0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
778            Self::NormalDisplayMode => ([0x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
779            Self::DisplayInversion(level) => {
780                ([0x20 | level as u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1)
781            }
782            Self::DisplayState(level) => {
783                ([0x28 | level as u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1)
784            }
785            Self::ColumnAddressSet(sc, ec) => (
786                [
787                    0x2A,
788                    (sc >> 8) as u8,
789                    (sc & 0xFF) as u8,
790                    (ec >> 8) as u8,
791                    (ec & 0xFF) as u8,
792                    0,
793                    0,
794                    0,
795                    0,
796                    0,
797                    0,
798                    0,
799                    0,
800                ],
801                5,
802            ),
803            Self::RowAddressSet(sp, ep) => (
804                [
805                    0x2B,
806                    (sp >> 8) as u8,
807                    (sp & 0xFF) as u8,
808                    (ep >> 8) as u8,
809                    (ep & 0xFF) as u8,
810                    0,
811                    0,
812                    0,
813                    0,
814                    0,
815                    0,
816                    0,
817                    0,
818                ],
819                5,
820            ),
821            Self::VertialScrollDef(tfa, vsa) => (
822                [
823                    0x33,
824                    (tfa >> 8) as u8,
825                    (tfa & 0xFF) as u8,
826                    (vsa >> 8) as u8,
827                    (vsa & 0xFF) as u8,
828                    0,
829                    0,
830                    0,
831                    0,
832                    0,
833                    0,
834                    0,
835                    0,
836                ],
837                5,
838            ),
839            Self::TearingEffectLine(mode) => {
840                ([0x34 | mode as u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1)
841            }
842            Self::VerticalScrollStartAddresss(vsp) => (
843                [
844                    0x37,
845                    (vsp >> 8) as u8,
846                    (vsp & 0xFF) as u8,
847                    0,
848                    0,
849                    0,
850                    0,
851                    0,
852                    0,
853                    0,
854                    0,
855                    0,
856                    0,
857                ],
858                3,
859            ),
860            Self::IdleMode(mode) => ([0x38 | mode as u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
861            Self::PixelFormatSet(dbi, dpi) => (
862                [
863                    0x3A,
864                    ((dpi as u8) << 4) | (dbi as u8),
865                    0,
866                    0,
867                    0,
868                    0,
869                    0,
870                    0,
871                    0,
872                    0,
873                    0,
874                    0,
875                    0,
876                ],
877                2,
878            ),
879            Self::SetTearScanline(sts) => (
880                [
881                    0x44,
882                    (((sts + 8) & 0x100) >> 8) as u8,
883                    ((sts + 8) & 0xFF) as u8,
884                    0,
885                    0,
886                    0,
887                    0,
888                    0,
889                    0,
890                    0,
891                    0,
892                    0,
893                    0,
894                ],
895                3,
896            ),
897            Self::DisplayBrightness(dbv) => ([0x51, dbv, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
898            Self::CtrlDisplay(bctrl, dd, bl) => (
899                [
900                    0x53,
901                    (bctrl as u8) << 5 | (dd as u8) << 3 | (bl as u8) << 2,
902                    0,
903                    0,
904                    0,
905                    0,
906                    0,
907                    0,
908                    0,
909                    0,
910                    0,
911                    0,
912                    0,
913                ],
914                2,
915            ),
916            Self::RGBInterfaceSignalCtrl(epl, dpl, hsp, vsp, rcm) => (
917                [
918                    0xB0,
919                    (epl as u8 & 0b1)
920                        | ((dpl as u8 & 0b1) << 1)
921                        | ((hsp as u8 & 0b1) << 2)
922                        | ((vsp as u8 & 0b1) << 3)
923                        | ((rcm as u8 & 0b11) << 5),
924                    0,
925                    0,
926                    0,
927                    0,
928                    0,
929                    0,
930                    0,
931                    0,
932                    0,
933                    0,
934                    0,
935                ],
936                2,
937            ),
938            Self::BlankingPorchControl(vfp, vbp, hbp) => (
939                [
940                    0xB5,
941                    vfp,
942                    vbp & 0b0111_1111,
943                    hbp & 0b0001_1111,
944                    0,
945                    0,
946                    0,
947                    0,
948                    0,
949                    0,
950                    0,
951                    0,
952                    0,
953                ],
954                4,
955            ),
956            Self::DispalyFunctionControl(gs, ss, sm, nl) => (
957                [
958                    0xB6,
959                    ((gs as u8 & 0b1) << 6) | ((ss as u8 & 0b1) << 5) | ((sm & 0b1) << 4),
960                    nl & 0b0001_1111,
961                    0,
962                    0,
963                    0,
964                    0,
965                    0,
966                    0,
967                    0,
968                    0,
969                    0,
970                    0,
971                ],
972                3,
973            ),
974            Self::TEControl(te_pol, te_width) => (
975                [
976                    0xBA,
977                    ((te_pol as u8) << 7) | (te_width & 0b0111_1111),
978                    0,
979                    0,
980                    0,
981                    0,
982                    0,
983                    0,
984                    0,
985                    0,
986                    0,
987                    0,
988                    0,
989                ],
990                2,
991            ),
992            Self::Interface(dm, rm, rim) => (
993                [
994                    0xF6,
995                    ((dm as u8 & 0b11) << 2) | ((rm as u8 & 0b1) << 1) | (rim as u8 & 0b1),
996                    0,
997                    0,
998                    0,
999                    0,
1000                    0,
1001                    0,
1002                    0,
1003                    0,
1004                    0,
1005                    0,
1006                    0,
1007                ],
1008                2,
1009            ),
1010            Self::PowerCriterioControl(vcire) => (
1011                [
1012                    0xC1,
1013                    ((vcire as u8 & 0b1) << 1),
1014                    0,
1015                    0,
1016                    0,
1017                    0,
1018                    0,
1019                    0,
1020                    0,
1021                    0,
1022                    0,
1023                    0,
1024                    0,
1025                ],
1026                2,
1027            ),
1028            Self::VCoreVoltageControl(vddad) => (
1029                [
1030                    0xA7,
1031                    0b0100_0000 | vddad as u8,
1032                    0,
1033                    0,
1034                    0,
1035                    0,
1036                    0,
1037                    0,
1038                    0,
1039                    0,
1040                    0,
1041                    0,
1042                    0,
1043                ],
1044                2,
1045            ),
1046            Self::Vreg1aVoltageControl(value) => {
1047                ([0xC3, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2)
1048            }
1049            Self::Vreg1bVoltageControl(value) => {
1050                ([0xC4, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2)
1051            }
1052            Self::Vreg2aVoltageControl(value) => {
1053                ([0xC9, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2)
1054            }
1055            Self::FrameRate(divn_mode) => (
1056                [
1057                    0xE8,
1058                    (divn_mode as u8 & 0b111) << 4,
1059                    0,
1060                    0,
1061                    0,
1062                    0,
1063                    0,
1064                    0,
1065                    0,
1066                    0,
1067                    0,
1068                    0,
1069                    0,
1070                ],
1071                2,
1072            ),
1073            Self::Spi2dataControl(data2_en, data_format) => (
1074                [
1075                    0xE9,
1076                    (data2_en as u8 & 0b1) << 3 | (data_format as u8 & 0b111),
1077                    0,
1078                    0,
1079                    0,
1080                    0,
1081                    0,
1082                    0,
1083                    0,
1084                    0,
1085                    0,
1086                    0,
1087                    0,
1088                ],
1089                3,
1090            ),
1091            Self::ChargePumpFrequentControl(
1092                avdd_clk_ad,
1093                avee_clk_ad,
1094                vcl_clk_ad,
1095                vgh_clk_ad,
1096                vgl_clk_ad,
1097            ) => (
1098                [
1099                    0xEC,
1100                    ((avdd_clk_ad & 0b111) << 4) | avee_clk_ad & 0b111,
1101                    vcl_clk_ad & 0b111,
1102                    ((vgh_clk_ad & 0b1111) << 4) | vgl_clk_ad & 0b1111,
1103                    0,
1104                    0,
1105                    0,
1106                    0,
1107                    0,
1108                    0,
1109                    0,
1110                    0,
1111                    0,
1112                ],
1113                4,
1114            ),
1115            Self::InnerRegisterEnable1 => ([0xFE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
1116            Self::InnerRegisterEnable2 => ([0xEF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
1117            Self::SetGamma1(gamma) => (
1118                [
1119                    0xF0,
1120                    // 0b001, 0b000_101
1121                    (gamma.dig2j0_n & 0b11) << 6 | (gamma.vr1_n & 0b0011_1111),
1122                    (gamma.dig2j1_n & 0b11) << 6 | (gamma.vr2_n & 0b0011_1111),
1123                    (gamma.vr4_n & 0b0001_1111),
1124                    (gamma.vr6_n & 0b0001_1111),
1125                    (gamma.vr0_n & 0b1111) << 4 | (gamma.vr13_n & 0b0000_1111),
1126                    (gamma.vr20_n & 0b0111_1111),
1127                    0,
1128                    0,
1129                    0,
1130                    0,
1131                    0,
1132                    0,
1133                ],
1134                7,
1135            ),
1136            Self::SetGamma2(gamma) => (
1137                [
1138                    0xF1,
1139                    (gamma.vr43_n & 0b0111_1111),
1140                    (gamma.vr27_n & 0b111) << 5 | (gamma.vr57_n & 0b0001_1111),
1141                    (gamma.vr36_n & 0b111) << 5 | (gamma.vr59_n & 0b0001_1111),
1142                    (gamma.vr61_n & 0b0011_1111),
1143                    (gamma.vr62_n & 0b0011_1111),
1144                    (gamma.vr50_n & 0b1111) << 4 | (gamma.vr63_n & 0b0000_1111),
1145                    0,
1146                    0,
1147                    0,
1148                    0,
1149                    0,
1150                    0,
1151                ],
1152                7,
1153            ),
1154            Self::SetGamma3(gamma) => (
1155                [
1156                    0xF2,
1157                    (gamma.dig2j0_p & 0b11) << 6 | (gamma.vr1_p & 0b0011_1111),
1158                    (gamma.dig2j1_p & 0b11) << 6 | (gamma.vr2_p & 0b0011_1111),
1159                    (gamma.vr4_p & 0b0001_1111),
1160                    (gamma.vr6_p & 0b0001_1111),
1161                    (gamma.vr0_p & 0b1111) << 4 | (gamma.vr13_p & 0b0000_1111),
1162                    (gamma.vr20_p & 0b0111_1111),
1163                    0,
1164                    0,
1165                    0,
1166                    0,
1167                    0,
1168                    0,
1169                ],
1170                7,
1171            ),
1172            Self::SetGamma4(gamma) => (
1173                [
1174                    0xF3,
1175                    (gamma.vr43_p & 0b0111_1111),
1176                    (gamma.vr27_p & 0b111) << 5 | (gamma.vr57_p & 0b0001_1111),
1177                    (gamma.vr36_p & 0b111) << 5 | (gamma.vr59_p & 0b0001_1111),
1178                    (gamma.vr61_p & 0b0011_1111),
1179                    (gamma.vr62_p & 0b0011_1111),
1180                    (gamma.vr50_p & 0b1111) << 4 | (gamma.vr63_p & 0b0000_1111),
1181                    0,
1182                    0,
1183                    0,
1184                    0,
1185                    0,
1186                    0,
1187                ],
1188                7,
1189            ),
1190            Self::MemoryWrite => ([0x2c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
1191            Self::MemoryWriteContinue => ([0x3c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
1192            Self::SetUndocumented0BEh => ([0xBE, 0x11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1193            Self::SetUndocumented0BCh => ([0xBC, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1194            Self::SetUndocumented0BDh => ([0xBD, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1195            Self::SetUndocumented0E1h => ([0xE1, 0x10, 0x0E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3),
1196            Self::SetUndocumented0DFh => ([0xDF, 0x21, 0x0c, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0], 4),
1197            Self::SetUndocumented0EDh => ([0xED, 0x1B, 0x0B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3),
1198            Self::SetUndocumented0AEh => ([0xAE, 0x77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1199            Self::SetUndocumented0CDh => ([0xCD, 0x63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1200            Self::SetUndocumented070h => (
1201                [
1202                    0x70, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03, 0, 0, 0,
1203                ],
1204                10,
1205            ),
1206
1207            Self::SetUndocumented0FFh => ([0xFF, 0x60, 0x01, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0], 4),
1208            Self::SetUndocumented0EBh(value) => ([0xEB, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1209            Self::SetUndocumented084h(value) => ([0x84, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1210            Self::SetUndocumented085h(value) => ([0x85, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1211            Self::SetUndocumented086h(value) => ([0x86, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1212            Self::SetUndocumented087h(value) => ([0x87, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1213            Self::SetUndocumented088h(value) => ([0x88, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1214            Self::SetUndocumented089h(value) => ([0x89, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1215            Self::SetUndocumented08Ah(value) => ([0x8A, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1216            Self::SetUndocumented08Bh(value) => ([0x8B, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1217            Self::SetUndocumented08Ch(value) => ([0x8C, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1218            Self::SetUndocumented08Dh(value) => ([0x8D, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1219            Self::SetUndocumented08Eh(value) => ([0x8E, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1220            Self::SetUndocumented08Fh(value) => ([0x8F, value, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 2),
1221            Self::SetUndocumented090h => {
1222                ([0x90, 0x08, 0x08, 0x08, 0x08, 0, 0, 0, 0, 0, 0, 0, 0], 5)
1223            }
1224            Self::MemoryAccessControl(my, mx, mv, ml, bgr, mh) => (
1225                [
1226                    0x36,
1227                    (my as u8) << 7
1228                        | (mx as u8) << 6
1229                        | (mv as u8) << 5
1230                        | (ml as u8) << 4
1231                        | (bgr as u8) << 3
1232                        | (mh as u8) << 2,
1233                    0,
1234                    0,
1235                    0,
1236                    0,
1237                    0,
1238                    0,
1239                    0,
1240                    0,
1241                    0,
1242                    0,
1243                    0,
1244                ],
1245                2,
1246            ),
1247            Self::SetUndocumented062h => (
1248                [
1249                    0x62, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70,
1250                ],
1251                13,
1252            ),
1253            Self::SetUndocumented063h => (
1254                [
1255                    0x63, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70,
1256                ],
1257                13,
1258            ),
1259            Self::SetUndocumented064h => (
1260                [
1261                    0x64, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07, 0, 0, 0, 0, 0,
1262                ],
1263                8,
1264            ),
1265            Self::SetUndocumented066h => (
1266                [
1267                    0x66, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00, 0, 0,
1268                ],
1269                11,
1270            ),
1271            Self::SetUndocumented067h => (
1272                [
1273                    0x67, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98, 0, 0,
1274                ],
1275                11,
1276            ),
1277            Self::SetUndocumented074h => (
1278                [
1279                    0x74, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00, 0, 0, 0, 0, 0,
1280                ],
1281                8,
1282            ),
1283            Self::SetUndocumented098h => ([0x98, 0x3e, 0x07, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 3),
1284        };
1285
1286        // Send command over the interface
1287        // TODO: do something better
1288        iface.send_commands(U8(&[data[0]]))?;
1289        if len > 1 {
1290            iface.send_data(U8(&data[1..len]))?;
1291        }
1292        Ok(())
1293    }
1294}
1295
1296/// Logical On/Off
1297#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1298#[repr(u8)]
1299pub enum Logical {
1300    Off = 0,
1301    On = 1,
1302}
1303
1304impl From<bool> for Logical {
1305    fn from(val: bool) -> Self {
1306        if val {
1307            Self::On
1308        } else {
1309            Self::Off
1310        }
1311    }
1312}
1313
1314impl From<u8> for Logical {
1315    fn from(val: u8) -> Self {
1316        match val {
1317            0 => Self::Off,
1318            _ => Self::On,
1319        }
1320    }
1321}
1322
1323/// Display Enable Polarity (DE Polarity)
1324#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1325#[repr(u8)]
1326pub enum DEPolarity {
1327    /// High enable for RGB interface
1328    HighEnableForRGB = 0,
1329    /// Low enable for RGB interface
1330    LowEnableForRGB = 1,
1331}
1332
1333impl From<bool> for DEPolarity {
1334    fn from(val: bool) -> Self {
1335        if val {
1336            Self::HighEnableForRGB
1337        } else {
1338            Self::LowEnableForRGB
1339        }
1340    }
1341}
1342
1343impl From<u8> for DEPolarity {
1344    fn from(val: u8) -> Self {
1345        match val {
1346            0 => Self::HighEnableForRGB,
1347            _ => Self::LowEnableForRGB,
1348        }
1349    }
1350}
1351
1352/// The Tearing Effect output signal pulse polarity
1353#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1354#[repr(u8)]
1355pub enum TEPolarity {
1356    /// High enable for RGB interface
1357    PositivePulse = 0,
1358    /// Low enable for RGB interface
1359    NegativePulse = 1,
1360}
1361
1362impl From<bool> for TEPolarity {
1363    fn from(val: bool) -> Self {
1364        if val {
1365            Self::PositivePulse
1366        } else {
1367            Self::NegativePulse
1368        }
1369    }
1370}
1371
1372impl From<u8> for TEPolarity {
1373    fn from(val: u8) -> Self {
1374        match val {
1375            0 => Self::PositivePulse,
1376            _ => Self::NegativePulse,
1377        }
1378    }
1379}
1380
1381/// Display Enable Polarity (DOTCLK Polarity)
1382#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1383#[repr(u8)]
1384pub enum DOTClk {
1385    /// Data fetched at the rising time
1386    FetchOnRising = 0,
1387    /// Data fetched at the falling time
1388    FetchOnFalling = 1,
1389}
1390
1391impl From<bool> for DOTClk {
1392    fn from(val: bool) -> Self {
1393        if val {
1394            Self::FetchOnRising
1395        } else {
1396            Self::FetchOnFalling
1397        }
1398    }
1399}
1400
1401impl From<u8> for DOTClk {
1402    fn from(val: u8) -> Self {
1403        match val {
1404            0 => Self::FetchOnRising,
1405            _ => Self::FetchOnFalling,
1406        }
1407    }
1408}
1409
1410/// Polarity Clock Sync
1411#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1412#[repr(u8)]
1413pub enum XSpl {
1414    /// Low level sync clock
1415    LowSyncClock = 0,
1416    /// Low level sync clock
1417    HighSyncClock = 1,
1418}
1419
1420impl From<bool> for XSpl {
1421    fn from(val: bool) -> Self {
1422        if val {
1423            Self::LowSyncClock
1424        } else {
1425            Self::HighSyncClock
1426        }
1427    }
1428}
1429
1430impl From<u8> for XSpl {
1431    fn from(val: u8) -> Self {
1432        match val {
1433            0 => Self::LowSyncClock,
1434            _ => Self::HighSyncClock,
1435        }
1436    }
1437}
1438
1439/// Polarity Clock Sync
1440#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1441#[repr(u8)]
1442pub enum RCMMode {
1443    /// DE Mode Valid data is determined by the DE signal
1444    DEMode = 0b10,
1445    /// SYNC Mode In SYNC mode, DE signal is ignored; blanking porch
1446    /// is determined by B5h command
1447    SyncMode = 0b11,
1448}
1449
1450impl From<u8> for RCMMode {
1451    fn from(val: u8) -> Self {
1452        match val {
1453            0b10 => Self::DEMode,
1454            _ => Self::SyncMode,
1455        }
1456    }
1457}
1458
1459/// Output Scan Direction
1460#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1461#[repr(u8)]
1462pub enum SSMode {
1463    /// To assign R, G, B dots to the source driver pins from S1 to S360, set SS = 0
1464    S1toS360 = 0,
1465    /// To assign R, G, B dots to the source driver pins from S360 to S1, set SS = 1.
1466    S360toS1 = 1,
1467}
1468
1469impl From<u8> for SSMode {
1470    fn from(val: u8) -> Self {
1471        match val {
1472            0 => Self::S1toS360,
1473            _ => Self::S1toS360,
1474        }
1475    }
1476}
1477
1478/// Display Operation Mode
1479/// Select the display operation mode
1480#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1481#[repr(u8)]
1482pub enum DMMode {
1483    /// Internal clock operation
1484    InternalClockOperation = 0,
1485    /// RGB Interface Mode
1486    RGBInterfaceMode = 1,
1487    /// VSYNC Interface Mode
1488    VSYNCInterfaceMode = 2,
1489    /// RGB Interface Mode
1490    SettingDisabled = 3,
1491}
1492
1493impl From<u8> for DMMode {
1494    fn from(val: u8) -> Self {
1495        match val {
1496            0 => Self::InternalClockOperation,
1497            1 => Self::RGBInterfaceMode,
1498            2 => Self::VSYNCInterfaceMode,
1499            _ => Self::SettingDisabled,
1500        }
1501    }
1502}
1503
1504/// Interface for RAM Access
1505/// Select the interface to access the GRAM.
1506#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1507#[repr(u8)]
1508pub enum RMMode {
1509    /// Select System or VSync Interface to write in GRAM
1510    SystemOrVSyncInterface = 0,
1511    /// Select RGB Interface to write in GRAM
1512    RGBInterface = 1,
1513}
1514
1515impl From<u8> for RMMode {
1516    fn from(val: u8) -> Self {
1517        match val {
1518            0 => Self::SystemOrVSyncInterface,
1519            1 => Self::RGBInterface,
1520            _ => Self::RGBInterface,
1521        }
1522    }
1523}
1524
1525/// RGB Interface Mode
1526/// Specify the RGB interface mode when the RGB interface is used.
1527/// These bit should be set before display operation through the RGB interface
1528/// and should not be set during operation.
1529#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1530#[repr(u8)]
1531pub enum RIMMode {
1532    /// 18- bit RGB interface (1 transfer/pixel)
1533    /// 16- bit RGB interface (1 transfer/pixel)
1534    TransferPerPixel1 = 0,
1535    /// 6- bit RGB interface (3 transfer/pixel)
1536    TransferPerPixel3 = 1,
1537}
1538
1539impl From<u8> for RIMMode {
1540    fn from(val: u8) -> Self {
1541        match val {
1542            0 => Self::TransferPerPixel1,
1543            1 => Self::TransferPerPixel3,
1544            _ => Self::TransferPerPixel3,
1545        }
1546    }
1547}
1548
1549/// Display Inversion Mode
1550/// Set display inversion mode
1551#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1552#[repr(u8)]
1553pub enum DINVMode {
1554    /// column inversion
1555    ColumnInversion = 0,
1556    /// 1 dot inversion
1557    Inversion1Dot = 1,
1558    /// 2 dot inversion
1559    Inversion2Dot = 2,
1560    /// 4 dot inversion
1561    Inversion4Dot = 3,
1562    /// 8 dot inversion
1563    Inversion8Dot = 4,
1564}
1565
1566impl From<u8> for DINVMode {
1567    fn from(val: u8) -> Self {
1568        match val {
1569            0 => Self::ColumnInversion,
1570            1 => Self::Inversion1Dot,
1571            2 => Self::Inversion2Dot,
1572            3 => Self::Inversion4Dot,
1573            4 => Self::Inversion8Dot,
1574            _ => Self::Inversion8Dot,
1575        }
1576    }
1577}
1578
1579/// 2 Data Line Mode 3/4-wire SPI
1580#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1581#[repr(u8)]
1582pub enum Data2EN {
1583    /// 3-wire SPI
1584    Data3Wire = 0,
1585    /// 4-wire SPI
1586    Data4Wire = 1,
1587}
1588
1589impl From<u8> for Data2EN {
1590    fn from(val: u8) -> Self {
1591        match val {
1592            0 => Self::Data3Wire,
1593            1 => Self::Data4Wire,
1594            _ => Self::Data4Wire,
1595        }
1596    }
1597}
1598
1599/// `DataFormat` MDT
1600/// Set Pixel Data Format in `2_data_line` mode.
1601#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1602#[repr(u8)]
1603pub enum DataFormatMDT {
1604    /// 65K color 1pixle/transition
1605    Color65k1PixelPerTransition = 0,
1606    /// 262K color 1pixle/transition
1607    Color262k1PixelPerTransition = 1,
1608    /// 262K color 2/3pixle/transition
1609    Color262k2Or3PixelPerTransition = 2,
1610    /// 4M color 1pixle/transition
1611    Color4Mk1PixelPerTransition = 4,
1612    /// 4M color 2/3pixle/transition
1613    Color4M2Or3PixelPerTransition = 5,
1614}
1615
1616impl From<u8> for DataFormatMDT {
1617    fn from(val: u8) -> Self {
1618        match val {
1619            0 => Self::Color65k1PixelPerTransition,
1620            1 => Self::Color262k1PixelPerTransition,
1621            2 => Self::Color262k2Or3PixelPerTransition,
1622            3 => Self::Color4Mk1PixelPerTransition,
1623            4 => Self::Color4M2Or3PixelPerTransition,
1624            _ => Self::Color4M2Or3PixelPerTransition,
1625        }
1626    }
1627}
1628
1629/// External reference voltage Vci or internal reference voltage VCIT
1630#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1631#[repr(u8)]
1632pub enum VCIRe {
1633    /// Internal reference voltage 2.5V (default)
1634    Internal = 0,
1635    /// External reference voltage Vci
1636    External = 1,
1637}
1638
1639impl From<u8> for VCIRe {
1640    fn from(val: u8) -> Self {
1641        match val {
1642            0 => Self::Internal,
1643            1 => Self::External,
1644            _ => Self::External,
1645        }
1646    }
1647}
1648
1649/// Voltage level value to output the VCORE level,
1650#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1651#[repr(u8)]
1652pub enum VddAd {
1653    VCore1_483V = 0x00,
1654    VCore1_545V = 0x01,
1655    VCore1_590V = 0x02,
1656    VCore1_638V = 0x03,
1657    VCore1_714V = 0x04,
1658    VCore1_279V = 0x05,
1659    VCore1_859V = 0x06,
1660    VCore1_925V = 0x07,
1661    VCore1_994V = 0x08,
1662    VCore2_109V = 0x09,
1663    VCore2_193V = 0x0a,
1664    VCore2_286V = 0x0b,
1665    VCore2_385V = 0x0c,
1666    VCore1_713V = 0x0d,
1667    VCore1_713Ve = 0x0e,
1668    VCore1_713Vf = 0x0f,
1669}
1670
1671impl From<u8> for VddAd {
1672    fn from(val: u8) -> Self {
1673        match val {
1674            0x00 => Self::VCore1_483V,
1675            0x01 => Self::VCore1_545V,
1676            0x02 => Self::VCore1_590V,
1677            0x03 => Self::VCore1_638V,
1678            0x04 => Self::VCore1_714V,
1679            0x05 => Self::VCore1_279V,
1680            0x06 => Self::VCore1_859V,
1681            0x07 => Self::VCore1_925V,
1682            0x08 => Self::VCore1_994V,
1683            0x09 => Self::VCore2_109V,
1684            0x0a => Self::VCore2_193V,
1685            0x0b => Self::VCore2_286V,
1686            0x0c => Self::VCore2_385V,
1687            0x0d => Self::VCore1_713V,
1688            0x0e => Self::VCore1_713Ve,
1689            0x0f => Self::VCore1_713Vf,
1690            _ => Self::VCore1_713Vf,
1691        }
1692    }
1693}
1694
1695/// Gate Output Scan Direction
1696/// Sets the direction of scan by the gate driver in the range determined by SCN [4:0] and NL
1697/// [4:0]. The scan direction determined by GS = 0 can be reversed by setting GS = 1.
1698#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1699#[repr(u8)]
1700pub enum GSMode {
1701    G1toG32 = 0,
1702    G32toG1 = 1,
1703}
1704
1705impl From<u8> for GSMode {
1706    fn from(val: u8) -> Self {
1707        match val {
1708            0 => Self::G1toG32,
1709            _ => Self::G32toG1,
1710        }
1711    }
1712}
1713
1714/// Dpi is the pixel format select of RGB interface.
1715#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1716#[repr(u8)]
1717pub enum Dpi {
1718    Pixel16bits = 0b0000_0101,
1719    Pixel18bits = 0b0000_0110,
1720}
1721
1722/// Dbi is the pixel format of MCU interface.
1723#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1724#[repr(u8)]
1725pub enum Dbi {
1726    Pixel12bits = 0b0000_0011,
1727    Pixel16bits = 0b0000_0101,
1728    Pixel18bits = 0b0000_0110,
1729}
1730
1731#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1732pub struct Gamma1 {
1733    /// dig2gam_dig2j0_n
1734    pub dig2j0_n: u8,
1735    /// dig2gam_vr1_n
1736    pub vr1_n: u8,
1737    /// dig2gam_dig2j1_n
1738    pub dig2j1_n: u8,
1739    /// dig2gam_vr2_n
1740    pub vr2_n: u8,
1741    /// dig2gam_vr4_n
1742    pub vr4_n: u8,
1743    /// dig2gam_vr6_n
1744    pub vr6_n: u8,
1745    /// dig2gam_vr0_n
1746    pub vr0_n: u8,
1747    /// dig2gam_vr13_n
1748    pub vr13_n: u8,
1749    /// dig2gam_vr20_n
1750    pub vr20_n: u8,
1751}
1752
1753#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1754pub struct Gamma2 {
1755    /// dig2gam_vr43_n
1756    pub vr43_n: u8,
1757    /// dig2gam_vr27_n
1758    pub vr27_n: u8,
1759    /// dig2gam_vr57_n
1760    pub vr57_n: u8,
1761    /// dig2gam_vr36_n
1762    pub vr36_n: u8,
1763    /// dig2gam_vr59_n
1764    pub vr59_n: u8,
1765    /// dig2gam_vr61_n
1766    pub vr61_n: u8,
1767    /// dig2gam_vr62_n
1768    pub vr62_n: u8,
1769    /// dig2gam_vr50_n
1770    pub vr50_n: u8,
1771    /// dig2gam_vr63_n
1772    pub vr63_n: u8,
1773}
1774
1775#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1776pub struct Gamma3 {
1777    /// dig2gam_dig2j0_p
1778    pub dig2j0_p: u8,
1779    /// dig2gam_vr1_p
1780    pub vr1_p: u8,
1781    /// dig2gam_dig2j1_p
1782    pub dig2j1_p: u8,
1783    /// dig2gam_vr2_p
1784    pub vr2_p: u8,
1785    /// dig2gam_vr4_p
1786    pub vr4_p: u8,
1787    /// dig2gam_vr6_p
1788    pub vr6_p: u8,
1789    /// dig2gam_vr0_p
1790    pub vr0_p: u8,
1791    /// dig2gam_vr13_p
1792    pub vr13_p: u8,
1793    /// dig2gam_vr20_p
1794    pub vr20_p: u8,
1795}
1796
1797#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1798pub struct Gamma4 {
1799    /// dig2gam_vr43_p
1800    pub vr43_p: u8,
1801    /// dig2gam_vr27_p
1802    pub vr27_p: u8,
1803    /// dig2gam_vr57_p
1804    pub vr57_p: u8,
1805    /// dig2gam_vr36_p
1806    pub vr36_p: u8,
1807    /// dig2gam_vr59_p
1808    pub vr59_p: u8,
1809    /// dig2gam_vr61_p
1810    pub vr61_p: u8,
1811    /// dig2gam_vr62_p
1812    pub vr62_p: u8,
1813    /// dig2gam_vr50_p
1814    pub vr50_p: u8,
1815    /// dig2gam_vr63_p
1816    pub vr63_p: u8,
1817}