From 7f9383c83b1a4758b3950bf91333222d4ba40ca3 Mon Sep 17 00:00:00 2001 From: Penny Wood Date: Thu, 23 May 2024 05:31:56 +0800 Subject: [PATCH] [sx1509] Output open drain pin mode (#6788) --- esphome/components/sx1509/__init__.py | 4 ++ esphome/components/sx1509/sx1509.cpp | 56 ++++++++++++++----- .../components/sx1509/test.esp32-c3-idf.yaml | 18 ++++++ tests/components/sx1509/test.esp32-c3.yaml | 18 ++++++ tests/components/sx1509/test.esp32-idf.yaml | 18 ++++++ tests/components/sx1509/test.esp32.yaml | 18 ++++++ tests/components/sx1509/test.esp8266.yaml | 18 ++++++ tests/components/sx1509/test.rp2040.yaml | 18 ++++++ 8 files changed, 155 insertions(+), 13 deletions(-) diff --git a/esphome/components/sx1509/__init__.py b/esphome/components/sx1509/__init__.py index faef940125..e4f79dc2bc 100644 --- a/esphome/components/sx1509/__init__.py +++ b/esphome/components/sx1509/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + CONF_OPEN_DRAIN, ) CONF_KEYPAD = "keypad" @@ -79,6 +80,8 @@ def validate_mode(value): raise cv.Invalid("Pulldown only available with input") if value[CONF_PULLUP] and value[CONF_PULLDOWN]: raise cv.Invalid("Can only have one of pullup or pulldown") + if value[CONF_OPEN_DRAIN] and not value[CONF_OUTPUT]: + raise cv.Invalid("Open drain available only with output") return value @@ -94,6 +97,7 @@ SX1509_PIN_SCHEMA = cv.All( cv.Optional(CONF_PULLUP, default=False): cv.boolean, cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, cv.Optional(CONF_OUTPUT, default=False): cv.boolean, + cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, }, validate_mode, ), diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp index ee90e0e410..855a90bacd 100644 --- a/esphome/components/sx1509/sx1509.cpp +++ b/esphome/components/sx1509/sx1509.cpp @@ -86,33 +86,63 @@ void SX1509Component::digital_write(uint8_t pin, bool bit_value) { } void SX1509Component::pin_mode(uint8_t pin, gpio::Flags flags) { + ESP_LOGI(TAG, "Configuring pin %u with flags %x", pin, flags); + + uint16_t temp_word = 0; + this->read_byte_16(REG_DIR_B, &this->ddr_mask_); - if (flags == gpio::FLAG_OUTPUT) { + if (flags & gpio::FLAG_OUTPUT) { + // Always disable input buffer + this->read_byte_16(REG_INPUT_DISABLE_B, &temp_word); + temp_word |= (1 << pin); + this->write_byte_16(REG_INPUT_DISABLE_B, temp_word); + + if (flags & gpio::FLAG_OPEN_DRAIN) { + // Pullup must be disabled for open drain mode + this->read_byte_16(REG_PULL_UP_B, &temp_word); + temp_word &= ~(1 << pin); + this->write_byte_16(REG_PULL_UP_B, temp_word); + this->read_byte_16(REG_OPEN_DRAIN_B, &temp_word); + temp_word |= (1 << pin); + this->write_byte_16(REG_OPEN_DRAIN_B, temp_word); + ESP_LOGD(TAG, "Open drain output mode set for %u", pin); + } else { + ESP_LOGD(TAG, "Output Mode for %u", pin); + } + + // Set direction to output this->ddr_mask_ &= ~(1 << pin); + this->write_byte_16(REG_DIR_B, this->ddr_mask_); } else { - this->ddr_mask_ |= (1 << pin); + ESP_LOGD(TAG, "Input Mode for %u", pin); - uint16_t temp_pullup; - this->read_byte_16(REG_PULL_UP_B, &temp_pullup); - uint16_t temp_pulldown; - this->read_byte_16(REG_PULL_DOWN_B, &temp_pulldown); + // Always enable input buffer + this->read_byte_16(REG_INPUT_DISABLE_B, &temp_word); + temp_word &= ~(1 << pin); + this->write_byte_16(REG_INPUT_DISABLE_B, temp_word); + // Pullup + this->read_byte_16(REG_PULL_UP_B, &temp_word); if (flags & gpio::FLAG_PULLUP) { - temp_pullup |= (1 << pin); + temp_word |= (1 << pin); } else { - temp_pullup &= ~(1 << pin); + temp_word &= ~(1 << pin); } + this->write_byte_16(REG_PULL_UP_B, temp_word); + // Pulldown + this->read_byte_16(REG_PULL_DOWN_B, &temp_word); if (flags & gpio::FLAG_PULLDOWN) { - temp_pulldown |= (1 << pin); + temp_word |= (1 << pin); } else { - temp_pulldown &= ~(1 << pin); + temp_word &= ~(1 << pin); } + this->write_byte_16(REG_PULL_DOWN_B, temp_word); - this->write_byte_16(REG_PULL_UP_B, temp_pullup); - this->write_byte_16(REG_PULL_DOWN_B, temp_pulldown); + // Set direction to input + this->ddr_mask_ |= (1 << pin); + this->write_byte_16(REG_DIR_B, this->ddr_mask_); } - this->write_byte_16(REG_DIR_B, this->ddr_mask_); } void SX1509Component::setup_led_driver(uint8_t pin) { diff --git a/tests/components/sx1509/test.esp32-c3-idf.yaml b/tests/components/sx1509/test.esp32-c3-idf.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp32-c3-idf.yaml +++ b/tests/components/sx1509/test.esp32-c3-idf.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32-c3.yaml b/tests/components/sx1509/test.esp32-c3.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp32-c3.yaml +++ b/tests/components/sx1509/test.esp32-c3.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32-idf.yaml b/tests/components/sx1509/test.esp32-idf.yaml index 1698f2abc4..aa1d161a43 100644 --- a/tests/components/sx1509/test.esp32-idf.yaml +++ b/tests/components/sx1509/test.esp32-idf.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp32.yaml b/tests/components/sx1509/test.esp32.yaml index 1698f2abc4..aa1d161a43 100644 --- a/tests/components/sx1509/test.esp32.yaml +++ b/tests/components/sx1509/test.esp32.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.esp8266.yaml b/tests/components/sx1509/test.esp8266.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.esp8266.yaml +++ b/tests/components/sx1509/test.esp8266.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true diff --git a/tests/components/sx1509/test.rp2040.yaml b/tests/components/sx1509/test.rp2040.yaml index ced849b3df..0397812880 100644 --- a/tests/components/sx1509/test.rp2040.yaml +++ b/tests/components/sx1509/test.rp2040.yaml @@ -13,3 +13,21 @@ binary_sensor: pin: sx1509: sx1509_hub number: 3 + +switch: + - platform: gpio + name: GPIO SX1509 Test Out Open Drain + pin: + sx1509: sx1509_hub + number: 0 + mode: + output: true + open_drain: true + + - platform: gpio + name: GPIO SX1509 Test Out Standard + pin: + sx1509: sx1509_hub + number: 1 + mode: + output: true