feat(hal): read display rotation from hardware_config.json
Python CI / test (3.12) (push) Canceled after 0s
Python CI / test (3.13) (push) Canceled after 0s

Load the full hardware config up front rather than only the GPIO section,
so display settings can come from the same file. Adds a rotate parameter
that falls back to display.rotate in the config when not passed
explicitly, and logs the resolved value.

Also bumps the dreader-hal submodule to 64c9177 (use partial draw) and
adds a direct IT8951 example that bypasses the HAL, for isolating display
problems to the driver layer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 22:28:02 +02:00
co-authored by Claude Opus 5
parent f7d59d025f
commit ed05dc9c2d
3 changed files with 134 additions and 13 deletions
+110
View File
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
"""
Direct IT8951 test - bypasses the HAL completely.
Uses IT8951 library directly like the working example.
"""
from IT8951 import constants
from IT8951.display import AutoEPDDisplay
from PIL import Image
def main():
"""Test display with direct IT8951 access."""
print("=" * 60)
print("Direct IT8951 Test - Half Black, Half White")
print("=" * 60)
print()
print("This test bypasses the HAL and uses IT8951 directly.")
print("Matches the working code you provided.")
print()
# Display size
width, height = 1872, 1404
shape = (height, width) # IT8951 uses (height, width) format
print(f"Display shape: {shape} (height, width)")
print(f"Dimensions: {width}x{height}")
print()
# Create test image
print("Creating test image...")
print(" Left half: BLACK (0)")
print(" Right half: WHITE (255)")
# Create grayscale image
screen = Image.new('L', shape, color=255) # White background
# Draw left half black
pixels = screen.load()
for y in range(height):
for x in range(width // 2):
pixels[x, y] = 0 # Black
print(f"✓ Image created: {screen.size} {screen.mode}")
print()
# Save for reference
output_file = "direct_test.png"
screen.save(output_file)
print(f"✓ Saved to: {output_file}")
print()
# Initialize display
print("Initializing IT8951 display...")
print(" VCOM: -1.7V")
print(" Rotation: CW (clockwise)")
print(" SPI: 24MHz")
display = AutoEPDDisplay(
vcom=-1.7,
rotate="CW",
spi_hz=24000000,
device=0,
bus=0
)
print("✓ Display initialized")
print()
# Display the image
print("Displaying image...")
print(" Using frame_buf.paste() + draw_full(GC16)")
display.frame_buf.paste(screen, (0, 0))
display.draw_full(constants.DisplayModes.GC16)
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 this works, the display hardware is fine!")
print("If this doesn't work, there's a hardware/wiring issue.")
print()
# Sleep display
input("Press Enter to put display to sleep and exit...")
epd = display.epd
epd.sleep()
print("Display put to sleep. Done!")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\nTest interrupted")
except Exception as e:
print(f"\nERROR: {e}")
import traceback
traceback.print_exc()