Compare commits

...
3 Commits
Author SHA1 Message Date
dtourolle 64c9177604 use partial draw
Python CI / test (3.12) (push) Failing after 42s
Python CI / test (3.13) (push) Failing after 40s
2025-11-23 15:21:36 +01:00
dtourolle bfa51c1439 add logging of screen events
Python CI / test (3.12) (push) Failing after 42s
Python CI / test (3.13) (push) Failing after 41s
2025-11-23 14:21:24 +01:00
dtourolle e5e9f62e31 Fix issue with detouch being logged as touch at 0,0 2025-11-23 14:19:29 +01:00
2 changed files with 39 additions and 8 deletions
+32 -3
View File
@@ -12,6 +12,7 @@ Hardware: IT8951 controller (used in Waveshare 6" e-Paper HAT and similar)
"""
import asyncio
import logging
import sys
import os
from typing import Optional
@@ -25,6 +26,8 @@ from IT8951.constants import DisplayModes
from ..types import RefreshMode
logger = logging.getLogger(__name__)
class IT8951DisplayDriver:
"""
@@ -93,6 +96,7 @@ class IT8951DisplayDriver:
"""Blocking initialization of display (runs in thread pool)."""
if self.virtual:
# Virtual display for testing
logger.info(f"Initializing IT8951 virtual display: {self.width}x{self.height}")
self.display = VirtualEPDDisplay(
dims=(self.width, self.height),
rotate=self.rotate,
@@ -100,6 +104,7 @@ class IT8951DisplayDriver:
)
else:
# Real e-ink display
logger.info(f"Initializing IT8951 e-ink display: {self.width}x{self.height}, VCOM={self.vcom}V")
self.display = AutoEPDDisplay(
vcom=self.vcom,
bus=self.bus,
@@ -110,7 +115,9 @@ class IT8951DisplayDriver:
)
# Clear screen
logger.info("Clearing IT8951 display to white")
self.display.clear()
logger.info("IT8951 display initialized successfully")
async def cleanup(self) -> None:
"""
@@ -162,12 +169,15 @@ class IT8951DisplayDriver:
# Determine refresh mode
display_mode = self._determine_refresh_mode(mode)
mode_name = self._get_mode_name(display_mode)
logger.info(f"[IT8951] Displaying image {image.size} {image.mode} | Refresh #{self._refresh_count + 1} | Mode: {mode_name}")
# Prepare image for e-ink
prepared_image = self._prepare_image(image)
# Update frame buffer
self.display.frame_buf = prepared_image
# Update frame buffer using paste (more reliable than direct assignment)
self.display.frame_buf.paste(prepared_image, (0, 0))
# Increment refresh counter
self._refresh_count += 1
@@ -180,6 +190,8 @@ class IT8951DisplayDriver:
display_mode
)
logger.info(f"[IT8951] Display update completed (refresh #{self._refresh_count})")
# Automatically put display to sleep after update to save power
# E-ink displays only need power during refresh, not for static display
if self.auto_sleep:
@@ -279,6 +291,17 @@ class IT8951DisplayDriver:
# Default to DU (fast)
return DisplayModes.DU
def _get_mode_name(self, display_mode: int) -> str:
"""Get human-readable name for display mode."""
if display_mode == DisplayModes.INIT:
return "INIT (full refresh)"
elif display_mode == DisplayModes.DU:
return "DU (fast)"
elif display_mode == DisplayModes.GC16:
return "GC16 (quality)"
else:
return f"Mode {display_mode}"
def _update_display(self, display_mode: int) -> None:
"""
Update the physical display (blocking).
@@ -293,7 +316,13 @@ class IT8951DisplayDriver:
if hasattr(self.display, 'epd') and self.auto_sleep:
self.display.epd.run()
# Use partial update for efficiency
# Use full refresh for INIT mode (clears ghosting) or first few refreshes
# Use partial refresh for fast updates
if display_mode == DisplayModes.INIT or self._refresh_count <= 2:
# Full refresh - more reliable for initial displays
self.display.draw_full(display_mode)
else:
# Partial update for efficiency
# IT8951 library tracks what changed and only updates that region
self.display.draw_partial(display_mode)
+5 -3
View File
@@ -76,6 +76,7 @@ class FT5xx6TouchDriver:
self._initialized = False
self._last_num_touches = 0
self._tracking_touch = False
self._last_touch_pos = (0, 0) # Track last known touch position for drag_end
async def initialize(self) -> None:
"""
@@ -206,6 +207,7 @@ class FT5xx6TouchDriver:
# Handle single-touch gestures with our gesture detector
if num_touches == 1:
x, y = record.t1x, record.t1y
self._last_touch_pos = (x, y) # Track position for drag_end
# Touch down
if self._last_num_touches == 0:
@@ -233,10 +235,10 @@ class FT5xx6TouchDriver:
elif num_touches == 0 and self._last_num_touches > 0:
# Get last known position
if self._last_num_touches == 1:
# Single finger up
# Single finger up - use last tracked position
gesture = self.gesture_detector.on_touch_up(
self.gesture_detector.current_pos[0] if self.gesture_detector.current_pos else 0,
self.gesture_detector.current_pos[1] if self.gesture_detector.current_pos else 0,
self._last_touch_pos[0],
self._last_touch_pos[1],
finger=0
)
self._tracking_touch = False