Files
forge-invar/src/forge_invar/i2c.py
T
2026-11-05 22:09:19 +01:00

55 lines
1.7 KiB
Python

import logging
import sys
import typing
from luma.core.error import DeviceNotFoundError
from luma.core.interface.serial import i2c
from luma.oled.device import device, sh1106
from PIL import Image
log = logging.getLogger(__name__)
class I2C:
def __init__(self) -> None:
self.__device: device | None = None
def __enter__(self) -> typing.Self:
self.__open_device()
return self
def __exit__(self, *_) -> None:
assert self.__device is not None
self.__device.cleanup()
def __open_device(self) -> None:
# Pin definitions: I2C Bus 1 (SDA=GPIO2, SCL=GPIO3)
# Default SSD1306 I2C address is 0x3C
serial_interface = i2c(port=1, address=0x3C)
try:
# Initialize the device. If using SH1106, change ssd1306 to sh1106
self.__device = sh1106(serial_interface, width=128, height=64, rotate=0)
except DeviceNotFoundError:
log.critical(
"Fatal: OLED not found at 0x3C. Check wiring and run i2cdetect -y 1"
)
sys.exit(1)
except OSError as e:
if e.errno == 121:
log.critical(
"Fatal: Remote I/O error. I2C bus is locked or physically disconnected."
)
else:
log.critical(f"Fatal OS Error: {e}")
sys.exit(1)
def update_display(self, image: Image.Image) -> None:
assert self.__device is not None
try:
self.__device.display(image)
except OSError as e:
if e.errno == 121:
log.error("Runtime Error: I2C bus dropped. Check physical connections.")
raise