CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-luma-oled

Display drivers for SSD1306/SSD1309/SSD1322/SSD1325/SSD1327/SSD1331/SSD1351/SSD1362/SH1106/SH1107/WS0010 OLED matrix displays

Pending
Overview
Eval results
Files

greyscale-displays.mddocs/

Greyscale 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.

Capabilities

SSD1322 Display

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 circle

SSD1322 NHD Variant

Specialized 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

SSD1325 Display

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)

SSD1327 Display

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)

SSD1362 Display

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)

Rendering Modes

RGB Mode (Greyscale)

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 grey

Monochrome Mode

In 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) # White

Advanced Usage

Custom Greyscale Levels

Work 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)

Performance Considerations

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 alignment

Common Patterns

Error Handling

import luma.core.error

try:
    device = ssd1327(serial, width=200, height=100)
except luma.core.error.DeviceDisplayModeError as e:
    print(f"Unsupported display mode: {e}")

Image Mode Compatibility

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 greyscale

Framebuffer Optimization

from 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

docs

character-displays.md

color-displays.md

greyscale-displays.md

index.md

interfaces.md

monochrome-displays.md

tile.json