Skip to content

Commit

Permalink
Port to gpiod/gpiodevice.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gadgetoid committed Nov 8, 2023
1 parent 47fc5e1 commit 8e6cee4
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 83 deletions.
12 changes: 6 additions & 6 deletions examples/framerate.py
Expand Up @@ -24,9 +24,9 @@

from PIL import Image, ImageDraw

import ST7735 as ST7735
import st7735

SPI_SPEED_MHZ = 10 # Higher speed = higher framerate
SPI_SPEED_MHZ = 4 # Higher speed = higher framerate

if len(sys.argv) > 1:
SPI_SPEED_MHZ = int(sys.argv[1])
Expand All @@ -41,11 +41,11 @@
""".format(SPI_SPEED_MHZ))

# Create ST7735 LCD display class.
disp = ST7735.ST7735(
disp = st7735.ST7735(
port=0,
cs=ST7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc=9,
backlight=19, # 18 for back BG slot, 19 for front BG slot.
cs=st7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc="PIN21",
backlight="PIN35", # 18 for back BG slot, 19 for front BG slot.
rotation=90,
spi_speed_hz=SPI_SPEED_MHZ * 1000000
)
Expand Down
10 changes: 5 additions & 5 deletions examples/gif.py
Expand Up @@ -23,7 +23,7 @@

from PIL import Image

import ST7735
import st7735

print("""
gif.py - Display a gif on the LCD.
Expand All @@ -39,11 +39,11 @@
sys.exit(0)

