ESPHome  2024.4.2
bp1658cj.cpp
Go to the documentation of this file.
1 #include "bp1658cj.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace bp1658cj {
6 
7 static const char *const TAG = "bp1658cj";
8 
9 static const uint8_t BP1658CJ_MODEL_ID = 0x80;
10 static const uint8_t BP1658CJ_ADDR_STANDBY = 0x0;
11 static const uint8_t BP1658CJ_ADDR_START_3CH = 0x10;
12 static const uint8_t BP1658CJ_ADDR_START_2CH = 0x20;
13 static const uint8_t BP1658CJ_ADDR_START_5CH = 0x30;
14 
15 static const uint8_t BP1658CJ_DELAY = 2;
16 
18  ESP_LOGCONFIG(TAG, "Setting up BP1658CJ Output Component...");
19  this->data_pin_->setup();
20  this->data_pin_->digital_write(false);
21  this->clock_pin_->setup();
22  this->clock_pin_->digital_write(false);
23  this->pwm_amounts_.resize(5, 0);
24 }
26  ESP_LOGCONFIG(TAG, "BP1658CJ:");
27  LOG_PIN(" Data Pin: ", this->data_pin_);
28  LOG_PIN(" Clock Pin: ", this->clock_pin_);
29  ESP_LOGCONFIG(TAG, " Color Channels Max Power: %u", this->max_power_color_channels_);
30  ESP_LOGCONFIG(TAG, " White Channels Max Power: %u", this->max_power_white_channels_);
31 }
32 
34  if (!this->update_)
35  return;
36 
37  uint8_t data[12];
38  if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
39  this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
40  for (int i = 1; i < 12; i++)
41  data[i] = 0;
42 
43  // First turn all channels off
44  data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_5CH;
45  this->write_buffer_(data, 12);
46  // Then sleep
47  data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_STANDBY;
48  this->write_buffer_(data, 12);
49  } else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
50  (this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) {
51  // Only data on white channels
52  data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_2CH;
53  data[1] = 0 << 4 | this->max_power_white_channels_;
54  for (int i = 2, j = 0; i < 12; i += 2, j++) {
55  data[i] = this->pwm_amounts_[j] & 0x1F;
56  data[i + 1] = (this->pwm_amounts_[j] >> 5) & 0x1F;
57  }
58  this->write_buffer_(data, 12);
59  } else if ((this->pwm_amounts_[0] > 0 || this->pwm_amounts_[1] > 0 || this->pwm_amounts_[2] > 0) &&
60  this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
61  // Only data on RGB channels
62  data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_3CH;
63  data[1] = this->max_power_color_channels_ << 4 | 0;
64  for (int i = 2, j = 0; i < 12; 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, 12);
69  } else {
70  // All channels
71  data[0] = BP1658CJ_MODEL_ID + BP1658CJ_ADDR_START_5CH;
72  data[1] = this->max_power_color_channels_ << 4 | this->max_power_white_channels_;
73  for (int i = 2, j = 0; i < 12; i += 2, j++) {
74  data[i] = this->pwm_amounts_[j] & 0x1F;
75  data[i + 1] = (this->pwm_amounts_[j] >> 5) & 0x1F;
76  }
77  this->write_buffer_(data, 12);
78  }
79 
80  this->update_ = false;
81 }
82 
83 void BP1658CJ::set_channel_value_(uint8_t channel, uint16_t value) {
84  if (this->pwm_amounts_[channel] != value) {
85  this->update_ = true;
86  this->update_channel_ = channel;
87  }
88  this->pwm_amounts_[channel] = value;
89 }
90 
91 void BP1658CJ::write_bit_(bool value) {
92  this->data_pin_->digital_write(value);
93  delayMicroseconds(BP1658CJ_DELAY);
94  this->clock_pin_->digital_write(true);
95  delayMicroseconds(BP1658CJ_DELAY);
96  this->clock_pin_->digital_write(false);
97  delayMicroseconds(BP1658CJ_DELAY);
98 }
99 
100 void BP1658CJ::write_byte_(uint8_t data) {
101  for (uint8_t mask = 0x80; mask; mask >>= 1) {
102  this->write_bit_(data & mask);
103  }
104 
105  // ack bit
107  this->clock_pin_->digital_write(true);
108  delayMicroseconds(BP1658CJ_DELAY);
109  this->clock_pin_->digital_write(false);
110  delayMicroseconds(BP1658CJ_DELAY);
112 }
113 
114 void BP1658CJ::write_buffer_(uint8_t *buffer, uint8_t size) {
115  this->data_pin_->digital_write(false);
116  delayMicroseconds(BP1658CJ_DELAY);
117  this->clock_pin_->digital_write(false);
118  delayMicroseconds(BP1658CJ_DELAY);
119 
120  for (uint32_t i = 0; i < size; i++) {
121  this->write_byte_(buffer[i]);
122  }
123 
124  this->clock_pin_->digital_write(true);
125  delayMicroseconds(BP1658CJ_DELAY);
126  this->data_pin_->digital_write(true);
127  delayMicroseconds(BP1658CJ_DELAY);
128 }
129 
130 } // namespace bp1658cj
131 } // namespace esphome
virtual void digital_write(bool value)=0
void dump_config() override
Definition: bp1658cj.cpp:25
void setup() override
Definition: bp1658cj.cpp:17
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
void write_buffer_(uint8_t *buffer, uint8_t size)
Definition: bp1658cj.cpp:114
uint8_t max_power_color_channels_
Definition: bp1658cj.h:56
void set_channel_value_(uint8_t channel, uint16_t value)
Definition: bp1658cj.cpp:83
void loop() override
Send new values if they were updated.
Definition: bp1658cj.cpp:33
void write_bit_(bool value)
Definition: bp1658cj.cpp:91
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
std::vector< uint16_t > pwm_amounts_
Definition: bp1658cj.h:59
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition: core.cpp:28
void write_byte_(uint8_t data)
Definition: bp1658cj.cpp:100
uint8_t max_power_white_channels_
Definition: bp1658cj.h:57