Metadata-Version: 2.4
Name: mcp23008
Version: 0.1.0
Summary: Python Library to interface with Microchip MCP23008 8-bit I2C I/O expander.
Author-email: Jonathan Oxer <jon@oxer.com.au>
Maintainer-email: Jonathan Oxer <jon@oxer.com.au>
License: MIT
Project-URL: bugs, https://github.com/SuperHouse/mcp23008/issues
Project-URL: homepage, https://github.com/SuperHouse/mcp23008
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: smbus2>=0.4.0
Dynamic: license-file

# MCP23008 Python Library

The Microchip MCP23008 is an 8-bit I2C I/O expander with per-pin direction
control, per-pin input polarity inversion, and per-pin internal pull-up
resistors. Pull-down is not supported.

Note: on power-up, all pins default to inputs with no pull-ups and no
inverted polarity.

This library was created for use with the
[MCP23008-based I/O module](https://github.com/SuperHouse/IOMOD)
as part of the
[Testomatic PCB test jig system](https://github.com/superhouse/testomatic).

It follows the same injectable-transport design as this project's sibling
[`ad5593r`](https://github.com/SuperHouse/ad5593r) library, so both chips
can be driven consistently -- including from behind an I2C multiplexer.

## Installation

Install the required dependency:

```bash
pip install -r requirements.txt
```

Or install directly:

```bash
pip install smbus2
```

## Usage

### Basic Setup

```python
from mcp23008 import MCP23008

# Create instance with I2C address 0x20 (the default, set by the A0-A2 pins)
# bus_number defaults to 1 (for Raspberry Pi)
mcp = MCP23008(0x20, bus_number=1)

# Check connection
print(f"Connected: {mcp.is_connected()}")
print(f"Address: 0x{mcp.get_address():02X}")
```

### Configure a Single Pin

```python
from mcp23008 import PinMode

# Change just pin 3 to output mode, without needing to know (or affect)
# what every other pin is currently configured as
mcp.pin_mode(3, PinMode.OUTPUT)

# Also accepts the mode's string value directly
mcp.pin_mode(1, "input")
```

### Digital I/O

```python
# Set pin 0 as output
mcp.pin_mode(0, PinMode.OUTPUT)

# Write HIGH to pin 0
mcp.digital_write(0, 1)

# Write LOW to pin 0
mcp.digital_write(0, 0)

# Write to all pins at once
mcp.digital_write_all(0b10101010)

# Set pin 1 as input, with its internal pull-up enabled
mcp.pin_mode(1, PinMode.INPUT)
mcp.set_pullup(1, True)

# Read pin 1
value = mcp.digital_read(1)

# Read all pins at once
all_pins = mcp.digital_read_all()
```

### Reset

```python
# Return all registers to their power-on-reset defaults (all pins input,
# no pull-ups, no inverted polarity). This is a *software* reset via
# register writes -- MCP23008 has no I2C reset command, only a hardware
# RESET pin, which this cannot drive.
mcp.reset()
```

### Cleanup

```python
# Close I2C bus when done
mcp.close()
```

## Examples

See the `examples/` directory:

- `examples/example_digital_output.py`: set pin 0 to digital output and drive it high, then low
- `examples/example_digital_output_passed_i2c.py`: the same digital output example, but with the I2C connection set up externally and passed in
- `examples/example_digital_input.py`: set pin 1 to digital input (with its pull-up enabled) and read it repeatedly

`example_digital_output.py` and `example_digital_output_passed_i2c.py` cover the same pin operations but show the two ways to set up the I2C connection, so you can compare them directly:

- **Let MCP23008 manage it** (`bus_number=1`, the default) -- the simplest option. MCP23008 lazily opens its own `smbus2.SMBus` on first use, and `close()` closes it. This is enough for the common case of a single MCP23008 directly on the Raspberry Pi's I2C bus.
- **Set it up yourself and pass it in** (`i2c_bus=...`) -- needed whenever something else has to control the connection: for example, several devices sharing one bus, or a device sitting behind an I2C multiplexer that needs a channel selected before each transaction. MCP23008 only needs an object exposing `writeto(address, buffer)`/`readfrom(address, length)`; since you own the connection's lifecycle, MCP23008 won't open or close it for you.

## Differences from the MCP23017 (and other MCP230xx variants)

The MCP23017 is functionally similar but has 16 I/O pins split across two
banks ("A" and "B"), addressed at different register offsets -- e.g. its
port-A `GPIO` register is at `0x12`, port-B at `0x13`. The MCP23008 has
only one bank, and its registers are laid out sequentially instead (`GPIO`
is at `0x09`). **This library only implements the MCP23008's single-bank
register map -- it will not address an MCP23017 or other dual-bank MCP230xx
part correctly**, despite the chips otherwise behaving very similarly.

## Error Codes

- `MCP23008_OK` (0x0000): Success
- `MCP23008_PIN_ERROR` (0xFF81): Invalid pin number
- `MCP23008_I2C_ERROR` (0xFF82): I2C communication error

## Notes

- If running on a Raspberry Pi, make sure I2C is enabled on your system! This
  is done using`sudo raspi-config` -> `Interface Options` -> `I2C`
- Uses `smbus2` for I2C communication
- Default I2C bus is 1 for Raspberry Pi. Modern Raspberry Pi models reserve bus 0
  for Pi Hat EEPROMs that are read at startup. Use `bus_number=0` for older
  Raspberry Pi models
- The device supports I2C addresses 0x20-0x27, set by the A0-A2 pins

## License

Released under the MIT licence.
