ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
lp5562_output.cpp
Go to the documentation of this file.
1#include "lp5562_output.h"
2#include "esphome/core/hal.h"
3#include "esphome/core/log.h"
4
5namespace esphome::lp5562 {
6
7ESPHOME_LOG_TAG(TAG, "lp5562");
8
9// see table 26 in the datasheet https://web.archive.org/web/20240327023921/https://www.ti.com/lit/ds/symlink/lp5562.pdf
10static constexpr uint8_t LP5562_REG_ENABLE = 0x00;
11static constexpr uint8_t LP5562_REG_CONFIG = 0x08;
12static constexpr uint8_t LP5562_REG_RESET = 0x0d;
13static constexpr uint8_t LP5562_REG_LED_MAP = 0x70;
14
15static constexpr uint8_t LP5562_RESET_VALUE = 0xff;
16
17static constexpr uint8_t LP5562_ENABLE_CHIP_EN = 0x40;
18static constexpr uint8_t LP5562_ENABLE_LOG_EN = 0x80;
19static constexpr uint8_t LP5562_CONFIG_INT_CLK_EN = 0x01;
20static constexpr uint8_t LP5562_LED_MAP_ALL_PWM_REGISTERS = 0x00; // every channel driven by its PWM register
21
22// PWM duty-cycle registers, indexed the same way as the LP5562_CHANNELS enum in output.py
23static const uint8_t LP5562_REG_PWM[4] PROGMEM = {
24 0x02, // blue
25 0x03, // green
26 0x04, // red
27 0x0e, // white
28};
29
30// Current registers, same order
31static const uint8_t LP5562_REG_CURRENT[4] PROGMEM = {
32 0x05, // blue
33 0x06, // green
34 0x07, // red
35 0x0f, // white
36};
37
39 // clear any state left over from before a warm reboot; the chip may not ACK while resetting, so ignore the result
40 this->write_byte(LP5562_REG_RESET, LP5562_RESET_VALUE);
41 delay(1);
42 // power up the chip and enable the internal 32 kHz oscillator, see
43 // https://github.com/m5stack/M5GFX/blob/b2422cdb4735159209c2097d425c0756505b9a81/src/M5GFX.cpp#L566
44 const uint8_t enable = LP5562_ENABLE_CHIP_EN | (this->logarithmic_dimming_ ? LP5562_ENABLE_LOG_EN : 0);
45 if (!this->write_byte(LP5562_REG_ENABLE, enable)) {
46 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
47 return;
48 }
49 delay(1);
50 // use the internal clock, and drive every channel directly from its PWM register instead of the
51 // internal blink/fade engines
52 if (!this->write_byte(LP5562_REG_CONFIG, LP5562_CONFIG_INT_CLK_EN) ||
53 !this->write_byte(LP5562_REG_LED_MAP, LP5562_LED_MAP_ALL_PWM_REGISTERS)) {
54 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
55 return;
56 }
57 for (size_t channel = 0; channel < this->currents_.size(); channel++) {
58 if (!this->write_byte(progmem_read_byte(&LP5562_REG_CURRENT[channel]), this->currents_[channel])) {
59 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
60 return;
61 }
62 }
63}
64
66 ESP_LOGCONFIG(TAG,
67 "LP5562:\n"
68 " Logarithmic dimming: %s",
69 YESNO(this->logarithmic_dimming_));
70 LOG_I2C_DEVICE(this);
71}
72
73void LP5562Output::set_channel_value_(uint8_t channel, uint8_t value) {
74 if (this->is_failed())
75 return;
76 if (!this->write_byte(progmem_read_byte(&LP5562_REG_PWM[channel]), value)) {
77 this->status_set_warning();
78 return;
79 }
81}
82
84 const uint8_t max_duty = 255;
85 const auto duty = static_cast<uint8_t>(roundf(state * max_duty));
86 this->parent_->set_channel_value_(this->channel_, duty);
87}
88
89} // namespace esphome::lp5562
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:274
void status_clear_warning()
Definition component.h:291
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:265
void write_state(float state) override
void set_channel_value_(uint8_t channel, uint8_t value)
std::array< uint8_t, 4 > currents_
bool state
Definition fan.h:2
ESPHOME_LOG_TAG(TAG, "lp5562")
void HOT delay(uint32_t ms)
Definition hal.cpp:85
uint8_t progmem_read_byte(const uint8_t *addr)
Definition hal.h:51