RA Flexible Software Package Documentation  Release v5.7.0

 
Audio Playback PWM (rm_audio_playback_pwm)

Functions

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Open (audio_playback_ctrl_t *const p_api_ctrl, audio_playback_cfg_t const *const p_cfg)
 
fsp_err_t RM_AUDIO_PLAYBACK_PWM_Close (audio_playback_ctrl_t *const p_api_ctrl)
 
fsp_err_t RM_AUDIO_PLAYBACK_PWM_Start (audio_playback_ctrl_t *const p_api_ctrl)
 
fsp_err_t RM_AUDIO_PLAYBACK_PWM_Stop (audio_playback_ctrl_t *const p_api_ctrl)
 
fsp_err_t RM_AUDIO_PLAYBACK_PWM_Play (audio_playback_ctrl_t *const p_api_ctrl, void const *const p_buffer, uint32_t length)
 

Detailed Description

Driver for the Audio Playback middleware on RA MCUs. This module implements the AUDIO PLAYBACK Interface.

Overview

Features

The Audio Playback with PWM middleware is used to play audio streams at user selected playback rate using Pulse Width Modulation hardware on GPT or AGT timers. This module can play 16-bit or 32-bit(available on selected MCUs) uncompressed, unsigned PCM audio stream when AGT is selected as PWM interface, and can play 32-bit uncompressed, unsigned PCM audio stream when GPT is used as PWM interface. Note some MCUs have 16-bit GPT timers/channels. In this case audio stream still needs to be 32 bits because the duty cycle register is 32-bit - just the upper 16 bits are ignored. The application code is expected to convert the signed PCM data to unsigned PCM data and scale it with the playback rate before starting the playback.

Configuration

Build Time Configurations for rm_audio_playback_pwm

The following build time configurations are defined in fsp_cfg/rm_audio_playback_pwm_cfg.h:

ConfigurationOptionsDefaultDescription
Parameter Checking
  • Default (BSP)
  • Enabled
  • Disabled
Default (BSP) If selected code for parameter checking is included in the build.
DMAC Support
  • Enabled
  • Disabled
Disabled Select if DMAC will be used.

Configurations for Audio > Audio Playback PWM (rm_audio_playback_pwm)

This module can be added to the Stacks tab via New Stack > Audio > Audio Playback PWM (rm_audio_playback_pwm).

ConfigurationOptionsDefaultDescription
General
NameName must be a valid C symbolg_rm_audio_playback0 Module name.
Playback Speed (Hz)Must be an integer and greater than 044100 Enter playback sample rate in Hz.
Interrupts
CallbackName must be a valid C symbolg_rm_audio_playback0_callback A user callback function. If this callback function is provided, it is called from the interrupt service routine (ISR) each time the playback completes.
PWM Output Pin
  • Pin A
  • Pin B
Pin A Select which timer output pin should be used for audio output.

Clock Configuration

The Audio Playback with PWM module does not require a specific clock configuration.

Pin Configuration

Configure the PWM output pins for selected PWM HAL layer peripheral (AGT/GPT). One of the following pins needs to be selected and enabled as PWM output for selected channel n,

If GPT is used as PWM interface,

If AGT is used as PWM interface,

Usage Notes

DMAC/DTC Integration

DMAC/DTC is used as a lower level transfer instance with this module and is operated in Normal mode to transfer 16 bit or 32 bit data from the audio stream buffer to the PWM peripheral AGT or GPT respectively. Destination address for transfer instance needs to be the Duty Cycle setting register GTCCR for GPT as PWM driver or AGTMA/AGTCMB in case of AGT as PWM driver. The Audio Playback with PWM module internally configures 'Transfer Size' as 2 Bytes if AGT is used for PWM generation, otherwise it configures 'Transfer Size" as 4 Bytes if GPT or AGTW is used for PWM generation. Refer the hardware manual to check whether the MCU supports AGT or the AGTW peripheral.

Examples

Basic Example

This is a basic example of minimal use of the RM_AUDIO_PLAYBACK_PWM in an application. This example shows how this driver can be used for playing a 16 bit uncompressed PCM audio from a single input buffer.

