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] 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)
@ -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) {
ESP_LOGE(I2S_TAG, "Not initialized yet");
return ESP_FAIL;
return ESP_ERR_INVALID_ARG;
}
p_i2s_obj[i2s_num]->sample_rate = rate;
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;
if (p_i2s_obj[i2s_num] == NULL) {
ESP_LOGE(I2S_TAG, "Not initialized yet");
return ESP_FAIL;
return ESP_ERR_INVALID_ARG;
}
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++) {
if (dma->desc && dma->desc[bux_idx])
if (dma->desc && 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]);
}
}
if (dma->buf)
if (dma->buf) {
free(dma->buf);
if (dma->desc)
}
if (dma->desc) {
free(dma->desc);
}
vQueueDelete(dma->queue);
vSemaphoreDelete(dma->mux);
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) {
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) {
int zero_bytes = 0;
i2s_write_bytes(i2s_num, (const char *)&zero_bytes, bytes_left, portMAX_DELAY);
size_t zero_bytes = 0, bytes_written;
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++) {
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;
}
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;
int bytes_can_write, bytes_writen = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL);
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL);
size_t bytes_written = 0;
int res = 0;
res = i2s_write(i2s_num, src, size, &bytes_written, ticks_to_wait);
if (res != ESP_OK) {
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);
src_byte = (char *)src;
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 (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) {
bytes_can_write = size;
}
memcpy(data_ptr, src, bytes_can_write);
memcpy(data_ptr, src_byte, 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;
bytes_writen += bytes_can_write;
(*bytes_written) += bytes_can_write;
}
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)
@ -1166,33 +1186,37 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
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;
int bytes_can_write, bytes_writen = 0, tail;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
I2S_CHECK((size > 0), "size must greater than zero", ESP_FAIL);
I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL);
I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_FAIL);
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL);
int bytes_can_write, tail;
int src_bytes, aim_bytes, zero_bytes;
*bytes_written = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG);
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) {
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) {
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)) {
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)) {
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);
size = size * aim_bytes / src_bytes;
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);
for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) {
j += zero_bytes;
memcpy(&data_ptr[j], &src[bytes_writen], aim_bytes - zero_bytes);
bytes_writen += (aim_bytes - zero_bytes);
memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes);
(*bytes_written) += (aim_bytes - zero_bytes);
}
size -= bytes_can_write;
p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
}
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;
int bytes_can_read, byte_read = 0;
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL);
I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_FAIL);
size_t bytes_read = 0;
int res = 0;
res = i2s_read(i2s_num, dest, size, &bytes_read, ticks_to_wait);
if (res != ESP_OK) {
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);
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) {
@ -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) {
bytes_can_read = size;
}
memcpy(dest, data_ptr, bytes_can_read);
memcpy(dest_byte, data_ptr, 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;
byte_read += bytes_can_read;
(*bytes_read) += bytes_can_read;
}
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;
char *data_ptr;
size_t bytes_push = 0;
int res = 0;
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) {
if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
return bytes_to_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;
res = i2s_write(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_push, ticks_to_wait);
if (res != ESP_OK) {
return ESP_FAIL;
} else {
return bytes_push;
}
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;
char *data_ptr;
size_t bytes_pop = 0;
int res = 0;
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) {
if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
return bytes_to_pop;
}
p_i2s_obj[i2s_num]->rx->rw_pos = 0;
res = i2s_read(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_pop, ticks_to_wait);
if (res != ESP_OK) {
return ESP_FAIL;
} else {
return bytes_pop;
}
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;
}

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

