debug scripts
This commit is contained in:
parent
73102392dd
commit
c62b8eff38
201
examples/test_hardware_display.py
Executable file
201
examples/test_hardware_display.py
Executable file
@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test to verify the hardware HAL can display images.
|
||||
Creates a test pattern and displays it on the e-ink screen.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from dreader.hal_hardware import HardwareDisplayHAL
|
||||
|
||||
|
||||
def create_test_image(width=1404, height=1872 ):
|
||||
"""Create a test pattern image."""
|
||||
print("Creating test image...")
|
||||
|
||||
# Create white background
|
||||
img = Image.new('RGBA', (width, height), color='white')
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Draw border
|
||||
border_width = 10
|
||||
draw.rectangle(
|
||||
[(border_width, border_width),
|
||||
(width - border_width, height - border_width)],
|
||||
outline='black',
|
||||
width=border_width
|
||||
)
|
||||
|
||||
# Draw title
|
||||
try:
|
||||
font_large = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 80)
|
||||
font_medium = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 50)
|
||||
except:
|
||||
font_large = ImageFont.load_default()
|
||||
font_medium = ImageFont.load_default()
|
||||
|
||||
# Center text
|
||||
title = "Hardware Display Test"
|
||||
title_bbox = draw.textbbox((0, 0), title, font=font_large)
|
||||
title_width = title_bbox[2] - title_bbox[0]
|
||||
title_x = (width - title_width) // 2
|
||||
draw.text((title_x, 100), title, fill='black', font=font_large)
|
||||
|
||||
# Instructions
|
||||
instructions = [
|
||||
"If you can see this, the display is working!",
|
||||
"",
|
||||
"Test pattern includes:",
|
||||
"• Border around the screen",
|
||||
"• Centered text",
|
||||
"• Diagonal lines",
|
||||
"• Corner markers"
|
||||
]
|
||||
|
||||
y = 250
|
||||
for line in instructions:
|
||||
if line:
|
||||
bbox = draw.textbbox((0, 0), line, font=font_medium)
|
||||
line_width = bbox[2] - bbox[0]
|
||||
x = (width - line_width) // 2
|
||||
draw.text((x, y), line, fill='black', font=font_medium)
|
||||
y += 70
|
||||
|
||||
# Draw diagonal lines
|
||||
draw.line([(50, 50), (width-50, height-50)], fill='black', width=3)
|
||||
draw.line([(width-50, 50), (50, height-50)], fill='black', width=3)
|
||||
|
||||
# Draw corner markers
|
||||
marker_size = 100
|
||||
# Top-left
|
||||
draw.rectangle([(20, 20), (20 + marker_size, 20 + marker_size)],
|
||||
fill='black')
|
||||
draw.text((30, 30), "TL", fill='white', font=font_medium)
|
||||
|
||||
# Top-right
|
||||
draw.rectangle([(width - 20 - marker_size, 20),
|
||||
(width - 20, 20 + marker_size)],
|
||||
fill='black')
|
||||
draw.text((width - 100, 30), "TR", fill='white', font=font_medium)
|
||||
|
||||
# Bottom-left
|
||||
draw.rectangle([(20, height - 20 - marker_size),
|
||||
(20 + marker_size, height - 20)],
|
||||
fill='black')
|
||||
draw.text((30, height - 100), "BL", fill='white', font=font_medium)
|
||||
|
||||
# Bottom-right
|
||||
draw.rectangle([(width - 20 - marker_size, height - 20 - marker_size),
|
||||
(width - 20, height - 20)],
|
||||
fill='black')
|
||||
draw.text((width - 100, height - 100), "BR", fill='white', font=font_medium)
|
||||
|
||||
print(f"Test image created: {width}x{height} RGBA")
|
||||
return img
|
||||
|
||||
|
||||
async def main(args):
|
||||
"""Test hardware display."""
|
||||
|
||||
print("=" * 60)
|
||||
print("Hardware Display Test")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
# Get VCOM from args
|
||||
vcom = args.vcom if hasattr(args, 'vcom') else -1.65
|
||||
print(f"Using VCOM: {vcom}V")
|
||||
print()
|
||||
|
||||
# Create test image
|
||||
test_image = create_test_image(1872, 1404)
|
||||
|
||||
# Save test image for reference
|
||||
output_file = "test_pattern.png"
|
||||
test_image.save(output_file)
|
||||
print(f"Test pattern saved to: {output_file}")
|
||||
print()
|
||||
|
||||
# Initialize hardware HAL
|
||||
print("Initializing hardware HAL...")
|
||||
hal = HardwareDisplayHAL(
|
||||
width=1872,
|
||||
height=1404,
|
||||
vcom=vcom,
|
||||
config_file="hardware_config.json"
|
||||
)
|
||||
|
||||
print("Initializing hardware components...")
|
||||
await hal.initialize()
|
||||
print("✓ Hardware initialized")
|
||||
print()
|
||||
|
||||
# Display the test image
|
||||
print("Displaying test image on e-ink screen...")
|
||||
print("(This may take a few seconds for the full refresh)")
|
||||
print(f"Converting image from {test_image.mode} to grayscale for e-ink...")
|
||||
|
||||
# Convert RGBA to grayscale (L mode) for e-ink display
|
||||
if test_image.mode == 'RGBA':
|
||||
# Convert RGBA to RGB first (flatten alpha)
|
||||
rgb_image = Image.new('RGB', test_image.size, (255, 255, 255))
|
||||
rgb_image.paste(test_image, mask=test_image.split()[3]) # Use alpha as mask
|
||||
test_image_gray = rgb_image.convert('L')
|
||||
else:
|
||||
test_image_gray = test_image.convert('L')
|
||||
|
||||
print(f"Image converted to {test_image_gray.mode} mode")
|
||||
await hal.show_image(test_image_gray)
|
||||
print("✓ Image displayed!")
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("SUCCESS!")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("If you can see the test pattern on the screen, the")
|
||||
print("hardware display is working correctly!")
|
||||
print()
|
||||
print("Check that you can see:")
|
||||
print(" • Black border around the edges")
|
||||
print(" • Title text centered at the top")
|
||||
print(" • Diagonal lines crossing the screen")
|
||||
print(" • Corner markers labeled TL, TR, BL, BR")
|
||||
print()
|
||||
print("Press Ctrl+C to exit")
|
||||
print()
|
||||
|
||||
# Keep running so user can see the image
|
||||
try:
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("\nCleaning up...")
|
||||
await hal.cleanup()
|
||||
print("Done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Test hardware display')
|
||||
parser.add_argument('--vcom', type=float, default=-1.65,
|
||||
help='VCOM voltage (check your display label, default: -1.65)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
asyncio.run(main(args))
|
||||
except KeyboardInterrupt:
|
||||
print("\nTest interrupted")
|
||||
except Exception as e:
|
||||
print(f"\nERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
175
examples/test_library_on_hardware.py
Executable file
175
examples/test_library_on_hardware.py
Executable file
@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to render the library view and display it on hardware.
|
||||
Combines library rendering with hardware display testing.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from dreader.library import LibraryManager
|
||||
from dreader.hal_hardware import HardwareDisplayHAL
|
||||
|
||||
|
||||
async def main(args):
|
||||
"""Test library rendering on hardware display."""
|
||||
|
||||
library_path = args.library_path
|
||||
output_path = "library_render_test.png"
|
||||
vcom = args.vcom
|
||||
|
||||
print("=" * 60)
|
||||
print("Library Rendering on Hardware Test")
|
||||
print("=" * 60)
|
||||
print(f"Library path: {library_path}")
|
||||
print(f"VCOM: {vcom}V")
|
||||
print(f"Output file: {output_path}")
|
||||
print()
|
||||
|
||||
# Step 1: Create library manager and scan
|
||||
print("Step 1: Creating library manager...")
|
||||
library = LibraryManager(
|
||||
library_path=library_path,
|
||||
page_size=(1872, 1404)
|
||||
)
|
||||
|
||||
print("Scanning library...")
|
||||
library.scan_library()
|
||||
|
||||
print()
|
||||
print(f"Found {len(library.books)} books:")
|
||||
for i, book in enumerate(library.books[:10], 1): # Show first 10
|
||||
print(f" {i}. {book['title']} by {book['author']}")
|
||||
if len(library.books) > 10:
|
||||
print(f" ... and {len(library.books) - 10} more")
|
||||
print()
|
||||
|
||||
# Step 2: Create and render library table
|
||||
print("Step 2: Creating library table (page 1)...")
|
||||
table = library.create_library_table(page=0)
|
||||
print(f"✓ Library table created: {table is not None}")
|
||||
if table:
|
||||
print(f" Table has {len(table.rows)} rows")
|
||||
print()
|
||||
|
||||
print("Rendering library view...")
|
||||
image = library.render_library()
|
||||
|
||||
if not image:
|
||||
print("ERROR: No image rendered!")
|
||||
print(f" library.library_table = {library.library_table}")
|
||||
print(f" library.rendered_page = {library.rendered_page}")
|
||||
return 1
|
||||
|
||||
print(f"✓ Library rendered: {image.size} {image.mode}")
|
||||
|
||||
# Check if image is not blank
|
||||
import numpy as np
|
||||
img_array = np.array(image)
|
||||
unique_colors = len(np.unique(img_array.reshape(-1, img_array.shape[-1]), axis=0))
|
||||
print(f" Image has {unique_colors} unique colors (blank would be ~1)")
|
||||
|
||||
# Sample some pixels to see what we have
|
||||
print(f" Sample pixels:")
|
||||
print(f" Top-left corner: {image.getpixel((10, 10))}")
|
||||
print(f" Center: {image.getpixel((936, 702))}")
|
||||
print(f" Bottom-right: {image.getpixel((1860, 1390))}")
|
||||
print()
|
||||
|
||||
# Save for reference
|
||||
print(f"Saving to {output_path}...")
|
||||
image.save(output_path)
|
||||
print(f"✓ Saved to {output_path}")
|
||||
print()
|
||||
|
||||
# Step 3: Initialize hardware HAL
|
||||
print("Step 3: Initializing hardware HAL...")
|
||||
hal = HardwareDisplayHAL(
|
||||
width=1872,
|
||||
height=1404,
|
||||
vcom=vcom,
|
||||
config_file="hardware_config.json"
|
||||
)
|
||||
|
||||
print("Initializing hardware components...")
|
||||
await hal.initialize()
|
||||
print("✓ Hardware initialized")
|
||||
print()
|
||||
|
||||
# Step 4: Display on e-ink screen
|
||||
print("Step 4: Displaying library on e-ink screen...")
|
||||
print("(This may take a few seconds for the full refresh)")
|
||||
print(f"Converting image from {image.mode} to grayscale for e-ink...")
|
||||
|
||||
# Convert to grayscale (L mode) for e-ink display
|
||||
if image.mode == 'RGBA':
|
||||
# Convert RGBA to RGB first (flatten alpha)
|
||||
rgb_image = Image.new('RGB', image.size, (255, 255, 255))
|
||||
rgb_image.paste(image, mask=image.split()[3]) # Use alpha as mask
|
||||
image_gray = rgb_image.convert('L')
|
||||
else:
|
||||
image_gray = image.convert('L')
|
||||
|
||||
print(f"Image converted to {image_gray.mode} mode")
|
||||
await hal.show_image(image_gray)
|
||||
print("✓ Image displayed!")
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("SUCCESS!")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("The library view should now be visible on your e-ink screen.")
|
||||
print()
|
||||
print(f"You can also view the saved PNG: {output_path}")
|
||||
print()
|
||||
print("Press Ctrl+C to exit")
|
||||
print()
|
||||
|
||||
# Keep running so user can see the image
|
||||
try:
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("\nCleaning up...")
|
||||
await hal.cleanup()
|
||||
print("Done!")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Test library rendering on hardware display'
|
||||
)
|
||||
parser.add_argument(
|
||||
'library_path',
|
||||
nargs='?',
|
||||
default='tests/data/library-epub',
|
||||
help='Path to library directory (default: tests/data/library-epub)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--vcom',
|
||||
type=float,
|
||||
default=-1.65,
|
||||
help='VCOM voltage (check your display label, default: -1.65)'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
exit_code = asyncio.run(main(args))
|
||||
sys.exit(exit_code or 0)
|
||||
except KeyboardInterrupt:
|
||||
print("\nTest interrupted")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f"\nERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
89
examples/test_library_render.py
Executable file
89
examples/test_library_render.py
Executable file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to render the library view and save it as PNG.
|
||||
This helps verify the rendering is working correctly.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from dreader.library import LibraryManager
|
||||
|
||||
|
||||
def main():
|
||||
"""Test library rendering and save as PNG."""
|
||||
|
||||
library_path = "tests/data/library-epub"
|
||||
output_path = "library_render_test.png"
|
||||
|
||||
print("=" * 60)
|
||||
print("Library Rendering Test")
|
||||
print("=" * 60)
|
||||
print(f"Library path: {library_path}")
|
||||
print(f"Output file: {output_path}")
|
||||
print()
|
||||
|
||||
# Create library manager
|
||||
print("Creating library manager...")
|
||||
library = LibraryManager(
|
||||
library_path=library_path,
|
||||
page_size=(1872, 1404)
|
||||
)
|
||||
|
||||
# Scan library
|
||||
print("Scanning library...")
|
||||
library.scan_library()
|
||||
|
||||
print()
|
||||
print(f"Found {len(library.books)} books:")
|
||||
for book in library.books:
|
||||
print(f" - {book['title']} by {book['author']}")
|
||||
print()
|
||||
|
||||
# Create library table (renders the first page)
|
||||
print("Creating library table (page 1)...")
|
||||
library.create_library_table(page=0)
|
||||
|
||||
# Render the table
|
||||
print("Rendering library view...")
|
||||
image = library.render_library()
|
||||
|
||||
if image:
|
||||
print(f"Image size: {image.size}")
|
||||
print(f"Image mode: {image.mode}")
|
||||
|
||||
# Save as PNG
|
||||
print(f"Saving to {output_path}...")
|
||||
image.save(output_path)
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("SUCCESS!")
|
||||
print("=" * 60)
|
||||
print(f"Library view saved to: {output_path}")
|
||||
print()
|
||||
print("You can view the image with:")
|
||||
print(f" xdg-open {output_path} # Linux")
|
||||
print(f" open {output_path} # macOS")
|
||||
print()
|
||||
|
||||
return 0
|
||||
else:
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("ERROR: No image rendered")
|
||||
print("=" * 60)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as e:
|
||||
print(f"\nERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
126
examples/test_simple_pattern.py
Executable file
126
examples/test_simple_pattern.py
Executable file
@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simplest possible test - half black, half white screen.
|
||||
This verifies the display can show black pixels.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from dreader.hal_hardware import HardwareDisplayHAL
|
||||
|
||||
|
||||
def create_simple_test():
|
||||
"""Create a simple half-black, half-white test image."""
|
||||
print("Creating simple test pattern...")
|
||||
print("Left half: BLACK")
|
||||
print("Right half: WHITE")
|
||||
|
||||
width, height = 1872, 1404
|
||||
|
||||
# Create grayscale image (L mode = 8-bit grayscale)
|
||||
img = Image.new('L', (width, height), color=255) # Start with white
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Draw left half black
|
||||
draw.rectangle(
|
||||
[(0, 0), (width // 2, height)],
|
||||
fill=0 # 0 = black
|
||||
)
|
||||
|
||||
print(f"Test image created: {width}x{height} grayscale")
|
||||
print(f" Left half ({width//2}px): BLACK (0)")
|
||||
print(f" Right half ({width//2}px): WHITE (255)")
|
||||
|
||||
return img
|
||||
|
||||
|
||||
async def main(args):
|
||||
"""Test hardware display with simple pattern."""
|
||||
|
||||
print("=" * 60)
|
||||
print("Simple Display Test - Half Black, Half White")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
vcom = args.vcom
|
||||
print(f"Using VCOM: {vcom}V")
|
||||
print()
|
||||
|
||||
# Create simple test image
|
||||
test_image = create_simple_test()
|
||||
|
||||
# Save test image for reference
|
||||
output_file = "simple_test.png"
|
||||
test_image.save(output_file)
|
||||
print(f"Test pattern saved to: {output_file}")
|
||||
print()
|
||||
|
||||
# Initialize hardware HAL
|
||||
print("Initializing hardware HAL...")
|
||||
hal = HardwareDisplayHAL(
|
||||
width=1872,
|
||||
height=1404,
|
||||
vcom=vcom,
|
||||
config_file="hardware_config.json"
|
||||
)
|
||||
|
||||
print("Initializing hardware components...")
|
||||
await hal.initialize()
|
||||
print("✓ Hardware initialized")
|
||||
print()
|
||||
|
||||
# Display the test image
|
||||
print("Displaying test pattern on e-ink screen...")
|
||||
print("(This may take a few seconds for the full refresh)")
|
||||
await hal.show_image(test_image)
|
||||
print("✓ Image displayed!")
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("CHECK YOUR SCREEN:")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("You should see:")
|
||||
print(" • LEFT HALF: BLACK")
|
||||
print(" • RIGHT HALF: WHITE")
|
||||
print()
|
||||
print("If you see this, the display is working!")
|
||||
print("If the screen is all white, there may be a driver issue.")
|
||||
print()
|
||||
print("Press Ctrl+C to exit")
|
||||
print()
|
||||
|
||||
# Keep running so user can see the image
|
||||
try:
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("\nCleaning up...")
|
||||
await hal.cleanup()
|
||||
print("Done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Simple display test')
|
||||
parser.add_argument('--vcom', type=float, default=-1.65,
|
||||
help='VCOM voltage (check your display label, default: -1.65)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
asyncio.run(main(args))
|
||||
except KeyboardInterrupt:
|
||||
print("\nTest interrupted")
|
||||
except Exception as e:
|
||||
print(f"\nERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
@ -5,8 +5,9 @@
|
||||
"display": {
|
||||
"width": 1872,
|
||||
"height": 1404,
|
||||
"vcom": -2.0,
|
||||
"vcom": -1.7,
|
||||
"spi_hz": 24000000,
|
||||
"rotate": "CW",
|
||||
"auto_sleep": true
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user