kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
ePaper optimisations.
rodzic
e510739daf
commit
1424c06bb6
|
@ -149,7 +149,7 @@ development so check for updates.
|
|||
7.4 [Class TSequence](./README.md#74-class-tsequence) Plotting realtime, time sequential data.
|
||||
8. [ESP32 touch pads](./README.md#8-esp32-touch-pads) Replacing buttons with touch pads.
|
||||
9. [Realtime applications](./README.md#9-realtime-applications) Accommodating tasks requiring fast RT performance.
|
||||
9.1 [ePaper refresh](./README.md#91-epaper-refresh) Using these techniques to provide a full refresh.
|
||||
10. [ePaper displays](./README.md#10-epaper-displays) Using these techniques to provide a full refresh.
|
||||
|
||||
[Appendix 1 Application design](./README.md#appendix-1-application-design) Tab order, button layout, encoder interface, use of graphics primitives
|
||||
[Appendix 2 Freezing bytecode](./README.md#appendix-2-freezing-bytecode) Optional way to save RAM.
|
||||
|
@ -509,7 +509,7 @@ of slow and visually intrusive refreshing. However there is an exception: the
|
|||
[Waveshare pico_epaper_42](https://www.waveshare.com/pico-epaper-4.2.htm). This
|
||||
supports partial updates which work remarkably well with minimal ghosting. Note
|
||||
that it can be used with hosts other than the Pico via the supplied cable. See
|
||||
[ePaper refresh](./README.md#91-epaper-refresh).
|
||||
[ePaper displays](./README.md#10-epaper-displays).
|
||||
|
||||
Display drivers are documented [here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md).
|
||||
|
||||
|
@ -3042,7 +3042,7 @@ another from occurring.
|
|||
```
|
||||
The demo `gui/demos/audio.py` provides example usage.
|
||||
|
||||
## 9.1 ePaper refresh
|
||||
# 10 ePaper displays
|
||||
|
||||
The [Waveshare pico_epaper_42](https://www.waveshare.com/pico-epaper-4.2.htm)
|
||||
is currently the only fully supported ePaper display, with a hardware_setup.py
|
||||
|
@ -3051,7 +3051,7 @@ initial refresh the driver is put into partial mode to provide reasonably
|
|||
quick and visually satisfactory response to button events. However ghosting may
|
||||
accumulate after long periods of running, and an application may occasionally
|
||||
need to perform a full refresh. This requires the "done" interlock described
|
||||
above.
|
||||
in section 9.
|
||||
|
||||
```python
|
||||
async def full_refresh():
|
||||
|
|
|
@ -94,6 +94,12 @@ EPD_partial_lut_bb1 = b"\x00\x19\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00
|
|||
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00"
|
||||
|
||||
@micropython.viper
|
||||
def _linv(dest:ptr8, source:ptr8, length:int):
|
||||
for n in range(length):
|
||||
c = source[n]
|
||||
dest[n] = c ^ 0xFF
|
||||
|
||||
class EPD(framebuf.FrameBuffer):
|
||||
# A monochrome approach should be used for coding this. The rgb method ensures
|
||||
# nothing breaks if users specify colors.
|
||||
|
@ -245,33 +251,41 @@ class EPD(framebuf.FrameBuffer):
|
|||
def ready(self):
|
||||
return not (self._busy or (self.busy_pin() == 0)) # 0 == busy
|
||||
|
||||
def _line(self, n, buf=bytearray(_BWIDTH)):
|
||||
img = self.mvb
|
||||
s = n * _BWIDTH
|
||||
for x, b in enumerate(img[s : s + _BWIDTH]):
|
||||
buf[x] = b ^ 0xFF
|
||||
@micropython.native
|
||||
def _line(self, start, buf=bytearray(_BWIDTH)): # Sending 50 bytes 40us at 10MHz, 12ms for 300 lines
|
||||
_linv(buf, self.mvb[start:], _BWIDTH) # Invert image data for EPD
|
||||
self.send_bytes(buf)
|
||||
|
||||
async def _as_show(self):
|
||||
# Timing @10MHz/250MHz: full refresh 2.1s, partial 740ms
|
||||
# Blocking with split=5 740/5=150ms
|
||||
async def _as_show(self, split):
|
||||
self.send_command(b"\x13")
|
||||
for j in range(_EPD_HEIGHT): # Loop would block ~300ms
|
||||
self._line(j)
|
||||
lps = _EPD_HEIGHT // split
|
||||
idx = 0
|
||||
#ttt = time.ticks_ms()
|
||||
for _ in range(split): # For each segment
|
||||
for _ in range(lps):
|
||||
self._line(idx)
|
||||
idx += _BWIDTH
|
||||
await asyncio.sleep_ms(0)
|
||||
#print("Time", time.ticks_diff(time.ticks_ms(), ttt))
|
||||
self._updated.set()
|
||||
self.send_command(b"\x12") # Async .display_on()
|
||||
self.send_command(b"\x12") # Nonblocking .display_on()
|
||||
while not self.busy_pin():
|
||||
await asyncio.sleep_ms(10) # About 1.7s
|
||||
await asyncio.sleep_ms(0) # About 1.7s for full refresh
|
||||
self._busy = False
|
||||
#print("Time", time.ticks_diff(time.ticks_ms(), ttt)) # ~630ms
|
||||
|
||||
async def do_refresh(self, split): # For micro-gui
|
||||
await self._as_show()
|
||||
assert (not self._busy), "Refresh while busy"
|
||||
await self._as_show(split) # split=5
|
||||
|
||||
def show(self):
|
||||
def show(self): # nanogui
|
||||
if self._busy:
|
||||
raise RuntimeError('Cannot refresh: display is busy.')
|
||||
self._busy = True # Immediate busy flag. Pin goes low much later.
|
||||
if self._asyn:
|
||||
asyncio.create_task(self._as_show())
|
||||
asyncio.create_task(self._as_show(5)) # split into 5 segments
|
||||
return
|
||||
self.send_command(b"\x13")
|
||||
for j in range(_EPD_HEIGHT):
|
||||
|
|
|
@ -119,7 +119,7 @@ class FooScreen(Screen):
|
|||
Checkbox(wri, row, col, callback=self.cbcb)
|
||||
col+= 40
|
||||
self.led = LED(wri, row, col, color=YELLOW, bdcolor=GREEN)
|
||||
CloseButton(wri)
|
||||
CloseButton(wri, bgcolor=BLACK)
|
||||
asyncio.create_task(run(dial, lbltim, m0, scale))
|
||||
|
||||
|
||||
|
@ -174,10 +174,9 @@ async def run(dial, lbltim, m0, scale):
|
|||
|
||||
|
||||
def test():
|
||||
if ssd.height < 240 or ssd.width < 320:
|
||||
print(' This test requires a display of at least 320x240 pixels.')
|
||||
else:
|
||||
print('Testing micro-gui...')
|
||||
Screen.change(FooScreen)
|
||||
print('Testing micro-gui...')
|
||||
Screen.change(FooScreen)
|
||||
print("End")
|
||||
ssd.sleep() # Tidy shutdown of EPD
|
||||
|
||||
test()
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
from machine import Pin, SPI, freq
|
||||
import gc
|
||||
|
||||
from drivers.epaper.pico_epaper_42 import EPD as SSD
|
||||
freq(250_000_000) # RP2 overclock
|
||||
# Create and export an SSD instance
|
||||
|
@ -37,7 +36,8 @@ prst = Pin(9, Pin.OUT, value=1)
|
|||
pcs = Pin(10, Pin.OUT, value=1)
|
||||
pdc = Pin(8, Pin.OUT, value=0) # Arbitrary pins
|
||||
busy = Pin(15, Pin.IN)
|
||||
spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4), baudrate=4_000_000)
|
||||
# Datasheet allows 10MHz
|
||||
spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4), baudrate=10_000_000)
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
|
||||
# Using normal socket connection default args apply
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
from machine import Pin, SPI, freq
|
||||
import gc
|
||||
|
||||
from drivers.epaper.pico_epaper_42 import EPD as SSD
|
||||
freq(250_000_000) # RP2 overclock
|
||||
# Create and export an SSD instance
|
||||
|
@ -37,7 +36,8 @@ prst = Pin(9, Pin.OUT, value=1)
|
|||
pcs = Pin(10, Pin.OUT, value=1)
|
||||
pdc = Pin(8, Pin.OUT, value=0) # Arbitrary pins
|
||||
busy = Pin(15, Pin.IN)
|
||||
spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4), baudrate=4_000_000)
|
||||
# Datasheet allows 10MHz
|
||||
spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4), baudrate=10_000_000)
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
|
||||
# Using normal socket connection default args apply
|
||||
|
|
Ładowanie…
Reference in New Issue