fix i2s mix result and error code

This commit is contained in:
Zhang Zhao Xiang 2018-04-11 19:37:31 +08:00
parent f147a8d73d
commit 9deb58859c
5 changed files with 199 additions and 157 deletions

190
components/driver/i2s.c Executable file → Normal file
View file

@ -226,7 +226,7 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2
* @param[out] sdm2 The sdm 2 * @param[out] sdm2 The sdm 2
* @param[out] odir The odir * @param[out] odir The odir
* *
* @return ESP_FAIL or ESP_OK * @return ESP_ERR_INVALID_ARG or ESP_OK
*/ */
static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
@ -303,7 +303,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
if (p_i2s_obj[i2s_num] == NULL) { if (p_i2s_obj[i2s_num] == NULL) {
ESP_LOGE(I2S_TAG, "Not initialized yet"); ESP_LOGE(I2S_TAG, "Not initialized yet");
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
p_i2s_obj[i2s_num]->sample_rate = rate; p_i2s_obj[i2s_num]->sample_rate = rate;
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor); double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
@ -541,21 +541,26 @@ static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma)
int bux_idx; int bux_idx;
if (p_i2s_obj[i2s_num] == NULL) { if (p_i2s_obj[i2s_num] == NULL) {
ESP_LOGE(I2S_TAG, "Not initialized yet"); ESP_LOGE(I2S_TAG, "Not initialized yet");
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
if (dma == NULL) { if (dma == NULL) {
return ESP_FAIL; ESP_LOGE(I2S_TAG, "dma is NULL");
return ESP_ERR_INVALID_ARG;
} }
for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) {
if (dma->desc && dma->desc[bux_idx]) if (dma->desc && dma->desc[bux_idx]) {
free(dma->desc[bux_idx]); free(dma->desc[bux_idx]);
if (dma->buf && dma->buf[bux_idx]) }
if (dma->buf && dma->buf[bux_idx]) {
free(dma->buf[bux_idx]); free(dma->buf[bux_idx]);
} }
if (dma->buf) }
if (dma->buf) {
free(dma->buf); free(dma->buf);
if (dma->desc) }
if (dma->desc) {
free(dma->desc); free(dma->desc);
}
vQueueDelete(dma->queue); vQueueDelete(dma->queue);
vSemaphoreDelete(dma->mux); vSemaphoreDelete(dma->mux);
free(dma); free(dma);
@ -999,10 +1004,11 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
} }
} }
if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) {
int bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; int bytes_left = 0;
bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4;
if (bytes_left) { if (bytes_left) {
int zero_bytes = 0; size_t zero_bytes = 0, bytes_written;
i2s_write_bytes(i2s_num, (const char *)&zero_bytes, bytes_left, portMAX_DELAY); i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY);
} }
for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) {
memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size);
@ -1113,14 +1119,28 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
return ESP_OK; return ESP_OK;
} }
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait) int i2s_write_bytes(i2s_port_t i2s_num, const void *src, size_t size, TickType_t ticks_to_wait)
{ {
char *data_ptr; size_t bytes_written = 0;
int bytes_can_write, bytes_writen = 0; int res = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); res = i2s_write(i2s_num, src, size, &bytes_written, ticks_to_wait);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); if (res != ESP_OK) {
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL); return ESP_FAIL;
} else {
return bytes_written;
}
}
esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait)
{
char *data_ptr, *src_byte;
int bytes_can_write;
*bytes_written = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
src_byte = (char *)src;
while (size > 0) { while (size > 0) {
if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
@ -1135,14 +1155,14 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t
if (bytes_can_write > size) { if (bytes_can_write > size) {
bytes_can_write = size; bytes_can_write = size;
} }
memcpy(data_ptr, src, bytes_can_write); memcpy(data_ptr, src_byte, bytes_can_write);
size -= bytes_can_write; size -= bytes_can_write;
src += bytes_can_write; src_byte += bytes_can_write;
p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
bytes_writen += bytes_can_write; (*bytes_written) += bytes_can_write;
} }
xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
return bytes_writen; return ESP_OK;
} }
esp_err_t i2s_adc_enable(i2s_port_t i2s_num) esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
@ -1166,33 +1186,37 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
return ESP_OK; return ESP_OK;
} }
int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits, int aim_bits, TickType_t ticks_to_wait) esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
{ {
char *data_ptr; char *data_ptr;
int bytes_can_write, bytes_writen = 0, tail; int bytes_can_write, tail;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); int src_bytes, aim_bytes, zero_bytes;
I2S_CHECK((size > 0), "size must greater than zero", ESP_FAIL); *bytes_written = 0;
I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_FAIL); I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL); I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) {
ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits);
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) {
ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits);
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) {
ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size);
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) { if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) {
ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size); ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size);
return ESP_FAIL; return ESP_ERR_INVALID_ARG;
} }
int src_bytes = src_bits / 8, aim_bytes = aim_bits / 8;
int zero_bytes = aim_bytes - src_bytes; src_bytes = src_bits / 8;
aim_bytes = aim_bits / 8;
zero_bytes = aim_bytes - src_bytes;
xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
size = size * aim_bytes / src_bytes; size = size * aim_bytes / src_bytes;
ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size);
@ -1215,23 +1239,37 @@ int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits
memset(data_ptr, 0, bytes_can_write); memset(data_ptr, 0, bytes_can_write);
for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) { for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) {
j += zero_bytes; j += zero_bytes;
memcpy(&data_ptr[j], &src[bytes_writen], aim_bytes - zero_bytes); memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes);
bytes_writen += (aim_bytes - zero_bytes); (*bytes_written) += (aim_bytes - zero_bytes);
} }
size -= bytes_can_write; size -= bytes_can_write;
p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
} }
xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
return bytes_writen; return ESP_OK;
} }
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait) int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks_to_wait)
{ {
char *data_ptr; size_t bytes_read = 0;
int bytes_can_read, byte_read = 0; int res = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); res = i2s_read(i2s_num, dest, size, &bytes_read, ticks_to_wait);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); if (res != ESP_OK) {
I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_FAIL); return ESP_FAIL;
} else {
return bytes_read;
}
}
esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
{
char *data_ptr, *dest_byte;
int bytes_can_read;
*bytes_read = 0;
dest_byte = (char *)dest;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG);
xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
while (size > 0) { while (size > 0) {
if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) {
@ -1246,62 +1284,40 @@ int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks
if (bytes_can_read > size) { if (bytes_can_read > size) {
bytes_can_read = size; bytes_can_read = size;
} }
memcpy(dest, data_ptr, bytes_can_read); memcpy(dest_byte, data_ptr, bytes_can_read);
size -= bytes_can_read; size -= bytes_can_read;
dest += bytes_can_read; dest_byte += bytes_can_read;
p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read; p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read;
byte_read += bytes_can_read; (*bytes_read) += bytes_can_read;
} }
xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux);
return byte_read; return ESP_OK;
} }
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait) int i2s_push_sample(i2s_port_t i2s_num, const void *sample, TickType_t ticks_to_wait)
{ {
int i, bytes_to_push = 0; size_t bytes_push = 0;
char *data_ptr; int res = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { res = i2s_write(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_push, ticks_to_wait);
if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { if (res != ESP_OK) {
return bytes_to_push; return ESP_FAIL;
} else {
return bytes_push;
} }
ESP_LOGD(I2S_TAG, "rw_pos: %d, buf_size: %d, curr_ptr: %d", p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr);
p_i2s_obj[i2s_num]->tx->rw_pos = 0;
}
data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr;
data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos;
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; i++) {
*data_ptr++ = *sample++;
bytes_to_push ++;
}
p_i2s_obj[i2s_num]->tx->rw_pos += bytes_to_push;
return bytes_to_push;
} }
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait) int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait)
{ {
int i, bytes_to_pop = 0; size_t bytes_pop = 0;
char *data_ptr; int res = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { res = i2s_read(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_pop, ticks_to_wait);
if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { if (res != ESP_OK) {
return bytes_to_pop; return ESP_FAIL;
} else {
return bytes_pop;
} }
p_i2s_obj[i2s_num]->rx->rw_pos = 0;
}
data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr;
data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos;
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
*sample++ = *data_ptr++;
bytes_to_pop++;
}
if (p_i2s_obj[i2s_num]->channel_num == 2) {
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
*sample++ = *data_ptr++;
bytes_to_pop++;
}
}
p_i2s_obj[i2s_num]->rx->rw_pos += p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
return bytes_to_pop;
} }

