13static constexpr uint8_t TAS58XX_PAGE_SELECT = 0x00;
14static constexpr uint8_t TAS58XX_BOOK_SELECT = 0x7F;
15static constexpr uint8_t TAS58XX_BOOK_CONTROL = 0x00;
16static constexpr uint8_t TAS58XX_PAGE_0 = 0x00;
19static constexpr uint8_t TAS58XX_RESET_CTRL = 0x01;
20static constexpr uint8_t TAS58XX_RESET_CTRL_ALL = 0x11;
21static constexpr uint8_t TAS58XX_DEVICE_CTRL_1 = 0x02;
22static constexpr uint8_t TAS58XX_DEVICE_CTRL_1_PBTL = (1 << 2);
23static constexpr uint8_t TAS58XX_DEVICE_CTRL_2 = 0x03;
24static constexpr uint8_t TAS58XX_DEVICE_CTRL_2_MUTE = (1 << 3);
25static constexpr uint8_t TAS58XX_CTRL_STATE_MASK = 0x03;
26static constexpr uint8_t TAS58XX_CTRL_STATE_DEEP_SLEEP = 0x00;
27static constexpr uint8_t TAS58XX_CTRL_STATE_SLEEP = 0x01;
28static constexpr uint8_t TAS58XX_CTRL_STATE_HIZ = 0x02;
29static constexpr uint8_t TAS58XX_CTRL_STATE_PLAY = 0x03;
30static constexpr uint8_t TAS58XX_CTRL_STATE_UNKNOWN = 0xFF;
31static constexpr uint8_t TAS58XX_DIG_VOL = 0x4C;
32static constexpr uint8_t TAS58XX_DIG_VOL_0DB = 0x30;
33static constexpr uint8_t TAS58XX_DIG_VOL_MINUS_103DB = 0xFE;
34static constexpr uint8_t TAS58XX_AGAIN = 0x54;
35static constexpr uint8_t TAS58XX_AGAIN_MINUS_15_5DB = 0x1F;
36static constexpr uint8_t TAS58XX_POWER_STATE = 0x68;
37static constexpr uint8_t TAS58XX_CHAN_FAULT = 0x70;
38static constexpr uint8_t TAS58XX_FAULT_REGISTER_COUNT = 4;
39static constexpr uint8_t TAS58XX_FAULT_CLEAR = 0x78;
40static constexpr uint8_t TAS58XX_FAULT_CLEAR_ANALOG = 0x80;
43static constexpr uint8_t TAS58XX_MIXER_COEFFICIENT_SIZE = 4;
45static constexpr uint8_t TAS58XX_MIXER_MUTE = 0x00;
46static constexpr uint8_t TAS58XX_MIXER_MINUS_6DB = 0x40;
47static constexpr uint8_t TAS58XX_MIXER_0DB = 0x80;
49static constexpr uint32_t PDN_LOW_MS = 1;
50static constexpr uint32_t PDN_TO_I2C_MS = 5;
51static constexpr uint32_t RESET_SETTLE_MS = 5;
53static const LogString *power_state_name(uint8_t
state) {
54 if (
state == TAS58XX_CTRL_STATE_DEEP_SLEEP)
55 return LOG_STR(
"Deep sleep");
56 if (
state == TAS58XX_CTRL_STATE_SLEEP)
57 return LOG_STR(
"Sleep");
58 if (
state == TAS58XX_CTRL_STATE_HIZ)
59 return LOG_STR(
"Hi-Z");
60 return LOG_STR(
"Play");
78 return this->
write_byte(TAS58XX_PAGE_SELECT, TAS58XX_PAGE_0) && this->
write_byte(TAS58XX_BOOK_SELECT, book) &&
86 !this->
write_byte(TAS58XX_DEVICE_CTRL_2, TAS58XX_CTRL_STATE_HIZ) ||
87 !this->
write_byte(TAS58XX_RESET_CTRL, TAS58XX_RESET_CTRL_ALL) ||
88 !this->
write_byte(TAS58XX_DEVICE_CTRL_2, TAS58XX_CTRL_STATE_HIZ)) {
89 ESP_LOGE(TAG,
"I2C write failed during reset");
92 delay(RESET_SETTLE_MS);
97 ESP_LOGE(TAG,
"I2C write failed during init");
103 const uint8_t again =
104 static_cast<uint8_t
>(lroundf(clamp(-this->
analog_gain_db_ * 2.0f, 0.0f,
float{TAS58XX_AGAIN_MINUS_15_5DB})));
108 !this->
write_byte(TAS58XX_FAULT_CLEAR, TAS58XX_FAULT_CLEAR_ANALOG)) {
109 ESP_LOGE(TAG,
"I2C write failed during init");
121 ESP_LOGD(TAG,
"[0x%02X] Activating", this->
address_);
124 ESP_LOGE(TAG,
"Failed to select the control port");
128 if (!this->
write_byte(TAS58XX_FAULT_CLEAR, TAS58XX_FAULT_CLEAR_ANALOG)) {
129 ESP_LOGW(TAG,
"Failed to clear faults");
133 if (this->
ctrl_state_ == TAS58XX_CTRL_STATE_DEEP_SLEEP &&
145 ESP_LOGD(TAG,
"[0x%02X] Deactivating", this->
address_);
147 ESP_LOGE(TAG,
"Failed to select the control port");
155 if (!this->
write_byte(TAS58XX_DEVICE_CTRL_2,
state | (muted ? TAS58XX_DEVICE_CTRL_2_MUTE : 0))) {
156 ESP_LOGE(TAG,
"Failed to write DEVICE_CTRL_2");
165 uint8_t fault_registers[TAS58XX_FAULT_REGISTER_COUNT];
166 if (!this->
read_bytes(TAS58XX_CHAN_FAULT, fault_registers,
sizeof(fault_registers)))
169 for (uint8_t
reg = 0;
reg < TAS58XX_FAULT_REGISTER_COUNT;
reg++)
176 for (uint8_t index = 0; index < 32; index++) {
178 if (!(changed & mask))
180 const LogString *name = model.
fault_name(index);
181 if (!(active & mask)) {
182 ESP_LOGI(TAG,
"[0x%02X] %s cleared", this->
address_, LOG_STR_ARG(name));
184 ESP_LOGE(TAG,
"[0x%02X] %s", this->
address_, LOG_STR_ARG(name));
186 ESP_LOGW(TAG,
"[0x%02X] %s", this->
address_, LOG_STR_ARG(name));
190 ESP_LOGW(TAG,
"[0x%02X] Output stays off: fix the cause, then call tas58xx.activate or power cycle the amplifier",
193 this->logged_faults_ = active;
195#ifdef USE_BINARY_SENSOR
196 if (this->have_fault_binary_sensor_ !=
nullptr)
197 this->have_fault_binary_sensor_->publish_state((active & model.
fault_error_mask) != 0);
209 !this->write_byte(TAS58XX_FAULT_CLEAR, TAS58XX_FAULT_CLEAR_ANALOG)) {
210 ESP_LOGW(TAG,
"Failed to clear faults");
220 ESP_LOGW(TAG,
"Failed to write mixer");
232 power_state &= TAS58XX_CTRL_STATE_MASK;
234 ESP_LOGD(TAG,
"[0x%02X] Power state: %s", this->
address_, LOG_STR_ARG(power_state_name(power_state)));
240 ESP_LOGW(TAG,
"Failed to write mixer");
245 const LogString *mixer_mode;
247 mixer_mode = LOG_STR(
"Stereo inverse");
249 mixer_mode = LOG_STR(
"Mono");
251 mixer_mode = LOG_STR(
"Left");
253 mixer_mode = LOG_STR(
"Right");
255 mixer_mode = LOG_STR(
"Stereo");
261 LOG_I2C_DEVICE(
this);
263 LOG_UPDATE_INTERVAL(
this);
265 " Analog Gain: %.1f dB\n"
268 " Volume Range: %.1f dB to %.1f dB",
272#ifdef USE_BINARY_SENSOR
273 LOG_BINARY_SENSOR(
" ",
"Any Fault", this->have_fault_binary_sensor_);
275 LOG_BINARY_SENSOR(
" ",
"Fault",
sensor);
288 float previous = this->
volume_;
300 const uint8_t dig_vol =
static_cast<uint8_t
>(
301 lroundf(clamp(TAS58XX_DIG_VOL_0DB - volume_db * 2.0f, 0.0f,
float{TAS58XX_DIG_VOL_MINUS_103DB})));
302 ESP_LOGV(TAG,
"Setting volume to 0x%02X", dig_vol);
303 return this->
write_byte(TAS58XX_DIG_VOL, dig_vol);
307 uint8_t left_to_left = TAS58XX_MIXER_0DB;
308 uint8_t right_to_left = TAS58XX_MIXER_MUTE;
309 uint8_t left_to_right = TAS58XX_MIXER_MUTE;
310 uint8_t right_to_right = TAS58XX_MIXER_0DB;
312 left_to_left = TAS58XX_MIXER_MUTE;
313 right_to_left = TAS58XX_MIXER_0DB;
314 left_to_right = TAS58XX_MIXER_0DB;
315 right_to_right = TAS58XX_MIXER_MUTE;
317 left_to_left = TAS58XX_MIXER_MINUS_6DB;
318 right_to_left = TAS58XX_MIXER_MINUS_6DB;
319 left_to_right = TAS58XX_MIXER_MINUS_6DB;
320 right_to_right = TAS58XX_MIXER_MINUS_6DB;
322 left_to_right = TAS58XX_MIXER_0DB;
323 right_to_right = TAS58XX_MIXER_MUTE;
325 left_to_left = TAS58XX_MIXER_MUTE;
326 right_to_left = TAS58XX_MIXER_0DB;
328 const uint8_t coefficients[4 * TAS58XX_MIXER_COEFFICIENT_SIZE] = {0, left_to_left, 0, 0, 0, right_to_left, 0, 0,
329 0, left_to_right, 0, 0, 0, right_to_right, 0, 0};
void mark_failed()
Mark this component as failed.
void status_set_warning()
void status_clear_warning()
virtual void digital_write(bool value)=0
uint8_t address_
store the address of the device on the bus
bool write_byte(uint8_t a_register, uint8_t data) const
bool read_byte(uint8_t a_register, uint8_t *data)
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len) const
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
binary_sensor::BinarySensor * sensor
bool set_mute_(bool muted)
std::array< binary_sensor::BinarySensor *, FAULT_SENSOR_COUNT > fault_binary_sensors_
void dump_config() override
bool set_volume(float volume) override
bool write_ctrl_state_(uint8_t state, bool muted)
void activate()
Clear faults, leave deep sleep and switch to play; the device waits in Hi-Z until an I2S clock is pre...
void deactivate()
Switch to deep sleep, the lowest power state that keeps I2C and the DSP running.
void on_audio_started() override
bool select_book_page_(uint8_t book, uint8_t page)
ESPHOME_LOG_TAG(TAG, "tas58xx")
@ MIXER_MODE_STEREO_INVERSE
void HOT delay(uint32_t ms)
uint8_t progmem_read_byte(const uint8_t *addr)
Everything that differs between models of the family.
uint8_t fault_sensor_bits[FAULT_SENSOR_COUNT]
Bit index for each FaultSensor, NO_BIT used where the model does not have that fault bit.
uint32_t fault_output_off_mask
Faults that keep the output off until cleared by activate()
const LogString *(* fault_name)(uint8_t index)
uint32_t fault_warning_mask
Faults logged as warnings.
uint8_t mixer_book
Location of the four 9.23 fixed point input mixer coefficients: LEFT_TO_LEFT, RIGHT_TO_LEFT,...
uint8_t startup_sequence_length
const LogString *(* name)()
uint32_t fault_latched_mask
Faults that stay set after the condition is gone and are cleared after each read.
const uint8_t(* startup_sequence)[2]
Remainder of the startup sequence, run after the reset, as {register, value} pairs in PROGMEM.
uint32_t fault_error_mask
Faults logged as errors and reported by have_fault.