"""Driver for the Waveshare epd4in0e (4", 6-color Spectra) panel. Thin wrapper around the vendored `waveshare_epd.epd4in0e` module -- the exact driver already proven working under the InkyPi install on this Pi. That driver only exposes `Clear()` and `display()`, both of which do a full `TurnOnDisplay()` flash cycle; there is no partial-refresh path for this panel at the hardware/SDK level, confirmed by reading the driver itself. """ import logging from display import Display logger = logging.getLogger(__name__) # The panel is physically native portrait (400x600), but mounted sideways -- # screens render in this landscape resolution, and show() rotates the frame # to match the panel's native orientation right before sending it over. RESOLUTION = (600, 400) PANEL_NATIVE_RESOLUTION = (400, 600) class EPD4in0eDisplay(Display): def __init__(self): self.resolution = RESOLUTION self._epd = None def init(self) -> None: from display.waveshare_epd import epd4in0e self._epd = epd4in0e.EPD() self._epd.init() logger.info("epd4in0e initialized") def show(self, image) -> None: if self._epd is None: self.init() width, height = self.resolution if image.size != (width, height): raise ValueError( f"Image size {image.size} does not match panel resolution {self.resolution}" ) # Re-init: the panel goes to sleep after every show(), and needs a # fresh init() before it will accept commands again. self._epd.init() # Clear first to avoid ghosting from the previous image -- also a # full flash, there's no way around it on this panel. self._epd.Clear() # Rotate landscape -> the panel's native portrait orientation. If this # comes out upside-down for how it's physically mounted, flip the # sign here (rotate(-90) instead of rotate(90)). rotated = image.convert("RGB").rotate(90, expand=True) if rotated.size != PANEL_NATIVE_RESOLUTION: raise ValueError(f"Rotated image {rotated.size} doesn't match panel {PANEL_NATIVE_RESOLUTION}") self._epd.display(self._epd.getbuffer(rotated)) def sleep(self) -> None: if self._epd is not None: self._epd.sleep() logger.info("epd4in0e put to sleep")