8
8
CircuitPython driver for Adafruit ePaper display breakouts
9
9
* Author(s): Dean Miller
10
10
"""
11
+ # pylint: disable=ungrouped-imports
11
12
12
13
import time
13
14
from micropython import const
14
15
from digitalio import Direction
15
16
from adafruit_epd import mcp_sram
16
17
18
+ try :
19
+ """Needed for type annotations"""
20
+ from typing import Any , Union , Callable , Optional
21
+ from busio import SPI
22
+ from digitalio import DigitalInOut
23
+ from circuitpython_typing .pil import Image
24
+
25
+ except ImportError :
26
+ pass
27
+
17
28
__version__ = "0.0.0+auto.0"
18
29
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
19
30
20
31
21
- class Adafruit_EPD : # pylint: disable=too-many-instance-attributes, too-many-public-methods
32
+ class Adafruit_EPD : # pylint: disable=too-many-instance-attributes, too-many-public-methods, too-many-arguments
22
33
"""Base class for EPD displays"""
23
34
24
35
BLACK = const (0 )
@@ -29,8 +40,16 @@ class Adafruit_EPD: # pylint: disable=too-many-instance-attributes, too-many-pu
29
40
LIGHT = const (5 )
30
41
31
42
def __init__ (
32
- self , width , height , spi , cs_pin , dc_pin , sramcs_pin , rst_pin , busy_pin
33
- ): # pylint: disable=too-many-arguments
43
+ self ,
44
+ width : int ,
45
+ height : int ,
46
+ spi : SPI ,
47
+ cs_pin : DigitalInOut ,
48
+ dc_pin : DigitalInOut ,
49
+ sramcs_pin : DigitalInOut ,
50
+ rst_pin : DigitalInOut ,
51
+ busy_pin : DigitalInOut ,
52
+ ) -> None : # pylint: disable=too-many-arguments
34
53
self ._width = width
35
54
self ._height = height
36
55
@@ -76,7 +95,7 @@ def __init__(
76
95
self ._black_inverted = self ._color_inverted = True
77
96
self .hardware_reset ()
78
97
79
- def display (self ): # pylint: disable=too-many-branches
98
+ def display (self ) -> None : # pylint: disable=too-many-branches
80
99
"""show the contents of the display buffer"""
81
100
self .power_up ()
82
101
@@ -149,15 +168,17 @@ def display(self): # pylint: disable=too-many-branches
149
168
150
169
self .update ()
151
170
152
- def hardware_reset (self ):
171
+ def hardware_reset (self ) -> None :
153
172
"""If we have a reset pin, do a hardware reset by toggling it"""
154
173
if self ._rst :
155
174
self ._rst .value = False
156
175
time .sleep (0.1 )
157
176
self ._rst .value = True
158
177
time .sleep (0.1 )
159
178
160
- def command (self , cmd , data = None , end = True ):
179
+ def command (
180
+ self , cmd : int , data : Optional [bytearray ] = None , end : bool = True
181
+ ) -> int :
161
182
"""Send command byte to display."""
162
183
self ._cs .value = True
163
184
self ._dc .value = False
@@ -176,7 +197,7 @@ def command(self, cmd, data=None, end=True):
176
197
177
198
return ret
178
199
179
- def _spi_transfer (self , data ) :
200
+ def _spi_transfer (self , data : Union [ int , bytearray ]) -> Optional [ int ] :
180
201
"""Transfer one byte or bytearray, toggling the cs pin if required by the EPD chipset"""
181
202
if isinstance (data , int ): # single byte!
182
203
self ._spibuf [0 ] = data
@@ -203,30 +224,30 @@ def _spi_transfer(self, data):
203
224
self ._spi_transfer (x )
204
225
return None
205
226
206
- def power_up (self ):
227
+ def power_up (self ) -> None :
207
228
"""Power up the display in preparation for writing RAM and updating.
208
229
must be implemented in subclass"""
209
230
raise NotImplementedError ()
210
231
211
- def power_down (self ):
232
+ def power_down (self ) -> None :
212
233
"""Power down the display, must be implemented in subclass"""
213
234
raise NotImplementedError ()
214
235
215
- def update (self ):
236
+ def update (self ) -> None :
216
237
"""Update the display from internal memory, must be implemented in subclass"""
217
238
raise NotImplementedError ()
218
239
219
- def write_ram (self , index ) :
240
+ def write_ram (self , index : int ) -> None :
220
241
"""Send the one byte command for starting the RAM write process. Returns
221
242
the byte read at the same time over SPI. index is the RAM buffer, can be
222
243
0 or 1 for tri-color displays. must be implemented in subclass"""
223
244
raise NotImplementedError ()
224
245
225
- def set_ram_address (self , x , y ) :
246
+ def set_ram_address (self , x : int , y : int ) -> None :
226
247
"""Set the RAM address location, must be implemented in subclass"""
227
248
raise NotImplementedError ()
228
249
229
- def set_black_buffer (self , index , inverted ) :
250
+ def set_black_buffer (self , index : Union [ 0 , 1 ], inverted : bool ) -> None :
230
251
"""Set the index for the black buffer data (0 or 1) and whether its inverted"""
231
252
if index == 0 :
232
253
self ._blackframebuf = self ._framebuf1
@@ -236,7 +257,7 @@ def set_black_buffer(self, index, inverted):
236
257
raise RuntimeError ("Buffer index must be 0 or 1" )
237
258
self ._black_inverted = inverted
238
259
239
- def set_color_buffer (self , index , inverted ) :
260
+ def set_color_buffer (self , index : Union [ 0 , 1 ], inverted : bool ) -> None :
240
261
"""Set the index for the color buffer data (0 or 1) and whether its inverted"""
241
262
if index == 0 :
242
263
self ._colorframebuf = self ._framebuf1
@@ -246,7 +267,12 @@ def set_color_buffer(self, index, inverted):
246
267
raise RuntimeError ("Buffer index must be 0 or 1" )
247
268
self ._color_inverted = inverted
248
269
249
- def _color_dup (self , func , args , color ):
270
+ def _color_dup (
271
+ self ,
272
+ func : Callable ,
273
+ args : Any ,
274
+ color : Union [0 , 1 , 2 , 3 , 4 , 5 ],
275
+ ) -> None :
250
276
black = getattr (self ._blackframebuf , func )
251
277
red = getattr (self ._colorframebuf , func )
252
278
if self ._blackframebuf is self ._colorframebuf : # monochrome
@@ -255,11 +281,11 @@ def _color_dup(self, func, args, color):
255
281
black (* args , color = (color == Adafruit_EPD .BLACK ) != self ._black_inverted )
256
282
red (* args , color = (color == Adafruit_EPD .RED ) != self ._color_inverted )
257
283
258
- def pixel (self , x , y , color ) :
284
+ def pixel (self , x : int , y : int , color : int ) -> None :
259
285
"""draw a single pixel in the display buffer"""
260
286
self ._color_dup ("pixel" , (x , y ), color )
261
287
262
- def fill (self , color ) :
288
+ def fill (self , color : int ) -> None :
263
289
"""fill the screen with the passed color"""
264
290
red_fill = ((color == Adafruit_EPD .RED ) != self ._color_inverted ) * 0xFF
265
291
black_fill = ((color == Adafruit_EPD .BLACK ) != self ._black_inverted ) * 0xFF
@@ -271,21 +297,34 @@ def fill(self, color):
271
297
self ._blackframebuf .fill (black_fill )
272
298
self ._colorframebuf .fill (red_fill )
273
299
274
- def rect (self , x , y , width , height , color ): # pylint: disable=too-many-arguments
300
+ def rect (
301
+ self , x : int , y : int , width : int , height : int , color : int
302
+ ) -> None : # pylint: disable=too-many-arguments
275
303
"""draw a rectangle"""
276
304
self ._color_dup ("rect" , (x , y , width , height ), color )
277
305
278
306
def fill_rect (
279
- self , x , y , width , height , color
280
- ): # pylint: disable=too-many-arguments
307
+ self , x : int , y : int , width : int , height : int , color : int
308
+ ) -> None : # pylint: disable=too-many-arguments
281
309
"""fill a rectangle with the passed color"""
282
310
self ._color_dup ("fill_rect" , (x , y , width , height ), color )
283
311
284
- def line (self , x_0 , y_0 , x_1 , y_1 , color ): # pylint: disable=too-many-arguments
312
+ def line (
313
+ self , x_0 : int , y_0 : int , x_1 : int , y_1 : int , color : int
314
+ ) -> None : # pylint: disable=too-many-arguments
285
315
"""Draw a line from (x_0, y_0) to (x_1, y_1) in passed color"""
286
316
self ._color_dup ("line" , (x_0 , y_0 , x_1 , y_1 ), color )
287
317
288
- def text (self , string , x , y , color , * , font_name = "font5x8.bin" , size = 1 ):
318
+ def text (
319
+ self ,
320
+ string : str ,
321
+ x : int ,
322
+ y : int ,
323
+ color : int ,
324
+ * ,
325
+ font_name : str = "font5x8.bin" ,
326
+ size : int = 1
327
+ ) -> None :
289
328
"""Write text string at location (x, y) in given color, using font file"""
290
329
if self ._blackframebuf is self ._colorframebuf : # monochrome
291
330
self ._blackframebuf .text (
@@ -315,39 +354,51 @@ def text(self, string, x, y, color, *, font_name="font5x8.bin", size=1):
315
354
)
316
355
317
356
@property
318
- def width (self ):
357
+ def width (self ) -> int :
319
358
"""The width of the display, accounting for rotation"""
320
359
if self .rotation in (0 , 2 ):
321
360
return self ._width
322
361
return self ._height
323
362
324
363
@property
325
- def height (self ):
364
+ def height (self ) -> int :
326
365
"""The height of the display, accounting for rotation"""
327
366
if self .rotation in (0 , 2 ):
328
367
return self ._height
329
368
return self ._width
330
369
331
370
@property
332
- def rotation (self ):
371
+ def rotation (self ) -> Union [ 0 , 1 , 2 , 3 ] :
333
372
"""The rotation of the display, can be one of (0, 1, 2, 3)"""
334
373
return self ._framebuf1 .rotation
335
374
336
375
@rotation .setter
337
- def rotation (self , val ) :
376
+ def rotation (self , val : int ) -> None :
338
377
self ._framebuf1 .rotation = val
339
378
if self ._framebuf2 :
340
379
self ._framebuf2 .rotation = val
341
380
342
- def hline (self , x , y , width , color ):
381
+ def hline (
382
+ self ,
383
+ x : int ,
384
+ y : int ,
385
+ width : int ,
386
+ color : int ,
387
+ ) -> None :
343
388
"""draw a horizontal line"""
344
389
self .fill_rect (x , y , width , 1 , color )
345
390
346
- def vline (self , x , y , height , color ):
391
+ def vline (
392
+ self ,
393
+ x : int ,
394
+ y : int ,
395
+ height : int ,
396
+ color : int ,
397
+ ) -> None :
347
398
"""draw a vertical line"""
348
399
self .fill_rect (x , y , 1 , height , color )
349
400
350
- def image (self , image ) :
401
+ def image (self , image : Image ) -> None :
351
402
"""Set buffer to value of Python Imaging Library image. The image should
352
403
be in RGB mode and a size equal to the display size.
353
404
"""
0 commit comments