NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
Template:RemoTI-1.4.0-AdvancedRemote-Voice
Contents
Detailed guide to add Voice support for the Advanced Remote project[edit]
This section describes all steps required to add the Voice remote functionality to RemoTI-1.4.0. There are several aspects and gotchas to consider. Each code snippet that is added comes with a brief comment of why it is added.
Project options update[edit]
- Add
$PROJ_DIR$\..\..\..\..\COMPONENTS\audio\include
to the include paths - Add to the pre-compiler options the following two defines
- We need to link with the audio library, in addition to the network library. Instead of adding the path to the compile options, we add a folder in the project, and then place both libraries there.
- Uncheck the box which includes command line arguments for the linker. This is required since we add the library to the project in a new folder.
- We also need to add
hal_codec.c
to drive the codec - To improve throughput and processing time we need to use compiler optimization settings for speed
|
![]() |
Source files update[edit]
Application[edit]
In the main application code, rsa_point.c
- Include headers
- Add stream event to the event list
- Add stream state to the state enum
- Add action define for audio and "push-to-talk". These defines serve as function pointer table index in the array
rsaAppKeyActions
. We simply subtract 0xB0 to use them as index. - Add action in key map, so that an action is associated with a button on the remote.
- Add functions to handle key press, and callback from audio library
- Add audio key action functions to function array.
- Add state variable to track audio state
- Initialize audio state when application initializes
- Add STOP_STREAM event handling
- We need all processing that has to do with audio to happen fast. So we use local compile optimization pragmas. Note that this is redundant when we can afford to use speed optimization globally, however it is required when we have to select parts of the code to optimize for speed. When streaming audio we route the send data confirmation to the audio library. Following are the updates required in the
RTI_SendDataCnf()
- Add function to process callback from audio library
- Add function to start/stop audio stream
#include "hal_codec.h"
#include "ras_lib.h"
// RSA Events
#define RSA_EVT_INIT 0x0001
...
#ifdef RAS_LIB
#define RSA_EVT_STOP_STREAM 0x0100
#endif
// RSA States
enum
{
...
RSA_STATE_POLLING,
#ifdef RAS_LIB
RSA_STATE_STREAM,
#endif
};
#define RSA_ACT_TOGGLE_POLL 0xB8
#if (defined RAS_LIB)
#define RSA_ACT_AUDIO 0xB9
#define RSA_ACT_PUSH_TO_TALK 0xBA
#endif //RAS_LIB
#define RSA_ACT_APP_END 0xBA
...
{ RSA_ACT_XMIT, RTI_CERC_RECORD, HID_NONE }, // 0b00 00 1000 - REC
{ RSA_ACT_XMIT, RTI_CERC_NUM_1, HID_KEYBOARD_1 }, // 0b00 00 1001 - 1
#if (defined RAS_LIB)
{ RSA_ACT_AUDIO, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 00 1010 - AV
#else
{ RSA_ACT_KEY_EX, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 00 1010 - AV
#endif //RAS_LIB
{ RSA_ACT_PAIR, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 00 1100 - RED (K1)
...
{ RSA_ACT_UNPAIR, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 01 1011 - YELLOW (K3)
#if (defined RAS_LIB)
{ RSA_PUSH_TO_TALK, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 01 1100 - GREEN (K2)
#else
{ RSA_ACT_TEST_MODE, RTI_CERC_RESERVED_1, HID_NONE }, // 0b00 01 1100 - GREEN (K2)
#endif
{ RSA_ACT_XMIT, RTI_CERC_NUM_8, HID_KEYBOARD_8 }, // 0b00 01 1101 - 8
...
#if (defined RAS_LIB)
static void rsaAudioKeyAction( rsaKeyState_t keyState );
static void rsaPushToTalkKeyAction( rsaKeyState_t keyState );
static void rsaAudioToggle(void);
void RSA_StreamStopped( uint8 status);
#endif //RAS_LIB
const rsaAppActionFn_t rsaAppKeyActions[] =
{
...
rsaTogglePollAction,
#if (defined RAS_LIB)
rsaAudioKeyAction,
rsaPushToTalkKeyAction
#endif //RAS_LIB
#ifdef RAS_LIB
static uint8 rsaAudioState;
#endif //RAS_LIB
void RSA_Init( uint8 taskId )
{
...
#ifdef RAS_LIB
rsaAudioState = RSA_STATE_READY;
#endif //RAS_LIB
uint16 RSA_ProcessEvent( uint8 taskId, uint16 events )
{
...
#ifdef RAS_LIB
if (events & RSA_EVT_STOP_STREAM)
{
if ( (rsaState == RSA_STATE_STREAM) )
{
//Rest the codec to put it in Power down mode
Hal_codecReset();
//Stop the MCLK
Hal_codecMclockStop();
RAS_Stop(); //==> Lib will call the stop confirmation callback
//Technically, it s not ready, a packet might be pending in the queue...
//Wait for the callback before chaning state
//rsaState = RSA_STATE_READY;
}
return events ^ RSA_EVT_STOP_STREAM;
}
#endif
#ifdef RAS_LIB
#pragma optimize=speed
#endif
void RTI_SendDataCnf( rStatus_t status )
{
#ifdef RAS_LIB
if( (rsaState == RSA_STATE_STREAM))
{
RAS_SendDataCnf(status);
}
#endif
#if (defined RAS_LIB)
void RSA_StreamStopped( uint8 status)
{
rsaState = RSA_STATE_READY;
if(status == 0)
{
#if (defined HAL_BUZZER) && (HAL_BUZZER == TRUE)
/* Tell OSAL to not go to sleep because buzzer uses T3 */
osal_pwrmgr_task_state( RSA_TaskId, PWRMGR_HOLD );
RSA_PlayTune( RSA_TUNE_END ); // ring buzzer to signal end
#endif
}
else
{
//Status fail, stop the clock...
Hal_codecReset();
//Stop the MCLK
Hal_codecMclockStop();
#if (defined HAL_BUZZER) && (HAL_BUZZER == TRUE)
/* Tell OSAL to not go to sleep because buzzer uses T3 */
osal_pwrmgr_task_state( RSA_TaskId, PWRMGR_HOLD );
RSA_PlayTune( RSA_TUNE_ERROR ); // ring buzzer to signal end error
#endif
}
rsaAudioState = RSA_STATE_READY;
}
#endif // RAS_LIB
#if (defined RAS_LIB)
uint8 globalRsaCalledRAS_Start = FALSE;
static void rsaAudioToggle(void)
{
if( rsaDestIndex != RTI_INVALID_PAIRING_REF)
{
{
if(rsaState == RSA_STATE_STREAM)
{
if (rsaAudioState == RSA_STATE_STREAM)
{
//Rest the codec to put it in Power down mode
Hal_codecReset();
//Stop the MCLK
Hal_codecMclockStop();
RAS_Stop(); //==> Lib will call the stop confirmation callback
//Technically, it s not ready, a packet might be pending in the queue...
//Wait for the callback before changing state
//rsaState = RSA_STATE_READY;
}
}
else if (rsaState == RSA_STATE_READY)
{
if (rsaAudioState == RSA_STATE_READY)
{
rasCfg_t rasAudioCfg;
rsaState = RSA_STATE_STREAM;
//First start the MCLK and reset the codec.
Hal_codecMclockStart(4000);
Hal_codecReset();
//Configure the codec
#ifdef CC2533F96_VRC_REVB
Hal_codecInit16kHz_ADC3101_mic_vrc_diff();
#else
Hal_codecInit16kHz_ADC3101_mic_vrc();
#endif
//Hal_codecInit16kHz_ADC3101_lineIn_vrc();
//Initialize the Audio Configuration Structure.
rasAudioCfg.fs = 16;
rasAudioCfg.nbBits = 16;
rasAudioCfg.format = 1;
rasAudioCfg.ras_StreamStopped = RSA_StreamStopped;
rsaAudioState = RSA_STATE_STREAM;
globalRsaCalledRAS_Start = TRUE;
RAS_Start( rsaDestIndex , rasAudioCfg);
globalRsaCalledRAS_Start = FALSE;
//If the audio needs to run for a specific duration, set a timeout now.
//if (rasCfg.duration)
// osal_start_timerEx(RSA_TaskId, RSA_EVT_STOP_AUDIO_CMD,rasCfg.duration*10 );
}
}
}
}
}
#endif // RAS_LIB
OSAL[edit]
In the OSAL setup code, rsa_osal.c
perform the following steps
- Include header
- Add
RAS_ProcessEvent
function to the task processing functions array. Position in array reflects the priority given to the audio task - Add OSAL init function for audio task. Again, order is not random, but reflects task priority
#include "ras_lib.h"
const pTaskEventHandlerFn tasksArr[] =
{
macEventLoop,
RCN_ProcessEvent,
RTI_ProcessEvent,
#ifdef RAS_LIB
RAS_ProcessEvent,
#endif //RAS_LIB
gdpOriginator_ProcessEvent,
RSA_ProcessEvent,
Hal_ProcessEvent
};
void osalInitTasks( void )
{
...
RTI_Init( taskID++ );
#ifdef RAS_LIB
RAS_Init( taskID++ );
#endif //RAS_LIB
gdpOriginator_Init( taskID++ );
Driver[edit]
In the main file, rsa_main.c
, add hardware initialization steps required for the codec.
- Include header
- Call the codec reset functions
#include "hal_codec.h"
#if (defined RAS_LIB)
Hal_codecResetConfig();
Hal_codecReset();
#endif
In the CODEC driver file hal_codec.c
, set global ticks to 0. The buzzer driver has been updated to use a divided global tick source (8MHz). Before starting the codec we must set it back to an undivided clock.
- While setting up the master clock, set the global tick speed back to undivided.
void Hal_codecMclockStart( uint16 freq )
{
...
/* Configure output pin as peripheral since we're using T4 to generate */
MCLK_SEL |= (uint8)HAL_MCLK_GPIO_PINS;
CLKCONCMD &= (TICKSPD_MASK ^ 0xFF);
T4CTL = divider |
HAL_T4_TIMER_CTL_CLEAR |
opmode;
In the DMA driver file hal_dma.c
, add hooks for the audio library.
- Include header
- Add
RAS_LIB
to precompiler clause to enable DMA interrupt, and to implement interrupt handler - Add call to audio library's DMA interrupt handler
#include "ras_lib.h"
void HalDmaInit( void )
{
...
#if (HAL_UART_DMA || \
((defined HAL_SPI) && (HAL_SPI == TRUE)) || \
(defined RAS_LIB) || \
((defined HAL_IRGEN) && (HAL_IRGEN == TRUE)))
DMAIE = 1;
#endif
}
#if (HAL_UART_DMA || \
((defined HAL_SPI) && (HAL_SPI == TRUE)) || \
(defined RAS_LIB) || \
((defined HAL_IRGEN) && (HAL_IRGEN == TRUE)))
/******************************************************************************
* @fn HalDMAInit
#if (defined RAS_LIB)
if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_RX ) )
{
HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_RX );
RAS_DmaIsr();
}
#endif
In the key scanner driver hal_key.c
update to support voice remote layout
- Voice remote uses P0.7 instead of P1.4 for key scan, so update relevant macros.
- In the initialization routine we no longer have to setup Port 1 since no pins are connected anymore
#ifdef CC2533F96_VRC_REVB
//VRC-RevB use P0.7 for key scan.
#define HAL_KEY_P0_GPIO_PINS ( HAL_KEY_BIT0 | HAL_KEY_BIT1 | HAL_KEY_BIT2 | HAL_KEY_BIT3 | HAL_KEY_BIT4 | HAL_KEY_BIT7)
#else
#define HAL_KEY_P0_GPIO_PINS ( HAL_KEY_BIT0 | HAL_KEY_BIT1 | HAL_KEY_BIT2 | HAL_KEY_BIT3 | HAL_KEY_BIT4)
#endif
...
#ifndef CC2533F96_VRC_REVB
//adv. remote use P1.4 for key scan.
#define HAL_KEY_P1_GPIO_PINS ( HAL_KEY_BIT4 )
#endif
...
#ifdef CC2533F96_VRC_REVB
//VRC-RevB use P0.7 for key scan.
#define HAL_KEY_P0_OUTPUT_PINS ( HAL_KEY_BIT3 | HAL_KEY_BIT4 | HAL_KEY_BIT7)
#else
#define HAL_KEY_P0_OUTPUT_PINS ( HAL_KEY_BIT3 | HAL_KEY_BIT4 )
#endif
...
#ifndef CC2533F96_VRC_REVB
#define HAL_KEY_P1_OUTPUT_PINS ( HAL_KEY_BIT4 )
#endif
...
#ifdef CC2533F96_VRC_REVB
#define HAL_KEY_SHIFT_REGISTER_DATA_PIN P0_7
#else
#define HAL_KEY_SHIFT_REGISTER_DATA_PIN P1_4
#endif
#ifndef CC2533F96_VRC_REVB
P1SEL &= (uint8) ~HAL_KEY_P1_GPIO_PINS;
#endif
...
#ifndef CC2533F96_VRC_REVB
P1DIR |= (uint8) HAL_KEY_P1_OUTPUT_PINS;
#endif
In the accelerometer driver hal_accel.c
update to support voice remote layout
- Voice remote uses P1.3 instead of P1.2 for accelerometer interrupt and no pin to control power to the accelerometer, so update relevant macros.
- Then update initialization code
#ifdef CC2533F96_VRC_REVB
//VRC-Rev B: P1.3 used for Accel interrupt
#define HAL_ACCEL_P1_GPIO_PINS ( BV(3) )
/* These defines indicate the direction of each pin */
#define HAL_ACCEL_P1_INPUT_PINS ( BV(3) )
/* Which pins are used for key interrupts */
#define HAL_ACCEL_P1_INTERRUPT_PINS ( BV(3) )
#else
...
/* Which pins are used for key interrupts */
#define HAL_ACCEL_P1_INTERRUPT_PINS ( BV(2) )
...
#endif
/* Initialize outputs */
#ifdef CC2533F96_VRC_REVB
P1SEL &= (uint8) ~HAL_ACCEL_P1_GPIO_PINS;
P1DIR &= (uint8) ~HAL_ACCEL_P1_INPUT_PINS;
#else
...
P1DIR &= (uint8) ~HAL_ACCEL_P1_INPUT_PINS;
#endif
In the gyro driver hal_gyro.c
update to support voice remote layout
- Voice remote uses P1.2 instead of P1.3 for gyro interrupt, and no pin to control power to the gyro, so update relevant macros.
- ifdef CC2533F96_VRC_REVB
- Update initialization code to not control power pin, which no longer exist
/* The following define which port pins are being used by the gyro */
#define HAL_GYRO_P0_GPIO_PINS ( BV( 5 ) )
#define HAL_GYRO_P1_GPIO_PINS ( BV( 2 ) )
/* These defines indicate the direction of each pin */
#define HAL_GYRO_P0_OUTPUT_PINS ( BV( 5 ) )
#define HAL_GYRO_P1_OUTPUT_PINS ( BV( 2 ) )
/* Defines for each output pin assignment */
#define HAL_GYRO_CLKIN_PIN P0_5
#define HAL_GYRO_INT_PIN P1_2
#else
...
#define HAL_GYRO_INT_PIN P1_3
#endif
#ifndef CC2533F96_VRC_REVB
HAL_GYRO_POWER_PIN = 1;
#endif