mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	[es8156] Add support for ES8156 audio DAC (#8085)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -133,6 +133,7 @@ esphome/components/ens160_i2c/* @latonita | ||||
| esphome/components/ens160_spi/* @latonita | ||||
| esphome/components/ens210/* @itn3rd77 | ||||
| esphome/components/es7210/* @kahrendt | ||||
| esphome/components/es8156/* @kbx81 | ||||
| esphome/components/es8311/* @kahrendt @kroimon | ||||
| esphome/components/esp32/* @esphome/core | ||||
| esphome/components/esp32_ble/* @Rapsssito @jesserockz | ||||
|   | ||||
							
								
								
									
										0
									
								
								esphome/components/es8156/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/es8156/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										27
									
								
								esphome/components/es8156/audio_dac.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								esphome/components/es8156/audio_dac.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| 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 = ["@kbx81"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| es8156_ns = cg.esphome_ns.namespace("es8156") | ||||
| ES8156 = es8156_ns.class_("ES8156", AudioDac, cg.Component, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ES8156), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
|     .extend(i2c.i2c_device_schema(0x08)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| 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) | ||||
							
								
								
									
										87
									
								
								esphome/components/es8156/es8156.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								esphome/components/es8156/es8156.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| #include "es8156.h" | ||||
| #include "es8156_const.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include <cinttypes> | ||||
|  | ||||
| namespace esphome { | ||||
| namespace es8156 { | ||||
|  | ||||
| static const char *const TAG = "es8156"; | ||||
|  | ||||
| // Mark the component as failed; use only in setup | ||||
| #define ES8156_ERROR_FAILED(func) \ | ||||
|   if (!(func)) { \ | ||||
|     this->mark_failed(); \ | ||||
|     return; \ | ||||
|   } | ||||
|  | ||||
| void ES8156::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up ES8156..."); | ||||
|  | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG02_SCLK_MODE, 0x04)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG20_ANALOG_SYS1, 0x2A)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG21_ANALOG_SYS2, 0x3C)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG22_ANALOG_SYS3, 0x00)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG24_ANALOG_LP, 0x07)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG23_ANALOG_SYS4, 0x00)); | ||||
|  | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0A_TIME_CONTROL1, 0x01)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0B_TIME_CONTROL2, 0x01)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG11_DAC_SDP, 0x00)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG19_EQ_CONTROL1, 0x20)); | ||||
|  | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0D_P2S_CONTROL, 0x14)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG09_MISC_CONTROL2, 0x00)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG18_MISC_CONTROL3, 0x00)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG08_CLOCK_ON_OFF, 0x3F)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x02)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x03)); | ||||
|   ES8156_ERROR_FAILED(this->write_byte(ES8156_REG25_ANALOG_SYS5, 0x20)); | ||||
| } | ||||
|  | ||||
| void ES8156::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "ES8156 Audio Codec:"); | ||||
|  | ||||
|   if (this->is_failed()) { | ||||
|     ESP_LOGCONFIG(TAG, "  Failed to initialize"); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool ES8156::set_volume(float volume) { | ||||
|   volume = clamp(volume, 0.0f, 1.0f); | ||||
|   uint8_t reg = remap<uint8_t, float>(volume, 0.0f, 1.0f, 0, 255); | ||||
|   ESP_LOGV(TAG, "Setting ES8156_REG14_VOLUME_CONTROL to %u (volume: %f)", reg, volume); | ||||
|   return this->write_byte(ES8156_REG14_VOLUME_CONTROL, reg); | ||||
| } | ||||
|  | ||||
| float ES8156::volume() { | ||||
|   uint8_t reg; | ||||
|   this->read_byte(ES8156_REG14_VOLUME_CONTROL, ®); | ||||
|   return remap<float, uint8_t>(reg, 0, 255, 0.0f, 1.0f); | ||||
| } | ||||
|  | ||||
| bool ES8156::set_mute_state_(bool mute_state) { | ||||
|   uint8_t reg13; | ||||
|  | ||||
|   this->is_muted_ = mute_state; | ||||
|  | ||||
|   if (!this->read_byte(ES8156_REG13_DAC_MUTE, ®13)) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   ESP_LOGV(TAG, "Read ES8156_REG13_DAC_MUTE: %u", reg13); | ||||
|  | ||||
|   if (mute_state) { | ||||
|     reg13 |= BIT(1) | BIT(2); | ||||
|   } else { | ||||
|     reg13 &= ~(BIT(1) | BIT(2)); | ||||
|   } | ||||
|  | ||||
|   ESP_LOGV(TAG, "Setting ES8156_REG13_DAC_MUTE to %u (muted: %s)", reg13, YESNO(mute_state)); | ||||
|   return this->write_byte(ES8156_REG13_DAC_MUTE, reg13); | ||||
| } | ||||
|  | ||||
| }  // namespace es8156 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										51
									
								
								esphome/components/es8156/es8156.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								esphome/components/es8156/es8156.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/components/audio_dac/audio_dac.h" | ||||
| #include "esphome/components/i2c/i2c.h" | ||||
| #include "esphome/core/component.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace es8156 { | ||||
|  | ||||
| class ES8156 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice { | ||||
|  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_; } | ||||
|  | ||||
|  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 es8156 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										68
									
								
								esphome/components/es8156/es8156_const.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								esphome/components/es8156/es8156_const.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "es8156.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace es8156 { | ||||
|  | ||||
| /* ES8156 register addresses */ | ||||
| /* | ||||
|  * RESET Control | ||||
|  */ | ||||
| static const uint8_t ES8156_REG00_RESET = 0x00; | ||||
| /* | ||||
|  * Clock Managerment | ||||
|  */ | ||||
| static const uint8_t ES8156_REG01_MAINCLOCK_CTL = 0x01; | ||||
| static const uint8_t ES8156_REG02_SCLK_MODE = 0x02; | ||||
| static const uint8_t ES8156_REG03_LRCLK_DIV_H = 0x03; | ||||
| static const uint8_t ES8156_REG04_LRCLK_DIV_L = 0x04; | ||||
| static const uint8_t ES8156_REG05_SCLK_DIV = 0x05; | ||||
| static const uint8_t ES8156_REG06_NFS_CONFIG = 0x06; | ||||
| static const uint8_t ES8156_REG07_MISC_CONTROL1 = 0x07; | ||||
| static const uint8_t ES8156_REG08_CLOCK_ON_OFF = 0x08; | ||||
| static const uint8_t ES8156_REG09_MISC_CONTROL2 = 0x09; | ||||
| static const uint8_t ES8156_REG0A_TIME_CONTROL1 = 0x0a; | ||||
| static const uint8_t ES8156_REG0B_TIME_CONTROL2 = 0x0b; | ||||
| /* | ||||
|  * System Control | ||||
|  */ | ||||
| static const uint8_t ES8156_REG0C_CHIP_STATUS = 0x0c; | ||||
| static const uint8_t ES8156_REG0D_P2S_CONTROL = 0x0d; | ||||
| static const uint8_t ES8156_REG10_DAC_OSR_COUNTER = 0x10; | ||||
| /* | ||||
|  * SDP Control | ||||
|  */ | ||||
| static const uint8_t ES8156_REG11_DAC_SDP = 0x11; | ||||
| static const uint8_t ES8156_REG12_AUTOMUTE_SET = 0x12; | ||||
| static const uint8_t ES8156_REG13_DAC_MUTE = 0x13; | ||||
| static const uint8_t ES8156_REG14_VOLUME_CONTROL = 0x14; | ||||
|  | ||||
| /* | ||||
|  * ALC Control | ||||
|  */ | ||||
| static const uint8_t ES8156_REG15_ALC_CONFIG1 = 0x15; | ||||
| static const uint8_t ES8156_REG16_ALC_CONFIG2 = 0x16; | ||||
| static const uint8_t ES8156_REG17_ALC_CONFIG3 = 0x17; | ||||
| static const uint8_t ES8156_REG18_MISC_CONTROL3 = 0x18; | ||||
| static const uint8_t ES8156_REG19_EQ_CONTROL1 = 0x19; | ||||
| static const uint8_t ES8156_REG1A_EQ_CONTROL2 = 0x1a; | ||||
| /* | ||||
|  * Analog System Control | ||||
|  */ | ||||
| static const uint8_t ES8156_REG20_ANALOG_SYS1 = 0x20; | ||||
| static const uint8_t ES8156_REG21_ANALOG_SYS2 = 0x21; | ||||
| static const uint8_t ES8156_REG22_ANALOG_SYS3 = 0x22; | ||||
| static const uint8_t ES8156_REG23_ANALOG_SYS4 = 0x23; | ||||
| static const uint8_t ES8156_REG24_ANALOG_LP = 0x24; | ||||
| static const uint8_t ES8156_REG25_ANALOG_SYS5 = 0x25; | ||||
| /* | ||||
|  * Chip Information | ||||
|  */ | ||||
| static const uint8_t ES8156_REGFC_I2C_PAGESEL = 0xFC; | ||||
| static const uint8_t ES8156_REGFD_CHIPID1 = 0xFD; | ||||
| static const uint8_t ES8156_REGFE_CHIPID0 = 0xFE; | ||||
| static const uint8_t ES8156_REGFF_CHIP_VERSION = 0xFF; | ||||
|  | ||||
| }  // namespace es8156 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										15
									
								
								tests/components/es8156/common.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/components/es8156/common.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| esphome: | ||||
