Skip to content

Commit f2537d3

Browse files
committed
audio: add internal dac and pdm output mode
1 parent bb2ea74 commit f2537d3

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

main/src/device/i2s.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,40 @@
1010

1111
void i2s0_init(void)
1212
{
13-
int use_apll = 0;
1413
esp_chip_info_t chip_info;
1514
esp_chip_info(&chip_info);
16-
// Don't use apll on rev0 chips
17-
if (chip_info.revision != 0) {
18-
use_apll = 1;
19-
}
2015
i2s_config_t i2s_config = {
16+
#if defined(CONFIG_I2S_OUTPUT_INTERNAL_DAC)
17+
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
18+
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
19+
.use_apll = 0,
20+
#elif defined(CONFIG_I2S_OUTPUT_PDM)
21+
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM,
22+
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
23+
.use_apll = 0,
24+
#else
2125
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
26+
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
27+
.use_apll = chip_info.revision, // Don't use apll on rev0 chips
28+
#endif
2229
.sample_rate = 44100,
23-
.bits_per_sample = 16,
30+
.bits_per_sample = 16,
2431
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
25-
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
2632
.dma_buf_count = 8,
2733
.dma_buf_len = 64,
28-
.use_apll = use_apll,
2934
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1
3035
};
36+
i2s_driver_install(0, &i2s_config, 0, NULL);
37+
#if defined(CONFIG_I2S_OUTPUT_INTERNAL_DAC) || defined(CONFIG_I2S_OUTPUT_PDM)
38+
i2s_set_pin(0, NULL);
39+
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
40+
#else
3141
i2s_pin_config_t pin_config = {
3242
.bck_io_num = 22,
3343
.ws_io_num = 21,
3444
.data_out_num = 19,
3545
.data_in_num = -1 // Not used
3646
};
37-
i2s_driver_install(0, &i2s_config, 0, NULL);
3847
i2s_set_pin(0, &pin_config);
48+
#endif
3949
}

main/src/tasks/bt_av.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,43 @@ void bt_av_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
5454
/* cb with decoded samples */
5555
void bt_av_a2d_data_cb(const uint8_t *data, uint32_t len)
5656
{
57-
i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY);
57+
TickType_t max_wait = 20 / portTICK_PERIOD_MS;
58+
#if defined(CONFIG_I2S_OUTPUT_INTERNAL_DAC)
59+
uint8_t num_channel = 2;
60+
uint8_t bytes_per_sample = sizeof(uint8_t) * 2; // 16-bit per channel
61+
uint8_t stride = bytes_per_sample * num_channel;
62+
63+
// pointer to left / right sample position
64+
char *ptr_l = (char *)data;
65+
char *ptr_r = (char *)data + stride;
66+
67+
int bytes_pushed = 0;
68+
for (int i = 0; i < len/stride; i++) {
69+
// assume 16 bit src bit_depth
70+
short left = *(short *) ptr_l;
71+
short right = *(short *) ptr_r;
72+
73+
// The built-in DAC wants unsigned samples, so we shift the range
74+
// from -32768-32767 to 0-65535.
75+
left = left + 0x8000;
76+
right = right + 0x8000;
77+
78+
uint32_t sample = (uint16_t) left;
79+
sample = (sample << 16 & 0xffff0000) | ((uint16_t) right);
80+
81+
bytes_pushed = i2s_push_sample(0, (const char*) &sample, max_wait);
82+
83+
// DMA buffer full - retry
84+
if (bytes_pushed == 0) {
85+
i--;
86+
} else {
87+
ptr_r += stride;
88+
ptr_l += stride;
89+
}
90+
}
91+
#else
92+
i2s_write_bytes(0, (const char *)data, len, max_wait);
93+
#endif
5894
}
5995

6096
void bt_av_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)

main/src/tasks/mp3_player.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ void mp3_player_task(void *pvParameters)
8484
/* render callback for the libmad synth */
8585
void render_sample_block(short *sample_buff_ch0, short *sample_buff_ch1, int num_samples, unsigned int num_channels)
8686
{
87+
TickType_t max_wait = 20 / portTICK_PERIOD_MS;
88+
8789
// pointer to left / right sample position
8890
char *ptr_l = (char*) sample_buff_ch0;
8991
char *ptr_r = (char*) sample_buff_ch1;
@@ -94,12 +96,26 @@ void render_sample_block(short *sample_buff_ch0, short *sample_buff_ch1, int num
9496
}
9597

9698
int bytes_pushed = 0;
97-
TickType_t max_wait = 20 / portTICK_PERIOD_MS; // portMAX_DELAY = bad idea
9899
for (int i = 0; i < num_samples; i++) {
100+
#if defined(CONFIG_I2S_OUTPUT_INTERNAL_DAC)
101+
// assume 16 bit src bit_depth
102+
short left = *(short *) ptr_l;
103+
short right = *(short *) ptr_r;
104+
105+
// The built-in DAC wants unsigned samples, so we shift the range
106+
// from -32768-32767 to 0-65535.
107+
left = left + 0x8000;
108+
right = right + 0x8000;
109+
110+
uint32_t sample = (uint16_t) left;
111+
sample = (sample << 16 & 0xffff0000) | ((uint16_t) right);
112+
113+
bytes_pushed = i2s_push_sample(0, (const char*) &sample, max_wait);
114+
#else
99115
/* low - high / low - high */
100116
const char samp32[4] = {ptr_l[0], ptr_l[1], ptr_r[0], ptr_r[1]};
101117
bytes_pushed = i2s_push_sample(0, (const char*) &samp32, max_wait);
102-
118+
#endif
103119
// DMA buffer full - retry
104120
if (bytes_pushed == 0) {
105121
i--;

0 commit comments

Comments
 (0)