Source code for adafruit_max7219.matrices

# SPDX-FileCopyrightText: 2017 Dan Halbert for Adafruit Industries
# SPDX-FileCopyrightText: 2021 Daniel Flanagan
#
# SPDX-License-Identifier: MIT

"""
`adafruit_max7219.matrices`
====================================================
"""
from micropython import const
from adafruit_framebuf import BitmapFont
from adafruit_max7219 import max7219

try:
    # Used only for typing
    from typing import Tuple
    import digitalio
    import busio
except ImportError:
    pass

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MAX7219.git"

_DECODEMODE = const(9)
_SCANLIMIT = const(11)
_SHUTDOWN = const(12)
_DISPLAYTEST = const(15)


[docs] class Matrix8x8(max7219.MAX7219): """ Driver for a 8x8 LED matrix based on the MAX7219 chip. :param ~busio.SPI spi: an spi busio or spi bitbangio object :param ~digitalio.DigitalInOut cs: digital in/out to use as chip select signal """ def __init__(self, spi: busio.SPI, cs: digitalio.DigitalInOut): super().__init__(8, 8, spi, cs)
[docs] def init_display(self) -> None: for cmd, data in ( (_SHUTDOWN, 0), (_DISPLAYTEST, 0), (_SCANLIMIT, 7), (_DECODEMODE, 0), (_SHUTDOWN, 1), ): self.write_cmd(cmd, data) self.fill(0) self.show()
[docs] def text( self, strg: str, xpos: int, ypos: int, bit_value: int = 1, *, font_name: str = "font5x8.bin" ) -> None: """ Draw text in the 8x8 matrix. :param str strg: string to place in to display :param int xpos: x position of LED in matrix :param int ypos: y position of LED in matrix :param int bit_value: > 1 sets the text, otherwise resets :param str font_name: path to binary font file (default: "font5x8.bin"). The font can only be set once, if you want a different font you must re-initialize the matrix. """ self.framebuf.text(strg, xpos, ypos, bit_value, font_name=font_name)
[docs] def clear_all(self) -> None: """ Clears all matrix leds. """ self.fill(0)
[docs] class CustomMatrix(max7219.ChainableMAX7219): """ Driver for a custom 8x8 LED matrix constellation based on daisy chained MAX7219 chips. :param ~busio.SPI spi: an spi busio or spi bitbangio object :param ~digitalio.DigitalInOut cs: digital in/out to use as chip select signal :param int width: the number of pixels wide :param int height: the number of pixels high :param int rotation: the number of times to rotate the coordinate system (default 1) """ def __init__( self, spi: busio.SPI, cs: digitalio.DigitalInOut, width: int, height: int, *, rotation: int = 1 ): super().__init__(width, height, spi, cs) self.y_offset = width // 8 self.y_index = self._calculate_y_coordinate_offsets() self.framebuf.rotation = rotation self.framebuf.fill_rect = self._fill_rect self._font = None def _calculate_y_coordinate_offsets(self) -> None: y_chunks = [] for _ in range(self.chain_length // (self.width // 8)): y_chunks.append([]) chunk = 0 chunk_size = 0 for index in range(self.chain_length * 8): y_chunks[chunk].append(index) chunk_size += 1 if chunk_size >= (self.width // 8): chunk_size = 0 chunk += 1 if chunk >= len(y_chunks): chunk = 0 y_index = [] for chunk in y_chunks: y_index += chunk return y_index
[docs] def init_display(self) -> None: for cmd, data in ( (_SHUTDOWN, 0), (_DISPLAYTEST, 0), (_SCANLIMIT, 7), (_DECODEMODE, 0), (_SHUTDOWN, 1), ): self.write_cmd(cmd, data) self.fill(0) self.show()
[docs] def clear_all(self) -> None: """ Clears all matrix leds. """ self.fill(0)
# pylint: disable=inconsistent-return-statements
[docs] def pixel(self, xpos: int, ypos: int, bit_value: int = None) -> None: """ Set one buffer bit :param int xpos: x position to set bit :param int ypos: y position to set bit :param int bit_value: value > 0 sets the buffer bit, else clears the buffer bit """ if xpos < 0 or ypos < 0 or xpos >= self.width or ypos >= self.height: return buffer_x, buffer_y = self._pixel_coords_to_framebuf_coords(xpos, ypos) return super().pixel(buffer_x, buffer_y, bit_value=bit_value)
def _pixel_coords_to_framebuf_coords(self, xpos: int, ypos: int) -> Tuple[int]: """ Convert matrix pixel coordinates into coordinates in the framebuffer :param int xpos: x position :param int ypos: y position :return: framebuffer coordinates (x, y) :rtype: Tuple[int] """ return (xpos - ((xpos // 8) * 8)) % 8, xpos // 8 + self.y_index[ ypos * self.y_offset ] def _get_pixel(self, xpos: int, ypos: int) -> int: """ Get value of a matrix pixel :param int xpos: x position :param int ypos: y position :return: value of pixel in matrix :rtype: int """ x, y = self._pixel_coords_to_framebuf_coords(xpos, ypos) buffer_value = self._buffer[-1 * y - 1] return ((buffer_value & 2**x) >> x) & 1 # Adafruit Circuit Python Framebuf Scroll Function # Authors: Kattni Rembor, Melissa LeBlanc-Williams and Tony DiCola, for Adafruit Industries # License: MIT License (https://opensource.org/licenses/MIT)
[docs] def scroll(self, delta_x: int, delta_y: int) -> None: """ Srcolls the display using delta_x, delta_y. :param int delta_x: positions to scroll in the x direction :param int delta_y: positions to scroll in the y direction """ if delta_x < 0: shift_x = 0 xend = self.width + delta_x dt_x = 1 else: shift_x = self.width - 1 xend = delta_x - 1 dt_x = -1 if delta_y < 0: y = 0 yend = self.height + delta_y dt_y = 1 else: y = self.height - 1 yend = delta_y - 1 dt_y = -1 while y != yend: x = shift_x while x != xend: self.pixel(x, y, self._get_pixel(x - delta_x, y - delta_y)) x += dt_x y += dt_y
[docs] def rect( self, x: int, y: int, width: int, height: int, color: int, fill: bool = False ) -> None: """ Draw a rectangle at the given position of the given size, color, and fill. :param int x: x position :param int y: y position :param int width: width of rectangle :param int height: height of rectangle :param int color: color of rectangle :param bool fill: 1 pixel outline or filled rectangle (default: False) """ # pylint: disable=too-many-arguments for row in range(height): y_pos = row + y for col in range(width): x_pos = col + x if fill: self.pixel(x_pos, y_pos, color) elif y_pos in (y, y + height - 1) or x_pos in (x, x + width - 1): self.pixel(x_pos, y_pos, color) else: continue
def _fill_rect(self, x: int, y: int, width: int, height: int, color: int) -> None: """ Draw a filled rectangle at the given position of the given size, color. :param int x: x position :param int y: y position :param int width: width of rectangle :param int height: height of rectangle :param int color: color of rectangle """ # pylint: disable=too-many-arguments return self.rect(x, y, width, height, color, True) # Adafruit Circuit Python Framebuf Text Function # Authors: Kattni Rembor, Melissa LeBlanc-Williams and Tony DiCola, for Adafruit Industries # License: MIT License (https://opensource.org/licenses/MIT)
[docs] def text( self, strg: str, xpos: int, ypos: int, color: int = 1, *, font_name: str = "font5x8.bin", size: int = 1 ) -> None: """ Draw text in the matrix. :param str strg: string to place in to display :param int xpos: x position of LED in matrix :param int ypos: y position of LED in matrix :param int color: > 1 sets the text, otherwise resets :param str font_name: path to binary font file (default: "font5x8.bin") :param int size: size of the font, acts as a multiplier """ for chunk in strg.split("\n"): if not self._font or self._font.font_name != font_name: # load the font! self._font = BitmapFont(font_name) width = self._font.font_width height = self._font.font_height for i, char in enumerate(chunk): char_x = xpos + (i * (width + 1)) * size if ( char_x + (width * size) > 0 and char_x < self.width and ypos + (height * size) > 0 and ypos < self.height ): self._font.draw_char( char, char_x, ypos, self.framebuf, color, size=size ) ypos += height * size