mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +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/ens160_spi/* @latonita | ||||||
| esphome/components/ens210/* @itn3rd77 | esphome/components/ens210/* @itn3rd77 | ||||||
| esphome/components/es7210/* @kahrendt | esphome/components/es7210/* @kahrendt | ||||||
|  | esphome/components/es8156/* @kbx81 | ||||||
| esphome/components/es8311/* @kahrendt @kroimon | esphome/components/es8311/* @kahrendt @kroimon | ||||||
| esphome/components/esp32/* @esphome/core | esphome/components/esp32/* @esphome/core | ||||||
| esphome/components/esp32_ble/* @Rapsssito @jesserockz | 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