Skip to content
This repository was archived by the owner on Sep 30, 2019. It is now read-only.

Commit 48a6f68

Browse files
committed
Refactor platform detection to common module, and add I2C support.
1 parent aa4382f commit 48a6f68

8 files changed

+384
-29
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
*.egg-info
12
*.pyc

Adafruit_GPIO/GPIO.py

+7-21
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020
# THE SOFTWARE.
2121

22-
import platform
22+
import Adafruit_GPIO.platform_detect as pd
2323

2424

2525
OUT = 0
@@ -128,33 +128,19 @@ def input(self, pin):
128128
return self.bbio_gpio.input(pin)
129129

130130

131-
def get_platform_gpio(plat=platform.platform(), **keywords):
131+
def get_platform_gpio(**keywords):
132132
"""Attempt to return a GPIO instance for the platform which the code is being
133133
executed on. Currently supports only the Raspberry Pi using the RPi.GPIO
134134
library and Beaglebone Black using the Adafruit_BBIO library. Will throw an
135135
exception if a GPIO instance can't be created for the current platform. The
136136
returned GPIO object is an instance of BaseGPIO.
137137
"""
138-
if plat is None:
139-
raise RuntimeError('Could not determine platform type.')
140-
141-
# TODO: Is there a better way to check if running on BBB or Pi? Relying on
142-
# the architecture name is brittle because new boards running armv6 or armv7
143-
# might come along and conflict with this simple identification scheme.
144-
145-
# Handle Raspberry Pi
146-
# Platform output on Raspbian testing/jessie ~May 2014:
147-
# Linux-3.10.25+-armv6l-with-debian-7.4
148-
if plat.lower().find('armv6l-with-debian') > -1:
138+
plat = pd.platform_detect()
139+
if plat == pd.RASPBERRY_PI:
149140
import RPi.GPIO
150141
return RPiGPIOAdapter(RPi.GPIO, **keywords)
151-
152-
# Handle Beaglebone Black
153-
# Platform output on Debian ~May 2014:
154-
# Linux-3.8.13-bone47-armv7l-with-debian-7.4
155-
if plat.lower().find('armv7l-with-debian') > -1:
142+
elif plat == pd.BEAGLEBONE_BLACK:
156143
import Adafruit_BBIO.GPIO
157144
return AdafruitBBIOAdapter(Adafruit_BBIO.GPIO, **keywords)
158-
159-
# Couldn't determine platform, raise error.
160-
raise RuntimeError('Unsupported platform: {0}'.format(plat))
145+
elif plat == pd.UNKNOWN:
146+
raise RuntimeError('Could not determine platform.')

Adafruit_GPIO/I2C.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Copyright (c) 2014 Adafruit Industries
2+
# Author: Tony DiCola
3+
# Based on Adafruit_I2C.py created by Kevin Townsend.
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
import logging
24+
25+
import smbus
26+
27+
28+
logger = logging.getLogger(__name__)
29+
30+
31+
def reverseByteOrder(data):
32+
"""Reverses the byte order of an int (16-bit) or long (32-bit) value."""
33+
# Courtesy Vishal Sapre
34+
byteCount = len(hex(data)[2:].replace('L','')[::2])
35+
val = 0
36+
for i in range(byteCount):
37+
val = (val << 8) | (data & 0xff)
38+
data >>= 8
39+
return val
40+
41+
def get_default_bus():
42+
"""Return the default bus number based on the device platform. For a
43+
Raspberry Pi either bus 0 or 1 (baed on the Pi revision) will be returned.
44+
For a Beaglebone Black the first user accessible bus, 1, will be returned.
45+
"""
46+
return 0
47+
48+
49+
class Device(object):
50+
"""Class for communicating with an I2C device using the smbus library.
51+
Allows reading and writing 8-bit, 16-bit, and byte array values to registers
52+
on the device."""
53+
logger = logging.getLogger(__name__)
54+
def __init__(self, address, busnum):
55+
"""Create an instance of the I2C device at the specified address on the
56+
specified I2C bus number."""
57+
self._address = address
58+
self._bus = smbus.SMBus(busnum)
59+
self._logger = logging.getLogger('Adafruit_I2C.Device.Bus.{0}.Address.{1:#0X}' \
60+
.format(busnum, address))
61+
62+
def write8(self, register, value):
63+
"""Write an 8-bit value to the specified register."""
64+
value = value & 0xFF
65+
self._bus.write_byte_data(self._address, register, value)
66+
self._logger.debug("Wrote 0x%02X to register 0x%02X",
67+
value, register)
68+
69+
def write16(self, register, value):
70+
"""Write a 16-bit value to the specified register."""
71+
value = value & 0xFFFF
72+
self._bus.write_word_data(self._address, register, value)
73+
self._logger.debug("Wrote 0x%04X to register pair 0x%02X, 0x%02X",
74+
value, register, register+1)
75+
76+
def writeList(self, register, data):
77+
"""Write bytes to the specified register."""
78+
self._bus.write_i2c_block_data(self._address, register, data)
79+
self._logger.debug("Wrote to register 0x%02X: %s",
80+
register, data)
81+
82+
def readList(self, register, length):
83+
"""Read a length number of bytes from the specified register. Results
84+
will be returned as a bytearray."""
85+
results = self._bus.read_i2c_block_data(self._address, register, length)
86+
self._logger.debug("Read the following from register 0x%02X: %s",
87+
register, results)
88+
return results
89+
90+
def readU8(self, register):
91+
"""Read an unsigned byte from the specified register."""
92+
result = self._bus.read_byte_data(self._address, register) & 0xFF
93+
self._logger.debug("Read 0x%02X from register 0x%02X",
94+
result, register)
95+
return result
96+
97+
def readS8(self, register):
98+
"""Read a signed byte from the specified register."""
99+
result = self._bus.read_byte_data(self._address, register) & 0xFF
100+
if result > 127:
101+
result -= 256
102+
self._logger.debug("Read 0x%02X from register 0x%02X",
103+
result, register)
104+
return result
105+
106+
def readU16(self, register):
107+
"""Read an unsigned 16-bit value from the specified register."""
108+
result = self._bus.read_word_data(self._address,register) & 0xFFFF
109+
self._logger.debug("Read 0x%04X from register pair 0x%02X, 0x%02X",
110+
result, register, register+1)
111+
return result
112+
113+
def readS16(self, register):
114+
"""Read a signed 16-bit value from the specified register."""
115+
result = self._bus.read_word_data(self._address,register)
116+
if result > 32767:
117+
result -= 65536
118+
self._logger.debug("Read 0x%04X from register pair 0x%02X, 0x%02X",
119+
result, register, register+1)
120+
return result

