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

Passing data from PDM callback to USB audio device

Hi,

I'm trying to pass audio data from PDM callback function to a USB device and I'm kind of stuck.

Background:
I'm using the nRF52840-DK board and 2 MP34DT05-A microphones. Since there is no PDM example in the SDK I took the liberty of writing the code from scratch based on the non-legacy PDM driver. It is very similar to I2S in design so didnt take much to make it work. To verify that it works I used fstorage library to save the samples into memory nd then Segger J-Flash to dump contents to file on a windows computer and the WaveSurfer to make sure it is actual audio data. (basically up to date code and applications described here)

IT WORKED

Here is a snippet of the relevant code in my program:

Now, the problem I'm facing is how to pass that data to a USB audio device.

I started with the USB audio device example in the SDK and stripped all the headphones related code since it is irrelevant.

When I looked at the code I could see that the function app_usbd_audio_class_tx_start() that actually passes data to the USB device is called inside the SOF handler of the headphones.
I needed to find a new home for it ..
My naive first attempt was to place it directly inside the PDM handler (where fstorage_write_done() is right now). To cut a long story short - it didnt work, it returns with code 8 (invalid state). So I went to the documentation and it says there that writing can only occur during an SOF event. (and it has a small example here that I tried to use).

I came up with this code (which doesnt work .. same old return code 8 - invalid state):

My question is - how can I pass the data from the PDM callback to the USB device reliably with no errors ?

Remark #1:
In the code snippets I attached the "// ." signify mode code there that I didnt bother to attach.

Remark #2:
I didnt change anything in the definition of the USB microphone which might be a problem.
Especially the following line:

When I connect the board to a Linux machine and look at dmesg output I get a warning/error that max interface should be 1. I guess the 2 and 3 values here are wrong.

Remark #3:
I read in the documentation that the isochroneous USB device can have a maximum buffer size of 1000 bytes, so I use a double buffer of 500 int16_t for the PDM:

Parents
  • I assume that app_usbd_audio_class_tx_start() return NRF_ERROR_INVALID_STATE because the USB driver is not in active state (SUSTATE_ACTIVE). I would have started looking at why the driver haven't transitioned to active state (compared to default example for instance \nRF5_SDK_15.3.0_59ac345\examples\peripheral\usbd_audio).

Reply
  • I assume that app_usbd_audio_class_tx_start() return NRF_ERROR_INVALID_STATE because the USB driver is not in active state (SUSTATE_ACTIVE). I would have started looking at why the driver haven't transitioned to active state (compared to default example for instance \nRF5_SDK_15.3.0_59ac345\examples\peripheral\usbd_audio).

Children
  • Notice where I placed app_usbd_audio_class_tx_start() ..

    It is inside the usbd_user_ev_handler() in a switch case of APP_USBD_EVT_DRV_SOF.
    Wouldnt that event be called only if a device is at least in activated state ?

    Another thing - first thing I check is that the device is configured (if (APP_USBD_STATE_Configured != app_usbd_core_state_get()) break;).
    Doesnt a device reach configured state after it is activated ?

    I attach here the entire main.c for you to take a look at (maybe you will notice something I have missed):

  • After debugging the SDK and checking why I get NRF_ERROR_INVALID_STATE when I call app_usbd_audio_class_tx_start() I found out that it is returned from inside the following if statement:

    inside the file "nRF5_SDK_15.3.0/components/libraries/usbd/app_usbd.c" inside function app_usbd_ep_transfer() (line 1820).

    What can disable the endpoint ? why does it happen in the middle of using it ?

  • If you can send me a hex file I may program to an nRF52840 DK here, then I can take an USB sniffer trace to check if I can see issues.

    Kenneth

  • I have embedded the whole main.c source file above 6 days ago.

    You can comment out the fstorage parts since you wont need them and find 2 PDM mics for input source.
    This was based on usb_audio code so same sdk_config (but you need to add PDM support).

    Thanks for helping, something doesnt make sense in the USB functionality

  • Is there no way you can strip away the PDM for now so I may run this on a devkit without PDM?

    Kenneth