<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/52242/passing-data-from-pdm-callback-to-usb-audio-device</link><description>Hi, 
 
 I&amp;#39;m trying to pass audio data from PDM callback function to a USB device and I&amp;#39;m kind of stuck. 
 Background: I&amp;#39;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</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 27 May 2024 02:11:48 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/52242/passing-data-from-pdm-callback-to-usb-audio-device" /><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/485938?ContentTypeID=1</link><pubDate>Mon, 27 May 2024 02:11:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cab8af55-3ac9-4b42-9e2f-4fde086e6904</guid><dc:creator>luke.zheng</dc:creator><description>&lt;p&gt;Hi yoyou，&lt;/p&gt;
&lt;p&gt;Have you solved the question?&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve the same problem in sdk_17&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/423412?ContentTypeID=1</link><pubDate>Wed, 03 May 2023 01:22:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b676ab7c-b5ad-4661-9979-80d77fba3884</guid><dc:creator>yoyou</dc:creator><description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;i&amp;#39;ve the same porbem in&amp;nbsp;&lt;span&gt;nRF5_SDK_17,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I2S mic 16bit 48Khz&amp;nbsp;stereo transferre to&amp;nbsp; USB AUIDO.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;some time&amp;nbsp;app_usbd_audio_class_tx_start() return code 17.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/298639?ContentTypeID=1</link><pubDate>Tue, 09 Mar 2021 10:45:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4eb1cda7-723a-49af-861f-63ccac13af95</guid><dc:creator>Jeffrey Haynes</dc:creator><description>&lt;p&gt;Did you ever figure this out?&amp;nbsp; Looks like maybe the buffer size is meant to be 16 bytes but I&amp;#39;m getting time compression and whole bunch of noise.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/247177?ContentTypeID=1</link><pubDate>Tue, 28 Apr 2020 22:43:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:42f65ffa-9c01-442d-a8c6-022b2016ca5e</guid><dc:creator>NewtoM</dc:creator><description>&lt;p&gt;Is there any news on this topic? The solution would interest me much!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/222966?ContentTypeID=1</link><pubDate>Mon, 02 Dec 2019 09:00:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2e139f87-52e0-4dc0-a6e8-c42ed1379c08</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;I send exactly what I get from the PDM callback when I have a buffer of 64 bytes:&lt;/p&gt;
&lt;p&gt;16 samples X 2 channels (stereo) X 16 bit sampling (2 bytes) = 64 bytes&lt;/p&gt;
&lt;p&gt;The audio is 16KHz which means the transfer rate is 64Kb/second&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/222934?ContentTypeID=1</link><pubDate>Mon, 02 Dec 2019 05:02:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:59a9e7dd-d5de-458c-8406-e748a03aa6c8</guid><dc:creator>abhipray</dc:creator><description>&lt;p&gt;How many samples are you sending via&amp;nbsp;&lt;em&gt;&lt;strong&gt;app_usbd_audio_class_tx_start()?&amp;nbsp;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;It should be 16 samples every 1ms SOF event for 16KHz audio.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/220485?ContentTypeID=1</link><pubDate>Mon, 18 Nov 2019 08:37:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d7f3f7ba-69f7-4f15-bd85-302d9e87576e</guid><dc:creator>DrYang</dc:creator><description>&lt;p&gt;I have same trouble....!!!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/220484?ContentTypeID=1</link><pubDate>Mon, 18 Nov 2019 08:36:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:90d39c10-4689-44dc-9d73-26bdc5ea6307</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;But the sample rate of the source is 16KHz ?!&lt;/p&gt;
&lt;p&gt;If I set the sample rate to 48KHz wouldnt the host expect 48KHz data and distort the audio ?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/220482?ContentTypeID=1</link><pubDate>Mon, 18 Nov 2019 08:28:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6f38b4a4-eed6-4a15-98f4-769ffa34e97f</guid><dc:creator>DrYang</dc:creator><description>&lt;p&gt;The reason is your sample rate,&amp;nbsp; this problem will be fixed if you set the sample rate to 48KHz, and also repeat if you set the sample rate to other value!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/215589?ContentTypeID=1</link><pubDate>Thu, 17 Oct 2019 16:41:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ede8faf1-68d0-407a-81c2-dcd525e851bd</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;I see your point, unfortunately I don&amp;#39;t see this being prioritized at the moment.&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/214967?ContentTypeID=1</link><pubDate>Tue, 15 Oct 2019 07:50:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:56bd5344-5657-4b67-b194-9f93d8dcc598</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;I&amp;#39;ve changed both NRFX_USBD_CONFIG_IRQ_PRIORITY and USBD_CONFIG_IRQ_PRIORITY to 0 (highest, they were set to 6) to no avail.&lt;/p&gt;
&lt;p&gt;Is there a chance one of the SDK developers can take a look at my code ? I&amp;#39;m pretty sure I follow exactly the code example and I still cant make it work (PDM audio through USB).&lt;/p&gt;
&lt;p&gt;There is no code example on the internet that does just that and actually works. Making this one work will be a breakthrough that will be useful for other developers who are interested in using nrf52840 for USB audio.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/214908?ContentTypeID=1</link><pubDate>Mon, 14 Oct 2019 15:07:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:be379fce-c351-4122-b633-5702a7a40a42</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Maybe you are not handling the USB callbacks fast enough due to other application interrupts processing,&amp;nbsp;for instance that the app_usbd_core_event_handler() give a response to late. Maybe try to change&amp;nbsp;NRFX_USBD_CONFIG_IRQ_PRIORITY.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/214767?ContentTypeID=1</link><pubDate>Mon, 14 Oct 2019 09:11:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8eff485b-07eb-4167-b55c-cc901094ce17</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;What am I doing wrong in the firmware code (which I attached) that causes this behavior ? is this a bug in the SDK ?&lt;/p&gt;
&lt;p&gt;IS this related to the distorted audio I get ?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/214746?ContentTypeID=1</link><pubDate>Mon, 14 Oct 2019 08:15:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f5c846a8-3f56-498c-ac84-ff2b4486864e</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Adding the USB sniffer file, I do believe you should be able to open it by downloading Ellisys Visual USB. Seems as the application does not reply to the first &lt;span&gt;&amp;#39;get device descriptor&amp;#39; from the USB host, instead the intended data is sent on the next &amp;#39;get configuration descriptor&amp;#39;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-2cf3751b8d6a4ecb87222133fae23655/screenshot.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;Sniffer trace:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-2cf3751b8d6a4ecb87222133fae23655/Case_5F00_236141.zip"&gt;devzone.nordicsemi.com/.../Case_5F00_236141.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Seems as the IN transaction from the nRF52840 which should be a response to &amp;#39;get device descriptor&amp;#39;, is instead replied on the next &amp;#39;get configuration descriptors&amp;#39; from the USB host.&lt;/p&gt;
&lt;p&gt;For comparison see the USB audio reference:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-2cf3751b8d6a4ecb87222133fae23655/Case_5F00_236141_5F00_reference_5F00_usb_5F00_audio_5F00_sdk15.2.zip"&gt;devzone.nordicsemi.com/.../Case_5F00_236141_5F00_reference_5F00_usb_5F00_audio_5F00_sdk15.2.zip&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211996?ContentTypeID=1</link><pubDate>Thu, 26 Sep 2019 09:07:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b81e6dee-0572-4c39-b7ae-768e14f204d0</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;I&amp;#39;m attaching here all information that might be relevant&lt;/p&gt;
&lt;p&gt;Linux &lt;strong&gt;dmesg&lt;/strong&gt;:&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;[590038.946652] usb 1-3: new full-speed USB device number 6 using xhci_hcd
[590039.097423] usb 1-3: New USB device found, idVendor=1915, idProduct=521a
[590039.097430] usb 1-3: New USB device strings: Mfr=1, Product=1, SerialNumber=1
[590039.097434] usb 1-3: Product: 000000000000
[590039.097437] usb 1-3: Manufacturer: 000000000000
[590039.097439] usb 1-3: SerialNumber: 000000000000
[590109.320154] retire_capture_urb: 431 callbacks suppressed
[590153.033160] retire_capture_urb: 708 callbacks suppressed
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Query USB device under Linux (&lt;strong&gt;lsusb -d 1915:521a -v&lt;/strong&gt;):&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;Bus 001 Device 006: ID 1915:521a Nordic Semiconductor ASA 
Couldn&amp;#39;t open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x1915 Nordic Semiconductor ASA
  idProduct          0x521a 
  bcdDevice            1.00
  iManufacturer           1 
  iProduct                1 
  iSerial                 1 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          113
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          4 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength           43
        bInCollection           1
        baInterfaceNr( 0)       1
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                13
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 2
        bSourceID               1
        bControlSize            2
        bmaControls( 0)      0x01
        bmaControls( 0)      0x00
          Mute Control
        bmaControls( 1)      0x01
        bmaControls( 1)      0x00
          Mute Control
        bmaControls( 2)      0x01
        bmaControls( 2)      0x00
          Mute Control
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             3
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               2
        iTerminal               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           1
        bDelay                  0 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                11
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            1 Discrete
        tSamFreq[ 0]        16000
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bLockDelayUnits         0 Undefined
          wLockDelay              0 Undefined
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x88  EP 8 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Full source code (&lt;strong&gt;main.c&lt;/strong&gt; 414 lines based on usb_audio example):&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include &amp;lt;stddef.h&amp;gt;

