Hello,
I'm using nrf52840 DK to test 1khz tone. The nRF Connect SDK version is v2.6.0.
I put a pcm raw data array of 1khz tone in the code and used i2s write to send the data to i2s out.
const struct device *const i2s_dev_tx = DEVICE_DT_GET(I2S_TX_NODE);
const struct device *const i2s_dev_rx = DEVICE_DT_GET(I2S_TX_NODE);
struct i2s_config config;
#define SAMPLE_FREQUENCY 48000
#define SAMPLE_BIT_WIDTH 16
#define BYTES_PER_SAMPLE sizeof(int16_t)
#define NUMBER_OF_CHANNELS 2
/* Such block length provides an echo with the delay of 100 ms. */
#define SAMPLES_PER_BLOCK ((SAMPLE_FREQUENCY / 10) * NUMBER_OF_CHANNELS)
#define INITIAL_BLOCKS 2
#define TIMEOUT 1000
#define BLOCK_SIZE (BYTES_PER_SAMPLE * SAMPLES_PER_BLOCK)
#define BLOCK_COUNT (INITIAL_BLOCKS + 2)
K_MEM_SLAB_DEFINE_STATIC(mem_slab, BLOCK_SIZE, BLOCK_COUNT, 4);
static int16_t data_buf_tmp[9600];
static bool configure_streams(const struct device *i2s_dev_tx,const struct i2s_config *config);
static void i2s_init(void){
int ret;
if (!device_is_ready(i2s_dev_tx)) {
LOG_ERR("%s is not ready", i2s_dev_tx->name);
}
config.word_size = SAMPLE_BIT_WIDTH;
config.channels = NUMBER_OF_CHANNELS;
config.format = I2S_FMT_DATA_FORMAT_I2S;
config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
config.frame_clk_freq = SAMPLE_FREQUENCY;
config.mem_slab = &mem_slab;
config.block_size = BLOCK_SIZE;
config.timeout = TIMEOUT;
ret = configure_streams(i2s_dev_tx, &config);
if (ret < 0) {
LOG_ERR("Failed to configure TX stream: %d", ret);
}
}
static bool configure_streams(const struct device *i2s_dev_tx,
const struct i2s_config *config)
{
int ret;
ret = i2s_configure(i2s_dev_tx, I2S_DIR_TX, config);
if (ret < 0) {
LOG_ERR("Failed to configure TX stream: %d\n", ret);
return false;
}
return true;
}
static void *mem_block;
static bool prepare_transfer(const struct device *i2s_dev_tx)
{
int ret;
for (int i = 0; i < INITIAL_BLOCKS; ++i) {
ret = k_mem_slab_alloc(&mem_slab, &mem_block, K_NO_WAIT);
if (ret < 0) {
LOG_ERR("Failed to allocate TX block %d: %d", i, ret);
return false;
}
memset(mem_block, 0, BLOCK_SIZE);
ret = i2s_write(i2s_dev_tx, mem_block, BLOCK_SIZE);
if (ret < 0) {
LOG_ERR("Failed to write block %d: %d", i, ret);
return false;
}
}
return true;
}
int main(void)
{
int ret;
i2s_init();
for(;;){
prepare_transfer(i2s_dev_tx);
ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, I2S_TRIGGER_START);
if (ret < 0) {
LOG_ERR("Failed to trigger command I2S_TRIGGER_START on TX: %d\n", ret);
}
// Put data into the buffer
for (int i = 0; i < 9600; i++) {
((int16_t*)mem_block)[i] = data[i];
}
for (int i = 0; i < SAMPLES_PER_BLOCK; ++i) {
int16_t *sample = &((int16_t *)mem_block)[i];
*sample += data_buf_tmp[i];
data_buf_tmp[i] = (*sample) / 2;
}
ret = i2s_write(i2s_dev_tx, mem_block, BLOCK_SIZE);
if (ret < 0) {
LOG_ERR("Failed to write data: %d", ret);
}else{
LOG_INF("Success to write data.");
}
ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, I2S_TRIGGER_DROP);
if (ret < 0) {
LOG_ERR("Failed to trigger command I2S_TRIGGER_DROP on TX: %d\n", ret);
}
}
return 0;
}
My pcm raw data array is an int16 stereo array, arranged as:
[left_data0,right_data0,left_data1,right_data1,....]
After testing, it is found that the output sound is distorted. Is there anything that needs to be adjusted?