91
components/driver/include/driver/i2s.h Executable file → Normal file
View file

@ -260,6 +260,18 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
*/ */
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num); esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
/**
* @brief Write data to I2S DMA transmit buffer.
*
* This function is deprecated. Use 'i2s_write' instead.
* This definition will be removed in a future release.
*
* @return
* - The amount of bytes written, if timeout, the result will be less than the size passed in.
* - ESP_FAIL Parameter error
*/
int i2s_write_bytes(i2s_port_t i2s_num, const void *src, size_t size, TickType_t ticks_to_wait) __attribute__ ((deprecated));
/** /**
* @brief Write data to I2S DMA transmit buffer. * @brief Write data to I2S DMA transmit buffer.
* *
@ -269,6 +281,8 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
* *
* @param size Size of data in bytes * @param size Size of data in bytes
* *
* @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in.
*
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* many ticks pass without space becoming available in the DMA * many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the * transmit buffer, then the function will return (note that if the
@ -276,14 +290,11 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
* may still take longer than this timeout.) Pass portMAX_DELAY for no * may still take longer than this timeout.) Pass portMAX_DELAY for no
* timeout. * timeout.
* *
* Format of the data in source buffer is determined by the I2S
* configuration (see i2s_config_t).
*
* @return * @return
* - Number of bytes written, if timeout occurred, bytes written will be less than the size passed. * - ESP_OK Success
* - ESP_FAIL Parameter error. * - ESP_ERR_INVALID_ARG Parameter error
*/ */
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait); esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait);
/** /**
* @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM. * @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM.
@ -298,6 +309,8 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t
* *
* @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits
* *
* @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in.
*
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* many ticks pass without space becoming available in the DMA * many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the * transmit buffer, then the function will return (note that if the
@ -309,10 +322,22 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t
* configuration (see i2s_config_t). * configuration (see i2s_config_t).
* *
* @return * @return
* - Number of bytes written, if timeout occurred, bytes written will be less than the size passed. * - ESP_OK Success
* - ESP_FAIL Parameter error. * - ESP_ERR_INVALID_ARG Parameter error
*/ */
int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits, int aim_bits, TickType_t ticks_to_wait); esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait);
/**
* @brief Read data from I2S DMA receive buffer
*
* This function is deprecated. Use 'i2s_read' instead.
* This definition will be removed in a future release.
*
* @return
* - The amount of bytes read, if timeout, bytes read will be less than the size passed in
* - ESP_FAIL Parameter error
*/
int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks_to_wait) __attribute__ ((deprecated));
/** /**
* @brief Read data from I2S DMA receive buffer * @brief Read data from I2S DMA receive buffer
@ -323,53 +348,54 @@ int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits
* *
* @param size Size of data in bytes * @param size Size of data in bytes
* *
* @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in.
*
* @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
* *
* Format of the data in source buffer is determined by the I2S
* configuration (see i2s_config_t).
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process, * @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
* to prevent the data getting corrupted. * to prevent the data getting corrupted.
* *
* @return * @return
* - Number of bytes read, if timeout occurred, bytes written will be less than the size passed. * - ESP_OK Success
* - ESP_FAIL Parameter error. * - ESP_ERR_INVALID_ARG Parameter error
*/ */
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait); esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);
/** /**
* @brief Push (write) a single sample to the I2S DMA TX buffer. * @brief Write a single sample to the I2S DMA TX buffer.
* *
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t). * This function is deprecated. Use 'i2s_write' instead.
* This definition will be removed in a future release.
* *
* @param i2s_num I2S_NUM_0, I2S_NUM_1 * @param i2s_num I2S_NUM_0, I2S_NUM_1
* *
* @param sample Pointer to buffer containing sample to write. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8. * @param sample Buffer to read data. Size of buffer (in bytes) = bits_per_sample / 8.
* *
* @param ticks_to_wait Push timeout in RTOS ticks. If space is not available in the DMA TX buffer within this period, no data is written and function returns 0. * @param ticks_to_wait Timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero.
* *
* @return * @return
* - Number of bytes successfully pushed to DMA buffer, will be either zero or the size of configured sample buffer. * - Number of bytes successfully pushed to DMA buffer, will be either zero or the size of configured sample buffer (in bytes).
* - ESP_FAIL Parameter error. * - ESP_FAIL Parameter error
*/ */
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait); int i2s_push_sample(i2s_port_t i2s_num, const void *sample, TickType_t ticks_to_wait) __attribute__ ((deprecated));
/** /**
* @brief Pop (read) a single sample from the I2S DMA RX buffer. * @brief Read a single sample from the I2S DMA RX buffer.
* *
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t). * This function is deprecated. Use 'i2s_read' instead.
* This definition will be removed in a future release.
* *
* @param i2s_num I2S_NUM_0, I2S_NUM_1 * @param i2s_num I2S_NUM_0, I2S_NUM_1
* *
* @param sample Buffer sample data will be read into. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8. * @param sample Buffer to write data. Size of buffer (in bytes) = bits_per_sample / 8.
* *
* @param ticks_to_wait Pop timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero. * @param ticks_to_wait Timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero.
* *
* @return * @return
* - Number of bytes successfully read from DMA buffer, will be either zero or the size of configured sample buffer. * - Number of bytes successfully read from DMA buffer, will be either zero or the size of configured sample buffer (in bytes).
* - ESP_FAIL Parameter error. * - ESP_FAIL Parameter error
*/ */
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait); int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait) __attribute__ ((deprecated));
/** /**
* @brief Set sample rate used for I2S RX and TX. * @brief Set sample rate used for I2S RX and TX.
@ -385,7 +411,6 @@ int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL I2s is not initialized
* - ESP_ERR_NO_MEM Out of memory * - ESP_ERR_NO_MEM Out of memory
*/ */
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate); esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate);
@ -445,7 +470,6 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_FAIL Not initialized
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM Out of memory * - ESP_ERR_NO_MEM Out of memory
*/ */
@ -471,8 +495,7 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error * - ESP_ERR_INVALID_STATE Driver state error
* - ESP_FAIL Internal driver error
*/ */
esp_err_t i2s_adc_enable(i2s_port_t i2s_num); esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
@ -483,7 +506,7 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error * - ESP_ERR_INVALID_STATE Driver state error
*/ */
esp_err_t i2s_adc_disable(i2s_port_t i2s_num); esp_err_t i2s_adc_disable(i2s_port_t i2s_num);