#include &amp;quot;nrf.h&amp;quot;
#include &amp;quot;app_util.h&amp;quot;
#include &amp;quot;nrf_drv_usbd.h&amp;quot;
#include &amp;quot;nrf_drv_clock.h&amp;quot;
#include &amp;quot;nrf_gpio.h&amp;quot;
#include &amp;quot;nrf_delay.h&amp;quot;
#include &amp;quot;nrf_drv_power.h&amp;quot;
#include &amp;quot;nrf_drv_pdm.h&amp;quot;

#include &amp;quot;app_usbd.h&amp;quot;
#include &amp;quot;app_usbd_core.h&amp;quot;
#include &amp;quot;app_usbd_string_desc.h&amp;quot;
#include &amp;quot;app_usbd_audio.h&amp;quot;
#include &amp;quot;app_error.h&amp;quot;
#include &amp;quot;boards.h&amp;quot;

#include &amp;quot;nrf_drv_clock.h&amp;quot;
#include &amp;quot;nrf_fstorage_nvmc.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;
#include &amp;quot;nrf_log_ctrl.h&amp;quot;
#include &amp;quot;nrf_log_default_backends.h&amp;quot;

// buffers for the PDM source (base NRFX_PDM_MAX_BUFFER_SIZE)
#define NRFX_PDM_BUFFER_SIZE (32)
static int8_t pdm_buffer_i = 0;
static int16_t pdm_buffer[2][NRFX_PDM_BUFFER_SIZE];
static volatile uint8_t usb_tx_idle = 1, audio_buffer_ready = 0;

#define LED_USB_RESUME (BSP_BOARD_LED_0)
#define LED_USB_START  (BSP_BOARD_LED_1)
#define LED_AUDIO_RX   (BSP_BOARD_LED_2)
#define LED_AUDIO_TX   (BSP_BOARD_LED_3)

/**
 * @brief Enable power USB detection
 *
 * Configure if example supports USB port connection
 */
