From 1022b0b0dea9c07cc47947a5e3b4a8064c02e5fe Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Jun 2017 23:16:59 +0100 Subject: [PATCH] Close #465 Factor out hardware SPI pin numbers; this is a effectively a rebase (and minor modification) of @lurch's original patch which conflicted after the merge of the remote-spi branch. --- gpiozero/pins/local.py | 11 ++++--- gpiozero/pins/pi.py | 67 ++++++++++++++++++++++++++-------------- gpiozero/pins/pigpiod.py | 12 +++++-- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/gpiozero/pins/local.py b/gpiozero/pins/local.py index b9ec330..9121dac 100644 --- a/gpiozero/pins/local.py +++ b/gpiozero/pins/local.py @@ -15,7 +15,7 @@ except ImportError: SpiDev = None from . import SPI -from .pi import PiFactory, PiPin +from .pi import PiFactory, PiPin, SPI_HARDWARE_PINS from .spi import SPISoftwareBus from ..devices import Device, SharedMixin from ..output_devices import OutputDevice @@ -81,11 +81,12 @@ class LocalPiHardwareSPI(SPI, Device): self._interface = None self._address = factory.address + ('SPI(port=%d, device=%d)' % (port, device),) super(LocalPiHardwareSPI, self).__init__() + pins = SPI_HARDWARE_PINS[port] self._reserve_pins( - factory.pin_address(11), - factory.pin_address(10), - factory.pin_address(9), - factory.pin_address((8, 7)[device]) + factory.pin_address(pins['clock']), + factory.pin_address(pins['mosi']), + factory.pin_address(pins['miso']), + factory.pin_address(pins['select'][device]) ) self._interface = SpiDev() self._interface.open(port, device) diff --git a/gpiozero/pins/pi.py b/gpiozero/pins/pi.py index 2f88ce3..1ec024d 100644 --- a/gpiozero/pins/pi.py +++ b/gpiozero/pins/pi.py @@ -32,6 +32,16 @@ from ..exc import ( ) +SPI_HARDWARE_PINS = { + 0: { + 'clock': 11, + 'mosi': 10, + 'miso': 9, + 'select': (8, 7), + }, +} + + class PiFactory(Factory): """ Abstract base class representing hardware attached to a Raspberry Pi. This @@ -105,21 +115,24 @@ class PiFactory(Factory): if kwargs: raise SPIBadArgs( 'unrecognized keyword argument %s' % kwargs.popitem()[0]) - if all(( - spi_args['clock_pin'] == 11, - spi_args['mosi_pin'] == 10, - spi_args['miso_pin'] == 9, - spi_args['select_pin'] in (7, 8), - )): - try: - return self.spi_classes[('hardware', shared)]( - self, port=0, device=0 if spi_args['select_pin'] == 8 else 1 - ) - except Exception as e: - warnings.warn( - SPISoftwareFallback( - 'failed to initialize hardware SPI, falling back to ' - 'software (error was: %s)' % str(e))) + for port, pins in SPI_HARDWARE_PINS.items(): + if all(( + spi_args['clock_pin'] == pins['clock'], + spi_args['mosi_pin'] == pins['mosi'], + spi_args['miso_pin'] == pins['miso'], + spi_args['select_pin'] in pins['select'], + )): + try: + return self.spi_classes[('hardware', shared)]( + self, port=port, + device=pins['select'].index(spi_args['select_pin']) + ) + except Exception as e: + warnings.warn( + SPISoftwareFallback( + 'failed to initialize hardware SPI, falling back to ' + 'software (error was: %s)' % str(e))) + break # Convert all pin arguments to integer GPIO numbers. This is necessary # to ensure the shared-key for shared implementations get matched # correctly, and is a bit of a hack for the pigpio bit-bang @@ -139,16 +152,17 @@ class PiFactory(Factory): Returns a tuple of ``(spi_args, other_args)``. """ - pin_defaults = { - 'clock_pin': 11, - 'mosi_pin': 10, - 'miso_pin': 9, - 'select_pin': 8, - } dev_defaults = { 'port': 0, 'device': 0, } + default_hw = SPI_HARDWARE_PINS[dev_defaults['port']] + pin_defaults = { + 'clock_pin': default_hw['clock'], + 'mosi_pin': default_hw['mosi'], + 'miso_pin': default_hw['miso'], + 'select_pin': default_hw['select'][dev_defaults['device']], + } spi_args = { key: value for (key, value) in kwargs.items() if key in pin_defaults or key in dev_defaults @@ -171,10 +185,15 @@ class PiFactory(Factory): } if spi_args['port'] != 0: raise SPIBadArgs('port 0 is the only valid SPI port') - if spi_args['device'] not in (0, 1): - raise SPIBadArgs('device must be 0 or 1') + selected_hw = SPI_HARDWARE_PINS[spi_args['port']] + try: + selected_hw['select'][spi_args['device']] + except IndexError: + raise SPIBadArgs( + 'device must be in the range 0..%d' % + len(selected_hw['select'])) spi_args = { - key: value if key != 'select_pin' else (8, 7)[spi_args['device']] + key: value if key != 'select_pin' else selected_hw['select'][spi_args['device']] for key, value in pin_defaults.items() } else: diff --git a/gpiozero/pins/pigpiod.py b/gpiozero/pins/pigpiod.py index 564c376..c6841be 100644 --- a/gpiozero/pins/pigpiod.py +++ b/gpiozero/pins/pigpiod.py @@ -12,7 +12,7 @@ from weakref import proxy import pigpio from . import SPI -from .pi import PiPin, PiFactory +from .pi import PiPin, PiFactory, SPI_HARDWARE_PINS from .data import pi_info from ..devices import Device from ..mixins import SharedMixin @@ -299,10 +299,16 @@ class PiGPIOHardwareSPI(SPI, Device): self._factory = proxy(factory) self._handle = None super(PiGPIOHardwareSPI, self).__init__() + pins = SPI_HARDWARE_PINS[port] self._reserve_pins(*( factory.address + ('GPIO%d' % pin,) - for pin in (11, 10, 9, (8, 7)[device]) - )) + for pin in ( + pins['clock'], + pins['mosi'], + pins['miso'], + pins['select'][device] + ) + )) self._spi_flags = 8 << 16 self._baud = 500000 self._handle = self._factory.connection.spi_open(