int16_t play_buffer[AUDIO_EXAMPLE_LENGTH];
uint32_t g_audio_callback_counter = 0;
void g_audio_example_counter_callback (audio_playback_callback_args_t * p_args)
{
{
g_audio_callback_counter++;
}
}
void basic_example (void)
{
fsp_err_t err;
/* Initialize the Audio Playback module for playing an audio stream. */
err = RM_AUDIO_PLAYBACK_PWM_Open(&g_audio_playback_pwm_ctrl, &g_audio_playback_pwm_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Set the 16 Bit PCM audio stream to play next */
err = RM_AUDIO_PLAYBACK_PWM_Play(&g_audio_playback_pwm_ctrl, play_buffer, AUDIO_EXAMPLE_LENGTH);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Start to the play the selected audio stream*/
err = RM_AUDIO_PLAYBACK_PWM_Start(&g_audio_playback_pwm_ctrl);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Wait till the playback is completed */
while (g_audio_callback_counter == 0)
{
;
}
/* Stop playing. */
err = RM_AUDIO_PLAYBACK_PWM_Stop(&g_audio_playback_pwm_ctrl);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
}

Streaming Example

This is an example of using Audio Playback module to play audio stream. This application uses a double buffer to store PCM sine wave data. It starts playing in the main loop, then loads the next buffer if it is ready in the callback. If the next buffer is not ready, a flag is set in the callback so the application knows to restart playing in the main loop. This example also demonstrates conversion of signed PCM format data to unsigned PWM format data along with scaling the data samples for optimum PWM wave generation.

#define AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_AUDIO_SAMPLING_FREQUENCY_HZ (22050U)
#define AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_PERIOD_VALUE_AT_22050HZ (0x11B7U)
#define AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_SAMPLES_PER_CHUNK (1024U)
#define AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_TONE_FREQUENCY_HZ (800U)
#define AUDIO_PLAYBACK_PWM_EXAMPLE_SAMPLES_TO_TRANSFER (1024U)
#define AUDIO_PLAYBACK_PWM_EXAMPLE_CONVERT_TO_PWM_SAMPLES (32768U)
#define AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_DATA_BIT_SIZE (16U)
int16_t g_stream_src[2][AUDIO_PLAYBACK_PWM_EXAMPLE_SAMPLES_TO_TRANSFER];
q15_t g_pwm_sample[2][AUDIO_PLAYBACK_PWM_EXAMPLE_SAMPLES_TO_TRANSFER];
q15_t g_pwm_scaled_sample[2][AUDIO_PLAYBACK_PWM_EXAMPLE_SAMPLES_TO_TRANSFER];
uint32_t g_buffer_index = 0;
volatile bool g_send_data_in_main_loop = true;
volatile bool g_data_ready = false;
/* Example callback called when Audio Playback is ready for more data. */
void rm_audio_playback_example_callback (audio_playback_callback_args_t * p_args)
{
/* Start playing next stream if data is ready. */
{
if (g_data_ready)
{
/* Reload data and handle errors. */
rm_audio_playback_example_play();
}
else
{
/* Data was not ready yet, send it in the main loop. */
g_send_data_in_main_loop = true;
}
}
}
/* Load the next stream and check for error condition. */
void rm_audio_playback_example_play (void)
{
/* Set the playback stream */
fsp_err_t err;
err =
RM_AUDIO_PLAYBACK_PWM_Play(&g_audio_playback_pwm_ctrl, (int16_t *) &g_pwm_scaled_sample[g_buffer_index][0],
(AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_SAMPLES_PER_CHUNK * sizeof(int16_t)));
if (FSP_SUCCESS == err)
{
/* Switch the buffer after data is sent. */
g_buffer_index = !g_buffer_index;
/* Allow loop to calculate next buffer. */
g_data_ready = false;
}
else
{
/* The
* application must wait until the audio playback is completed. In this example, the
* callback sets data or resets the flag g_send_data_in_main_loop. */
}
}
/* Calculate samples. This example is just a sine wave. For this type of data, it would be better to calculate
* one period and loop it. This example should be updated for the audio data used by the application. */
void rm_audio_playback_example_calculate_samples (uint32_t buffer_index)
{
static uint32_t t = 0U;
/* Create a sine wave. Using formula sample = sin(2 * pi * tone_frequency * t / sampling_frequency) */
uint32_t freq = AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_TONE_FREQUENCY_HZ;
for (uint32_t i = 0; i < AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_SAMPLES_PER_CHUNK; i += 1)
{
float input = (((float) (freq * t)) * (float) M_TWOPI) /
AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_AUDIO_SAMPLING_FREQUENCY_HZ;
t++;
/* Store sample. */
int16_t sample = (int16_t) ((INT16_MAX * sinf(input)));
g_stream_src[buffer_index][i] = sample;
}
/* Convert signed PCM data to unsigned PCM data as PWM needs unsigned input. */
arm_offset_q15(&g_stream_src[buffer_index][0],
(q15_t) (INT16_MAX + 1),
&g_pwm_sample[buffer_index][0],
AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_SAMPLES_PER_CHUNK);
/* Scale the data by the selected period for the timer (calculated for equivalent playback rate) */
arm_scale_q15(&g_pwm_sample[buffer_index][0],
AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_PERIOD_VALUE_AT_22050HZ,
AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_DATA_BIT_SIZE,
&g_pwm_scaled_sample[buffer_index][0],
AUDIO_PLAYBACK_PWM_STREAMING_EXAMPLE_SAMPLES_PER_CHUNK);
/* Data is ready to be sent in the interrupt. */
g_data_ready = true;
}
void rm_audio_playback_streaming_example (void)
{
fsp_err_t err = FSP_SUCCESS;
/* Initialize the module.
* Configure the following pins in the pin configurator for PWM output:
* - If the GPT timer is used for generation of PWM waves configure GTIOCAn or GTIOCBn pin and enable the output
* to these pins through the GPT module properties for desired channel n.
* - Otherwise, if AGT is used for generation of PWM waves configure AGTOAn or AGTOBn pin and enable the output to
* to these pins through the AGT module properties for desired channel n.
* Configure the DMAC/DTC destination address as following:
* - If the GPT timer is used for generation of PWM waves, configure DMAC/DTC destination address to the address of
* GTCCRC register (&R_GPTn->GTCCR[2]) if PWM output pin is GTIOCA otherwise configure to the address of GTCCRD
* register (&R_GPTn->GTCCR[3]) if PWM output pin is GTIOCB for desired GPT channel n.
* - If the AGT timer is used for generation of PWM waves, configure DMAC/DTC destination address as the address of
* AGTCMA register (&R_AGTn->AGTCMA) if PWM output pin is AGTOA otherwise the address of AGTCMB register
* (&R_AGTn->AGTCMB) if the PWM output pin is AGTOB for desired AGT channel n.
* Configure the DMAC/DTC transfer size as 4 Bytes if PWM interface is GPT timer otherwise configure transfer size as 2 Bytes if
* PWM interface is AGT timer. */
err = RM_AUDIO_PLAYBACK_PWM_Open(&g_audio_playback_pwm_ctrl, &g_audio_playback_pwm_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Start timer and transfer modules. */
err = RM_AUDIO_PLAYBACK_PWM_Start(&g_audio_playback_pwm_ctrl);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
while (true)
{
/* Prepare data in a buffer that is not currently used for transmission. */
rm_audio_playback_example_calculate_samples(g_buffer_index);
/* Send data in main loop the first time, and if it was not ready in the interrupt. */
if (g_send_data_in_main_loop)
{
/* Clear flag. */
g_send_data_in_main_loop = false;
/* Reload data and handle errors. */
rm_audio_playback_example_play();
}
/* If the next buffer is ready, wait for the data to be sent in the interrupt. */
while (g_data_ready)
{
/* Do nothing. */
}
}
}

Data Structures

struct  audio_playback_pwm_instance_ctrl_t
 

Data Structure Documentation

◆ audio_playback_pwm_instance_ctrl_t

struct audio_playback_pwm_instance_ctrl_t

AUDIO_PLAYBACK_PWM instance control block. DO NOT MODIFY. Initialization occurs when RM_AUDIO_PLAYBACK_PWM_Open() is called.

Data Fields

void(* p_callback )(audio_playback_callback_args_t *p_args)
 
void * p_context
 
audio_playback_cfg_t const * p_cfg
 Pointer to the configuration structure.
 
uint32_t open
 Used by driver to check if the control structure is valid.
 
timer_instance_t const * p_lower_lvl_timer
 Timer API used to generate sampling frequency and GPT/AGT API used to access PWM hardware.
 
transfer_instance_t const * p_lower_lvl_transfer
 Transfer API used to transfer data each sampling frequency.
 

Field Documentation

◆ p_callback

void(* audio_playback_pwm_instance_ctrl_t::p_callback) (audio_playback_callback_args_t *p_args)

Callback called when play is complete.

◆ p_context

void* audio_playback_pwm_instance_ctrl_t::p_context

Placeholder for user data. Passed to the user callback in audio_playback_callback_args_t.

Function Documentation

◆ RM_AUDIO_PLAYBACK_PWM_Open()

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Open ( audio_playback_ctrl_t *const  p_api_ctrl,
audio_playback_cfg_t const *const  p_cfg 
)

Opens and configures the Audio Playback with PWM driver. Sets playback speed and transfer rate to read the audio buffer.

Example:

/* Initialize the Audio Playback module for playing an audio stream. */
err = RM_AUDIO_PLAYBACK_PWM_Open(&g_audio_playback_pwm_ctrl, &g_audio_playback_pwm_cfg);
Return values
FSP_SUCCESSAudio Playback module successfully configured.
FSP_ERR_ALREADY_OPENModule already open.
FSP_ERR_ASSERTIONOne or more pointers point to NULL or callback is NULL.

◆ RM_AUDIO_PLAYBACK_PWM_Close()

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Close ( audio_playback_ctrl_t *const  p_api_ctrl)

Closes the module driver. Enables module stop mode.

Return values
FSP_SUCCESSModule successfully closed.
FSP_ERR_NOT_OPENDriver not open.
FSP_ERR_ASSERTIONPointer pointing to NULL.
Note
This function will close all the lower level HAL drivers as well.

◆ RM_AUDIO_PLAYBACK_PWM_Start()

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Start ( audio_playback_ctrl_t *const  p_api_ctrl)

Start the PWM HAL driver (AGT or GPT) and timer HAL (AGT or GPT) drivers.

  • Example:
    /* Start to the play the selected audio stream*/
    err = RM_AUDIO_PLAYBACK_PWM_Start(&g_audio_playback_pwm_ctrl);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    Return values
    FSP_SUCCESSAudio playback hardware started successfully.
    FSP_ERR_ASSERTIONThe parameter p_ctrl is NULL.
    FSP_ERR_NOT_OPENDriver not open. This function calls

◆ RM_AUDIO_PLAYBACK_PWM_Stop()

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Stop ( audio_playback_ctrl_t *const  p_api_ctrl)

Stop the PWM HAL driver (AGT or GPT) and timer HAL driver (AGT or GPT).

  • Example:
    /* Stop playing. */
    err = RM_AUDIO_PLAYBACK_PWM_Stop(&g_audio_playback_pwm_ctrl);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    Return values
    FSP_SUCCESSAudio playback hardware stopped successfully.
    FSP_ERR_ASSERTIONThe parameter p_ctrl is NULL.
    FSP_ERR_NOT_OPENDriver not open. This function calls

◆ RM_AUDIO_PLAYBACK_PWM_Play()

fsp_err_t RM_AUDIO_PLAYBACK_PWM_Play ( audio_playback_ctrl_t *const  p_api_ctrl,
void const *const  p_buffer,
uint32_t  length 
)

Play a single audio buffer by input samples to the PWM HAL (AGT or GPT) at the sampling frequency configured by the timer.

  • Example:
    /* Set the 16 Bit PCM audio stream to play next */
    err = RM_AUDIO_PLAYBACK_PWM_Play(&g_audio_playback_pwm_ctrl, play_buffer, AUDIO_EXAMPLE_LENGTH);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    Return values
    FSP_SUCCESSBuffer playback began successfully.
    FSP_ERR_ASSERTIONThe parameter p_ctrl or p_buffer is NULL or buffer length is greater than 0x10000.
    FSP_ERR_NOT_OPENDriver not open.. This function calls