]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blobdiff - displayio/_displaycore.py
Keep track of displays and buses in init
[hackapet/Adafruit_Blinka_Displayio.git] / displayio / _displaycore.py
index a50d094fb656a20bb4b75396490855fda378ffc2..ccda898e66a6c268f748921560817244307ac51b 100644 (file)
@@ -22,7 +22,7 @@ __version__ = "0.0.0+auto.0"
 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_Displayio.git"
 
 
-from typing import Union
+import time
 import circuitpython_typing
 from paralleldisplay import ParallelBus
 from ._fourwire import FourWire
@@ -30,12 +30,11 @@ from ._group import Group
 from ._i2cdisplay import I2CDisplay
 from ._structs import ColorspaceStruct, TransformStruct, RectangleStruct
 from ._area import Area
-
-displays = []
+from ._displaybus import _DisplayBus
 
 
 class _DisplayCore:
-    # pylint: disable=too-many-arguments, too-many-instance-attributes
+    # pylint: disable=too-many-arguments, too-many-instance-attributes, too-many-locals
 
     def __init__(
         self,
@@ -53,8 +52,16 @@ class _DisplayCore:
         bytes_per_cell: int,
         reverse_pixels_in_byte: bool,
         reverse_bytes_in_word: bool,
+        column_command: int,
+        row_command: int,
+        set_current_column_command: int,
+        set_current_row_command: int,
+        data_as_commands: bool,
+        always_toggle_chip_select: bool,
+        sh1107_addressing: bool,
+        address_little_endian: bool,
     ):
