diff --git a/components/squeezelite/.sc3357753833280144641.c b/components/squeezelite/.sc3357753833280144641.c deleted file mode 100644 index e69de29b..00000000 diff --git a/components/squeezelite/ac101/ac101.c b/components/squeezelite/ac101/ac101.c index e3bac89d..f7227e1d 100644 --- a/components/squeezelite/ac101/ac101.c +++ b/components/squeezelite/ac101/ac101.c @@ -48,118 +48,84 @@ static const char TAG[] = "AC101"; return b;\ } -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); -static void deinit(void); +static bool init(char *config, int i2c_port, i2s_config_t *i2s_config); static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode); -const struct adac_s dac_ac101 = { "AC101", init, deinit, power, speaker, headset, volume }; +const struct adac_s dac_ac101 = { "AC101", init, adac_deinit, power, speaker, headset, volume }; -static esp_err_t i2c_write_reg(uint8_t reg, uint16_t val); -static uint16_t i2c_read_reg(uint8_t reg); static void ac101_start(ac_module_t mode); static void ac101_stop(void); static void ac101_set_earph_volume(uint8_t volume); static void ac101_set_spk_volume(uint8_t volume); -static int i2c_port; - /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { - esp_err_t res = ESP_OK; - char *p; - - // configure i2c - i2c_config_t i2c_config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = -1, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = -1, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 250000, - }; - - if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); - - i2c_port = i2c_port_num; - i2c_param_config(i2c_port, &i2c_config); - i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); - - res = i2c_read_reg(CHIP_AUDIO_RS); - - if (!res) { +static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) { + adac_init(config, i2c_port); + if (adac_read_word(AC101_ADDR, CHIP_AUDIO_RS) == 0xffff) { ESP_LOGW(TAG, "No AC101 detected"); i2c_driver_delete(i2c_port); - return 0; + return false; } - res = i2c_write_reg(CHIP_AUDIO_RS, 0x123); - // huh? + ESP_LOGI(TAG, "AC101 detected"); + + adac_write_word(AC101_ADDR, CHIP_AUDIO_RS, 0x123); vTaskDelay(100 / portTICK_PERIOD_MS); // enable the PLL from BCLK source - i2c_write_reg(PLL_CTRL1, BIN(0000,0001,0100,1111)); // F=1,M=1,PLL,INT=31 (medium) - i2c_write_reg(PLL_CTRL2, BIN(1000,0110,0000,0000)); // PLL, F=96,N_i=1024-96,F=0,N_f=0*0.2; - // i2c_write_reg(PLL_CTRL2, BIN(1000,0011,1100,0000)); + adac_write_word(AC101_ADDR, PLL_CTRL1, BIN(0000,0001,0100,1111)); // F=1,M=1,PLL,INT=31 (medium) + adac_write_word(AC101_ADDR, PLL_CTRL2, BIN(1000,0110,0000,0000)); // PLL, F=96,N_i=1024-96,F=0,N_f=0*0.2; + // adac_write_word(AC101_ADDR, PLL_CTRL2, BIN(1000,0011,1100,0000)); // clocking system - i2c_write_reg(SYSCLK_CTRL, BIN(1010,1010,0000,1000)); // PLLCLK, BCLK1, IS1CLK, PLL, SYSCLK - i2c_write_reg(MOD_CLK_ENA, BIN(1000,0000,0000,1100)); // IS21, ADC, DAC - i2c_write_reg(MOD_RST_CTRL, BIN(1000,0000,0000,1100)); // IS21, ADC, DAC - i2c_write_reg(I2S_SR_CTRL, BIN(0111,0000,0000,0000)); // 44.1kHz + adac_write_word(AC101_ADDR, SYSCLK_CTRL, BIN(1010,1010,0000,1000)); // PLLCLK, BCLK1, IS1CLK, PLL, SYSCLK + adac_write_word(AC101_ADDR, MOD_CLK_ENA, BIN(1000,0000,0000,1100)); // IS21, ADC, DAC + adac_write_word(AC101_ADDR, MOD_RST_CTRL, BIN(1000,0000,0000,1100)); // IS21, ADC, DAC + adac_write_word(AC101_ADDR, I2S_SR_CTRL, BIN(0111,0000,0000,0000)); // 44.1kHz // analogue config - i2c_write_reg(I2S1LCK_CTRL, BIN(1000,1000,0101,0000)); // Slave, BCLK=I2S/8,LRCK=32,16bits,I2Smode, Stereo - i2c_write_reg(I2S1_SDOUT_CTRL, BIN(1100,0000,0000,0000)); // I2S1ADC (R&L) - i2c_write_reg(I2S1_SDIN_CTRL, BIN(1100,0000,0000,0000)); // IS21DAC (R&L) - i2c_write_reg(I2S1_MXR_SRC, BIN(0010,0010,0000,0000)); // ADCL, ADCR - i2c_write_reg(ADC_SRCBST_CTRL, BIN(0100,0100,0100,0000)); // disable all boost (default) + adac_write_word(AC101_ADDR, I2S1LCK_CTRL, BIN(1000,1000,0101,0000)); // Slave, BCLK=I2S/8,LRCK=32,16bits,I2Smode, Stereo + adac_write_word(AC101_ADDR, I2S1_SDOUT_CTRL, BIN(1100,0000,0000,0000)); // I2S1ADC (R&L) + adac_write_word(AC101_ADDR, I2S1_SDIN_CTRL, BIN(1100,0000,0000,0000)); // IS21DAC (R&L) + adac_write_word(AC101_ADDR, I2S1_MXR_SRC, BIN(0010,0010,0000,0000)); // ADCL, ADCR + adac_write_word(AC101_ADDR, ADC_SRCBST_CTRL, BIN(0100,0100,0100,0000)); // disable all boost (default) #if ENABLE_ADC - i2c_write_reg(ADC_SRC, BIN(0000,0100,0000,1000)); // source=linein(R/L) - i2c_write_reg(ADC_DIG_CTRL, BIN(1000,0000,0000,0000)); // enable digital ADC - i2c_write_reg(ADC_ANA_CTRL, BIN(1011, 1011,0000,0000)); // enable analogue R/L, 0dB + adac_write_word(AC101_ADDR, ADC_SRC, BIN(0000,0100,0000,1000)); // source=linein(R/L) + adac_write_word(AC101_ADDR, ADC_DIG_CTRL, BIN(1000,0000,0000,0000)); // enable digital ADC + adac_write_word(AC101_ADDR, ADC_ANA_CTRL, BIN(1011, 1011,0000,0000)); // enable analogue R/L, 0dB #else - i2c_write_reg(ADC_SRC, BIN(0000,0000,0000,0000)); // source=none - i2c_write_reg(ADC_DIG_CTRL, BIN(0000,0000,0000,0000)); // disable digital ADC - i2c_write_reg(ADC_ANA_CTRL, BIN(0011, 0011,0000,0000)); // disable analogue R/L, 0dB + adac_write_word(AC101_ADDR, ADC_SRC, BIN(0000,0000,0000,0000)); // source=none + adac_write_word(AC101_ADDR, ADC_DIG_CTRL, BIN(0000,0000,0000,0000)); // disable digital ADC + adac_write_word(AC101_ADDR, ADC_ANA_CTRL, BIN(0011, 0011,0000,0000)); // disable analogue R/L, 0dB #endif //Path Configuration - i2c_write_reg(DAC_MXR_SRC, BIN(1000,1000,0000,0000)); // DAC from I2S - i2c_write_reg(DAC_DIG_CTRL, BIN(1000,0000,0000,0000)); // enable DAC - i2c_write_reg(OMIXER_DACA_CTRL, BIN(1111,0000,0000,0000)); // enable DAC/Analogue (see note on offset removal and PA) - i2c_write_reg(OMIXER_DACA_CTRL, BIN(1111,1111,0000,0000)); // this toggle is needed for headphone PA offset + adac_write_word(AC101_ADDR, DAC_MXR_SRC, BIN(1000,1000,0000,0000)); // DAC from I2S + adac_write_word(AC101_ADDR, DAC_DIG_CTRL, BIN(1000,0000,0000,0000)); // enable DAC + adac_write_word(AC101_ADDR, OMIXER_DACA_CTRL, BIN(1111,0000,0000,0000)); // enable DAC/Analogue (see note on offset removal and PA) + adac_write_word(AC101_ADDR, OMIXER_DACA_CTRL, BIN(1111,1111,0000,0000)); // this toggle is needed for headphone PA offset #if ENABLE_ADC - i2c_write_reg(OMIXER_SR, BIN(0000,0001,0000,0010)); // source=DAC(R/L) (are DACR and DACL really inverted in bitmap?) + adac_write_word(AC101_ADDR, OMIXER_SR, BIN(0000,0001,0000,0010)); // source=DAC(R/L) (are DACR and DACL really inverted in bitmap?) #else - i2c_write_reg(OMIXER_SR, BIN(0000,0101,0000,1010)); // source=DAC(R/L) and LINEIN(R/L) + adac_write_word(AC101_ADDR, OMIXER_SR, BIN(0000,0101,0000,1010)); // source=DAC(R/L) and LINEIN(R/L) #endif // enable earphone & speaker - i2c_write_reg(SPKOUT_CTRL, 0x0220); - i2c_write_reg(HPOUT_CTRL, 0xf801); + adac_write_word(AC101_ADDR, SPKOUT_CTRL, 0x0220); + adac_write_word(AC101_ADDR, HPOUT_CTRL, 0xf801); // set gain for speaker and earphone ac101_set_spk_volume(100); ac101_set_earph_volume(100); - ESP_LOGI(TAG, "AC101 uses I2C sda:%d, scl:%d", i2c_config.sda_io_num, i2c_config.scl_io_num); - - return (res == ESP_OK); + return true; } -/**************************************************************************************** - * init - */ -static void deinit(void) { - i2c_driver_delete(i2c_port); -} - /**************************************************************************************** * change volume */ @@ -190,9 +156,9 @@ static void power(adac_power_e mode) { * speaker */ static void speaker(bool active) { - uint16_t value = i2c_read_reg(SPKOUT_CTRL); - if (active) i2c_write_reg(SPKOUT_CTRL, value | SPKOUT_EN); - else i2c_write_reg(SPKOUT_CTRL, value & ~SPKOUT_EN); + uint16_t value = adac_read_word(AC101_ADDR, SPKOUT_CTRL); + if (active) adac_write_word(AC101_ADDR, SPKOUT_CTRL, value | SPKOUT_EN); + else adac_write_word(AC101_ADDR, SPKOUT_CTRL, value & ~SPKOUT_EN); } /**************************************************************************************** @@ -200,51 +166,11 @@ static void speaker(bool active) { */ static void headset(bool active) { // there might be aneed to toggle OMIXER_DACA_CTRL 11:8, not sure - uint16_t value = i2c_read_reg(HPOUT_CTRL); - if (active) i2c_write_reg(HPOUT_CTRL, value | EAROUT_EN); - else i2c_write_reg(HPOUT_CTRL, value & ~EAROUT_EN); + uint16_t value = adac_read_word(AC101_ADDR, HPOUT_CTRL); + if (active) adac_write_word(AC101_ADDR, HPOUT_CTRL, value | EAROUT_EN); + else adac_write_word(AC101_ADDR, HPOUT_CTRL, value & ~EAROUT_EN); } -/**************************************************************************************** - * - */ -static esp_err_t i2c_write_reg(uint8_t reg, uint16_t val) -{ - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - esp_err_t ret =0; - uint8_t send_buff[4]; - send_buff[0] = (AC101_ADDR << 1); - send_buff[1] = reg; - send_buff[2] = (val>>8) & 0xff; - send_buff[3] = val & 0xff; - ret |= i2c_master_start(cmd); - ret |= i2c_master_write(cmd, send_buff, 4, ACK_CHECK_EN); - ret |= i2c_master_stop(cmd); - ret |= i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - return ret; -} - -/**************************************************************************************** - * - */ -static uint16_t i2c_read_reg(uint8_t reg) { - uint8_t data[2] = { 0 }; - - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( AC101_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( AC101_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN); //check or not - i2c_master_read(cmd, data, 2, ACK_VAL); - i2c_master_stop(cmd); - i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - - return (data[0] << 8) + data[1];; -} - /**************************************************************************************** * */ @@ -264,7 +190,7 @@ void set_sample_rate(int rate) { ESP_LOGW(TAG, "Unknown sample rate %hu", rate); rate = SAMPLE_RATE_44100; } - i2c_write_reg(I2S_SR_CTRL, rate); + adac_write_word(AC101_ADDR, I2S_SR_CTRL, rate); } /**************************************************************************************** @@ -273,8 +199,8 @@ void set_sample_rate(int rate) { static void ac101_set_spk_volume(uint8_t volume) { uint16_t value = max(volume, 100); value = ((int) value * 0x1f) / 100; - value |= i2c_read_reg(SPKOUT_CTRL) & ~0x1f; - i2c_write_reg(SPKOUT_CTRL, value); + value |= adac_read_word(AC101_ADDR, SPKOUT_CTRL) & ~0x1f; + adac_write_word(AC101_ADDR, SPKOUT_CTRL, value); } /**************************************************************************************** @@ -283,8 +209,8 @@ static void ac101_set_spk_volume(uint8_t volume) { static void ac101_set_earph_volume(uint8_t volume) { uint16_t value = max(volume, 100); value = (((int) value * 0x3f) / 100) << 4; - value |= i2c_read_reg(HPOUT_CTRL) & ~(0x3f << 4); - i2c_write_reg(HPOUT_CTRL, value); + value |= adac_read_word(AC101_ADDR, HPOUT_CTRL) & ~(0x3f << 4); + adac_write_word(AC101_ADDR, HPOUT_CTRL, value); } #if 0 @@ -292,14 +218,14 @@ static void ac101_set_earph_volume(uint8_t volume) { * Get normalized (0..100) speaker volume */ static int ac101_get_spk_volume(void) { - return ((i2c_read_reg(SPKOUT_CTRL) & 0x1f) * 100) / 0x1f; + return ((adac_read_word(AC101_ADDR, SPKOUT_CTRL) & 0x1f) * 100) / 0x1f; } /**************************************************************************************** * Get normalized (0..100) earphone volume */ static int ac101_get_earph_volume(void) { - return (((i2c_read_reg(HPOUT_CTRL) >> 4) & 0x3f) * 100) / 0x3f; + return (((adac_read_word(AC101_ADDR, HPOUT_CTRL) >> 4) & 0x3f) * 100) / 0x3f; } /**************************************************************************************** @@ -308,7 +234,7 @@ static int ac101_get_earph_volume(void) { static void ac101_set_output_mixer_gain(ac_output_mixer_gain_t gain,ac_output_mixer_source_t source) { uint16_t regval,temp,clrbit; - regval = i2c_read_reg(OMIXER_BST1_CTRL); + regval = adac_read_word(AC101_ADDR, OMIXER_BST1_CTRL); switch(source){ case SRC_MIC1: temp = (gain&0x7) << 6; @@ -327,14 +253,15 @@ static void ac101_set_output_mixer_gain(ac_output_mixer_gain_t gain,ac_output_mi } regval &= clrbit; regval |= temp; - i2c_write_reg(OMIXER_BST1_CTRL,regval); + adac_write_word(AC101_ADDR, OMIXER_BST1_CTRL,regval); } /**************************************************************************************** * */ -static void ac101_deinit(void) { - i2c_write_reg(CHIP_AUDIO_RS, 0x123); //soft reset +static void deinit(void) { + adac_write_word(AC101_ADDR, CHIP_AUDIO_RS, 0x123); //soft reset + adac_deinit(); } /**************************************************************************************** @@ -342,11 +269,11 @@ static void ac101_deinit(void) { */ static void ac101_i2s_config_clock(ac_i2s_clock_t *cfg) { uint16_t regval=0; - regval = i2c_read_reg(I2S1LCK_CTRL); + regval = adac_read_word(AC101_ADDR, I2S1LCK_CTRL); regval &= 0xe03f; regval |= (cfg->bclk_div << 9); regval |= (cfg->lclk_div << 6); - i2c_write_reg(I2S1LCK_CTRL, regval); + adac_write_word(AC101_ADDR, I2S1LCK_CTRL, regval); } #endif @@ -356,21 +283,21 @@ static void ac101_i2s_config_clock(ac_i2s_clock_t *cfg) { */ static void ac101_start(ac_module_t mode) { if (mode == AC_MODULE_LINE) { - i2c_write_reg(0x51, 0x0408); - i2c_write_reg(0x40, 0x8000); - i2c_write_reg(0x50, 0x3bc0); + adac_write_word(AC101_ADDR, 0x51, 0x0408); + adac_write_word(AC101_ADDR, 0x40, 0x8000); + adac_write_word(AC101_ADDR, 0x50, 0x3bc0); } if (mode == AC_MODULE_ADC || mode == AC_MODULE_ADC_DAC || mode == AC_MODULE_LINE) { // I2S1_SDOUT_CTRL - // i2c_write_reg(PLL_CTRL2, 0x8120); - i2c_write_reg(0x04, 0x800c); - i2c_write_reg(0x05, 0x800c); - // res |= i2c_write_reg(0x06, 0x3000); + // adac_write_word(AC101_ADDR, PLL_CTRL2, 0x8120); + adac_write_word(AC101_ADDR, 0x04, 0x800c); + adac_write_word(AC101_ADDR, 0x05, 0x800c); + // res |= adac_write_word(AC101_ADDR, 0x06, 0x3000); } if (mode == AC_MODULE_DAC || mode == AC_MODULE_ADC_DAC || mode == AC_MODULE_LINE) { - uint16_t value = i2c_read_reg(PLL_CTRL2); + uint16_t value = adac_read_word(AC101_ADDR, PLL_CTRL2); value |= 0x8000; - i2c_write_reg(PLL_CTRL2, value); + adac_write_word(AC101_ADDR, PLL_CTRL2, value); } } @@ -378,8 +305,8 @@ static void ac101_start(ac_module_t mode) { * */ static void ac101_stop(void) { - uint16_t value = i2c_read_reg(PLL_CTRL2); + uint16_t value = adac_read_word(AC101_ADDR, PLL_CTRL2); value &= ~0x8000; - i2c_write_reg(PLL_CTRL2, value); + adac_write_word(AC101_ADDR, PLL_CTRL2, value); } diff --git a/components/squeezelite/adac.h b/components/squeezelite/adac.h index 369b0071..eeaa5d9c 100644 --- a/components/squeezelite/adac.h +++ b/components/squeezelite/adac.h @@ -11,6 +11,7 @@ #include "freertos/FreeRTOS.h" #include "driver/i2s.h" +#include "driver/i2c.h" typedef enum { ADAC_ON = 0, ADAC_STANDBY, ADAC_OFF } adac_power_e; @@ -28,3 +29,10 @@ extern const struct adac_s dac_tas57xx; extern const struct adac_s dac_tas5713; extern const struct adac_s dac_ac101; extern const struct adac_s dac_external; + +int adac_init(char *config, int i2c_port); +void adac_deinit(void); +esp_err_t adac_write_byte(int i2c_addr, uint8_t reg, uint8_t val); +esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val); +uint8_t adac_read_byte(int i2c_addr, uint8_t reg); +uint16_t adac_read_word(int i2c_addr, uint8_t reg); diff --git a/components/squeezelite/adac_core.c b/components/squeezelite/adac_core.c new file mode 100644 index 00000000..e83c2214 --- /dev/null +++ b/components/squeezelite/adac_core.c @@ -0,0 +1,164 @@ +/* + * Squeezelite for esp32 + * + * (c) Sebastien 2019 + * Philippe G. 2019, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + */ + +#include +#include +#include +#include +#include "driver/i2c.h" +#include "esp_log.h" +#include "adac.h" + +static const char TAG[] = "DAC core"; +static int i2c_port = -1; + +/**************************************************************************************** + * init + */ +int adac_init(char *config, int i2c_port_num) { + char *p; + int i2c_addr = 0; + i2c_port = i2c_port_num; + + // configure i2c + i2c_config_t i2c_config = { + .mode = I2C_MODE_MASTER, + .sda_io_num = -1, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_io_num = -1, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 250000, + }; + + if ((p = strcasestr(config, "i2c")) != NULL) i2c_addr = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); + + if (i2c_config.sda_io_num == -1 || i2c_config.scl_io_num == -1) { + ESP_LOGW(TAG, "DAC does not use i2c"); + return i2c_addr; + } + + ESP_LOGI(TAG, "DAC uses I2C port:%d, sda:%d, scl:%d", i2c_port, i2c_config.sda_io_num, i2c_config.scl_io_num); + + // we have an I2C configured + i2c_param_config(i2c_port, &i2c_config); + i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); + + return i2c_addr; +} + +/**************************************************************************************** + * close + */ +void adac_deinit(void) { + if (i2c_port != -1) i2c_driver_delete(i2c_port); +} + +/**************************************************************************************** + * + */ +esp_err_t adac_write_byte(int i2c_addr,uint8_t reg, uint8_t val) { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); + i2c_master_write_byte(cmd, val, I2C_MASTER_NACK); + + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + if (ret != ESP_OK) { + ESP_LOGW(TAG, "I2C write failed"); + } + + return ret; +} + +/**************************************************************************************** + * + */ +uint8_t adac_read_byte(int i2c_addr, uint8_t reg) { + uint8_t data = 255; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); + i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK); + + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + if (ret != ESP_OK) { + ESP_LOGW(TAG, "I2C read failed"); + } + + return data; +} + +/**************************************************************************************** + * + */ +uint16_t adac_read_word(int i2c_addr, uint8_t reg) { + uint8_t data[2] = { 255, 255 }; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); + i2c_master_read(cmd, data, 2, I2C_MASTER_NACK); + + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + if (ret != ESP_OK) { + ESP_LOGW(TAG, "I2C read failed"); + } + + return (data[0] << 8) | data[1]; +} + +/**************************************************************************************** + * + */ +esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val) +{ + uint8_t data[] = { i2c_addr << 1, reg, + val >> 8, val & 0xff }; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write(cmd, data, 4, I2C_MASTER_NACK); + + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + if (ret != ESP_OK) { + ESP_LOGW(TAG, "I2C write failed"); + } + + return ret; +} \ No newline at end of file diff --git a/components/squeezelite/external/dac_external.c b/components/squeezelite/external/dac_external.c index 60242a7d..0694ab51 100644 --- a/components/squeezelite/external/dac_external.c +++ b/components/squeezelite/external/dac_external.c @@ -20,7 +20,6 @@ static const char TAG[] = "DAC external"; -static void deinit(void) { } static void speaker(bool active) { } static void headset(bool active) { } static bool volume(unsigned left, unsigned right) { return false; } @@ -28,48 +27,30 @@ static void power(adac_power_e mode); static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); static bool i2c_json_execute(char *set); -static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val); -static uint8_t i2c_read_reg(uint8_t reg); -const struct adac_s dac_external = { "i2s", init, deinit, power, speaker, headset, volume }; -static int i2c_port, i2c_addr; +const struct adac_s dac_external = { "i2s", init, adac_deinit, power, speaker, headset, volume }; static cJSON *i2c_json; +static int i2c_addr; /**************************************************************************************** * init */ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { char *p; - i2c_port = i2c_port_num; - // configure i2c - i2c_config_t i2c_config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = -1, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = -1, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 250000, - }; - - if ((p = strcasestr(config, "i2c")) != NULL) i2c_addr = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); - + i2c_addr = adac_init(config, i2c_port_num); + if (!i2c_addr) return false; + + ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr); + p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL); i2c_json = cJSON_Parse(p); - if (!i2c_addr || !i2c_json || i2c_config.sda_io_num == -1 || i2c_config.scl_io_num == -1) { + if (!i2c_json) { if (p) free(p); - ESP_LOGW(TAG, "No i2c controlset found"); + ESP_LOGW(TAG, "no i2c controlset found"); return true; } - - ESP_LOGI(TAG, "DAC uses I2C @%d with sda:%d, scl:%d", i2c_addr, i2c_config.sda_io_num, i2c_config.scl_io_num); - - // we have an I2C configured - i2c_param_config(i2c_port, &i2c_config); - i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); if (!i2c_json_execute("init")) { ESP_LOGE(TAG, "could not intialize DAC"); @@ -105,70 +86,17 @@ bool i2c_json_execute(char *set) { if (!reg || !val) continue; if (!mode) { - i2c_write_reg(reg->valueint, val->valueint); + adac_write_byte(i2c_addr, reg->valueint, val->valueint); } else if (!strcasecmp(mode->valuestring, "or")) { - uint8_t data = i2c_read_reg(reg->valueint); + uint8_t data = adac_read_byte(i2c_addr,reg->valueint); data |= (uint8_t) val->valueint; - i2c_write_reg(reg->valueint, data); + adac_write_byte(i2c_addr, reg->valueint, data); } else if (!strcasecmp(mode->valuestring, "and")) { - uint8_t data = i2c_read_reg(reg->valueint); + uint8_t data = adac_read_byte(i2c_addr, reg->valueint); data &= (uint8_t) val->valueint; - i2c_write_reg(reg->valueint, data); + adac_write_byte(i2c_addr, reg->valueint, data); } } return true; } - -/**************************************************************************************** - * - */ -static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val) { - esp_err_t ret; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - - i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); - i2c_master_write_byte(cmd, val, I2C_MASTER_NACK); - - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - ESP_LOGW(TAG, "I2C write failed"); - } - - return ret; -} - -/**************************************************************************************** - * - */ -static uint8_t i2c_read_reg(uint8_t reg) { - esp_err_t ret; - uint8_t data = 0; - - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - - i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); - i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK); - - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - ESP_LOGW(TAG, "I2C read failed"); - } - - return data; -} - - diff --git a/components/squeezelite/helix-aac.c b/components/squeezelite/helix-aac.c index 723db9ff..f2a48287 100644 --- a/components/squeezelite/helix-aac.c +++ b/components/squeezelite/helix-aac.c @@ -158,10 +158,11 @@ static int read_mp4_header(unsigned long *samplerate_p, unsigned char *channels_ info.sampRateCore = rates[info.sampRateCore]; info.nChans = (*ptr++ & 0x7f) >> 3; *channels_p = info.nChans; - *samplerate_p = info.sampRateCore; if (desc_len > 2 && ((ptr[0] << 3) | (ptr[1] >> 5)) == 0x2b7 && (ptr[1] & 0x1f) == 0x05 && (ptr[2] & 0x80)) { - LOG_WARN("AAC SBR mode activated => high CPU consumption (please proxy)"); *samplerate_p = rates[(ptr[2] & 0x78) >> 3]; + LOG_WARN("AAC SBR mode activated => high CPU consumption expected, please use LMS proxy to mitigate"); + } else { + *samplerate_p = info.sampRateCore; } HAAC(a, SetRawBlockParams, a->hAac, 0, &info); LOG_DEBUG("playable aac track: %u (p:%x, r:%d, c:%d)", trak, info.profile, info.sampRateCore, info.nChans); diff --git a/components/squeezelite/tas57xx/dac_5713.c b/components/squeezelite/tas57xx/dac_5713.c index 135fa6f7..7bc77f9d 100644 --- a/components/squeezelite/tas57xx/dac_5713.c +++ b/components/squeezelite/tas57xx/dac_5713.c @@ -20,7 +20,7 @@ #include "adac.h" #define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) -#define TAS5713 0x36 /* i2c address of TAS5713 */ +#define TAS5713 (0x36 >> 1) /* i2c address of TAS5713 */ // TAS5713 I2C-bus register addresses @@ -40,13 +40,12 @@ static const char TAG[] = "TAS5713"; static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); -static void deinit(void); static void speaker(bool active) { }; static void headset(bool active) { } ; static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode) { }; -const struct adac_s dac_tas5713 = {"TAS5713", init, deinit, power, speaker, headset, volume}; +const struct adac_s dac_tas5713 = {"TAS5713", init, adac_deinit, power, speaker, headset, volume}; struct tas5713_cmd_s { uint8_t reg; @@ -63,53 +62,30 @@ typedef enum { TAS57_VOLUME } dac_cmd_e; -static int i2c_port; - -static void tas5713_set(uint8_t reg, uint8_t val); -static uint8_t tas5713_get(uint8_t reg); - /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { - char *p; - i2c_port = i2c_port_num; - - // configure i2c - i2c_config_t i2c_config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = -1, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = -1, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 250000, - }; - - if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); - - i2c_param_config(i2c_port, &i2c_config); - esp_err_t res = i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); - - /* find if there is a tas5713 attached. Reg 0 should read non-zero if so */ - if (!tas5713_get(0x00)) { +static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) { + /* find if there is a tas5713 attached. Reg 0 should read non-zero but not 255 if so */ + adac_init(config, i2c_port); + if (adac_read_byte(TAS5713, 0x00) == 255) { ESP_LOGW(TAG, "No TAS5713 detected"); - i2c_driver_delete(i2c_port); + adac_deinit(); return 0; } - ESP_LOGI(TAG, "TAS5713 uses I2C sda:%d, scl:%d", i2c_config.sda_io_num, i2c_config.scl_io_num); + ESP_LOGI(TAG, "TAS5713 found"); /* do the init sequence */ - tas5713_set(TAS5713_OSC_TRIM, 0x00); /* a delay is required after this */ + esp_err_t res = adac_write_byte(TAS5713, TAS5713_OSC_TRIM, 0x00); /* a delay is required after this */ vTaskDelay(50 / portTICK_PERIOD_MS); - tas5713_set(TAS5713_SERIAL_DATA_INTERFACE, 0x03); /* I2S LJ 16 bit */ - tas5713_set(TAS5713_SYSTEM_CTRL2, 0x00); /* exit all channel shutdown */ - tas5713_set(TAS5713_SOFT_MUTE, 0x00); /* unmute */ - tas5713_set(TAS5713_VOL_MASTER, 0x20); - tas5713_set(TAS5713_VOL_CH1, 0x30); - tas5713_set(TAS5713_VOL_CH2, 0x30); - tas5713_set(TAS5713_VOL_HEADPHONE, 0xFF); + res |= adac_write_byte(TAS5713, TAS5713_SERIAL_DATA_INTERFACE, 0x03); /* I2S LJ 16 bit */ + res |= adac_write_byte(TAS5713, TAS5713_SYSTEM_CTRL2, 0x00); /* exit all channel shutdown */ + res |= adac_write_byte(TAS5713, TAS5713_SOFT_MUTE, 0x00); /* unmute */ + res |= adac_write_byte(TAS5713, TAS5713_VOL_MASTER, 0x20); + res |= adac_write_byte(TAS5713, TAS5713_VOL_CH1, 0x30); + res |= adac_write_byte(TAS5713, TAS5713_VOL_CH2, 0x30); + res |= adac_write_byte(TAS5713, TAS5713_VOL_HEADPHONE, 0xFF); /* The tas5713 typically has the mclk connected to the sclk. In this configuration, mclk must be a multiple of the sclk. The lowest workable @@ -126,70 +102,9 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { return true; } -/**************************************************************************************** - * init - */ -static void deinit(void) { - i2c_driver_delete(i2c_port); -} - /**************************************************************************************** * change volume */ static bool volume(unsigned left, unsigned right) { return false; } - - -/**************************************************************************************** - * DAC specific commands - */ -void tas5713_set(uint8_t reg, uint8_t val) { - esp_err_t ret = ESP_OK; - - ESP_LOGI(TAG,"TAS5713 send %x %x", reg, val); - i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); - - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, - TAS5713 | I2C_MASTER_WRITE, - I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, reg, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, val, I2C_MASTER_NACK); - i2c_master_stop(i2c_cmd); - ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_RATE_MS); - - i2c_cmd_link_delete(i2c_cmd); - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Could not send command to TAS5713 %d", ret); - } -} - -/************************************************************************* - * Read from i2c for the tas5713. This doubles as tas5713 detect. This function - * returns zero on error, so read register 0x00 for tas detect, which will be - * non-zero in this application. - */ -static uint8_t tas5713_get(uint8_t reg) { - int ret; - uint8_t data = 0; - i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); - - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, TAS5713 | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, reg, I2C_MASTER_NACK); - - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, TAS5713 | I2C_MASTER_READ, I2C_MASTER_NACK); - i2c_master_read_byte(i2c_cmd, &data, I2C_MASTER_NACK); - - i2c_master_stop(i2c_cmd); - ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_RATE_MS); - i2c_cmd_link_delete(i2c_cmd); - - if (ret == ESP_OK) { - ESP_LOGI(TAG,"TAS5713 reg 0x%x is 0x%x", reg, data); - } - return data; -} diff --git a/components/squeezelite/tas57xx/dac_57xx.c b/components/squeezelite/tas57xx/dac_57xx.c index aa0fac3a..b585ede4 100644 --- a/components/squeezelite/tas57xx/dac_57xx.c +++ b/components/squeezelite/tas57xx/dac_57xx.c @@ -18,19 +18,18 @@ #include "esp_log.h" #include "adac.h" -#define TAS575x 0x98 -#define TAS578x 0x90 +#define TAS575x (0x98 >> 1) +#define TAS578x (0x90 >> 1) static const char TAG[] = "TAS575x/8x"; static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); -static void deinit(void); static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode); -const struct adac_s dac_tas57xx = { "TAS57xx", init, deinit, power, speaker, headset, volume }; +const struct adac_s dac_tas57xx = { "TAS57xx", init, adac_deinit, power, speaker, headset, volume }; struct tas57xx_cmd_s { uint8_t reg; @@ -60,7 +59,7 @@ static const struct tas57xx_cmd_s tas57xx_cmd[] = { }; static uint8_t tas57_addr; -static int i2c_port; + int i2c_port_x; static void dac_cmd(dac_cmd_e cmd, ...); static int tas57_detect(void); @@ -68,32 +67,15 @@ static int tas57_detect(void); /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { - char *p; - i2c_port = i2c_port_num; - - // configure i2c - i2c_config_t i2c_config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = -1, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = -1, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 250000, - }; - - if ((p = strcasestr(config, "sda")) != NULL) i2c_config.sda_io_num = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "scl")) != NULL) i2c_config.scl_io_num = atoi(strchr(p, '=') + 1); - - i2c_param_config(i2c_port, &i2c_config); - i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); - +static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) { // find which TAS we are using (if any) +i2c_port_x = i2c_port; + adac_init(config, i2c_port); tas57_addr = tas57_detect(); - + if (!tas57_addr) { ESP_LOGW(TAG, "No TAS57xx detected"); - i2c_driver_delete(i2c_port); + adac_deinit(); return false; } @@ -101,7 +83,7 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { for (int i = 0; tas57xx_init_sequence[i].reg != 0xff; i++) { i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, tas57_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(i2c_cmd, (tas57_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); i2c_master_write_byte(i2c_cmd, tas57xx_init_sequence[i].reg, I2C_MASTER_NACK); i2c_master_write_byte(i2c_cmd, tas57xx_init_sequence[i].value, I2C_MASTER_NACK); ESP_LOGD(TAG, "i2c write %x at %u", tas57xx_init_sequence[i].reg, tas57xx_init_sequence[i].value); @@ -110,8 +92,6 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { i2c_master_stop(i2c_cmd); esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_RATE_MS); i2c_cmd_link_delete(i2c_cmd); - - ESP_LOGI(TAG, "TAS57xx uses I2C sda:%d, scl:%d", i2c_config.sda_io_num, i2c_config.scl_io_num); if (res != ESP_OK) { ESP_LOGE(TAG, "could not intialize TAS57xx %d", res); @@ -121,13 +101,6 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config) { return true; } -/**************************************************************************************** - * init - */ -static void deinit(void) { - i2c_driver_delete(i2c_port); -} - /**************************************************************************************** * change volume */ @@ -176,25 +149,17 @@ void dac_cmd(dac_cmd_e cmd, ...) { esp_err_t ret = ESP_OK; va_start(args, cmd); - i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); switch(cmd) { case TAS57_VOLUME: ESP_LOGE(TAG, "DAC volume not handled yet"); break; default: - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, tas57_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, tas57xx_cmd[cmd].reg, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, tas57xx_cmd[cmd].value, I2C_MASTER_NACK); - i2c_master_stop(i2c_cmd); - ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_RATE_MS); + ret = adac_write_byte(tas57_addr, tas57xx_cmd[cmd].reg, tas57xx_cmd[cmd].value); } - i2c_cmd_link_delete(i2c_cmd); - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "could not intialize TAS57xx %d", ret); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "could not use TAS57xx %d", ret); } va_end(args); @@ -204,25 +169,10 @@ void dac_cmd(dac_cmd_e cmd, ...) { * TAS57 detection */ static int tas57_detect(void) { - uint8_t data, addr[] = {TAS578x, TAS575x}; - int ret; + uint8_t addr[] = {TAS578x, TAS575x}; for (int i = 0; i < sizeof(addr); i++) { - i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); - - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, addr[i] | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, 00, I2C_MASTER_NACK); - - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, addr[i] | I2C_MASTER_READ, I2C_MASTER_NACK); - i2c_master_read_byte(i2c_cmd, &data, I2C_MASTER_NACK); - - i2c_master_stop(i2c_cmd); - ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_RATE_MS); - i2c_cmd_link_delete(i2c_cmd); - - if (ret == ESP_OK) { + if (adac_read_byte(addr[i], 0) != 255) { ESP_LOGI(TAG, "Detected TAS @0x%x", addr[i]); return addr[i]; }