View file

@ -53,7 +53,8 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
{ {
i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY); size_t bytes_written;
i2s_write(0, data, len, &bytes_written, portMAX_DELAY);
if (++m_pkt_cnt % 100 == 0) { if (++m_pkt_cnt % 100 == 0) {
ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt); ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt);
} }

View file

@ -29,6 +29,7 @@ static void setup_triangle_sine_waves(int bits)
int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4); int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4);
unsigned int i, sample_val; unsigned int i, sample_val;
double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE; double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE;
size_t i2s_bytes_write = 0;
printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits+8)/16)*SAMPLE_PER_CYCLE*4); printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits+8)/16)*SAMPLE_PER_CYCLE*4);
@ -68,7 +69,7 @@ static void setup_triangle_sine_waves(int bits)
// i2s_push_sample(0, &samples_data[i*2], 100); // i2s_push_sample(0, &samples_data[i*2], 100);
// } // }
// or write // or write
i2s_write_bytes(I2S_NUM, (const char *)samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, 100); i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
free(samples_data); free(samples_data);
} }

7
examples/peripherals/i2s_adc_dac/main/app_main.c Executable file → Normal file
View file

@ -205,6 +205,7 @@ void example_i2s_adc_dac(void*arg)
example_erase_flash(); example_erase_flash();
int i2s_read_len = EXAMPLE_I2S_READ_LEN; int i2s_read_len = EXAMPLE_I2S_READ_LEN;
int flash_wr_size = 0; int flash_wr_size = 0;
size_t bytes_read, bytes_written;
//2. Record audio from ADC and save in flash //2. Record audio from ADC and save in flash
#if RECORD_IN_FLASH_EN #if RECORD_IN_FLASH_EN
@ -213,7 +214,7 @@ void example_i2s_adc_dac(void*arg)
i2s_adc_enable(EXAMPLE_I2S_NUM); i2s_adc_enable(EXAMPLE_I2S_NUM);
while (flash_wr_size < FLASH_RECORD_SIZE) { while (flash_wr_size < FLASH_RECORD_SIZE) {
//read data from I2S bus, in this case, from ADC. //read data from I2S bus, in this case, from ADC.
i2s_read_bytes(EXAMPLE_I2S_NUM, (char*) i2s_read_buff, i2s_read_len, portMAX_DELAY); i2s_read(EXAMPLE_I2S_NUM, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
example_disp_buf((uint8_t*) i2s_read_buff, 64); example_disp_buf((uint8_t*) i2s_read_buff, 64);
//save original data from I2S(ADC) into flash. //save original data from I2S(ADC) into flash.
esp_partition_write(data_partition, flash_wr_size, i2s_read_buff, i2s_read_len); esp_partition_write(data_partition, flash_wr_size, i2s_read_buff, i2s_read_len);
@ -239,7 +240,7 @@ void example_i2s_adc_dac(void*arg)
//process data and scale to 8bit for I2S DAC. //process data and scale to 8bit for I2S DAC.
example_i2s_adc_data_scale(i2s_write_buff, flash_read_buff, FLASH_SECTOR_SIZE); example_i2s_adc_data_scale(i2s_write_buff, flash_read_buff, FLASH_SECTOR_SIZE);
//send data //send data
i2s_write_bytes(EXAMPLE_I2S_NUM, (char*) i2s_write_buff, FLASH_SECTOR_SIZE, portMAX_DELAY); i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, FLASH_SECTOR_SIZE, &bytes_written, portMAX_DELAY);
printf("playing: %d %%\n", rd_offset * 100 / flash_wr_size); printf("playing: %d %%\n", rd_offset * 100 / flash_wr_size);
} }
#endif #endif
@ -252,7 +253,7 @@ void example_i2s_adc_dac(void*arg)
while (offset < tot_size) { while (offset < tot_size) {
int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset); int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset);
int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t*)(audio_table + offset), play_len); int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t*)(audio_table + offset), play_len);
i2s_write_bytes(EXAMPLE_I2S_NUM, (const char*) i2s_write_buff, i2s_wr_len, portMAX_DELAY); i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY);
offset += play_len; offset += play_len;
example_disp_buf((uint8_t*) i2s_write_buff, 32); example_disp_buf((uint8_t*) i2s_write_buff, 32);
} }