pico_epaper_42 drivers async refresh: improve means of limiting blocking time.

pull/70/head
Peter Hinch 2024-07-04 18:50:23 +01:00
rodzic 7ecabf0fc1
commit df7656802a
3 zmienionych plików z 15 dodań i 7 usunięć

Wyświetl plik

@ -1447,6 +1447,10 @@ needed in more advanced asynchronous applications and their use is discussed in
seconds to enable viewing. This enables generic nanogui demos to be run on an seconds to enable viewing. This enables generic nanogui demos to be run on an
EPD. EPD.
Class variable:
* `MAXBLOCK = 25` Defines the maximum period (in ms) that an asynchronous
refresh can block before yielding to the scheduler.
Note that in synchronous applications with `demo_mode=False`, `refresh` returns Note that in synchronous applications with `demo_mode=False`, `refresh` returns
while the display is updating. Applications should issue `wait_until_ready` while the display is updating. Applications should issue `wait_until_ready`
before issuing another refresh. before issuing another refresh.

Wyświetl plik

@ -118,6 +118,7 @@ def _linv(dest: ptr32, source: ptr32, length: int):
class EPD(framebuf.FrameBuffer): class EPD(framebuf.FrameBuffer):
MAXBLOCK = 25 # Max async blocking time in ms
# A monochrome approach should be used for coding this. The rgb method ensures # A monochrome approach should be used for coding this. The rgb method ensures
# nothing breaks if users specify colors. # nothing breaks if users specify colors.
@staticmethod @staticmethod
@ -229,7 +230,7 @@ class EPD(framebuf.FrameBuffer):
self._cs(1) self._cs(1)
# Time to convert and transmit 1000 bytes ~ 1ms: most of that is tx @ 10MHz # Time to convert and transmit 1000 bytes ~ 1ms: most of that is tx @ 10MHz
# Yield every 16 transfers means blocking is ~16ms # Yield whenever code has blocked for more than EPD.MAXBLOCK
# Total convert and transmit time for 15000 bytes is ~15ms. # Total convert and transmit time for 15000 bytes is ~15ms.
# Timing @10MHz/250MHz: full refresh 2.1s, partial 740ms: the bulk of the time # Timing @10MHz/250MHz: full refresh 2.1s, partial 740ms: the bulk of the time
# is spent spinning on the busy pin and is CPU frequency independent. # is spent spinning on the busy pin and is CPU frequency independent.
@ -238,14 +239,15 @@ class EPD(framebuf.FrameBuffer):
fbidx = 0 # Index into framebuf fbidx = 0 # Index into framebuf
nbytes = len(self._ibuf) # Bytes to send nbytes = len(self._ibuf) # Bytes to send
nleft = len(self._buf) # Size of framebuf nleft = len(self._buf) # Size of framebuf
npass = 0 tyield = time.ticks_ms() # Time of last yield
while nleft > 0: while nleft > 0:
self._bsend(fbidx, nbytes) # Invert, buffer and send nbytes self._bsend(fbidx, nbytes) # Invert, buffer and send nbytes
fbidx += nbytes # Adjust for bytes already sent fbidx += nbytes # Adjust for bytes already sent
nleft -= nbytes nleft -= nbytes
nbytes = min(nbytes, nleft) nbytes = min(nbytes, nleft)
if not ((npass := npass + 1) % 16): if time.ticks_diff(time.ticks_ms(), tyield) > EPD.MAXBLOCK:
await asyncio.sleep_ms(0) # Control blocking time await asyncio.sleep_ms(0) # Don't allow excessive blocking
tyield = time.ticks_ms()
self.updated.set() self.updated.set()
self._command(b"\x12") # Nonblocking .display_on() self._command(b"\x12") # Nonblocking .display_on()
while not self._busy_pin(): # Wait on display hardware while not self._busy_pin(): # Wait on display hardware

Wyświetl plik

@ -112,6 +112,7 @@ def _lmap(dest: ptr8, source: ptr8, pattern: int, length: int):
class EPD(framebuf.FrameBuffer): class EPD(framebuf.FrameBuffer):
MAXBLOCK = 25 # Max async blocking time in ms
# The rgb method maps colors onto a 2-bit greyscale # The rgb method maps colors onto a 2-bit greyscale
# colors.py creates color constants with 2-bit colors which are written to FB # colors.py creates color constants with 2-bit colors which are written to FB
@staticmethod @staticmethod
@ -238,14 +239,15 @@ class EPD(framebuf.FrameBuffer):
nbytes = len(self.ibuf) # Bytes to send nbytes = len(self.ibuf) # Bytes to send
didx = nbytes * 2 # Increment of framebuf index didx = nbytes * 2 # Increment of framebuf index
nleft = len(self._buf) # Size of framebuf nleft = len(self._buf) # Size of framebuf
npass = 0 tyield = time.ticks_ms() # Time of last yield
while nleft > 0: while nleft > 0:
self._bsend(fbidx, pattern, nbytes) # Grey-map, buffer and send nbytes self._bsend(fbidx, pattern, nbytes) # Grey-map, buffer and send nbytes
fbidx += didx # Adjust for bytes already sent fbidx += didx # Adjust for bytes already sent
nleft -= didx nleft -= didx
nbytes = min(nbytes, nleft) nbytes = min(nbytes, nleft)
if not ((npass := npass + 1) % 16): if time.ticks_diff(time.ticks_ms(), tyield) > EPD.MAXBLOCK:
await asyncio.sleep_ms(0) # Control blocking time await asyncio.sleep_ms(0) # Don't allow excessive blocking
tyield = time.ticks_ms()
self.updated.set() self.updated.set()
self._command(b"\x12") # Nonblocking .display_on() self._command(b"\x12") # Nonblocking .display_on()