diff --git a/esphome/components/kp18058/kp18058.cpp b/esphome/components/kp18058/kp18058.cpp index 825829b77f..e84e55d246 100644 --- a/esphome/components/kp18058/kp18058.cpp +++ b/esphome/components/kp18058/kp18058.cpp @@ -6,9 +6,9 @@ namespace kp18058 { static const char *const TAG = "kp18058"; static const uint8_t I2C_MAX_RETRY = 3; -#define BIT_CHECK(PIN, N) !!((PIN & (1 << N))) +#define BIT_CHECK(PIN, N) !!(((PIN) & (1 << (N)))) -uint8_t GetParityBit(uint8_t b) { +uint8_t get_parity_bit(uint8_t b) { uint8_t sum = 0; for (int i = 1; i < 8; i++) { if (BIT_CHECK(b, i)) { @@ -18,9 +18,9 @@ uint8_t GetParityBit(uint8_t b) { return sum % 2; // 0 for even, 1 for odd } -kp18058::kp18058() : i2c_ready_(false), max_cw_current_(0), max_rgb_current_(0) { - for (int i = 0; i < 5; ++i) { - channels_[i] = nullptr; +kp18058::kp18058() : max_cw_current_(0), max_rgb_current_(0), i2c_ready_(false) { + for (auto &channel : channels_) { + channel = nullptr; } } @@ -33,13 +33,12 @@ void kp18058::dump_config() { ESP_LOGCONFIG(TAG, "KP18058 LED Driver:"); LOG_PIN(" Data Pin: ", i2c_.get_data_pin()); LOG_PIN(" Clock Pin: ", i2c_.get_clock_pin()); - ESP_LOGCONFIG(TAG, " I2C Communication %s", i2c_ready_ ? "Initialized": "FAILED"); + ESP_LOGCONFIG(TAG, " I2C Communication %s", i2c_ready_ ? "Initialized" : "FAILED"); ESP_LOGCONFIG(TAG, " CW max current: %.1f", this->max_cw_current_); ESP_LOGCONFIG(TAG, " RGB max current: %.1f", this->max_rgb_current_); } void kp18058::program_led_driver() { - if (!i2c_ready_) { ESP_LOGI(TAG, "Reestablishing communication with KP18058."); i2c_ready_ = i2c_.reset(); @@ -49,25 +48,25 @@ void kp18058::program_led_driver() { } } - // returns true if All channels are zero or nullptr - auto areAllChannelsZero = [this]() { - for (int i = 0; i < 5; ++i) { - if (channels_[i] != nullptr && channels_[i]->get_value() > 0) { + // Returns true if all channels are zero or nullptr + auto all_channels_zero = [this]() { + for (auto *channel : channels_) { + if (channel != nullptr && channel->get_value() > 0) { // If any channel is non-zero, return false - return false; + return false; } } - return true; + return true; }; // Create the settings union KP18058_Settings settings{}; - - settings.address_identification = 1; - settings.working_mode = areAllChannelsZero() ? STANDBY_MODE : RGBCW_MODE; + + settings.address_identification = 1; + settings.working_mode = all_channels_zero() ? STANDBY_MODE : RGBCW_MODE; // Set byte address start. valid values are 0 - 13 // In this message always all bytes are transmited (starting from 0) - settings.start_byte_address = 0x00; + settings.start_byte_address = 0x00; // Set Line Compensation Mechanism settings.line_compensation_enable = LC_DISABLE; @@ -75,9 +74,9 @@ void kp18058::program_led_driver() { settings.line_comp_slope = LC_SLOPE_10_PERCENT; settings.rc_filter_enable = RC_FILTER_DISABLE; - // Set max current values - settings.max_current_out4_5 = static_cast(max_cw_current_/2.5) & 0x1F; - settings.max_current_out1_3 = static_cast(max_rgb_current_/2.5) & 0x1F; + // Set max current values + settings.max_current_out4_5 = static_cast(max_cw_current_ / 2.5) & 0x1F; + settings.max_current_out1_3 = static_cast(max_rgb_current_ / 2.5) & 0x1F; // set dimming method for RGB channels and chop dimming frequency settings.chop_dimming_out1_3 = ANALOG_DIMMING; @@ -85,14 +84,14 @@ void kp18058::program_led_driver() { // Set grayscale values for each output channel for (int i = 0; i < 5; i++) { - uint16_t useVal = (channels_[i] != nullptr) ? channels_[i]->get_value() : 0; - settings.channels[i].upper_grayscale = (useVal >> 5) & 0x1F; - settings.channels[i].lower_grayscale = useVal & 0x1F; + uint16_t use_val = (channels_[i] != nullptr) ? channels_[i]->get_value() : 0; + settings.channels[i].upper_grayscale = (use_val >> 5) & 0x1F; + settings.channels[i].lower_grayscale = use_val & 0x1F; } // Calculate parity bits for each byte for (int i = 0; i < sizeof(KP18058_Settings); ++i) { - settings.bytes[i] |= GetParityBit(settings.bytes[i]); + settings.bytes[i] |= get_parity_bit(settings.bytes[i]); } // Send the I2C message @@ -102,7 +101,8 @@ void kp18058::program_led_driver() { bool write_succeeded; for (int attempt = 0; attempt < I2C_MAX_RETRY; attempt++) { write_succeeded = i2c_.write_byte(settings.bytes[i]); - if (write_succeeded) break; + if (write_succeeded) + break; } // if all tries failed break and stop sending the rest of the frame bytes if (!write_succeeded) { @@ -112,7 +112,6 @@ void kp18058::program_led_driver() { } } i2c_.stop(); - return; } } // namespace kp18058 diff --git a/esphome/components/kp18058/kp18058.h b/esphome/components/kp18058/kp18058.h index 4624035a3a..ad70877656 100644 --- a/esphome/components/kp18058/kp18058.h +++ b/esphome/components/kp18058/kp18058.h @@ -111,10 +111,9 @@ class kp18058_output : public output::FloatOutput { // Request parent to reprogram the LED driver with updated brightness values. this->parent_->program_led_driver(); } - + // 10-bit grayscale value representing intensity (0-1023) of the output. uint16_t value_; - // Pointer to the parent kp18058 driver class for this output channel. kp18058 *parent_; }; diff --git a/esphome/components/kp18058/message.h b/esphome/components/kp18058/message.h index 83a62f2e1a..2535f8007d 100644 --- a/esphome/components/kp18058/message.h +++ b/esphome/components/kp18058/message.h @@ -6,146 +6,134 @@ namespace kp18058 { /** * @brief Enumeration for device working modes. */ -typedef enum { - STANDBY_MODE = 0b00, - RGB_MODE = 0b01, - CW_MODE = 0b10, - RGBCW_MODE = 0b11 -} WorkingMode; +enum WorkingMode { STANDBY_MODE = 0b00, RGB_MODE = 0b01, CW_MODE = 0b10, RGBCW_MODE = 0b11 }; /** * @brief Enumeration for Line Compensation Mode. * * Controls whether line compensation is enabled or disabled. * When the input voltage exceeds the voltage threshold - * the Line compensation decreases the current linearly with the defined slope + * the Line compensation decreases the current linearly with the defined slope. */ -typedef enum { - LC_DISABLE = 0b0, - LC_ENABLE = 0b1 -} LCMode; +enum LCMode { LC_DISABLE = 0b0, LC_ENABLE = 0b1 }; /** * @brief Enumeration for Line Compensation Start Threshold. * - * Defines the input voltage at which line compensation activates. The slope of compensation + * Defines the input voltage at which line compensation activates. The slope of compensation * changes depending on voltage range and on the Compensation Slope parameter: * - For low thresholds (140V to 175V): Compensation slope parameter is defined for 15V increment. * - For high thresholds (260V to 330V): Compensation slope parameter is defined for 30V increment. */ -typedef enum { - // Low voltage thresholds (15V increments) - LC_THRESHOLD_140V = 0b0000, - LC_THRESHOLD_145V = 0b0001, - LC_THRESHOLD_150V = 0b0010, - LC_THRESHOLD_155V = 0b0011, - LC_THRESHOLD_160V = 0b0100, - LC_THRESHOLD_165V = 0b0101, - LC_THRESHOLD_170V = 0b0110, - LC_THRESHOLD_175V = 0b0111, +enum LCThreshold : uint8_t { + // Low voltage thresholds (15V increments) + LC_THRESHOLD_140V = 0b0000, + LC_THRESHOLD_145V = 0b0001, + LC_THRESHOLD_150V = 0b0010, + LC_THRESHOLD_155V = 0b0011, + LC_THRESHOLD_160V = 0b0100, + LC_THRESHOLD_165V = 0b0101, + LC_THRESHOLD_170V = 0b0110, + LC_THRESHOLD_175V = 0b0111, - // High voltage thresholds (30V increments) - LC_THRESHOLD_260V = 0b1000, - LC_THRESHOLD_270V = 0b1001, - LC_THRESHOLD_280V = 0b1010, - LC_THRESHOLD_290V = 0b1011, - LC_THRESHOLD_300V = 0b1100, - LC_THRESHOLD_310V = 0b1101, - LC_THRESHOLD_320V = 0b1110, - LC_THRESHOLD_330V = 0b1111 -} LCThreshold; + // High voltage thresholds (30V increments) + LC_THRESHOLD_260V = 0b1000, + LC_THRESHOLD_270V = 0b1001, + LC_THRESHOLD_280V = 0b1010, + LC_THRESHOLD_290V = 0b1011, + LC_THRESHOLD_300V = 0b1100, + LC_THRESHOLD_310V = 0b1101, + LC_THRESHOLD_320V = 0b1110, + LC_THRESHOLD_330V = 0b1111 +}; /** - * @brief Enumeration for Line Compensation Slope Settings + * @brief Enumeration for Line Compensation Slope Settings. * * Defines the slope used to decrease the current when line compensation is enabled. */ -typedef enum { - LC_SLOPE_7_5_PERCENT = 0b00, /**< current decreases 7.5% */ - LC_SLOPE_10_PERCENT = 0b01, /**< current decreases 10% */ - LC_SLOPE_12_5_PERCENT = 0b10, /**< current decreases 12.5% */ - LC_SLOPE_15_PERCENT = 0b11 /**< current decreases 15% */ -} LCSlope; +enum LCSlope { + LC_SLOPE_7_5_PERCENT = 0b00, /**< current decreases 7.5% */ + LC_SLOPE_10_PERCENT = 0b01, /**< current decreases 10% */ + LC_SLOPE_12_5_PERCENT = 0b10, /**< current decreases 12.5% */ + LC_SLOPE_15_PERCENT = 0b11 /**< current decreases 15% */ +}; /** - * #brief Enumeration for RC Filter Settings + * @brief Enumeration for RC Filter Settings. * - * Controls whether RC filtering is enabled for line compensation calculations. + * Controls whether RC filtering is enabled for line compensation calculations. * When enabled, it takes an average input voltage; otherwise, it uses the instantaneous input value. */ -typedef enum { - RC_FILTER_ENABLE = 0b0, - RC_FILTER_DISABLE = 0b1 -} RCFilter; +enum RCFilter { RC_FILTER_ENABLE = 0b0, RC_FILTER_DISABLE = 0b1 }; /** - * @brief Enumeration for Dimming Modes for RGB Channels (1-3) + * @brief Enumeration for Dimming Modes for RGB Channels (1-3). * * Specifies whether analog dimming or chop dimming is used for RGB channels. */ -typedef enum { - ANALOG_DIMMING = 0b0, /**< Analog dimming mode, adjusts LED current amplitude. */ - CHOP_DIMMING = 0b1 /**< Chop dimming mode, adjusts LED current duty cycle. */ -} DimmingMode; +enum DimmingMode { + ANALOG_DIMMING = 0b0, /**< Analog dimming mode, adjusts LED current amplitude. */ + CHOP_DIMMING = 0b1 /**< Chop dimming mode, adjusts LED current duty cycle. */ +}; /** - * Enumeration for Chop Dimming Frequency Settings - * Defines the frequency used for chop dimming mode. */ -typedef enum { - CD_FREQUENCY_4KHZ = 0b00, - CD_FREQUENCY_2KHZ = 0b01, - CD_FREQUENCY_1KHZ = 0b10, - CD_FREQUENCY_500HZ = 0b11 -} CDFrequency; + * @brief Enumeration for Chop Dimming Frequency Settings. + * + * Defines the frequency used for chop dimming mode. + */ +enum CDFrequency : uint8_t { + CD_FREQUENCY_4KHZ = 0b00, + CD_FREQUENCY_2KHZ = 0b01, + CD_FREQUENCY_1KHZ = 0b10, + CD_FREQUENCY_500HZ = 0b11 +}; #pragma pack(push, 1) /** - * Union representing the structure of the I2C message - * for configuring the KP18058 LED driver settings. + * @brief Union representing the structure of the I2C message for configuring the KP18058 LED driver settings. */ typedef union { + // Access the settings as a structure + struct { + // Byte 0 + uint8_t byte0_parity_bit : 1; + uint8_t start_byte_address : 4; + WorkingMode working_mode : 2; + uint8_t address_identification : 1; - // Access the settings as a structure + // Byte 1 + uint8_t byte1_parity_bit : 1; + LCSlope line_comp_slope : 2; + LCThreshold line_comp_threshold : 4; + LCMode line_compensation_enable : 1; + + // Byte 2 + uint8_t byte2_parity_bit : 1; + uint8_t max_current_out1_3 : 5; + CDFrequency chop_dimming_frequency : 2; + + // Byte 3 + uint8_t byte3_parity_bit : 1; + uint8_t max_current_out4_5 : 5; + RCFilter rc_filter_enable : 1; + DimmingMode chop_dimming_out1_3 : 1; + + // Channel array for OUT1 to OUT5 grayscale data struct { - // Byte 0 - uint8_t byte0_parity_bit : 1; - uint8_t start_byte_address : 4; - WorkingMode working_mode : 2; - uint8_t address_identification : 1; + uint8_t upper_parity : 1; + uint8_t upper_grayscale : 5; /**< upper 5 bits of the channel value */ + uint8_t upper_reserved : 2; - // Byte 1 - uint8_t byte1_parity_bit : 1; - LCSlope line_comp_slope : 2; - LCThreshold line_comp_threshold : 4; - LCMode line_compensation_enable : 1; - - // Byte 2 - uint8_t byte2_parity_bit : 1; - uint8_t max_current_out1_3 : 5; - CDFrequency chop_dimming_frequency : 2; - - // Byte 3 - uint8_t byte3_parity_bit : 1; - uint8_t max_current_out4_5 : 5; - RCFilter rc_filter_enable : 1; - DimmingMode chop_dimming_out1_3 : 1; - - // Channel array for OUT1 to OUT5 grayscale data - struct { - uint8_t upper_parity : 1; - uint8_t upper_grayscale : 5; /**< upper 5 bits of the channel value */ - uint8_t upper_reserved : 2; - - uint8_t lower_parity : 1; - uint8_t lower_grayscale : 5; /**< lower 5 bits of the channel value */ - uint8_t lower_reserved : 2; - } channels[5]; - }; - - // Access the settings as a byte array - uint8_t bytes[14]; + uint8_t lower_parity : 1; + uint8_t lower_grayscale : 5; /**< lower 5 bits of the channel value */ + uint8_t lower_reserved : 2; + } channels[5]; + }; + // Access the settings as a byte array + uint8_t bytes[14]; } KP18058_Settings; #pragma pack(pop) diff --git a/esphome/components/kp18058/softi2c.cpp b/esphome/components/kp18058/softi2c.cpp index 6708384623..7df7248c22 100644 --- a/esphome/components/kp18058/softi2c.cpp +++ b/esphome/components/kp18058/softi2c.cpp @@ -43,10 +43,9 @@ bool softI2C::reset() { // Final verification: both SDA and SCL should be high (bus idle) return (data_pin_->digital_read()) && (clock_pin_->digital_read()); } - -bool softI2C::write_byte(uint8_t value) { - ns_sleep(SOFT_I2C_CLOCK_TIME/2); +bool softI2C::write_byte(uint8_t value) { + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); for (uint8_t curr = 0x80; curr != 0; curr >>= 1) { if (curr & value) { @@ -60,7 +59,7 @@ bool softI2C::write_byte(uint8_t value) { // Data is written to the register on the falling edge of SCL // it needs to be valid through at least HOLD TIME // waiting half a cycle assuming it is longer than HOLD_TIME - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); } // Every time the transmission of 8bit data (one byte) @@ -69,9 +68,9 @@ bool softI2C::write_byte(uint8_t value) { bool ack_received; set_high(data_pin_); set_high(clock_pin_); - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); ack_received = !data_pin_->digital_read(); - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); set_low(clock_pin_); return ack_received; @@ -81,19 +80,18 @@ void softI2C::start() { set_low(data_pin_); // It needs to be valid through at least HOLD TIME // Waiting half a cycle. Assuming it is longer than HOLD_TIME - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); set_low(clock_pin_); - return; } void softI2C::stop() { - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); set_low(data_pin_); // It needs to be valid through at least HOLD TIME // Waiting half a cycle. Assuming it is longer than HOLD_TIME - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); set_high(clock_pin_); - ns_sleep(SOFT_I2C_CLOCK_TIME/2); + ns_sleep(SOFT_I2C_CLOCK_TIME / 2); set_high(data_pin_); } diff --git a/esphome/components/kp18058/softi2c.h b/esphome/components/kp18058/softi2c.h index c513731a18..16799f7c60 100644 --- a/esphome/components/kp18058/softi2c.h +++ b/esphome/components/kp18058/softi2c.h @@ -7,7 +7,7 @@ namespace kp18058 { /** * @brief Class to implement a software I2C protocol. - * + * * This class allows communication with I2C devices using GPIO pins * to simulate I2C communication through software control. */ @@ -17,7 +17,7 @@ class softI2C { /** * @brief Sets up the I2C pins. - * + * * This method initializes the data and clock pin objects by calling * their respective setup methods. */ @@ -28,7 +28,7 @@ class softI2C { /** * @brief Sets the GPIO pins for data and clock. - * + * * This method associates the provided GPIO pins with the I2C instance. * * @param data_pin Pointer to the GPIOPin object for the data line (SDA). @@ -41,25 +41,25 @@ class softI2C { /** * @brief Gets the data pin associated with this I2C instance. - * + * * @return Pointer to the GPIOPin object for the data line (SDA). */ - GPIOPin* get_data_pin() const { return data_pin_; } + GPIOPin *get_data_pin() const { return data_pin_; } /** * @brief Gets the clock pin associated with this I2C instance. - * + * * @return Pointer to the GPIOPin object for the clock line (SCL). - */ - GPIOPin* get_clock_pin() const { return clock_pin_; } + */ + GPIOPin *get_clock_pin() const { return clock_pin_; } /** * @brief Resets the I2C bus and checks for device readiness. - * + * * This method generates clock pulses to clear any stuck data on the bus, * checks the state of the data line (SDA), and sends start-stop signals * to ensure proper initialization. - * + * * @return true if the reset was successful and the bus is free. * @return false if the reset failed (SDA remains low). */ @@ -67,7 +67,7 @@ class softI2C { /** * @brief Initiates the start condition for I2C communication. - * + * * This method pulls the data line (SDA) low while the clock line (SCL) * is high, signaling the start of communication to the slave device. */ @@ -75,7 +75,7 @@ class softI2C { /** * @brief Initiates the stop condition for I2C communication. - * + * * This method releases the data line (SDA) after setting the clock line (SCL) high, * signaling the end of communication to the slave device. */ @@ -83,7 +83,7 @@ class softI2C { /** * @brief Writes a byte of data to the I2C bus. - * + * * This method sends a byte by shifting each bit to the data line (SDA). * After the byte is sent, it checks for an acknowledgment (ACK) from the slave device. * @@ -94,10 +94,9 @@ class softI2C { bool write_byte(uint8_t value); private: - /** * @brief Sets the specified GPIO pin low. - * + * * This method configures the pin as an output and writes a low value (false) to it. * * @param pin Pointer to the GPIOPin object representing the pin to set low. @@ -109,18 +108,15 @@ class softI2C { /** * @brief Sets the specified GPIO pin high. - * + * * This method configures the pin as an input with a pull-up resistor. * * @param pin Pointer to the GPIOPin object representing the pin to set high. */ + void set_high(GPIOPin *pin) { pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); } - void set_high(GPIOPin *pin) { - pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); - } - - GPIOPin *data_pin_; ///< Pointer to the GPIOPin object for the data line (SDA). - GPIOPin *clock_pin_; ///< Pointer to the GPIOPin object for the clock line (SCL). + GPIOPin *data_pin_; ///< Pointer to the GPIOPin object for the data line (SDA). + GPIOPin *clock_pin_; ///< Pointer to the GPIOPin object for the clock line (SCL). }; } // namespace kp18058