Display drivers for SSD1306/SSD1309/SSD1322/SSD1325/SSD1327/SSD1331/SSD1351/SSD1362/SH1106/SH1107/WS0010 OLED matrix displays
—
4-bit greyscale OLED displays supporting 16 levels of grey intensity. These displays can render both monochrome and greyscale content with automatic RGB to greyscale conversion using luma calculation.
Serial interface to a 4-bit greyscale SSD1322 OLED display with flexible resolution support and dual rendering modes.
class ssd1322:
def __init__(self, serial_interface=None, width=256, height=64, rotate=0, mode="RGB", framebuffer=None, **kwargs):
"""
Initialize SSD1322 greyscale OLED display.
Parameters:
- serial_interface: Serial interface (usually luma.core.interface.serial.spi)
- width: Number of horizontal pixels (default: 256)
- height: Number of vertical pixels (default: 64)
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
- mode: Rendering mode "1" (monochrome) or "RGB" (greyscale) (default: "RGB")
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
"""
def command(self, cmd, *args):
"""
Send command and optional arguments to the display.
Parameters:
- cmd: Command byte
- args: Optional command arguments passed as data
"""Supported Resolutions: (256,64), (256,48), (256,32), (128,64), (128,48), (128,32), (64,64), (64,48), (64,32)
Usage example:
from luma.core.interface.serial import spi
from luma.oled.device import ssd1322
from luma.core.render import canvas
# Initialize large greyscale display
serial = spi(port=0, device=0, bus_speed_hz=8000000)
device = ssd1322(serial, width=256, height=64, mode="RGB")
# Draw greyscale content
with canvas(device) as draw:
# RGB colors automatically converted to greyscale
draw.rectangle((0, 0, 256, 64), fill=(128, 128, 128)) # Grey background
draw.text((10, 10), "Greyscale Text", fill=(255, 255, 255)) # White text
draw.ellipse((50, 20, 100, 50), fill=(64, 64, 64)) # Dark grey circleSpecialized version of SSD1322 for Newhaven Display (NHD) modules with fixed configuration.
class ssd1322_nhd:
def __init__(self, serial_interface=None, width=128, height=64, rotate=0, mode="RGB", framebuffer=full_frame(), **kwargs):
"""
Initialize SSD1322 NHD greyscale OLED display.
Parameters:
- serial_interface: Serial interface (usually luma.core.interface.serial.spi)
- width: Fixed at 128 pixels
- height: Fixed at 64 pixels
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
- mode: Rendering mode "1" (monochrome) or "RGB" (greyscale) (default: "RGB")
- framebuffer: Fixed to full_frame() strategy
"""
def display(self, image):
"""
Display 1-bit monochrome or 24-bit RGB image as greyscale.
Parameters:
- image: PIL.Image in mode "1" or "RGB"
"""
def command(self, cmd, *args):
"""
Send command and optional arguments to the display.
"""Supported Resolutions: (128,64) only
Serial interface to a 4-bit greyscale SSD1325 OLED display with specialized greyscale table support.
class ssd1325:
def __init__(self, serial_interface=None, width=128, height=64, rotate=0, mode="RGB", framebuffer=None, **kwargs):
"""
Initialize SSD1325 greyscale OLED display.
Parameters:
- serial_interface: Serial interface (usually luma.core.interface.serial.spi)
- width: Number of horizontal pixels (default: 128)
- height: Number of vertical pixels (default: 64)
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
- mode: Rendering mode "1" (monochrome) or "RGB" (greyscale) (default: "RGB")
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
"""Supported Resolutions: (128,64)
Serial interface to a 4-bit greyscale SSD1327 OLED display with square format and enhanced greyscale support.
class ssd1327:
def __init__(self, serial_interface=None, width=128, height=128, rotate=0, mode="RGB", framebuffer=None, **kwargs):
"""
Initialize SSD1327 greyscale OLED display.
Parameters:
- serial_interface: Serial interface (usually luma.core.interface.serial.spi)
- width: Number of horizontal pixels (default: 128)
- height: Number of vertical pixels (default: 128)
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
- mode: Rendering mode "1" (monochrome) or "RGB" (greyscale) (default: "RGB")
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
"""Supported Resolutions: (128,128)
Serial interface to a 4-bit greyscale SSD1362 OLED display with wide format support.
class ssd1362:
def __init__(self, serial_interface=None, width=256, height=64, rotate=0, mode="RGB", framebuffer=None, **kwargs):
"""
Initialize SSD1362 greyscale OLED display.
Parameters:
- serial_interface: Serial interface (usually luma.core.interface.serial.spi)
- width: Number of horizontal pixels (default: 256)
- height: Number of vertical pixels (default: 64)
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
- mode: Rendering mode "1" (monochrome) or "RGB" (greyscale) (default: "RGB")
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
"""Supported Resolutions: (256,64)
In RGB mode, color images are converted to 4-bit greyscale using luma calculation:
# RGB mode for greyscale rendering (default)
device = ssd1322(serial, mode="RGB")
with canvas(device) as draw:
# Colors converted using Y' = 0.299R' + 0.587G' + 0.114B'
draw.rectangle((0, 0, 100, 50), fill=(255, 0, 0)) # Red -> Dark grey
draw.rectangle((100, 0, 200, 50), fill=(0, 255, 0)) # Green -> Light grey
draw.rectangle((0, 50, 100, 64), fill=(0, 0, 255)) # Blue -> Very dark greyIn monochrome mode, displays render as 1-bit black and white:
# Monochrome mode
device = ssd1322(serial, mode="1")
with canvas(device) as draw:
# Only black (0) and white (255) pixels
draw.rectangle((0, 0, 256, 64), fill=0) # Black
draw.text((10, 10), "Mono Text", fill=255) # WhiteWork directly with greyscale values (0-15 for 4-bit):
from PIL import Image
# Create greyscale image with specific levels
img = Image.new("L", (128, 64)) # "L" mode for greyscale
pixels = img.load()
for x in range(128):
for y in range(64):
# Create gradient (values 0-255 mapped to 0-15 internally)
pixels[x, y] = int((x / 128) * 255)
device.display(img)Greyscale displays use nibble packing (2 pixels per byte):
# Efficient for even-width displays
device = ssd1322(serial, width=256, height=64) # 256 is divisible by 4
# Less efficient for odd-width displays
device = ssd1325(serial, width=128, height=64) # Requires pixel alignmentimport luma.core.error
try:
device = ssd1327(serial, width=200, height=100)
except luma.core.error.DeviceDisplayModeError as e:
print(f"Unsupported display mode: {e}")from PIL import Image
# Compatible image modes
mono_img = Image.new("1", (128, 64)) # 1-bit monochrome
grey_img = Image.new("L", (128, 64)) # 8-bit greyscale
rgb_img = Image.new("RGB", (128, 64)) # 24-bit RGB
# All can be displayed on greyscale devices
device.display(mono_img) # Direct display
device.display(grey_img) # Direct display
device.display(rgb_img) # Converted to greyscalefrom luma.core.framebuffer import diff_to_previous, full_frame
# Recommended for animations and frequent updates
device = ssd1322(serial, framebuffer=diff_to_previous())
# Use for static content or troubleshooting
device = ssd1322(serial, framebuffer=full_frame())Install with Tessl CLI
npx tessl i tessl/pypi-luma-oled