|   on_boot: | ||||
|     then: | ||||
|       - audio_dac.mute_off: | ||||
|       - audio_dac.mute_on: | ||||
|       - audio_dac.set_volume: | ||||
|           volume: 50% | ||||
|  | ||||
| i2c: | ||||
|   - id: i2c_es8156 | ||||
|     scl: ${scl_pin} | ||||
|     sda: ${sda_pin} | ||||
|  | ||||
| audio_dac: | ||||
|   - platform: es8156 | ||||
							
								
								
									
										5
									
								
								tests/components/es8156/test.esp32-ard.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/es8156/test.esp32-ard.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO16 | ||||
|   sda_pin: GPIO17 | ||||
|  | ||||
| <<: !include common.yaml | ||||
							
								
								
									
										5
									
								
								tests/components/es8156/test.esp32-c3-ard.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/es8156/test.esp32-c3-ard.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|  | ||||
| <<: !include common.yaml | ||||
							
								
								
									
										5
									
								
								tests/components/es8156/test.esp32-c3-idf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/es8156/test.esp32-c3-idf.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|  | ||||
| <<: !include common.yaml | ||||
							
								
								
									
										5
									
								
								tests/components/es8156/test.esp32-idf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/es8156/test.esp32-idf.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO16 | ||||
|   sda_pin: GPIO17 | ||||
|  | ||||
| <<: !include common.yaml | ||||
							
								
								
									
										5
									
								
								tests/components/es8156/test.esp8266-ard.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/es8156/test.esp8266-ard.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|  | ||||
| <<: !include common.yaml | ||||
		Reference in New Issue
	
	Block a user