# Create TFT LCD display class.
disp = ST7735.ST7735(
disp = st7735.ST7735(
port=0,
cs=ST7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc=9,
backlight=19, # 18 for back BG slot, 19 for front BG slot.
cs=st7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc="GPIO9",
backlight="GPIO19", # 18 for back BG slot, 19 for front BG slot.
spi_speed_hz=4000000
)

Expand Down
10 changes: 5 additions & 5 deletions examples/image.py
Expand Up @@ -22,7 +22,7 @@

from PIL import Image

import ST7735 as ST7735
import st7735

print("""
image.py - Display an image on the LCD.
Expand All @@ -38,11 +38,11 @@
image_file = sys.argv[1]

# Create ST7735 LCD display class.
disp = ST7735.ST7735(
disp = st7735.ST7735(
port=0,
cs=ST7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc=9,
backlight=19, # 18 for back BG slot, 19 for front BG slot.
cs=st7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc="GPIO9",
backlight="GPIO19", # 18 for back BG slot, 19 for front BG slot.
rotation=90,
spi_speed_hz=4000000
)
Expand Down
10 changes: 5 additions & 5 deletions examples/scrolling-text.py
Expand Up @@ -2,16 +2,16 @@

from PIL import Image, ImageDraw, ImageFont

import ST7735
import st7735

MESSAGE = "Hello World! How are you today?"

# Create ST7735 LCD display class.
disp = ST7735.ST7735(
disp = st7735.ST7735(
port=0,
cs=ST7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc=9,
backlight=19, # 18 for back BG slot, 19 for front BG slot.
cs=st7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc="GPIO9",
backlight="GPIO19", # 18 for back BG slot, 19 for front BG slot.
rotation=90,
spi_speed_hz=10000000
)
Expand Down
10 changes: 5 additions & 5 deletions examples/shapes.py
Expand Up @@ -20,7 +20,7 @@
# THE SOFTWARE.
from PIL import Image, ImageDraw, ImageFont

import ST7735
import st7735

print("""
shapes.py - Display test shapes on the LCD using PIL.
Expand All @@ -31,11 +31,11 @@
""")

# Create ST7735 LCD display class.
disp = ST7735.ST7735(
disp = st7735.ST7735(
port=0,
cs=ST7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc=9,
backlight=19, # 18 for back BG slot, 19 for front BG slot.
cs=st7735.BG_SPI_CS_FRONT, # BG_SPI_CSB_BACK or BG_SPI_CS_FRONT
dc="GPIO9",
backlight="GPIO19", # 18 for back BG slot, 19 for front BG slot.
rotation=90,
spi_speed_hz=4000000
)
Expand Down
40 changes: 22 additions & 18 deletions st7735/__init__.py
Expand Up @@ -20,12 +20,17 @@
# THE SOFTWARE.
import numbers
import time

import numpy as np
import RPi.GPIO as GPIO

import spidev
import gpiod
import gpiodevice
from gpiod.line import Direction, Value


__version__ = "0.0.5"
__version__ = '0.0.5'

OUTL = gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE)

BG_SPI_CS_BACK = 0
BG_SPI_CS_FRONT = 1
Expand Down Expand Up @@ -121,9 +126,9 @@ def __init__(self, port, cs, dc, backlight=None, rst=None, width=ST7735_TFTWIDTH
height=ST7735_TFTHEIGHT, rotation=90, offset_left=None, offset_top=None, invert=True, bgr=True, spi_speed_hz=4000000):
"""Create an instance of the display using SPI communication.
Must provide the GPIO pin number for the D/C pin and the SPI driver.
Must provide the GPIO pin label for the D/C pin and the SPI driver.
Can optionally provide the GPIO pin number for the reset pin as the rst parameter.
Can optionally provide the GPIO pin label for the reset pin as the rst parameter.
:param port: SPI port number
:param cs: SPI chip-select number (0 or 1 for BCM
Expand All @@ -139,9 +144,6 @@ def __init__(self, port, cs, dc, backlight=None, rst=None, width=ST7735_TFTWIDTH
"""

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

self._spi = spidev.SpiDev(port, cs)
self._spi.mode = 0
self._spi.lsbfirst = False
Expand All @@ -167,20 +169,22 @@ def __init__(self, port, cs, dc, backlight=None, rst=None, width=ST7735_TFTWIDTH

self._offset_top = offset_top

gpiodevice.friendly_errors = True

# Set DC as output.
GPIO.setup(dc, GPIO.OUT)
self._dc_lines, self._dc_line = gpiodevice.get_pin(dc, "st7735-dc", OUTL)

# Setup backlight as output (if provided).
self._backlight = backlight
if backlight is not None:
GPIO.setup(backlight, GPIO.OUT)
GPIO.output(backlight, GPIO.LOW)
self._bl_lines, self._bl_line = gpiodevice.get_pin(backlight, "st7735-bl", OUTL)
self._bl_lines.set_value(self._bl_line, Value.INACTIVE)
time.sleep(0.1)
GPIO.output(backlight, GPIO.HIGH)
self._bl_lines.set_value(self._bl_line, Value.ACTIVE)

# Setup reset as output (if provided).
if rst is not None:
GPIO.setup(rst, GPIO.OUT)
self._rst_lines, self._rst_line = gpiodevice.get_pin(rst, "st7735-rst", OUTL)

self.reset()
self._init()
Expand All @@ -192,7 +196,7 @@ def send(self, data, is_data=True, chunk_size=4096):
single SPI transaction, with a default of 4096.
"""
# Set DC low for command, high for data.
GPIO.output(self._dc, is_data)
self._dc_lines.set_value(self._dc_line, Value.ACTIVE if is_data else Value.INACTIVE)
# Convert scalar argument to list so either can be passed as parameter.
if isinstance(data, numbers.Number):
data = [data & 0xFF]
Expand All @@ -201,7 +205,7 @@ def send(self, data, is_data=True, chunk_size=4096):
def set_backlight(self, value):
"""Set the backlight on/off."""
if self._backlight is not None:
GPIO.output(self._backlight, value)
self._bl_lines.set_value(self._bl_line, Value.ACTIVE if value else Value.INACTIVE)

def display_off(self):
self.command(ST7735_DISPOFF)
Expand Down Expand Up @@ -234,11 +238,11 @@ def data(self, data):
def reset(self):
"""Reset the display, if reset pin is connected."""
if self._rst is not None:
GPIO.output(self._rst, 1)
self._rst_lines.set_value(self._rst_line, Value.ACTIVE)
time.sleep(0.500)
GPIO.output(self._rst, 0)
self._rst_lines.set_value(self._rst_line, Value.INACTIVE)
time.sleep(0.500)
GPIO.output(self._rst, 1)
self._rst_lines.set_value(self._rst_line, Value.ACTIVE)
time.sleep(0.500)

def _init(self):
Expand Down
25 changes: 15 additions & 10 deletions tests/conftest.py
Expand Up @@ -16,16 +16,21 @@ def st7735():


@pytest.fixture(scope='function', autouse=False)
def GPIO():
"""Mock RPi.GPIO module."""
GPIO = mock.MagicMock()
# Fudge for Python < 37 (possibly earlier)
sys.modules['RPi'] = mock.Mock()
sys.modules['RPi'].GPIO = GPIO
sys.modules['RPi.GPIO'] = GPIO
yield GPIO
del sys.modules['RPi']
del sys.modules['RPi.GPIO']
def gpiod():
"""Mock gpiod module."""
sys.modules['gpiod'] = mock.MagicMock()
sys.modules['gpiod.line'] = mock.MagicMock()
yield sys.modules['gpiod']
del sys.modules['gpiod']


@pytest.fixture(scope='function', autouse=False)
def gpiodevice():
"""Mock gpiodevice module."""
sys.modules['gpiodevice'] = mock.MagicMock()
sys.modules['gpiodevice'].get_pin.return_value = (mock.Mock(), 0)
yield sys.modules['gpiodevice']
del sys.modules['gpiodevice']


@pytest.fixture(scope='function', autouse=False)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_dimensions.py
@@ -1,10 +1,10 @@
def test_128_64_0(GPIO, spidev, numpy, st7735):
def test_128_64_0(gpiodevice, gpiod, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24, width=128, height=64, rotation=0)
assert display.width == 128
assert display.height == 64


def test_128_64_90(GPIO, spidev, numpy, st7735):
def test_128_64_90(gpiodevice, gpiod, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24, width=128, height=64, rotation=90)
assert display.width == 64
assert display.height == 128
6 changes: 3 additions & 3 deletions tests/test_features.py
@@ -1,18 +1,18 @@
import mock


def test_display(GPIO, spidev, numpy, st7735):
def test_display(gpiodevice, gpiod, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24)
numpy.dstack().flatten().tolist.return_value = [0xff, 0x00, 0xff, 0x00]
display.display(mock.MagicMock())

spidev.SpiDev().xfer3.assert_called_with([0xff, 0x00, 0xff, 0x00])


def test_color565(GPIO, spidev, numpy, st7735):
def test_color565(gpiodevice, gpiod, spidev, numpy, st7735):
assert st7735.color565(255, 255, 255) == 0xFFFF


def test_image_to_data(GPIO, spidev, numpy, st7735):
def test_image_to_data(gpiodevice, gpiod, spidev, numpy, st7735):
numpy.dstack().flatten().tolist.return_value = []
assert st7735.image_to_data(mock.MagicMock()) == []
41 changes: 17 additions & 24 deletions tests/test_setup.py
@@ -1,38 +1,31 @@
import mock


def test_setup(GPIO, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24)
del display
def test_setup(gpiodevice, gpiod, spidev, numpy, st7735):
_ = st7735.ST7735(port=0, cs=0, dc="GPIO24")

GPIO.output.assert_has_calls([
mock.call(24, True),
mock.call(24, False)
gpiodevice.get_pin.assert_has_calls([
mock.call("GPIO24", "st7735-dc", st7735.OUTL)
], any_order=True)


def test_setup_no_invert(GPIO, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24, invert=False)
del display
def test_setup_no_invert(gpiodevice, gpiod, spidev, numpy, st7735):
_ = st7735.ST7735(port=0, cs=0, dc="GPIO24", invert=False)


def test_setup_with_backlight(GPIO, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24, backlight=4)
GPIO.setup.assert_called_with(4, GPIO.OUT)
def test_setup_with_backlight(gpiodevice, gpiod, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc="GPIO24", backlight="GPIO4")

display.set_backlight(GPIO.HIGH)
display.set_backlight(True)

GPIO.output.assert_has_calls([
mock.call(4, GPIO.LOW),
mock.call(4, GPIO.HIGH),
# Dozens of falls with True/False here
# due to _init() being called and the display
# setup setting the command/data pin
mock.call(4, GPIO.HIGH)
gpiodevice.get_pin.assert_has_calls([
mock.call("GPIO4", "st7735-bl", st7735.OUTL)
], any_order=True)


def test_setup_with_reset(GPIO, spidev, numpy, st7735):
display = st7735.ST7735(port=0, cs=0, dc=24, rst=4)
GPIO.setup.assert_called_with(4, GPIO.OUT)
del display
def test_setup_with_reset(gpiodevice, gpiod, spidev, numpy, st7735):
_ = st7735.ST7735(port=0, cs=0, dc=24, rst="GPIO4")

gpiodevice.get_pin.assert_has_calls([
mock.call("GPIO4", "st7735-rst", st7735.OUTL)
], any_order=True)

0 comments on commit 8e6cee4

Please sign in to comment.