Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp Displayio and Add grayscale #114

Merged
merged 23 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
255ac2d
Finish adding code to ColorConverter
makermelissa Sep 20, 2023
6221337
Keep track of displays and buses in init
makermelissa Sep 21, 2023
0d24325
More displayio code updates
makermelissa Sep 22, 2023
8dc304f
Fewer bugs, more code, shape done
makermelissa Sep 22, 2023
156e7fc
Fixed buffer and get_refresh_areas
makermelissa Sep 22, 2023
33accff
Remove more of PIL
makermelissa Sep 23, 2023
a53c930
More bug fixes
makermelissa Sep 26, 2023
e46cbbe
Added missing stuff, fixed group layer order issue
makermelissa Sep 26, 2023
a0f10b5
More bug fixes and it is working
makermelissa Sep 26, 2023
4ce6ccf
Slight optimization and uses CP font as default
makermelissa Sep 27, 2023
2514566
Add changed file that wasn't included in last commit
makermelissa Sep 27, 2023
fd69c0e
Speed improvements by making larger buffer
makermelissa Sep 27, 2023
7c8fcb8
Bug fixes for SSD1306
makermelissa Sep 27, 2023
5addeea
Update begin_transaction
makermelissa Sep 27, 2023
07b3c4b
Bug fixes for SSD1306
makermelissa Sep 28, 2023
3ace921
Add some missing checks to display
makermelissa Sep 28, 2023
11e8cc6
Make some internal functions protected
makermelissa Sep 28, 2023
b6c1453
Remove debug code + add bus free
makermelissa Sep 28, 2023
213fe1e
Update OnDiskBitmap and add finish_refresh to Converter
makermelissa Sep 29, 2023
dd0a5d5
Remove numpy and PIL from requirements
makermelissa Sep 29, 2023
1a2f326
Add pillow back in because fontio uses it
makermelissa Sep 29, 2023
9c6cace
Optimize OnDiskBitMap a bit
makermelissa Sep 29, 2023
d99b13f
bug fix when ram height > 0x100
makermelissa Sep 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -396,4 +396,4 @@ min-public-methods=1

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception
overgeneral-exceptions=builtins.Exception
57 changes: 53 additions & 4 deletions displayio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Author(s): Melissa LeBlanc-Williams

"""

import threading
from typing import Union
from ._fourwire import FourWire
from ._i2cdisplay import I2CDisplay
Expand All @@ -30,19 +30,68 @@
from ._palette import Palette
from ._shape import Shape
from ._tilegrid import TileGrid
from ._display import displays
from ._displaybus import _DisplayBus
from ._constants import CIRCUITPY_DISPLAY_LIMIT

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"


displays = []
display_buses = []


def _background():
"""Main thread function to loop through all displays and update them"""
while True:
for display in displays:
display._background() # pylint: disable=protected-access


def release_displays() -> None:
"""Releases any actively used displays so their busses and pins can be used again.

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.
"""
for _disp in displays:
_disp._release() # pylint: disable=protected-access
for display in displays:
display._release() # pylint: disable=protected-access
displays.clear()

for display_bus in display_buses:
display_bus.deinit()
display_buses.clear()


def allocate_display(new_display: Union[Display, EPaperDisplay]) -> None:
"""Add a display to the displays pool and return the new display"""
if len(displays) >= CIRCUITPY_DISPLAY_LIMIT:
raise RuntimeError("Too many displays")
displays.append(new_display)


def allocate_display_bus(new_display_bus: _DisplayBus) -> None:
"""Add a display bus to the display_buses pool and return the new display bus"""
if len(display_buses) >= CIRCUITPY_DISPLAY_LIMIT:
raise RuntimeError(
"Too many display busses; forgot displayio.release_displays() ?"
)
display_buses.append(new_display_bus)


background_thread = threading.Thread(target=_background, daemon=True)


# Start the background thread
def _start_background():
if not background_thread.is_alive():
background_thread.start()


def _stop_background():
if background_thread.is_alive():
# Stop the thread
background_thread.join()


_start_background()
40 changes: 25 additions & 15 deletions displayio/_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@


class Area:
# pylint: disable=invalid-name,missing-function-docstring
"""Area Class to represent an area to be updated. Currently not used."""
"""Area Class to represent an area to be updated."""

# pylint: disable=invalid-name
def __init__(self, x1: int = 0, y1: int = 0, x2: int = 0, y2: int = 0):
self.x1 = x1
self.y1 = y1
Expand All @@ -38,25 +38,29 @@ def __init__(self, x1: int = 0, y1: int = 0, x2: int = 0, y2: int = 0):
def __str__(self):
return f"Area TL({self.x1},{self.y1}) BR({self.x2},{self.y2})"

def _copy_into(self, dst) -> None:
def copy_into(self, dst) -> None:
"""Copy the area into another area."""
dst.x1 = self.x1
dst.y1 = self.y1
dst.x2 = self.x2
dst.y2 = self.y2

def _scale(self, scale: int) -> None:
def scale(self, scale: int) -> None:
"""Scale the area by scale."""
self.x1 *= scale
self.y1 *= scale
self.x2 *= scale
self.y2 *= scale

def _shift(self, dx: int, dy: int) -> None:
def shift(self, dx: int, dy: int) -> None:
"""Shift the area by dx and dy."""
self.x1 += dx
self.y1 += dy
self.x2 += dx
self.y2 += dy

def _compute_overlap(self, other, overlap) -> bool:
def compute_overlap(self, other, overlap) -> bool:
"""Compute the overlap between two areas. Returns True if there is an overlap."""
a = self
overlap.x1 = max(a.x1, other.x1)
overlap.x2 = min(a.x2, other.x2)
Expand All @@ -69,22 +73,24 @@ def _compute_overlap(self, other, overlap) -> bool:

return overlap.y1 < overlap.y2

def _empty(self):
def empty(self):
"""Return True if the area is empty."""
return (self.x1 == self.x2) or (self.y1 == self.y2)

def _canon(self):
def canon(self):
"""Make sure the area is in canonical form."""
if self.x1 > self.x2:
self.x1, self.x2 = self.x2, self.x1
if self.y1 > self.y2:
self.y1, self.y2 = self.y2, self.y1

def _union(self, other, union):
# pylint: disable=protected-access
if self._empty():
self._copy_into(union)
def union(self, other, union):
"""Combine this area along with another into union"""
if self.empty():
self.copy_into(union)
return
if other._empty():
other._copy_into(union)
if other.empty():
other.copy_into(union)
return

union.x1 = min(self.x1, other.x1)
Expand All @@ -93,12 +99,15 @@ def _union(self, other, union):
union.y2 = max(self.y2, other.y2)

def width(self) -> int:
"""Return the width of the area."""
return self.x2 - self.x1

def height(self) -> int:
"""Return the height of the area."""
return self.y2 - self.y1

def size(self) -> int:
"""Return the size of the area."""
return self.width() * self.height()

def __eq__(self, other):
Expand All @@ -113,14 +122,15 @@ def __eq__(self, other):
)

@staticmethod
def _transform_within(
def transform_within(
mirror_x: bool,
mirror_y: bool,
transpose_xy: bool,
original: Area,
whole: Area,
transformed: Area,
):
"""Transform an area within a larger area."""
# pylint: disable=too-many-arguments
# Original and whole must be in the same coordinate space.
if mirror_x:
Expand Down
Loading