Skip to content

Commit 3a26151

Browse files
authored
Initial checkin from Adafruit-Raspberry-Pi-Python-Code
Original source of Adafruit_MCP230xx.py which relies on Adafruit wrapper for Raspberry Pi I2C before porting to Micropython (based on adafruit/Adafruit-Raspberry-Pi-Python-Code@b11eda5 )
1 parent 419ff44 commit 3a26151

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed

mcp23017.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#!/usr/bin/python
2+
3+
# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried)
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+
MCP23017_IODIRA = 0x00
28+
MCP23017_IODIRB = 0x01
29+
MCP23017_GPIOA = 0x12
30+
MCP23017_GPIOB = 0x13
31+
MCP23017_GPPUA = 0x0C
32+
MCP23017_GPPUB = 0x0D
33+
MCP23017_OLATA = 0x14
34+
MCP23017_OLATB = 0x15
35+
MCP23008_GPIOA = 0x09
36+
MCP23008_GPPUA = 0x06
37+
MCP23008_OLATA = 0x0A
38+
39+
class Adafruit_MCP230XX(object):
40+
OUTPUT = 0
41+
INPUT = 1
42+
43+
def __init__(self, address, num_gpios, busnum=-1):
44+
assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16"
45+
self.i2c = Adafruit_I2C(address=address, busnum=busnum)
46+
self.address = address
47+
self.num_gpios = num_gpios
48+
49+
# set defaults
50+
if num_gpios <= 8:
51+
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
52+
self.direction = self.i2c.readU8(MCP23017_IODIRA)
53+
self.i2c.write8(MCP23008_GPPUA, 0x00)
54+
elif num_gpios > 8 and num_gpios <= 16:
55+
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
56+
self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B
57+
self.direction = self.i2c.readU8(MCP23017_IODIRA)
58+
self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8
59+
self.i2c.write8(MCP23017_GPPUA, 0x00)
60+
self.i2c.write8(MCP23017_GPPUB, 0x00)
61+
62+
def _changebit(self, bitmap, bit, value):
63+
assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
64+
if value == 0:
65+
return bitmap & ~(1 << bit)
66+
elif value == 1:
67+
return bitmap | (1 << bit)
68+
69+
def _readandchangepin(self, port, pin, value, currvalue = None):
70+
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
71+
#assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
72+
if not currvalue:
73+
currvalue = self.i2c.readU8(port)
74+
newvalue = self._changebit(currvalue, pin, value)
75+
self.i2c.write8(port, newvalue)
76+
return newvalue
77+
78+
79+
def pullup(self, pin, value):
80+
if self.num_gpios <= 8:
81+
return self._readandchangepin(MCP23008_GPPUA, pin, value)
82+
if self.num_gpios <= 16:
83+
lvalue = self._readandchangepin(MCP23017_GPPUA, pin, value)
84+
if (pin < 8):
85+
return
86+
else:
87+
return self._readandchangepin(MCP23017_GPPUB, pin-8, value) << 8
88+
89+
# Set pin to either input or output mode
90+
def config(self, pin, mode):
91+
if self.num_gpios <= 8:
92+
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
93+
if self.num_gpios <= 16:
94+
if (pin < 8):
95+
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
96+
else:
97+
self.direction |= self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8
98+
99+
return self.direction
100+
101+
def output(self, pin, value):
102+
# assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
103+
if self.num_gpios <= 8:
104+
self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA))
105+
if self.num_gpios <= 16:
106+
if (pin < 8):
107+
self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA))
108+
else:
109+
self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) << 8
110+
111+
return self.outputvalue
112+
113+
114+
self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue)
115+
return self.outputvalue
116+
117+
def input(self, pin):
118+
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
119+
assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
120+
if self.num_gpios <= 8:
121+
value = self.i2c.readU8(MCP23008_GPIOA)
122+
elif self.num_gpios > 8 and self.num_gpios <= 16:
123+
value = self.i2c.readU8(MCP23017_GPIOA)
124+
value |= self.i2c.readU8(MCP23017_GPIOB) << 8
125+
return value & (1 << pin)
126+
127+
def readU8(self):
128+
result = self.i2c.readU8(MCP23008_OLATA)
129+
return(result)
130+
131+
def readS8(self):
132+
result = self.i2c.readU8(MCP23008_OLATA)
133+
if (result > 127): result -= 256
134+
return result
135+
136+
def readU16(self):
137+
assert self.num_gpios >= 16, "16bits required"
138+
lo = self.i2c.readU8(MCP23017_OLATA)
139+
hi = self.i2c.readU8(MCP23017_OLATB)
140+
return((hi << 8) | lo)
141+
142+
def readS16(self):
143+
assert self.num_gpios >= 16, "16bits required"
144+
lo = self.i2c.readU8(MCP23017_OLATA)
145+
hi = self.i2c.readU8(MCP23017_OLATB)
146+
if (hi > 127): hi -= 256
147+
return((hi << 8) | lo)
148+
149+
def write8(self, value):
150+
self.i2c.write8(MCP23008_OLATA, value)
151+
152+
def write16(self, value):
153+
assert self.num_gpios >= 16, "16bits required"
154+
self.i2c.write8(MCP23017_OLATA, value & 0xFF)
155+
self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF)
156+
157+
# RPi.GPIO compatible interface for MCP23017 and MCP23008
158+
159+
class MCP230XX_GPIO(object):
160+
OUT = 0
161+
IN = 1
162+
BCM = 0
163+
BOARD = 0
164+
def __init__(self, busnum, address, num_gpios):
165+
self.chip = Adafruit_MCP230XX(address, num_gpios, busnum)
166+
def setmode(self, mode):
167+
# do nothing
168+
pass
169+
def setup(self, pin, mode):
170+
self.chip.config(pin, mode)
171+
def input(self, pin):
172+
return self.chip.input(pin)
173+
def output(self, pin, value):
174+
self.chip.output(pin, value)
175+
def pullup(self, pin, value):
176+
self.chip.pullup(pin, value)
177+
178+
179+
if __name__ == '__main__':
180+
# ***************************************************
181+
# Set num_gpios to 8 for MCP23008 or 16 for MCP23017!
182+
# ***************************************************
183+
mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) # MCP23008
184+
# mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 16) # MCP23017
185+
186+
# Set pins 0, 1 and 2 to output (you can set pins 0..15 this way)
187+
mcp.config(0, mcp.OUTPUT)
188+
mcp.config(1, mcp.OUTPUT)
189+
mcp.config(2, mcp.OUTPUT)
190+
191+
# Set pin 3 to input with the pullup resistor enabled
192+
mcp.config(3, mcp.INPUT)
193+
mcp.pullup(3, 1)
194+
195+
# Read input pin and display the results
196+
print "Pin 3 = %d" % (mcp.input(3) >> 3)
197+
198+
# Python speed test on output 0 toggling at max speed
199+
print "Starting blinky on pin 0 (CTRL+C to quit)"
200+
while (True):
201+
mcp.output(0, 1) # Pin 0 High
202+
time.sleep(1);
203+
mcp.output(0, 0) # Pin 0 Low
204+
time.sleep(1);

0 commit comments

Comments
 (0)