diff --git a/esphome/components/gpio_expander/cached_gpio.h b/esphome/components/gpio_expander/cached_gpio.h index d88b59bb9b..eeff98cb6e 100644 --- a/esphome/components/gpio_expander/cached_gpio.h +++ b/esphome/components/gpio_expander/cached_gpio.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "esphome/core/hal.h" namespace esphome::gpio_expander { @@ -20,14 +21,18 @@ namespace esphome::gpio_expander { /// Examples: MCP23017 (2x8-bit banks), TCA9555 (2x8-bit banks) /// * uint16_t: For chips that read all pins at once (up to 16 pins) /// Examples: PCF8574/8575 (8/16 pins), PCA9554/9555 (8/16 pins) -/// N - Total number of pins (as uint8_t) -template class CachedGpioExpander { +/// N - Total number of pins (maximum 65535) +/// P - Type for pin number parameters (automatically selected based on N: +/// uint8_t for N<=256, uint16_t for N>256). Can be explicitly specified +/// if needed (e.g., for components like SN74HC165 with >256 pins) +template 256), uint16_t, uint8_t>::type> +class CachedGpioExpander { public: /// @brief Read the state of the given pin. This will invalidate the cache for the given pin number. /// @param pin Pin number to read /// @return Pin state - bool digital_read(uint8_t pin) { - const uint8_t bank = pin / BANK_SIZE; + bool digital_read(P pin) { + const P bank = pin / BANK_SIZE; const T pin_mask = (1 << (pin % BANK_SIZE)); // Check if specific pin cache is valid if (this->read_cache_valid_[bank] & pin_mask) { @@ -43,7 +48,7 @@ template class CachedGpioExpander { return this->digital_read_cache(pin); } - void digital_write(uint8_t pin, bool value) { this->digital_write_hw(pin, value); } + void digital_write(P pin, bool value) { this->digital_write_hw(pin, value); } protected: /// @brief Read GPIO bank from hardware into internal state @@ -51,23 +56,23 @@ template class CachedGpioExpander { /// @return true if read succeeded, false on communication error /// @note This does NOT return the pin state. It returns whether the read operation succeeded. /// The actual pin state should be returned by digital_read_cache(). - virtual bool digital_read_hw(uint8_t pin) = 0; + virtual bool digital_read_hw(P pin) = 0; /// @brief Get cached pin value from internal state /// @param pin Pin number to read /// @return Pin state (true = HIGH, false = LOW) - virtual bool digital_read_cache(uint8_t pin) = 0; + virtual bool digital_read_cache(P pin) = 0; /// @brief Write GPIO state to hardware /// @param pin Pin number to write /// @param value Pin state to write (true = HIGH, false = LOW) - virtual void digital_write_hw(uint8_t pin, bool value) = 0; + virtual void digital_write_hw(P pin, bool value) = 0; /// @brief Invalidate cache. This function should be called in component loop(). void reset_pin_cache_() { memset(this->read_cache_valid_, 0x00, CACHE_SIZE_BYTES); } - static constexpr uint8_t BITS_PER_BYTE = 8; - static constexpr uint8_t BANK_SIZE = sizeof(T) * BITS_PER_BYTE; + static constexpr uint16_t BITS_PER_BYTE = 8; + static constexpr uint16_t BANK_SIZE = sizeof(T) * BITS_PER_BYTE; static constexpr size_t BANKS = N / BANK_SIZE; static constexpr size_t CACHE_SIZE_BYTES = BANKS * sizeof(T);