mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-02-01 23:30:54 +03:00
new cspot/bell
This commit is contained in:
@@ -2,45 +2,42 @@
|
||||
|
||||
#include "driver/i2s.h"
|
||||
|
||||
AC101AudioSink::AC101AudioSink()
|
||||
{
|
||||
// Disable software volume control, all handled by ::volumeChanged
|
||||
softwareVolumeControl = false;
|
||||
AC101AudioSink::AC101AudioSink() {
|
||||
// Disable software volume control, all handled by ::volumeChanged
|
||||
softwareVolumeControl = false;
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
i2s_config_t i2s_config = {
|
||||
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true //Auto clear tx descriptor on underflow
|
||||
};
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true //Auto clear tx descriptor on underflow
|
||||
};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 26,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 26,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
|
||||
dac = &dac_a1s;
|
||||
dac = &dac_a1s;
|
||||
|
||||
dac->init(0, 0, &i2s_config);
|
||||
dac->speaker(false);
|
||||
dac->power(ADAC_ON);
|
||||
dac->init(0, 0, &i2s_config);
|
||||
dac->speaker(false);
|
||||
dac->power(ADAC_ON);
|
||||
|
||||
startI2sFeed();
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
AC101AudioSink::~AC101AudioSink()
|
||||
{
|
||||
}
|
||||
AC101AudioSink::~AC101AudioSink() {}
|
||||
|
||||
void AC101AudioSink::volumeChanged(uint16_t volume) {
|
||||
dac->volume(volume, volume);
|
||||
dac->volume(volume, volume);
|
||||
}
|
||||
|
||||
@@ -1,47 +1,45 @@
|
||||
#include "BufferedAudioSink.h"
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
RingbufHandle_t dataBuffer;
|
||||
|
||||
static void i2sFeed(void *pvParameters)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
size_t itemSize;
|
||||
char *item = (char *)xRingbufferReceiveUpTo(dataBuffer, &itemSize, portMAX_DELAY, 512);
|
||||
if (item != NULL)
|
||||
{
|
||||
size_t written = 0;
|
||||
while (written < itemSize)
|
||||
{
|
||||
i2s_write((i2s_port_t)0, item, itemSize, &written, portMAX_DELAY);
|
||||
}
|
||||
vRingbufferReturnItem(dataBuffer, (void *)item);
|
||||
}
|
||||
static void i2sFeed(void* pvParameters) {
|
||||
while (true) {
|
||||
size_t itemSize;
|
||||
char* item = (char*)xRingbufferReceiveUpTo(dataBuffer, &itemSize,
|
||||
portMAX_DELAY, 512);
|
||||
if (item != NULL) {
|
||||
size_t written = 0;
|
||||
while (written < itemSize) {
|
||||
i2s_write((i2s_port_t)0, item, itemSize, &written, portMAX_DELAY);
|
||||
}
|
||||
vRingbufferReturnItem(dataBuffer, (void*)item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedAudioSink::startI2sFeed(size_t buf_size)
|
||||
{
|
||||
dataBuffer = xRingbufferCreate(buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
xTaskCreatePinnedToCore(&i2sFeed, "i2sFeed", 4096, NULL, 10, NULL, tskNO_AFFINITY);
|
||||
void BufferedAudioSink::startI2sFeed(size_t buf_size) {
|
||||
dataBuffer = xRingbufferCreate(buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
xTaskCreatePinnedToCore(&i2sFeed, "i2sFeed", 4096, NULL, 10, NULL,
|
||||
tskNO_AFFINITY);
|
||||
}
|
||||
|
||||
void BufferedAudioSink::feedPCMFrames(const uint8_t *buffer, size_t bytes)
|
||||
{
|
||||
feedPCMFramesInternal(buffer, bytes);
|
||||
void BufferedAudioSink::feedPCMFrames(const uint8_t* buffer, size_t bytes) {
|
||||
feedPCMFramesInternal(buffer, bytes);
|
||||
}
|
||||
|
||||
void BufferedAudioSink::feedPCMFramesInternal(const void *pvItem, size_t xItemSize)
|
||||
{
|
||||
xRingbufferSend(dataBuffer, pvItem, xItemSize, portMAX_DELAY);
|
||||
void BufferedAudioSink::feedPCMFramesInternal(const void* pvItem,
|
||||
size_t xItemSize) {
|
||||
xRingbufferSend(dataBuffer, pvItem, xItemSize, portMAX_DELAY);
|
||||
}
|
||||
|
||||
bool BufferedAudioSink::setParams(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) {
|
||||
// TODO override this for sinks with custom mclk
|
||||
i2s_set_clk((i2s_port_t)0, sampleRate, (i2s_bits_per_sample_t)bitDepth, (i2s_channel_t)channelCount);
|
||||
return true;
|
||||
bool BufferedAudioSink::setParams(uint32_t sampleRate, uint8_t channelCount,
|
||||
uint8_t bitDepth) {
|
||||
// TODO override this for sinks with custom mclk
|
||||
i2s_set_clk((i2s_port_t)0, sampleRate, (i2s_bits_per_sample_t)bitDepth,
|
||||
(i2s_channel_t)channelCount);
|
||||
return true;
|
||||
}
|
||||
@@ -1,106 +1,101 @@
|
||||
#include "ES8311AudioSink.h"
|
||||
extern "C" {
|
||||
#include "es8311.h"
|
||||
#include "es8311.h"
|
||||
}
|
||||
ES8311AudioSink::ES8311AudioSink()
|
||||
{
|
||||
this->softwareVolumeControl = false;
|
||||
esp_err_t ret_val = ESP_OK;
|
||||
Es8311Config cfg = {
|
||||
.esMode = ES_MODE_SLAVE,
|
||||
.i2c_port_num = I2C_NUM_0,
|
||||
.i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 1,
|
||||
.scl_io_num = 2,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
},
|
||||
.dacOutput = (DacOutput) (DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2),
|
||||
.adcInput = ADC_INPUT_LINPUT1_RINPUT1,
|
||||
};
|
||||
cfg.i2c_cfg.master.clk_speed = 100000;
|
||||
Es8311Init(&cfg);
|
||||
Es8311SetBitsPerSample(ES_MODULE_DAC, BIT_LENGTH_16BITS);
|
||||
Es8311ConfigFmt(ES_MODULE_DAC, ES_I2S_NORMAL);
|
||||
Es8311SetVoiceVolume(60);
|
||||
Es8311Start(ES_MODULE_DAC);
|
||||
ES8311WriteReg(ES8311_CLK_MANAGER_REG01, 0xbf);
|
||||
ES8311WriteReg(ES8311_CLK_MANAGER_REG02, 0x18);
|
||||
ES8311AudioSink::ES8311AudioSink() {
|
||||
this->softwareVolumeControl = false;
|
||||
esp_err_t ret_val = ESP_OK;
|
||||
Es8311Config cfg = {
|
||||
.esMode = ES_MODE_SLAVE,
|
||||
.i2c_port_num = I2C_NUM_0,
|
||||
.i2c_cfg =
|
||||
{
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 1,
|
||||
.scl_io_num = 2,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
},
|
||||
.dacOutput = (DacOutput)(DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 |
|
||||
DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2),
|
||||
.adcInput = ADC_INPUT_LINPUT1_RINPUT1,
|
||||
};
|
||||
cfg.i2c_cfg.master.clk_speed = 100000;
|
||||
Es8311Init(&cfg);
|
||||
Es8311SetBitsPerSample(ES_MODULE_DAC, BIT_LENGTH_16BITS);
|
||||
Es8311ConfigFmt(ES_MODULE_DAC, ES_I2S_NORMAL);
|
||||
Es8311SetVoiceVolume(60);
|
||||
Es8311Start(ES_MODULE_DAC);
|
||||
ES8311WriteReg(ES8311_CLK_MANAGER_REG01, 0xbf);
|
||||
ES8311WriteReg(ES8311_CLK_MANAGER_REG02, 0x18);
|
||||
|
||||
// .codec_mode = AUDIO_HAL_CODEC_MODE_DECODE,
|
||||
// .i2s_iface = {
|
||||
// .mode = AUDIO_HAL_MODE_SLAVE,
|
||||
// .fmt = AUDIO_HAL_I2S_NORMAL,
|
||||
// .samples = AUDIO_HAL_44K_SAMPLES,
|
||||
// .bits = AUDIO_HAL_BIT_LENGTH_16BITS,
|
||||
// },
|
||||
// };
|
||||
// .codec_mode = AUDIO_HAL_CODEC_MODE_DECODE,
|
||||
// .i2s_iface = {
|
||||
// .mode = AUDIO_HAL_MODE_SLAVE,
|
||||
// .fmt = AUDIO_HAL_I2S_NORMAL,
|
||||
// .samples = AUDIO_HAL_44K_SAMPLES,
|
||||
// .bits = AUDIO_HAL_BIT_LENGTH_16BITS,
|
||||
// },
|
||||
// };
|
||||
|
||||
// ret_val |= es8311_codec_init(&cfg);
|
||||
// ret_val |= es8311_set_bits_per_sample(cfg.i2s_iface.bits);
|
||||
// ret_val |= es8311_config_fmt((es_i2s_fmt_t) cfg.i2s_iface.fmt);
|
||||
// ret_val |= es8311_codec_set_voice_volume(60);
|
||||
// ret_val |= es8311_codec_ctrl_state(cfg.codec_mode, AUDIO_HAL_CTRL_START);
|
||||
// ret_val |= es8311_codec_set_clk();
|
||||
// ret_val |= es8311_codec_init(&cfg);
|
||||
// ret_val |= es8311_set_bits_per_sample(cfg.i2s_iface.bits);
|
||||
// ret_val |= es8311_config_fmt((es_i2s_fmt_t) cfg.i2s_iface.fmt);
|
||||
// ret_val |= es8311_codec_set_voice_volume(60);
|
||||
// ret_val |= es8311_codec_ctrl_state(cfg.codec_mode, AUDIO_HAL_CTRL_START);
|
||||
// ret_val |= es8311_codec_set_clk();
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // 2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0, // Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = true, // Auto clear tx descriptor on underflow
|
||||
};
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // 2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0, // Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = true, // Auto clear tx descriptor on underflow
|
||||
};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.mck_io_num = 42,
|
||||
.bck_io_num = 40,
|
||||
.ws_io_num = 41,
|
||||
.data_out_num = 39,
|
||||
.data_in_num = -1,
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.mck_io_num = 42,
|
||||
.bck_io_num = 40,
|
||||
.ws_io_num = 41,
|
||||
.data_out_num = 39,
|
||||
.data_in_num = -1,
|
||||
};
|
||||
|
||||
int err;
|
||||
int err;
|
||||
|
||||
err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE("OI", "i2s driver installation error: %d", err);
|
||||
}
|
||||
err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s driver installation error: %d", err);
|
||||
}
|
||||
|
||||
err = i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE("OI", "i2s set pin error: %d", err);
|
||||
}
|
||||
err = i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s set pin error: %d", err);
|
||||
}
|
||||
|
||||
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
// REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 0);
|
||||
// ESP_LOGI("OI", "MCLK output on CLK_OUT1");
|
||||
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
// REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 0);
|
||||
// ESP_LOGI("OI", "MCLK output on CLK_OUT1");
|
||||
|
||||
startI2sFeed();
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
void ES8311AudioSink::volumeChanged(uint16_t volume)
|
||||
{
|
||||
Es8311SetVoiceVolume(volume);
|
||||
void ES8311AudioSink::volumeChanged(uint16_t volume) {
|
||||
Es8311SetVoiceVolume(volume);
|
||||
}
|
||||
|
||||
void ES8311AudioSink::writeReg(uint8_t reg_add, uint8_t data)
|
||||
{
|
||||
}
|
||||
void ES8311AudioSink::writeReg(uint8_t reg_add, uint8_t data) {}
|
||||
|
||||
void ES8311AudioSink::setSampleRate(uint32_t sampleRate) {
|
||||
std::cout << "ES8311AudioSink::setSampleRate(" << sampleRate << ")" << std::endl;
|
||||
// i2s set sample rate
|
||||
es8311_Codec_Startup(0, sampleRate);
|
||||
std::cout << "ES8311AudioSink::setSampleRate(" << sampleRate << ")"
|
||||
<< std::endl;
|
||||
// i2s set sample rate
|
||||
es8311_Codec_Startup(0, sampleRate);
|
||||
}
|
||||
|
||||
ES8311AudioSink::~ES8311AudioSink()
|
||||
{
|
||||
}
|
||||
ES8311AudioSink::~ES8311AudioSink() {}
|
||||
|
||||
@@ -1,150 +1,145 @@
|
||||
#include "ES8388AudioSink.h"
|
||||
|
||||
struct es8388_cmd_s {
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
ES8388AudioSink::ES8388AudioSink()
|
||||
{
|
||||
// configure i2c
|
||||
i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 33,
|
||||
.scl_io_num = 32,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
};
|
||||
ES8388AudioSink::ES8388AudioSink() {
|
||||
// configure i2c
|
||||
i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 33,
|
||||
.scl_io_num = 32,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
};
|
||||
|
||||
i2c_config.master.clk_speed = 100000;
|
||||
i2c_config.master.clk_speed = 100000;
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 256 * 44100
|
||||
};
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 256 * 44100};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 26,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 26,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
|
||||
int err;
|
||||
int err;
|
||||
|
||||
err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s driver installation error: %d", err);
|
||||
}
|
||||
err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s driver installation error: %d", err);
|
||||
}
|
||||
|
||||
err = i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s set pin error: %d", err);
|
||||
}
|
||||
err = i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2s set pin error: %d", err);
|
||||
}
|
||||
|
||||
err = i2c_param_config(0, &i2c_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c param config error: %d", err);
|
||||
}
|
||||
|
||||
err = i2c_driver_install(0, I2C_MODE_MASTER, 0, 0, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c driver installation error: %d", err);
|
||||
}
|
||||
err = i2c_param_config(0, &i2c_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c param config error: %d", err);
|
||||
}
|
||||
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
err = i2c_driver_install(0, I2C_MODE_MASTER, 0, 0, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c driver installation error: %d", err);
|
||||
}
|
||||
|
||||
err = i2c_master_start(i2c_cmd);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c master start error: %d", err);
|
||||
}
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
/* mute DAC during setup, power up all systems, slave mode */
|
||||
writeReg(ES8388_DACCONTROL3, 0x04);
|
||||
writeReg(ES8388_CONTROL2, 0x50);
|
||||
writeReg(ES8388_CHIPPOWER, 0x00);
|
||||
writeReg(ES8388_MASTERMODE, 0x00);
|
||||
err = i2c_master_start(i2c_cmd);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("OI", "i2c master start error: %d", err);
|
||||
}
|
||||
|
||||
/* power up DAC and enable LOUT1+2 / ROUT1+2, ADC sample rate = DAC sample rate */
|
||||
writeReg(ES8388_DACPOWER, 0x3e);
|
||||
writeReg(ES8388_CONTROL1, 0x12);
|
||||
/* mute DAC during setup, power up all systems, slave mode */
|
||||
writeReg(ES8388_DACCONTROL3, 0x04);
|
||||
writeReg(ES8388_CONTROL2, 0x50);
|
||||
writeReg(ES8388_CHIPPOWER, 0x00);
|
||||
writeReg(ES8388_MASTERMODE, 0x00);
|
||||
|
||||
/* DAC I2S setup: 16 bit word length, I2S format; MCLK / Fs = 256*/
|
||||
writeReg(ES8388_DACCONTROL1, 0x18);
|
||||
writeReg(ES8388_DACCONTROL2, 0x02);
|
||||
/* power up DAC and enable LOUT1+2 / ROUT1+2, ADC sample rate = DAC sample rate */
|
||||
writeReg(ES8388_DACPOWER, 0x3e);
|
||||
writeReg(ES8388_CONTROL1, 0x12);
|
||||
|
||||
/* DAC to output route mixer configuration: ADC MIX TO OUTPUT */
|
||||
writeReg(ES8388_DACCONTROL16, 0x1B);
|
||||
writeReg(ES8388_DACCONTROL17, 0x90);
|
||||
writeReg(ES8388_DACCONTROL20, 0x90);
|
||||
/* DAC I2S setup: 16 bit word length, I2S format; MCLK / Fs = 256*/
|
||||
writeReg(ES8388_DACCONTROL1, 0x18);
|
||||
writeReg(ES8388_DACCONTROL2, 0x02);
|
||||
|
||||
/* DAC and ADC use same LRCK, enable MCLK input; output resistance setup */
|
||||
writeReg(ES8388_DACCONTROL21, 0x80);
|
||||
writeReg(ES8388_DACCONTROL23, 0x00);
|
||||
/* DAC to output route mixer configuration: ADC MIX TO OUTPUT */
|
||||
writeReg(ES8388_DACCONTROL16, 0x1B);
|
||||
writeReg(ES8388_DACCONTROL17, 0x90);
|
||||
writeReg(ES8388_DACCONTROL20, 0x90);
|
||||
|
||||
/* DAC volume control: 0dB (maximum, unattented) */
|
||||
writeReg(ES8388_DACCONTROL5, 0x00);
|
||||
writeReg(ES8388_DACCONTROL4, 0x00);
|
||||
/* DAC and ADC use same LRCK, enable MCLK input; output resistance setup */
|
||||
writeReg(ES8388_DACCONTROL21, 0x80);
|
||||
writeReg(ES8388_DACCONTROL23, 0x00);
|
||||
|
||||
/* power down ADC while configuring; volume: +9dB for both channels */
|
||||
writeReg(ES8388_ADCPOWER, 0xff);
|
||||
writeReg(ES8388_ADCCONTROL1, 0x88); // +24db
|
||||
/* DAC volume control: 0dB (maximum, unattented) */
|
||||
writeReg(ES8388_DACCONTROL5, 0x00);
|
||||
writeReg(ES8388_DACCONTROL4, 0x00);
|
||||
|
||||
/* select LINPUT2 / RINPUT2 as ADC input; stereo; 16 bit word length, format right-justified, MCLK / Fs = 256 */
|
||||
writeReg(ES8388_ADCCONTROL2, 0xf0); // 50
|
||||
writeReg(ES8388_ADCCONTROL3, 0x80); // 00
|
||||
writeReg(ES8388_ADCCONTROL4, 0x0e);
|
||||
writeReg(ES8388_ADCCONTROL5, 0x02);
|
||||
/* power down ADC while configuring; volume: +9dB for both channels */
|
||||
writeReg(ES8388_ADCPOWER, 0xff);
|
||||
writeReg(ES8388_ADCCONTROL1, 0x88); // +24db
|
||||
|
||||
/* set ADC volume */
|
||||
writeReg(ES8388_ADCCONTROL8, 0x20);
|
||||
writeReg(ES8388_ADCCONTROL9, 0x20);
|
||||
/* select LINPUT2 / RINPUT2 as ADC input; stereo; 16 bit word length, format right-justified, MCLK / Fs = 256 */
|
||||
writeReg(ES8388_ADCCONTROL2, 0xf0); // 50
|
||||
writeReg(ES8388_ADCCONTROL3, 0x80); // 00
|
||||
writeReg(ES8388_ADCCONTROL4, 0x0e);
|
||||
writeReg(ES8388_ADCCONTROL5, 0x02);
|
||||
|
||||
/* set LOUT1 / ROUT1 volume: 0dB (unattenuated) */
|
||||
writeReg(ES8388_DACCONTROL24, 0x1e);
|
||||
writeReg(ES8388_DACCONTROL25, 0x1e);
|
||||
/* set ADC volume */
|
||||
writeReg(ES8388_ADCCONTROL8, 0x20);
|
||||
writeReg(ES8388_ADCCONTROL9, 0x20);
|
||||
|
||||
/* set LOUT2 / ROUT2 volume: 0dB (unattenuated) */
|
||||
writeReg(ES8388_DACCONTROL26, 0x1e);
|
||||
writeReg(ES8388_DACCONTROL27, 0x1e);
|
||||
/* set LOUT1 / ROUT1 volume: 0dB (unattenuated) */
|
||||
writeReg(ES8388_DACCONTROL24, 0x1e);
|
||||
writeReg(ES8388_DACCONTROL25, 0x1e);
|
||||
|
||||
/* power up and enable DAC; power up ADC (no MIC bias) */
|
||||
writeReg(ES8388_DACPOWER, 0x3c);
|
||||
writeReg(ES8388_DACCONTROL3, 0x00);
|
||||
writeReg(ES8388_ADCPOWER, 0x00);
|
||||
/* set LOUT2 / ROUT2 volume: 0dB (unattenuated) */
|
||||
writeReg(ES8388_DACCONTROL26, 0x1e);
|
||||
writeReg(ES8388_DACCONTROL27, 0x1e);
|
||||
|
||||
startI2sFeed();
|
||||
/* power up and enable DAC; power up ADC (no MIC bias) */
|
||||
writeReg(ES8388_DACPOWER, 0x3c);
|
||||
writeReg(ES8388_DACCONTROL3, 0x00);
|
||||
writeReg(ES8388_ADCPOWER, 0x00);
|
||||
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
void ES8388AudioSink::writeReg(uint8_t reg_add, uint8_t data)
|
||||
{
|
||||
void ES8388AudioSink::writeReg(uint8_t reg_add, uint8_t data) {
|
||||
|
||||
int res = 0;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
res |= i2c_master_start(cmd);
|
||||
res |= i2c_master_write_byte(cmd, ES8388_ADDR, ACK_CHECK_EN);
|
||||
res |= i2c_master_write_byte(cmd, reg_add, ACK_CHECK_EN);
|
||||
res |= i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
|
||||
res |= i2c_master_stop(cmd);
|
||||
res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
int res = 0;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
res |= i2c_master_start(cmd);
|
||||
res |= i2c_master_write_byte(cmd, ES8388_ADDR, ACK_CHECK_EN);
|
||||
res |= i2c_master_write_byte(cmd, reg_add, ACK_CHECK_EN);
|
||||
res |= i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
|
||||
res |= i2c_master_stop(cmd);
|
||||
res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE("RR", "Unable to write to ES8388: %d", res);
|
||||
}else{
|
||||
ESP_LOGE("RR", "register successfull written.");
|
||||
}
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE("RR", "Unable to write to ES8388: %d", res);
|
||||
} else {
|
||||
ESP_LOGE("RR", "register successfull written.");
|
||||
}
|
||||
}
|
||||
|
||||
ES8388AudioSink::~ES8388AudioSink()
|
||||
{
|
||||
}
|
||||
ES8388AudioSink::~ES8388AudioSink() {}
|
||||
|
||||
@@ -2,35 +2,31 @@
|
||||
|
||||
#include "driver/i2s.h"
|
||||
|
||||
ES9018AudioSink::ES9018AudioSink()
|
||||
{
|
||||
i2s_config_t i2s_config = {
|
||||
ES9018AudioSink::ES9018AudioSink() {
|
||||
i2s_config_t i2s_config = {
|
||||
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 384 * 44100
|
||||
};
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 384 * 44100};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 32,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
|
||||
startI2sFeed();
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 32,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
ES9018AudioSink::~ES9018AudioSink()
|
||||
{
|
||||
}
|
||||
ES9018AudioSink::~ES9018AudioSink() {}
|
||||
|
||||
@@ -1,35 +1,32 @@
|
||||
#include "InternalAudioSink.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
InternalAudioSink::InternalAudioSink()
|
||||
{
|
||||
softwareVolumeControl = true;
|
||||
usign = true;
|
||||
#ifdef I2S_MODE_DAC_BUILT_IN
|
||||
InternalAudioSink::InternalAudioSink() {
|
||||
softwareVolumeControl = true;
|
||||
usign = true;
|
||||
#ifdef I2S_MODE_DAC_BUILT_IN
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN), // Only TX
|
||||
.sample_rate = (i2s_bits_per_sample_t)44100,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0,//ESP_INTR_FLAG_LEVEL1
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk=-1
|
||||
};
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX |
|
||||
I2S_MODE_DAC_BUILT_IN), // Only TX
|
||||
.sample_rate = (i2s_bits_per_sample_t)44100,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0, //ESP_INTR_FLAG_LEVEL1
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = -1};
|
||||
|
||||
//install and start i2s driver
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
//init DAC
|
||||
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
#endif
|
||||
//install and start i2s driver
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
//init DAC
|
||||
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
#endif
|
||||
|
||||
startI2sFeed();
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
InternalAudioSink::~InternalAudioSink()
|
||||
{
|
||||
}
|
||||
InternalAudioSink::~InternalAudioSink() {}
|
||||
|
||||
@@ -2,35 +2,31 @@
|
||||
|
||||
#include "driver/i2s.h"
|
||||
|
||||
PCM5102AudioSink::PCM5102AudioSink()
|
||||
{
|
||||
i2s_config_t i2s_config = {
|
||||
PCM5102AudioSink::PCM5102AudioSink() {
|
||||
i2s_config_t i2s_config = {
|
||||
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 384 * 44100
|
||||
};
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 384 * 44100};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 32,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 27,
|
||||
.ws_io_num = 32,
|
||||
.data_out_num = 25,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
|
||||
startI2sFeed();
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
PCM5102AudioSink::~PCM5102AudioSink()
|
||||
{
|
||||
}
|
||||
PCM5102AudioSink::~PCM5102AudioSink() {}
|
||||
|
||||
@@ -5,124 +5,118 @@
|
||||
// See http://www.hardwarebook.info/S/PDIF for more info on this protocol
|
||||
// Conversion table to biphase code mark (LSB first, ending in 1)
|
||||
static const uint16_t bmc_convert[256] = {
|
||||
0x3333, 0xb333, 0xd333, 0x5333, 0xcb33, 0x4b33, 0x2b33, 0xab33,
|
||||
0xcd33, 0x4d33, 0x2d33, 0xad33, 0x3533, 0xb533, 0xd533, 0x5533,
|
||||
0xccb3, 0x4cb3, 0x2cb3, 0xacb3, 0x34b3, 0xb4b3, 0xd4b3, 0x54b3,
|
||||
0x32b3, 0xb2b3, 0xd2b3, 0x52b3, 0xcab3, 0x4ab3, 0x2ab3, 0xaab3,
|
||||
0xccd3, 0x4cd3, 0x2cd3, 0xacd3, 0x34d3, 0xb4d3, 0xd4d3, 0x54d3,
|
||||
0x32d3, 0xb2d3, 0xd2d3, 0x52d3, 0xcad3, 0x4ad3, 0x2ad3, 0xaad3,
|
||||
0x3353, 0xb353, 0xd353, 0x5353, 0xcb53, 0x4b53, 0x2b53, 0xab53,
|
||||
0xcd53, 0x4d53, 0x2d53, 0xad53, 0x3553, 0xb553, 0xd553, 0x5553,
|
||||
0xcccb, 0x4ccb, 0x2ccb, 0xaccb, 0x34cb, 0xb4cb, 0xd4cb, 0x54cb,
|
||||
0x32cb, 0xb2cb, 0xd2cb, 0x52cb, 0xcacb, 0x4acb, 0x2acb, 0xaacb,
|
||||
0x334b, 0xb34b, 0xd34b, 0x534b, 0xcb4b, 0x4b4b, 0x2b4b, 0xab4b,
|
||||
0xcd4b, 0x4d4b, 0x2d4b, 0xad4b, 0x354b, 0xb54b, 0xd54b, 0x554b,
|
||||
0x332b, 0xb32b, 0xd32b, 0x532b, 0xcb2b, 0x4b2b, 0x2b2b, 0xab2b,
|
||||
0xcd2b, 0x4d2b, 0x2d2b, 0xad2b, 0x352b, 0xb52b, 0xd52b, 0x552b,
|
||||
0xccab, 0x4cab, 0x2cab, 0xacab, 0x34ab, 0xb4ab, 0xd4ab, 0x54ab,
|
||||
0x32ab, 0xb2ab, 0xd2ab, 0x52ab, 0xcaab, 0x4aab, 0x2aab, 0xaaab,
|
||||
0xcccd, 0x4ccd, 0x2ccd, 0xaccd, 0x34cd, 0xb4cd, 0xd4cd, 0x54cd,
|
||||
0x32cd, 0xb2cd, 0xd2cd, 0x52cd, 0xcacd, 0x4acd, 0x2acd, 0xaacd,
|
||||
0x334d, 0xb34d, 0xd34d, 0x534d, 0xcb4d, 0x4b4d, 0x2b4d, 0xab4d,
|
||||
0xcd4d, 0x4d4d, 0x2d4d, 0xad4d, 0x354d, 0xb54d, 0xd54d, 0x554d,
|
||||
0x332d, 0xb32d, 0xd32d, 0x532d, 0xcb2d, 0x4b2d, 0x2b2d, 0xab2d,
|
||||
0xcd2d, 0x4d2d, 0x2d2d, 0xad2d, 0x352d, 0xb52d, 0xd52d, 0x552d,
|
||||
0xccad, 0x4cad, 0x2cad, 0xacad, 0x34ad, 0xb4ad, 0xd4ad, 0x54ad,
|
||||
0x32ad, 0xb2ad, 0xd2ad, 0x52ad, 0xcaad, 0x4aad, 0x2aad, 0xaaad,
|
||||
0x3335, 0xb335, 0xd335, 0x5335, 0xcb35, 0x4b35, 0x2b35, 0xab35,
|
||||
0xcd35, 0x4d35, 0x2d35, 0xad35, 0x3535, 0xb535, 0xd535, 0x5535,
|
||||
0xccb5, 0x4cb5, 0x2cb5, 0xacb5, 0x34b5, 0xb4b5, 0xd4b5, 0x54b5,
|
||||
0x32b5, 0xb2b5, 0xd2b5, 0x52b5, 0xcab5, 0x4ab5, 0x2ab5, 0xaab5,
|
||||
0xccd5, 0x4cd5, 0x2cd5, 0xacd5, 0x34d5, 0xb4d5, 0xd4d5, 0x54d5,
|
||||
0x32d5, 0xb2d5, 0xd2d5, 0x52d5, 0xcad5, 0x4ad5, 0x2ad5, 0xaad5,
|
||||
0x3355, 0xb355, 0xd355, 0x5355, 0xcb55, 0x4b55, 0x2b55, 0xab55,
|
||||
0xcd55, 0x4d55, 0x2d55, 0xad55, 0x3555, 0xb555, 0xd555, 0x5555,
|
||||
0x3333, 0xb333, 0xd333, 0x5333, 0xcb33, 0x4b33, 0x2b33, 0xab33, 0xcd33,
|
||||
0x4d33, 0x2d33, 0xad33, 0x3533, 0xb533, 0xd533, 0x5533, 0xccb3, 0x4cb3,
|
||||
0x2cb3, 0xacb3, 0x34b3, 0xb4b3, 0xd4b3, 0x54b3, 0x32b3, 0xb2b3, 0xd2b3,
|
||||
0x52b3, 0xcab3, 0x4ab3, 0x2ab3, 0xaab3, 0xccd3, 0x4cd3, 0x2cd3, 0xacd3,
|
||||
0x34d3, 0xb4d3, 0xd4d3, 0x54d3, 0x32d3, 0xb2d3, 0xd2d3, 0x52d3, 0xcad3,
|
||||
0x4ad3, 0x2ad3, 0xaad3, 0x3353, 0xb353, 0xd353, 0x5353, 0xcb53, 0x4b53,
|
||||
0x2b53, 0xab53, 0xcd53, 0x4d53, 0x2d53, 0xad53, 0x3553, 0xb553, 0xd553,
|
||||
0x5553, 0xcccb, 0x4ccb, 0x2ccb, 0xaccb, 0x34cb, 0xb4cb, 0xd4cb, 0x54cb,
|
||||
0x32cb, 0xb2cb, 0xd2cb, 0x52cb, 0xcacb, 0x4acb, 0x2acb, 0xaacb, 0x334b,
|
||||
0xb34b, 0xd34b, 0x534b, 0xcb4b, 0x4b4b, 0x2b4b, 0xab4b, 0xcd4b, 0x4d4b,
|
||||
0x2d4b, 0xad4b, 0x354b, 0xb54b, 0xd54b, 0x554b, 0x332b, 0xb32b, 0xd32b,
|
||||
0x532b, 0xcb2b, 0x4b2b, 0x2b2b, 0xab2b, 0xcd2b, 0x4d2b, 0x2d2b, 0xad2b,
|
||||
0x352b, 0xb52b, 0xd52b, 0x552b, 0xccab, 0x4cab, 0x2cab, 0xacab, 0x34ab,
|
||||
0xb4ab, 0xd4ab, 0x54ab, 0x32ab, 0xb2ab, 0xd2ab, 0x52ab, 0xcaab, 0x4aab,
|
||||
0x2aab, 0xaaab, 0xcccd, 0x4ccd, 0x2ccd, 0xaccd, 0x34cd, 0xb4cd, 0xd4cd,
|
||||
0x54cd, 0x32cd, 0xb2cd, 0xd2cd, 0x52cd, 0xcacd, 0x4acd, 0x2acd, 0xaacd,
|
||||
0x334d, 0xb34d, 0xd34d, 0x534d, 0xcb4d, 0x4b4d, 0x2b4d, 0xab4d, 0xcd4d,
|
||||
0x4d4d, 0x2d4d, 0xad4d, 0x354d, 0xb54d, 0xd54d, 0x554d, 0x332d, 0xb32d,
|
||||
0xd32d, 0x532d, 0xcb2d, 0x4b2d, 0x2b2d, 0xab2d, 0xcd2d, 0x4d2d, 0x2d2d,
|
||||
0xad2d, 0x352d, 0xb52d, 0xd52d, 0x552d, 0xccad, 0x4cad, 0x2cad, 0xacad,
|
||||
0x34ad, 0xb4ad, 0xd4ad, 0x54ad, 0x32ad, 0xb2ad, 0xd2ad, 0x52ad, 0xcaad,
|
||||
0x4aad, 0x2aad, 0xaaad, 0x3335, 0xb335, 0xd335, 0x5335, 0xcb35, 0x4b35,
|
||||
0x2b35, 0xab35, 0xcd35, 0x4d35, 0x2d35, 0xad35, 0x3535, 0xb535, 0xd535,
|
||||
0x5535, 0xccb5, 0x4cb5, 0x2cb5, 0xacb5, 0x34b5, 0xb4b5, 0xd4b5, 0x54b5,
|
||||
0x32b5, 0xb2b5, 0xd2b5, 0x52b5, 0xcab5, 0x4ab5, 0x2ab5, 0xaab5, 0xccd5,
|
||||
0x4cd5, 0x2cd5, 0xacd5, 0x34d5, 0xb4d5, 0xd4d5, 0x54d5, 0x32d5, 0xb2d5,
|
||||
0xd2d5, 0x52d5, 0xcad5, 0x4ad5, 0x2ad5, 0xaad5, 0x3355, 0xb355, 0xd355,
|
||||
0x5355, 0xcb55, 0x4b55, 0x2b55, 0xab55, 0xcd55, 0x4d55, 0x2d55, 0xad55,
|
||||
0x3555, 0xb555, 0xd555, 0x5555,
|
||||
};
|
||||
|
||||
#define I2S_BUG_MAGIC (26 * 1000 * 1000) // magic number for avoiding I2S bug
|
||||
#define BITS_PER_SUBFRAME 64
|
||||
#define FRAMES_PER_BLOCK 192
|
||||
#define SPDIF_BUF_SIZE (BITS_PER_SUBFRAME/8 * 2 * FRAMES_PER_BLOCK)
|
||||
#define SPDIF_BUF_ARRAY_SIZE (SPDIF_BUF_SIZE / sizeof(uint32_t))
|
||||
#define I2S_BUG_MAGIC (26 * 1000 * 1000) // magic number for avoiding I2S bug
|
||||
#define BITS_PER_SUBFRAME 64
|
||||
#define FRAMES_PER_BLOCK 192
|
||||
#define SPDIF_BUF_SIZE (BITS_PER_SUBFRAME / 8 * 2 * FRAMES_PER_BLOCK)
|
||||
#define SPDIF_BUF_ARRAY_SIZE (SPDIF_BUF_SIZE / sizeof(uint32_t))
|
||||
|
||||
#define BMC_B 0x33173333 // block start
|
||||
#define BMC_M 0x331d3333 // left ch
|
||||
#define BMC_W 0x331b3333 // right ch
|
||||
#define BMC_MW_DIF (BMC_M ^ BMC_W)
|
||||
#define BMC_B 0x33173333 // block start
|
||||
#define BMC_M 0x331d3333 // left ch
|
||||
#define BMC_W 0x331b3333 // right ch
|
||||
#define BMC_MW_DIF (BMC_M ^ BMC_W)
|
||||
|
||||
static uint32_t spdif_buf[SPDIF_BUF_ARRAY_SIZE];
|
||||
static uint32_t *spdif_ptr;
|
||||
static uint32_t* spdif_ptr;
|
||||
|
||||
static void spdif_buf_init(void)
|
||||
{
|
||||
// first bllock has W preamble
|
||||
spdif_buf[0] = BMC_B;
|
||||
static void spdif_buf_init(void) {
|
||||
// first bllock has W preamble
|
||||
spdif_buf[0] = BMC_B;
|
||||
|
||||
// all other blocks are alternating M, then W preamble
|
||||
uint32_t bmc_mw = BMC_M;
|
||||
for (int i = 2; i < SPDIF_BUF_ARRAY_SIZE; i += 2)
|
||||
{
|
||||
spdif_buf[i] = bmc_mw ^= BMC_MW_DIF;
|
||||
}
|
||||
// all other blocks are alternating M, then W preamble
|
||||
uint32_t bmc_mw = BMC_M;
|
||||
for (int i = 2; i < SPDIF_BUF_ARRAY_SIZE; i += 2) {
|
||||
spdif_buf[i] = bmc_mw ^= BMC_MW_DIF;
|
||||
}
|
||||
}
|
||||
|
||||
SPDIFAudioSink::SPDIFAudioSink(uint8_t spdifPin)
|
||||
{
|
||||
// initialize S/PDIF buffer
|
||||
spdif_buf_init();
|
||||
spdif_ptr = spdif_buf;
|
||||
this->spdifPin = spdifPin;
|
||||
this->setParams(44100, 16, 2);
|
||||
startI2sFeed(SPDIF_BUF_SIZE * 16);
|
||||
SPDIFAudioSink::SPDIFAudioSink(uint8_t spdifPin) {
|
||||
// initialize S/PDIF buffer
|
||||
spdif_buf_init();
|
||||
spdif_ptr = spdif_buf;
|
||||
this->spdifPin = spdifPin;
|
||||
this->setParams(44100, 16, 2);
|
||||
startI2sFeed(SPDIF_BUF_SIZE * 16);
|
||||
}
|
||||
|
||||
bool SPDIFAudioSink::setParams(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) {
|
||||
if (bitDepth != 16 || channelCount != 2) // TODO support mono playback and different bit widths
|
||||
return false;
|
||||
int sample_rate = (int)sampleRate * 2;
|
||||
int bclk = sample_rate * 64 * 2;
|
||||
int mclk = (I2S_BUG_MAGIC / bclk) * bclk;
|
||||
bool SPDIFAudioSink::setParams(uint32_t sampleRate, uint8_t channelCount,
|
||||
uint8_t bitDepth) {
|
||||
if (bitDepth != 16 ||
|
||||
channelCount != 2) // TODO support mono playback and different bit widths
|
||||
return false;
|
||||
int sample_rate = (int)sampleRate * 2;
|
||||
int bclk = sample_rate * 64 * 2;
|
||||
int mclk = (I2S_BUG_MAGIC / bclk) * bclk;
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.sample_rate = (uint32_t) sample_rate,
|
||||
.sample_rate = (uint32_t)sample_rate,
|
||||
#else
|
||||
.sample_rate = (int) sample_rate,
|
||||
.sample_rate = (int)sample_rate,
|
||||
#endif
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)(bitDepth * 2),
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true,
|
||||
.fixed_mclk = mclk, // avoiding I2S bug
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = -1,
|
||||
.ws_io_num = -1,
|
||||
.data_out_num = spdifPin,
|
||||
.data_in_num = -1,
|
||||
};
|
||||
i2s_driver_uninstall((i2s_port_t)0);
|
||||
int err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, nullptr);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
return !err;
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)(bitDepth * 2),
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true,
|
||||
.fixed_mclk = mclk, // avoiding I2S bug
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = -1,
|
||||
.ws_io_num = -1,
|
||||
.data_out_num = spdifPin,
|
||||
.data_in_num = -1,
|
||||
};
|
||||
i2s_driver_uninstall((i2s_port_t)0);
|
||||
int err = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, nullptr);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
return !err;
|
||||
}
|
||||
|
||||
SPDIFAudioSink::~SPDIFAudioSink() {
|
||||
i2s_driver_uninstall((i2s_port_t)0);
|
||||
i2s_driver_uninstall((i2s_port_t)0);
|
||||
}
|
||||
|
||||
int num_frames = 0;
|
||||
|
||||
void SPDIFAudioSink::feedPCMFrames(const uint8_t *buffer, size_t bytes)
|
||||
{
|
||||
for (int i = 0; i < bytes; i += 2)
|
||||
{
|
||||
/**
|
||||
void SPDIFAudioSink::feedPCMFrames(const uint8_t* buffer, size_t bytes) {
|
||||
for (int i = 0; i < bytes; i += 2) {
|
||||
/**
|
||||
* What is this, and why does it work?
|
||||
*
|
||||
* Rather than assemble all S/PDIF frames from scratch we want to do the
|
||||
@@ -171,16 +165,16 @@ void SPDIFAudioSink::feedPCMFrames(const uint8_t *buffer, size_t bytes)
|
||||
* I did not come up with this, all credit goes to
|
||||
* github.com/amedes/esp_a2dp_sink_spdif
|
||||
*/
|
||||
uint32_t lo = ((uint32_t)(bmc_convert[buffer[i]]) << 16);
|
||||
uint32_t hi = (uint32_t)((int16_t)bmc_convert[buffer[i+1]]);
|
||||
uint32_t lo = ((uint32_t)(bmc_convert[buffer[i]]) << 16);
|
||||
uint32_t hi = (uint32_t)((int16_t)bmc_convert[buffer[i + 1]]);
|
||||
|
||||
*(spdif_ptr + 1) = ((lo ^ hi) << 1) >> 1;
|
||||
*(spdif_ptr + 1) = ((lo ^ hi) << 1) >> 1;
|
||||
|
||||
spdif_ptr += 2; // advance to next audio data
|
||||
|
||||
if (spdif_ptr >= &spdif_buf[SPDIF_BUF_ARRAY_SIZE]) {
|
||||
feedPCMFramesInternal(spdif_buf, sizeof(spdif_buf));
|
||||
spdif_ptr = spdif_buf;
|
||||
}
|
||||
spdif_ptr += 2; // advance to next audio data
|
||||
|
||||
if (spdif_ptr >= &spdif_buf[SPDIF_BUF_ARRAY_SIZE]) {
|
||||
feedPCMFramesInternal(spdif_buf, sizeof(spdif_buf));
|
||||
spdif_ptr = spdif_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +1,107 @@
|
||||
#include "TAS5711AudioSink.h"
|
||||
|
||||
|
||||
struct tas5711_cmd_s {
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static const struct tas5711_cmd_s tas5711_init_sequence[] = {
|
||||
{ 0x00, 0x6c }, // 0x6c - 256 x mclk
|
||||
{ 0x04, 0x03 }, // 0x03 - 16 bit i2s
|
||||
{ 0x05, 0x00 }, // system control 0x00 is audio playback
|
||||
{ 0x06, 0x00 }, // disable mute
|
||||
{ 0x07, 0x50 }, // volume register
|
||||
{ 0xff, 0xff }
|
||||
{0x00, 0x6c}, // 0x6c - 256 x mclk
|
||||
{0x04, 0x03}, // 0x03 - 16 bit i2s
|
||||
{0x05, 0x00}, // system control 0x00 is audio playback
|
||||
{0x06, 0x00}, // disable mute
|
||||
{0x07, 0x50}, // volume register
|
||||
{0xff, 0xff}
|
||||
|
||||
};
|
||||
i2c_ack_type_t ACK_CHECK_EN = (i2c_ack_type_t)0x1;
|
||||
|
||||
TAS5711AudioSink::TAS5711AudioSink()
|
||||
{
|
||||
i2s_config_t i2s_config = {
|
||||
TAS5711AudioSink::TAS5711AudioSink() {
|
||||
i2s_config_t i2s_config = {
|
||||
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 256 * 44100
|
||||
};
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // Only TX
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_MSB,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 512,
|
||||
.use_apll = true,
|
||||
.tx_desc_auto_clear = true, //Auto clear tx descriptor on underflow
|
||||
.fixed_mclk = 256 * 44100};
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 5,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 26,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = 5,
|
||||
.ws_io_num = 25,
|
||||
.data_out_num = 26,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
|
||||
i2s_set_pin((i2s_port_t)0, &pin_config);
|
||||
// configure i2c
|
||||
i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 21,
|
||||
.scl_io_num = 23,
|
||||
.sda_pullup_en = GPIO_PULLUP_DISABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_DISABLE,
|
||||
};
|
||||
|
||||
// configure i2c
|
||||
i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 21,
|
||||
.scl_io_num = 23,
|
||||
.sda_pullup_en = GPIO_PULLUP_DISABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_DISABLE,
|
||||
};
|
||||
i2c_config.master.clk_speed = 250000;
|
||||
|
||||
i2c_config.master.clk_speed = 250000;
|
||||
i2c_param_config(i2c_port, &i2c_config);
|
||||
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_param_config(i2c_port, &i2c_config);
|
||||
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
uint8_t data, addr = (0x1b);
|
||||
|
||||
uint8_t data, addr = (0x1b);
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, 00, ACK_CHECK_EN);
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, 00, ACK_CHECK_EN);
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (addr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||
i2c_master_read_byte(i2c_cmd, &data, ACK_CHECK_EN);
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (addr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||
i2c_master_read_byte(i2c_cmd, &data, ACK_CHECK_EN);
|
||||
i2c_master_stop(i2c_cmd);
|
||||
int ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
|
||||
i2c_master_stop(i2c_cmd);
|
||||
int ret = i2c_master_cmd_begin(i2c_port, i2c_cmd, 50 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI("RR", "Detected TAS");
|
||||
} else {
|
||||
ESP_LOGI("RR", "Unable to detect dac");
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI("RR", "Detected TAS");
|
||||
}
|
||||
else {
|
||||
ESP_LOGI("RR", "Unable to detect dac");
|
||||
}
|
||||
writeReg(0x1b, 0x00);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
writeReg(0x1b, 0x00);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
for (int i = 0; tas5711_init_sequence[i].reg != 0xff; i++) {
|
||||
writeReg(tas5711_init_sequence[i].reg, tas5711_init_sequence[i].value);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; tas5711_init_sequence[i].reg != 0xff; i++) {
|
||||
writeReg(tas5711_init_sequence[i].reg, tas5711_init_sequence[i].value);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
startI2sFeed();
|
||||
startI2sFeed();
|
||||
}
|
||||
|
||||
void TAS5711AudioSink::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
void TAS5711AudioSink::writeReg(uint8_t reg, uint8_t value) {
|
||||
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
|
||||
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (0x1b << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, reg, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, value, ACK_CHECK_EN);
|
||||
i2c_master_start(i2c_cmd);
|
||||
i2c_master_write_byte(i2c_cmd, (0x1b << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, reg, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(i2c_cmd, value, ACK_CHECK_EN);
|
||||
|
||||
i2c_master_stop(i2c_cmd);
|
||||
esp_err_t res =
|
||||
i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_PERIOD_MS);
|
||||
|
||||
i2c_master_stop(i2c_cmd);
|
||||
esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_PERIOD_MS);
|
||||
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE("RR", "Unable to write to TAS5711");
|
||||
}
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE("RR", "Unable to write to TAS5711");
|
||||
}
|
||||
i2c_cmd_link_delete(i2c_cmd);
|
||||
}
|
||||
|
||||
TAS5711AudioSink::~TAS5711AudioSink()
|
||||
{
|
||||
}
|
||||
TAS5711AudioSink::~TAS5711AudioSink() {}
|
||||
|
||||
@@ -22,16 +22,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_types.h>
|
||||
#include <esp_system.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "ac101.h"
|
||||
#include <driver/i2c.h>
|
||||
#include <driver/i2s.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_types.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <string.h>
|
||||
#include "adac.h"
|
||||
#include "ac101.h"
|
||||
|
||||
const static char TAG[] = "AC101";
|
||||
|
||||
@@ -42,14 +42,13 @@ const static char TAG[] = "AC101";
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define AC_ASSERT(a, format, b, ...) \
|
||||
if ((a) != 0) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, format, ##__VA_ARGS__); \
|
||||
return b; \
|
||||
}
|
||||
#define AC_ASSERT(a, format, b, ...) \
|
||||
if ((a) != 0) { \
|
||||
ESP_LOGE(TAG, format, ##__VA_ARGS__); \
|
||||
return b; \
|
||||
}
|
||||
|
||||
static bool init(int i2c_port_num, int i2s_num, i2s_config_t *config);
|
||||
static bool init(int i2c_port_num, int i2s_num, i2s_config_t* config);
|
||||
static void deinit(void);
|
||||
static void speaker(bool active);
|
||||
static void headset(bool active);
|
||||
@@ -71,356 +70,357 @@ static int i2c_port;
|
||||
/****************************************************************************************
|
||||
* init
|
||||
*/
|
||||
static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
static bool init(int i2c_port_num, int i2s_num, i2s_config_t* i2s_config) {
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
i2c_port = i2c_port_num;
|
||||
i2c_port = i2c_port_num;
|
||||
|
||||
// configure i2c
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 33,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = 32,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 250000,
|
||||
};
|
||||
// configure i2c
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 33,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = 32,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 250000,
|
||||
};
|
||||
|
||||
i2c_param_config(i2c_port, &i2c_config);
|
||||
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
|
||||
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);
|
||||
res = i2c_read_reg(CHIP_AUDIO_RS);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
ESP_LOGW(TAG, "No AC101 detected");
|
||||
i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
if (!res) {
|
||||
ESP_LOGW(TAG, "No AC101 detected");
|
||||
i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "AC101 DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num, i2c_config.scl_io_num);
|
||||
ESP_LOGI(TAG, "AC101 DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num,
|
||||
i2c_config.scl_io_num);
|
||||
|
||||
res = i2c_write_reg(CHIP_AUDIO_RS, 0x123);
|
||||
// huh?
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
res = i2c_write_reg(CHIP_AUDIO_RS, 0x123);
|
||||
// huh?
|
||||
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));
|
||||
// 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));
|
||||
|
||||
// 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
|
||||
// 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
|
||||
|
||||
// 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)
|
||||
// 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)
|
||||
#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
|
||||
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
|
||||
#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
|
||||
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
|
||||
#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
|
||||
//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
|
||||
#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?)
|
||||
i2c_write_reg(
|
||||
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)
|
||||
i2c_write_reg(OMIXER_SR, BIN(0000, 0101, 0000,
|
||||
1010)); // source=DAC(R/L) and LINEIN(R/L)
|
||||
#endif
|
||||
|
||||
// configure I2S pins & install driver
|
||||
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t){.bck_io_num = 27, .ws_io_num = 26, .data_out_num = 25, .data_in_num = -1};
|
||||
res |= i2s_driver_install(i2s_num, i2s_config, 0, NULL);
|
||||
res |= i2s_set_pin(i2s_num, &i2s_pin_config);
|
||||
// configure I2S pins & install driver
|
||||
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t){
|
||||
.bck_io_num = 27, .ws_io_num = 26, .data_out_num = 25, .data_in_num = -1};
|
||||
res |= i2s_driver_install(i2s_num, i2s_config, 0, NULL);
|
||||
res |= i2s_set_pin(i2s_num, &i2s_pin_config);
|
||||
|
||||
// enable earphone & speaker
|
||||
i2c_write_reg(SPKOUT_CTRL, 0x0220);
|
||||
i2c_write_reg(HPOUT_CTRL, 0xf801);
|
||||
// enable earphone & speaker
|
||||
i2c_write_reg(SPKOUT_CTRL, 0x0220);
|
||||
i2c_write_reg(HPOUT_CTRL, 0xf801);
|
||||
|
||||
// set gain for speaker and earphone
|
||||
ac101_set_spk_volume(70);
|
||||
ac101_set_earph_volume(70);
|
||||
// set gain for speaker and earphone
|
||||
ac101_set_spk_volume(70);
|
||||
ac101_set_earph_volume(70);
|
||||
|
||||
ESP_LOGI(TAG, "DAC using I2S bck:%d, ws:%d, do:%d", i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num);
|
||||
ESP_LOGI(TAG, "DAC using I2S bck:%d, ws:%d, do:%d", i2s_pin_config.bck_io_num,
|
||||
i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num);
|
||||
|
||||
return (res == ESP_OK);
|
||||
return (res == ESP_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* init
|
||||
*/
|
||||
static void deinit(void)
|
||||
{
|
||||
i2c_driver_delete(i2c_port);
|
||||
static void deinit(void) {
|
||||
i2c_driver_delete(i2c_port);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* change volume
|
||||
*/
|
||||
static void volume(unsigned left, unsigned right)
|
||||
{
|
||||
ac101_set_earph_volume(left);
|
||||
// nothing at that point, volume is handled by backend
|
||||
static void volume(unsigned left, unsigned right) {
|
||||
ac101_set_earph_volume(left);
|
||||
// nothing at that point, volume is handled by backend
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* power
|
||||
*/
|
||||
static void power(adac_power_e mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ADAC_STANDBY:
|
||||
case ADAC_OFF:
|
||||
ac101_stop();
|
||||
break;
|
||||
case ADAC_ON:
|
||||
ac101_start(AC_MODULE_DAC);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "unknown power command");
|
||||
break;
|
||||
}
|
||||
static void power(adac_power_e mode) {
|
||||
switch (mode) {
|
||||
case ADAC_STANDBY:
|
||||
case ADAC_OFF:
|
||||
ac101_stop();
|
||||
break;
|
||||
case ADAC_ON:
|
||||
ac101_start(AC_MODULE_DAC);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "unknown power command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* headset
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
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_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static uint16_t i2c_read_reg(uint8_t reg)
|
||||
{
|
||||
uint8_t data[2] = {0};
|
||||
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_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
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_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
return (data[0] << 8) + data[1];
|
||||
;
|
||||
return (data[0] << 8) + data[1];
|
||||
;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
void set_sample_rate(int rate)
|
||||
{
|
||||
if (rate == 8000)
|
||||
rate = SAMPLE_RATE_8000;
|
||||
else if (rate == 11025)
|
||||
rate = SAMPLE_RATE_11052;
|
||||
else if (rate == 12000)
|
||||
rate = SAMPLE_RATE_12000;
|
||||
else if (rate == 16000)
|
||||
rate = SAMPLE_RATE_16000;
|
||||
else if (rate == 22050)
|
||||
rate = SAMPLE_RATE_22050;
|
||||
else if (rate == 24000)
|
||||
rate = SAMPLE_RATE_24000;
|
||||
else if (rate == 32000)
|
||||
rate = SAMPLE_RATE_32000;
|
||||
else if (rate == 44100)
|
||||
rate = SAMPLE_RATE_44100;
|
||||
else if (rate == 48000)
|
||||
rate = SAMPLE_RATE_48000;
|
||||
else if (rate == 96000)
|
||||
rate = SAMPLE_RATE_96000;
|
||||
else if (rate == 192000)
|
||||
rate = SAMPLE_RATE_192000;
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG, "Unknown sample rate %hu", rate);
|
||||
rate = SAMPLE_RATE_44100;
|
||||
}
|
||||
i2c_write_reg(I2S_SR_CTRL, rate);
|
||||
void set_sample_rate(int rate) {
|
||||
if (rate == 8000)
|
||||
rate = SAMPLE_RATE_8000;
|
||||
else if (rate == 11025)
|
||||
rate = SAMPLE_RATE_11052;
|
||||
else if (rate == 12000)
|
||||
rate = SAMPLE_RATE_12000;
|
||||
else if (rate == 16000)
|
||||
rate = SAMPLE_RATE_16000;
|
||||
else if (rate == 22050)
|
||||
rate = SAMPLE_RATE_22050;
|
||||
else if (rate == 24000)
|
||||
rate = SAMPLE_RATE_24000;
|
||||
else if (rate == 32000)
|
||||
rate = SAMPLE_RATE_32000;
|
||||
else if (rate == 44100)
|
||||
rate = SAMPLE_RATE_44100;
|
||||
else if (rate == 48000)
|
||||
rate = SAMPLE_RATE_48000;
|
||||
else if (rate == 96000)
|
||||
rate = SAMPLE_RATE_96000;
|
||||
else if (rate == 192000)
|
||||
rate = SAMPLE_RATE_192000;
|
||||
else {
|
||||
ESP_LOGW(TAG, "Unknown sample rate %hu", rate);
|
||||
rate = SAMPLE_RATE_44100;
|
||||
}
|
||||
i2c_write_reg(I2S_SR_CTRL, rate);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Get normalized (0..100) speaker volume
|
||||
*/
|
||||
static int ac101_get_spk_volume(void)
|
||||
{
|
||||
return ((i2c_read_reg(SPKOUT_CTRL) & 0x1f) * 100) / 0x1f;
|
||||
static int ac101_get_spk_volume(void) {
|
||||
return ((i2c_read_reg(SPKOUT_CTRL) & 0x1f) * 100) / 0x1f;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Set normalized (0..100) volume
|
||||
*/
|
||||
static void ac101_set_spk_volume(uint8_t volume)
|
||||
{
|
||||
uint16_t value = min(volume, 100);
|
||||
value = ((int)value * 0x1f) / 100;
|
||||
value |= i2c_read_reg(SPKOUT_CTRL) & ~0x1f;
|
||||
i2c_write_reg(SPKOUT_CTRL, value);
|
||||
static void ac101_set_spk_volume(uint8_t volume) {
|
||||
uint16_t value = min(volume, 100);
|
||||
value = ((int)value * 0x1f) / 100;
|
||||
value |= i2c_read_reg(SPKOUT_CTRL) & ~0x1f;
|
||||
i2c_write_reg(SPKOUT_CTRL, value);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Get normalized (0..100) earphone volume
|
||||
*/
|
||||
static int ac101_get_earph_volume(void)
|
||||
{
|
||||
return (((i2c_read_reg(HPOUT_CTRL) >> 4) & 0x3f) * 100) / 0x3f;
|
||||
static int ac101_get_earph_volume(void) {
|
||||
return (((i2c_read_reg(HPOUT_CTRL) >> 4) & 0x3f) * 100) / 0x3f;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Set normalized (0..100) earphone volume
|
||||
*/
|
||||
static void ac101_set_earph_volume(uint8_t volume)
|
||||
{
|
||||
uint16_t value = min(volume, 255);
|
||||
value = (((int)value * 0x3f) / 255) << 4;
|
||||
value |= i2c_read_reg(HPOUT_CTRL) & ~(0x3f << 4);
|
||||
i2c_write_reg(HPOUT_CTRL, value);
|
||||
static void ac101_set_earph_volume(uint8_t volume) {
|
||||
uint16_t value = min(volume, 255);
|
||||
value = (((int)value * 0x3f) / 255) << 4;
|
||||
value |= i2c_read_reg(HPOUT_CTRL) & ~(0x3f << 4);
|
||||
i2c_write_reg(HPOUT_CTRL, value);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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);
|
||||
switch (source)
|
||||
{
|
||||
case SRC_MIC1:
|
||||
temp = (gain & 0x7) << 6;
|
||||
clrbit = ~(0x7 << 6);
|
||||
break;
|
||||
case SRC_MIC2:
|
||||
temp = (gain & 0x7) << 3;
|
||||
clrbit = ~(0x7 << 3);
|
||||
break;
|
||||
case SRC_LINEIN:
|
||||
temp = (gain & 0x7);
|
||||
clrbit = ~0x7;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
regval &= clrbit;
|
||||
regval |= temp;
|
||||
i2c_write_reg(OMIXER_BST1_CTRL, regval);
|
||||
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);
|
||||
switch (source) {
|
||||
case SRC_MIC1:
|
||||
temp = (gain & 0x7) << 6;
|
||||
clrbit = ~(0x7 << 6);
|
||||
break;
|
||||
case SRC_MIC2:
|
||||
temp = (gain & 0x7) << 3;
|
||||
clrbit = ~(0x7 << 3);
|
||||
break;
|
||||
case SRC_LINEIN:
|
||||
temp = (gain & 0x7);
|
||||
clrbit = ~0x7;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
regval &= clrbit;
|
||||
regval |= temp;
|
||||
i2c_write_reg(OMIXER_BST1_CTRL, regval);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (mode == AC_MODULE_DAC || mode == AC_MODULE_ADC_DAC || mode == AC_MODULE_LINE)
|
||||
{
|
||||
uint16_t value = i2c_read_reg(PLL_CTRL2);
|
||||
value |= 0x8000;
|
||||
i2c_write_reg(PLL_CTRL2, value);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (mode == AC_MODULE_DAC || mode == AC_MODULE_ADC_DAC ||
|
||||
mode == AC_MODULE_LINE) {
|
||||
uint16_t value = i2c_read_reg(PLL_CTRL2);
|
||||
value |= 0x8000;
|
||||
i2c_write_reg(PLL_CTRL2, value);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void ac101_stop(void)
|
||||
{
|
||||
uint16_t value = i2c_read_reg(PLL_CTRL2);
|
||||
value &= ~0x8000;
|
||||
i2c_write_reg(PLL_CTRL2, value);
|
||||
static void ac101_stop(void) {
|
||||
uint16_t value = i2c_read_reg(PLL_CTRL2);
|
||||
value &= ~0x8000;
|
||||
i2c_write_reg(PLL_CTRL2, value);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void ac101_deinit(void)
|
||||
{
|
||||
i2c_write_reg(CHIP_AUDIO_RS, 0x123); //soft reset
|
||||
static void ac101_deinit(void) {
|
||||
i2c_write_reg(CHIP_AUDIO_RS, 0x123); //soft reset
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Don't know when this one is supposed to be called
|
||||
*/
|
||||
static void ac101_i2s_config_clock(ac_i2s_clock_t *cfg)
|
||||
{
|
||||
uint16_t regval = 0;
|
||||
regval = i2c_read_reg(I2S1LCK_CTRL);
|
||||
regval &= 0xe03f;
|
||||
regval |= (cfg->bclk_div << 9);
|
||||
regval |= (cfg->lclk_div << 6);
|
||||
i2c_write_reg(I2S1LCK_CTRL, regval);
|
||||
static void ac101_i2s_config_clock(ac_i2s_clock_t* cfg) {
|
||||
uint16_t regval = 0;
|
||||
regval = i2c_read_reg(I2S1LCK_CTRL);
|
||||
regval &= 0xe03f;
|
||||
regval |= (cfg->bclk_div << 9);
|
||||
regval |= (cfg->lclk_div << 6);
|
||||
i2c_write_reg(I2S1LCK_CTRL, regval);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user