diff options
Diffstat (limited to 'lib/Adafruit_Python_GPIO/Adafruit_GPIO/MCP230xx.py')
-rw-r--r-- | lib/Adafruit_Python_GPIO/Adafruit_GPIO/MCP230xx.py | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lib/Adafruit_Python_GPIO/Adafruit_GPIO/MCP230xx.py b/lib/Adafruit_Python_GPIO/Adafruit_GPIO/MCP230xx.py new file mode 100644 index 0000000..3ba8b5f --- /dev/null +++ b/lib/Adafruit_Python_GPIO/Adafruit_GPIO/MCP230xx.py @@ -0,0 +1,165 @@ +# Copyright (c) 2014 Adafruit Industries +# Author: Tony DiCola +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +import math + +import Adafruit_GPIO as GPIO +import Adafruit_GPIO.I2C as I2C + + +class MCP230xxBase(GPIO.BaseGPIO): + """Base class to represent an MCP230xx series GPIO extender. Is compatible + with the Adafruit_GPIO BaseGPIO class so it can be used as a custom GPIO + class for interacting with device. + """ + + def __init__(self, address, i2c=None, **kwargs): + """Initialize MCP230xx at specified I2C address and bus number. If bus + is not specified it will default to the appropriate platform detected bus. + """ + # Create I2C device. + if i2c is None: + import Adafruit_GPIO.I2C as I2C + i2c = I2C + self._device = i2c.get_i2c_device(address, **kwargs) + # Assume starting in ICON.BANK = 0 mode (sequential access). + # Compute how many bytes are needed to store count of GPIO. + self.gpio_bytes = int(math.ceil(self.NUM_GPIO/8.0)) + # Buffer register values so they can be changed without reading. + self.iodir = [0xFF]*self.gpio_bytes # Default direction to all inputs. + self.gppu = [0x00]*self.gpio_bytes # Default to pullups disabled. + self.gpio = [0x00]*self.gpio_bytes + # Write current direction and pullup buffer state. + self.write_iodir() + self.write_gppu() + + + def setup(self, pin, value): + """Set the input or output mode for a specified pin. Mode should be + either GPIO.OUT or GPIO.IN. + """ + self._validate_pin(pin) + # Set bit to 1 for input or 0 for output. + if value == GPIO.IN: + self.iodir[int(pin/8)] |= 1 << (int(pin%8)) + elif value == GPIO.OUT: + self.iodir[int(pin/8)] &= ~(1 << (int(pin%8))) + else: + raise ValueError('Unexpected value. Must be GPIO.IN or GPIO.OUT.') + self.write_iodir() + + + def output(self, pin, value): + """Set the specified pin the provided high/low value. Value should be + either GPIO.HIGH/GPIO.LOW or a boolean (True = HIGH). + """ + self.output_pins({pin: value}) + + def output_pins(self, pins): + """Set multiple pins high or low at once. Pins should be a dict of pin + name to pin value (HIGH/True for 1, LOW/False for 0). All provided pins + will be set to the given values. + """ + [self._validate_pin(pin) for pin in pins.keys()] + # Set each changed pin's bit. + for pin, value in iter(pins.items()): + if value: + self.gpio[int(pin/8)] |= 1 << (int(pin%8)) + else: + self.gpio[int(pin/8)] &= ~(1 << (int(pin%8))) + # Write GPIO state. + self.write_gpio() + + + def input(self, pin): + """Read the specified pin and return GPIO.HIGH/True if the pin is pulled + high, or GPIO.LOW/False if pulled low. + """ + return self.input_pins([pin])[0] + + def input_pins(self, pins): + """Read multiple pins specified in the given list and return list of pin values + GPIO.HIGH/True if the pin is pulled high, or GPIO.LOW/False if pulled low. + """ + [self._validate_pin(pin) for pin in pins] + # Get GPIO state. + self.gpio = self._device.readList(self.GPIO, self.gpio_bytes) + # Return True if pin's bit is set. + return [(self.gpio[int(pin/8)] & 1 << (int(pin%8))) > 0 for pin in pins] + + + def pullup(self, pin, enabled): + """Turn on the pull-up resistor for the specified pin if enabled is True, + otherwise turn off the pull-up resistor. + """ + self._validate_pin(pin) + if enabled: + self.gppu[int(pin/8)] |= 1 << (int(pin%8)) + else: + self.gppu[int(pin/8)] &= ~(1 << (int(pin%8))) + self.write_gppu() + + def write_gpio(self, gpio=None): + """Write the specified byte value to the GPIO registor. If no value + specified the current buffered value will be written. + """ + if gpio is not None: + self.gpio = gpio + self._device.writeList(self.GPIO, self.gpio) + + def write_iodir(self, iodir=None): + """Write the specified byte value to the IODIR registor. If no value + specified the current buffered value will be written. + """ + if iodir is not None: + self.iodir = iodir + self._device.writeList(self.IODIR, self.iodir) + + def write_gppu(self, gppu=None): + """Write the specified byte value to the GPPU registor. If no value + specified the current buffered value will be written. + """ + if gppu is not None: + self.gppu = gppu + self._device.writeList(self.GPPU, self.gppu) + + +class MCP23017(MCP230xxBase): + """MCP23017-based GPIO class with 16 GPIO pins.""" + # Define number of pins and registor addresses. + NUM_GPIO = 16 + IODIR = 0x00 + GPIO = 0x12 + GPPU = 0x0C + + def __init__(self, address=0x20, **kwargs): + super(MCP23017, self).__init__(address, **kwargs) + + +class MCP23008(MCP230xxBase): + """MCP23008-based GPIO class with 8 GPIO pins.""" + # Define number of pins and registor addresses. + NUM_GPIO = 8 + IODIR = 0x00 + GPIO = 0x09 + GPPU = 0x06 + + def __init__(self, address=0x20, **kwargs): + super(MCP23008, self).__init__(address, **kwargs) |