blob: 2596688bec870706a650cbab0f8872d352834e71 [file] [log] [blame]
/*
** Copyright (c) 2015-2017 by Silicon Laboratories
**
** $Id: demo_common.c 6365 2017-04-06 22:18:56Z nizajerk $
**
** Distributed by:
** Silicon Laboratories, Inc
**
** This file contains proprietary information.
** No dissemination allowed without prior written permission from
** Silicon Laboratories, Inc.
**
** File Description:
** Various utility functions that are common for the ProSLIC API demos...
**
**
*/
#include "demo_common.h"
#include "user_intf.h"
#include "si_voice_datatypes.h"
#include "api_demo.h"
////#include DEMO_INCLUDE
/* If the header files are NOT defined, this is the fall back limit */
#define SI_DEMO_MAX_ENUM_DEFAULT 32
#ifdef FXS_CONSTANTS_HDR
#include FXS_CONSTANTS_HDR /* See makefile for how this is determined... */
#endif
#ifdef DAA_CONSTANTS_HDR
#include DAA_CONSTANTS_HDR /* See makefile for how this is determined... */
#endif
#ifdef SI3217X
#include "si3217x.h"
#include "vdaa.h"
extern Si3217x_General_Cfg Si3217x_General_Configuration;
#endif
#ifdef SI3226X
#include "si3226x.h"
#endif
#ifdef SI3218X
#include "si3218x.h"
#endif
#ifdef SI3219X
#include "si3219x.h"
#endif
#ifdef SI3228X
#include "si3228x.h"
#endif
#ifdef VDAA_SUPPORT
#include "vdaa.h"
#endif
#ifdef TSTIN_SUPPORT
#include "proslic_tstin_limits.h"
#endif
/*****************************************************************************************************/
#ifdef PERL
#ifndef NOFXS_SUPPORT
extern const char *Ring_preset_options[];
extern const char *DcFeed_preset_options[];
extern const char *Impedance_preset_options[];
extern const char *FSK_preset_options[];
extern const char *PulseMeter_preset_options[];
extern const char *Tone_preset_options[];
extern const char *PCM_preset_options[];
#endif
#ifdef VDAA_SUPPORT
extern const char *Vdaa_country_preset_options[];
extern const char *Vdaa_audioGain_preset_options[];
extern const char *Vdaa_ringDetect_preset_options[];
extern const char *Vdaa_PCM_preset_options[];
extern const char *Vdaa_hybrid_preset_options[];
#endif
#endif /* PERL */
extern int modem_is_wb, modem_is_master;
/*****************************************************************************************************/
#ifndef LOGPRINT_PREFIX
#define LOGPRINT_PREFIX "ProSLIC_DEMO: "
#endif
/*****************************************************************************************************/
/* This is a simple initialization - all ports have the same device type. For a more complex
* system, a customer could key off of port_id and depending on value, fill in the "correct" setting
* for their system. No memory allocation is done here.
*/
#ifndef SIVOICE_USE_CUSTOM_PORT_INFO
void demo_init_port_info(demo_port_t *port, unsigned int port_id)
{
SILABS_UNREFERENCED_PARAMETER(port_id);
#ifdef SI3217X
port->deviceType = SI3217X_TYPE;
port->numberOfDevice = SI3217XB_NUMBER_OF_DEVICE;
port->numberOfChan = SI3217XB_NUMBER_OF_CHAN;
port->chanPerDevice = SI3217X_CHAN_PER_DEVICE;
#endif
#ifdef SI3226X
port->deviceType = SI3226X_TYPE;
port->numberOfDevice = SI3226X_NUMBER_OF_DEVICE;
port->numberOfChan = SI3226X_NUMBER_OF_CHAN;
port->chanPerDevice =SI3226X_CHAN_PER_DEVICE;
#endif
#ifdef SI3218X
port->deviceType = SI3218X_TYPE;
port->numberOfDevice = SI3218X_NUMBER_OF_DEVICE;
port->numberOfChan = SI3218X_NUMBER_OF_CHAN;
port->chanPerDevice = SI3218X_CHAN_PER_DEVICE;
#endif
#ifdef SI3219X
port->deviceType = SI3219X_TYPE;
port->numberOfDevice = SI3219X_NUMBER_OF_DEVICE;
port->numberOfChan = SI3219X_NUMBER_OF_CHAN;
port->chanPerDevice = SI3219X_CHAN_PER_DEVICE;
#endif
#ifdef SI3228X
port->deviceType = SI3228X_TYPE;
port->numberOfDevice = SI3228X_NUMBER_OF_DEVICE;
port->numberOfChan = SI3228X_NUMBER_OF_CHAN;
port->chanPerDevice = SI3228X_CHAN_PER_DEVICE;
#endif
#ifdef SI3050_CHIPSET
port->deviceType = SI3050_TYPE;
port->numberOfDevice = SI3050_NUMBER_OF_DEVICE;
port->numberOfChan = SI3050_NUMBER_OF_CHAN;
port->chanPerDevice = SI3050_CHAN_PER_DEVICE;
#endif
}
#endif /* SIVOICE_USE_CUSTOM_PORT_INFO */
/*****************************************************************************************************/
int demo_alloc(demo_port_t *port, int *base_channel_index,
controlInterfaceType *proslic_api_hwIf)
{
int i;
LOGPRINT("%sAllocating memory\n", LOGPRINT_PREFIX);
/* First allocate all the needed data structures for ProSLIC API */
if( SiVoice_createDevices(&(port->devices),
(uInt32)(port->numberOfDevice)) != RC_NONE )
{
return RC_NO_MEM;
}
if( SiVoice_createChannels(&(port->channels),
(uInt32)port->numberOfChan) != RC_NONE )
{
goto free_mem;
}
/* Demo specific code */
port->channelPtrs = SIVOICE_CALLOC(sizeof(SiVoiceChanType_ptr),
port->numberOfChan);
port->demo_info = SIVOICE_CALLOC(sizeof(demo_chan_info_t),
port->numberOfChan);
if( (port->channelPtrs == NULL) || (port->demo_info == NULL) )
{
goto free_mem;
}
/* Back to API init code */
#ifdef TSTIN_SUPPORT
LOGPRINT("%sCreating Inward Test Objs...\n", LOGPRINT_PREFIX);
if( ProSLIC_createTestInObjs(&(port->pTstin),
(uInt32)(port->numberOfChan) != RC_NONE) )
{
goto free_mem;
}
#endif
for(i = 0; i < port->numberOfChan; i++)
{
/* If supporting more than 1 SPI interface, a code change is needed here - channel count may not match
* and the pointer to the api_hwIf may change for the SPI object... */
if(SiVoice_SWInitChan(&(port->channels[i]),
(i + port->channelBaseIndex), port->deviceType,
&(port->devices[i/port->chanPerDevice]), proslic_api_hwIf ) != RC_NONE)
{
goto free_mem;
}
port->channelPtrs[i] = &(port->channels[i]); /* Demo specific */
#ifdef TSTIN_SUPPORT
LOGPRINT("%sConfiguring Inward Tests...\n", LOGPRINT_PREFIX);
ProSLIC_testInPcmLpbkSetup(port->pTstin, &ProSLIC_testIn_PcmLpbk_Test);
ProSLIC_testInDcFeedSetup(port->pTstin, &ProSLIC_testIn_DcFeed_Test);
ProSLIC_testInRingingSetup(port->pTstin, &ProSLIC_testIn_Ringing_Test);
ProSLIC_testInBatterySetup(port->pTstin, &ProSLIC_testIn_Battery_Test);
ProSLIC_testInAudioSetup(port->pTstin, &ProSLIC_testIn_Audio_Test);
#endif
SiVoice_setSWDebugMode(&(port->channels[i]),
TRUE); /* Enable debug mode for all channels */
#ifdef ENABLE_INITIAL_LOGGING
SiVoice_setTraceMode(&(port->channels[i]),
TRUE); /* Enable trace mode for all channels */
#endif
}
/* Demo specific code */
port->channelBaseIndex = *base_channel_index;
(*base_channel_index) += port->numberOfChan;
return RC_NONE;
free_mem:
demo_free(port);
return RC_NO_MEM;
}
/*****************************************************************************************************/
int demo_init_devices(demo_port_t *port)
{
int rc=0;
#ifndef NOFXS_SUPPORT
LOGPRINT("%sInitializing ProSLIC...\n", LOGPRINT_PREFIX);
if(ProSLIC_Init(port->channelPtrs, port->numberOfChan) != RC_NONE)
{
LOGPRINT("%s ERROR: ProSLIC_Init() failed\n", LOGPRINT_PREFIX);
return(-1);
}
#endif
#ifdef VDAA_SUPPORT
if( (port->deviceType == SI3050_TYPE)
#if defined(SI3217X)
/* Si32178/9 Rev B only supports VDAA */
||( (Si3217x_General_Configuration.daa_cntl != 0)
&& (port->deviceType == SI3217X_TYPE)
&& (port->channels->deviceId->chipRev == 1) )
#endif /* 17x */
)
{
LOGPRINT("%sInitializing FXO...\n", LOGPRINT_PREFIX);
/* Initialize any DAA channels that are present */
if (Vdaa_Init(port->channelPtrs, port->numberOfChan))
{
LOGPRINT("\n%s ERROR : DAA Initialization Failed\n", LOGPRINT_PREFIX);
return(-1);
}
}
#endif
#ifndef SKIP_LBCAL
/*
** Longitudinal Balance Calibration
**
*/
LOGPRINT("%sStarting Longitudinal Balance Calibration...\n", LOGPRINT_PREFIX);
rc = ProSLIC_LBCal(port->channelPtrs, port->numberOfChan);
if(rc != RC_NONE)
{
LOGPRINT("\n%sLB CAL ERROR : %d\n", LOGPRINT_PREFIX, rc);
}
#endif
return rc;
}
/*****************************************************************************************************/
int demo_load_presets(demo_port_t *port)
{
int i;
SiVoiceChanType_ptr chanPtr;
LOGPRINT("%sLoading presets...\n",LOGPRINT_PREFIX);
for(i = 0; i < port->numberOfChan; i++)
{
chanPtr = port->channelPtrs[i];
#ifndef NOFXS_SUPPORT
/* We assume the 1st constants setting is the default one... */
ProSLIC_DCFeedSetup(chanPtr, 0);
ProSLIC_RingSetup(chanPtr, 0);
ProSLIC_ZsynthSetup(chanPtr, 0);
if (modem_is_wb)
ProSLIC_PCMSetup(chanPtr, PCM_16LIN_WB);
else
ProSLIC_PCMSetup(chanPtr, PCM_16LIN);
ProSLIC_PCMTimeSlotSetup(chanPtr, 1, 1); //1826 MSA use 1 bit offset for both Rx & Tx PCM data
#endif
#ifdef VDAA_SUPPORT
Vdaa_CountrySetup(chanPtr, 0);
Vdaa_HybridSetup(chanPtr, 0);
Vdaa_PCMSetup(chanPtr, 0);
#endif
}
return 0;
}
/*****************************************************************************************************/
int demo_set_chan_state(demo_port_t *port)
{
int i;
#ifndef NOFXS_SUPPORT
int j;
#endif
SiVoiceChanType_ptr chanPtr;
for(i = 0; i < port->numberOfChan; i++)
{
chanPtr = port->channelPtrs[i];
#ifndef NOFXS_SUPPORT
ProSLIC_SetLinefeedStatus(chanPtr, LF_FWD_ACTIVE);
ProSLIC_EnableInterrupts(chanPtr);
/* Cache IRQEN settings for the demo */
for(j = PROSLIC_REG_IRQEN1; j < PROSLIC_REG_IRQEN4; j++)
{
port->demo_info[i].irq_save[j-PROSLIC_REG_IRQEN1] =
SiVoice_ReadReg(chanPtr, j);
}
#endif
#ifdef VDAA_SUPPORT
Vdaa_SetHookStatus(chanPtr, VDAA_ONHOOK);
#endif
}
return 0;
}
/*****************************************************************************************************/
void demo_shutdown(demo_port_t *port)
{
#ifdef NOFXS_SUPPORT
SILABS_UNREFERENCED_PARAMETER(port);
#else
int i;
SiVoiceChanType_ptr chanPtr;
for(i = 0; i < port->numberOfChan; i++)
{
chanPtr = port->channelPtrs[i];
ProSLIC_ShutdownChannel(chanPtr);
}
#endif
}
/*****************************************************************************************************/
void demo_free(demo_port_t *port)
{
#ifdef TSTIN_SUPPORT
ProSLIC_destroyTestInObjs(&(port->pTstin));
#endif
if(port->demo_info != NULL)
{
SIVOICE_FREE(port->demo_info);
}
SiVoice_destroyChannels( &(port->channels) );
SiVoice_destroyDevices( &(port->devices) );
if(port->channelPtrs != NULL)
{
SIVOICE_FREE(port->channelPtrs);
}
}
/*****************************************************************************************************/
int demo_get_preset(demo_preset_t preset_enum)
{
int max_value, user_input;
const char *preset_string[] =
{
"Ringing",
"DC Feed",
"Zsynth",
"FSK",
"Pulse Metering",
"Tone Generation",
"PCM",
"Country",
"Audio Gain",
"Ring Validation",
"PCM",
"Hybrid"
};
#ifdef PERL
const char **menu_items;
#endif
switch(preset_enum)
{
#ifndef NOFXS_SUPPORT
case DEMO_RING_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = RINGING_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Ring_preset_options;
#endif
break;
case DEMO_DCFEED_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = DC_FEED_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = DcFeed_preset_options;
#endif
break;
case DEMO_IMPEDANCE_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = IMPEDANCE_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Impedance_preset_options;
#endif
break;
case DEMO_FSK_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = FSK_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = FSK_preset_options;
#endif
break;
case DEMO_PM_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = PULSE_METERING_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = PulseMeter_preset_options;
#endif
break;
case DEMO_TONEGEN_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = TONE_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Tone_preset_options;
#endif
break;
case DEMO_PCM_PRESET:
#ifdef FXS_CONSTANTS_HDR
max_value = PCM_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = PCM_preset_options;
#endif
break;
#endif /* FXS selection */
#ifdef VDAA_SUPPORT
case DEMO_VDAA_COUNTRY_PRESET:
#ifdef DAA_CONSTANTS_HDR
max_value = VDAA_COUNTRY_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Vdaa_country_preset_options;
#endif
break;
case DEMO_VDAA_AUDIO_GAIN_PRESET:
#ifdef DAA_CONSTANTS_HDR
max_value = VDAA_AUDIO_GAIN_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Vdaa_audioGain_preset_options;
#endif
break;
case DEMO_VDAA_RING_VALIDATION_PRESET:
#ifdef DAA_CONSTANTS_HDR
max_value = VDAA_RING_VALIDATION_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Vdaa_ringDetect_preset_options;
#endif
break;
case DEMO_VDAA_PCM_PRESET:
#ifdef DAA_CONSTANTS_HDR
max_value = VDAA_PCM_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Vdaa_PCM_preset_options;
#endif
break;
case DEMO_VDAA_HYBRID_PRESET:
#ifdef DAA_CONSTANTS_HDR
max_value = VDAA_HYBRID_LAST_ENUM-1;
#else
max_value = SI_DEMO_MAX_ENUM_DEFAULT;
#endif
#ifdef PERL
menu_items = Vdaa_hybrid_preset_options;
#endif
break;
#endif /* VDAA */
default:
return -1; /* We shouldn't hit this line... but just in case... */
} /* switch(preset_enum) */
#ifndef PERL
do
{
printf("Enter %s preset (0-%d) %s", preset_string[preset_enum], max_value,
PROSLIC_PROMPT);
user_input = get_int(0, max_value);
}
while( user_input >= max_value);
#else
do
{
display_menu(preset_string[preset_enum], menu_items);
printf("Select Menu item (0-%d) %s ", max_value, PROSLIC_PROMPT);
user_input = get_int( 0, max_value) ;
}
while(user_input > max_value);
#endif
return user_input;
}
/*****************************************************************************************************/
SiVoiceChanType_ptr demo_get_cptr(demo_state_t *pState, int channel_number)
{
int i;
if(channel_number >= pState->totalChannelCount)
{
return NULL;
}
/* Determine which port we're on */
for(i = 0; channel_number < pState->ports[i].channelBaseIndex; i++)
{
}
return pState->ports[i].channelPtrs[(channel_number - pState->ports[i].channelBaseIndex)];
}
/*****************************************************************************************************/
void demo_save_slic_irqens(demo_state_t *pState)
{
int portIndex = pState->currentChannel - pState->currentPort->channelBaseIndex;
int i;
for(i = PROSLIC_REG_IRQEN1; i < PROSLIC_REG_IRQEN4; i++)
{
pState->currentPort->demo_info[portIndex].irq_save[i-PROSLIC_REG_IRQEN1] =
SiVoice_ReadReg(pState->currentChanPtr, i);
}
}
/*****************************************************************************************************/
void demo_restore_slic_irqens(demo_state_t *pState)
{
int portIndex = pState->currentChannel - pState->currentPort->channelBaseIndex;
int i;
for(i = PROSLIC_REG_IRQEN1; i < PROSLIC_REG_IRQEN4; i++)
{
SiVoice_WriteReg(pState->currentChanPtr, i,
pState->currentPort->demo_info[portIndex].irq_save[i-PROSLIC_REG_IRQEN1] );
}
}