88CircuitPython driver for Adafruit ePaper display breakouts
99* Author(s): Dean Miller
1010"""
11+ # pylint: disable=ungrouped-imports
1112
1213import time
1314from micropython import const
1415from digitalio import Direction
1516from adafruit_epd import mcp_sram
1617
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+
1728__version__ = "0.0.0+auto.0"
1829__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
1930
2031
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
2233 """Base class for EPD displays"""
2334
2435 BLACK = const (0 )
@@ -29,8 +40,16 @@ class Adafruit_EPD: # pylint: disable=too-many-instance-attributes, too-many-pu
2940 LIGHT = const (5 )
3041
3142 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
3453 self ._width = width
3554 self ._height = height
3655
@@ -76,7 +95,7 @@ def __init__(
7695 self ._black_inverted = self ._color_inverted = True
7796 self .hardware_reset ()
7897
79- def display (self ): # pylint: disable=too-many-branches
98+ def display (self ) -> None : # pylint: disable=too-many-branches
8099 """show the contents of the display buffer"""
81100 self .power_up ()
82101
@@ -149,15 +168,17 @@ def display(self): # pylint: disable=too-many-branches
149168
150169 self .update ()
151170
152- def hardware_reset (self ):
171+ def hardware_reset (self ) -> None :
153172 """If we have a reset pin, do a hardware reset by toggling it"""
154173 if self ._rst :
155174 self ._rst .value = False
156175 time .sleep (0.1 )
157176 self ._rst .value = True
158177 time .sleep (0.1 )
159178
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 :
161182 """Send command byte to display."""
162183 self ._cs .value = True
163184 self ._dc .value = False
@@ -176,7 +197,7 @@ def command(self, cmd, data=None, end=True):
176197
177198 return ret
178199
179- def _spi_transfer (self , data ) :
200+ def _spi_transfer (self , data : Union [ int , bytearray ]) -> Optional [ int ] :
180201 """Transfer one byte or bytearray, toggling the cs pin if required by the EPD chipset"""
181202 if isinstance (data , int ): # single byte!
182203 self ._spibuf [0 ] = data
@@ -203,30 +224,30 @@ def _spi_transfer(self, data):
203224 self ._spi_transfer (x )
204225 return None
205226
206- def power_up (self ):
227+ def power_up (self ) -> None :
207228 """Power up the display in preparation for writing RAM and updating.
208229 must be implemented in subclass"""
209230 raise NotImplementedError ()
210231
211- def power_down (self ):
232+ def power_down (self ) -> None :
212233 """Power down the display, must be implemented in subclass"""
213234 raise NotImplementedError ()
214235
215- def update (self ):
236+ def update (self ) -> None :
216237 """Update the display from internal memory, must be implemented in subclass"""
217238 raise NotImplementedError ()
218239
219- def write_ram (self , index ) :
240+ def write_ram (self , index : int ) -> None :
220241 """Send the one byte command for starting the RAM write process. Returns
221242 the byte read at the same time over SPI. index is the RAM buffer, can be
222243 0 or 1 for tri-color displays. must be implemented in subclass"""
223244 raise NotImplementedError ()
224245
225- def set_ram_address (self , x , y ) :
246+ def set_ram_address (self , x : int , y : int ) -> None :
226247 """Set the RAM address location, must be implemented in subclass"""
227248 raise NotImplementedError ()
228249
229- def set_black_buffer (self , index , inverted ) :
250+ def set_black_buffer (self , index : Union [ 0 , 1 ], inverted : bool ) -> None :
230251 """Set the index for the black buffer data (0 or 1) and whether its inverted"""
231252 if index == 0 :
232253 self ._blackframebuf = self ._framebuf1
@@ -236,7 +257,7 @@ def set_black_buffer(self, index, inverted):
236257 raise RuntimeError ("Buffer index must be 0 or 1" )
237258 self ._black_inverted = inverted
238259
239- def set_color_buffer (self , index , inverted ) :
260+ def set_color_buffer (self , index : Union [ 0 , 1 ], inverted : bool ) -> None :
240261 """Set the index for the color buffer data (0 or 1) and whether its inverted"""
241262 if index == 0 :
242263 self ._colorframebuf = self ._framebuf1
@@ -246,7 +267,12 @@ def set_color_buffer(self, index, inverted):
246267 raise RuntimeError ("Buffer index must be 0 or 1" )
247268 self ._color_inverted = inverted
248269
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 :
250276 black = getattr (self ._blackframebuf , func )
251277 red = getattr (self ._colorframebuf , func )
252278 if self ._blackframebuf is self ._colorframebuf : # monochrome
@@ -255,11 +281,11 @@ def _color_dup(self, func, args, color):
255281 black (* args , color = (color == Adafruit_EPD .BLACK ) != self ._black_inverted )
256282 red (* args , color = (color == Adafruit_EPD .RED ) != self ._color_inverted )
257283
258- def pixel (self , x , y , color ) :
284+ def pixel (self , x : int , y : int , color : int ) -> None :
259285 """draw a single pixel in the display buffer"""
260286 self ._color_dup ("pixel" , (x , y ), color )
261287
262- def fill (self , color ) :
288+ def fill (self , color : int ) -> None :
263289 """fill the screen with the passed color"""
264290 red_fill = ((color == Adafruit_EPD .RED ) != self ._color_inverted ) * 0xFF
265291 black_fill = ((color == Adafruit_EPD .BLACK ) != self ._black_inverted ) * 0xFF
@@ -271,21 +297,34 @@ def fill(self, color):
271297 self ._blackframebuf .fill (black_fill )
272298 self ._colorframebuf .fill (red_fill )
273299
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
275303 """draw a rectangle"""
276304 self ._color_dup ("rect" , (x , y , width , height ), color )
277305
278306 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
281309 """fill a rectangle with the passed color"""
282310 self ._color_dup ("fill_rect" , (x , y , width , height ), color )
283311
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
285315 """Draw a line from (x_0, y_0) to (x_1, y_1) in passed color"""
286316 self ._color_dup ("line" , (x_0 , y_0 , x_1 , y_1 ), color )
287317
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 :
289328 """Write text string at location (x, y) in given color, using font file"""
290329 if self ._blackframebuf is self ._colorframebuf : # monochrome
291330 self ._blackframebuf .text (
@@ -315,39 +354,51 @@ def text(self, string, x, y, color, *, font_name="font5x8.bin", size=1):
315354 )
316355
317356 @property
318- def width (self ):
357+ def width (self ) -> int :
319358 """The width of the display, accounting for rotation"""
320359 if self .rotation in (0 , 2 ):
321360 return self ._width
322361 return self ._height
323362
324363 @property
325- def height (self ):
364+ def height (self ) -> int :
326365 """The height of the display, accounting for rotation"""
327366 if self .rotation in (0 , 2 ):
328367 return self ._height
329368 return self ._width
330369
331370 @property
332- def rotation (self ):
371+ def rotation (self ) -> Union [ 0 , 1 , 2 , 3 ] :
333372 """The rotation of the display, can be one of (0, 1, 2, 3)"""
334373 return self ._framebuf1 .rotation
335374
336375 @rotation .setter
337- def rotation (self , val ) :
376+ def rotation (self , val : int ) -> None :
338377 self ._framebuf1 .rotation = val
339378 if self ._framebuf2 :
340379 self ._framebuf2 .rotation = val
341380
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 :
343388 """draw a horizontal line"""
344389 self .fill_rect (x , y , width , 1 , color )
345390
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 :
347398 """draw a vertical line"""
348399 self .fill_rect (x , y , 1 , height , color )
349400
350- def image (self , image ) :
401+ def image (self , image : Image ) -> None :
351402 """Set buffer to value of Python Imaging Library image. The image should
352403 be in RGB mode and a size equal to the display size.
353404 """
0 commit comments