16 # Don't import pillow if we're running in the CI. We could mock it out but that
17 # would require mocking in all reverse dependencies.
18 if "GITHUB_ACTION" not in os.environ and "READTHEDOCS" not in os.environ:
19 # This will only work on Linux
22 # this would be for Github Actions
23 utils = None # pylint: disable=invalid-name
25 __version__ = "0.0.0-auto.0"
26 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
31 class _DisplayioSingleton():
35 def release_displays():
36 """Releases any actively used displays so their busses and pins can be used again. This will also release the builtin display on boards that have one. You will need to reinitialize it yourself afterwards.
38 Use this once in your code.py if you initialize a display. Place it right before the initialization so the display is active as long as possible.
44 """Stores values of a certain size in a 2D array"""
45 def __init__(self, width, height, value_count):
46 """Create a Bitmap object with the given fixed size. Each pixel stores a value that is used to index into a corresponding palette. This enables differently colored sprites to share the underlying Bitmap. value_count is used to minimize the memory used to store the Bitmap.
50 def __getitem__(self, index):
52 Returns the value at the given index. The index can either be
53 an x,y tuple or an int equal to `y * width + x`.
57 def __setitem__(self, index, value):
59 Sets the value at the given index. The index can either be
60 an x,y tuple or an int equal to `y * width + x`.
64 def fill(self, value):
65 """Fills the bitmap with the supplied palette index value."""
70 """Width of the bitmap. (read only)"""
75 """Height of the bitmap. (read only)"""
80 """Converts one color format to another."""
82 """Create a ColorConverter object to convert color formats.
83 Only supports RGB888 to RGB565 currently.
87 def convert(self, color):
88 "Converts the given RGB888 color to RGB565"
93 "When true the color converter dithers the output by adding random noise when truncating to display bitdepth"
97 def dither(self, value):
98 if not isinstance(value, bool):
99 raise ValueError("Value should be boolean")
104 """This initializes a display and connects it into CircuitPython. Unlike other objects in CircuitPython, Display objects live until ``displayio.release_displays()`` is called. This is done so that CircuitPython can use the display itself.
106 Most people should not use this class directly. Use a specific display driver instead that will contain the initialization sequence at minimum.
108 .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, bytes_per_cell=1, reverse_pixels_in_byte=False, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False, auto_refresh=True, native_frames_per_second=60)
111 def __init__(self, display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, bytes_per_cell=1, reverse_pixels_in_byte=False, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False, auto_refresh=True, native_frames_per_second=60):
112 """Create a Display object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
114 The ``init_sequence`` is bitpacked to minimize the ram impact. Every command begins with a command byte followed by a byte to determine the parameter count and if a delay is need after. When the top bit of the second byte is 1, the next byte will be the delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay byte. The third through final bytes are the remaining command parameters. The next byte will begin a new command definition. Here is a portion of ILI9341 init code:
115 .. code-block:: python
117 init_sequence = (b"\xe1\x0f\x00\x0E\x14\x03\x11\x07\x31\xC1\x48\x08\x0F\x0C\x31\x36\x0F" # Set Gamma
118 b"\x11\x80\x78"# Exit Sleep then delay 0x78 (120ms)
119 b"\x29\x80\x78"# Display on then delay 0x78 (120ms)
121 display = displayio.Display(display_bus, init_sequence, width=320, height=240)
123 The first command is 0xe1 with 15 (0xf) parameters following. The second and third are 0x11 and 0x29 respectively with delays (0x80) of 120ms (0x78) and no parameters. Multiple byte literals (b”“) are merged together on load. The parens are needed to allow byte literals on subsequent lines.
125 The initialization sequence should always leave the display memory access inline with the scan of the display to minimize tearing artifacts.
127 self._display_bus = display_bus
128 self._set_column_command=0x2a
129 self._set_row_command=0x2b
130 self._write_ram_command=0x2c
131 self._brightness_command=brightness_command
132 self._data_as_commands = data_as_commands
133 self._single_byte_bounds = single_byte_bounds
135 while i < len(init_sequence):
136 command = bytes([init_sequence[i]])
137 data_size = init_sequence[i + 1]
138 delay = (data_size & 0x80) > 0
140 data_byte = init_sequence[i + 2]
141 if (self._single_byte_bounds):
142 data = command + init_sequence[i + 2:i + 2 + data_size]
143 display_bus.send(True, data, toggle_every_byte=True)
145 display_bus.send(True, command, toggle_every_byte=True)
147 display_bus.send(False, init_sequence[i + 2:i + 2 + data_size])
151 delay_time_ms = init_sequence[i + 1 + data_size]
152 if (delay_time_ms == 255):
154 time.sleep(delay_time_ms / 1000)
157 def show(self, group):
158 """Switches to displaying the given group of layers. When group is None, the default CircuitPython terminal will be shown.
162 def refresh(self, *, target_frames_per_second=60, minimum_frames_per_second=1):
163 """When auto refresh is off, waits for the target frame rate and then refreshes the display, returning True. If the call has taken too long since the last refresh call for the given target frame rate, then the refresh returns False immediately without updating the screen to hopefully help getting caught up.
165 If the time since the last successful refresh is below the minimum frame rate, then an exception will be raised. Set minimum_frames_per_second to 0 to disable.
167 When auto refresh is on, updates the display immediately. (The display will also update without calls to this.)
171 def fill_row(self, y, buffer):
175 def auto_refresh(self):
179 def auto_refresh(self, value):
183 def brightness(self):
184 """The brightness of the display as a float. 0.0 is off and 1.0 is full `brightness`. When `auto_brightness` is True, the value of `brightness` will change automatically. If `brightness` is set, `auto_brightness` will be disabled and will be set to False.
189 def brightness(self, value):
193 def auto_brightness(self):
194 """True when the display brightness is adjusted automatically, based on an ambient light sensor or other method. Note that some displays may have this set to True by default, but not actually implement automatic brightness adjustment. `auto_brightness` is set to False if `brightness` is set manually.
198 @auto_brightness.setter
199 def auto_brightness(self, value):
212 """The rotation of the display as an int in degrees."""
216 def rotation(self, value):
225 def __init__(self, display_bus, start_sequence, stop_sequence, *, width, height, ram_width, ram_height, colstart=0, rowstart=0, rotation=0, set_column_window_command=None, set_row_window_command=None, single_byte_bounds=False, write_black_ram_command, black_bits_inverted=False, write_color_ram_command=None, color_bits_inverted=False, highlight_color=0x000000, refresh_display_command, refresh_time=40, busy_pin=None, busy_state=True, seconds_per_frame=180, always_toggle_chip_select=False):
227 Create a EPaperDisplay object on the given display bus (displayio.FourWire or displayio.ParallelBus).
229 The start_sequence and stop_sequence are bitpacked to minimize the ram impact. Every command begins with a command byte followed by a byte to determine the parameter count and if a delay is need after. When the top bit of the second byte is 1, the next byte will be the delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay byte. The third through final bytes are the remaining command parameters. The next byte will begin a new command definition.
233 def show(self, group):
234 """Switches to displaying the given group of layers. When group is None, the default CircuitPython terminal will be shown.
239 """Refreshes the display immediately or raises an exception if too soon. Use ``time.sleep(display.time_to_refresh)`` to sleep until a refresh can occur.
243 def time_to_refresh(self):
244 """Time, in fractional seconds, until the ePaper display can be refreshed."""
261 """Manage updating a display over SPI four wire protocol in the background while
262 Python code runs. It doesn’t handle display initialization.
264 def __init__(self, spi_bus, *, command, chip_select, reset=None, baudrate=24000000, polarity=0, phase=0):
265 """Create a FourWire object associated with the given pins.
267 The SPI bus and pins are then in use by the display until displayio.release_displays() is called even after a reload. (It does this so CircuitPython can use the display after your code is done.) So, the first time you initialize a display bus in code.py you should call :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
269 self._dc = digitalio.DigitalInOut(command)
270 self._dc.switch_to_output()
271 self.chip_select = digitalio.DigitalInOut(chip_select)
272 self.chip_select.switch_to_output(value=True)
274 if reset is not None:
275 self._reset = digitalio.DigitalInOut(reset)
276 self._reset.switch_to_output(value=True)
280 while self._spi.try_lock():
282 self._spi.configure(baudrate=baudrate, polarity=polarity, phase=phase)
286 if self._reset is not None:
292 def send(self, command, data, *, toggle_every_byte=False):
293 while self._spi.try_lock():
295 self._dc.value = not command
296 if (toggle_every_byte):
298 self._spi.write(bytes([byte]))
299 self.chip_select.value = True
301 self.chip_select.value = False
303 self._spi.write(data)
307 """Manage a group of sprites and groups and how they are inter-related."""
308 def __init__(self, *, max_size=4, scale=1, x=0, y=0):
309 """Create a Group of a given size and scale. Scale is in
310 one dimension. For example, scale=2 leads to a layer’s
311 pixel being 2x2 pixels when in the group.
315 def append(self, layer):
316 """Append a layer to the group. It will be drawn
321 def insert(self, index, layer):
322 """Insert a layer into the group."""
325 def index(self, layer):
326 """Returns the index of the first copy of layer.
327 Raises ValueError if not found.
331 def pop(self, index=-1):
332 """Remove the ith item and return it."""
335 def remove(self, layer):
336 """Remove the first copy of layer. Raises ValueError
337 if it is not present."""
341 """Returns the number of layers in a Group"""
344 def __getitem__(self, index):
345 """Returns the value at the given index."""
348 def __setitem__(self, index, value):
349 """Sets the value at the given index."""
352 def __delitem__(self, index):
353 """Deletes the value at the given index."""
361 def hidden(self, value):
369 def scale(self, value):
390 """Manage updating a display over I2C in the background while Python code runs. It doesn’t handle display initialization.
392 def __init__(self, i2c_bus, *, device_address, reset=None):
393 """Create a I2CDisplay object associated with the given I2C bus and reset pin.
395 The I2C bus and pins are then in use by the display until displayio.release_displays() is called even after a reload. (It does this so CircuitPython can use the display after your code is done.) So, the first time you initialize a display bus in code.py you should call :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
402 def send(self, command, data):
406 class OnDisplayBitmap:
408 Loads values straight from disk. This minimizes memory use but can lead to much slower pixel load times.
409 These load times may result in frame tearing where only part of the image is visible."""
410 def __init__(self, file):
415 """Width of the bitmap. (read only)"""
420 """Height of the bitmap. (read only)"""
425 """Map a pixel palette_index to a full color. Colors are transformed to the display’s format internally to save memory."""
426 def __init__(self, color_count):
427 """Create a Palette object to store a set number of colors."""
431 """Returns the number of colors in a Palette"""
434 def __setitem__(self, index, value):
435 """Sets the pixel color at the given index. The index should be an integer in the range 0 to color_count-1.
437 The value argument represents a color, and can be from 0x000000 to 0xFFFFFF (to represent an RGB value). Value can be an int, bytes (3 bytes (RGB) or 4 bytes (RGB + pad byte)), bytearray, or a tuple or list of 3 integers.
441 def make_transparent(self, palette_index):
444 def make_opaque(self, palette_index):
449 """Manage updating a display over 8-bit parallel bus in the background while Python code runs.
450 This protocol may be refered to as 8080-I Series Parallel Interface in datasheets.
451 It doesn’t handle display initialization.
453 def __init__(self, i2c_bus, *, device_address, reset=None):
454 """Create a ParallelBus object associated with the given pins. The bus is inferred from data0 by implying the next 7 additional pins on a given GPIO port.
456 The parallel bus and pins are then in use by the display until displayio.release_displays() is called even after a reload. (It does this so CircuitPython can use the display after your code is done.) So, the first time you initialize a display bus in code.py you should call :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
461 """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin is available.
465 def send(self, command, data):
466 """Sends the given command value followed by the full set of data. Display state, such as
467 vertical scroll, set via ``send`` may or may not be reset once the code is done.
473 """Create a Shape object with the given fixed size. Each pixel is one bit and is stored by the column
474 boundaries of the shape on each row. Each row’s boundary defaults to the full row.
476 def __init__(self, width, height, *, mirror_x=False, mirror_y=False):
477 """Create a Shape object with the given fixed size. Each pixel is one bit and is stored by the
478 column boundaries of the shape on each row. Each row’s boundary defaults to the full row.
482 def set_boundary(self, y, start_x, end_x):
483 """Loads pre-packed data into the given row."""
488 """Position a grid of tiles sourced from a bitmap and pixel_shader combination. Multiple grids can share bitmaps and pixel shaders.
490 A single tile grid is also known as a Sprite.
492 def __init__(self, bitmap, *, pixel_shader, width=1, height=1, tile_width=None, tile_height=None, default_tile=0, x=0, y=0):
493 """Create a TileGrid object. The bitmap is source for 2d pixels. The pixel_shader is used to convert the value and its location to a display native pixel color. This may be a simple color palette lookup, a gradient, a pattern or a color transformer.
495 tile_width and tile_height match the height of the bitmap by default.
501 """True when the TileGrid is hidden. This may be False even when a part of a hidden Group."""
505 def hidden(self, value):
510 """X position of the left edge in the parent."""
515 """Y position of the top edge in the parent."""
520 """If true, the left edge rendered will be the right edge of the right-most tile."""
524 def flip_x(self, value):
529 """If true, the top edge rendered will be the bottom edge of the bottom-most tile."""
533 def flip_y(self, value):
537 def transpose_xy(self):
538 """If true, the TileGrid’s axis will be swapped. When combined with mirroring, any 90 degree
539 rotation can be achieved along with the corresponding mirrored version.
544 def transpose_xy(self, value):
548 def pixel_shader(self):
549 """The pixel shader of the tilegrid."""
552 def __getitem__(self, index):
553 """Returns the tile index at the given index. The index can either be an x,y tuple or an int equal to ``y * width + x``'."""
556 def __setitem__(self, index, value):
557 """Sets the tile index at the given index. The index can either be an x,y tuple or an int equal to ``y * width + x``."""