8static const char *
const TAG =
"apds9960";
10#define APDS9960_ERROR_CHECK(func) \
12 this->mark_failed(); \
15#define APDS9960_WRITE_BYTE(reg, value) APDS9960_ERROR_CHECK(this->write_byte(reg, value));
18 ESP_LOGCONFIG(TAG,
"Setting up APDS9960...");
26 if (
id != 0xAB &&
id != 0x9C &&
id != 0xA8) {
33 APDS9960_WRITE_BYTE(0x81, 0xDB);
35 APDS9960_WRITE_BYTE(0x83, 0xF6);
37 APDS9960_WRITE_BYTE(0x8E, 0x87);
39 APDS9960_WRITE_BYTE(0x9D, 0x00);
41 APDS9960_WRITE_BYTE(0x9E, 0x00);
43 APDS9960_WRITE_BYTE(0x8D, 0x60);
47 APDS9960_ERROR_CHECK(this->
read_byte(0x8F, &val));
59 APDS9960_WRITE_BYTE(0x8F,
val);
62 APDS9960_WRITE_BYTE(0x8C, 0x11);
64 APDS9960_WRITE_BYTE(0x90, 0x01);
66 APDS9960_WRITE_BYTE(0x9F, 0x00);
68 APDS9960_WRITE_BYTE(0xA0, 0x28);
70 APDS9960_WRITE_BYTE(0xA1, 0x1E);
73 APDS9960_WRITE_BYTE(0xA2, 0x40);
76 APDS9960_ERROR_CHECK(this->
read_byte(0xA3, &val));
90 APDS9960_WRITE_BYTE(0xA3,
val);
93 APDS9960_WRITE_BYTE(0xA4, 0x00);
95 APDS9960_WRITE_BYTE(0xA5, 0x00);
97 APDS9960_WRITE_BYTE(0xA7, 0x00);
99 APDS9960_WRITE_BYTE(0xA9, 0x00);
101 APDS9960_WRITE_BYTE(0xA6, 0xC9);
105 APDS9960_WRITE_BYTE(0xAA, 0x00);
116 APDS9960_WRITE_BYTE(0x80,
val);
120 return this->red_sensor_ !=
nullptr || this->green_sensor_ !=
nullptr || this->blue_sensor_ !=
nullptr ||
121 this->clear_sensor_ !=
nullptr;
127void APDS9960::dump_config() {
128 ESP_LOGCONFIG(TAG,
"APDS9960:");
129 LOG_I2C_DEVICE(
this);
131 LOG_UPDATE_INTERVAL(
this);
134 LOG_SENSOR(
" ",
"Red channel", this->red_sensor_);
135 LOG_SENSOR(
" ",
"Green channel", this->green_sensor_);
136 LOG_SENSOR(
" ",
"Blue channel", this->blue_sensor_);
137 LOG_SENSOR(
" ",
"Clear channel", this->clear_sensor_);
138 LOG_SENSOR(
" ",
"Proximity", this->proximity_sensor_);
142 switch (this->error_code_) {
144 ESP_LOGE(TAG,
"Communication with APDS9960 failed!");
147 ESP_LOGE(TAG,
"APDS9960 has invalid id!");
150 ESP_LOGE(TAG,
"Setting up APDS9960 registers failed!");
156#define APDS9960_WARNING_CHECK(func, warning) \
158 ESP_LOGW(TAG, warning); \
159 this->status_set_warning(); \
163void APDS9960::update() {
165 APDS9960_WARNING_CHECK(this->
read_byte(0x93, &status),
"Reading status bit failed.");
178 if ((status & 0x01) == 0x00) {
184 APDS9960_WARNING_CHECK(this->
read_bytes(0x94, raw, 8),
"Reading color values failed.");
186 uint16_t uint_clear = (uint16_t(
raw[1]) << 8) |
raw[0];
187 uint16_t uint_red = (uint16_t(
raw[3]) << 8) |
raw[2];
188 uint16_t uint_green = (uint16_t(
raw[5]) << 8) |
raw[4];
189 uint16_t uint_blue = (uint16_t(
raw[7]) << 8) |
raw[6];
191 float clear_perc = (uint_clear / float(UINT16_MAX)) * 100.0f;
192 float red_perc = (uint_red / float(UINT16_MAX)) * 100.0f;
193 float green_perc = (uint_green / float(UINT16_MAX)) * 100.0f;
194 float blue_perc = (uint_blue / float(UINT16_MAX)) * 100.0f;
196 ESP_LOGD(TAG,
"Got clear=%.1f%% red=%.1f%% green=%.1f%% blue=%.1f%%", clear_perc, red_perc, green_perc, blue_perc);
198 if (this->clear_sensor_ !=
nullptr)
199 this->clear_sensor_->publish_state(clear_perc);
200 if (this->red_sensor_ !=
nullptr)
201 this->red_sensor_->publish_state(red_perc);
202 if (this->green_sensor_ !=
nullptr)
203 this->green_sensor_->publish_state(green_perc);
204 if (this->blue_sensor_ !=
nullptr)
205 this->blue_sensor_->publish_state(blue_perc);
212 if (this->proximity_sensor_ ==
nullptr)
215 if ((
status & 0b10) == 0x00) {
221 APDS9960_WARNING_CHECK(this->
read_byte(0x9C, &prox),
"Reading proximity values failed.");
223 float prox_perc = (prox / float(UINT8_MAX)) * 100.0f;
224 ESP_LOGD(TAG,
"Got proximity=%.1f%%", prox_perc);
225 this->proximity_sensor_->publish_state(prox_perc);
233 APDS9960_WARNING_CHECK(this->
read_byte(0xAF, &status),
"Reading gesture status failed.");
235 if ((
status & 0b01) == 0) {
240 if ((
status & 0b10) == 0b10) {
241 ESP_LOGV(TAG,
"FIFO buffer has filled to capacity!");
245 APDS9960_WARNING_CHECK(this->
read_byte(0xAE, &fifo_level),
"Reading FIFO level failed.");
246 if (fifo_level == 0) {
251 APDS9960_WARNING_CHECK(fifo_level <= 32,
"FIFO level has invalid value.")
254 for (uint8_t pos = 0; pos < fifo_level * 4; pos += 32) {
258 uint8_t
read = std::min(32, fifo_level * 4 - pos);
259 APDS9960_WARNING_CHECK(this->
read_bytes(0xFC + pos, buf + pos,
read),
"Reading FIFO buffer failed.");
269 for (uint32_t i = 0; i < fifo_level * 4; i += 4) {
270 const int up = buf[i + 0];
271 const int down = buf[i + 1];
272 const int left = buf[i + 2];
273 const int right = buf[i + 3];
278#ifdef USE_BINARY_SENSOR
282 bin = this->up_direction_binary_sensor_;
285 ESP_LOGD(TAG,
"Got gesture UP");
288 bin = this->down_direction_binary_sensor_;
291 ESP_LOGD(TAG,
"Got gesture DOWN");
294 bin = this->left_direction_binary_sensor_;
297 ESP_LOGD(TAG,
"Got gesture LEFT");
300 bin = this->right_direction_binary_sensor_;
303 ESP_LOGD(TAG,
"Got gesture RIGHT");
309 if (bin !=
nullptr) {
339 const int up_down_delta = up - down;
340 const int left_right_delta = left - right;
341 const bool up_down_significant = abs(up_down_delta) > 13;
342 const bool left_right_significant = abs(left_right_delta) > 13;
344 if (up_down_significant) {
345 if (up_down_delta < 0) {
366 if (left_right_significant) {
367 if (left_right_delta < 0) {
392 this->proximity_sensor_ !=
nullptr
399#ifdef USE_BINARY_SENSOR
400 return this->up_direction_binary_sensor_ !=
nullptr || this->left_direction_binary_sensor_ !=
nullptr ||
401 this->down_direction_binary_sensor_ !=
nullptr || this->right_direction_binary_sensor_ !=
nullptr;