A Python library to drive MAX7219 LED matrices, WS2812 NeoPixels, and APA102 DotStar LEDs on Raspberry Pi
—
Hardware register constants for MAX7219 chips and character-to-segment mapping utilities for seven-segment displays. These low-level components support the device implementations and text rendering capabilities.
Register address constants for direct MAX7219 chip communication and configuration.
class max7219:
"""
MAX7219 LED driver register addresses and constants.
Used internally by the max7219 device class for hardware communication.
"""
NOOP = 0x00 # No operation register
DIGIT_0 = 0x01 # First digit register (digits 0-7: 0x01-0x08)
DECODEMODE = 0x09 # Decode mode register (BCD decode control)
INTENSITY = 0x0A # Intensity register (LED brightness: 0x00-0x0F)
SCANLIMIT = 0x0B # Scan limit register (number of digits to display)
SHUTDOWN = 0x0C # Shutdown register (normal/shutdown mode)
DISPLAYTEST = 0x0F # Display test register (test mode on/off)Character-to-segment pattern conversion functions for seven-segment displays.
def regular(text, notfound="_"):
"""
Map text characters to 7-segment display patterns using standard character set.
Parameters:
- text: String to convert to segment patterns
- notfound: Character to use for unmappable characters (default: "_")
Returns:
- Generator yielding segment bit patterns as integers
Yields:
- int: 8-bit pattern where each bit represents a segment (MSB unused)
Bit layout: 0GFEDCBA (A=top, B=top-right, C=bottom-right,
D=bottom, E=bottom-left, F=top-left, G=middle)
"""
def dot_muncher(text, notfound="_"):
"""
Map text with decimal point handling for 7-segment displays.
Combines dots with previous characters to save display positions.
Parameters:
- text: String to convert (dots after characters combine with previous char)
- notfound: Character to use for unmappable characters (default: "_")
Returns:
- Generator yielding segment patterns with dot integration
Yields:
- int: 8-bit pattern with dot bit (MSB) for decimal point display
Bit layout: DGFEDCBA (D=dot/decimal point, others same as regular)
Example:
- "12.34" becomes 3 patterns: "1", "2.", "3", "4"
- The "2." combines digit 2 with decimal point bit
"""from luma.led_matrix.const import max7219 as max7219_const
from luma.core.interface.serial import spi, noop
# Low-level register access (normally handled by max7219 device class)
serial = spi(port=0, device=0, gpio=noop())
# Set intensity to maximum
serial.write([max7219_const.INTENSITY, 0x0F])
# Enable normal operation (exit shutdown)
serial.write([max7219_const.SHUTDOWN, 0x01])
# Set scan limit to display all 8 digits
serial.write([max7219_const.SCANLIMIT, 0x07])from luma.led_matrix.segment_mapper import regular, dot_muncher
# Basic character mapping
text = "HELLO"
patterns = list(regular(text))
print([f"0x{p:02X}" for p in patterns])
# Output: ['0x76', '0x79', '0x38', '0x38', '0x5C']
# Handle unmappable characters
text = "HI@"
patterns = list(regular(text, notfound="?"))
# @ maps to ?, which maps to 0x00 (no segments)
# Decimal point handling
text = "12.34"
regular_patterns = list(regular(text))
print(f"Regular: {len(regular_patterns)} patterns") # 5 patterns
dot_patterns = list(dot_muncher(text))
print(f"Dot muncher: {len(dot_patterns)} patterns") # 4 patterns
# Second pattern will have decimal point bit setfrom luma.led_matrix.segment_mapper import regular
from luma.led_matrix.device import neopixel
from luma.core.render import canvas
# Create custom segment display using mapping functions
def display_text_on_segments(device, text, color=(255, 255, 255)):
"""Display text using direct segment patterns."""
patterns = list(regular(text))
# Assume 7 LEDs per digit arranged as segments
# This is a simplified example - real implementation would
# need proper LED addressing for segment layout
for digit_pos, pattern in enumerate(patterns):
for segment in range(7):
if pattern & (1 << segment):
# Calculate LED position for this segment
led_index = digit_pos * 7 + segment
# Set LED color (implementation depends on device layout)
# This would require custom canvas drawing or direct LED control
# Usage with neosegment device
device = neopixel(cascaded=28) # 4 digits × 7 segments
display_text_on_segments(device, "TEST")from luma.led_matrix.segment_mapper import _DIGITS
# View supported characters
print("Supported characters:")
for char, pattern in sorted(_DIGITS.items()):
print(f"'{char}': 0x{pattern:02X}")
# The _DIGITS dictionary contains mappings like:
# '0': 0x3F, '1': 0x06, '2': 0x5B, '3': 0x4F, '4': 0x66
# 'A': 0x77, 'B': 0x7C, 'C': 0x39, 'D': 0x5E, 'E': 0x79, 'F': 0x71
# 'H': 0x76, 'L': 0x38, 'P': 0x73, 'U': 0x3E
# '-': 0x40, '_': 0x08, '"': 0x22, etc.from luma.led_matrix.segment_mapper import dot_muncher
from luma.led_matrix.device import neosegment
display = neosegment(width=4)
# Display temperature like "72.5"
temp = 72.5
temp_text = f"{temp:.1f}"
# Use dot_muncher to handle decimal point efficiently
patterns = list(dot_muncher(temp_text))
print(f"Temperature '{temp_text}' uses {len(patterns)} digit positions")
# Display normally - neosegment handles the segment patterns internally
display.text = temp_textDigits: 0123456789
Letters: ABCDEFHLPU (uppercase), rnot (lowercase representations)
Symbols: - _ " ' ° and various special characters
Seven-segment displays use a 7-bit pattern (plus optional decimal point):
AAA
F B
F B
GGG
E C
E C
DDD [DP]Bit positions: 0GFEDCBA (bit 7 unused in regular mapping, used for decimal in dot_muncher)
Example with "12.34":
['1', '2', '.', '3', '4'] → 5 positions['1', '2.', '3', '4'] → 4 positionsInstall with Tessl CLI
npx tessl i tessl/pypi-luma--led-matrix