From a77e6596d42ee75ff197a1dce6fdc77a38518853 Mon Sep 17 00:00:00 2001 From: Evgeny Vlasenko Date: Sun, 22 Sep 2024 22:23:30 +0400 Subject: [PATCH 1/3] feat: add xl9535 support, issue #400 --- mqtt_io/modules/gpio/xl9535.py | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 mqtt_io/modules/gpio/xl9535.py diff --git a/mqtt_io/modules/gpio/xl9535.py b/mqtt_io/modules/gpio/xl9535.py new file mode 100644 index 00000000..1785e3d3 --- /dev/null +++ b/mqtt_io/modules/gpio/xl9535.py @@ -0,0 +1,79 @@ +""" +XL9535/PCA9535/TCA9535 IO expander +""" + +from typing import Optional, cast + +from ...exceptions import RuntimeConfigError +from ...types import ConfigType, PinType +from . import GenericGPIO, PinDirection, PinPUD + +REQUIREMENTS = ("smbus2",) +CONFIG_SCHEMA = { + "i2c_bus_num": {"type": "integer", "required": True, "empty": False}, + "chip_addr": {"type": "integer", "required": True, "empty": False}, +} + +#XL9535_INPUT_PORT_0 = 0x00, +#XL9535_INPUT_PORT_1 = 0x01 +XL9535_OUTPUT_PORT_0 = 0x02 +#XL9535_OUTPUT_PORT_1 = 0x03 +#XL9535_INVERSION_PORT_0 = 0x04 +#XL9535_INVERSION_PORT_1 = 0x05 +XL9535_CONFIG_PORT_0 = 0x06 +#XL9535_CONFIG_PORT_1 = 0x07 + +class GPIO(GenericGPIO): + """ + Implementation of GPIO class for the XL9535/PCA9535/TCA9535 IO expander chip. + + Pin numbers 0 - 15. + """ + + PIN_SCHEMA = { + "pin": {"type": 'integer', "required": True, "min": 0, "max": 15}, + } + + def setup_module(self) -> None: + # pylint: disable=import-outside-toplevel,import-error + # pylint: disable=no-name-in-module + from smbus2 import SMBus # type: ignore + + self.bus = SMBus(self.config["i2c_bus_num"]) + self.address = self.config["chip_addr"] + + # configure all pins as outputs + self.bus.write_word_data(self.address, XL9535_CONFIG_PORT_0, 0x0000) + # off all outputs be default + self.bus.write_word_data(self.address, XL9535_OUTPUT_PORT_0, 0x0000) + + def setup_pin( + self, + pin: PinType, + direction: PinDirection, + pullup: PinPUD, + pin_config: ConfigType, + initial: Optional[str] = None, + ) -> None: + # I han't found any ready-made expansion boards on sale where the chip works as an input. + # For simplicity, the implementation only supports the chip working in output mode. + if direction == PinDirection.INPUT: + raise RuntimeConfigError("Unsupported PinDirection: INPUT") + initial = pin_config.get("initial") + if initial is not None: + if initial == "high": + self.set_pin(pin, True) + elif initial == "low": + self.set_pin(pin, False) + + def set_pin(self, pin: PinType, value: bool) -> None: + assert pin in range(16), "Pin number must be an integer between 0 and 15" + current_state = self.bus.read_word_data(self.address, XL9535_OUTPUT_PORT_0) + bit = 1 << cast(int, pin) + new_state = current_state | bit if value else current_state & (~bit & 0xffff) + self.bus.write_word_data(self.address, XL9535_OUTPUT_PORT_0, new_state) + + def get_pin(self, pin: PinType) -> bool: + assert pin in range(16), "Pin number must be an integer between 0 and 15" + state = self.bus.read_word_data(self.address, XL9535_OUTPUT_PORT_0) + return bool(state & 1 << cast(int, pin)) From e56784994e9e19b5e157dfa28f2781b993eb07fa Mon Sep 17 00:00:00 2001 From: Evgeny Vlasenko Date: Thu, 26 Sep 2024 18:49:01 +0400 Subject: [PATCH 2/3] fix: close i2c bus --- mqtt_io/modules/gpio/xl9535.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mqtt_io/modules/gpio/xl9535.py b/mqtt_io/modules/gpio/xl9535.py index 1785e3d3..14d768d2 100644 --- a/mqtt_io/modules/gpio/xl9535.py +++ b/mqtt_io/modules/gpio/xl9535.py @@ -77,3 +77,6 @@ def get_pin(self, pin: PinType) -> bool: assert pin in range(16), "Pin number must be an integer between 0 and 15" state = self.bus.read_word_data(self.address, XL9535_OUTPUT_PORT_0) return bool(state & 1 << cast(int, pin)) + + def cleanup(self) -> None: + self.bus.close() From 3d9126421c1554d0542e2f08eb63ac6c4854cfb9 Mon Sep 17 00:00:00 2001 From: Evgeny Vlasenko Date: Thu, 26 Sep 2024 19:21:26 +0400 Subject: [PATCH 3/3] chore: add xl9535 to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 03a469c0..f66a87bb 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Hardware support is provided by specific GPIO, Sensor and Stream modules. It's e - PCF8575 IO expander (`pcf8575`) - PiFace Digital IO 2 (`piface2`) - Raspberry Pi GPIO (`raspberrypi`) + - XL9535/PCA9535/TCA9535 IO expander (`xl9535`) ### Sensors