]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blob - displayio/__init__.py
relax background thread and add possibility to stop the background thread
[hackapet/Adafruit_Blinka_Displayio.git] / displayio / __init__.py
1 # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4
5 """
6 `displayio`
7 ================================================================================
8
9 displayio for Blinka
10
11 **Software and Dependencies:**
12
13 * Adafruit Blinka:
14   https://github.com/adafruit/Adafruit_Blinka/releases
15
16 * Author(s): Melissa LeBlanc-Williams
17
18 """
19 import threading
20 import time
21 from typing import Union
22
23 import fourwire
24 import i2cdisplaybus
25 from busdisplay import BusDisplay
26 from busdisplay._displaybus import _DisplayBus
27 from epaperdisplay import EPaperDisplay
28 from ._bitmap import Bitmap
29 from ._colorspace import Colorspace
30 from ._colorconverter import ColorConverter
31 from ._group import Group
32 from ._ondiskbitmap import OnDiskBitmap
33 from ._palette import Palette
34 from ._tilegrid import TileGrid
35 from ._constants import CIRCUITPY_DISPLAY_LIMIT
36
37 # 8.x Backwards compatibility, remove at 10.x or
38 # when compatibility is removed from core displayio
39 Display = BusDisplay
40 FourWire = fourwire.FourWire
41 I2CDisplay = i2cdisplaybus.I2CDisplayBus
42
43 __version__ = "0.0.0+auto.0"
44 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
45
46
47 displays = []
48 display_buses = []
49
50
51 def _background(stop_event):
52     """Main thread function to loop through all displays and update them"""
53     while not stop_event.is_set():
54         for display in displays:
55             display._background()  # pylint: disable=protected-access
56     
57         # relax system when _background does nothing 
58         # and we are in a while True loop consuming lots of CPU
59         time.sleep(0.0)
60
61
62 def release_displays() -> None:
63     """Releases any actively used displays so their busses and pins can be used again.
64
65     Use this once in your code.py if you initialize a display. Place it right before the
66     initialization so the display is active as long as possible.
67     """
68     for display in displays:
69         display._release()  # pylint: disable=protected-access
70     displays.clear()
71
72     for display_bus in display_buses:
73         display_bus.deinit()
74     display_buses.clear()
75
76
77 def allocate_display(new_display: Union[BusDisplay, EPaperDisplay]) -> None:
78     """Add a display to the displays pool and return the new display"""
79     if len(displays) >= CIRCUITPY_DISPLAY_LIMIT:
80         raise RuntimeError("Too many displays")
81     displays.append(new_display)
82
83
84 def allocate_display_bus(new_display_bus: _DisplayBus) -> None:
85     """Add a display bus to the display_buses pool and return the new display bus"""
86     if len(display_buses) >= CIRCUITPY_DISPLAY_LIMIT:
87         raise RuntimeError(
88             "Too many display busses; forgot displayio.release_displays() ?"
89         )
90     display_buses.append(new_display_bus)
91
92
93 background_thread_stop_event = threading.Event()
94 background_thread = threading.Thread(target=_background,args=(background_thread_stop_event,), daemon=True)
95
96
97 # Start the background thread
98 def _start_background():
99     if not background_thread.is_alive():
100         background_thread.start()
101
102
103 def _stop_background():
104     if background_thread.is_alive():
105         background_thread_stop_event.set()
106         # Stop the thread
107         background_thread.join()
108
109
110 _start_background()