TI-RTOS Drivers
tidrivers_cc13xx_cc26xx_2_21_01_01
|
PDM driver implementation for a CC26XX PDM controller.
============================================================================
The PDM header file should be included in an application as follows:
This driver is written to be able to perform continuous audio streaming of PDM data from a microphone. It also controls one DIO to be able to turn on power to the microphone.
This PDM driver performs two operations that requires processing
This driver is configured to process 256 bytes of PDM data provided by the I2S hardware module at a time, sampled at 1.024 Mbps. The PDM driver consequently receives such a buffer approximately every 2ms. A frame of PDMCC26XX_Params.retBufSizeInBytes PCM data bytes minus four metadata bytes is provided to the application after being filled by all or part of one or more 64 byte buffers of PCM data derived from the 256 bytes of PDM data. The resulting PCM frame provided to the application is a 16bit PCM signal sampled at 16kHz.
The driver creates a separate task to run in.
The driver currently only samples on a single edge of the I2S clock.
Before using PDM on CC26XX:
While using PDM on CC26XX:
After PDM operation has ended:
The application is notified of errors via the registered callback function.
If the application fails to consume buffers in a timely manner and consequently the heap is full when driver tries to allocate a new buffer for new incoming data, the driver will drop all new incoming data until a buffer can be allocated to store it. Data is dropped one PCM data buffer at a time , even though it is streamed into the device and copied into the buffer in smaller chunks. This is done to keep the data expected in any buffer in sync with the sequence number of the buffer that keeps incrementing even when the buffer is dopped. The application may keep track of lost frames by comparing sequence numbers.
Hence, the PDM stream will never have a buffer overflow, but if the memory available in the heap is too low it may lose frames because because there is nowhere to put the incoming
If the heap frees up again and the PDM task runs, it will automatically resume normal operation again. The only application-observable difference is the incremented version number.
PDMCC26XX_open() returns NULL and rolls back all prior parts of the initialisation if any part of the initialisation fails. The following can cause PDMCC26XX_open() to fail:
PDMCC26XX_startStream() returns false if it fails. The following can cause PDMCC26XX_startStream() to fail:
PDMCC26XX_stopStream() returns false if it fails. The following can cause PDMCC26XX_stopStream() to fail:
The PDMCC26XX driver sets a power constraint while streaming to keep the device out of standby. When the stream has ended, the power constraint is released.
The following statements are valid:
API function | Description |
---|---|
PDMCC26XX_init() | Initialize PDM driver |
PDMCC26XX_open() | Set system dependencies, configure pins |
PDMCC26XX_startStream() | Turn on mic, start stream and prevent standby |
PDMCC26XX_stopStream() | Stop stream and release standby hold, turn off mic |
PDMCC26XX_requestBuffer() | Request a buffer from the driver |
PDMCC26XX_close() | Disable HW and release system dependencies |
The standard use case involves calling PDMCC26XX_open() once and calling PDMCC26XX_startStream() and PDMCC26XX_stopStream() to start and stop the stream as needed. PDMCC26XX_close() is called when the PDM driver will no longer be needed again. In order for the PDM driver task to run, the application pends on a semaphore that is posted in the PDMCC26XX_Params::callbackFxn. In this example, the application requests 128 buffers. In a real application, the process of pending on a semaphore, requesting a buffer, and freeing it would be repeated as often as required by the use case before stopping the stream.
The PDM driver interface produces log statements if instrumentation is enabled.
Instrumentation | Description |
---|---|
Diags_USER1 | Logs the start and end of each API call of the PDM driver and progress through events |
Diags_USER2 | Logs occurances in the I2S sub-module of the PDM driver |
Warnings | Logs unexpected events such as initialisations or memory allocations failing |
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/drivers/PIN.h>
#include <ti/sysbios/family/arm/m3/Hwi.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
Go to the source code of this file.
Data Structures | |
struct | PDMCC26XX_metaData |
Metadata associated with an array of PCM data. More... | |
struct | PDMCC26XX_pcmBuffer |
PCM buffer pointed to in a PDMCC26XX_BufferRequest. More... | |
struct | PDMCC26XX_Config |
The PDMCC26XX_Config structure contains a set of pointers used to characterize the PDMCC26XX driver implementation. More... | |
struct | PDMCC26XX_HWAttrs |
PDMCC26XX Hardware attributes. More... | |
struct | PDMCC26XX_StreamNotification |
A PDMCC26XX_StreamNotification data structure is used with PDMCC26XX_CallbackFxn(). Provides notification about available buffers and potential errors. More... | |
struct | PDMCC26XX_BufferRequest |
A PDMCC26XX_BufferRequest data structure is used with PDMCC26XX_requestBuffer(). More... | |
struct | PDMCC26XX_Params |
PDMCC26XX Parameters are used to with the PDMCC26XX_open() call. Default values for these parameters are set using PDMCC26XX_Params_init(). More... | |
struct | PDMCC26XX_Object |
PDMCC26XX Object. More... | |
Macros | |
#define | ti_sysbios_family_arm_m3_Hwi__nolocalnames |
#define | PDM_TASK_STACK_SIZE 500 |
#define | PDM_BUFFER_SIZE_IN_BLOCKS 3 |
#define | PCM_SAMPLE_SIZE 16 |
#define | PCM_COMPRESSION_RATE 4 |
#define | PCM_METADATA_SIZE sizeof(PDMCC26XX_metaData) |
Typedefs | |
typedef void *(* | PDMCC26XX_MallocFxn) (size_t memSize) |
PDMCC26XX_MallocFxn is a function pointer for the malloc function to be used by the driver. More... | |
typedef void(* | PDMCC26XX_FreeFxn) (void *ptr, size_t memSize) |
PDMCC26XX_FreeFxn is a function pointer for the free function to be used by the driver. This is needed for memory clean up, if something goes wrong. More... | |
typedef struct PDMCC26XX_Config | PDMCC26XX_Config |
The PDMCC26XX_Config structure contains a set of pointers used to characterize the PDMCC26XX driver implementation. More... | |
typedef struct PDMCC26XX_HWAttrs | PDMCC26XX_HWAttrs |
PDMCC26XX Hardware attributes. More... | |
typedef struct PDMCC26XX_Config * | PDMCC26XX_Handle |
A handle that is returned from a PDMCC26XX_open() call. More... | |
typedef enum PDMCC26XX_Status | PDMCC26XX_Status |
Status codes that are set by the PDM driver. More... | |
typedef enum PDMCC26XX_Gain | PDMCC26XX_Gain |
Predefined gain settings. More... | |
typedef struct PDMCC26XX_StreamNotification | PDMCC26XX_StreamNotification |
A PDMCC26XX_StreamNotification data structure is used with PDMCC26XX_CallbackFxn(). Provides notification about available buffers and potential errors. More... | |
typedef void(* | PDMCC26XX_CallbackFxn) (PDMCC26XX_Handle handle, PDMCC26XX_StreamNotification *streamNotification) |
The definition of a callback function used when buffers are ready. More... | |
typedef struct PDMCC26XX_BufferRequest | PDMCC26XX_BufferRequest |
A PDMCC26XX_BufferRequest data structure is used with PDMCC26XX_requestBuffer(). More... | |
typedef struct PDMCC26XX_Params | PDMCC26XX_Params |
PDMCC26XX Parameters are used to with the PDMCC26XX_open() call. Default values for these parameters are set using PDMCC26XX_Params_init(). More... | |
typedef struct PDMCC26XX_Object | PDMCC26XX_Object |
PDMCC26XX Object. More... | |
Enumerations | |
enum | PDMCC26XX_Status { PDMCC26XX_STREAM_IDLE, PDMCC26XX_STREAM_BLOCK_READY, PDMCC26XX_STREAM_BLOCK_READY_BUT_PDM_OVERFLOW, PDMCC26XX_STREAM_ERROR, PDMCC26XX_STREAM_STOPPING, PDMCC26XX_STREAM_STOPPED, PDMCC26XX_STREAM_FAILED_TO_STOP } |
Status codes that are set by the PDM driver. More... | |
enum | PDMCC26XX_Gain { PDMCC26XX_GAIN_24, PDMCC26XX_GAIN_18, PDMCC26XX_GAIN_12, PDMCC26XX_GAIN_6, PDMCC26XX_GAIN_0, PDMCC26XX_GAIN_END } |
Predefined gain settings. More... | |
Functions | |
void | PDMCC26XX_init (PDMCC26XX_Handle handle) |
PDM CC26XX initialization. More... | |
PDMCC26XX_Handle | PDMCC26XX_open (PDMCC26XX_Params *params) |
Function to initialize the CC26XX PDM peripheral specified by the particular handle. The parameter specifies which mode the PDM will operate. More... | |
void | PDMCC26XX_close (PDMCC26XX_Handle handle) |
Function to close a given CC26XX PDM peripheral specified by the PDM handle. More... | |
bool | PDMCC26XX_startStream (PDMCC26XX_Handle handle) |
Function to start streaming PDM data. More... | |
bool | PDMCC26XX_stopStream (PDMCC26XX_Handle handle) |
Function to stop streaming PDM data. More... | |
bool | PDMCC26XX_requestBuffer (PDMCC26XX_Handle handle, PDMCC26XX_BufferRequest *bufferRequest) |
Function for requesting buffer. More... | |
Variables | |
const PDMCC26XX_Config | PDMCC26XX_config [] |
#define ti_sysbios_family_arm_m3_Hwi__nolocalnames |
The following allows this header file to be included in an application file which also includes ti/sysbios/hal/Hwi.h.
#define PDM_TASK_STACK_SIZE 500 |
Defines TI-RTOS stack size allocation. It is a conservative estimate. Change this to save a few bytes of RAM on stack allocation. The stack usage is independent of the PCM return buffer size specified by the application.
#define PDM_BUFFER_SIZE_IN_BLOCKS 3 |
PDM buffer size in number of blocks. We assume that we will be able to consume PDM samples in a timely manner. This allows us to use the minium number of blocks (3) for the PDMCC26XX driver. If the application can not service the PDM task in time, increase this value to permit more latency in processing incoming PDM data at the cost of increased RAM useage.
#define PCM_SAMPLE_SIZE 16 |
Uncompressed PCM sample size in bits
#define PCM_COMPRESSION_RATE 4 |
Compression rate if compression is enabled
#define PCM_METADATA_SIZE sizeof(PDMCC26XX_metaData) |
PCM data metadata size. When a buffer is requested there will be metadata prepended. In other words the pointer returned points to the metadata header. Depending on the mode, this contains different information. The first byte is always an 8-bit sequence number.
typedef void*(* PDMCC26XX_MallocFxn) (size_t memSize) |
PDMCC26XX_MallocFxn is a function pointer for the malloc function to be used by the driver.
typedef void(* PDMCC26XX_FreeFxn) (void *ptr, size_t memSize) |
PDMCC26XX_FreeFxn is a function pointer for the free function to be used by the driver. This is needed for memory clean up, if something goes wrong.
typedef struct PDMCC26XX_Config PDMCC26XX_Config |
The PDMCC26XX_Config structure contains a set of pointers used to characterize the PDMCC26XX driver implementation.
typedef struct PDMCC26XX_HWAttrs PDMCC26XX_HWAttrs |
PDMCC26XX Hardware attributes.
These fields are used by the PDM driver
typedef struct PDMCC26XX_Config* PDMCC26XX_Handle |
A handle that is returned from a PDMCC26XX_open() call.
typedef enum PDMCC26XX_Status PDMCC26XX_Status |
Status codes that are set by the PDM driver.
typedef enum PDMCC26XX_Gain PDMCC26XX_Gain |
Predefined gain settings.
Gain is controlled by modifying the first coefficient of the PDM filter. Use these defines to get correct gain setting. All these values are in dB. Default filter will add 12dB gain. In fact this is not an amplification, this setting uses all the information in the PDM samples, so if use case allows it this will have the least compromised range. PDM2PCM algotrithm returns false if any of the samples decimated goes above 2^16 - 1, i.e. the sample clipped during decimation. This information can be used for automatic gain control.
typedef struct PDMCC26XX_StreamNotification PDMCC26XX_StreamNotification |
A PDMCC26XX_StreamNotification data structure is used with PDMCC26XX_CallbackFxn(). Provides notification about available buffers and potential errors.
typedef void(* PDMCC26XX_CallbackFxn) (PDMCC26XX_Handle handle, PDMCC26XX_StreamNotification *streamNotification) |
The definition of a callback function used when buffers are ready.
PDMCC26XX_Handle | PDMCC26XX_Handle |
typedef struct PDMCC26XX_BufferRequest PDMCC26XX_BufferRequest |
A PDMCC26XX_BufferRequest data structure is used with PDMCC26XX_requestBuffer().
buffer is a pointer to the requested buffer. It is NULL if no buffer is available. Each buffer contains a metadata header of size PCM_METADATA_SIZE. The first byte of the metadata is always an 8 bit sequence number. The other bytes depends on mode.
Mode | Interpretation of bufferIn being NULL after returning |
---|---|
Blocking mode | Request timed out and still no buffer available |
Non-Blocking mode | No buffer available |
typedef struct PDMCC26XX_Params PDMCC26XX_Params |
PDMCC26XX Parameters are used to with the PDMCC26XX_open() call. Default values for these parameters are set using PDMCC26XX_Params_init().
typedef struct PDMCC26XX_Object PDMCC26XX_Object |
PDMCC26XX Object.
The application must not access any member variables of this structure!
enum PDMCC26XX_Status |
Status codes that are set by the PDM driver.
enum PDMCC26XX_Gain |
Predefined gain settings.
Gain is controlled by modifying the first coefficient of the PDM filter. Use these defines to get correct gain setting. All these values are in dB. Default filter will add 12dB gain. In fact this is not an amplification, this setting uses all the information in the PDM samples, so if use case allows it this will have the least compromised range. PDM2PCM algotrithm returns false if any of the samples decimated goes above 2^16 - 1, i.e. the sample clipped during decimation. This information can be used for automatic gain control.
Enumerator | |
---|---|
PDMCC26XX_GAIN_24 |
24dB gain |
PDMCC26XX_GAIN_18 |
18dB gain |
PDMCC26XX_GAIN_12 |
12dB gain. Default |
PDMCC26XX_GAIN_6 |
6dB gain |
PDMCC26XX_GAIN_0 |
0dB gain |
PDMCC26XX_GAIN_END |
Internal use only |
void PDMCC26XX_init | ( | PDMCC26XX_Handle | handle | ) |
PDM CC26XX initialization.
PDMCC26XX_Handle PDMCC26XX_open | ( | PDMCC26XX_Params * | params | ) |
Function to initialize the CC26XX PDM peripheral specified by the particular handle. The parameter specifies which mode the PDM will operate.
The function will set a dependency on the PDM module, which in turn powers up the module and enables the clock. IOs are also allocated, however the PDM driver will not begin streaming audio until PDMCC26XX_startStream() is called.
params | Pointer to a parameter block. Will use default parameters if NULL |
void PDMCC26XX_close | ( | PDMCC26XX_Handle | handle | ) |
Function to close a given CC26XX PDM peripheral specified by the PDM handle.
Posts an event that shuts down the I2S hardware, frees all memory used by the driver on the heap, releases the pins back to the PIN driver, and releases the dependency on the corresponding power domain.
handle | A PDMCC26XX_Handle returned from PDMCC26XX_open() |
bool PDMCC26XX_startStream | ( | PDMCC26XX_Handle | handle | ) |
Function to start streaming PDM data.
Posts an event that tells the I2S hardware to start streaming and the PDM task to start processing incoming data.
handle | A PDM handle returned from PDMCC26XX_open() |
bool PDMCC26XX_stopStream | ( | PDMCC26XX_Handle | handle | ) |
Function to stop streaming PDM data.
Blocks while the I2S module shuts down gracefully. Subsequently posts an event to let the PDM task process any remaining data.
handle | A PDM handle returned from PDMCC26XX_open() |
bool PDMCC26XX_requestBuffer | ( | PDMCC26XX_Handle | handle, |
PDMCC26XX_BufferRequest * | bufferRequest | ||
) |
Function for requesting buffer.
PDMCC26XX_requestBuffer returns immediately even if no buffer is available. The caller is notified through events each time a buffer is available. However, more than one buffer may be available. Hence, the caller should request even without notification if the caller is ready to process.
handle | A PDM handle returned from PDMCC26XX_open() |
*bufferRequest | Pointer to PDMCC26XX_BufferRequest struct |
const PDMCC26XX_Config PDMCC26XX_config[] |
PDMCC26XX_Config struct defined in the board file