ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
bp5758d.cpp
Go to the documentation of this file.
1#include "bp5758d.h"
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace bp5758d {
6
7static const char *const TAG = "bp5758d";
8
9static const uint8_t BP5758D_MODEL_ID = 0b10000000;
10static const uint8_t BP5758D_ADDR_STANDBY = 0b00000000;
11// Note, channel start address seems ambiguous and mis-translated.
12// Documentation states all are "invalid sleep"
13// All 3 values appear to activate all 5 channels. Using the mapping
14// from BP1658CJ ordering since it won't break anything.
15static const uint8_t BP5758D_ADDR_START_3CH = 0b00010000;
16static const uint8_t BP5758D_ADDR_START_2CH = 0b00100000;
17static const uint8_t BP5758D_ADDR_START_5CH = 0b00110000;
18static const uint8_t BP5758D_ALL_DATA_CHANNEL_ENABLEMENT = 0b00011111;
19
20static const uint8_t BP5758D_DELAY = 2;
21
23 this->data_pin_->setup();
24 this->data_pin_->digital_write(false);
25 delayMicroseconds(BP5758D_DELAY);
26 this->clock_pin_->setup();
27 this->clock_pin_->digital_write(false);
28 delayMicroseconds(BP5758D_DELAY);
29 this->channel_current_.resize(5, 0);
30 this->pwm_amounts_.resize(5, 0);
31}
33 ESP_LOGCONFIG(TAG, "BP5758D:");
34 LOG_PIN(" Data Pin: ", this->data_pin_);
35 LOG_PIN(" Clock Pin: ", this->clock_pin_);
36}
37
39 if (!this->update_)
40 return;
41
42 uint8_t data[17];
43 if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
44 this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
45 for (int i = 1; i < 17; i++)
46 data[i] = 0;
47
48 // First turn all channels off
49 data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_5CH;
50 this->write_buffer_(data, 17);
51 // Then sleep
52 data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY;
53 this->write_buffer_(data, 17);
54 } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
55 (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) {
56 // Only data on white channels
57 data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_2CH;
58 data[1] = BP5758D_ALL_DATA_CHANNEL_ENABLEMENT;
59 data[2] = 0;
60 data[3] = 0;
61 data[4] = 0;
62 data[5] = this->pwm_amounts_[3] > 0 ? correct_current_level_bits_(this->channel_current_[3]) : 0;
63 data[6] = this->pwm_amounts_[4] > 0 ? correct_current_level_bits_(this->channel_current_[4]) : 0;
64 for (int i = 7, j = 0; i <= 15; i += 2, j++) {
65 data[i] = this->pwm_amounts_[j] & 0x1F;
66 data[i + 1] = (this->pwm_amounts_[j] >> 5) & 0x1F;
67 }
68 this->write_buffer_(data, 17);
69 } else if ((this->pwm_amounts_[0] > 0 || this->pwm_amounts_[1] > 0 || this->pwm_amounts_[2] > 0) &&
70 this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
71 // Only data on RGB channels
72 data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH;
73 data[1] = BP5758D_ALL_DATA_CHANNEL_ENABLEMENT;
74 data[2] = this->pwm_amounts_[0] > 0 ? correct_current_level_bits_(this->channel_current_[0]) : 0;
75 data[3] = this->pwm_amounts_[1] > 0 ? correct_current_level_bits_(this->channel_current_[1]) : 0;
76 data[4] = this->pwm_amounts_[2] > 0 ? correct_current_level_bits_(this->channel_current_[2]) : 0;
77 data[5] = 0;
78 data[6] = 0;
79 for (int i = 7, j = 0; i <= 15; i += 2, j++) {
80 data[i] = this->pwm_amounts_[j] & 0x1F;
81 data[i + 1] = (this->pwm_amounts_[j] >> 5) & 0x1F;
82 }
83 this->write_buffer_(data, 17);
84 } else {
85 // All channels
86 data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_5CH;
87 data[1] = BP5758D_ALL_DATA_CHANNEL_ENABLEMENT;
88 data[2] = this->pwm_amounts_[0] > 0 ? correct_current_level_bits_(this->channel_current_[0]) : 0;
89 data[3] = this->pwm_amounts_[1] > 0 ? correct_current_level_bits_(this->channel_current_[1]) : 0;
90 data[4] = this->pwm_amounts_[2] > 0 ? correct_current_level_bits_(this->channel_current_[2]) : 0;
91 data[5] = this->pwm_amounts_[3] > 0 ? correct_current_level_bits_(this->channel_current_[3]) : 0;
92 data[6] = this->pwm_amounts_[4] > 0 ? correct_current_level_bits_(this->channel_current_[4]) : 0;
93 for (int i = 7, j = 0; i <= 15; i += 2, j++) {
94 data[i] = this->pwm_amounts_[j] & 0x1F;
95 data[i + 1] = (this->pwm_amounts_[j] >> 5) & 0x1F;
96 }
97 this->write_buffer_(data, 17);
98 }
99
100 this->update_ = false;
101}
102
103uint8_t BP5758D::correct_current_level_bits_(uint8_t current) {
104 // Anything below 64 uses normal bitmapping.
105 if (current < 64) {
106 return current;
107 }
108
109 // Anything above 63 needs to be offset by +34 because the driver remaps bit 7 (normally 64) to 30.
110 // (no idea why(!) but it is documented)
111 // Example:
112 // integer 64 would normally put out 0b01000000 but here 0b01000000 = 30 whereas everything lower
113 // is normal, so we add 34 to the integer where
114 // integer 98 = 0b01100010 which is 30 (7th bit adjusted) + 34 (1st-6th bits).
115 return current + 34;
116}
117
118void BP5758D::set_channel_value_(uint8_t channel, uint16_t value) {
119 if (this->pwm_amounts_[channel] != value) {
120 this->update_ = true;
121 this->update_channel_ = channel;
122 }
123 this->pwm_amounts_[channel] = value;
124}
125
126void BP5758D::set_channel_current_(uint8_t channel, uint8_t current) { this->channel_current_[channel] = current; }
127
128void BP5758D::write_bit_(bool value) {
129 this->data_pin_->digital_write(value);
130 delayMicroseconds(BP5758D_DELAY);
131 this->clock_pin_->digital_write(true);
132 delayMicroseconds(BP5758D_DELAY);
133 this->clock_pin_->digital_write(false);
134 delayMicroseconds(BP5758D_DELAY);
135}
136
137void BP5758D::write_byte_(uint8_t data) {
138 for (uint8_t mask = 0x80; mask; mask >>= 1) {
139 this->write_bit_(data & mask);
140 }
141
142 // ack bit
144 this->clock_pin_->digital_write(true);
145 delayMicroseconds(BP5758D_DELAY);
146 this->clock_pin_->digital_write(false);
147 delayMicroseconds(BP5758D_DELAY);
149}
150
151void BP5758D::write_buffer_(uint8_t *buffer, uint8_t size) {
152 this->data_pin_->digital_write(false);
153 delayMicroseconds(BP5758D_DELAY);
154 this->clock_pin_->digital_write(false);
155 delayMicroseconds(BP5758D_DELAY);
156
157 for (uint32_t i = 0; i < size; i++) {
158 this->write_byte_(buffer[i]);
159 }
160
161 this->clock_pin_->digital_write(true);
162 delayMicroseconds(BP5758D_DELAY);
163 this->data_pin_->digital_write(true);
164 delayMicroseconds(BP5758D_DELAY);
165}
166
167} // namespace bp5758d
168} // namespace esphome
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
virtual void digital_write(bool value)=0
void setup() override
Definition bp5758d.cpp:22
std::vector< uint8_t > channel_current_
Definition bp5758d.h:58
void dump_config() override
Definition bp5758d.cpp:32
void write_byte_(uint8_t data)
Definition bp5758d.cpp:137
void set_channel_current_(uint8_t channel, uint8_t current)
Definition bp5758d.cpp:126
void set_channel_value_(uint8_t channel, uint16_t value)
Definition bp5758d.cpp:118
void write_buffer_(uint8_t *buffer, uint8_t size)
Definition bp5758d.cpp:151
void write_bit_(bool value)
Definition bp5758d.cpp:128
void loop() override
Send new values if they were updated.
Definition bp5758d.cpp:38
uint8_t correct_current_level_bits_(uint8_t current)
Definition bp5758d.cpp:103
std::vector< uint16_t > pwm_amounts_
Definition bp5758d.h:59
@ FLAG_OUTPUT
Definition gpio.h:19
@ FLAG_INPUT
Definition gpio.h:18
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition core.cpp:31