Skip to content

Commit f1a5ab7

Browse files
author
ladyada
committed
MCP23017 (and 23008 some day) classes
1 parent 4e28f20 commit f1a5ab7

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed
+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/usr/bin/python
2+
3+
# Copyright 2012 Daniel Berlin
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin
7+
# the Software without restriction, including without limitation the rights to
8+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9+
# of the Software, and to permit persons to whom the Software is furnished to do
10+
# so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# 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 THE
21+
# SOFTWARE.
22+
23+
from Adafruit_I2C import Adafruit_I2C
24+
import smbus
25+
import time
26+
27+
28+
MCP23008_IODIRA = 0x00
29+
30+
MCP23017_IODIRA = 0x00
31+
MCP23017_IODIRB = 0x01
32+
MCP23017_GPIOA = 0x12
33+
MCP23017_GPIOB = 0x13
34+
MCP23017_GPPUA = 0x0C
35+
MCP23017_GPPUB = 0x0D
36+
MCP23017_OLATA = 0x14
37+
MCP23017_OLATB = 0x15
38+
39+
OUTPUT = 0
40+
INPUT = 1
41+
42+
class Adafruit_MCP230XX(object):
43+
44+
def __init__(self, busnum, address, num_gpios):
45+
assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16"
46+
self.i2c = Adafruit_I2C(address, smbus.SMBus(busnum), True)
47+
self.address = address
48+
self.num_gpios = num_gpios
49+
50+
# set defaults
51+
52+
if num_gpios <= 8:
53+
self.i2c.write8(MCP23008_IODIRA, 0xFF) # all inputs on port A
54+
self.direction = self.i2c.readU8(MCP23008_IODIRA)
55+
self.i2c.write8(MCP23008_GPPU, 0x00)
56+
elif num_gpios > 8 and num_gpios <= 16:
57+
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
58+
self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B
59+
self.direction = self.i2c.readU8(MCP23017_IODIRA)
60+
self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8
61+
self.i2c.write8(MCP23017_GPPUA, 0x00)
62+
self.i2c.write8(MCP23017_GPPUB, 0x00)
63+
64+
def _changebit(self, bitmap, bit, value):
65+
assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
66+
if value == 0:
67+
return bitmap & ~(1 << bit)
68+
elif value == 1:
69+
return bitmap | (1 << bit)
70+
71+
def _readandchangepin(self, port, pin, value, currvalue = None):
72+
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
73+
#assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
74+
if not currvalue:
75+
currvalue = self.i2c.readU8(port)
76+
newvalue = self._changebit(currvalue, pin, value)
77+
self.i2c.write8(port, newvalue)
78+
return newvalue
79+
80+
81+
def pullup(self, pin, value):
82+
if self.num_gpios <= 8:
83+
return self._readandchangepin(MCP23008_GPPU, pin, value)
84+
if self.num_gpios <= 16:
85+
if (pin < 8):
86+
return self._readandchangepin(MCP23017_GPPUA, pin, value)
87+
else:
88+
return self._readandchangepin(MCP23017_GPPUB, pin-8, value)
89+
90+
# Set pin to either input or output mode
91+
def config(self, pin, mode):
92+
if self.num_gpios <= 8:
93+
self.direction = self._readandchangepin(MCP23008_IODIR, pin, mode)
94+
if self.num_gpios <= 16:
95+
if (pin < 8):
96+
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
97+
else:
98+
self.direction = self._readandchangepin(MCP23017_IODIRB, pin-8, mode)
99+
100+
return self.direction
101+
102+
def output(self, pin, value):
103+
assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
104+
105+
if self.num_gpios <= 8:
106+
self.outputvalue = self._readandchangepin(MCP23008_GPIO, pin, value. self.i2c.readU8(MCP23008_OLAT))
107+
if self.num_gpios <= 16:
108+
if (pin < 8):
109+
self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA))
110+
else:
111+
self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB))
112+
113+
return self.outputvalue
114+
115+
116+
self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue)
117+
return self.outputvalue
118+
119+
def input(self, pin):
120+
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
121+
assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
122+
if self.num_gpios <= 8:
123+
value = self.i2c.readU8(MCP23008_GPIO)
124+
elif self.num_gpios > 8 and self.num_gpios <= 16:
125+
value = self.i2c.readU16(MCP23017_GPIOA)
126+
temp = value >> 8
127+
value <<= 8
128+
value |= temp
129+
return value & (1 << pin)
130+
131+
132+
133+
# RPi.GPIO compatible interface for MCP23017 and MCP23008
134+
135+
class MCP230XX_GPIO(object):
136+
OUT = 0
137+
IN = 1
138+
BCM = 0
139+
BOARD = 0
140+
def __init__(self, busnum, address, num_gpios):
141+
self.chip = Adafruit_MCP230XX(busnum, address, num_gpios)
142+
def setmode(self, mode):
143+
# do nothing
144+
pass
145+
def setup(self, pin, mode):
146+
self.chip.config(pin, mode)
147+
def input(self, pin):
148+
return self.chip.input(pin)
149+
def output(self, pin, value):
150+
self.chip.output(pin, value)
151+
def pullup(self, pin, value):
152+
self.chip.pullup(pin, value)
153+
154+
155+
if __name__ == '__main__':
156+
157+
# input test
158+
# for i in range(16):
159+
# mcp.pullup(i, 1)
160+
# while (True):
161+
# for i in range(16):
162+
# print "%d: %x" % (i, mcp.input(i) >> i)
163+
164+
# output test
165+
# for i in range(16):
166+
# mcp.config(i, OUTPUT)
167+
# while (True):
168+
# for i in range(16):
169+
# mcp.output(i, 0)
170+
# time.sleep(0.1)
171+
# for i in range(16):
172+
# mcp.output(i, 1)
173+
# time.sleep(0.1)
174+
175+
176+
mcp = Adafruit_MCP230XX(busnum = 1, address = 0x20, num_gpios = 16)
177+
mcp.config(8, OUTPUT)
178+
mcp.config(7, OUTPUT)
179+
mcp.config(6, OUTPUT)
180+
mcp.output(8, 1)
181+
mcp.output(7, 1)
182+
mcp.output(6, 1)

0 commit comments

Comments
 (0)