#ifndef USBD_POWER_DETECTION
#define USBD_POWER_DETECTION true
#endif

/**
 * @brief Audio class user event handler
 */
static void mic_audio_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                      app_usbd_audio_user_event_t   event);

/* Channels and feature controls configuration */

/**
 * @brief   Input terminal channel configuration
 */
#define MIC_TERMINAL_CH_CONFIG()                                                                       \
        (APP_USBD_AUDIO_IN_TERM_CH_CONFIG_LEFT_FRONT | APP_USBD_AUDIO_IN_TERM_CH_CONFIG_RIGHT_FRONT)

/**
 * @brief   Feature controls
 *
 *      general
 *      channel 0
 *      channel 1
 */
#define MIC_FEATURE_CONTROLS()                                                                     \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE),                         \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE),                         \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE)


/* Microphone descriptors */

/**
 * @brief   Audio class specific format descriptor
 */
APP_USBD_AUDIO_FORMAT_DESCRIPTOR(m_mic_form_desc, 
                                 APP_USBD_AUDIO_AS_FORMAT_I_DSC(    /* Format type 1 descriptor */
                                    2,                              /* Number of channels */
                                    2,                              /* Subframe size */
                                    16,                             /* Bit resolution */
                                    1,                              /* Frequency type */
                                    APP_USBD_U24_TO_RAW_DSC(16000)) /* Frequency */
                                );

/**
 * @brief   Audio class input terminal descriptor
 */
APP_USBD_AUDIO_INPUT_DESCRIPTOR(m_mic_inp_desc, 
                                APP_USBD_AUDIO_INPUT_TERMINAL_DSC(
                                    1,                                     /* Terminal ID */
                                    APP_USBD_AUDIO_TERMINAL_IN_MICROPHONE, /* Terminal type */
                                    2,                                     /* Number of channels */
                                    MIC_TERMINAL_CH_CONFIG())              /* Channels config */
                                );

/**
 * @brief   Audio class output terminal descriptor
 */
APP_USBD_AUDIO_OUTPUT_DESCRIPTOR(m_mic_out_desc, 
                                 APP_USBD_AUDIO_OUTPUT_TERMINAL_DSC(
                                    3,                                     /* Terminal ID */
                                    APP_USBD_AUDIO_TERMINAL_USB_STREAMING, /* Terminal type */
                                    2)                                     /* Source ID */
                                );

/**
 * @brief   Audio class feature unit descriptor
 */
APP_USBD_AUDIO_FEATURE_DESCRIPTOR(m_mic_fea_desc, 
                                  APP_USBD_AUDIO_FEATURE_UNIT_DSC(
                                    2,                      /* Unit ID */
                                    1,                      /* Source ID */
                                    MIC_FEATURE_CONTROLS()) /* List of controls */
                                 );

/* Interfaces lists */

/**
 * @brief Interfaces list passed to @ref APP_USBD_AUDIO_GLOBAL_DEF
 */
#define MIC_INTERFACES_CONFIG() APP_USBD_AUDIO_CONFIG_IN(0, 1)

/*lint -save -e26 -e64 -e123 -e505 -e651*/

/**
 * @brief Microphone Audio class instance
 */
APP_USBD_AUDIO_GLOBAL_DEF(m_app_audio_microphone,
                          MIC_INTERFACES_CONFIG(),
                          mic_audio_user_ev_handler,
                          &amp;amp;m_mic_form_desc,
                          &amp;amp;m_mic_inp_desc,
                          &amp;amp;m_mic_out_desc,
                          &amp;amp;m_mic_fea_desc,
                          0,
                          APP_USBD_AUDIO_AS_IFACE_FORMAT_PCM,
                          64,
                          APP_USBD_AUDIO_SUBCLASS_AUDIOSTREAMING
);

/**
 * @brief Actual microphone mute state
 */
static uint8_t  m_mute_mic;

/**
 * @brief Actual microphone sampling frequency
 */
static uint32_t m_freq_mic;

/**
 * @brief Audio class specific request handle (microphone)
 */
static void mic_audio_user_class_req(app_usbd_class_inst_t const * p_inst)
{
    app_usbd_audio_t const * p_audio = app_usbd_audio_class_get(p_inst);
    app_usbd_audio_req_t * p_req = app_usbd_audio_class_request_get(p_audio);

    UNUSED_VARIABLE(m_mute_mic);
    UNUSED_VARIABLE(m_freq_mic);

    switch (p_req-&amp;gt;req_target)
    {
        case APP_USBD_AUDIO_CLASS_REQ_IN:
        	NRF_LOG_INFO(&amp;quot;APP_USBD_AUDIO_CLASS_REQ_IN&amp;quot;);

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only mute control is defined
                p_req-&amp;gt;payload[0] = m_mute_mic;
            }

            break;
        case APP_USBD_AUDIO_CLASS_REQ_OUT:
        	NRF_LOG_INFO(&amp;quot;APP_USBD_AUDIO_CLASS_REQ_OUT&amp;quot;);

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only mute control is defined
                m_mute_mic = p_req-&amp;gt;payload[0];
                NRF_LOG_INFO(&amp;quot;m_mute_mic = %d&amp;quot;, m_mute_mic);
            }

            break;
        case APP_USBD_AUDIO_EP_REQ_IN:
        	NRF_LOG_INFO(&amp;quot;APP_USBD_AUDIO_EP_REQ_IN&amp;quot;);

            break;
        case APP_USBD_AUDIO_EP_REQ_OUT:
        	NRF_LOG_INFO(&amp;quot;APP_USBD_AUDIO_EP_REQ_OUT&amp;quot;);

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only set frequency is supported
            	NRF_LOG_INFO(&amp;quot;APP_USBD_AUDIO_EP_REQ_OUT -&amp;gt; APP_USBD_AUDIO_REQ_SET_CUR&amp;quot;);
                m_freq_mic = uint24_decode(p_req-&amp;gt;payload);
            }

            break;
        default:
        	NRF_LOG_INFO(&amp;quot;mic_audio_user_class_req(default)&amp;quot;);
            break;
    }
}

