Hello,
I'm using nrf52840 USB Audio headset application on nRF52840 DK. The nRF connect SDK version is v2.6.0.
I want to change the output to i2s out. The following are my modifications:
static bool prepare_transfer(const struct device *i2s_dev_tx) { int ret; void *mem_block; 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; } static void data_received(const struct device *dev, struct net_buf *buffer, size_t size) { int ret; if (!buffer || !size) { /* This should never happen */ return; } LOG_DBG("Received %d data, buffer %p", size, buffer); memcpy(data_buf+loop_times*size,buffer->data,size); loop_times++; if(loop_times == 100){ loop_times = 0; 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); } void *mem_block; ret = k_mem_slab_alloc(&mem_slab, &mem_block, K_NO_WAIT); if (ret < 0) { LOG_ERR("Failed to allocate TX block: %d", ret); return false; } /* Put data into the tx buffer */ for (int i = 0; i < 19200; i++) { ((uint8_t*)mem_block)[i] = data_buf[i]; } 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); } } net_buf_unref(buffer); }
int main(void) { const struct device *hs_dev; int ret; LOG_INF("Entered %s", __func__); hs_dev = DEVICE_DT_GET_ONE(usb_audio_hs); if (!device_is_ready(hs_dev)) { LOG_ERR("Device USB Headset is not ready"); return 0; } LOG_INF("Found USB Headset Device"); appAmpAD85020bInit(); usb_audio_register(hs_dev, &ops); ret = usb_enable(NULL); if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; } LOG_INF("USB enabled"); 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); } return 0; }
Here is my prj.conf.
CONFIG_STDOUT_CONSOLE=y #USB related configs CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PRODUCT="Zephyr USB audio sample" CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n #LOG subsystem related configs CONFIG_LOG=y CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y #net buf options CONFIG_NET_BUF=y #USB audio related configs CONFIG_USB_DEVICE_AUDIO=y CONFIG_I2S=y CONFIG_I2C=y
Here is my app.overlay.
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
&zephyr_udc0 {
hs_0 {
compatible = "usb-audio-hs";
mic-feature-mute;
mic-channel-l;
mic-channel-r;
hp-feature-mute;
hp-channel-l;
hp-channel-r;
hp-feature-volume;
volume-max = <0x0500>;
volume-min = <0xBA00>;
volume-res = <0x100>;
};
};
&pinctrl {
i2c0_default_alt: i2c0_default_alt {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 30)>,
<NRF_PSEL(TWIM_SCL, 0, 31)>;
};
};
i2c0_sleep_alt: i2c0_sleep_alt {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 30)>,
<NRF_PSEL(TWIM_SCL, 0, 31)>;
low-power-enable;
};
};
i2s0_default_alt: i2s0_default_alt {
group1 {
psels = <NRF_PSEL(I2S_SCK_M, 1, 15)>,
<NRF_PSEL(I2S_LRCK_M, 1, 12)>,
<NRF_PSEL(I2S_SDOUT, 1, 13)>,
<NRF_PSEL(I2S_SDIN, 1, 14)>;
};
};
};
&i2c0 {
status = "okay";
compatible = "nordic,nrf-twim";
label = "I2C_0";
pinctrl-0 = <&i2c1_default>;
pinctrl-1 = <&i2c1_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000>;
};
i2s_rxtx: &i2s0 {
status = "okay";
pinctrl-0 = <&i2s0_default_alt>;
pinctrl-names = "default";
};
After modifying, the speaker does not output any sound.
Judging from the log, no errors occurred during the process. I checked the I2S pin signal with a logic analyzer and the signal looks normal.
Is there anything else that needs to be modified?