This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use nrf5340 as a USB Microphone device?

I want to use nrf5340 as a USB Audio Microphone.

I am taking the help of zephyr/samples/subsys/usb/audio/headphones_microphone sample app, which contains USB Headphone + USB Microphone.

To disable USB Headphone, I am commenting hp_dev related code from main.c and I am modifying the nrf5340dk_nrf5340_cpuapp.overlay as follows:

&usbd {
mic_0 {
label = "MICROPHONE";
compatible = "usb-audio-mic";
feature-mute;
channel-l;
channel-r;
};
};

I have a static 192 byte PCM buffer that I want to continuously send over USB, for which I am using the following code in loop:

struct usb_audio_dev_data *audio_dev_data = mic_dev->data;
struct net_buf *buffer = net_buf_alloc(audio_dev_data->pool, K_NO_WAIT);
memcpy(buffer->data, pcm_buffer, buffer_len);
ret = usb_audio_send(dev, buffer, buffer_len);

But it does not work and the code crashes. 

Please advise.

  • Hi

    You mean you run the code in a loop as fast as possible?

    Then you will eventually run out of net_buffers, or fill up the USB buffers. 

    Are you checking the return codes from net_buf_alloc(..) and usb_audio_send(..) to see if they return any errors?

    I would recommend registering the data_written_cb callback in the hp_ops setup, so that you get a callback whenever an audio packet is successfully sent over the USB interface. Then you can use this to schedule the next update.

    Best regards
    Torbjørn

  • Hi, t

    Thanks, I handled the buffers so that they don't fill up, and also wrote the data_written_cb. Within this callback, I am sending 192 bytes of audio data by calling usb_audio_send() again so that data is sent continuously after each successfully data_written_cb call. I can now see the Zephyr USB audio sample listed in the Audio Input devices of the host device. But I can not hear any sound on my host device. I tried sending a 400Hz sine wave, 600Hz sine wave, and also a 1 sec sample of a song (192k sized buffer), but I cannot hear any of those on the host default speaker. I captured the incoming USB data on the host device using wireshark, and it looks like the buffer that I am sending is getting received at the host side. But I am also seeing this error on wireshark :
    USB isodesc 0 [Protocol error (-EPROTO)] (192 bytes)
    Status: Protocol error (-EPROTO) (-71)

    One USB packet as captured on wireshark is as follows:


    00 de e9 93 00 88 ff ff 43 00 88 78 02 00 2d 00 .Þé...ÿÿC..x..-.
    c6 be 2b 61 00 00 00 00 8d c3 01 00 00 00 00 00 ƾ+a.....Ã......
    c0 00 00 00 d0 00 00 00 00 00 00 00 01 00 00 00 À...Ð...........
    01 00 00 00 82 01 00 00 04 02 00 00 01 00 00 00 ................
    b9 ff ff ff 00 00 00 00 c0 00 00 00 00 00 00 00 ¹ÿÿÿ....À.......
    00 08 00 00 3c aa e3 59 b3 52 bf e7 36 fe aa 62 ....<ªãY³R¿ç6þªb
    29 be 72 55 fc 11 e4 55 ec 66 62 66 b4 0f 29 cc )¾rUü.äUìfbf´.)Ì
    e5 de ea a0 26 b9 8a 00 2b ff 61 43 06 d1 ed 00 åÞê &¹..+ÿaC.Ñí.
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 01 00 00 a8 04 2e 03 20 00 00 c0 00 04 ......¨... ..À..
    2e 03 20 10 e2 07 8d b6 09 a5 f8 7b 56 8e f6 e0 .. .â..¶.¥ø{V.öà

    What could be wrong?
    Let me know if you want the entire wireshark capture, or want to look at the code.

  • Hi 

    How are you receiving the sound on the host side? 

    Unless you have some program trying to get sound from the microphone device, you won't be able to send anything from the nRF device. 

    In my case I am using the Audacity audio editing application in order to record audio, as this program makes it very easy to select the input source:

    I decided to test this myself based on your input, and realized that using the data_written_cb callback was not the easiest way to use the microphone class. 

    Instead I configured the data_request_cb callback, which will be triggered every time the host opens the microphone port for input. Then I could prepare a packet for sending here and send it over the USB interface. 

    Best regards
    Torbjørn

  • Thanks for your input. I was using another audio recorder for capturing the incoming audio. With your suggestion, I added data_request_cb and used it to send the audio buffer to the host. With this, I was successfully able tos send 192k static PCM buffers of 400hz and 600hz sine wave and record it at the host side. Now I would like to send dynamic audio values to the host. My input is coming from an I2S interface which I want to relay to the USB host. The I2S gives me 1920 bytes of data every 10ms, which I am memcopying into a buffer, and sending over USB inside data_request_cb. From wireshark, I can see that the data is being transmitted to the host successfully, but now again I am not able to hear it after recording on the host side. Any suggestions that I can try?

  • Hi 

    Could it be that your host is trying to play back audio to your nRF device as well, over USB?

    Could you try to change the playback device on the host side to ensure that you play sound to the standard sound driver, and not the USB driver set up by the nRF device?

    Best regards
    Torbjørn

Related