summaryrefslogtreecommitdiff
path: root/Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py
diff options
context:
space:
mode:
Diffstat (limited to 'Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py')
-rw-r--r--Adafruit_Python_GPIO/Adafruit_GPIO/SPI.py328
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