|
| 1 | +# The MIT License (MIT) |
| 2 | +# |
| 3 | +# Copyright (c) 2017 Tony DiCola for Adafruit Industries |
| 4 | +# refactor by Carter Nelson |
| 5 | +# |
| 6 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | +# of this software and associated documentation files (the "Software"), to deal |
| 8 | +# in the Software without restriction, including without limitation the rights |
| 9 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | +# copies of the Software, and to permit persons to whom the Software is |
| 11 | +# furnished to do so, subject to the following conditions: |
| 12 | +# |
| 13 | +# The above copyright notice and this permission notice shall be included in |
| 14 | +# all copies or substantial portions of the Software. |
| 15 | +# |
| 16 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | +# THE SOFTWARE. |
| 23 | +""" |
| 24 | +`digital_inout` |
| 25 | +==================================================== |
| 26 | +
|
| 27 | +Digital input/output of the MCP230xx. |
| 28 | +
|
| 29 | +* Author(s): Tony DiCola |
| 30 | +""" |
| 31 | + |
| 32 | +import digitalio |
| 33 | + |
| 34 | +__version__ = "0.0.0-auto.0" |
| 35 | +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx.git" |
| 36 | + |
| 37 | +# Internal helpers to simplify setting and getting a bit inside an integer. |
| 38 | +def _get_bit(val, bit): |
| 39 | + return val & (1 << bit) > 0 |
| 40 | + |
| 41 | +def _enable_bit(val, bit): |
| 42 | + return val | (1 << bit) |
| 43 | + |
| 44 | +def _clear_bit(val, bit): |
| 45 | + return val & ~(1 << bit) |
| 46 | + |
| 47 | + |
| 48 | +class DigitalInOut: |
| 49 | + """Digital input/output of the MCP230xx. The interface is exactly the |
| 50 | + same as the digitalio.DigitalInOut class (however the MCP230xx does not |
| 51 | + support pull-down resistors and an exception will be thrown |
| 52 | + attempting to set one). |
| 53 | + """ |
| 54 | + |
| 55 | + def __init__(self, pin_number, mcp230xx): |
| 56 | + """Specify the pin number of the MCP230xx (0...7 for MCP23008, or 0...15 |
| 57 | + for MCP23017) and MCP23008 instance. |
| 58 | + """ |
| 59 | + self._pin = pin_number |
| 60 | + self._mcp = mcp230xx |
| 61 | + |
| 62 | + # kwargs in switch functions below are _necessary_ for compatibility |
| 63 | + # with DigitalInout class (which allows specifying pull, etc. which |
| 64 | + # is unused by this class). Do not remove them, instead turn off pylint |
| 65 | + # in this case. |
| 66 | + #pylint: disable=unused-argument |
| 67 | + def switch_to_output(self, value=False, **kwargs): |
| 68 | + """Switch the pin state to a digital output with the provided starting |
| 69 | + value (True/False for high or low, default is False/low). |
| 70 | + """ |
| 71 | + self.direction = digitalio.Direction.OUTPUT |
| 72 | + self.value = value |
| 73 | + |
| 74 | + def switch_to_input(self, pull=None, **kwargs): |
| 75 | + """Switch the pin state to a digital input with the provided starting |
| 76 | + pull-up resistor state (optional, no pull-up by default). Note that |
| 77 | + pull-down resistors are NOT supported! |
| 78 | + """ |
| 79 | + self.direction = digitalio.Direction.INPUT |
| 80 | + self.pull = pull |
| 81 | + #pylint: enable=unused-argument |
| 82 | + |
| 83 | + @property |
| 84 | + def value(self): |
| 85 | + """The value of the pin, either True for high or False for |
| 86 | + low. Note you must configure as an output or input appropriately |
| 87 | + before reading and writing this value. |
| 88 | + """ |
| 89 | + return _get_bit(self._mcp.gpio, self._pin) |
| 90 | + |
| 91 | + @value.setter |
| 92 | + def value(self, val): |
| 93 | + if val: |
| 94 | + self._mcp.gpio = _enable_bit(self._mcp.gpio, self._pin) |
| 95 | + else: |
| 96 | + self._mcp.gpio = _clear_bit(self._mcp.gpio, self._pin) |
| 97 | + |
| 98 | + @property |
| 99 | + def direction(self): |
| 100 | + """The direction of the pin, either True for an input or |
| 101 | + False for an output. |
| 102 | + """ |
| 103 | + if _get_bit(self._mcp.iodir, self._pin): |
| 104 | + return digitalio.Direction.INPUT |
| 105 | + return digitalio.Direction.OUTPUT |
| 106 | + |
| 107 | + @direction.setter |
| 108 | + def direction(self, val): |
| 109 | + if val == digitalio.Direction.INPUT: |
| 110 | + self._mcp.iodir = _enable_bit(self._mcp.iodir, self._pin) |
| 111 | + elif val == digitalio.Direction.OUTPUT: |
| 112 | + self._mcp.iodir = _clear_bit(self._mcp.iodir, self._pin) |
| 113 | + else: |
| 114 | + raise ValueError('Expected INPUT or OUTPUT direction!') |
| 115 | + |
| 116 | + @property |
| 117 | + def pull(self): |
| 118 | + """Enable or disable internal pull-up resistors for this pin. A |
| 119 | + value of digitalio.Pull.UP will enable a pull-up resistor, and None will |
| 120 | + disable it. Pull-down resistors are NOT supported! |
| 121 | + """ |
| 122 | + if _get_bit(self._mcp.gppu, self._pin): |
| 123 | + return digitalio.Pull.UP |
| 124 | + return None |
| 125 | + |
| 126 | + @pull.setter |
| 127 | + def pull(self, val): |
| 128 | + if val is None: |
| 129 | + self._mcp.gppu = _clear_bit(self._mcp.gppu, self._pin) |
| 130 | + elif val == digitalio.Pull.UP: |
| 131 | + self._mcp.gppu = _enable_bit(self._mcp.gppu, self._pin) |
| 132 | + elif val == digitalio.Pull.DOWN: |
| 133 | + raise ValueError('Pull-down resistors are not supported!') |
| 134 | + else: |
| 135 | + raise ValueError('Expected UP, DOWN, or None for pull state!') |
0 commit comments