diff options
Diffstat (limited to 'Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py')
-rw-r--r-- | Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py b/Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py deleted file mode 100644 index c20a32c..0000000 --- a/Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py +++ /dev/null @@ -1,328 +0,0 @@ -# Copyright (c) 2014 Adafruit Industries -# Author: Tony DiCola -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -import operator -import time - -import Adafruit_GPIO as GPIO - - -MSBFIRST = 0 -LSBFIRST = 1 - - -class SpiDev(object): - """Hardware-based SPI implementation using the spidev interface.""" - - def __init__(self, port, device, max_speed_hz=500000): - """Initialize an SPI device using the SPIdev interface. Port and device - identify the device, for example the device /dev/spidev1.0 would be port - 1 and device 0. - """ - import spidev - self._device = spidev.SpiDev() - self._device.open(port, device) - self._device.max_speed_hz=max_speed_hz - # Default to mode 0, and make sure CS is active low. - self._device.mode = 0 - self._device.cshigh = False - - def set_clock_hz(self, hz): - """Set the speed of the SPI clock in hertz. Note that not all speeds - are supported and a lower speed might be chosen by the hardware. - """ - self._device.max_speed_hz=hz - - def set_mode(self, mode): - """Set SPI mode which controls clock polarity and phase. Should be a - numeric value 0, 1, 2, or 3. See wikipedia page for details on meaning: - http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - """ - if mode < 0 or mode > 3: - raise ValueError('Mode must be a value 0, 1, 2, or 3.') - self._device.mode = mode - - def set_bit_order(self, order): - """Set order of bits to be read/written over serial lines. Should be - either MSBFIRST for most-significant first, or LSBFIRST for - least-signifcant first. - """ - if order == MSBFIRST: - self._device.lsbfirst = False - elif order == LSBFIRST: - self._device.lsbfirst = True - else: - raise ValueError('Order must be MSBFIRST or LSBFIRST.') - - def close(self): - """Close communication with the SPI device.""" - self._device.close() - - def write(self, data): - """Half-duplex SPI write. The specified array of bytes will be clocked - out the MOSI line. - """ - self._device.writebytes(data) - - def read(self, length): - """Half-duplex SPI read. The specified length of bytes will be clocked - in the MISO line and returned as a bytearray object. - """ - return bytearray(self._device.readbytes(length)) - - def transfer(self, data): - """Full-duplex SPI read and write. The specified array of bytes will be - clocked out the MOSI line, while simultaneously bytes will be read from - the MISO line. Read bytes will be returned as a bytearray object. - """ - return bytearray(self._device.xfer2(data)) - -class SpiDevMraa(object): - """Hardware SPI implementation with the mraa library on Minnowboard""" - def __init__(self, port, device, max_speed_hz=500000): - import mraa - self._device = mraa.Spi(0) - self._device.mode(0) - - def set_clock_hz(self, hz): - """Set the speed of the SPI clock in hertz. Note that not all speeds - are supported and a lower speed might be chosen by the hardware. - """ - self._device.frequency(hz) - - def set_mode(self,mode): - """Set SPI mode which controls clock polarity and phase. Should be a - numeric value 0, 1, 2, or 3. See wikipedia page for details on meaning: - http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - """ - if mode < 0 or mode > 3: - raise ValueError('Mode must be a value 0, 1, 2, or 3.') - self._device.mode(mode) - - def set_bit_order(self, order): - """Set order of bits to be read/written over serial lines. Should be - either MSBFIRST for most-significant first, or LSBFIRST for - least-signifcant first. - """ - if order == MSBFIRST: - self._device.lsbmode(False) - elif order == LSBFIRST: - self._device.lsbmode(True) - else: - raise ValueError('Order must be MSBFIRST or LSBFIRST.') - - def close(self): - """Close communication with the SPI device.""" - self._device.Spi() - - def write(self, data): - """Half-duplex SPI write. The specified array of bytes will be clocked - out the MOSI line. - """ - self._device.write(bytearray(data)) - -class BitBang(object): - """Software-based implementation of the SPI protocol over GPIO pins.""" - - def __init__(self, gpio, sclk, mosi=None, miso=None, ss=None): - """Initialize bit bang (or software) based SPI. Must provide a BaseGPIO - class, the SPI clock, and optionally MOSI, MISO, and SS (slave select) - pin numbers. If MOSI is set to None then writes will be disabled and fail - with an error, likewise for MISO reads will be disabled. If SS is set to - None then SS will not be asserted high/low by the library when - transfering data. - """ - self._gpio = gpio - self._sclk = sclk - self._mosi = mosi - self._miso = miso - self._ss = ss - # Set pins as outputs/inputs. - gpio.setup(sclk, GPIO.OUT) - if mosi is not None: - gpio.setup(mosi, GPIO.OUT) - if miso is not None: - gpio.setup(miso, GPIO.IN) - if ss is not None: - gpio.setup(ss, GPIO.OUT) - # Assert SS high to start with device communication off. - gpio.set_high(ss) - # Assume mode 0. - self.set_mode(0) - # Assume most significant bit first order. - self.set_bit_order(MSBFIRST) - - def set_clock_hz(self, hz): - """Set the speed of the SPI clock. This is unsupported with the bit - bang SPI class and will be ignored. - """ - pass - - def set_mode(self, mode): - """Set SPI mode which controls clock polarity and phase. Should be a - numeric value 0, 1, 2, or 3. See wikipedia page for details on meaning: - http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - """ - if mode < 0 or mode > 3: - raise ValueError('Mode must be a value 0, 1, 2, or 3.') - if mode & 0x02: - # Clock is normally high in mode 2 and 3. - self._clock_base = GPIO.HIGH - else: - # Clock is normally low in mode 0 and 1. - self._clock_base = GPIO.LOW - if mode & 0x01: - # Read on trailing edge in mode 1 and 3. - self._read_leading = False - else: - # Read on leading edge in mode 0 and 2. - self._read_leading = True - # Put clock into its base state. - self._gpio.output(self._sclk, self._clock_base) - - def set_bit_order(self, order): - """Set order of bits to be read/written over serial lines. Should be - either MSBFIRST for most-significant first, or LSBFIRST for - least-signifcant first. - """ - # Set self._mask to the bitmask which points at the appropriate bit to - # read or write, and appropriate left/right shift operator function for - # reading/writing. - if order == MSBFIRST: - self._mask = 0x80 - self._write_shift = operator.lshift - self._read_shift = operator.rshift - elif order == LSBFIRST: - self._mask = 0x01 - self._write_shift = operator.rshift - self._read_shift = operator.lshift - else: - raise ValueError('Order must be MSBFIRST or LSBFIRST.') - - def close(self): - """Close the SPI connection. Unused in the bit bang implementation.""" - pass - - def write(self, data, assert_ss=True, deassert_ss=True): - """Half-duplex SPI write. If assert_ss is True, the SS line will be - asserted low, the specified bytes will be clocked out the MOSI line, and - if deassert_ss is True the SS line be put back high. - """ - # Fail MOSI is not specified. - if self._mosi is None: - raise RuntimeError('Write attempted with no MOSI pin specified.') - if assert_ss and self._ss is not None: - self._gpio.set_low(self._ss) - for byte in data: - for i in range(8): - # Write bit to MOSI. - if self._write_shift(byte, i) & self._mask: - self._gpio.set_high(self._mosi) - else: - self._gpio.set_low(self._mosi) - # Flip clock off base. - self._gpio.output(self._sclk, not self._clock_base) - # Return clock to base. - self._gpio.output(self._sclk, self._clock_base) - if deassert_ss and self._ss is not None: - self._gpio.set_high(self._ss) - - def read(self, length, assert_ss=True, deassert_ss=True): - """Half-duplex SPI read. If assert_ss is true, the SS line will be - asserted low, the specified length of bytes will be clocked in the MISO - line, and if deassert_ss is true the SS line will be put back high. - Bytes which are read will be returned as a bytearray object. - """ - if self._miso is None: - raise RuntimeError('Read attempted with no MISO pin specified.') - if assert_ss and self._ss is not None: - self._gpio.set_low(self._ss) - result = bytearray(length) - for i in range(length): - for j in range(8): - # Flip clock off base. - self._gpio.output(self._sclk, not self._clock_base) - # Handle read on leading edge of clock. - if self._read_leading: - if self._gpio.is_high(self._miso): - # Set bit to 1 at appropriate location. - result[i] |= self._read_shift(self._mask, j) - else: - # Set bit to 0 at appropriate location. - result[i] &= ~self._read_shift(self._mask, j) - # Return clock to base. - self._gpio.output(self._sclk, self._clock_base) - # Handle read on trailing edge of clock. - if not self._read_leading: - if self._gpio.is_high(self._miso): - # Set bit to 1 at appropriate location. - result[i] |= self._read_shift(self._mask, j) - else: - # Set bit to 0 at appropriate location. - result[i] &= ~self._read_shift(self._mask, j) - if deassert_ss and self._ss is not None: - self._gpio.set_high(self._ss) - return result - - def transfer(self, data, assert_ss=True, deassert_ss=True): - """Full-duplex SPI read and write. If assert_ss is true, the SS line - will be asserted low, the specified bytes will be clocked out the MOSI - line while bytes will also be read from the MISO line, and if - deassert_ss is true the SS line will be put back high. Bytes which are - read will be returned as a bytearray object. - """ - if self._mosi is None: - raise RuntimeError('Write attempted with no MOSI pin specified.') - if self._mosi is None: - raise RuntimeError('Read attempted with no MISO pin specified.') - if assert_ss and self._ss is not None: - self._gpio.set_low(self._ss) - result = bytearray(len(data)) - for i in range(len(data)): - for j in range(8): - # Write bit to MOSI. - if self._write_shift(data[i], j) & self._mask: - self._gpio.set_high(self._mosi) - else: - self._gpio.set_low(self._mosi) - # Flip clock off base. - self._gpio.output(self._sclk, not self._clock_base) - # Handle read on leading edge of clock. - if self._read_leading: - if self._gpio.is_high(self._miso): - # Set bit to 1 at appropriate location. - result[i] |= self._read_shift(self._mask, j) - else: - # Set bit to 0 at appropriate location. - result[i] &= ~self._read_shift(self._mask, j) - # Return clock to base. - self._gpio.output(self._sclk, self._clock_base) - # Handle read on trailing edge of clock. - if not self._read_leading: - if self._gpio.is_high(self._miso): - # Set bit to 1 at appropriate location. - result[i] |= self._read_shift(self._mask, j) - else: - # Set bit to 0 at appropriate location. - result[i] &= ~self._read_shift(self._mask, j) - if deassert_ss and self._ss is not None: - self._gpio.set_high(self._ss) - return result |