| /* | |
| ** 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] ); | |
| } | |
| } | |