mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
Doh! SPI tests fail when the spidev package is installed (which it normally isn't in my virtualenv) because hardware SPI always takes precedence and the mock SPI stuff only replaces software SPI.
198 lines
8.1 KiB
Python
198 lines
8.1 KiB
Python
from __future__ import (
|
|
unicode_literals,
|
|
absolute_import,
|
|
print_function,
|
|
division,
|
|
)
|
|
nstr = str
|
|
str = type('')
|
|
|
|
|
|
import sys
|
|
import pytest
|
|
from array import array
|
|
from mock import patch
|
|
from collections import namedtuple
|
|
|
|
from gpiozero.pins.native import NativeFactory
|
|
from gpiozero.pins.local import (
|
|
LocalPiHardwareSPI,
|
|
LocalPiSoftwareSPI,
|
|
LocalPiHardwareSPIShared,
|
|
LocalPiSoftwareSPIShared,
|
|
)
|
|
from gpiozero.pins.mock import MockSPIDevice
|
|
from gpiozero import *
|
|
|
|
|
|
def teardown_function(function):
|
|
Device._pin_factory.reset()
|
|
|
|
|
|
def test_spi_hardware_params():
|
|
with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
|
|
mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
|
|
io_open.return_value.__enter__.return_value = ['Revision: a21042']
|
|
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
|
|
patch('gpiozero.pins.local.SpiDev'):
|
|
with Device._pin_factory.spi() as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(port=0, device=0) as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(port=0, device=1) as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(clock_pin=11) as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=8) as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=7) as device:
|
|
assert isinstance(device, LocalPiHardwareSPI)
|
|
with Device._pin_factory.spi(shared=True) as device:
|
|
assert isinstance(device, LocalPiHardwareSPIShared)
|
|
with pytest.raises(ValueError):
|
|
Device._pin_factory.spi(port=1)
|
|
with pytest.raises(ValueError):
|
|
Device._pin_factory.spi(device=2)
|
|
with pytest.raises(ValueError):
|
|
Device._pin_factory.spi(port=0, clock_pin=12)
|
|
with pytest.raises(ValueError):
|
|
Device._pin_factory.spi(foo='bar')
|
|
|
|
def test_spi_software_params():
|
|
with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
|
|
mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
|
|
io_open.return_value.__enter__.return_value = ['Revision: a21042']
|
|
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
|
|
patch('gpiozero.pins.local.SpiDev'):
|
|
with Device._pin_factory.spi(select_pin=6) as device:
|
|
assert isinstance(device, LocalPiSoftwareSPI)
|
|
with Device._pin_factory.spi(clock_pin=11, mosi_pin=9, miso_pin=10) as device:
|
|
assert isinstance(device, LocalPiSoftwareSPI)
|
|
with Device._pin_factory.spi(select_pin=6, shared=True) as device:
|
|
assert isinstance(device, LocalPiSoftwareSPIShared)
|
|
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
|
|
patch('gpiozero.pins.local.SpiDev', None):
|
|
# Clear out the old factory's pins cache (this is only necessary
|
|
# because we're being very naughty switching out pin factories)
|
|
Device._pin_factory.pins.clear()
|
|
# Ensure software fallback works when SpiDev isn't present
|
|
with Device._pin_factory.spi() as device:
|
|
assert isinstance(device, LocalPiSoftwareSPI)
|
|
|
|
def test_spi_hardware_conflict():
|
|
with patch('gpiozero.pins.local.SpiDev') as spidev:
|
|
with LED(11) as led:
|
|
with pytest.raises(GPIOPinInUse):
|
|
Device._pin_factory.spi(port=0, device=0)
|
|
with patch('gpiozero.pins.local.SpiDev') as spidev:
|
|
with Device._pin_factory.spi(port=0, device=0) as spi:
|
|
with pytest.raises(GPIOPinInUse):
|
|
LED(11)
|
|
|
|
def test_spi_hardware_read():
|
|
with patch('gpiozero.pins.local.SpiDev') as spidev:
|
|
spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
|
|
with Device._pin_factory.spi() as device:
|
|
assert device.read(3) == [0, 1, 2]
|
|
assert device.read(6) == list(range(6))
|
|
|
|
def test_spi_hardware_write():
|
|
with patch('gpiozero.pins.local.SpiDev') as spidev:
|
|
spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
|
|
with Device._pin_factory.spi() as device:
|
|
assert device.write([0, 1, 2]) == 3
|
|
assert spidev.return_value.xfer2.called_with([0, 1, 2])
|
|
assert device.write(list(range(6))) == 6
|
|
assert spidev.return_value.xfer2.called_with(list(range(6)))
|
|
|
|
def test_spi_hardware_modes():
|
|
with patch('gpiozero.pins.local.SpiDev') as spidev:
|
|
spidev.return_value.mode = 0
|
|
spidev.return_value.lsbfirst = False
|
|
spidev.return_value.cshigh = True
|
|
spidev.return_value.bits_per_word = 8
|
|
with Device._pin_factory.spi() as device:
|
|
assert device.clock_mode == 0
|
|
assert not device.clock_polarity
|
|
assert not device.clock_phase
|
|
device.clock_polarity = False
|
|
assert device.clock_mode == 0
|
|
device.clock_polarity = True
|
|
assert device.clock_mode == 2
|
|
device.clock_phase = True
|
|
assert device.clock_mode == 3
|
|
assert not device.lsb_first
|
|
assert device.select_high
|
|
assert device.bits_per_word == 8
|
|
device.select_high = False
|
|
device.lsb_first = True
|
|
device.bits_per_word = 12
|
|
assert not spidev.return_value.cshigh
|
|
assert spidev.return_value.lsbfirst
|
|
assert spidev.return_value.bits_per_word == 12
|
|
|
|
def test_spi_software_read():
|
|
class SPISlave(MockSPIDevice):
|
|
def on_start(self):
|
|
super(SPISlave, self).on_start()
|
|
for i in range(10):
|
|
self.tx_word(i)
|
|
with patch('gpiozero.pins.local.SpiDev', None), \
|
|
SPISlave(11, 10, 9, 8) as slave, \
|
|
Device._pin_factory.spi() as master:
|
|
assert master.read(3) == [0, 1, 2]
|
|
assert master.read(6) == [0, 1, 2, 3, 4, 5]
|
|
slave.clock_phase = True
|
|
master.clock_phase = True
|
|
assert master.read(3) == [0, 1, 2]
|
|
assert master.read(6) == [0, 1, 2, 3, 4, 5]
|
|
|
|
def test_spi_software_write():
|
|
with patch('gpiozero.pins.local.SpiDev', None), \
|
|
MockSPIDevice(11, 10, 9, 8) as test_device, \
|
|
Device._pin_factory.spi() as master:
|
|
master.write([0])
|
|
assert test_device.rx_word() == 0
|
|
master.write([2, 0])
|
|
assert test_device.rx_word() == 512
|
|
master.write([0, 1, 1])
|
|
assert test_device.rx_word() == 257
|
|
|
|
def test_spi_software_clock_mode():
|
|
with patch('gpiozero.pins.local.SpiDev', None), \
|
|
Device._pin_factory.spi() as master:
|
|
assert master.clock_mode == 0
|
|
assert not master.clock_polarity
|
|
assert not master.clock_phase
|
|
master.clock_polarity = False
|
|
assert master.clock_mode == 0
|
|
master.clock_polarity = True
|
|
assert master.clock_mode == 2
|
|
master.clock_phase = True
|
|
assert master.clock_mode == 3
|
|
master.clock_mode = 0
|
|
assert not master.clock_polarity
|
|
assert not master.clock_phase
|
|
with pytest.raises(ValueError):
|
|
master.clock_mode = 5
|
|
|
|
def test_spi_software_attr():
|
|
with patch('gpiozero.pins.local.SpiDev', None), \
|
|
Device._pin_factory.spi() as master:
|
|
assert not master.lsb_first
|
|
assert not master.select_high
|
|
assert master.bits_per_word == 8
|
|
master.bits_per_word = 12
|
|
assert master.bits_per_word == 12
|
|
master.lsb_first = True
|
|
assert master.lsb_first
|
|
master.select_high = True
|
|
assert master.select_high
|
|
with pytest.raises(ValueError):
|
|
master.bits_per_word = 0
|
|
|
|
|
|
# XXX Test two simultaneous SPI devices sharing clock, MOSI, and MISO, with
|
|
# separate select pins (including threaded tests which attempt simultaneous
|
|
# reading/writing)
|