Skip to content

Commit 3a662a9

Browse files
committed
Add support for M5Stack Atomic EchoBase
Works well with ATOMS3R.
1 parent fd01e69 commit 3a662a9

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

src/Kconfig.projbuild

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
menu "OpenAI Board Configuration"
2+
3+
choice OPENAI_BOARD_TYPE
4+
prompt "openai board type"
5+
default OPENAI_BOARD_ESP32_S3
6+
7+
config OPENAI_BOARD_ESP32_S3
8+
bool "default demo board ESP32-S3"
9+
10+
config OPENAI_BOARD_M5_ATOMS3R
11+
bool "M5Stack ATOMS3R with EchoBase"
12+
13+
endchoice
14+
15+
endmenu

src/idf_component.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
dependencies:
2+
espressif/es8311: "^1.0.0~1"
23
idf:
34
version: ">=4.1.0"

src/media.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "main.h"
55

6+
#if CONFIG_OPENAI_BOARD_ESP32_S3
67
#define OPUS_OUT_BUFFER_SIZE 1276 // 1276 bytes is recommended by opus_encode
78
#define SAMPLE_RATE 8000
89
#define BUFFER_SAMPLES 320
@@ -14,11 +15,32 @@
1415
#define ADC_BCLK_PIN 38
1516
#define ADC_LRCLK_PIN 39
1617
#define ADC_DATA_PIN 40
18+
#elif CONFIG_OPENAI_BOARD_M5_ATOMS3R
19+
#include "es8311.h"
20+
#define OPUS_OUT_BUFFER_SIZE 1276 // 1276 bytes is recommended by opus_encode
21+
#define SAMPLE_RATE 16000 //! EchoBase not support 8K sample rate :)
22+
#define BUFFER_SAMPLES (320 * 2)
23+
24+
#define I2C_PORT I2C_NUM_1
25+
#define I2C_FREQ_HZ 400000
26+
#define I2C_SCL_PIN 39
27+
#define I2C_SDA_PIN 38
28+
29+
#define I2S_PORT I2S_NUM_1
30+
#define MCLK_PIN -1
31+
#define DAC_BCLK_PIN 8
32+
#define DAC_LRCLK_PIN 6
33+
#define DAC_DATA_PIN 5
34+
#define ADC_DATA_PIN 7
35+
36+
es8311_handle_t es8311_handle = nullptr;
37+
#endif
1738

1839
#define OPUS_ENCODER_BITRATE 30000
1940
#define OPUS_ENCODER_COMPLEXITY 0
2041

2142
void oai_init_audio_capture() {
43+
#if CONFIG_OPENAI_BOARD_ESP32_S3
2244
i2s_config_t i2s_config_out = {
2345
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
2446
.sample_rate = SAMPLE_RATE,
@@ -76,6 +98,74 @@ void oai_init_audio_capture() {
7698
printf("Failed to set I2S pins for audio input");
7799
return;
78100
}
101+
#elif CONFIG_OPENAI_BOARD_M5_ATOMS3R
102+
i2c_config_t conf = {
103+
.mode = I2C_MODE_MASTER,
104+
.sda_io_num = I2C_SDA_PIN,
105+
.scl_io_num = I2C_SCL_PIN,
106+
.sda_pullup_en = GPIO_PULLUP_ENABLE,
107+
.scl_pullup_en = GPIO_PULLUP_ENABLE,
108+
.master =
109+
{
110+
.clk_speed = I2C_FREQ_HZ,
111+
}
112+
};
113+
114+
i2c_param_config(I2C_PORT, &conf);
115+
i2c_driver_install(I2C_PORT, conf.mode, 0, 0, 0);
116+
117+
es8311_handle = es8311_create(I2C_PORT, ES8311_ADDRRES_0);
118+
if (es8311_handle == nullptr) {
119+
printf("Failed to create ES8311 handle");
120+
return;
121+
}
122+
123+
es8311_clock_config_t clk_cfg = {
124+
.mclk_inverted = false,
125+
.sclk_inverted = false,
126+
.mclk_from_mclk_pin = false,
127+
.sample_frequency = SAMPLE_RATE,
128+
};
129+
130+
if (es8311_init(es8311_handle, &clk_cfg, ES8311_RESOLUTION_32,
131+
ES8311_RESOLUTION_32) != ESP_OK) {
132+
printf("Failed to initialize ES8311");
133+
return;
134+
}
135+
136+
es8311_voice_volume_set(es8311_handle, 80, NULL);
137+
es8311_microphone_config(es8311_handle, false);
138+
139+
i2s_config_t i2s_config = {
140+
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX),
141+
.sample_rate = SAMPLE_RATE,
142+
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
143+
.channel_format = I2S_CHANNEL_FMT_ALL_LEFT, //! Important for EchoBase
144+
.communication_format = I2S_COMM_FORMAT_I2S,
145+
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
146+
.dma_buf_count = 8,
147+
.dma_buf_len = BUFFER_SAMPLES,
148+
.use_apll = 1,
149+
.tx_desc_auto_clear = true,
150+
};
151+
if (i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL) != ESP_OK) {
152+
printf("Failed to configure I2S driver for audio input/output");
153+
return;
154+
}
155+
156+
i2s_pin_config_t pin_config_out = {
157+
.mck_io_num = -1,
158+
.bck_io_num = DAC_BCLK_PIN,
159+
.ws_io_num = DAC_LRCLK_PIN,
160+
.data_out_num = DAC_DATA_PIN,
161+
.data_in_num = ADC_DATA_PIN,
162+
};
163+
if (i2s_set_pin(I2S_PORT, &pin_config_out) != ESP_OK) {
164+
printf("Failed to set I2S pins for audio output");
165+
return;
166+
}
167+
i2s_zero_dma_buffer(I2S_PORT);
168+
#endif
79169
}
80170

