Yet Another WebIOPi+
 All Classes Namespaces Files Functions Variables Macros Pages
spi.py
Go to the documentation of this file.
1 # Copyright 2012-2013 Eric Ptak - trouch.com
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import fcntl
16 import array
17 import ctypes
18 import struct
19 
20 from webiopi.utils.version import PYTHON_MAJOR
21 from webiopi.devices.bus import Bus
22 
23 # from spi/spidev.h
24 _IOC_NRBITS = 8
25 _IOC_TYPEBITS = 8
26 _IOC_SIZEBITS = 14
27 _IOC_DIRBITS = 2
28 
29 _IOC_NRSHIFT = 0
30 _IOC_TYPESHIFT = (_IOC_NRSHIFT+_IOC_NRBITS)
31 _IOC_SIZESHIFT = (_IOC_TYPESHIFT+_IOC_TYPEBITS)
32 _IOC_DIRSHIFT = (_IOC_SIZESHIFT+_IOC_SIZEBITS)
33 
34 _IOC_NONE = 0
35 _IOC_WRITE = 1
36 _IOC_READ = 2
37 
38 def _IOC(direction,t,nr,size):
39  return (((direction) << _IOC_DIRSHIFT) |
40  ((size) << _IOC_SIZESHIFT) |
41  ((t) << _IOC_TYPESHIFT) |
42  ((nr) << _IOC_NRSHIFT))
43 def _IOR(t, number, size):
44  return _IOC(_IOC_READ, t, number, size)
45 def _IOW(t, number, size):
46  return _IOC(_IOC_WRITE, t, number, size)
47 
48 SPI_CPHA = 0x01
49 SPI_CPOL = 0x02
50 
51 SPI_MODE_0 = (0|0)
52 SPI_MODE_1 = (0|SPI_CPHA)
53 SPI_MODE_2 = (SPI_CPOL|0)
54 SPI_MODE_3 = (SPI_CPOL|SPI_CPHA)
55 
56 # does not work
57 # SPI_CS_HIGH = 0x04
58 # SPI_LSB_FIRST = 0x08
59 # SPI_3WIRE = 0x10
60 # SPI_LOOP = 0x20
61 # SPI_NO_CS = 0x40
62 # SPI_READY = 0x80
63 
64 SPI_IOC_MAGIC = ord('k')
65 
66 def SPI_IOC_MESSAGE(count):
67  return _IOW(SPI_IOC_MAGIC, 0, count)
68 
69 # Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3)
70 SPI_IOC_RD_MODE = _IOR(SPI_IOC_MAGIC, 1, 1)
71 SPI_IOC_WR_MODE = _IOW(SPI_IOC_MAGIC, 1, 1)
72 
73 # Read / Write SPI bit justification
74 # does not work
75 # SPI_IOC_RD_LSB_FIRST = _IOR(SPI_IOC_MAGIC, 2, 1)
76 # SPI_IOC_WR_LSB_FIRST = _IOW(SPI_IOC_MAGIC, 2, 1)
77 
78 # Read / Write SPI device word length (1..N)
79 SPI_IOC_RD_BITS_PER_WORD = _IOR(SPI_IOC_MAGIC, 3, 1)
80 SPI_IOC_WR_BITS_PER_WORD = _IOW(SPI_IOC_MAGIC, 3, 1)
81 
82 # Read / Write SPI device default max speed hz
83 SPI_IOC_RD_MAX_SPEED_HZ = _IOR(SPI_IOC_MAGIC, 4, 4)
84 SPI_IOC_WR_MAX_SPEED_HZ = _IOW(SPI_IOC_MAGIC, 4, 4)
85 
86 class SPI(Bus):
87  def __init__(self, chip=0, mode=0, bits=8, speed=0):
88  Bus.__init__(self, "SPI", "/dev/spidev0.%d" % chip)
89  self.chip = chip
90 
91  val8 = array.array('B', [0])
92  val8[0] = mode
93  if fcntl.ioctl(self.fd, SPI_IOC_WR_MODE, val8):
94  raise Exception("Cannot write SPI Mode")
95  if fcntl.ioctl(self.fd, SPI_IOC_RD_MODE, val8):
96  raise Exception("Cannot read SPI Mode")
97  self.mode = struct.unpack('B', val8)[0]
98  assert(self.mode == mode)
99 
100  val8[0] = bits
101  if fcntl.ioctl(self.fd, SPI_IOC_WR_BITS_PER_WORD, val8):
102  raise Exception("Cannot write SPI Bits per word")
103  if fcntl.ioctl(self.fd, SPI_IOC_RD_BITS_PER_WORD, val8):
104  raise Exception("Cannot read SPI Bits per word")
105  self.bits = struct.unpack('B', val8)[0]
106  assert(self.bits == bits)
107 
108  val32 = array.array('I', [0])
109  if speed > 0:
110  val32[0] = speed
111  if fcntl.ioctl(self.fd, SPI_IOC_WR_MAX_SPEED_HZ, val32):
112  raise Exception("Cannot write SPI Max speed")
113  if fcntl.ioctl(self.fd, SPI_IOC_RD_MAX_SPEED_HZ, val32):
114  raise Exception("Cannot read SPI Max speed")
115  self.speed = struct.unpack('I', val32)[0]
116  assert((self.speed == speed) or (speed == 0))
117 
118  def __str__(self):
119  return "SPI(chip=%d, mode=%d, speed=%dHz)" % (self.chip, self.mode, self.speed)
120 
121  def xfer(self, txbuff=None):
122  length = len(txbuff)
123  if PYTHON_MAJOR >= 3:
124  _txbuff = bytes(txbuff)
125  _txptr = ctypes.create_string_buffer(_txbuff)
126  else:
127  _txbuff = str(bytearray(txbuff))
128  _txptr = ctypes.create_string_buffer(_txbuff)
129  _rxptr = ctypes.create_string_buffer(length)
130 
131  data = struct.pack("QQLLHBBL", #64 64 32 32 16 8 8 32 b = 32B
132  ctypes.addressof(_txptr),
133  ctypes.addressof(_rxptr),
134  length,
135  self.speed,
136  0, #delay
137  self.bits,
138  0, # cs_change,
139  0 # pad
140  )
141 
142  fcntl.ioctl(self.fd, SPI_IOC_MESSAGE(len(data)), data)
143  _rxbuff = ctypes.string_at(_rxptr, length)
144  return bytearray(_rxbuff)
145 
def SPI_IOC_MESSAGE
Definition: spi.py:66