Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(SOURCES "audio_codecs/audio_codec.cc"
"audio_codecs/no_audio_codec.cc"
"audio_codecs/box_audio_codec.cc"
"audio_codecs/es8311_audio_codec.cc"
"audio_codecs/es8374_audio_codec.cc"
"audio_codecs/es8388_audio_codec.cc"
"led/single_led.cc"
"led/circular_strip.cc"
Expand Down Expand Up @@ -136,6 +137,8 @@ elseif(CONFIG_BOARD_TYPE_SENSECAP_WATCHER)
set(BOARD_TYPE "sensecap-watcher")
elseif(CONFIG_BOARD_TYPE_DOIT_S3_AIBOX)
set(BOARD_TYPE "doit-s3-aibox")
elseif(CONFIG_BOARD_TYPE_MIXGO_NOVA)
set(BOARD_TYPE "mixgo-nova")
elseif(CONFIG_BOARD_TYPE_ESP32_CGC)
set(BOARD_TYPE "esp32-cgc")
endif()
Expand Down
2 changes: 2 additions & 0 deletions main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ choice BOARD_TYPE
bool "SenseCAP Watcher"
config BOARD_TYPE_DOIT_S3_AIBOX
bool "四博智联AI陪伴盒子"
config BOARD_TYPE_MIXGO_NOVA
bool "元控·青春"
endchoice

choice DISPLAY_OLED_TYPE
Expand Down
194 changes: 194 additions & 0 deletions main/audio_codecs/es8374_audio_codec.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#include "es8374_audio_codec.h"

#include <esp_log.h>

static const char TAG[] = "Es8374AudioCodec";

Es8374AudioCodec::Es8374AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate,
gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din,
gpio_num_t pa_pin, uint8_t es8374_addr, bool use_mclk) {
duplex_ = true; // 是否双工
input_reference_ = false; // 是否使用参考输入,实现回声消除
input_channels_ = 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
pa_pin_ = pa_pin;
CreateDuplexChannels(mclk, bclk, ws, dout, din);

// Do initialize of related interface: data_if, ctrl_if and gpio_if
audio_codec_i2s_cfg_t i2s_cfg = {
.port = I2S_NUM_0,
.rx_handle = rx_handle_,
.tx_handle = tx_handle_,
};
data_if_ = audio_codec_new_i2s_data(&i2s_cfg);
assert(data_if_ != NULL);

// Output
audio_codec_i2c_cfg_t i2c_cfg = {
.port = i2c_port,
.addr = es8374_addr,
.bus_handle = i2c_master_handle,
};
ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg);
assert(ctrl_if_ != NULL);

gpio_if_ = audio_codec_new_gpio();
assert(gpio_if_ != NULL);

es8374_codec_cfg_t es8374_cfg = {};
es8374_cfg.ctrl_if = ctrl_if_;
es8374_cfg.gpio_if = gpio_if_;
es8374_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH;
es8374_cfg.pa_pin = pa_pin;
codec_if_ = es8374_codec_new(&es8374_cfg);
assert(codec_if_ != NULL);

esp_codec_dev_cfg_t dev_cfg = {
.dev_type = ESP_CODEC_DEV_TYPE_OUT,
.codec_if = codec_if_,
.data_if = data_if_,
};
output_dev_ = esp_codec_dev_new(&dev_cfg);
assert(output_dev_ != NULL);
dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN;
input_dev_ = esp_codec_dev_new(&dev_cfg);
assert(input_dev_ != NULL);
esp_codec_set_disable_when_closed(output_dev_, false);
esp_codec_set_disable_when_closed(input_dev_, false);
ESP_LOGI(TAG, "Es8374AudioCodec initialized");
}

Es8374AudioCodec::~Es8374AudioCodec() {
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
esp_codec_dev_delete(output_dev_);
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
esp_codec_dev_delete(input_dev_);

audio_codec_delete_codec_if(codec_if_);
audio_codec_delete_ctrl_if(ctrl_if_);
audio_codec_delete_gpio_if(gpio_if_);
audio_codec_delete_data_if(data_if_);
}

void Es8374AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) {
assert(input_sample_rate_ == output_sample_rate_);

i2s_chan_config_t chan_cfg = {
.id = I2S_NUM_0,
.role = I2S_ROLE_MASTER,
.dma_desc_num = 6,
.dma_frame_num = 240,
.auto_clear_after_cb = true,
.auto_clear_before_cb = false,
.intr_priority = 0,
};
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_));

i2s_std_config_t std_cfg = {
.clk_cfg = {
.sample_rate_hz = (uint32_t)output_sample_rate_,
.clk_src = I2S_CLK_SRC_DEFAULT,
.mclk_multiple = I2S_MCLK_MULTIPLE_256,
#ifdef I2S_HW_VERSION_2
.ext_clk_freq_hz = 0,
#endif
},
.slot_cfg = {
.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO,
.slot_mode = I2S_SLOT_MODE_STEREO,
.slot_mask = I2S_STD_SLOT_BOTH,
.ws_width = I2S_DATA_BIT_WIDTH_16BIT,
.ws_pol = false,
.bit_shift = true,
#ifdef I2S_HW_VERSION_2
.left_align = true,
.big_endian = false,
.bit_order_lsb = false
#endif
},
.gpio_cfg = {
.mclk = mclk,
.bclk = bclk,
.ws = ws,
.dout = dout,
.din = din,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false
}
}
};

ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg));
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg));
ESP_LOGI(TAG, "Duplex channels created");
}

void Es8374AudioCodec::SetOutputVolume(int volume) {
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume));
AudioCodec::SetOutputVolume(volume);
}

