mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 14:16:40 +00:00
Add es8388 audio_dac (#8342)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
a8fdb6db4d
commit
04ee1a87e9
@ -139,6 +139,7 @@ esphome/components/es7210/* @kahrendt
|
||||
esphome/components/es7243e/* @kbx81
|
||||
esphome/components/es8156/* @kbx81
|
||||
esphome/components/es8311/* @kahrendt @kroimon
|
||||
esphome/components/es8388/* @P4uLT
|
||||
esphome/components/esp32/* @esphome/core
|
||||
esphome/components/esp32_ble/* @Rapsssito @jesserockz
|
||||
esphome/components/esp32_ble_client/* @jesserockz
|
||||
|
0
esphome/components/es8388/__init__.py
Normal file
0
esphome/components/es8388/__init__.py
Normal file
26
esphome/components/es8388/audio_dac.py
Normal file
26
esphome/components/es8388/audio_dac.py
Normal file
@ -0,0 +1,26 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
from esphome.components.audio_dac import AudioDac
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ["@P4uLT"]
|
||||
CONF_ES8388_ID = "es8388_id"
|
||||
|
||||
es8388_ns = cg.esphome_ns.namespace("es8388")
|
||||
|
||||
ES8388 = es8388_ns.class_("ES8388", AudioDac, cg.Component, i2c.I2CDevice)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema({cv.GenerateID(): cv.declare_id(ES8388)})
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x10))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
289
esphome/components/es8388/es8388.cpp
Normal file
289
esphome/components/es8388/es8388.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
#include "es8388.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
static const char *const TAG = "es8388";
|
||||
|
||||
// Mark the component as failed; use only in setup
|
||||
#define ES8388_ERROR_FAILED(func) \
|
||||
if (!(func)) { \
|
||||
this->mark_failed(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
// Return false; use outside of setup
|
||||
#define ES8388_ERROR_CHECK(func) \
|
||||
if (!(func)) { \
|
||||
return false; \
|
||||
}
|
||||
|
||||
void ES8388::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ES8388...");
|
||||
|
||||
// mute DAC
|
||||
this->set_mute_state_(true);
|
||||
|
||||
// I2S worker mode
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_MASTERMODE, 0x00));
|
||||
|
||||
/* Chip Control and Power Management */
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_CONTROL2, 0x50));
|
||||
// normal all and power up all
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_CHIPPOWER, 0x00));
|
||||
|
||||
// vmidsel/500k
|
||||
// EnRef=0,Play&Record Mode,(0x17-both of mic&play)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_CONTROL1, 0x12));
|
||||
|
||||
// i2s 16 bits
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL1, 0x18));
|
||||
// sample freq 256
|
||||
// DACFsMode,SINGLE SPEED; DACFsRatio,256
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL2, 0x02));
|
||||
// 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL16, 0x00));
|
||||
// only left DAC to left mixer enable 0db
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL17, 0x90));
|
||||
// only right DAC to right mixer enable 0db
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL20, 0x90));
|
||||
// set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL21, 0x80));
|
||||
// vroi=0 - 1.5k VREF to analog output resistance (default)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL23, 0x00));
|
||||
|
||||
// power down adc and line in
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCPOWER, 0xFF));
|
||||
|
||||
//@nightdav
|
||||
ES8388_ERROR_FAILED(
|
||||
this->write_byte(ES8388_ADCCONTROL1, 0x00)); // +21dB : recommended value for ALC & voice recording
|
||||
|
||||
// set to Mono Right
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL3, 0x02));
|
||||
|
||||
// I2S 16 Bits length and I2S serial audio data format
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL4, 0x0d));
|
||||
// ADCFsMode,singel SPEED,RATIO=256
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL5, 0x02));
|
||||
|
||||
// ADC Volume
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL8, 0x00));
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL9, 0x00));
|
||||
|
||||
//@nightDav
|
||||
// ALC Config (as recommended by ES8388 user guide for voice recording)
|
||||
|
||||
// Reg 0x12 = 0xe2 (ALC enable, PGA Max. Gain=23.5dB, Min. Gain=0dB)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL10, 0xe2));
|
||||
|
||||
// Reg 0x13 = 0xa0 (ALC Target=-1.5dB, ALC Hold time =0 mS)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL11, 0xa0));
|
||||
// Reg 0x14 = 0x12(Decay time =820uS , Attack time = 416 uS)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL12, 0x12));
|
||||
|
||||
// Reg 0x15 = 0x06(ALC mode)
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL13, 0x06));
|
||||
|
||||
// Reg 0x16 = 0xc3(nose gate = -40.5dB, NGG = 0x01(mute ADC))
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL14, 0xc3));
|
||||
|
||||
// Power on ADC
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL21, 0x80));
|
||||
|
||||
// Start state machine
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_CHIPPOWER, 0xF0));
|
||||
delay(1);
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_CHIPPOWER, 0x00));
|
||||
|
||||
// DAC volume max
|
||||
// Set initial volume
|
||||
// this->set_volume(0.75); // 0.75 = 0xBF = 0dB
|
||||
|
||||
this->set_mute_state_(false);
|
||||
|
||||
// unmute ADC with fade in
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCCONTROL7, 0x60));
|
||||
// unmute DAC with fade in
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_DACCONTROL3, 0x20));
|
||||
|
||||
// Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCPOWER, 0x09));
|
||||
|
||||
#ifdef USE_SELECT
|
||||
if (this->dac_output_select_ != nullptr) {
|
||||
auto dac_power = this->get_dac_power();
|
||||
if (dac_power.has_value()) {
|
||||
auto dac_power_str = this->dac_output_select_->at(dac_power.value());
|
||||
if (dac_power_str.has_value()) {
|
||||
this->dac_output_select_->publish_state(dac_power_str.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown DAC output power value: %d", dac_power.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this->adc_input_mic_select_ != nullptr) {
|
||||
auto mic_input = this->get_mic_input();
|
||||
if (mic_input.has_value()) {
|
||||
auto mic_input_str = this->adc_input_mic_select_->at(mic_input.value());
|
||||
if (mic_input_str.has_value()) {
|
||||
this->adc_input_mic_select_->publish_state(mic_input_str.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown ADC input mic value: %d", mic_input.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ES8388::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ES8388 Audio Codec:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
#ifdef USE_SELECT
|
||||
LOG_SELECT(" ", "DacOutputSelect", this->dac_output_select_);
|
||||
LOG_SELECT(" ", "ADCInputMicSelect", this->adc_input_mic_select_);
|
||||
#endif
|
||||
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGCONFIG(TAG, " Failed to initialize");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ES8388::set_volume(float volume) {
|
||||
volume = clamp(volume, 0.0f, 1.0f);
|
||||
uint8_t value = remap<uint8_t, float>(volume, 0.0f, 1.0f, -96, 0);
|
||||
ESP_LOGD(TAG, "Setting ES8388_DACCONTROL4 / ES8388_DACCONTROL5 to 0x%02X (volume: %f)", value, volume);
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL4, value));
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL5, value));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float ES8388::volume() {
|
||||
uint8_t value;
|
||||
ES8388_ERROR_CHECK(this->read_byte(ES8388_DACCONTROL4, &value));
|
||||
return remap<float, uint8_t>(value, -96, 0, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
bool ES8388::set_mute_state_(bool mute_state) {
|
||||
uint8_t value = 0;
|
||||
|
||||
this->is_muted_ = mute_state;
|
||||
|
||||
ES8388_ERROR_CHECK(this->read_byte(ES8388_DACCONTROL3, &value));
|
||||
ESP_LOGV(TAG, "Read ES8388_DACCONTROL3: 0x%02X", value);
|
||||
|
||||
if (mute_state) {
|
||||
value = 0x3C;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Setting ES8388_DACCONTROL3 to 0x%02X (muted: %s)", value, YESNO(mute_state));
|
||||
return this->write_byte(ES8388_DACCONTROL3, value);
|
||||
}
|
||||
|
||||
// Set dac power output
|
||||
bool ES8388::set_dac_output(DacOutputLine line) {
|
||||
uint8_t reg_out1 = 0;
|
||||
uint8_t reg_out2 = 0;
|
||||
uint8_t dac_power = 0;
|
||||
|
||||
// 0x00: -30dB , 0x1E: 0dB
|
||||
switch (line) {
|
||||
case DAC_OUTPUT_LINE1:
|
||||
reg_out1 = 0x1E;
|
||||
dac_power = ES8388_DAC_OUTPUT_LOUT1_ROUT1;
|
||||
break;
|
||||
case DAC_OUTPUT_LINE2:
|
||||
reg_out2 = 0x1E;
|
||||
dac_power = ES8388_DAC_OUTPUT_LOUT2_ROUT2;
|
||||
break;
|
||||
case DAC_OUTPUT_BOTH:
|
||||
reg_out1 = 0x1E;
|
||||
reg_out2 = 0x1E;
|
||||
dac_power = ES8388_DAC_OUTPUT_BOTH;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown DAC output line: %d", line);
|
||||
return false;
|
||||
};
|
||||
|
||||
ESP_LOGV(TAG, "Setting ES8388_DACPOWER to 0x%02X", dac_power);
|
||||
ESP_LOGV(TAG, "Setting ES8388_DACCONTROL24 / ES8388_DACCONTROL25 to 0x%02X", reg_out1);
|
||||
ESP_LOGV(TAG, "Setting ES8388_DACCONTROL26 / ES8388_DACCONTROL27 to 0x%02X", reg_out2);
|
||||
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL24, reg_out1)); // LOUT1VOL
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL25, reg_out1)); // ROUT1VOL
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL26, reg_out2)); // LOUT2VOL
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL27, reg_out2)); // ROUT1VOL
|
||||
|
||||
return this->write_byte(ES8388_DACPOWER, dac_power);
|
||||
}
|
||||
|
||||
optional<DacOutputLine> ES8388::get_dac_power() {
|
||||
uint8_t dac_power;
|
||||
if (!this->read_byte(ES8388_DACPOWER, &dac_power)) {
|
||||
this->status_momentary_warning("Failed to read ES8388_DACPOWER");
|
||||
return {};
|
||||
}
|
||||
switch (dac_power) {
|
||||
case ES8388_DAC_OUTPUT_LOUT1_ROUT1:
|
||||
return DAC_OUTPUT_LINE1;
|
||||
case ES8388_DAC_OUTPUT_LOUT2_ROUT2:
|
||||
return DAC_OUTPUT_LINE2;
|
||||
case ES8388_DAC_OUTPUT_BOTH:
|
||||
return DAC_OUTPUT_BOTH;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Set ADC input MIC
|
||||
bool ES8388::set_adc_input_mic(AdcInputMicLine line) {
|
||||
uint8_t mic_input = 0;
|
||||
|
||||
switch (line) {
|
||||
case ADC_INPUT_MIC_LINE1:
|
||||
mic_input = ES8388_ADC_INPUT_LINPUT1_RINPUT1;
|
||||
break;
|
||||
case ADC_INPUT_MIC_LINE2:
|
||||
mic_input = ES8388_ADC_INPUT_LINPUT2_RINPUT2;
|
||||
break;
|
||||
case ADC_INPUT_MIC_DIFFERENCE:
|
||||
mic_input = ES8388_ADC_INPUT_DIFFERENCE;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown ADC input mic line: %d", line);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Setting ES8388_ADCCONTROL2 to 0x%02X", mic_input);
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_ADCCONTROL2, mic_input));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
optional<AdcInputMicLine> ES8388::get_mic_input() {
|
||||
uint8_t mic_input;
|
||||
if (!this->read_byte(ES8388_ADCCONTROL2, &mic_input)) {
|
||||
this->status_momentary_warning("Failed to read ES8388_ADCCONTROL2");
|
||||
return {};
|
||||
}
|
||||
switch (mic_input) {
|
||||
case ES8388_ADC_INPUT_LINPUT1_RINPUT1:
|
||||
return ADC_INPUT_MIC_LINE1;
|
||||
case ES8388_ADC_INPUT_LINPUT2_RINPUT2:
|
||||
return ADC_INPUT_MIC_LINE2;
|
||||
case ES8388_ADC_INPUT_DIFFERENCE:
|
||||
return ADC_INPUT_MIC_DIFFERENCE;
|
||||
default:
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
81
esphome/components/es8388/es8388.h
Normal file
81
esphome/components/es8388/es8388.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "esphome/components/audio_dac/audio_dac.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
#ifdef USE_SELECT
|
||||
#include "esphome/components/select/select.h"
|
||||
#endif
|
||||
|
||||
#include "es8388_const.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
enum DacOutputLine : uint8_t {
|
||||
DAC_OUTPUT_LINE1,
|
||||
DAC_OUTPUT_LINE2,
|
||||
DAC_OUTPUT_BOTH,
|
||||
};
|
||||
|
||||
enum AdcInputMicLine : uint8_t {
|
||||
ADC_INPUT_MIC_LINE1,
|
||||
ADC_INPUT_MIC_LINE2,
|
||||
ADC_INPUT_MIC_DIFFERENCE,
|
||||
};
|
||||
|
||||
class ES8388 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
|
||||
#ifdef USE_SELECT
|
||||
SUB_SELECT(dac_output)
|
||||
SUB_SELECT(adc_input_mic)
|
||||
#endif
|
||||
|
||||
public:
|
||||
/////////////////////////
|
||||
// Component overrides //
|
||||
/////////////////////////
|
||||
|
||||
void setup() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
void dump_config() override;
|
||||
|
||||
////////////////////////
|
||||
// AudioDac overrides //
|
||||
////////////////////////
|
||||
|
||||
/// @brief Writes the volume out to the DAC
|
||||
/// @param volume floating point between 0.0 and 1.0
|
||||
/// @return True if successful and false otherwise
|
||||
bool set_volume(float volume) override;
|
||||
|
||||
/// @brief Gets the current volume out from the DAC
|
||||
/// @return floating point between 0.0 and 1.0
|
||||
float volume() override;
|
||||
|
||||
/// @brief Disables mute for audio out
|
||||
/// @return True if successful and false otherwise
|
||||
bool set_mute_off() override { return this->set_mute_state_(false); }
|
||||
|
||||
/// @brief Enables mute for audio out
|
||||
/// @return True if successful and false otherwise
|
||||
bool set_mute_on() override { return this->set_mute_state_(true); }
|
||||
|
||||
bool is_muted() override { return this->is_muted_; }
|
||||
|
||||
optional<DacOutputLine> get_dac_power();
|
||||
optional<AdcInputMicLine> get_mic_input();
|
||||
|
||||
bool set_dac_output(DacOutputLine line);
|
||||
bool set_adc_input_mic(AdcInputMicLine line);
|
||||
|
||||
protected:
|
||||
/// @brief Mutes or unmutes the DAC audio out
|
||||
/// @param mute_state True to mute, false to unmute
|
||||
/// @return True if successful and false otherwise
|
||||
bool set_mute_state_(bool mute_state);
|
||||
};
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
83
esphome/components/es8388/es8388_const.h
Normal file
83
esphome/components/es8388/es8388_const.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
/* ES8388 register */
|
||||
static const uint8_t ES8388_CONTROL1 = 0x00;
|
||||
static const uint8_t ES8388_CONTROL2 = 0x01;
|
||||
|
||||
static const uint8_t ES8388_CHIPPOWER = 0x02;
|
||||
|
||||
static const uint8_t ES8388_ADCPOWER = 0x03;
|
||||
static const uint8_t ES8388_DACPOWER = 0x04;
|
||||
|
||||
static const uint8_t ES8388_CHIPLOPOW1 = 0x05;
|
||||
static const uint8_t ES8388_CHIPLOPOW2 = 0x06;
|
||||
|
||||
static const uint8_t ES8388_ANAVOLMANAG = 0x07;
|
||||
|
||||
static const uint8_t ES8388_MASTERMODE = 0x08;
|
||||
|
||||
/* ADC */
|
||||
static const uint8_t ES8388_ADCCONTROL1 = 0x09;
|
||||
static const uint8_t ES8388_ADCCONTROL2 = 0x0a;
|
||||
static const uint8_t ES8388_ADCCONTROL3 = 0x0b;
|
||||
static const uint8_t ES8388_ADCCONTROL4 = 0x0c;
|
||||
static const uint8_t ES8388_ADCCONTROL5 = 0x0d;
|
||||
static const uint8_t ES8388_ADCCONTROL6 = 0x0e;
|
||||
static const uint8_t ES8388_ADCCONTROL7 = 0x0f;
|
||||
static const uint8_t ES8388_ADCCONTROL8 = 0x10;
|
||||
static const uint8_t ES8388_ADCCONTROL9 = 0x11;
|
||||
static const uint8_t ES8388_ADCCONTROL10 = 0x12;
|
||||
static const uint8_t ES8388_ADCCONTROL11 = 0x13;
|
||||
static const uint8_t ES8388_ADCCONTROL12 = 0x14;
|
||||
static const uint8_t ES8388_ADCCONTROL13 = 0x15;
|
||||
static const uint8_t ES8388_ADCCONTROL14 = 0x16;
|
||||
/* DAC */
|
||||
static const uint8_t ES8388_DACCONTROL1 = 0x17;
|
||||
static const uint8_t ES8388_DACCONTROL2 = 0x18;
|
||||
static const uint8_t ES8388_DACCONTROL3 = 0x19;
|
||||
static const uint8_t ES8388_DACCONTROL4 = 0x1a;
|
||||
static const uint8_t ES8388_DACCONTROL5 = 0x1b;
|
||||
static const uint8_t ES8388_DACCONTROL6 = 0x1c;
|
||||
static const uint8_t ES8388_DACCONTROL7 = 0x1d;
|
||||
static const uint8_t ES8388_DACCONTROL8 = 0x1e;
|
||||
static const uint8_t ES8388_DACCONTROL9 = 0x1f;
|
||||
static const uint8_t ES8388_DACCONTROL10 = 0x20;
|
||||
static const uint8_t ES8388_DACCONTROL11 = 0x21;
|
||||
static const uint8_t ES8388_DACCONTROL12 = 0x22;
|
||||
static const uint8_t ES8388_DACCONTROL13 = 0x23;
|
||||
static const uint8_t ES8388_DACCONTROL14 = 0x24;
|
||||
static const uint8_t ES8388_DACCONTROL15 = 0x25;
|
||||
static const uint8_t ES8388_DACCONTROL16 = 0x26;
|
||||
static const uint8_t ES8388_DACCONTROL17 = 0x27;
|
||||
static const uint8_t ES8388_DACCONTROL18 = 0x28;
|
||||
static const uint8_t ES8388_DACCONTROL19 = 0x29;
|
||||
static const uint8_t ES8388_DACCONTROL20 = 0x2a;
|
||||
static const uint8_t ES8388_DACCONTROL21 = 0x2b;
|
||||
static const uint8_t ES8388_DACCONTROL22 = 0x2c;
|
||||
static const uint8_t ES8388_DACCONTROL23 = 0x2d;
|
||||
static const uint8_t ES8388_DACCONTROL24 = 0x2e;
|
||||
static const uint8_t ES8388_DACCONTROL25 = 0x2f;
|
||||
static const uint8_t ES8388_DACCONTROL26 = 0x30;
|
||||
static const uint8_t ES8388_DACCONTROL27 = 0x31;
|
||||
static const uint8_t ES8388_DACCONTROL28 = 0x32;
|
||||
static const uint8_t ES8388_DACCONTROL29 = 0x33;
|
||||
static const uint8_t ES8388_DACCONTROL30 = 0x34;
|
||||
|
||||
static const uint8_t ES8388_DAC_OUTPUT_NONE = 0xC0; // ALL DAC DOWN
|
||||
|
||||
static const uint8_t ES8388_DAC_OUTPUT_LOUT1_ROUT1 = 0x30;
|
||||
static const uint8_t ES8388_DAC_OUTPUT_LOUT2_ROUT2 = 0x0C;
|
||||
static const uint8_t ES8388_DAC_OUTPUT_BOTH = 0x3C;
|
||||
|
||||
static const uint8_t ES8388_ADC_INPUT_LINPUT1_RINPUT1 = 0x00;
|
||||
static const uint8_t ES8388_ADC_INPUT_MIC1 = 0x05;
|
||||
static const uint8_t ES8388_ADC_INPUT_MIC2 = 0x06;
|
||||
static const uint8_t ES8388_ADC_INPUT_LINPUT2_RINPUT2 = 0x50;
|
||||
static const uint8_t ES8388_ADC_INPUT_DIFFERENCE = 0xf0;
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
47
esphome/components/es8388/select/__init__.py
Normal file
47
esphome/components/es8388/select/__init__.py
Normal file
@ -0,0 +1,47 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import select
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import ENTITY_CATEGORY_CONFIG, ICON_CHIP # noqa: F401
|
||||
|
||||
from ..audio_dac import CONF_ES8388_ID, ES8388, es8388_ns
|
||||
|
||||
CONF_DAC_OUTPUT = "dac_output"
|
||||
CONF_ADC_INPUT_MIC = "adc_input_mic"
|
||||
|
||||
DacOutputSelect = es8388_ns.class_("DacOutputSelect", select.Select)
|
||||
ADCInputMicSelect = es8388_ns.class_("ADCInputMicSelect", select.Select)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
{
|
||||
cv.GenerateID(CONF_ES8388_ID): cv.use_id(ES8388),
|
||||
cv.Optional(CONF_DAC_OUTPUT): select.select_schema(
|
||||
DacOutputSelect,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
icon=ICON_CHIP,
|
||||
),
|
||||
cv.Optional(CONF_ADC_INPUT_MIC): select.select_schema(
|
||||
ADCInputMicSelect,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
icon=ICON_CHIP,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_ES8388_ID])
|
||||
if dac_output_config := config.get(CONF_DAC_OUTPUT):
|
||||
s = await select.new_select(
|
||||
dac_output_config,
|
||||
options=["LINE1", "LINE2", "BOTH"],
|
||||
)
|
||||
await cg.register_parented(s, parent)
|
||||
cg.add(parent.set_dac_output_select(s))
|
||||
|
||||
if adc_input_mic_config := config.get(CONF_ADC_INPUT_MIC):
|
||||
s = await select.new_select(
|
||||
adc_input_mic_config,
|
||||
options=["LINE1", "LINE2", "DIFFERENCE"],
|
||||
)
|
||||
await cg.register_parented(s, parent)
|
||||
cg.add(parent.set_adc_input_mic_select(s))
|
12
esphome/components/es8388/select/adc_input_mic_select.cpp
Normal file
12
esphome/components/es8388/select/adc_input_mic_select.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "adc_input_mic_select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
void ADCInputMicSelect::control(const std::string &value) {
|
||||
this->publish_state(value);
|
||||
this->parent_->set_adc_input_mic(static_cast<AdcInputMicLine>(this->index_of(value).value()));
|
||||
}
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
15
esphome/components/es8388/select/adc_input_mic_select.h
Normal file
15
esphome/components/es8388/select/adc_input_mic_select.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/es8388/es8388.h"
|
||||
#include "esphome/components/select/select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
class ADCInputMicSelect : public select::Select, public Parented<ES8388> {
|
||||
protected:
|
||||
void control(const std::string &value) override;
|
||||
};
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
12
esphome/components/es8388/select/dac_output_select.cpp
Normal file
12
esphome/components/es8388/select/dac_output_select.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "dac_output_select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
void DacOutputSelect::control(const std::string &value) {
|
||||
this->publish_state(value);
|
||||
this->parent_->set_dac_output(static_cast<DacOutputLine>(this->index_of(value).value()));
|
||||
}
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
15
esphome/components/es8388/select/dac_output_select.h
Normal file
15
esphome/components/es8388/select/dac_output_select.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/es8388/es8388.h"
|
||||
#include "esphome/components/select/select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es8388 {
|
||||
|
||||
class DacOutputSelect : public select::Select, public Parented<ES8388> {
|
||||
protected:
|
||||
void control(const std::string &value) override;
|
||||
};
|
||||
|
||||
} // namespace es8388
|
||||
} // namespace esphome
|
@ -95,6 +95,7 @@
|
||||
|
||||
// Feature flags which do not work for zephyr
|
||||
#ifndef USE_ZEPHYR
|
||||
#define USE_AUDIO_DAC
|
||||
#define USE_AUDIO_FLAC_SUPPORT
|
||||
#define USE_AUDIO_MP3_SUPPORT
|
||||
#define USE_API
|
||||
|
25
tests/components/es8388/common.yaml
Normal file
25
tests/components/es8388/common.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- audio_dac.mute_off:
|
||||
- audio_dac.mute_on:
|
||||
|
||||
- audio_dac.set_volume:
|
||||
volume: 50%
|
||||
|
||||
i2c:
|
||||
- id: i2c_es8388
|
||||
scl: ${scl_pin}
|
||||
sda: ${sda_pin}
|
||||
|
||||
audio_dac:
|
||||
- platform: es8388
|
||||
id: es8388_parent
|
||||
|
||||
select:
|
||||
- platform: es8388
|
||||
es8388_id: es8388_parent
|
||||
dac_output:
|
||||
name: "DAC Output"
|
||||
adc_input_mic:
|
||||
name: "ADC Input MIC"
|
5
tests/components/es8388/test.esp32-ard.yaml
Normal file
5
tests/components/es8388/test.esp32-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es8388/test.esp32-c3-ard.yaml
Normal file
5
tests/components/es8388/test.esp32-c3-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es8388/test.esp32-c3-idf.yaml
Normal file
5
tests/components/es8388/test.esp32-c3-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es8388/test.esp32-idf.yaml
Normal file
5
tests/components/es8388/test.esp32-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es8388/test.esp8266-ard.yaml
Normal file
5
tests/components/es8388/test.esp8266-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
Loading…
x
Reference in New Issue
Block a user