182 lines
4.3 KiB
C
182 lines
4.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>
|
|
|
|
#define TAG "ES8311"
|
|
|
|
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;
|
|
}
|
|
|
|
static uint8_t db_to_es8311_vol(float db) {
|
|
if (db < -95.5f)
|
|
db = -95.5f;
|
|
if (db > 32.0f)
|
|
db = 32.0f;
|
|
|
|
// ES8311 typically uses 0.5 dB steps
|
|
int v = (int)((db + 95.5f) * 2.0f);
|
|
|
|
if (v < 0)
|
|
v = 0;
|
|
if (v > 255)
|
|
v = 255;
|
|
|
|
return (uint8_t)v;
|
|
}
|
|
|
|
void es8311_set_dac_volume(float vol) {
|
|
es8311_write(ES8311_DAC_REG32, db_to_es8311_vol(vol));
|
|
}
|
|
|
|
void es8311_set_adc_volume(float vol) {
|
|
es8311_write(ES8311_ADC_REG17, db_to_es8311_vol(vol));
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static void es8311_write_eq_coeff(uint8_t reg_base, uint32_t coeff) {
|
|
coeff &= 0x3FFFFFFF;
|
|
|
|
es8311_write(reg_base + 0, (uint8_t)((coeff >> 24) & 0x3F));
|
|
es8311_write(reg_base + 1, (uint8_t)(coeff >> 16));
|
|
es8311_write(reg_base + 2, (uint8_t)(coeff >> 8));
|
|
es8311_write(reg_base + 3, (uint8_t)(coeff));
|
|
}
|
|
void es8311_set_eq(const es8311_eq_t *eq) {
|
|
if (!eq)
|
|
return;
|
|
|
|
// B0
|
|
es8311_write_eq_coeff(0x1D, eq->b0);
|
|
|
|
// A1
|
|
es8311_write_eq_coeff(0x21, eq->a1);
|
|
|
|
// A2
|
|
es8311_write_eq_coeff(0x25, eq->a2);
|
|
|
|
// B1
|
|
es8311_write_eq_coeff(0x29, eq->b1);
|
|
|
|
// B2
|
|
es8311_write_eq_coeff(0x2D, eq->b2);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Reset sequence
|
|
es8311_write(ES8311_RESET_REG00, 0x1F);
|
|
vTaskDelay(pdMS_TO_TICKS(20));
|
|
es8311_write(ES8311_RESET_REG00, 0x00);
|
|
es8311_write(ES8311_RESET_REG00, 0x80); // Power-on command
|
|
|
|
es8311_write(ES8311_CLK_MANAGER_REG01,
|
|
ES8311_CLK_MANAGER_REG01_MCLK_SEL_FROM_BCLK |
|
|
0x3F
|
|
);
|
|
|
|
es8311_write(ES8311_CLK_MANAGER_REG06,
|
|
ES8311_CLK_MANAGER_REG06_NORMAL_BCLK |
|
|
ES8311_CLK_MANAGER_REG06_CONTINUAL_BCLK
|
|
);
|
|
}
|
|
|
|
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 = 48000;
|
|
const int duration_ms = 100;
|
|
const int freq_hz = 1000; // 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
|
|
}
|
|
|
|
audio_write(buf, num_samples * 2);
|
|
free(buf);
|
|
} |