void Es8374AudioCodec::EnableInput(bool enable) {
if (enable == input_enabled_) {
return;
}
if (enable) {
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)input_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 40.0));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
AudioCodec::EnableInput(enable);
}

void Es8374AudioCodec::EnableOutput(bool enable) {
if (enable == output_enabled_) {
return;
}
if (enable) {
// Play 16bit 1 channel
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)output_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_));
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 1);
}
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 0);
}
}
AudioCodec::EnableOutput(enable);
}

int Es8374AudioCodec::Read(int16_t* dest, int samples) {
if (input_enabled_) {
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t)));
}
return samples;
}

int Es8374AudioCodec::Write(const int16_t* data, int samples) {
if (output_enabled_) {
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t)));
}
return samples;
}
38 changes: 38 additions & 0 deletions main/audio_codecs/es8374_audio_codec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef _ES8374_AUDIO_CODEC_H
#define _ES8374_AUDIO_CODEC_H

#include "audio_codec.h"

#include <driver/i2c.h>
#include <driver/gpio.h>
#include <esp_codec_dev.h>
#include <esp_codec_dev_defaults.h>

class Es8374AudioCodec : public AudioCodec {
private:
const audio_codec_data_if_t* data_if_ = nullptr;
const audio_codec_ctrl_if_t* ctrl_if_ = nullptr;
const audio_codec_if_t* codec_if_ = nullptr;
const audio_codec_gpio_if_t* gpio_if_ = nullptr;

esp_codec_dev_handle_t output_dev_ = nullptr;
esp_codec_dev_handle_t input_dev_ = nullptr;
gpio_num_t pa_pin_ = GPIO_NUM_NC;

void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din);

virtual int Read(int16_t* dest, int samples) override;
virtual int Write(const int16_t* data, int samples) override;

public:
Es8374AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate,
gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din,
gpio_num_t pa_pin, uint8_t es8374_addr, bool use_mclk = true);
virtual ~Es8374AudioCodec();

virtual void SetOutputVolume(int volume) override;
virtual void EnableInput(bool enable) override;
virtual void EnableOutput(bool enable) override;
};

#endif // _ES8374_AUDIO_CODEC_H
72 changes: 72 additions & 0 deletions main/boards/mixgo-nova/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Mixgo_Nova(元控·青春) 开发板

<img src="https://mixly.cn/public/icon/2024/6/09705006c1c643beb96338791ee1dea0_m.png" alt="Mixgo_Nova" width="200"/>

&zwnj;**[Mixgo_Nova](https://mixly.cn/fredqian/mixgo_nova)**&zwnj; 是一款专为物联网、教育及创客项目设计的多功能开发板,集成丰富传感器与无线通信模块,支持图形化编程(Mixly)和离线语音交互,适合快速原型开发与教学。

---

## 🛠️ 编译配置命令

**ES8374 CODE MIC采集问题:**

```
managed_components\espressif__esp_codec_dev\device\es8374

static int es8374_config_adc_input(audio_codec_es8374_t *codec, es_adc_input_t input)
{
int ret = 0;
int reg = 0;
ret |= es8374_read_reg(codec, 0x21, &reg);
if (ret == 0) {
reg = (reg & 0xcf) | 0x24;
ret |= es8374_write_reg(codec, 0x21, reg);
}
return ret;
}

PS: L386 reg = (reg & 0xcf) | 0x14; 改成 reg = (reg & 0xcf) | 0x24;
```

**配置编译目标为 ESP32S3:**

```bash
idf.py set-target esp32s3
```

**打开 menuconfig:**

```bash
idf.py menuconfig
```

**选择板子:**

```
Xiaozhi Assistant -> Board Type -> 元控·青春
```

**修改 psram 配置:**

```
Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> QUAD Mode PSRAM
```

**修改 Flash 配置:**

```
Serial flasher config -> Flash size -> 8 MB
Partition Table -> Custom partition CSV file -> partitions_8M.csv
```

**编译:**

```bash
idf.py build
```

**合并BIN:**

```bash
idf.py merge-bin -o xiaozhi-nova.bin -f raw
```
42 changes: 42 additions & 0 deletions main/boards/mixgo-nova/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_

#include <driver/gpio.h>

#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000

#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_35
#define AUDIO_I2S_GPIO_WS GPIO_NUM_47
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_34
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_33
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48

#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_37
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_36
#define AUDIO_CODEC_ES8374_ADDR ES8374_CODEC_DEFAULT_ADDR

#define BUILTIN_LED_GPIO GPIO_NUM_38
#define BOOT_BUTTON_GPIO GPIO_NUM_0
#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC
#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC

#define DISPLAY_MOSI_PIN GPIO_NUM_40
#define DISPLAY_CLK_PIN GPIO_NUM_41
#define DISPLAY_DC_PIN GPIO_NUM_18
#define DISPLAY_CS_PIN GPIO_NUM_45
#define DISPLAY_RST_PIN GPIO_NUM_NC
#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_14
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 160
#define DISPLAY_MIRROR_X true
#define DISPLAY_MIRROR_Y true
#define DISPLAY_SWAP_XY false
#define DISPLAY_INVERT_COLOR false
#define DISPLAY_OFFSET_X 2
#define DISPLAY_OFFSET_Y 1
#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false

#endif // _BOARD_CONFIG_H_
14 changes: 14 additions & 0 deletions main/boards/mixgo-nova/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"target": "esp32s3",
"builds": [
{
"name": "mixgo-nova",
"sdkconfig_append": [
"CONFIG_SPIRAM_MODE_QUAD=y",
"CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y",
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions_8M.csv\"",
"CONFIG_LCD_ST7735_128X160=y"
]
}
]
}
Loading
Loading