Adafruit_GPIO/platform_detect.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright (c) 2014 Adafruit Industries
2+
# Author: Tony DiCola
3+
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
11+
# The above copyright notice and this permission notice shall be included in all
12+
# copies or substantial portions of the Software.
13+
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
# SOFTWARE.
21+
import platform
22+
23+
# Platform identification constants.
24+
UNKNOWN = 0
25+
RASPBERRY_PI = 1
26+
BEAGLEBONE_BLACK = 2
27+
28+
29+
def platform_detect():
30+
"""Detect if running on the Raspberry Pi or Beaglebone Black and return the
31+
platform type. Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN."""
32+
33+
# TODO: Is there a better way to check if running on BBB or Pi? Relying on
34+
# the architecture name is brittle because new boards running armv6 or armv7
35+
# might come along and conflict with this simple identification scheme. One
36+
# option might be switching to read /proc/cpuinfo.
37+
plat = platform.platform()
38+
39+
# Handle Raspberry Pi
40+
# Platform output on Raspbian testing/jessie ~May 2014:
41+
# Linux-3.10.25+-armv6l-with-debian-7.4
42+
if plat.lower().find('armv6l-with-debian') > -1:
43+
return RASPBERRY_PI
44+
# Handle Beaglebone Black
45+
# Platform output on Debian ~May 2014:
46+
# Linux-3.8.13-bone47-armv7l-with-debian-7.4
47+
elif plat.lower().find('armv7l-with-debian') > -1:
48+
return BEAGLEBONE_BLACK
49+
else:
50+
return UNKNOWN

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from setuptools import setup, find_packages
44

55
setup(name = 'Adafruit_GPIO',
6-
version = '0.1.0',
6+
version = '0.2.0',
77
author = 'Tony DiCola',
88
author_email = 'tdicola@adafruit.com',
99
description = 'Library to provide a cross-platform GPIO interface on the Raspberry Pi and Beaglebone Black using the RPi.GPIO and Adafruit_BBIO libraries.',

test/test_GPIO.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,23 @@ def test_input(self):
109109
class TestGetPlatformGPIO(unittest.TestCase):
110110
def test_raspberrypi(self):
111111
rpi = Mock()
112-
with patch.dict('sys.modules', {'RPi': rpi, 'RPi.GPIO': rpi.gpio}):
113-
gpio = GPIO.get_platform_gpio(plat='Linux-3.10.25+-armv6l-with-debian-7.4')
114-
self.assertIsInstance(gpio, GPIO.RPiGPIOAdapter)
112+
with patch('platform.platform',
113+
new=Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4')):
114+
with patch.dict('sys.modules',
115+
{'RPi': rpi, 'RPi.GPIO': rpi.gpio}):
116+
gpio = GPIO.get_platform_gpio()
117+
self.assertIsInstance(gpio, GPIO.RPiGPIOAdapter)
115118

116119
def test_beagleboneblack(self):
117120
bbio = Mock()
118-
with patch.dict('sys.modules', {'Adafruit_BBIO': bbio, 'Adafruit_BBIO.GPIO': bbio.gpio}):
119-
gpio = GPIO.get_platform_gpio(plat='Linux-3.8.13-bone47-armv7l-with-debian-7.4')
120-
self.assertIsInstance(gpio, GPIO.AdafruitBBIOAdapter)
121+
with patch('platform.platform',
122+
new=Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4')):
123+
with patch.dict('sys.modules',
124+
{'Adafruit_BBIO': bbio, 'Adafruit_BBIO.GPIO': bbio.gpio}):
125+
gpio = GPIO.get_platform_gpio()
126+
self.assertIsInstance(gpio, GPIO.AdafruitBBIOAdapter)
121127

122128
def test_otherplatform(self):
123-
self.assertRaises(RuntimeError, GPIO.get_platform_gpio, plat='foo-bar')
129+
with patch('platform.platform',
130+
new=Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit')):
131+
self.assertRaises(RuntimeError, GPIO.get_platform_gpio)

0 commit comments

Comments
 (0)