diff --git a/esphome/components/dallas_pio/binary_sensor.py b/esphome/components/dallas_pio/binary_sensor.py index 9105655890..a64998febb 100644 --- a/esphome/components/dallas_pio/binary_sensor.py +++ b/esphome/components/dallas_pio/binary_sensor.py @@ -26,7 +26,9 @@ def validate_mode(value): CUSTOM_PIN_SCHEMA = cv.Schema( { - cv.Required("number"): cv.one_of("PIOA", "PIOB", upper=True), + cv.Required("number"): cv.one_of( + "PIOA", "PIOB", "P0", "P1", "P2", "P3", "P4", "P5", "P6", "P7", upper=True + ), cv.Optional(CONF_INVERTED, default=False): cv.boolean, cv.Optional(CONF_MODE, default={"input": True}): validate_mode, } @@ -63,6 +65,10 @@ async def to_code(config): cg.add(var.set_pin(0x01)) # PIOA assiociated to 0x01 elif pin_number == "PIOB": cg.add(var.set_pin(0x02)) # PIOB assiociated to 0x02 + elif pin_number.startswith("P"): + pin_index = int(pin_number[1:]) + if 0 <= pin_index <= 7: + cg.add(var.set_pin(1 + pin_index)) cg.add(var.set_pin_inverted(pin_inverted)) cg.add(var.set_pin_mode(pin_mode.get("input", True), pin_mode.get("output", False))) # cg.add(var.set_inverted(inverted)) diff --git a/esphome/components/dallas_pio/dallas_pio.cpp b/esphome/components/dallas_pio/dallas_pio.cpp index 1a04af19da..066b2c454e 100644 --- a/esphome/components/dallas_pio/dallas_pio.cpp +++ b/esphome/components/dallas_pio/dallas_pio.cpp @@ -147,6 +147,7 @@ bool DallasPio::ds2413_get_state_(uint8_t &state) { return false; break; } + state = this->pin_inverted_ ? !state : state; return true; } // ds2413_get_state_ @@ -326,6 +327,7 @@ bool DallasPio::ds2406_get_state_(uint8_t &state, bool use_crc = false) { return false; } state = pio_sensed_level; + state = this->pin_inverted_ ? !state : state; return true; } // ds2406_get_state_ @@ -497,7 +499,7 @@ bool DallasPio::ds2408_get_state_(uint8_t &state, bool use_crc = false) { } state = (current_state >> pin_index) & 0x01; - + state = this->pin_inverted_ ? !state : state; return true; } // ds2408_get_state_ @@ -509,15 +511,14 @@ void DallasPio::ds2408_write_state_(bool state, bool use_crc = false) { // PIO Output Latch State Register Bitmap // ADDR b7 b6 b5 b4 b3 b2 b1 b0 // 0x89 PL7 PL6 PL5 PL4 PL3 PL2 PL1 PL0 - // Initialize One-Wire bus for this device - uint8_t current_state = 0; + // Be aware to pull up RSTZ pin to be able to write outputs !! uint8_t ack = 0; - if (!this->ds2408_read_device_(current_state, use_crc)) { - this->status_set_warning(); - return; - } - uint8_t new_state = state ? (current_state | (1 << this->pin_)) : (current_state & ~(1 << this->pin_)); - + uint8_t new_state = (state ^ this->pin_inverted_) ? (this->ds2408_write_current_state_ | (1 << (this->pin_ - 1))) + : (this->ds2408_write_current_state_ & ~(1 << (this->pin_ - 1))); + this->ds2408_write_current_state_ = new_state; + uint8_t read_after_write = 0; + bool read_state_after_write = true; + // ESP_LOGD(TAG, "new_state: 0x%04X this->pin_: %d state: %u", new_state, this->pin_, state); if (!this->check_address_()) { this->status_set_warning(); return; @@ -533,9 +534,22 @@ void DallasPio::ds2408_write_state_(bool state, bool use_crc = false) { this->bus_->write8(new_state); this->bus_->write8(~new_state); ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure + read_after_write = this->bus_->read8(); } - if (ack != DALLAS_DS2413_COMMAND_PIO_ACK_SUCCESS) { - ESP_LOGW(TAG, "Failed to write One-Wire bus."); + // ESP_LOGD(TAG, "ack: 0x%04X read_after_write: 0x%04X", ack, read_after_write); + if (ack != DALLAS_DS2408_COMMAND_PIO_ACK_SUCCESS) { + ESP_LOGW(TAG, "Failed to write One-Wire bus with ack: 0x%04X", ack); + this->status_set_warning(); + return; + } + read_state_after_write = ((read_after_write & (1 << (this->pin_ - 1))) != 0); + if (read_state_after_write != state) { + ESP_LOGW(TAG, "Failed to write One-Wire bus write %u read %u", state, read_state_after_write); + this->status_set_warning(); + return; + } + if (!this->bus_->reset()) { + ESP_LOGW(TAG, "Failed to reset One-Wire bus."); this->status_set_warning(); return; } diff --git a/esphome/components/dallas_pio/dallas_pio.h b/esphome/components/dallas_pio/dallas_pio.h index 56280881bc..5e1856d60e 100644 --- a/esphome/components/dallas_pio/dallas_pio.h +++ b/esphome/components/dallas_pio/dallas_pio.h @@ -87,6 +87,7 @@ class DallasPio : public Component, public one_wire::OneWireDevice { bool pin_inverted_; uint8_t pio_output_register_; uint16_t calculate_crc16_(const uint8_t *data, size_t length); + uint8_t ds2408_write_current_state_ = 0xFF; }; } // namespace dallas_pio diff --git a/esphome/components/dallas_pio/dallas_pio.py b/esphome/components/dallas_pio/dallas_pio.py index 44f1dd0fda..18a35ce26b 100644 --- a/esphome/components/dallas_pio/dallas_pio.py +++ b/esphome/components/dallas_pio/dallas_pio.py @@ -14,17 +14,29 @@ CONF_REFERENCE = "reference" CONF_CRC = "crc" +def validate_pin(value, reference=""): + reference = reference.upper() + if reference in ["DS2413", "DS2406"]: + return cv.one_of("PIOA", "PIOB", upper=True)(value) + elif reference == "DS2408": + return cv.one_of("P0", "P1", "P2", "P3", "P4", "P5", "P6", "P7", upper=True)( + value + ) + raise cv.Invalid("Invalid pin configuration for the given reference.") + + def validate_crc_option(config_list): for conf in config_list: reference = conf.get("reference", "").upper() - if not reference or reference == "DS2413": + if not reference: continue - if reference in {"DS2406", "DS2408"} and "crc" not in conf: + crc_value = conf.get("crc", False) + if reference not in {"DS2413", "DS2406", "DS2408"}: + raise cv.Invalid(f"Unsupported reference: {reference}") + if crc_value and reference != "DS2406": raise cv.Invalid( - "Option 'crc' is required when 'reference' is DS2406 or DS2408." + f"Option 'crc' can only be set to true for reference DS2406, not {reference}." ) - if reference not in {"DS2406", "DS2408"} and "crc" in conf: - raise cv.Invalid("Option 'crc' is not supported for this reference.") return config_list diff --git a/esphome/components/dallas_pio/dallas_pio_constants.h b/esphome/components/dallas_pio/dallas_pio_constants.h index 5a0db44366..4230d0a30d 100644 --- a/esphome/components/dallas_pio/dallas_pio_constants.h +++ b/esphome/components/dallas_pio/dallas_pio_constants.h @@ -17,6 +17,7 @@ static const uint8_t DALLAS_DS2406_COMMAND_READ_STATUS = 0xAA; static const uint8_t DALLAS_DS2406_COMMAND_WRITE_STATUS = 0x55; static const uint8_t DALLAS_DS2408_COMMAND_READ_PIO_REGISTERS = 0xF0; static const uint8_t DALLAS_DS2408_COMMAND_WRITE_PIO_REGISTERS = 0x5A; +static const uint8_t DALLAS_DS2408_COMMAND_PIO_ACK_SUCCESS = 0xAA; } // namespace dallas_pio } // namespace esphome diff --git a/esphome/components/dallas_pio/switch.py b/esphome/components/dallas_pio/switch.py index 2895f4770f..b8d7aa17b7 100644 --- a/esphome/components/dallas_pio/switch.py +++ b/esphome/components/dallas_pio/switch.py @@ -26,7 +26,9 @@ def validate_mode(value): CUSTOM_PIN_SCHEMA = cv.Schema( { - cv.Required("number"): cv.one_of("PIOA", "PIOB", upper=True), + cv.Required("number"): cv.one_of( + "PIOA", "PIOB", "P0", "P1", "P2", "P3", "P4", "P5", "P6", "P7", upper=True + ), cv.Optional(CONF_INVERTED, default=False): cv.boolean, cv.Optional(CONF_MODE, default={"output": True}): validate_mode, } @@ -62,6 +64,10 @@ async def to_code(config): cg.add(var.set_pin(0x01)) # PIOA assiociated to 0x01 elif pin_number == "PIOB": cg.add(var.set_pin(0x02)) # PIOB assiociated to 0x02 + elif pin_number.startswith("P"): + pin_index = int(pin_number[1:]) + if 0 <= pin_index <= 7: + cg.add(var.set_pin(1 + pin_index)) cg.add(var.set_pin_inverted(pin_inverted)) cg.add(var.set_pin_mode(pin_mode.get("input", False), pin_mode.get("output", True))) if CONF_INVERTED in config: