Pulse Code Modulation (PCM) API Reference#

The Pulse Code Modulation (PCM) unified application programming interface (API) provides functions for initialization, configuration, blocking and non-blocking data transfers, direct memory access (DMA) integration, and event-based callbacks.

Use these APIs to operate the PCM peripheral in Primary (controller) or Secondary (target) mode and to build robust, low-latency digital audio streaming applications on SiWx917 devices.

Public APIs#

This section introduces the public PCM APIs available on the SiWx917 platform.

The PCM APIs support initialization, configuration, and data transfer management for digital audio streams.

You can use these APIs to:

  • Configure primary or secondary operation modes

  • Set sampling rate, bit depth, and channel configuration

  • Perform blocking or non-blocking data transfers for transmit and receive operations

  • Integrate DMA for efficient and non-blocking data streaming

Complete Reference:
PCM Public APIs — WiSeConnect (Si91x)

Example Projects:

Callback and Notification APIs#

In addition to synchronous (blocking) operation, the PCM driver supports asynchronous event notifications. By registering an application callback (typically during initialization), your application can be notified of key PCM events such as:

  • Transfer completion

  • FIFO underrun or overrun

  • DMA transfer errors

  • Frame synchronization issues

This event-driven approach improves responsiveness and allows the CPU to perform other tasks while audio data is being transferred.

Callback Function Definition#

The following typedef defines the function signature for callbacks invoked by the PCM driver when a runtime event occurs:

typedef void (*sl_pcm_callback_t)(sl_pcm_instance_t pcm_instance, uint32_t event);

Parameters:

  • pcm_instance: Identifies the PCM instance that generated the event.

  • event: Indicates the event type (for example, transfer complete, underrun, or error).

Usage Guidelines#

  1. Implement a callback function that matches the sl_pcm_callback_t signature.

  2. Assign your callback to the configuration structure (config.pcm_callback = my_pcm_event_handler;).

  3. Initialize the PCM driver using the driver initialization API:

    sl_pcm_status_t sl_pcm_driver_init(sl_pcm_instance_t pcm_instance, const sl_pcm_config_t *p_user_config);
  4. Use the callback to handle transfer completion or error conditions.

  5. Keep the callback short and non-blocking—use flags or queues to defer processing to application threads.

Example#

void my_pcm_event_handler(sl_pcm_instance_t pcm_instance, uint32_t event)
{
    if (event == SL_PCM_EVENT_TRANSFER_COMPLETE) {
        DEBUGOUT("PCM transfer completed successfully.\n");
    } else if (event == SL_PCM_EVENT_UNDERRUN) {
        DEBUGOUT("PCM underrun occurred — check buffer management.\n");
    } else {
        DEBUGOUT("PCM event: %lu\n", event);
    }
}

void app_pcm_init(void)
{
    sl_pcm_config_t config = {0};
    config.mode = SL_PCM_PRIMARY;              // Primary (controller) mode
    config.sample_rate = SL_PCM_SAMPLING_RATE_16000; // 16 kHz
    config.data_size = SL_PCM_DATA_SIZE_16;    // 16-bit resolution
    config.pcm_callback = my_pcm_event_handler; // Register callback

    sl_pcm_driver_init(SL_PCM_INSTANCE_0, &config); // Initialize PCM driver
}

Integration#

To use callbacks effectively:

  • Register your callback during initialization or via a dedicated register-callback API.

  • Ensure your callback is lightweight—avoid blocking calls or long computations.

  • Use synchronization primitives (for example, semaphores or message queues) to notify application threads.

  • Monitor event codes for transfer complete, underrun, and error handling.

Example Initialization Prototype:

sl_pcm_status_t sl_pcm_driver_init(sl_pcm_instance_t pcm_instance, const sl_pcm_config_t *p_user_config);

Common Steps#

  1. Define the callback using sl_pcm_callback_t.

  2. Assign it to your configuration structure.

  3. Initialize the PCM driver with the callback.

  4. Trigger transfers using blocking or DMA-based APIs.

  5. Handle completion or error events inside your callback.

Best Practices#

  • Enable debug logs to monitor transfer progress and error codes.

  • Use a logic analyzer to observe PCM signals (BCLK, WS/LRCLK, DIN, DOUT) for timing validation.

  • Confirm that DMA buffer alignment matches hardware requirements.

  • Test both blocking and non-blocking transfer paths for functional coverage.

Reference#

For more information, see: