55
55
56
56
from adafruit_bus_device .i2c_device import I2CDevice
57
57
58
+ try :
59
+ from typing import TYPE_CHECKING , List , Tuple
60
+
61
+ if TYPE_CHECKING :
62
+ from circuitpython_typing import ReadableBuffer
63
+ import busio
64
+ except ImportError as e :
65
+ pass
66
+
58
67
__version__ = "0.0.0+auto.0"
59
68
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731.git"
60
69
@@ -89,17 +98,18 @@ class IS31FL3731:
89
98
90
99
:param ~busio.I2C i2c: the connected i2c bus i2c_device
91
100
:param int address: the device address; defaults to 0x74
101
+ :param int frames: static 0 or animation frames (0-7)
92
102
"""
93
103
94
- width = 16
95
- height = 9
104
+ width : int = 16
105
+ height : int = 9
96
106
97
- def __init__ (self , i2c , address = 0x74 , frames = None ):
107
+ def __init__ (self , i2c : busio . I2C , address : int = 0x74 , frames : int = None ) -> None :
98
108
self .i2c_device = I2CDevice (i2c , address )
99
109
self ._frame = None
100
110
self ._init (frames = frames )
101
111
102
- def _i2c_read_reg (self , reg , result ) :
112
+ def _i2c_read_reg (self , reg : int = None , result : bytes = None ) -> bytes :
103
113
# Read a buffer of data from the specified 8-bit I2C register address.
104
114
# The provided result parameter will be filled to capacity with bytes
105
115
# of data read from the register.
@@ -108,36 +118,40 @@ def _i2c_read_reg(self, reg, result):
108
118
return result
109
119
return None
110
120
111
- def _i2c_write_reg (self , reg , data ) :
121
+ def _i2c_write_reg (self , reg : int = None , data : bytes = None ) -> bytes :
112
122
# Write a contiguous block of data (bytearray) starting at the
113
123
# specified I2C register address (register passed as argument).
114
124
self ._i2c_write_block (bytes ([reg ]) + data )
115
125
116
- def _i2c_write_block (self , data ) :
126
+ def _i2c_write_block (self , data : bytes = None ) -> bytes :
117
127
# Write a buffer of data (byte array) to the specified I2C register
118
128
# address.
119
129
with self .i2c_device as i2c :
120
130
i2c .write (data )
121
131
122
- def _bank (self , bank = None ):
132
+ def _bank (self , bank : int = None ) -> int :
123
133
if bank is None :
124
134
result = bytearray (1 )
125
135
return self ._i2c_read_reg (_BANK_ADDRESS , result )[0 ]
126
136
self ._i2c_write_reg (_BANK_ADDRESS , bytearray ([bank ]))
127
137
return None
128
138
129
- def _register (self , bank , register , value = None ):
139
+ def _register (
140
+ self , bank : int = None , register : int = None , value : int = None
141
+ ) -> int :
130
142
self ._bank (bank )
131
143
if value is None :
132
144
result = bytearray (1 )
145
+ print (f"Register: { result } " )
133
146
return self ._i2c_read_reg (register , result )[0 ]
134
147
self ._i2c_write_reg (register , bytearray ([value ]))
135
148
return None
136
149
137
150
def _mode (self , mode = None ):
151
+ """Function for setting _register mode"""
138
152
return self ._register (_CONFIG_BANK , _MODE_REGISTER , mode )
139
153
140
- def _init (self , frames = None ) :
154
+ def _init (self , frames : int = 0 ) -> int :
141
155
self .sleep (True )
142
156
# Clear config; sets to Picture Mode, no audio sync, maintains sleep
143
157
self ._bank (_CONFIG_BANK )
@@ -160,15 +174,15 @@ def reset(self):
160
174
time .sleep (0.01 ) # 10 MS pause to reset.
161
175
self .sleep (False )
162
176
163
- def sleep (self , value ):
177
+ def sleep (self , value : bool = False ):
164
178
"""
165
179
Set the Software Shutdown Register bit
166
180
167
181
:param value: True to set software shutdown bit; False unset
168
182
"""
169
183
return self ._register (_CONFIG_BANK , _SHUTDOWN_REGISTER , not value )
170
184
171
- def autoplay (self , delay = 0 , loops = 0 , frames = 0 ) :
185
+ def autoplay (self , delay : float = 0.0 , loops : int = 0 , frames : int = 0 ) -> int :
172
186
"""
173
187
Start autoplay
174
188
@@ -190,15 +204,15 @@ def autoplay(self, delay=0, loops=0, frames=0):
190
204
self ._register (_CONFIG_BANK , _AUTOPLAY2_REGISTER , delay % 64 )
191
205
self ._mode (_AUTOPLAY_MODE | self ._frame )
192
206
193
- def fade (self , fade_in = None , fade_out = None , pause = 0 ) :
207
+ def fade (self , fade_in : int = None , fade_out : int = None , pause : int = 0 ) -> int :
194
208
"""
195
209
Start and stop the fade feature. If both fade_in and fade_out are None (the
196
210
default), the breath feature is used for fading. if fade_in is None, then
197
211
fade_in = fade_out. If fade_out is None, then fade_out = fade_in
198
212
199
- :param fade_in: positive number; 0->100
200
- :param fade-out: positive number; 0->100
201
- :param pause: breath register 2 pause value
213
+ :param fade_in: int positive number; 0->100
214
+ :param fade-out: int positive number; 0->100
215
+ :param pause: int breath register 2 pause value
202
216
"""
203
217
if fade_in is None and fade_out is None :
204
218
self ._register (_CONFIG_BANK , _BREATH2_REGISTER , 0 )
@@ -223,12 +237,12 @@ def fade(self, fade_in=None, fade_out=None, pause=0):
223
237
self ._register (_CONFIG_BANK , _BREATH1_REGISTER , fade_out << 4 | fade_in )
224
238
self ._register (_CONFIG_BANK , _BREATH2_REGISTER , 1 << 4 | pause )
225
239
226
- def frame (self , frame = None , show = True ):
240
+ def frame (self , frame : int = None , show : bool = True ) -> int :
227
241
"""
228
242
Set the current frame
229
243
230
- :param frame: frame number; 0-7 or None. If None function returns current frame
231
- :param show: True to show the frame; False to not show.
244
+ :param frame: int frame number; 0-7 or None. If None function returns current frame
245
+ :param show: bool True to show the frame; False to not show.
232
246
"""
233
247
if frame is None :
234
248
return self ._frame
@@ -239,11 +253,17 @@ def frame(self, frame=None, show=True):
239
253
self ._register (_CONFIG_BANK , _FRAME_REGISTER , frame )
240
254
return None
241
255
242
- def audio_sync (self , value = None ):
256
+ def audio_sync (self , value : int = None ) -> int :
243
257
"""Set the audio sync feature register"""
244
258
return self ._register (_CONFIG_BANK , _AUDIOSYNC_REGISTER , value )
245
259
246
- def audio_play (self , sample_rate , audio_gain = 0 , agc_enable = False , agc_fast = False ):
260
+ def audio_play (
261
+ self ,
262
+ sample_rate : int = 0 ,
263
+ audio_gain : int = 0 ,
264
+ agc_enable : bool = False ,
265
+ agc_fast : bool = False ,
266
+ ) -> int :
247
267
"""Controls the audio play feature"""
248
268
if sample_rate == 0 :
249
269
self ._mode (_PICTURE_MODE )
@@ -262,7 +282,7 @@ def audio_play(self, sample_rate, audio_gain=0, agc_enable=False, agc_fast=False
262
282
)
263
283
self ._mode (_AUDIOPLAY_MODE )
264
284
265
- def blink (self , rate = None ):
285
+ def blink (self , rate : int = None ) -> int :
266
286
"""Updates the blink register"""
267
287
# pylint: disable=no-else-return
268
288
# This needs to be refactored when it can be tested
@@ -275,13 +295,13 @@ def blink(self, rate=None):
275
295
self ._register (_CONFIG_BANK , _BLINK_REGISTER , rate & 0x07 | 0x08 )
276
296
return None
277
297
278
- def fill (self , color = None , blink = None , frame = None ) :
298
+ def fill (self , color : int = None , blink : bool = False , frame : int = 0 ) -> int :
279
299
"""
280
300
Fill the display with a brightness level
281
301
282
302
:param color: brightness 0->255
283
- :param blink: True if blinking is required
284
- :param frame: which frame to fill 0->7
303
+ :param blink: bool True to blink
304
+ :param frame: int the frame to set the pixel, default 0
285
305
"""
286
306
if frame is None :
287
307
frame = self ._frame
@@ -306,30 +326,66 @@ def pixel_addr(x, y):
306
326
return x + y * 16
307
327
308
328
# pylint: disable-msg=too-many-arguments
309
- def pixel (self , x , y , color = None , blink = None , frame = None ):
329
+ def pixel (
330
+ self ,
331
+ x : int ,
332
+ y : int ,
333
+ color : int = 255 ,
334
+ blink : bool = False ,
335
+ frame : int = 0 ,
336
+ rotate : int = 0 ,
337
+ ):
310
338
"""
311
- Blink or brightness for x-, y-pixel
312
-
313
- :param x: horizontal pixel position
314
- :param y: vertical pixel position
315
- :param color: brightness value 0->255
316
- :param blink: True to blink
317
- :param frame: the frame to set the pixel
339
+ Matrix display configuration
340
+
341
+ :param x: int horizontal pixel position
342
+ :param y: int vertical pixel position
343
+ :param color: int brightness value 0->255
344
+ :param blink: bool True to blink
345
+ :param frame: int the frame to set the pixel, default 0
346
+ :param rotate: int display rotation (0, 90, 180, 270)
318
347
"""
319
- if not 0 <= x <= self .width :
320
- return None
321
- if not 0 <= y <= self .height :
322
- return None
323
- pixel = self .pixel_addr (x , y )
348
+
349
+ if rotate not in (0 , 90 , 180 , 270 ):
350
+ raise ValueError ("Rotation must be 0, 90, 180, or 270 degrees" )
351
+
352
+ if rotate == 0 :
353
+ if not 0 <= x <= self .width :
354
+ return None
355
+ if not 0 <= y <= self .height :
356
+ return None
357
+ pixel = self .pixel_addr (x , y )
358
+ elif rotate == 90 :
359
+ if not 0 <= y <= self .width :
360
+ return None
361
+ if not 0 <= x <= self .height :
362
+ return None
363
+ pixel = self .pixel_addr (y , self .height - x - 1 )
364
+ elif rotate == 180 :
365
+ if not 0 <= x <= self .width :
366
+ return None
367
+ if not 0 <= y <= self .height :
368
+ return None
369
+ pixel = self .pixel_addr (self .width - x - 1 , self .height - y - 1 )
370
+ elif rotate == 270 :
371
+ if not 0 <= y <= self .width :
372
+ return None
373
+ if not 0 <= x <= self .height :
374
+ return None
375
+ pixel = self .pixel_addr (self .width - y - 1 , x )
376
+
324
377
if color is None and blink is None :
325
378
return self ._register (self ._frame , pixel )
379
+ # frames other than 0 only used in animation. allow None.
326
380
if frame is None :
327
381
frame = self ._frame
382
+ # Brightness
328
383
if color is not None :
329
384
if not 0 <= color <= 255 :
330
- raise ValueError ("Color out of range" )
385
+ raise ValueError ("Brightness or Color out of range (0-255) " )
331
386
self ._register (frame , _COLOR_OFFSET + pixel , color )
332
- if blink is not None :
387
+ # Blink works but not well while animated
388
+ if blink :
333
389
addr , bit = divmod (pixel , 8 )
334
390
bits = self ._register (frame , _BLINK_OFFSET + addr )
335
391
if blink :
@@ -341,13 +397,13 @@ def pixel(self, x, y, color=None, blink=None, frame=None):
341
397
342
398
# pylint: enable-msg=too-many-arguments
343
399
344
- def image (self , img , blink = None , frame = None ) :
400
+ def image (self , img : bytes = None , blink : bool = False , frame : int = 0 ) -> bytes :
345
401
"""Set buffer to value of Python Imaging Library image. The image should
346
402
be in 8-bit mode (L) and a size equal to the display size.
347
403
348
404
:param img: Python Imaging Library image
349
405
:param blink: True to blink
350
- :param frame: the frame to set the image
406
+ :param frame: the frame to set the image, default 0
351
407
"""
352
408
if img .mode != "L" :
353
409
raise ValueError ("Image must be in mode L." )
0 commit comments