ESPHome  2024.4.0
tlc59208f_output.cpp
Go to the documentation of this file.
1 #include "tlc59208f_output.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/helpers.h"
4 #include "esphome/core/hal.h"
5 
6 namespace esphome {
7 namespace tlc59208f {
8 
9 static const char *const TAG = "tlc59208f";
10 
11 // * marks register defaults
12 // 0*: Register auto increment disabled, 1: Register auto increment enabled
13 const uint8_t TLC59208F_MODE1_AI2 = (1 << 7);
14 // 0*: don't auto increment bit 1, 1: auto increment bit 1
15 const uint8_t TLC59208F_MODE1_AI1 = (1 << 6);
16 // 0*: don't auto increment bit 0, 1: auto increment bit 0
17 const uint8_t TLC59208F_MODE1_AI0 = (1 << 5);
18 // 0: normal mode, 1*: low power mode, osc off
19 const uint8_t TLC59208F_MODE1_SLEEP = (1 << 4);
20 // 0*: device doesn't respond to i2c bus sub-address 1, 1: responds
21 const uint8_t TLC59208F_MODE1_SUB1 = (1 << 3);
22 // 0*: device doesn't respond to i2c bus sub-address 2, 1: responds
23 const uint8_t TLC59208F_MODE1_SUB2 = (1 << 2);
24 // 0*: device doesn't respond to i2c bus sub-address 3, 1: responds
25 const uint8_t TLC59208F_MODE1_SUB3 = (1 << 1);
26 // 0: device doesn't respond to i2c all-call 3, 1*: responds to all-call
27 const uint8_t TLC59208F_MODE1_ALLCALL = (1 << 0);
28 
29 // 0*: Group dimming, 1: Group blinking
30 const uint8_t TLC59208F_MODE2_DMBLNK = (1 << 5);
31 // 0*: Output change on Stop command, 1: Output change on ACK
32 const uint8_t TLC59208F_MODE2_OCH = (1 << 3);
33 // 0*: WDT disabled, 1: WDT enabled
34 const uint8_t TLC59208F_MODE2_WDTEN = (1 << 2);
35 // WDT timeouts
36 const uint8_t TLC59208F_MODE2_WDT_5MS = (0 << 0);
37 const uint8_t TLC59208F_MODE2_WDT_15MS = (1 << 0);
38 const uint8_t TLC59208F_MODE2_WDT_25MS = (2 << 0);
39 const uint8_t TLC59208F_MODE2_WDT_35MS = (3 << 0);
40 
41 // --- Special function ---
42 // Call address to perform software reset, no devices will ACK
43 const uint8_t TLC59208F_SWRST_ADDR = 0x96; //(0x4b 7-bit addr + ~W)
44 const uint8_t TLC59208F_SWRST_SEQ[2] = {0xa5, 0x5a};
45 
46 // --- Registers ---2
47 // Mode register 1
48 const uint8_t TLC59208F_REG_MODE1 = 0x00;
49 // Mode register 2
50 const uint8_t TLC59208F_REG_MODE2 = 0x01;
51 // PWM0
52 const uint8_t TLC59208F_REG_PWM0 = 0x02;
53 // Group PWM
54 const uint8_t TLC59208F_REG_GROUPPWM = 0x0a;
55 // Group Freq
56 const uint8_t TLC59208F_REG_GROUPFREQ = 0x0b;
57 // LEDOUTx registers
58 const uint8_t TLC59208F_REG_LEDOUT0 = 0x0c;
59 const uint8_t TLC59208F_REG_LEDOUT1 = 0x0d;
60 // Sub-address registers
61 const uint8_t TLC59208F_REG_SUBADR1 = 0x0e; // default: 0x92 (8-bit addr)
62 const uint8_t TLC59208F_REG_SUBADR2 = 0x0f; // default: 0x94 (8-bit addr)
63 const uint8_t TLC59208F_REG_SUBADR3 = 0x10; // default: 0x98 (8-bit addr)
64 // All call address register
65 const uint8_t TLC59208F_REG_ALLCALLADR = 0x11; // default: 0xd0 (8-bit addr)
66 
67 // --- Output modes ---
68 static const uint8_t LDR_OFF = 0x00;
69 static const uint8_t LDR_ON = 0x01;
70 static const uint8_t LDR_PWM = 0x02;
71 static const uint8_t LDR_GRPPWM = 0x03;
72 
74  ESP_LOGCONFIG(TAG, "Setting up TLC59208FOutputComponent...");
75 
76  ESP_LOGV(TAG, " Resetting all devices on the bus...");
77 
78  // Reset all devices on the bus
79  if (this->bus_->write(TLC59208F_SWRST_ADDR >> 1, TLC59208F_SWRST_SEQ, 2) != i2c::ERROR_OK) {
80  ESP_LOGE(TAG, "RESET failed");
81  this->mark_failed();
82  return;
83  }
84 
85  // Auto increment registers, and respond to all-call address
86  if (!this->write_byte(TLC59208F_REG_MODE1, TLC59208F_MODE1_AI2 | TLC59208F_MODE1_ALLCALL)) {
87  ESP_LOGE(TAG, "MODE1 failed");
88  this->mark_failed();
89  return;
90  }
91  if (!this->write_byte(TLC59208F_REG_MODE2, this->mode_)) {
92  ESP_LOGE(TAG, "MODE2 failed");
93  this->mark_failed();
94  return;
95  }
96  // Set all 3 outputs to be individually controlled
97  // TODO: think of a way to support group dimming
98  if (!this->write_byte(TLC59208F_REG_LEDOUT0, (LDR_PWM << 6) | (LDR_PWM << 4) | (LDR_PWM << 2) | (LDR_PWM << 0))) {
99  ESP_LOGE(TAG, "LEDOUT0 failed");
100  this->mark_failed();
101  return;
102  }
103  if (!this->write_byte(TLC59208F_REG_LEDOUT1, (LDR_PWM << 6) | (LDR_PWM << 4) | (LDR_PWM << 2) | (LDR_PWM << 0))) {
104  ESP_LOGE(TAG, "LEDOUT1 failed");
105  this->mark_failed();
106  return;
107  }
108  delayMicroseconds(500);
109 
110  this->loop();
111 }
112 
114  ESP_LOGCONFIG(TAG, "TLC59208F:");
115  ESP_LOGCONFIG(TAG, " Mode: 0x%02X", this->mode_);
116 
117  if (this->is_failed()) {
118  ESP_LOGE(TAG, "Setting up TLC59208F failed!");
119  }
120 }
121 
123  if (this->min_channel_ == 0xFF || !this->update_)
124  return;
125 
126  for (uint8_t channel = this->min_channel_; channel <= this->max_channel_; channel++) {
127  uint8_t pwm = this->pwm_amounts_[channel];
128  ESP_LOGVV(TAG, "Channel %02u: pwm=%04u ", channel, pwm);
129 
130  uint8_t reg = TLC59208F_REG_PWM0 + channel;
131  if (!this->write_byte(reg, pwm)) {
132  this->status_set_warning();
133  return;
134  }
135  }
136 
137  this->status_clear_warning();
138  this->update_ = false;
139 }
140 
142  auto c = channel->channel_;
143  this->min_channel_ = std::min(this->min_channel_, c);
144  this->max_channel_ = std::max(this->max_channel_, c);
145  channel->set_parent(this);
146 }
147 
149  const uint8_t max_duty = 255;
150  const float duty_rounded = roundf(state * max_duty);
151  auto duty = static_cast<uint8_t>(duty_rounded);
152  this->parent_->set_channel_value_(this->channel_, duty);
153 }
154 
155 } // namespace tlc59208f
156 } // namespace esphome
const uint8_t TLC59208F_REG_GROUPPWM
const uint8_t TLC59208F_REG_ALLCALLADR
const uint8_t TLC59208F_MODE1_SLEEP
const uint8_t TLC59208F_REG_LEDOUT1
const uint8_t TLC59208F_REG_PWM0
const uint8_t TLC59208F_MODE1_SUB3
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
const uint8_t TLC59208F_REG_SUBADR2
const uint8_t TLC59208F_MODE1_AI0
const uint8_t TLC59208F_MODE2_WDT_5MS
void set_parent(T *parent)
Set the parent of this object.
Definition: helpers.h:523
const uint8_t TLC59208F_REG_SUBADR1
const uint8_t TLC59208F_MODE1_ALLCALL
const uint8_t TLC59208F_MODE2_WDT_15MS
const uint8_t TLC59208F_REG_SUBADR3
void write_state(float state) override
No error found during execution of method.
Definition: i2c_bus.h:13
void register_channel(TLC59208FChannel *channel)
void status_clear_warning()
Definition: component.cpp:166
const uint8_t TLC59208F_SWRST_ADDR
const uint8_t TLC59208F_REG_LEDOUT0
const uint8_t TLC59208F_MODE2_WDTEN
const uint8_t TLC59208F_MODE1_SUB1
I2CBus * bus_
pointer to I2CBus instance
Definition: i2c.h:270
const uint8_t TLC59208F_MODE2_WDT_25MS
const uint8_t TLC59208F_REG_GROUPFREQ
virtual ErrorCode write(uint8_t address, const uint8_t *buffer, size_t len)
Definition: i2c_bus.h:62
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition: i2c.h:262
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
const uint8_t TLC59208F_MODE2_OCH
const uint8_t TLC59208F_MODE2_DMBLNK
const uint8_t TLC59208F_MODE1_AI2
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition: core.cpp:28
const uint8_t TLC59208F_SWRST_SEQ[2]
const uint8_t TLC59208F_REG_MODE1
const uint8_t TLC59208F_REG_MODE2
const uint8_t TLC59208F_MODE1_AI1
const uint8_t TLC59208F_MODE2_WDT_35MS
bool state
Definition: fan.h:34
const uint8_t TLC59208F_MODE1_SUB2