@@ -6,182 +6,148 @@ use embedded_hal::digital::v2::OutputPin;
66
77pub use display_interface:: { DataFormat , DisplayError , WriteOnlyDataCommand } ;
88
9+ /// This trait represents the data pins of a parallel bus.
10+ ///
11+ /// See [Generic8BitBus] for a generic implementation.
12+ pub trait OutputBus {
13+ /// [u8] for 8-bit busses, [u16] for 16-bit busses, etc.
14+ type Word : Copy ;
15+
16+ fn set_value ( & mut self , value : Self :: Word ) -> Result < ( ) , DisplayError > ;
17+ }
18+
19+ macro_rules! generic_bus {
20+ ( $GenericxBitBus: ident { type Word = $Word: ident; Pins { $( $PX: ident => $x: tt, ) * } } ) => {
21+ /// A generic implementation of [OutputBus] using [OutputPin]s
22+ pub struct $GenericxBitBus<$( $PX, ) * > {
23+ pins: ( $( $PX, ) * ) ,
24+ last: $Word,
25+ }
26+
27+ impl <$( $PX, ) * > $GenericxBitBus<$( $PX, ) * >
28+ where
29+ $( $PX: OutputPin , ) *
30+ {
31+ /// Creates a new instance and initializes the bus to `0`.
32+ ///
33+ /// The first pin in the tuple is the least significant bit.
34+ pub fn new( pins: ( $( $PX, ) * ) ) -> Result <Self , DisplayError > {
35+ let mut bus = Self { pins, last: $Word:: MAX } ;
36+
37+ // By setting `last` to all ones, we ensure that this will update all the pins
38+ bus. set_value( 0 ) ?;
39+
40+ Ok ( bus)
41+ }
42+
43+ /// Consumes the bus and returns the pins. This does not change the state of the pins.
44+ pub fn release( self ) -> ( $( $PX, ) * ) {
45+ self . pins
46+ }
47+ }
48+
49+ impl <$( $PX, ) * > OutputBus
50+ for $GenericxBitBus<$( $PX, ) * >
51+ where
52+ $( $PX: OutputPin , ) *
53+ {
54+ type Word = $Word;
55+
56+ fn set_value( & mut self , value: Self :: Word ) -> Result <( ) , DisplayError > {
57+ let changed = value ^ self . last;
58+
59+ // It's quite common for multiple consecutive values to be identical, e.g. when filling or
60+ // clearing the screen, so let's optimize for that case
61+ if changed != 0 {
62+ $(
63+ let mask = 1 << $x;
64+ if changed & mask != 0 {
65+ if value & mask != 0 {
66+ self . pins. $x. set_high( )
67+ } else {
68+ self . pins. $x. set_low( )
69+ }
70+ . map_err( |_| DisplayError :: BusWriteError ) ?;
71+ }
72+ ) *
73+
74+ self . last = value;
75+ }
76+
77+ Ok ( ( ) )
78+ }
79+ }
80+
81+ impl <$( $PX, ) * > core:: convert:: TryFrom <( $( $PX, ) * ) >
82+ for $GenericxBitBus<$( $PX, ) * >
83+ where
84+ $( $PX: OutputPin , ) *
85+ {
86+ type Error = DisplayError ;
87+
88+ fn try_from( pins: ( $( $PX, ) * ) ) -> Result <Self , Self :: Error > {
89+ Self :: new( pins)
90+ }
91+ }
92+ } ;
93+ }
94+
95+ generic_bus ! {
96+ Generic8BitBus {
97+ type Word = u8 ;
98+ Pins {
99+ P0 => 0 ,
100+ P1 => 1 ,
101+ P2 => 2 ,
102+ P3 => 3 ,
103+ P4 => 4 ,
104+ P5 => 5 ,
105+ P6 => 6 ,
106+ P7 => 7 ,
107+ }
108+ }
109+ }
110+
9111/// Parallel 8 Bit communication interface
10112///
11113/// This interface implements an 8-Bit "8080" style write-only display interface using any
12- /// `embedded_hal` `digital::v2::OutputPin` implementation.
13- ///
14- /// For the 8-Bit implementation you need to provide 8 types implementing `OutputPin` which
15- /// ressemble the bits 0 through 7 (which bit 0 being the LSB and 7 the MSB) as well as one
114+ /// 8-bit [OutputBus] implementation as well as one
16115/// `OutputPin` for the data/command selection and one `OutputPin` for the write-enable flag.
17116///
18117/// All pins are supposed to be high-active, high for the D/C pin meaning "data" and the
19118/// write-enable being pulled low before the setting of the bits and supposed to be sampled at a
20119/// low to high edge.
21- pub struct PGPIO8BitInterface < P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR > {
22- p0 : P0 ,
23- p1 : P1 ,
24- p2 : P2 ,
25- p3 : P3 ,
26- p4 : P4 ,
27- p5 : P5 ,
28- p6 : P6 ,
29- p7 : P7 ,
120+ pub struct PGPIO8BitInterface < BUS , DC , WR > {
121+ bus : BUS ,
30122 dc : DC ,
31123 wr : WR ,
32- last : u8 ,
33124}
34125
35- impl < P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR >
36- PGPIO8BitInterface < P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR >
126+ impl < BUS , DC , WR > PGPIO8BitInterface < BUS , DC , WR >
37127where
38- P0 : OutputPin ,
39- P1 : OutputPin ,
40- P2 : OutputPin ,
41- P3 : OutputPin ,
42- P4 : OutputPin ,
43- P5 : OutputPin ,
44- P6 : OutputPin ,
45- P7 : OutputPin ,
128+ BUS : OutputBus < Word = u8 > ,
46129 DC : OutputPin ,
47130 WR : OutputPin ,
48131{
49132 /// Create new parallel GPIO interface for communication with a display driver
50- #[ allow( clippy:: too_many_arguments) ]
51- pub fn new (
52- p0 : P0 ,
53- p1 : P1 ,
54- p2 : P2 ,
55- p3 : P3 ,
56- p4 : P4 ,
57- p5 : P5 ,
58- p6 : P6 ,
59- p7 : P7 ,
60- dc : DC ,
61- wr : WR ,
62- ) -> Self {
63- Self {
64- p0,
65- p1,
66- p2,
67- p3,
68- p4,
69- p5,
70- p6,
71- p7,
72- dc,
73- wr,
74- last : 0 ,
75- }
133+ pub fn new ( bus : BUS , dc : DC , wr : WR ) -> Self {
134+ Self { bus, dc, wr }
76135 }
77136
78137 /// Consume the display interface and return
79- /// the GPIO pins used by it
80- pub fn release ( self ) -> ( P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR ) {
81- (
82- self . p0 , self . p1 , self . p2 , self . p3 , self . p4 , self . p5 , self . p6 , self . p7 , self . dc ,
83- self . wr ,
84- )
138+ /// the bus and GPIO pins used by it
139+ pub fn release ( self ) -> ( BUS , DC , WR ) {
140+ ( self . bus , self . dc , self . wr )
85141 }
86142
87143 fn set_value ( self : & mut Self , value : u8 ) -> Result < ( ) , DisplayError > {
88- let changed = value ^ self . last ;
89-
90- // It's quite common for multiple consecutive values to be identical, e.g. when filling or
91- // clearing the screen, so let's optimize for that case
92- if changed == 0 {
93- return Ok ( ( ) ) ;
94- }
95-
96- self . last = value;
97-
98- if changed & 1 != 0 {
99- if value & 1 != 0 {
100- self . p0 . set_high ( )
101- } else {
102- self . p0 . set_low ( )
103- }
104- . map_err ( |_| DisplayError :: BusWriteError ) ?
105- } ;
106-
107- if changed & 2 != 0 {
108- if value & 2 != 0 {
109- self . p1 . set_high ( )
110- } else {
111- self . p1 . set_low ( )
112- }
113- . map_err ( |_| DisplayError :: BusWriteError ) ?
114- } ;
115-
116- if changed & 4 != 0 {
117- if value & 4 != 0 {
118- self . p2 . set_high ( )
119- } else {
120- self . p2 . set_low ( )
121- }
122- . map_err ( |_| DisplayError :: BusWriteError ) ?
123- } ;
124-
125- if changed & 8 != 0 {
126- if value & 8 != 0 {
127- self . p3 . set_high ( )
128- } else {
129- self . p3 . set_low ( )
130- }
131- . map_err ( |_| DisplayError :: BusWriteError ) ?
132- } ;
133-
134- if changed & 16 != 0 {
135- if value & 16 != 0 {
136- self . p4 . set_high ( )
137- } else {
138- self . p4 . set_low ( )
139- }
140- . map_err ( |_| DisplayError :: BusWriteError ) ?
141- } ;
142-
143- if changed & 32 != 0 {
144- if value & 32 != 0 {
145- self . p5 . set_high ( )
146- } else {
147- self . p5 . set_low ( )
148- }
149- . map_err ( |_| DisplayError :: BusWriteError ) ?
150- } ;
151-
152- if changed & 64 != 0 {
153- if value & 64 != 0 {
154- self . p6 . set_high ( )
155- } else {
156- self . p6 . set_low ( )
157- }
158- . map_err ( |_| DisplayError :: BusWriteError ) ?
159- } ;
160-
161- if changed & 128 != 0 {
162- if value & 128 != 0 {
163- self . p7 . set_high ( )
164- } else {
165- self . p7 . set_low ( )
166- }
167- . map_err ( |_| DisplayError :: BusWriteError ) ?
168- } ;
169-
170- Ok ( ( ) )
144+ self . bus . set_value ( value)
171145 }
172146}
173147
174- impl < P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR > WriteOnlyDataCommand
175- for PGPIO8BitInterface < P0 , P1 , P2 , P3 , P4 , P5 , P6 , P7 , DC , WR >
148+ impl < BUS , DC , WR > WriteOnlyDataCommand for PGPIO8BitInterface < BUS , DC , WR >
176149where
177- P0 : OutputPin ,
178- P1 : OutputPin ,
179- P2 : OutputPin ,
180- P3 : OutputPin ,
181- P4 : OutputPin ,
182- P5 : OutputPin ,
183- P6 : OutputPin ,
184- P7 : OutputPin ,
150+ BUS : OutputBus < Word = u8 > ,
185151 DC : OutputPin ,
186152 WR : OutputPin ,
187153{
0 commit comments