/**
 * @brief User event handler @ref app_usbd_audio_user_ev_handler_t (microphone)
 */
static void mic_audio_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                      app_usbd_audio_user_event_t   event)
{
    app_usbd_audio_t const * p_audio = app_usbd_audio_class_get(p_inst);
    UNUSED_VARIABLE(p_audio);

    switch (event)
    {
        case APP_USBD_AUDIO_USER_EVT_CLASS_REQ:
            mic_audio_user_class_req(p_inst);
            break;
        case APP_USBD_AUDIO_USER_EVT_TX_DONE:
        {
        	usb_tx_idle = 1;
            bsp_board_led_invert(LED_AUDIO_TX);
            //NRF_LOG_INFO(&amp;quot;mic frame txed&amp;quot;);
            break;
        }
        default:
        	NRF_LOG_INFO(&amp;quot;mic_audio_user_ev_handler(default)&amp;quot;);
            break;
    }
}

/**
 * @brief USBD library specific event handler.
 *
 * @param event     USBD library event.
 */
static void usbd_user_ev_handler(app_usbd_event_type_t event)
{
    switch (event)
    {
        case APP_USBD_EVT_DRV_SOF:
            break;

        case APP_USBD_EVT_DRV_SETUP:
        	NRF_LOG_INFO(&amp;quot;USB setup&amp;quot;);

        	break;
        case APP_USBD_EVT_DRV_SUSPEND:
        	NRF_LOG_INFO(&amp;quot;USB suspend&amp;quot;);

            bsp_board_leds_off();
            break;
        case APP_USBD_EVT_DRV_RESUME:
        	NRF_LOG_INFO(&amp;quot;USB resume&amp;quot;);

            bsp_board_led_on(LED_USB_RESUME);
            break;
        case APP_USBD_EVT_STARTED:
        	NRF_LOG_INFO(&amp;quot;USB started&amp;quot;);

            bsp_board_led_on(LED_USB_START);

            // start PDM
            APP_ERROR_CHECK(nrfx_pdm_start());

            break;
        case APP_USBD_EVT_STOPPED:
        	NRF_LOG_INFO(&amp;quot;USB stopped&amp;quot;);

        	// start PDM
        	APP_ERROR_CHECK(nrfx_pdm_stop());

            app_usbd_disable();
            bsp_board_leds_off();
            break;
        case APP_USBD_EVT_POWER_DETECTED:
            NRF_LOG_INFO(&amp;quot;USB power detected&amp;quot;);

            if (!nrf_drv_usbd_is_enabled())
            {
                app_usbd_enable();
            }
            break;
        case APP_USBD_EVT_POWER_REMOVED:
            NRF_LOG_INFO(&amp;quot;USB power removed&amp;quot;);
            app_usbd_stop();
            break;
        case APP_USBD_EVT_POWER_READY:
            NRF_LOG_INFO(&amp;quot;USB ready&amp;quot;);
            app_usbd_start();
            break;
        default:
            break;
    }
}

static void mic_sof_ev_handler(uint16_t framecnt)
{
	// make sure we&amp;#39;re in proper state (configured)
	if (APP_USBD_STATE_Configured != app_usbd_core_state_get()) return;

	// are we in the middle of a transfer ?
	if (!usb_tx_idle) return;

	// do we have a buffer ready for transfer ?
	if (audio_buffer_ready == 0) return;

	// transfer the off-line buffer to the USB device now
	usb_tx_idle = 0;
	ret_code_t ret = app_usbd_audio_class_tx_start(&amp;amp;m_app_audio_microphone.base,
			pdm_buffer[pdm_buffer_i == 0 ? 1 : 0], NRFX_PDM_BUFFER_SIZE*2);

	// haven&amp;#39;t started transferring -&amp;gt; wont reach TX done
	if (ret != NRF_SUCCESS) {
		usb_tx_idle = 1;
		NRF_LOG_ERROR(&amp;quot;mic_sof_ev_handler() -&amp;gt; app_usbd_audio_class_tx_start() = %d&amp;quot;, ret);
	}

	// this buffer is being transferred
	audio_buffer_ready = 0;
}

static void nrfx_pdm_event_handler(nrfx_pdm_evt_t const *const p_evt)
{
	// we have an error ?
	if (p_evt-&amp;gt;error != NRFX_PDM_NO_ERROR) {
		NRF_LOG_INFO(&amp;quot;PDM error event: %d&amp;quot;, p_evt-&amp;gt;error);
		return;
	}

	// expected to set a new buffer ?
	if (p_evt-&amp;gt;buffer_requested) {
		// update buffer index
		pdm_buffer_i = pdm_buffer_i == 0 ? 1 : 0;

		// set new buffer
		nrfx_pdm_buffer_set(pdm_buffer[pdm_buffer_i], NRFX_PDM_BUFFER_SIZE);
	}

	// got a buffer with data ?
	if (p_evt-&amp;gt;buffer_released != NULL) {
		// we have buffer ready
		audio_buffer_ready = 1;
	}
}