81171
opus_int16 *output_buffer = NULL;
@@ -98,8 +188,13 @@ void oai_audio_decode(uint8_t *data, size_t size) {
98188

99189
if (decoded_size > 0) {
100190
size_t bytes_written = 0;
191+
#if CONFIG_OPENAI_BOARD_ESP32_S3
101192
i2s_write(I2S_NUM_0, output_buffer, BUFFER_SAMPLES * sizeof(opus_int16),
102193
&bytes_written, portMAX_DELAY);
194+
#elif CONFIG_OPENAI_BOARD_M5_ATOMS3R
195+
i2s_write(I2S_PORT, output_buffer, BUFFER_SAMPLES * sizeof(opus_int16),
196+
&bytes_written, portMAX_DELAY);
197+
#endif
103198
}
104199
}
105200

@@ -132,8 +227,13 @@ void oai_init_audio_encoder() {
132227
void oai_send_audio(PeerConnection *peer_connection) {
133228
size_t bytes_read = 0;
134229

230+
#if CONFIG_OPENAI_BOARD_ESP32_S3
135231
i2s_read(I2S_NUM_1, encoder_input_buffer, BUFFER_SAMPLES, &bytes_read,
136232
portMAX_DELAY);
233+
#elif CONFIG_OPENAI_BOARD_M5_ATOMS3R
234+
i2s_read(I2S_PORT, encoder_input_buffer, BUFFER_SAMPLES, &bytes_read,
235+
portMAX_DELAY);
236+
#endif
137237

138238
auto encoded_size =
139239
opus_encode(opus_encoder, encoder_input_buffer, BUFFER_SAMPLES / 2,

src/webrtc.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,19 @@ static void oai_onconnectionstatechange_task(PeerConnectionState state,
3737
#endif
3838
} else if (state == PEER_CONNECTION_CONNECTED) {
3939
#ifndef LINUX_BUILD
40+
#if CONFIG_OPENAI_BOARD_ESP32_S3
4041
StackType_t *stack_memory = (StackType_t *)heap_caps_malloc(
4142
20000 * sizeof(StackType_t), MALLOC_CAP_SPIRAM);
4243
xTaskCreateStaticPinnedToCore(oai_send_audio_task, "audio_publisher", 20000,
4344
NULL, 7, stack_memory, &task_buffer, 0);
45+
#elif CONFIG_OPENAI_BOARD_M5_ATOMS3R
46+
// Because we change the sampling rate to 16K, so we need increased the
47+
// memory size, if not will overflow :)
48+
StackType_t *stack_memory = (StackType_t *)heap_caps_malloc(
49+
40000 * sizeof(StackType_t), MALLOC_CAP_SPIRAM);
50+
xTaskCreateStaticPinnedToCore(oai_send_audio_task, "audio_publisher", 40000,
51+
NULL, 7, stack_memory, &task_buffer, 0);
52+
#endif
4453
#endif
4554
}
4655
}

0 commit comments

Comments
 (0)