Skip to content

Commit

Permalink
Changed block_orientation valid parameters
Browse files Browse the repository at this point in the history
Used to take “horizontal” or “vertical”, now additionally allows 0, 90,
-90.
The strings are marked as deprecated and are no longer documented, but
are still supported up until the next major version.
  • Loading branch information
rm-hull committed Mar 18, 2017
1 parent a10fe14 commit ad7638c
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Expand Up @@ -4,6 +4,8 @@ ChangeLog
+------------+------------------------------------------------------------------------+------------+
| Version | Description | Date |
+============+========================================================================+============+
| *Upcoming* | * Change MAX7219's block_orientation to support ±90° angle correction | |
+------------+------------------------------------------------------------------------+------------+
| **0.7.0** | * **BREAKING CHANGE:** Move sevensegment class to | 2017/03/04 |
| | ``luma.led_matrix.virtual`` package | |
| | * Documentation updates & corrections | |
Expand Down
6 changes: 3 additions & 3 deletions doc/install.rst
Expand Up @@ -126,17 +126,17 @@ matrices::

$ python examples/matrix_demo.py -h
usage: matrix_demo.py [-h] [--cascaded CASCADED]
[--block-orientation {horizontal,vertical}]
[--block-orientation {0, 90, -90}]

matrix_demo arguments

optional arguments:
-h, --help show this help message and exit
--cascaded CASCADED, -n CASCADED
Number of cascaded MAX7219 LED matrices (default: 1)
--block-orientation {horizontal,vertical}
--block-orientation {0, 90, -90}
Corrects block orientation when wired vertically
(default: horizontal)
(default: 0)

Similarly, there is a basic demo of the capabilities of the
:py:class:`luma.led_matrix.virtual.sevensegment` wrapper::
Expand Down
9 changes: 5 additions & 4 deletions doc/python-usage.rst
Expand Up @@ -179,7 +179,7 @@ below,
from luma.led_matrix.device import max7219
from luma.core.legacy.font import proportional, LCD_FONT
serial = spi(port=0, device=0, gpio=noop(), block_orientation="vertical")
serial = spi(port=0, device=0, gpio=noop(), block_orientation=-90)
device = max7219(serial, width=32, height=24)
with canvas(device) as draw:
Expand All @@ -202,8 +202,9 @@ out-of-phase such that horizontal scrolling appears as below:
.. image:: images/block_reorientation.gif
:alt: block alignment

This can be rectified by initializing the :py:class:`~luma.led_matrix.device.max7219`
device with a parameter of :py:attr:`block_orientation="vertical"`:
This can be rectified by initializing the :py:class:`~luma.led_matrix.device.max7219`
device with a parameter of :py:attr:`block_orientation=-90` (or +90, if your device is
aligned the other way):

.. code:: python
Expand All @@ -212,7 +213,7 @@ device with a parameter of :py:attr:`block_orientation="vertical"`:
from luma.led_matrix.device import max7219
serial = spi(port=0, device=0, gpio=noop())
device = max7219(serial, cascaded=4, block_orientation="vertical")
device = max7219(serial, cascaded=4, block_orientation=-90)
Every time a display render is subsequenly requested, the underlying image
representation is corrected to reverse the 90° phase shift.
Expand Down
2 changes: 1 addition & 1 deletion examples/box_demo.py
Expand Up @@ -33,7 +33,7 @@ def demo(w, h, block_orientation, rotate):

parser.add_argument('--width', type=int, default=8, help='Width')
parser.add_argument('--height', type=int, default=8, help='height')
parser.add_argument('--block-orientation', type=str, default='vertical', choices=['horizontal', 'vertical'], help='Corrects block orientation when wired vertically')
parser.add_argument('--block-orientation', type=int, default=-90, choices=[0, 90, -90], help='Corrects block orientation when wired vertically')
parser.add_argument('--rotate', type=int, default=0, choices=[0, 1, 2, 3], help='Rotation factor')

args = parser.parse_args()
Expand Down
2 changes: 1 addition & 1 deletion examples/matrix_demo.py
Expand Up @@ -111,7 +111,7 @@ def demo(n, block_orientation):
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

parser.add_argument('--cascaded', '-n', type=int, default=1, help='Number of cascaded MAX7219 LED matrices')
parser.add_argument('--block-orientation', type=str, default='horizontal', choices=['horizontal', 'vertical'], help='Corrects block orientation when wired vertically')
parser.add_argument('--block-orientation', type=str, default=0, choices=[0, 90, -90], help='Corrects block orientation when wired vertically')

args = parser.parse_args()

Expand Down
35 changes: 27 additions & 8 deletions luma/led_matrix/device.py
Expand Up @@ -30,6 +30,7 @@

from luma.core.serial import noop
from luma.core.device import device
from luma.core.util import deprecation
import luma.core.error
import luma.led_matrix.const