int main(void)
{
    ret_code_t ret;
    static const app_usbd_config_t usbd_config = {
        .ev_state_proc = usbd_user_ev_handler,
        .enable_sof = true
    };

    ret = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(ret);
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);

    nrfx_pdm_config_t config = NRFX_PDM_DEFAULT_CONFIG(ARDUINO_SCL_PIN, ARDUINO_SDA_PIN);
    ret = nrfx_pdm_init(&amp;amp;config, nrfx_pdm_event_handler);
    APP_ERROR_CHECK(ret);

    NRF_LOG_INFO(&amp;quot;USBD audio example started.&amp;quot;);

    // Initialize LEDs and buttons
    bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);

    ret = app_usbd_init(&amp;amp;usbd_config);
    APP_ERROR_CHECK(ret);

    app_usbd_class_inst_t const * class_inst_mic =
        app_usbd_audio_class_inst_get(&amp;amp;m_app_audio_microphone);

    ret = app_usbd_audio_sof_interrupt_register(class_inst_mic, mic_sof_ev_handler);
    APP_ERROR_CHECK(ret);

    ret = app_usbd_class_append(class_inst_mic);
    APP_ERROR_CHECK(ret);

    if (USBD_POWER_DETECTION)
    {
        ret = app_usbd_power_events_enable();
        APP_ERROR_CHECK(ret);
    }
    else
    {
        NRF_LOG_INFO(&amp;quot;No USB power detection enabled\r\nStarting USB now&amp;quot;);

        app_usbd_enable();
        app_usbd_start();
    }

    NRF_LOG_INFO(&amp;quot;Entering main loop&amp;quot;);

    while (true)
    {
        while (app_usbd_event_queue_process())
        {
            /* Nothing to do */
        }

        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        /* Sleep CPU only if there was no interrupt since last loop processing */
        __WFE();
    }
}

/** @} */
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;hex file (for nRF52840-DK):&lt;br /&gt;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/communityserver-discussions-components-files/4/5241.nrf52840_5F00_xxaa.hex"&gt;devzone.nordicsemi.com/.../5241.nrf52840_5F00_xxaa.hex&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you need anything else just say&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211913?ContentTypeID=1</link><pubDate>Wed, 25 Sep 2019 19:41:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:57c9cba5-c61e-4730-86ef-9af834d1caae</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Unfortunately I am not able to take time to sit down and debug your project at the moment, but if you can send me the precompiled hex file I can take a quick look at the USB sniffer trace.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211492?ContentTypeID=1</link><pubDate>Tue, 24 Sep 2019 10:24:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:64282083-19b6-4ad3-a5e2-78b668cd4c35</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;You dont need to strip the PDM parts, it will perform just the same without microphones connected and will fill the buffers with trash.&lt;/p&gt;
&lt;p&gt;The USB part will still behave the same&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211368?ContentTypeID=1</link><pubDate>Mon, 23 Sep 2019 16:58:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:56178799-8147-47fb-8e16-22b62f7fbd95</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Is there no way you can strip away the PDM for now so I may run this on a devkit without PDM?&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211298?ContentTypeID=1</link><pubDate>Mon, 23 Sep 2019 13:36:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:98644d85-0725-42b0-941a-6f7038c72a10</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;I have embedded the whole main.c source file above 6 days ago.&lt;/p&gt;
&lt;p&gt;You can comment out the fstorage parts since you wont need them and find 2 PDM mics for input source.&lt;br /&gt;This was based on usb_audio code so same sdk_config (but you need to add PDM support).&lt;/p&gt;
&lt;p&gt;Thanks for helping, something doesnt make sense in the USB functionality&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211292?ContentTypeID=1</link><pubDate>Mon, 23 Sep 2019 13:28:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:36a16140-4ff2-4089-b100-a87be4125897</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/211068?ContentTypeID=1</link><pubDate>Sun, 22 Sep 2019 11:00:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eb3d8331-3f2d-4159-8f23-cbef6466d099</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;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:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;if (!nrf_drv_usbd_ep_enable_check(ep))
{
    return NRF_ERROR_INVALID_STATE;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;inside the file &amp;quot;nRF5_SDK_15.3.0/components/libraries/usbd/app_usbd.c&amp;quot; inside function app_usbd_ep_transfer() (line 1820).&lt;/p&gt;
&lt;p&gt;What can disable the endpoint ? why does it happen in the middle of using it ?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/210234?ContentTypeID=1</link><pubDate>Tue, 17 Sep 2019 20:06:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4db5df3a-8e85-49f1-9d98-6bd522b5e9d1</guid><dc:creator>Or</dc:creator><description>&lt;p&gt;Notice where I placed &lt;em&gt;&lt;strong&gt;app_usbd_audio_class_tx_start()&lt;/strong&gt;&lt;/em&gt; ..&lt;/p&gt;
&lt;p&gt;It is inside the usbd_user_ev_handler() in a switch case of APP_USBD_EVT_DRV_SOF.&lt;br /&gt;Wouldnt that event be called only if a device is at least in activated state ?&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another thing - first thing I check is that the device is configured (&lt;em&gt;&lt;strong&gt;if (APP_USBD_STATE_Configured != app_usbd_core_state_get()) break;&lt;/strong&gt;&lt;/em&gt;).&lt;br /&gt;Doesnt a device reach configured state after it is activated ?&lt;/p&gt;
&lt;p&gt;I attach here the entire main.c for you to take a look at (maybe you will notice something I have missed):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include &amp;lt;stddef.h&amp;gt;

#include &amp;quot;nrf.h&amp;quot;
#include &amp;quot;app_util.h&amp;quot;
#include &amp;quot;nrf_drv_usbd.h&amp;quot;
#include &amp;quot;nrf_drv_clock.h&amp;quot;
#include &amp;quot;nrf_gpio.h&amp;quot;
#include &amp;quot;nrf_delay.h&amp;quot;
#include &amp;quot;nrf_drv_power.h&amp;quot;
#include &amp;quot;nrf_drv_pdm.h&amp;quot;

#include &amp;quot;app_usbd.h&amp;quot;
#include &amp;quot;app_usbd_core.h&amp;quot;
#include &amp;quot;app_usbd_string_desc.h&amp;quot;
#include &amp;quot;app_usbd_audio.h&amp;quot;
#include &amp;quot;app_error.h&amp;quot;
#include &amp;quot;boards.h&amp;quot;

#include &amp;quot;nrf_drv_clock.h&amp;quot;
#include &amp;quot;nrf_fstorage_nvmc.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;
#include &amp;quot;nrf_log_ctrl.h&amp;quot;
#include &amp;quot;nrf_log_default_backends.h&amp;quot;

/**@file
 * @defgroup usbd_aduio_example main.c
 * @{
 * @ingroup usbd_audio_example
 * @brief USBD Audio class example
 *
 */

/* FSTORAGE
 */
void fstorage_callback(nrf_fstorage_evt_t * p_evt);

#define FSTORAGE_BASE_ADDR 0x60000
#define FSTORAGE_END_ADDR 0x80000

static volatile uint32_t flash_addr = FSTORAGE_BASE_ADDR;
static volatile uint8_t fstorage_write_done = 1;

NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage_instance) =
{
    .evt_handler    = fstorage_callback,
    .start_addr     = FSTORAGE_BASE_ADDR,
    .end_addr       = FSTORAGE_END_ADDR,
};

