@@ -6,182 +6,148 @@ use embedded_hal::digital::v2::OutputPin;
6
6
7
7
pub use display_interface:: { DataFormat , DisplayError , WriteOnlyDataCommand } ;
8
8
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
+
9
111
/// Parallel 8 Bit communication interface
10
112
///
11
113
/// 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
16
115
/// `OutputPin` for the data/command selection and one `OutputPin` for the write-enable flag.
17
116
///
18
117
/// All pins are supposed to be high-active, high for the D/C pin meaning "data" and the
19
118
/// write-enable being pulled low before the setting of the bits and supposed to be sampled at a
20
119
/// 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 ,
30
122
dc : DC ,
31
123
wr : WR ,
32
- last : u8 ,
33
124
}
34
125
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 >
37
127
where
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 > ,
46
129
DC : OutputPin ,
47
130
WR : OutputPin ,
48
131
{
49
132
/// 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 }
76
135
}
77
136
78
137
/// 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 )
85
141
}
86
142
87
143
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)
171
145
}
172
146
}
173
147
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 >
176
149
where
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 > ,
185
151
DC : OutputPin ,
186
152
WR : OutputPin ,
187
153
{
0 commit comments