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

Commit 21d0b04

Browse files
committedFeb 16, 2016
Add a GPIO class to support PCA9XXX chips
1 parent cdf7a7b commit 21d0b04

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
 

‎Adafruit_GPIO/PCA95xx.py

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
'''
2+
Adafruit compatible using BaseGPIO class to represent a PCA9555 IO expander
3+
Copyright (C) 2016 Matias Vidal
4+
Ported from: https://github.com/dberlin/PCA95XX
5+
6+
# Copyright 2012 Daniel Berlin
7+
8+
Permission is hereby granted, free of charge, to any person obtaining a copy of
9+
this software and associated documentation files (the "Software"), to deal in
10+
the Software without restriction, including without limitation the rights to
11+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12+
of the Software, and to permit persons to whom the Software is furnished to do
13+
so, subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all
16+
copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
SOFTWARE.'''
25+
26+
import Adafruit_GPIO as GPIO
27+
import Adafruit_GPIO.I2C as I2C
28+
29+
# For the PCA 953X and 955X series, the chips with 8 GPIO's have these port numbers
30+
# The chips with 16 GPIO's have the first port for each type at double these numbers
31+
# IE The first config port is 6
32+
33+
INPUT_PORT = 0
34+
OUTPUT_PORT = 1
35+
POLARITY_PORT = 2
36+
CONFIG_PORT = 3
37+
38+
IN = GPIO.IN
39+
OUT = GPIO.OUT
40+
HIGH = GPIO.HIGH
41+
LOW = GPIO.LOW
42+
43+
44+
class PCA9555(GPIO.BaseGPIO):
45+
"""Class to represent a PCA9555 GPIO extender. Compatible
46+
with the Adafruit_GPIO BaseGPIO class so it can be used as a custom GPIO
47+
class for interacting with device.
48+
"""
49+
NUM_GPIO = 16
50+
51+
def __init__(self, address=0x20, busnum=None, i2c=None, num_gpios=16, **kwargs):
52+
address = int(address)
53+
self.__name__ = "PCA955"
54+
# Create I2C device.
55+
i2c = i2c or I2C
56+
busnum = busnum or i2c.get_default_bus()
57+
self._device = i2c.get_i2c_device(address, busnum, **kwargs)
58+
self.num_gpios = num_gpios
59+
60+
if self.num_gpios <= 8:
61+
self.iodir = self._device.readU8(CONFIG_PORT)
62+
self.outputvalue = self._device.readU8(OUTPUT_PORT)
63+
64+
elif self.num_gpios > 8 and self.num_gpios <= 16:
65+
self.iodir = self._device.readU16(CONFIG_PORT<< 1)
66+
self.outputvalue = self._device.readU16(OUTPUT_PORT << 1)
67+
68+
def _changebit(self, bitmap, bit, value):
69+
assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
70+
if value == 0:
71+
return bitmap & ~(1 << bit)
72+
elif value == 1:
73+
return bitmap | (1 << bit)
74+
75+
# Change the value of bit PIN on port PORT to VALUE. If the
76+
# current pin state for the port is passed in as PORTSTATE, we
77+
# will avoid doing a read to get it. The port pin state must be
78+
# complete if passed in (IE it should not just be the value of the
79+
# single pin we are trying to change)
80+
def _readandchangepin(self, port, pin, value, portstate = None):
81+
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
82+
if not portstate:
83+
if self.num_gpios <= 8:
84+
portstate = self._device.readU8(port)
85+
elif self.num_gpios > 8 and self.num_gpios <= 16:
86+
portstate = self._device.readU16(port << 1)
87+
newstate = self._changebit(portstate, pin, value)
88+
if self.num_gpios <= 8:
89+
self._device.write8(port, newstate)
90+
else:
91+
self._device.write16(port << 1, newstate)
92+
return newstate
93+
94+
# Polarity inversion
95+
def polarity(self, pin, value):
96+
return self._readandchangepin(POLARITY_PORT, pin, value)
97+
98+
# Pin direction
99+
def config(self, pin, mode):
100+
self.iodir = self._readandchangepin(CONFIG_PORT, pin, mode, self.iodir)
101+
return self.iodir
102+
103+
def output(self, pin, value):
104+
assert self.iodir & (1 << pin) == 0, "Pin %s not set to output" % pin
105+
self.outputvalue = self._readandchangepin(OUTPUT_PORT, pin, value, self.outputvalue)
106+
return self.outputvalue
107+
108+
def input(self, pin):
109+
assert self.iodir & (1 << pin) != 0, "Pin %s not set to input" % pin
110+
if self.num_gpios <= 8:
111+
value = self._device.readU8(INPUT_PORT)
112+
elif self.num_gpios > 8 and self.num_gpios <= 16:
113+
value = self._device.readU16(INPUT_PORT << 1)
114+
return value & (1 << pin)
115+
116+
def setup(self, pin, mode):
117+
self.config(pin, mode)
118+
119+
def cleanup(self, pin=None):
120+
# nothing to cleanup
121+
pass

0 commit comments

Comments
 (0)