// buffers for the PDM source
#define NRFX_PDM_BUFFER_SIZE 500
static volatile int8_t pdm_buffer_i = 0;
static int16_t pdm_buffer[2][NRFX_PDM_BUFFER_SIZE];
static volatile int8_t usb_tx_done = 1, audio_buffer_txed = 1;

#define LED_USB_RESUME (BSP_BOARD_LED_0)
#define LED_USB_START  (BSP_BOARD_LED_1)
#define LED_AUDIO_RX   (BSP_BOARD_LED_2)
#define LED_AUDIO_TX   (BSP_BOARD_LED_3)

/**
 * @brief USB audio samples size
 */
#define BUFFER_SIZE  (48)

/**
 * @brief Enable power USB detection
 *
 * Configure if example supports USB port connection
 */
#ifndef USBD_POWER_DETECTION
#define USBD_POWER_DETECTION true
#endif

/**
 * @brief Audio class user event handler
 */
static void mic_audio_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                      app_usbd_audio_user_event_t   event);

/* Channels and feature controls configuration */

/**
 * @brief   Input terminal channel configuration
 */
#define MIC_TERMINAL_CH_CONFIG()                                                                       \
        (APP_USBD_AUDIO_IN_TERM_CH_CONFIG_LEFT_FRONT | APP_USBD_AUDIO_IN_TERM_CH_CONFIG_RIGHT_FRONT)

/**
 * @brief   Feature controls
 *
 *      general
 *      channel 0
 *      channel 1
 */
#define MIC_FEATURE_CONTROLS()                                                                     \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE),                         \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE),                         \
        APP_USBD_U16_TO_RAW_DSC(APP_USBD_AUDIO_FEATURE_UNIT_CONTROL_MUTE)


/* Microphone descriptors */

/**
 * @brief   Audio class specific format descriptor
 */
APP_USBD_AUDIO_FORMAT_DESCRIPTOR(m_mic_form_desc, 
                                 APP_USBD_AUDIO_AS_FORMAT_I_DSC(    /* Format type 1 descriptor */
                                    2,                              /* Number of channels */
                                    2,                              /* Subframe size */
                                    16,                             /* Bit resolution */
                                    1,                              /* Frequency type */
                                    APP_USBD_U24_TO_RAW_DSC(16000)) /* Frequency */
                                );

/**
 * @brief   Audio class input terminal descriptor
 */
APP_USBD_AUDIO_INPUT_DESCRIPTOR(m_mic_inp_desc, 
                                APP_USBD_AUDIO_INPUT_TERMINAL_DSC(
                                    1,                                     /* Terminal ID */
                                    APP_USBD_AUDIO_TERMINAL_IN_MICROPHONE, /* Terminal type */
                                    2,                                     /* Number of channels */
                                    MIC_TERMINAL_CH_CONFIG())              /* Channels config */
                                );

/**
 * @brief   Audio class output terminal descriptor
 */
APP_USBD_AUDIO_OUTPUT_DESCRIPTOR(m_mic_out_desc, 
                                 APP_USBD_AUDIO_OUTPUT_TERMINAL_DSC(
                                    3,                                     /* Terminal ID */
                                    APP_USBD_AUDIO_TERMINAL_USB_STREAMING, /* Terminal type */
                                    2)                                     /* Source ID */
                                );

/**
 * @brief   Audio class feature unit descriptor
 */
APP_USBD_AUDIO_FEATURE_DESCRIPTOR(m_mic_fea_desc, 
                                  APP_USBD_AUDIO_FEATURE_UNIT_DSC(
                                    2,                      /* Unit ID */
                                    1,                      /* Source ID */
                                    MIC_FEATURE_CONTROLS()) /* List of controls */
                                 );

/* Interfaces lists */

/**
 * @brief Interfaces list passed to @ref APP_USBD_AUDIO_GLOBAL_DEF
 */
#define MIC_INTERFACES_CONFIG() APP_USBD_AUDIO_CONFIG_IN(2, 3)

/*lint -save -e26 -e64 -e123 -e505 -e651*/

/**
 * @brief Microphone Audio class instance
 */