@ -263,42 +263,55 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
/**
* @brief Write data to I2S DMA transmit buffer.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
* This function is deprecated. Use 'i2s_write' instead.
* This definition will be removed in a future release.
*
* @param src Source address to write from
* @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.
*
* @param size Size of data in bytes
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* @param src Source address to write from
*
* @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
* many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the
* data is written to 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).
*
* @return
* - Number of bytes written, if timeout occurred, bytes written will be less than the size passed.
* - ESP_FAIL Parameter error.
* - ESP_OK Success
* - 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.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param src Source address to write from
* @param src Source address to write from
*
* @param size Size of data in bytes
* @param size Size of data in bytes
*
* @param src_bits Source audio bit
* @param src_bits Source audio bit
*
* @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 ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* @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
* many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the
* data is written to the DMA buffer in pieces, the overall operation
@ -309,67 +322,80 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t
* configuration (see i2s_config_t).
*
* @return
* - Number of bytes written, if timeout occurred, bytes written will be less than the size passed.
* - ESP_FAIL Parameter error.
* - ESP_OK Success
* - 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
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
* This function is deprecated. Use 'i2s_read' instead.
* This definition will be removed in a future release.
*
* @param dest Destination address to read into
* @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
*
* @param size Size of data in bytes
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @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 dest Destination address to read into
*
* @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.
*
* 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,
* to prevent the data getting corrupted.
*
* @return
* - Number of bytes read, if timeout occurred, bytes written will be less than the size passed.
* - ESP_FAIL Parameter error.
* - ESP_OK Success
* - 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
* - Number of bytes successfully pushed to DMA buffer, will be either zero or the size of configured sample buffer.
* - ESP_FAIL Parameter error.
* - 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
*/
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
* - Number of bytes successfully read from DMA buffer, will be either zero or the size of configured sample buffer.
* - ESP_FAIL Parameter error.
* - 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
*/
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.
@ -385,7 +411,6 @@ int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL I2s is not initialized
* - ESP_ERR_NO_MEM Out of memory
*/
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
* - ESP_OK Success
* - ESP_FAIL Not initialized
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM Out of memory
*/
@ -454,7 +478,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
/**
* @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad,
* and set ADC parameters.
* @param adc_unit SAR ADC unit index
* @param adc_unit SAR ADC unit index
* @param adc_channel ADC channel index
* @return
* - ESP_OK Success
@ -469,10 +493,9 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
*
* @param i2s_num i2s port index
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error
* - ESP_FAIL Internal driver error
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Driver state error
*/
esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
@ -481,9 +504,9 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
* @param i2s_num i2s port index
* @note This function would release the lock of ADC so that other tasks can use ADC.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Driver state error
*/
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)
{
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) {
ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt);
}

View file

@ -1,7 +1,7 @@
/* I2S Example
This example code will output 100Hz sine wave and triangle wave to 2-channel of I2S driver
Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data
Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data
This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -29,11 +29,12 @@ static void setup_triangle_sine_waves(int bits)
int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4);
unsigned int i, sample_val;
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);
triangle_float = -(pow(2, bits)/2 - 1);
for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
sin_float = sin(i * PI / 180.0);
if(sin_float >= 0)
@ -56,7 +57,7 @@ static void setup_triangle_sine_waves(int bits)
samples_data[i*2] = ((int) triangle_float);
samples_data[i*2 + 1] = ((int) sin_float);
}
}
i2s_set_clk(I2S_NUM, SAMPLE_RATE, bits, 2);
@ -68,12 +69,12 @@ static void setup_triangle_sine_waves(int bits)
// i2s_push_sample(0, &samples_data[i*2], 100);
// }
// 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);
}
void app_main()
{
{
//for 36Khz sample rates, we create 100Hz sine wave, every cycle need 36000/100 = 360 samples (4-bytes or 8-bytes each sample)
//depend on bits_per_sample
//using 6 buffers, we need 60-samples per buffer
@ -82,7 +83,7 @@ void app_main()
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
.sample_rate = SAMPLE_RATE,
.bits_per_sample = 16,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 6,
@ -106,7 +107,7 @@ void app_main()
test_bits += 8;
if(test_bits > 32)
test_bits = 16;
}
}
}

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();
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
int flash_wr_size = 0;
size_t bytes_read, bytes_written;
//2. Record audio from ADC and save in flash
#if RECORD_IN_FLASH_EN
@ -213,7 +214,7 @@ void example_i2s_adc_dac(void*arg)
i2s_adc_enable(EXAMPLE_I2S_NUM);
while (flash_wr_size < FLASH_RECORD_SIZE) {
//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);
//save original data from I2S(ADC) into flash.
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.
example_i2s_adc_data_scale(i2s_write_buff, flash_read_buff, FLASH_SECTOR_SIZE);
//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);
}
#endif
@ -252,7 +253,7 @@ void example_i2s_adc_dac(void*arg)
while (offset < tot_size) {
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);
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;
example_disp_buf((uint8_t*) i2s_write_buff, 32);
}