Catch SPI conflicts properly

Also handle SPI flags in pigpio implementation more elegantly (just
store the flags and manipulate them instead of keeping separate fields)
This commit is contained in:
Dave Jones
2016-10-21 21:51:10 +01:00
parent ba1a7e6497
commit a9f9aa4a3e
2 changed files with 52 additions and 48 deletions

View File

@@ -89,12 +89,6 @@ class LocalPiHardwareSPI(SPI, Device):
self._interface.open(port, device)
self._interface.max_speed_hz = 500000
def _conflicts_with(self, other):
return not (
isinstance(other, LocalPiHardwareSPI) and
(self._port, self._device) != (other._port, other._device)
)
def close(self):
if self._interface:
try:
@@ -165,6 +159,12 @@ class LocalPiSoftwareSPI(SPI, OutputDevice):
self.close()
raise
def _conflicts_with(self, other):
return not (
isinstance(other, LocalPiSoftwareSPI) and
(self.pin.number != other.pin.number)
)
def close(self):
if self._bus:
self._bus.close()

View File

@@ -294,13 +294,17 @@ class PiGPIOHardwareSPI(SPI, Device):
factory.address + ('GPIO%d' % pin,)
for pin in (11, 10, 9, (8, 7)[device])
))
self._mode = 0
self._select_high = False
self._bits_per_word = 8
self._spi_flags = 8 << 16
self._baud = 500000
self._handle = self._factory.connection.spi_open(
device, self._baud, self._spi_flags())
def _conflicts_with(self, other):
return not (
isinstance(other, PiGPIOHardwareSPI) and
(self._port, self._device) != (other._port, other._device)
)
def close(self):
try:
self._factory._spis.remove(self)
@@ -329,44 +333,37 @@ class PiGPIOHardwareSPI(SPI, Device):
except DeviceClosed:
return 'SPI(closed)'
def _spi_flags(self):
return (
self._mode << 0 |
self._select_high << (2 + self._device) |
self._bits_per_word << 16
)
def _get_clock_mode(self):
return self._clock_mode
return self._spi_flags & 0x3
def _set_clock_mode(self, value):
self._check_open()
if not 0 <= value < 4:
raise SPIInvalidClockmode("%d is not a valid SPI clock mode" % value)
raise SPIInvalidClockMode("%d is not a valid SPI clock mode" % value)
self._factory.connection.spi_close(self._handle)
self._clock_mode = value
self._spi_flags = (self._spi_flags & ~0x3) | value
self._handle = self._factory.connection.spi_open(
self._device, self._baud, self._spi_flags())
self._device, self._baud, self._spi_flags)
def _get_select_high(self):
return self._select_high
return bool((self._spi_flags >> (2 + self._device)) & 0x1)
def _set_select_high(self, value):
self._check_open()
self._factory.connection.spi_close(self._handle)
self._select_high = bool(value)
self._spi_flags = (self._spi_flags & ~0x1c) | (bool(value) << (2 + self._device))
self._handle = self._factory.connection.spi_open(
self._device, self._baud, self._spi_flags())
self._device, self._baud, self._spi_flags)
def _get_bits_per_word(self):
return self._bits_per_word
return (self._spi_flags >> 16) & 0x3f
def _set_bits_per_word(self, value):
self._check_open()
self._factory.connection.spi_close(self._handle)
self._bits_per_word = value
self._spi_flags = (self._spi_flags & ~0x3f0000) | ((value & 0x3f) << 16)
self._handle = self._factory.connection.spi_open(
self._device, self._baud, self._spi_flags())
self._device, self._baud, self._spi_flags)
def transfer(self, data):
self._check_open()
@@ -380,10 +377,12 @@ class PiGPIOHardwareSPI(SPI, Device):
class PiGPIOSoftwareSPI(SPI, Device):
def __init__(self, factory, clock_pin, mosi_pin, miso_pin, select_pin):
self._select_pin = None
self._closed = True
self._select_pin = select_pin
self._clock_pin = clock_pin
self._mosi_pin = mosi_pin
self._miso_pin = miso_pin
self._factory = weakref.proxy(factory)
self._address = factory.address + (
)
super(PiGPIOSoftwareSPI, self).__init__()
self._reserve_pins(
factory.pin_address(clock_pin),
@@ -391,24 +390,25 @@ class PiGPIOSoftwareSPI(SPI, Device):
factory.pin_address(miso_pin),
factory.pin_address(select_pin),
)
self._mode = 0
self._select_high = False
self._lsb_first = False
self._spi_flags = 0
self._baud = 100000
try:
self._factory.connection.bb_spi_open(
select_pin, miso_pin, mosi_pin, clock_pin,
self._baud, self._spi_flags())
self._baud, self._spi_flags)
# Only set after opening bb_spi; if that fails then close() will
# also fail if bb_spi_close is attempted on an un-open interface
self._select_pin = select_pin
self._clock_pin = clock_pin
self._mosi_pin = mosi_pin
self._miso_pin = miso_pin
self._closed = False
except:
self.close()
raise
def _conflicts_with(self, other):
return not (
isinstance(other, PiGPIOHardwareSPI) and
(self._select_pin) != (other._select_pin)
)
def close(self):
try:
self._factory._spis.remove(self)
@@ -417,14 +417,14 @@ class PiGPIOSoftwareSPI(SPI, Device):
# internal list, ignore the error
pass
if not self.closed:
self._closed = True
self._factory.connection.bb_spi_close(self._select_pin)
self._select_pin = None
self._release_all()
super(PiGPIOSoftwareSPI, self).close()
@property
def closed(self):
return self._select_pin is None or self._factory.connection is None
return self._closed
def __repr__(self):
try:
@@ -445,39 +445,43 @@ class PiGPIOSoftwareSPI(SPI, Device):
)
def _get_clock_mode(self):
return self._clock_mode
return self._spi_flags & 0x3
def _set_clock_mode(self, value):
self._check_open()
if not 0 <= value < 4:
raise SPIInvalidClockmode("%d is not a valid SPI clock mode" % value)
self._factory.connection.bb_spi_close(self._select_pin)
self._clock_mode = value
self._spi_flags = (self._spi_flags & ~0x3) | value
self._factory.connection.bb_spi_open(
self._select_pin, self._miso_pin, self._mosi_pin, self._clock_pin,
self._baud, self._spi_flags())
self._baud, self._spi_flags)
def _get_select_high(self):
return self._select_high
return bool(self._spi_flags & 0x4)
def _set_select_high(self, value):
self._check_open()
self._factory.connection.bb_spi_close(self._select_pin)
self._select_high = bool(value)
self._spi_flags = (self._spi_flags & ~0x4) | (bool(value) << 2)
self._factory.connection.bb_spi_open(
self._select_pin, self._miso_pin, self._mosi_pin, self._clock_pin,
self._baud, self._spi_flags())
self._baud, self._spi_flags)
def _get_lsb_first(self):
return self._lsb_first
return bool(self._spi_flags & 0xc000)
def _set_lsb_first(self, value):
self._check_open()
self._factory.connection.bb_spi_close(self._select_pin)
self._lsb_first = bool(value)
self._spi_flags = (
(self._spi_flags & ~0xc000)
| (bool(value) << 14)
| (bool(value) << 15)
)
self._factory.connection.bb_spi_open(
self._select_pin, self._miso_pin, self._mosi_pin, self._clock_pin,
self._baud, self._spi_flags())
self._baud, self._spi_flags)
def transfer(self, data):
self._check_open()