APP_USBD_AUDIO_GLOBAL_DEF(m_app_audio_microphone,
                          MIC_INTERFACES_CONFIG(),
                          mic_audio_user_ev_handler,
                          &amp;amp;m_mic_form_desc,
                          &amp;amp;m_mic_inp_desc,
                          &amp;amp;m_mic_out_desc,
                          &amp;amp;m_mic_fea_desc,
                          0,
                          APP_USBD_AUDIO_AS_IFACE_FORMAT_PCM,
                          192,
                          APP_USBD_AUDIO_SUBCLASS_AUDIOSTREAMING
);


/*lint -restore*/

/**
 * @brief Internal audio temporary buffer
 */
//static int16_t  m_temp_buffer[2 * BUFFER_SIZE];



/**
 * @brief The size of last received block from the microphone
 */
//static size_t m_temp_buffer_size;

/**
 * @brief Actual microphone mute state
 */
static uint8_t  m_mute_mic;

/**
 * @brief Actual microphone sampling frequency
 */
static uint32_t m_freq_mic;

/**
 * @brief Audio class specific request handle (microphone)
 */
static void mic_audio_user_class_req(app_usbd_class_inst_t const * p_inst)
{
    app_usbd_audio_t const * p_audio = app_usbd_audio_class_get(p_inst);
    app_usbd_audio_req_t * p_req = app_usbd_audio_class_request_get(p_audio);

    UNUSED_VARIABLE(m_mute_mic);
    UNUSED_VARIABLE(m_freq_mic);

    switch (p_req-&amp;gt;req_target)
    {
        case APP_USBD_AUDIO_CLASS_REQ_IN:

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only mute control is defined
                p_req-&amp;gt;payload[0] = m_mute_mic;
            }

            break;
        case APP_USBD_AUDIO_CLASS_REQ_OUT:

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only mute control is defined
                m_mute_mic = p_req-&amp;gt;payload[0];
            }

            break;
        case APP_USBD_AUDIO_EP_REQ_IN:
            break;
        case APP_USBD_AUDIO_EP_REQ_OUT:

            if (p_req-&amp;gt;req_type == APP_USBD_AUDIO_REQ_SET_CUR)
            {
                //Only set frequency is supported
                m_freq_mic = uint24_decode(p_req-&amp;gt;payload);
            }

            break;
        default:
            break;
    }
}

/**
 * @brief User event handler @ref app_usbd_audio_user_ev_handler_t (microphone)
 */
static void mic_audio_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                      app_usbd_audio_user_event_t   event)
{
    app_usbd_audio_t const * p_audio = app_usbd_audio_class_get(p_inst);
    UNUSED_VARIABLE(p_audio);

    switch (event)
    {
        case APP_USBD_AUDIO_USER_EVT_CLASS_REQ:
            mic_audio_user_class_req(p_inst);
            break;
        case APP_USBD_AUDIO_USER_EVT_TX_DONE:
        {
        	usb_tx_done = 1;
            bsp_board_led_invert(LED_AUDIO_TX);
            break;
        }
        default:
            break;
    }
}

/**
 * @brief USBD library specific event handler.
 *
 * @param event     USBD library event.
 */
static void usbd_user_ev_handler(app_usbd_event_type_t event)
{
    switch (event)
    {
        case APP_USBD_EVT_DRV_SOF:
            // make sure we&amp;#39;re in proper state (configured)
            if (APP_USBD_STATE_Configured != app_usbd_core_state_get()) break;

            // are we in the middle of a transfer ?
            if (!usb_tx_done) break;

            // do we have a buffer ready for transfer ?
            if (audio_buffer_txed) break;

        	// transfer the off-line buffer to the USB device now
            usb_tx_done = 0;
            ret_code_t ret = app_usbd_audio_class_tx_start(&amp;amp;m_app_audio_microphone.base,
        			pdm_buffer[pdm_buffer_i == 0 ? 1 : 0], NRFX_PDM_BUFFER_SIZE);

            // haven&amp;#39;t started transferring -&amp;gt; wont reach TX done
            if (ret != NRF_SUCCESS) {
            	usb_tx_done = 1;
            	NRF_LOG_INFO(&amp;quot;APP_USBD_EVT_DRV_SOF -&amp;gt; app_usbd_audio_class_tx_start = %d&amp;quot;, ret);
            }

            // this buffer is being transferred
            else audio_buffer_txed = 1;

            break;
        case APP_USBD_EVT_DRV_SUSPEND:
            bsp_board_leds_off();
            break;
        case APP_USBD_EVT_DRV_RESUME:
            bsp_board_led_on(LED_USB_RESUME);
            break;
        case APP_USBD_EVT_STARTED:
            bsp_board_led_on(LED_USB_START);

            // start PDM
            APP_ERROR_CHECK(nrfx_pdm_start());

            break;
        case APP_USBD_EVT_STOPPED:
        	// start PDM
        	APP_ERROR_CHECK(nrfx_pdm_stop());

            app_usbd_disable();
            bsp_board_leds_off();
            break;
        case APP_USBD_EVT_POWER_DETECTED:
            NRF_LOG_INFO(&amp;quot;USB power detected&amp;quot;);

            if (!nrf_drv_usbd_is_enabled())
            {
                app_usbd_enable();
            }
            break;
        case APP_USBD_EVT_POWER_REMOVED:
            NRF_LOG_INFO(&amp;quot;USB power removed&amp;quot;);
            app_usbd_stop();
            break;
        case APP_USBD_EVT_POWER_READY:
            NRF_LOG_INFO(&amp;quot;USB ready&amp;quot;);
            app_usbd_start();
            break;
        default:
            break;
    }
}

