Files
cardputerfw/main/drivers/es8311.c

236 lines
7.3 KiB
C

#include "es8311.h"
#include "drivers/i2s.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#include "i2c.h"
#include "pins.h"
#include <math.h>
#include <stdint.h>
i2c_master_dev_handle_t es8311_i2c_dev;
int es8311_write(uint8_t reg, uint8_t val) {
esp_err_t ret = i2c_write_reg(es8311_i2c_dev, reg, val);
if (ret != ESP_OK) {
printf("ES8311 write failed: reg=0x%02X, ret=%d\n", reg, ret);
return -1;
}
return 0;
}
void es8311_set_dac_volume(float vol) {
if (vol < -95.5f) {
vol = -95.5f;
}
if (vol > 32) {
vol = 32;
}
vol *= 2;
uint8_t volByte = vol;
es8311_write(ES8311_DAC_REG32, volByte);
}
void es8311_set_adc_volume(float vol) {
if (vol < -95.5f) {
vol = -95.5f;
}
if (vol > 32) {
vol = 32;
}
vol *= 2;
uint8_t volByte = vol;
es8311_write(ES8311_ADC_REG17, volByte);
}
uint8_t es8311_read(uint8_t reg) {
uint8_t val;
esp_err_t ret = i2c_read_reg(es8311_i2c_dev, reg, &val);
if (ret != ESP_OK) {
printf("ES8311 read failed: reg=0x%02X, ret=%d\n", reg, ret);
return 0xFF;
}
return val;
}
void es8311_init(void) {
printf("ES8311: Starting initialization...\n");
i2c_device_config_t dev_cfg = {
.device_address = ES8311_I2C_ADDR,
.scl_speed_hz = 400000,
};
esp_err_t ret = i2c_master_bus_add_device(bus, &dev_cfg, &es8311_i2c_dev);
if (ret != ESP_OK) {
printf("ES8311: Failed to add I2C device: %d\n", ret);
return;
}
es8311_write(ES8311_SDPIN_REG,
ES8311_SDPIN_FORMAT_I2S | ES8311_SDPIN_WORD_24BIT |
ES8311_SDPIN_LR_NORMAL_POLARITY | ES8311_SDPIN_UNMUTE |
ES8311_SDPIN_SEL_LEFT_TO_DAC);
es8311_write(ES8311_SDPOUT_REG,
ES8311_SDPOUT_FORMAT_I2S | ES8311_SDPOUT_WORD_24BIT |
ES8311_SDPOUT_LR_NORMAL_POLARITY | ES8311_SDPOUT_UNMUTE);
es8311_write(ES8311_RESET_REG00,
ES8311_RESET_CSM_MSC_SLAVE | ES8311_RESET_CSM_ON);
es8311_write(ES8311_CLK_MANAGER_REG07,
ES8311_CLK_MANAGER_REG07_ADCDAT_NORMAL_MODE |
ES8311_CLK_MANAGER_REG07_BCLK_LRCLK_NORMAL_MODE);
es8311_write(ES8311_CLK_MANAGER_REG01,
ES8311_CLK_MANAGER_REG01_MCLK_INV_OFF |
ES8311_CLK_MANAGER_REG01_MCLK_OFF |
ES8311_CLK_MANAGER_REG01_MCLK_SEL_FROM_BCLK |
ES8311_CLK_MANAGER_REG01_BCLK_OFF);
// mclk 12.288 MHz LRCK 48kHz
es8311_write(ES8311_CLK_MANAGER_REG02, 0x00);
es8311_write(ES8311_CLK_MANAGER_REG03, 0x10);
es8311_write(ES8311_CLK_MANAGER_REG04, 0x10);
es8311_write(ES8311_CLK_MANAGER_REG05, 0x00);
es8311_write(ES8311_ADC_REG16, 0x04); // 24 db gain
// off in slave mode, we dont care
es8311_write(ES8311_CLK_MANAGER_REG06,
ES8311_CLK_MANAGER_REG06_CONTINUAL_BCLK |
ES8311_CLK_MANAGER_REG06_NORMAL_BCLK |
ES8311_CLK_MANAGER_REG06_DIV_BCLK_3);
// lrck divider is ignored, since we are in slave mode
es8311_write(ES8311_RESET_REG00,
ES8311_RESET_CSM_MSC_SLAVE | ES8311_RESET_CSM_ON |
ES8311_RESET_DIGITAL_RUN | ES8311_RESET_CLOCK_MANAGER_RUN |
ES8311_RESET_MASTER_RUN | ES8311_RESET_ADC_DIGITAL_RUN |
ES8311_RESET_DAC_DIGITAL_RUN);
es8311_write(ES8311_SYSTEM_REG0D,
ES8311_SYSTEM_REG0D_ANALOG_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_BIAS_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_ADC_BIAS_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_ADC_REFERENCE_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_DAC_REFERENCE_ENABLED |
ES8311_SYSTEM_REG0D_VMID_START_NORMAL_SPEED);
es8311_write(ES8311_SYSTEM_REG0D,
ES8311_SYSTEM_REG0D_ANALOG_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_BIAS_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_ADC_BIAS_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_ADC_REFERENCE_ENABLED |
ES8311_SYSTEM_REG0D_ANALOG_DAC_REFERENCE_ENABLED |
ES8311_SYSTEM_REG0D_VMID_NORMAL);
es8311_write(ES8311_SYSTEM_REG0F,
ES8311_SYSTEM_REG0F_DAC_NORMAL_MODE |
ES8311_SYSTEM_REG0F_PGA_NORMAL_MODE |
ES8311_SYSTEM_REG0F_PGA_OUTPUT_NORMAL_MODE |
ES8311_SYSTEM_REG0F_VCMMOD_NORMAL_MODE |
ES8311_SYSTEM_REG0F_ADC_REFERENCE_NORMAL_MODE |
ES8311_SYSTEM_REG0F_DAC_REFERENCE_NORMAL_MODE |
ES8311_SYSTEM_REG0F_FLASH_NORMAL_MODE |
ES8311_SYSTEM_REG0F_INT1_NORMAL_MODE);
es8311_write(ES8311_SYSTEM_REG0E,
ES8311_SYSTEM_REG0E_PGA_ENABLE |
ES8311_SYSTEM_REG0E_PDN_MOD_ENABLE |
ES8311_SYSTEM_REG0E_MOD_NORMAL
);
es8311_write(ES8311_SYSTEM_REG14,
ES8311_SYSTEM_REG14_DMIC_OFF |
ES8311_SYSTEM_REG14_MIC1 |
ES8311_SYSTEM_REG14_GAIN_30DB
);
es8311_write(ES8311_ADC_REG1C,
ES8311_ADC_REG1C_HPF_DYNAMIC_HPF |
ES8311_ADC_REG1C_ADCEQ_BYPASS
);
es8311_write(ES8311_ADC_REG18,
ES8311_ADC_REG18_AUTO_LEVEL_CONTROL_ENABLE |
ES8311_ADC_REG18_AUTO_MUTE_DISABLE |
ES8311_ADC_REG18_0_25DB_PER_65536LRCK
);
es8311_write(ES8311_ADC_REG19,
ES8311_ADC_REG19_ALC_MIN_LEVEL_NEG_30_1DB |
ES8311_ADC_REG19_ALC_MAX_LEVEL_NEG_6_0DB
);
es8311_write(ES8311_ADC_REG1A,
ES8311_ADC_REG1A_AUTOMUTE_NEG_96DB |
ES8311_ADC_REG1A_AUTOMUTE_32768_SAMPLES
);
}
int audio_write(const int16_t *samples, size_t count) {
size_t written;
esp_err_t r = i2s_channel_write(i2s_tx, samples, count * sizeof(int16_t),
&written, portMAX_DELAY);
if (r != ESP_OK)
return -1;
return written / sizeof(int16_t);
}
int audio_read(int16_t *samples, size_t count) {
size_t read;
esp_err_t r = i2s_channel_read(i2s_rx, samples, count * sizeof(int16_t),
&read, portMAX_DELAY);
if (r != ESP_OK)
return -1;
return read / sizeof(int16_t);
}
void audio_beep(void) {
// ES8311 expects stereo I2S (left + right channels)
static int16_t buf[ES8311_BEEP_DURATION_SAMPLES * 2]; // *2 for stereo
for (int i = 0; i < ES8311_BEEP_DURATION_SAMPLES; i++) {
int phase = (i / ES8311_BEEP_HALF_PERIOD) & 1;
int16_t sample = phase ? ES8311_BEEP_AMPLITUDE : -ES8311_BEEP_AMPLITUDE;
buf[i * 2] = sample; // Left channel
buf[i * 2 + 1] = sample; // Right channel (same as left for mono)
}
int written = audio_write(buf, ES8311_BEEP_DURATION_SAMPLES * 2);
printf("Beep: wrote %d samples\n", written);
}
void audio_test_tone(void) {
const int sample_rate = 44100;
const int duration_ms = 1000;
const int freq_hz = 440; // A4 note
const int num_samples = (sample_rate * duration_ms) / 1000;
int16_t *buf = malloc(num_samples * 2 * sizeof(int16_t));
if (!buf) {
printf("Failed to allocate tone buffer\n");
return;
}
for (int i = 0; i < num_samples; i++) {
float t = (float)i / sample_rate;
int16_t sample = (int16_t)(sin(2.0f * M_PI * freq_hz * t) * 8000.0f);
buf[i * 2] = sample; // Left
buf[i * 2 + 1] = sample; // Right
}
printf("Playing 440Hz tone for 1 second...\n");
audio_write(buf, num_samples * 2);
free(buf);
}