Expand All @@ -45,7 +46,7 @@ class max7219(device):
commands can then be called to affect the brightness and other settings.
"""
def __init__(self, serial_interface=None, width=8, height=8, cascaded=None, rotate=0,
block_orientation="horizontal", **kwargs):
block_orientation=0, **kwargs):
super(max7219, self).__init__(luma.led_matrix.const.max7219, serial_interface)

# Derive (override) the width and height if a cascaded param supplied
Expand All @@ -59,9 +60,27 @@ def __init__(self, serial_interface=None, width=8, height=8, cascaded=None, rota
raise luma.core.error.DeviceDisplayModeError(
"Unsupported display mode: {0} x {1}".format(width, height))

assert block_orientation in [0, 90, -90, "horizontal", "vertical"]
if block_orientation == "vertical":
msg = (
"WARNING! block_orientation=\"vertical\" is now deprecated and "
"should be changed to block_orientation=-90 to acheive the same "
"effect. Use of \"vertical\" will be removed entirely beginning "
"v1.0.0")
deprecation(msg)
self._correction_angle = -90
elif block_orientation == "horizontal":
msg = (
"WARNING! block_orientation=\"horizontal\" is now deprecated and "
"should be changed to block_orientation=0 to acheive the same "
"effect. Use of \"horizontal\" will be removed entirely beginning "
"v1.0.0")
deprecation(msg)
self._correction_angle = 0
else:
self._correction_angle = block_orientation

self.cascaded = cascaded or (width * height) // 64
assert(block_orientation in ["horizontal", "vertical"])
self._block_orientation = block_orientation
self._offsets = [(y * self._w) + x
for y in range(self._h - 8, -8, -8)
for x in range(self._w - 8, -8, -8)]
Expand All @@ -77,18 +96,18 @@ def __init__(self, serial_interface=None, width=8, height=8, cascaded=None, rota

def preprocess(self, image):
"""
Performs the inherited behviour (if any), and if the LED matrix is
declared to being a common row cathode, each 8x8 block of pixels
is rotated 90° clockwise.
Performs the inherited behviour (if any), and if the LED matrix
orientation is declared to need correction, each 8x8 block of pixels
is rotated 90° clockwise or counter-clockwise.
"""
image = super(max7219, self).preprocess(image)

if self._block_orientation == "vertical":
if self._correction_angle != 0:
image = image.copy()
for y in range(0, self._h, 8):
for x in range(0, self._w, 8):
box = (x, y, x + 8, y + 8)
rotated_block = image.crop(box).rotate(-90)
rotated_block = image.crop(box).rotate(self._correction_angle)
image.paste(rotated_block, box)

return image
Expand Down
7 changes: 4 additions & 3 deletions luma/led_matrix/legacy.py
Expand Up @@ -8,7 +8,8 @@


# trigger DeprecationWarning
deprecation_msg = ("WARNING! 'luma.led_matrix.legacy' is now deprecated and will be removed in "
"v1.0.0. Please use the equivalent functionality from "
"'luma.core.legacy' and 'luma.core.legacy.font'.")
deprecation_msg = (
"WARNING! 'luma.led_matrix.legacy' is now deprecated and will be removed in "
"v1.0.0. Please use the equivalent functionality from "
"'luma.core.legacy' and 'luma.core.legacy.font'.")
deprecation(deprecation_msg)
33 changes: 30 additions & 3 deletions tests/test_max7219.py
Expand Up @@ -4,6 +4,7 @@
# See LICENSE.rst for details.

import pytest
import warnings

from luma.led_matrix.device import max7219
from luma.core.render import canvas
Expand Down Expand Up @@ -121,7 +122,7 @@ def test_display_16x16():


def test_normal_alignment():
device = max7219(serial, cascaded=2, block_orientation="horizontal")
device = max7219(serial, cascaded=2, block_orientation=0)
serial.reset_mock()

with canvas(device) as draw:
Expand All @@ -139,8 +140,8 @@ def test_normal_alignment():
])


def test_block_realignment():
device = max7219(serial, cascaded=2, block_orientation="vertical")
def test_block_realignment_minus90():
device = max7219(serial, cascaded=2, block_orientation=-90)
serial.reset_mock()

with canvas(device) as draw:
Expand All @@ -158,6 +159,32 @@ def test_block_realignment():
])


def test_block_realignment_plus90():
device = max7219(serial, cascaded=2, block_orientation=90)
serial.reset_mock()

with canvas(device) as draw:
draw.rectangle((0, 0, 15, 3), outline="white")

serial.data.assert_has_calls([
call([1, 0xFF, 1, 0xFF]),
call([2, 0x01, 2, 0x80]),
call([3, 0x01, 3, 0x80]),
call([4, 0xFF, 4, 0xFF]),
call([5, 0x00, 5, 0x00]),
call([6, 0x00, 6, 0x00]),
call([7, 0x00, 7, 0x00]),
call([8, 0x00, 8, 0x00])
])


def test_unknown_block_orientation():
with pytest.raises(AssertionError):
max7219(serial, cascaded=2, block_orientation="sausages")


def test_deprecated_block_orientation(recwarn):
warnings.simplefilter('always')
max7219(serial, cascaded=2, block_orientation="vertical")
max7219(serial, cascaded=2, block_orientation="horizontal")
assert len(recwarn) == 2

0 comments on commit ad7638c

Please sign in to comment.