static void nrfx_pdm_event_handler(nrfx_pdm_evt_t const *const p_evt) {
	/*NRF_LOG_INFO(&amp;quot;nrfx_pdm_event_handler(buffer_released:%d buffer_requested:%d error:%d)&amp;quot;,
			p_evt-&amp;gt;buffer_released == NULL ? 0 : 1,
			p_evt-&amp;gt;buffer_requested ? 1 : 0,
			p_evt-&amp;gt;error);*/

	// we have an error ?
	if (p_evt-&amp;gt;error != NRFX_PDM_NO_ERROR) {
		NRF_LOG_INFO(&amp;quot;PDM error event: %d&amp;quot;, p_evt-&amp;gt;error);
		return;
	}

	// got a buffer with data ?
	if (p_evt-&amp;gt;buffer_released != NULL) {
		// we have buffer ready
		audio_buffer_txed = 0;

		// do we have space to write ?
		if (flash_addr + NRFX_PDM_BUFFER_SIZE*2 &amp;lt; FSTORAGE_END_ADDR) {
			if (fstorage_write_done /*nrf_fstorage_is_busy(&amp;amp;fstorage_instance)*/) {
				// write to flash
				fstorage_write_done = 0;
				ret_code_t rc = nrf_fstorage_write(
					&amp;amp;fstorage_instance,     /* The instance to use. */
					flash_addr,             /* The address in flash where to store the data. */
					p_evt-&amp;gt;buffer_released, /* A pointer to the data. */
					NRFX_PDM_BUFFER_SIZE*2, /* Lenght of the data, in bytes. */
					NULL                    /* Optional parameter, backend-dependent. */
				);

				if (rc != NRF_SUCCESS)
					NRF_LOG_ERROR(&amp;quot;nrf_fstorage_write() = %d&amp;quot;, rc);
			} else NRF_LOG_ERROR(&amp;quot;fstorage busy -&amp;gt; dumping buffer&amp;quot;);
		}
	}

	// expected to set a new buffer ?
	if (p_evt-&amp;gt;buffer_requested) {
		NRF_LOG_INFO(&amp;quot;PDM buffer requested&amp;quot;);

		// update buffer index
		pdm_buffer_i = pdm_buffer_i == 0 ? 1 : 0;

		// set new buffer
		nrfx_pdm_buffer_set(pdm_buffer[pdm_buffer_i], NRFX_PDM_BUFFER_SIZE);
	}
}

void fstorage_callback(nrf_fstorage_evt_t * p_evt) {
	if (p_evt-&amp;gt;result != NRF_SUCCESS) {
		NRF_LOG_INFO(&amp;quot;--&amp;gt; Event received: ERROR while executing an fstorage operation.&amp;quot;);
		return;
	}

	switch (p_evt-&amp;gt;id) {
	case NRF_FSTORAGE_EVT_WRITE_RESULT:
		NRF_LOG_INFO(&amp;quot;--&amp;gt; Event received: wrote %d bytes at address 0x%x.&amp;quot;, p_evt-&amp;gt;len, p_evt-&amp;gt;addr);
		flash_addr += NRFX_PDM_BUFFER_SIZE*2;
		fstorage_write_done = 1;
		break;

	default:
		break;
	}
}

int main(void)
{
    ret_code_t ret;
    static const app_usbd_config_t usbd_config = {
        .ev_state_proc = usbd_user_ev_handler,
        .enable_sof = true
    };

    ret = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(ret);
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);

    ret = nrf_fstorage_init(
		&amp;amp;fstorage_instance, /* You fstorage instance, previously defined. */
		&amp;amp;nrf_fstorage_nvmc, /* Name of the backend. */
		NULL                /* Optional parameter, backend-dependant. */
	);
    APP_ERROR_CHECK(ret);

    nrfx_pdm_config_t config = NRFX_PDM_DEFAULT_CONFIG(ARDUINO_SCL_PIN, ARDUINO_SDA_PIN);
    ret = nrfx_pdm_init(&amp;amp;config, nrfx_pdm_event_handler);
    APP_ERROR_CHECK(ret);

    NRF_LOG_INFO(&amp;quot;USBD audio example started.&amp;quot;);

    // Initialize LEDs and buttons
    bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);

    ret = app_usbd_init(&amp;amp;usbd_config);
    APP_ERROR_CHECK(ret);

    app_usbd_class_inst_t const * class_inst_mic =
        app_usbd_audio_class_inst_get(&amp;amp;m_app_audio_microphone);
    ret = app_usbd_class_append(class_inst_mic);
    APP_ERROR_CHECK(ret);

    if (USBD_POWER_DETECTION)
    {
        ret = app_usbd_power_events_enable();
        APP_ERROR_CHECK(ret);
    }
    else
    {
        NRF_LOG_INFO(&amp;quot;No USB power detection enabled\r\nStarting USB now&amp;quot;);

        app_usbd_enable();
        app_usbd_start();
    }

    NRF_LOG_INFO(&amp;quot;Entering main loop&amp;quot;);

    while (true)
    {
        while (app_usbd_event_queue_process())
        {
            /* Nothing to do */
        }

        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        /* Sleep CPU only if there was no interrupt since last loop processing */
        __WFE();
    }
}

/** @} */&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Passing data from PDM callback to USB audio device</title><link>https://devzone.nordicsemi.com/thread/210224?ContentTypeID=1</link><pubDate>Tue, 17 Sep 2019 18:58:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3ac5f968-a7ec-4f86-b950-c17bd2ff4b54</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;&lt;span&gt;I assume that app_usbd_audio_class_tx_start() return NRF_ERROR_INVALID_STATE because the USB driver is not in active state (&lt;/span&gt;&lt;span&gt;SUSTATE_ACTIVE). I would have started looking at why the driver haven&amp;#39;t transitioned to active state (compared to default example for instance&amp;nbsp;\nRF5_SDK_15.3.0_59ac345\examples\peripheral\usbd_audio).&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>