/ adafruit_mcp230xx / mcp23017.py
mcp23017.py
1 # SPDX-FileCopyrightText: 2017 Tony DiCola for Adafruit Industries 2 # SPDX-FileCopyrightText: 2019 Carter Nelson 3 # 4 # SPDX-License-Identifier: MIT 5 6 """ 7 `mcp23017` 8 ==================================================== 9 10 CircuitPython module for the MCP23017 I2C I/O extenders. 11 12 * Author(s): Tony DiCola 13 """ 14 15 from micropython import const 16 from .mcp230xx import MCP230XX 17 from .digital_inout import DigitalInOut 18 19 __version__ = "0.0.0-auto.0" 20 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx.git" 21 22 # pylint: disable=bad-whitespace 23 _MCP23017_ADDRESS = const(0x20) 24 _MCP23017_IODIRA = const(0x00) 25 _MCP23017_IODIRB = const(0x01) 26 _MCP23017_IPOLA = const(0x02) 27 _MCP23017_GPINTENA = const(0x04) 28 _MCP23017_DEFVALA = const(0x06) 29 _MCP23017_INTCONA = const(0x08) 30 _MCP23017_IOCON = const(0x0A) 31 _MCP23017_GPPUA = const(0x0C) 32 _MCP23017_GPPUB = const(0x0D) 33 _MCP23017_GPIOA = const(0x12) 34 _MCP23017_GPIOB = const(0x13) 35 _MCP23017_INTFA = const(0x0E) 36 _MCP23017_INTFB = const(0x0F) 37 _MCP23017_INTCAPA = const(0x10) 38 _MCP23017_INTCAPB = const(0x11) 39 40 41 class MCP23017(MCP230XX): 42 """Supports MCP23017 instance on specified I2C bus and optionally 43 at the specified I2C address. 44 """ 45 46 def __init__(self, i2c, address=_MCP23017_ADDRESS): 47 super().__init__(i2c, address) 48 # Reset to all inputs with no pull-ups and no inverted polarity. 49 self.iodir = 0xFFFF 50 self.gppu = 0x0000 51 self.iocon = 0x4 # turn on IRQ Pins as open drain 52 self._write_u16le(_MCP23017_IPOLA, 0x0000) 53 54 @property 55 def gpio(self): 56 """The raw GPIO output register. Each bit represents the 57 output value of the associated pin (0 = low, 1 = high), assuming that 58 pin has been configured as an output previously. 59 """ 60 return self._read_u16le(_MCP23017_GPIOA) 61 62 @gpio.setter 63 def gpio(self, val): 64 self._write_u16le(_MCP23017_GPIOA, val) 65 66 @property 67 def gpioa(self): 68 """The raw GPIO A output register. Each bit represents the 69 output value of the associated pin (0 = low, 1 = high), assuming that 70 pin has been configured as an output previously. 71 """ 72 return self._read_u8(_MCP23017_GPIOA) 73 74 @gpioa.setter 75 def gpioa(self, val): 76 self._write_u8(_MCP23017_GPIOA, val) 77 78 @property 79 def gpiob(self): 80 """The raw GPIO B output register. Each bit represents the 81 output value of the associated pin (0 = low, 1 = high), assuming that 82 pin has been configured as an output previously. 83 """ 84 return self._read_u8(_MCP23017_GPIOB) 85 86 @gpiob.setter 87 def gpiob(self, val): 88 self._write_u8(_MCP23017_GPIOB, val) 89 90 @property 91 def iodir(self): 92 """The raw IODIR direction register. Each bit represents 93 direction of a pin, either 1 for an input or 0 for an output mode. 94 """ 95 return self._read_u16le(_MCP23017_IODIRA) 96 97 @iodir.setter 98 def iodir(self, val): 99 self._write_u16le(_MCP23017_IODIRA, val) 100 101 @property 102 def iodira(self): 103 """The raw IODIR A direction register. Each bit represents 104 direction of a pin, either 1 for an input or 0 for an output mode. 105 """ 106 return self._read_u8(_MCP23017_IODIRA) 107 108 @iodira.setter 109 def iodira(self, val): 110 self._write_u8(_MCP23017_IODIRA, val) 111 112 @property 113 def iodirb(self): 114 """The raw IODIR B direction register. Each bit represents 115 direction of a pin, either 1 for an input or 0 for an output mode. 116 """ 117 return self._read_u8(_MCP23017_IODIRB) 118 119 @iodirb.setter 120 def iodirb(self, val): 121 self._write_u8(_MCP23017_IODIRB, val) 122 123 @property 124 def gppu(self): 125 """The raw GPPU pull-up register. Each bit represents 126 if a pull-up is enabled on the specified pin (1 = pull-up enabled, 127 0 = pull-up disabled). Note pull-down resistors are NOT supported! 128 """ 129 return self._read_u16le(_MCP23017_GPPUA) 130 131 @gppu.setter 132 def gppu(self, val): 133 self._write_u16le(_MCP23017_GPPUA, val) 134 135 @property 136 def gppua(self): 137 """The raw GPPU A pull-up register. Each bit represents 138 if a pull-up is enabled on the specified pin (1 = pull-up enabled, 139 0 = pull-up disabled). Note pull-down resistors are NOT supported! 140 """ 141 return self._read_u8(_MCP23017_GPPUA) 142 143 @gppua.setter 144 def gppua(self, val): 145 self._write_u8(_MCP23017_GPPUA, val) 146 147 @property 148 def gppub(self): 149 """The raw GPPU B pull-up register. Each bit represents 150 if a pull-up is enabled on the specified pin (1 = pull-up enabled, 151 0 = pull-up disabled). Note pull-down resistors are NOT supported! 152 """ 153 return self._read_u8(_MCP23017_GPPUB) 154 155 @gppub.setter 156 def gppub(self, val): 157 self._write_u8(_MCP23017_GPPUB, val) 158 159 def get_pin(self, pin): 160 """Convenience function to create an instance of the DigitalInOut class 161 pointing at the specified pin of this MCP23017 device. 162 """ 163 assert 0 <= pin <= 15 164 return DigitalInOut(pin, self) 165 166 @property 167 def interrupt_configuration(self): 168 """The raw INTCON interrupt control register. The INTCON register 169 controls how the associated pin value is compared for the 170 interrupt-on-change feature. If a bit is set, the corresponding 171 I/O pin is compared against the associated bit in the DEFVAL 172 register. If a bit value is clear, the corresponding I/O pin is 173 compared against the previous value. 174 """ 175 return self._read_u16le(_MCP23017_INTCONA) 176 177 @interrupt_configuration.setter 178 def interrupt_configuration(self, val): 179 self._write_u16le(_MCP23017_INTCONA, val) 180 181 @property 182 def interrupt_enable(self): 183 """The raw GPINTEN interrupt control register. The GPINTEN register 184 controls the interrupt-on-change feature for each pin. If a bit is 185 set, the corresponding pin is enabled for interrupt-on-change. 186 The DEFVAL and INTCON registers must also be configured if any pins 187 are enabled for interrupt-on-change. 188 """ 189 return self._read_u16le(_MCP23017_GPINTENA) 190 191 @interrupt_enable.setter 192 def interrupt_enable(self, val): 193 self._write_u16le(_MCP23017_GPINTENA, val) 194 195 @property 196 def default_value(self): 197 """The raw DEFVAL interrupt control register. The default comparison 198 value is configured in the DEFVAL register. If enabled (via GPINTEN 199 and INTCON) to compare against the DEFVAL register, an opposite value 200 on the associated pin will cause an interrupt to occur. 201 """ 202 return self._read_u16le(_MCP23017_DEFVALA) 203 204 @default_value.setter 205 def default_value(self, val): 206 self._write_u16le(_MCP23017_DEFVALA, val) 207 208 @property 209 def io_control(self): 210 """The raw IOCON configuration register. Bit 1 controls interrupt 211 polarity (1 = active-high, 0 = active-low). Bit 2 is whether irq pin 212 is open drain (1 = open drain, 0 = push-pull). Bit 3 is unused. 213 Bit 4 is whether SDA slew rate is enabled (1 = yes). Bit 5 is if I2C 214 address pointer auto-increments (1 = no). Bit 6 is whether interrupt 215 pins are internally connected (1 = yes). Bit 7 is whether registers 216 are all in one bank (1 = no). 217 """ 218 return self._read_u8(_MCP23017_IOCON) 219 220 @io_control.setter 221 def io_control(self, val): 222 self._write_u8(_MCP23017_IOCON, val) 223 224 @property 225 def int_flag(self): 226 """Returns a list with the pin numbers that caused an interrupt 227 port A ----> pins 0-7 228 port B ----> pins 8-15 229 """ 230 intf = self._read_u16le(_MCP23017_INTFA) 231 flags = [pin for pin in range(16) if intf & (1 << pin)] 232 return flags 233 234 @property 235 def int_flaga(self): 236 """Returns a list of pin numbers that caused an interrupt in port A 237 pins: 0-7 238 """ 239 intfa = self._read_u8(_MCP23017_INTFA) 240 flags = [pin for pin in range(8) if intfa & (1 << pin)] 241 return flags 242 243 @property 244 def int_flagb(self): 245 """Returns a list of pin numbers that caused an interrupt in port B 246 pins: 8-15 247 """ 248 intfb = self._read_u8(_MCP23017_INTFB) 249 flags = [pin + 8 for pin in range(8) if intfb & (1 << pin)] 250 return flags 251 252 def clear_ints(self): 253 """Clears interrupts by reading INTCAP.""" 254 self._read_u16le(_MCP23017_INTCAPA) 255 256 def clear_inta(self): 257 """Clears port A interrupts.""" 258 self._read_u8(_MCP23017_INTCAPA) 259 260 def clear_intb(self): 261 """Clears port B interrupts.""" 262 self._read_u8(_MCP23017_INTCAPB)