-        self._colorspace = ColorspaceStruct(
+        self.colorspace = ColorspaceStruct(
             depth=color_depth,
             grayscale=grayscale,
             grayscale_bit=8 - color_depth,
@@ -64,12 +71,23 @@ class _DisplayCore:
             reverse_bytes_in_word=reverse_bytes_in_word,
             dither=False,
         )
-        self._current_group = None
-        self._colstart = colstart
-        self._rowstart = rowstart
-        self._last_refresh = 0
-        self._refresh_in_progress = False
-        self._full_refresh = False
+        self.current_group = None
+        self.colstart = colstart
+        self.rowstart = rowstart
+        self.last_refresh = 0
+
+        self.column_command = column_command
+        self.row_command = row_command
+        self.set_current_column_command = set_current_column_command
+        self.set_current_row_command = set_current_row_command
+        self.data_as_commands = data_as_commands
+        self.always_toggle_chip_select = always_toggle_chip_select
+        self.sh1107_addressing = sh1107_addressing
+        self.address_little_endian = address_little_endian
+
+        self.refresh_in_progress = False
+        self.full_refresh = False
+        self.last_refresh = 0
 
         if bus:
             if isinstance(bus, (FourWire, I2CDisplay, ParallelBus)):
@@ -81,75 +99,75 @@ class _DisplayCore:
                 raise ValueError("Unsupported display bus type")
 
         self._bus = bus
-        self._area = Area(0, 0, width, height)
+        self.area = Area(0, 0, width, height)
 
-        self._width = width
-        self._height = height
-        self._ram_width = ram_width
-        self._ram_height = ram_height
-        self._rotation = rotation
-        self._transform = TransformStruct()
+        self.width = width
+        self.height = height
+        self.ram_width = ram_width
+        self.ram_height = ram_height
+        self.rotation = rotation
+        self.transform = TransformStruct()
 
     def set_rotation(self, rotation: int) -> None:
         """
         Sets the rotation of the display as an int in degrees.
         """
         # pylint: disable=protected-access, too-many-branches
-        transposed = self._rotation in (90, 270)
+        transposed = self.rotation in (90, 270)
         will_be_transposed = rotation in (90, 270)
         if transposed != will_be_transposed:
-            self._width, self._height = self._height, self._width
+            self.width, self.height = self.height, self.width
 
-        height = self._height
-        width = self._width
+        height = self.height
+        width = self.width
 
         rotation %= 360
-        self._rotation = rotation
-        self._transform.x = 0
-        self._transform.y = 0
-        self._transform.scale = 1
-        self._transform.mirror_x = False
-        self._transform.mirror_y = False
-        self._transform.transpose_xy = False
+        self.rotation = rotation
+        self.transform.x = 0
+        self.transform.y = 0
+        self.transform.scale = 1
+        self.transform.mirror_x = False
+        self.transform.mirror_y = False
+        self.transform.transpose_xy = False
 
         if rotation in (0, 180):
             if rotation == 180:
-                self._transform.mirror_x = True
-                self._transform.mirror_y = True
+                self.transform.mirror_x = True
+                self.transform.mirror_y = True
         else:
-            self._transform.transpose_xy = True
+            self.transform.transpose_xy = True
             if rotation == 270:
-                self._transform.mirror_y = True
+                self.transform.mirror_y = True
             else:
-                self._transform.mirror_x = True
-
-        self._area.x1 = 0
-        self._area.y1 = 0
-        self._area.next = None
-
-        self._transform.dx = 1
-        self._transform.dy = 1
-        if self._transform.transpose_xy:
-            self._area.x2 = height
-            self._area.y2 = width
-            if self._transform.mirror_x:
-                self._transform.x = height
-                self._transform.dx = -1
-            if self._transform.mirror_y:
-                self._transform.y = width
-                self._transform.dy = -1
+                self.transform.mirror_x = True
+
+        self.area.x1 = 0
+        self.area.y1 = 0
+        self.area.next = None
+
+        self.transform.dx = 1
+        self.transform.dy = 1
+        if self.transform.transpose_xy:
+            self.area.x2 = height
+            self.area.y2 = width
+            if self.transform.mirror_x:
+                self.transform.x = height
+                self.transform.dx = -1
+            if self.transform.mirror_y:
+                self.transform.y = width
+                self.transform.dy = -1
         else:
-            self._area.x2 = width
-            self._area.y2 = height
-            if self._transform.mirror_x:
-                self._transform.x = width
-                self._transform.dx = -1
-            if self._transform.mirror_y:
-                self._transform.y = height
-                self._transform.dy = -1
-
-        if self._current_group is not None:
-            self._current_group._update_transform(self._transform)
+            self.area.x2 = width
+            self.area.y2 = height
+            if self.transform.mirror_x:
+                self.transform.x = width
+                self.transform.dx = -1
+            if self.transform.mirror_y:
+                self.transform.y = height
+                self.transform.dy = -1
+
+        if self.current_group is not None:
+            self.current_group._update_transform(self.transform)
 
     def show(self, root_group: Group) -> bool:
         # pylint: disable=protected-access
@@ -167,25 +185,25 @@ class _DisplayCore:
             circuitpython_splash = _Supervisor().circuitpython_splash
             if not circuitpython_splash._in_group:
                 root_group = circuitpython_splash
-            elif self._current_group == circuitpython_splash:
+            elif self.current_group == circuitpython_splash:
                 return True
         """
 
-        if root_group == self._current_group:
+        if root_group == self.current_group:
             return True
 
         if root_group is not None and root_group._in_group:
             return False
 
-        if self._current_group is not None:
-            self._current_group._in_group = False
+        if self.current_group is not None:
+            self.current_group._in_group = False
 
         if root_group is not None:
-            root_group._update_transform(self._transform)
+            root_group._update_transform(self.transform)
             root_group._in_group = True
 
-        self._current_group = root_group
-        self._full_refresh = True
+        self.current_group = root_group
+        self.full_refresh = True
 
         return True
 
@@ -193,38 +211,38 @@ class _DisplayCore:
         # pylint: disable=protected-access
         """Mark the display core as currently being refreshed"""
 
-        if self._refresh_in_progress:
+        if self.refresh_in_progress:
             return False
 
-        self._refresh_in_progress = True
-        # self._last_refresh = _Supervisor()._ticks_ms64()
+        self.refresh_in_progress = True
+        self.last_refresh = time.monotonic() * 1000
         return True
 
     def finish_refresh(self) -> None:
         # pylint: disable=protected-access
         """Unmark the display core as currently being refreshed"""
 
-        if self._current_group is not None:
-            self._current_group._finish_refresh()
+        if self.current_group is not None:
+            self.current_group._finish_refresh()
 
-        self._full_refresh = False
-        self._refresh_in_progress = False
-        # self._last_refresh = _Supervisor()._ticks_ms64()
+        self.full_refresh = False
+        self.refresh_in_progress = False
+        self.last_refresh = time.monotonic() * 1000
 
     def get_refresh_areas(self) -> list:
         """Get a list of areas to be refreshed"""
         subrectangles = []
-        if self._current_group is not None:
+        if self.current_group is not None:
             # Eventually calculate dirty rectangles here
-            subrectangles.append(RectangleStruct(0, 0, self._width, self._height))
+            subrectangles.append(RectangleStruct(0, 0, self.width, self.height))
         return subrectangles
 
     def release(self) -> None:
         """Release the display from the current group"""
         # pylint: disable=protected-access
 
-        if self._current_group is not None:
-            self._current_group._in_group = False
+        if self.current_group is not None:
+            self.current_group._in_group = False
 
     def fill_area(
         self,
@@ -235,22 +253,22 @@ class _DisplayCore:
         # pylint: disable=protected-access
         """Call the current group's fill area function"""
 
-        return self._current_group._fill_area(self._colorspace, area, mask, buffer)
+        return self.current_group._fill_area(self.colorspace, area, mask, buffer)
 
     def clip_area(self, area: Area, clipped: Area) -> bool:
         """Shrink the area to the region shared by the two areas"""
         # pylint: disable=protected-access
 
-        overlaps = self._area._compute_overlap(area, clipped)
+        overlaps = self.area._compute_overlap(area, clipped)
         if not overlaps:
             return False
 
         # Expand the area if we have multiple pixels per byte and we need to byte align the bounds
-        if self._colorspace.depth < 8:
+        if self.colorspace.depth < 8:
             pixels_per_byte = (
-                8 // self._colorspace.depth * self._colorspace.bytes_per_cell
+                8 // self.colorspace.depth * self.colorspace.bytes_per_cell
             )
-            if self._colorspace.pixels_in_byte_share_row:
+            if self.colorspace.pixels_in_byte_share_row:
                 if clipped.x1 % pixels_per_byte != 0:
                     clipped.x1 -= clipped.x1 % pixels_per_byte
                 if clipped.x2 % pixels_per_byte != 0:
@@ -290,21 +308,21 @@ class _DisplayCore:
         """
         Gets the width of the display in pixels.
         """
-        return self._width
+        return self.width
 
     def get_height(self) -> int:
         """
         Gets the height of the display in pixels.
         """
-        return self._height
+        return self.height
 
     def get_rotation(self) -> int:
         """
         Gets the rotation of the display as an int in degrees.
         """
-        return self._rotation
+        return self.rotation
 
-    def get_bus(self) -> Union[FourWire, ParallelBus, I2CDisplay]:
+    def get_bus(self) -> _DisplayBus:
         """
         The bus being used by the display. [readonly]
         """