diff options
Diffstat (limited to 'software/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c')
-rw-r--r-- | software/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c | 13431 |
1 files changed, 13431 insertions, 0 deletions
diff --git a/software/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c new file mode 100644 index 0000000..b51ebfd --- /dev/null +++ b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c @@ -0,0 +1,13431 @@ +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +File: oct6100_channel.c + + Copyright (c) 2001-2005 Octasic Inc. + +Description: + + This file contains functions used to open, modify and close echo + cancellation channels. + +This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is +free software; you can redistribute it and/or modify it under the terms of +the GNU General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later version. + +The OCT6100 GPL API is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with the OCT6100 GPL API; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +$Octasic_Release: OCT612xAPI-01.00-PR38 $ + +$Octasic_Revision: 449 $ + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + +/***************************** INCLUDE FILES *******************************/ + +#include "octdef.h" + +#include "oct6100api/oct6100_defines.h" +#include "oct6100api/oct6100_errors.h" +#include "oct6100api/oct6100_apiud.h" + +#include "apilib/octapi_llman.h" + +#include "oct6100api/oct6100_tlv_inst.h" +#include "oct6100api/oct6100_chip_open_inst.h" +#include "oct6100api/oct6100_chip_stats_inst.h" +#include "oct6100api/oct6100_interrupts_inst.h" +#include "oct6100api/oct6100_remote_debug_inst.h" +#include "oct6100api/oct6100_debug_inst.h" +#include "oct6100api/oct6100_api_inst.h" +#include "oct6100api/oct6100_mixer_inst.h" +#include "oct6100api/oct6100_tsi_cnct_inst.h" +#include "oct6100api/oct6100_conf_bridge_inst.h" +#include "oct6100api/oct6100_tone_detection_inst.h" +#include "oct6100api/oct6100_phasing_tsst_inst.h" +#include "oct6100api/oct6100_tsst_inst.h" +#include "oct6100api/oct6100_channel_inst.h" + +#include "oct6100api/oct6100_interrupts_pub.h" +#include "oct6100api/oct6100_chip_open_pub.h" +#include "oct6100api/oct6100_tsi_cnct_pub.h" +#include "oct6100api/oct6100_playout_buf_pub.h" +#include "oct6100api/oct6100_phasing_tsst_pub.h" +#include "oct6100api/oct6100_mixer_pub.h" +#include "oct6100api/oct6100_conf_bridge_pub.h" +#include "oct6100api/oct6100_tone_detection_pub.h" +#include "oct6100api/oct6100_channel_pub.h" + +#include "oct6100_chip_open_priv.h" +#include "oct6100_miscellaneous_priv.h" +#include "oct6100_memory_priv.h" +#include "oct6100_tsst_priv.h" +#include "oct6100_mixer_priv.h" +#include "oct6100_phasing_tsst_priv.h" +#include "oct6100_tsi_cnct_priv.h" +#include "oct6100_playout_buf_priv.h" +#include "oct6100_conf_bridge_priv.h" +#include "oct6100_tone_detection_priv.h" +#include "oct6100_channel_priv.h" + + +/**************************** PUBLIC FUNCTIONS ****************************/ + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelOpen + +Description: This function opens a echo cancellation channel. An echo cancellation + channel is constituted of two voice stream (RIN/ROUT and SIN/SOUT), and + an echo cancelling core. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelOpen Pointer to echo channel open structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelOpenDef( + IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) +{ + f_pChannelOpen->pulChannelHndl = NULL; + f_pChannelOpen->ulUserChanId = cOCT6100_INVALID_VALUE; + f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; + f_pChannelOpen->fEnableToneDisabler = FALSE; + f_pChannelOpen->fEnableExtToneDetection = FALSE; + + /* VQE configuration.*/ + f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; + f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; + f_pChannelOpen->VqeConfig.fRinLevelControl = FALSE; + f_pChannelOpen->VqeConfig.lRinLevelControlGainDb = 0; + f_pChannelOpen->VqeConfig.fSoutLevelControl = FALSE; + f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb = 0; + f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl = FALSE; + f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = -20; + f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl = FALSE; + f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = -20; + f_pChannelOpen->VqeConfig.fRinHighLevelCompensation = FALSE; + f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = -10; + f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; + f_pChannelOpen->VqeConfig.fSoutNoiseBleaching = FALSE; + f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction = FALSE; + f_pChannelOpen->VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; + f_pChannelOpen->VqeConfig.fEnableNlp = TRUE; + f_pChannelOpen->VqeConfig.fEnableTailDisplacement = FALSE; + f_pChannelOpen->VqeConfig.ulTailDisplacement = cOCT6100_AUTO_SELECT_TAIL; + f_pChannelOpen->VqeConfig.ulTailLength = cOCT6100_AUTO_SELECT_TAIL; + + f_pChannelOpen->VqeConfig.fDtmfToneRemoval = FALSE; + + f_pChannelOpen->VqeConfig.fAcousticEcho = FALSE; + f_pChannelOpen->VqeConfig.lDefaultErlDb = -6; + f_pChannelOpen->VqeConfig.ulAecTailLength = 128; + f_pChannelOpen->VqeConfig.lAecDefaultErlDb = 0; + f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA = 1; + f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB = 0; + f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior = cOCT6100_DOUBLE_TALK_BEH_NORMAL; + f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = 0; + f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = 0; + f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement = FALSE; + f_pChannelOpen->VqeConfig.fRoutNoiseReduction = FALSE; + f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb = -18; + f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation = 6; + f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay = 300; + f_pChannelOpen->VqeConfig.fEnableMusicProtection = FALSE; + /* Older images have idle code detection hard-coded to enabled. */ + f_pChannelOpen->VqeConfig.fIdleCodeDetection = TRUE; + + /* TDM configuration.*/ + f_pChannelOpen->TdmConfig.ulRinNumTssts = 1; + f_pChannelOpen->TdmConfig.ulSinNumTssts = 1; + f_pChannelOpen->TdmConfig.ulRoutNumTssts = 1; + f_pChannelOpen->TdmConfig.ulSoutNumTssts = 1; + + f_pChannelOpen->TdmConfig.ulRinTimeslot = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulRinStream = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulRinPcmLaw = cOCT6100_PCM_U_LAW; + + f_pChannelOpen->TdmConfig.ulSinTimeslot = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulSinStream = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulSinPcmLaw = cOCT6100_PCM_U_LAW; + + f_pChannelOpen->TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulRoutPcmLaw = cOCT6100_PCM_U_LAW; + + f_pChannelOpen->TdmConfig.ulSoutTimeslot = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulSoutStream = cOCT6100_UNASSIGNED; + f_pChannelOpen->TdmConfig.ulSoutPcmLaw = cOCT6100_PCM_U_LAW; + + /* CODEC configuration.*/ + f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition = cOCT6100_ADPCM_IN_LOW_BITS; + + f_pChannelOpen->CodecConfig.ulEncoderPort = cOCT6100_CHANNEL_PORT_SOUT; + f_pChannelOpen->CodecConfig.ulEncodingRate = cOCT6100_G711_64KBPS; + f_pChannelOpen->CodecConfig.ulDecoderPort = cOCT6100_CHANNEL_PORT_RIN; + f_pChannelOpen->CodecConfig.ulDecodingRate = cOCT6100_G711_64KBPS; + + f_pChannelOpen->CodecConfig.fEnableSilenceSuppression = FALSE; + f_pChannelOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; + f_pChannelOpen->CodecConfig.ulPhase = 0; + f_pChannelOpen->CodecConfig.ulPhasingType = cOCT6100_NO_PHASING; + + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelOpen( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelOpenSer( f_pApiInstance, f_pChannelOpen ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelClose + +Description: This function closes an echo canceller channel + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelClose Pointer to channel close structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelCloseDef( + IN OUT tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) +{ + f_pChannelClose->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelClose( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelCloseSer( f_pApiInstance, f_pChannelClose ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelModify + +Description: This function will modify the parameter of an echo channel. If + the call to this channel allows the channel to go from power down + to enable, the API will activate it. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelModify Pointer to echo channel change structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelModifyDef( + IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) +{ + f_pChannelModify->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pChannelModify->ulUserChanId = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->ulEchoOperationMode = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->fEnableToneDisabler = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->fApplyToAllChannels = FALSE; + + f_pChannelModify->fDisableToneDetection = FALSE; + f_pChannelModify->fStopBufferPlayout = FALSE; + f_pChannelModify->fRemoveConfBridgeParticipant = FALSE; + f_pChannelModify->fRemoveBroadcastTssts = FALSE; + + f_pChannelModify->fTdmConfigModified = FALSE; + f_pChannelModify->fVqeConfigModified = FALSE; + f_pChannelModify->fCodecConfigModified = FALSE; + + /* VQE config. */ + f_pChannelModify->VqeConfig.fSinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fRinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fRinLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lRinLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lSoutLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fRinAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lRinAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lSoutAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fRinHighLevelCompensation = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lRinHighLevelCompensationThresholdDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutAdaptiveNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutNoiseBleaching = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutConferencingNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulComfortNoiseMode = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fEnableNlp = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fEnableTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->VqeConfig.fDtmfToneRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->VqeConfig.fAcousticEcho = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulAecTailLength = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lAecDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulNonLinearityBehaviorA = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulNonLinearityBehaviorB = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulDoubleTalkBehavior = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fSoutNaturalListenerEnhancement = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fRoutNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.lAnrSnrEnhancementDb = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulAnrVoiceNoiseSegregation = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.ulToneDisablerVqeActivationDelay = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fEnableMusicProtection = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->VqeConfig.fIdleCodeDetection = cOCT6100_KEEP_PREVIOUS_SETTING; + + /* TDM config. */ + f_pChannelModify->TdmConfig.ulRinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulRoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->TdmConfig.ulRinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulRinStream = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulRinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->TdmConfig.ulSinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSinStream = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->TdmConfig.ulRoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulRoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulRoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->TdmConfig.ulSoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->TdmConfig.ulSoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; + + /* CODEC config. */ + f_pChannelModify->CodecConfig.ulEncoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulEncodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulDecoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulDecodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; + + f_pChannelModify->CodecConfig.fEnableSilenceSuppression = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulPhasingTsstHndl = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulPhase = cOCT6100_KEEP_PREVIOUS_SETTING; + f_pChannelModify->CodecConfig.ulPhasingType = cOCT6100_KEEP_PREVIOUS_SETTING; + + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelModify( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Check the apply to all channels flag first. */ + if ( f_pChannelModify->fApplyToAllChannels != TRUE && + f_pChannelModify->fApplyToAllChannels != FALSE ) + return cOCT6100_ERR_CHANNEL_APPLY_TO_ALL_CHANNELS; + + /* Check if must apply modification to all channels. */ + if ( f_pChannelModify->fApplyToAllChannels == TRUE ) + { + tPOCT6100_API_CHANNEL pChanEntry; + UINT16 usChanIndex; + + /* Loop through all channels and look for the opened ones. */ + for ( usChanIndex = 0; usChanIndex < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; usChanIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, usChanIndex ); + + /* Check if this one is opened. */ + if ( pChanEntry->fReserved == TRUE ) + { + /* Channel is opened. Form handle and call actual modify function. */ + f_pChannelModify->ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | usChanIndex; + + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); + if ( ulFncRes != cOCT6100_ERR_OK ) + break; + } + } + } + else /* if ( f_pChannelModify->fApplyToAllChannels == FALSE ) */ + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); + } + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelCreateBiDir + +Description: This function creates a bidirectional channel using two standard + echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelCreateBiDir Pointer to channel create BiDir structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelCreateBiDirDef( + IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) +{ + f_pChannelCreateBiDir->pulBiDirChannelHndl = NULL; + + f_pChannelCreateBiDir->ulFirstChannelHndl = cOCT6100_INVALID_HANDLE; + f_pChannelCreateBiDir->ulSecondChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelCreateBiDir( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelCreateBiDirSer( f_pApiInstance, f_pChannelCreateBiDir ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelDestroyBiDir + +Description: This function destroys a bidirectional channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelDestroyBiDir Pointer to channel destroy BiDir structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelDestroyBiDirDef( + IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) +{ + f_pChannelDestroyBiDir->ulBiDirChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelDestroyBiDir( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelDestroyBiDirSer( f_pApiInstance, f_pChannelDestroyBiDir ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelBroadcastTsstAdd + +Description: This function adds a TSST to one of the two output ports of a channel. + This TSST can never be modified by a call to Oct6100ChannelModify. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelBroadcastTsstAdd Pointer to the an Add Broadcast TSST structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelBroadcastTsstAddDef( + tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelBroadcastTsstAdd ) +{ + f_pChannelBroadcastTsstAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + f_pChannelBroadcastTsstAdd->ulPort = cOCT6100_INVALID_PORT; + f_pChannelBroadcastTsstAdd->ulTimeslot = cOCT6100_INVALID_TIMESLOT; + f_pChannelBroadcastTsstAdd->ulStream = cOCT6100_INVALID_STREAM; + + return cOCT6100_ERR_OK; + +} + +UINT32 Oct6100ChannelBroadcastTsstAdd( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelBroadcastTsstAdd ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelBroadcastTsstAddSer( f_pApiInstance, f_pChannelBroadcastTsstAdd ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelBroadcastTsstRemove + +Description: This function removes a TSST from one of the two output ports of a channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelBroadcastTsstRemove Pointer to the a Remove Broadcast TSST structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelBroadcastTsstRemoveDef( + tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelBroadcastTsstRemove ) +{ + f_pChannelBroadcastTsstRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + f_pChannelBroadcastTsstRemove->ulPort = cOCT6100_INVALID_PORT; + f_pChannelBroadcastTsstRemove->ulTimeslot = cOCT6100_INVALID_TIMESLOT; + f_pChannelBroadcastTsstRemove->ulStream = cOCT6100_INVALID_STREAM; + + f_pChannelBroadcastTsstRemove->fRemoveAll = FALSE; + + return cOCT6100_ERR_OK; +} + + +UINT32 Oct6100ChannelBroadcastTsstRemove( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelBroadcastTsstRemove ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, f_pChannelBroadcastTsstRemove ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelGetStats + +Description: This function retrieves all the config and stats related to the channel + designated by ulChannelHndl. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelStats Pointer to a tOCT6100_CHANNEL_STATS structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelGetStatsDef( + IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ) +{ + f_pChannelStats->fResetStats = FALSE; + + f_pChannelStats->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pChannelStats->ulUserChanId = cOCT6100_INVALID_STAT; + f_pChannelStats->ulEchoOperationMode = cOCT6100_INVALID_STAT; + f_pChannelStats->fEnableToneDisabler = FALSE; + f_pChannelStats->ulMutePortsMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; + f_pChannelStats->fEnableExtToneDetection = FALSE; + + /* VQE configuration.*/ + f_pChannelStats->VqeConfig.fEnableNlp = FALSE; + f_pChannelStats->VqeConfig.fEnableTailDisplacement = FALSE; + f_pChannelStats->VqeConfig.ulTailDisplacement = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulTailLength = cOCT6100_INVALID_STAT; + + f_pChannelStats->VqeConfig.fSinDcOffsetRemoval = FALSE; + f_pChannelStats->VqeConfig.fRinDcOffsetRemoval = FALSE; + f_pChannelStats->VqeConfig.fRinLevelControl = FALSE; + f_pChannelStats->VqeConfig.fSoutLevelControl = FALSE; + f_pChannelStats->VqeConfig.fRinAutomaticLevelControl = FALSE; + f_pChannelStats->VqeConfig.fSoutAutomaticLevelControl = FALSE; + f_pChannelStats->VqeConfig.fRinHighLevelCompensation = FALSE; + f_pChannelStats->VqeConfig.fAcousticEcho = FALSE; + f_pChannelStats->VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; + f_pChannelStats->VqeConfig.fDtmfToneRemoval = FALSE; + + f_pChannelStats->VqeConfig.fSoutNoiseBleaching = FALSE; + f_pChannelStats->VqeConfig.fSoutConferencingNoiseReduction = FALSE; + + f_pChannelStats->VqeConfig.ulComfortNoiseMode = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulNonLinearityBehaviorA = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulNonLinearityBehaviorB = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulDoubleTalkBehavior = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.lRinLevelControlGainDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lSoutLevelControlGainDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lRinAutomaticLevelControlTargetDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lSoutAutomaticLevelControlTargetDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lRinHighLevelCompensationThresholdDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lDefaultErlDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.lAecDefaultErlDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.ulAecTailLength = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.fSoutNaturalListenerEnhancement = FALSE; + f_pChannelStats->VqeConfig.fRoutNoiseReduction = FALSE; + f_pChannelStats->VqeConfig.lAnrSnrEnhancementDb = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->VqeConfig.ulAnrVoiceNoiseSegregation = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.ulToneDisablerVqeActivationDelay = cOCT6100_INVALID_STAT; + f_pChannelStats->VqeConfig.fEnableMusicProtection = FALSE; + f_pChannelStats->VqeConfig.fIdleCodeDetection = FALSE; + + + + /* TDM configuration.*/ + f_pChannelStats->TdmConfig.ulMaxBroadcastTssts = 0; + f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = FALSE; + f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = FALSE; + + f_pChannelStats->TdmConfig.ulNumRoutBroadcastTssts = 0; + f_pChannelStats->TdmConfig.ulNumSoutBroadcastTssts = 0; + + f_pChannelStats->TdmConfig.ulRinNumTssts = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSinNumTssts = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulRoutNumTssts = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSoutNumTssts = cOCT6100_INVALID_STAT; + + f_pChannelStats->TdmConfig.ulRinTimeslot = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulRinStream = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulRinPcmLaw = cOCT6100_INVALID_STAT; + + f_pChannelStats->TdmConfig.ulSinTimeslot = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSinStream = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSinPcmLaw = cOCT6100_INVALID_STAT; + + f_pChannelStats->TdmConfig.ulRoutTimeslot = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulRoutStream = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulRoutPcmLaw = cOCT6100_INVALID_STAT; + + f_pChannelStats->TdmConfig.pulRoutBroadcastTimeslot = NULL; + f_pChannelStats->TdmConfig.pulRoutBroadcastStream = NULL; + + f_pChannelStats->TdmConfig.ulSoutTimeslot = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSoutStream = cOCT6100_INVALID_STAT; + f_pChannelStats->TdmConfig.ulSoutPcmLaw = cOCT6100_INVALID_STAT; + + f_pChannelStats->TdmConfig.pulSoutBroadcastTimeslot = NULL; + f_pChannelStats->TdmConfig.pulSoutBroadcastStream = NULL; + + + /* CODEC configuration.*/ + f_pChannelStats->CodecConfig.ulAdpcmNibblePosition = cOCT6100_INVALID_STAT; + + f_pChannelStats->CodecConfig.ulEncoderPort = cOCT6100_INVALID_STAT; + f_pChannelStats->CodecConfig.ulEncodingRate = cOCT6100_INVALID_STAT; + f_pChannelStats->CodecConfig.ulDecoderPort = cOCT6100_INVALID_STAT; + f_pChannelStats->CodecConfig.ulDecodingRate = cOCT6100_INVALID_STAT; + + f_pChannelStats->CodecConfig.fEnableSilenceSuppression = FALSE; + f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_STAT; + f_pChannelStats->CodecConfig.ulPhase = cOCT6100_INVALID_STAT; + f_pChannelStats->CodecConfig.ulPhasingType = cOCT6100_INVALID_STAT; + + f_pChannelStats->ulNumEchoPathChanges = cOCT6100_INVALID_STAT; + f_pChannelStats->ulToneDisablerStatus = cOCT6100_INVALID_STAT; + f_pChannelStats->fEchoCancellerConverged = FALSE; + f_pChannelStats->fSinVoiceDetected = FALSE; + f_pChannelStats->lCurrentERL = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->ulCurrentEchoDelay = cOCT6100_INVALID_STAT; + + f_pChannelStats->lMaxERL = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->ulMaxEchoDelay = cOCT6100_INVALID_STAT; + + f_pChannelStats->lRinLevel = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lRinAppliedGain = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lSoutAppliedGain = cOCT6100_INVALID_SIGNED_STAT; + f_pChannelStats->lComfortNoiseLevel = cOCT6100_INVALID_SIGNED_STAT; + + + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelGetStats( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ApiChannelGetStatsSer( f_pApiInstance, f_pChannelStats ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelMute + +Description: This function mutes some or all of the ports designated by + ulChannelHndl. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelMute Pointer to a tPOCT6100_CHANNEL_MUTE structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelMuteDef( + IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) +{ + f_pChannelMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pChannelMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelMute( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelMuteSer( f_pApiInstance, f_pChannelMute ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelUnMute + +Description: This function unmutes some or all of the ports designated by + ulChannelHndl. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelUnMute Pointer to a tPOCT6100_CHANNEL_UNMUTE structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelUnMuteDef( + IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) +{ + f_pChannelUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pChannelUnMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100ChannelUnMute( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ChannelUnMuteSer( f_pApiInstance, f_pChannelUnMute ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} + +/**************************** PRIVATE FUNCTIONS ****************************/ + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiGetChannelsEchoSwSizes + +Description: Gets the sizes of all portions of the API instance pertinent + to the management of the ECHO memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pOpenChip Pointer to chip configuration struct. +f_pInstSizes Pointer to struct containing instance sizes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiGetChannelsEchoSwSizes( + IN tPOCT6100_CHIP_OPEN f_pOpenChip, + OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) +{ + UINT32 ulTempVar; + UINT32 ulResult; + UINT32 ulMaxChannels; + + ulMaxChannels = f_pOpenChip->ulMaxChannels; + + if ( f_pOpenChip->fEnableChannelRecording == TRUE && ulMaxChannels != 672 ) + ulMaxChannels++; + + /* Determine the amount of memory required for the API echo channel list.*/ + f_pInstSizes->ulChannelList = ulMaxChannels * sizeof( tOCT6100_API_CHANNEL ); /* Add one for the record channel.*/ + f_pInstSizes->ulBiDirChannelList = f_pOpenChip->ulMaxBiDirChannels * sizeof( tOCT6100_API_BIDIR_CHANNEL ); + if ( ulMaxChannels > 0 ) + { + /* Calculate memory needed for ECHO memory allocation */ + ulResult = OctapiLlmAllocGetSize( ulMaxChannels, &f_pInstSizes->ulChannelAlloc ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_0; + } + else + { + f_pInstSizes->ulChannelAlloc = 0; + } + if ( f_pOpenChip->ulMaxBiDirChannels > 0 ) + { + /* Calculate memory needed for ECHO memory allocation */ + ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxBiDirChannels, &f_pInstSizes->ulBiDirChannelAlloc ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_0; + } + else + { + f_pInstSizes->ulBiDirChannelAlloc = 0; + } + + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelList, ulTempVar ) + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelAlloc, ulTempVar ) + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelList, ulTempVar ) + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelAlloc, ulTempVar ) + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiChannelsEchoSwInit + +Description: Initializes all elements of the instance structure associated + to the ECHO memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiChannelsEchoSwInit( + IN tPOCT6100_INSTANCE_API f_pApiInstance ) +{ + tPOCT6100_API_CHANNEL pChannelsEchoList; + tPOCT6100_API_BIDIR_CHANNEL pBiDirChannelsList; + tPOCT6100_SHARED_INFO pSharedInfo; + UINT16 usMaxChannels; + PVOID pEchoChanAlloc; + PVOID pBiDirChanAlloc; + UINT32 ulResult; + + /* Get local pointer to shared portion of the API instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Initialize the ECHO channel API list.*/ + usMaxChannels = pSharedInfo->ChipConfig.usMaxChannels; + + /* add a channel to initialize if the recording is activated. */ + if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) + usMaxChannels++; + + /* Set all entries in the ADCPM channel list to unused. */ + mOCT6100_GET_CHANNEL_LIST_PNT( pSharedInfo, pChannelsEchoList ); + + /* Initialize the API ECHO channels allocation software to "all free". */ + if ( usMaxChannels > 0 ) + { + /* Clear the memory */ + Oct6100UserMemSet( pChannelsEchoList, 0x00, sizeof(tOCT6100_API_CHANNEL) * usMaxChannels ); + + mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoChanAlloc ) + + ulResult = OctapiLlmAllocInit( &pEchoChanAlloc, usMaxChannels ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_1; + } + + mOCT6100_GET_BIDIR_CHANNEL_LIST_PNT( pSharedInfo, pBiDirChannelsList ); + + if ( pSharedInfo->ChipConfig.usMaxBiDirChannels > 0 ) + { + /* Clear the memory */ + Oct6100UserMemSet( pBiDirChannelsList, 0x00, sizeof(tOCT6100_API_BIDIR_CHANNEL) * pSharedInfo->ChipConfig.usMaxBiDirChannels ); + + mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pBiDirChanAlloc ) + + ulResult = OctapiLlmAllocInit( &pBiDirChanAlloc, pSharedInfo->ChipConfig.usMaxBiDirChannels ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A9; + + } + + return cOCT6100_ERR_OK; +} + + + + + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelOpenSer + +Description: Opens a echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelOpen Pointer to channel configuration structure. Then handle + identifying the buffer in all future function calls is + returned in this structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelOpenSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) +{ + tOCT6100_API_ECHO_CHAN_INDEX ChannelIndexConf; + UINT32 ulResult; + + /* Check the user's configuration of the echo cancellation channel for errors. */ + ulResult = Oct6100ApiCheckChannelParams( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the echo cancellation channel. */ + ulResult = Oct6100ApiReserveChannelResources( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write all necessary structures to activate the echo cancellation channel. */ + ulResult = Oct6100ApiWriteChannelStructs( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new echo cancellation channels's entry in the ECHO channel list. */ + ulResult = Oct6100ApiUpdateChannelEntry( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckChannelParams + +Description: Checks the user's echo cancellation channel open configuration for errors. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelOpen Pointer to echo cancellation channel open configuration structure. +f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckChannelParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) +{ + tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; + tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; + tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; + UINT32 ulDecoderNumTssts; + UINT32 ulResult; + + /* Dereference the configuration structure for clearer code and faster access.*/ + pTdmConfig = &f_pChannelOpen->TdmConfig; + pVqeConfig = &f_pChannelOpen->VqeConfig; + pCodecConfig = &f_pChannelOpen->CodecConfig; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels == 0 ) + return cOCT6100_ERR_CHANNEL_DISABLED; + + if ( f_pChannelOpen->pulChannelHndl == NULL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && + f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) + return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; + + /* Check the 2100Hz echo disabling configuration.*/ + if ( f_pChannelOpen->fEnableToneDisabler != TRUE && + f_pChannelOpen->fEnableToneDisabler != FALSE ) + return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; + + /* Check the extended Tone Detection flag value.*/ + if ( f_pChannelOpen->fEnableExtToneDetection != TRUE && + f_pChannelOpen->fEnableExtToneDetection != FALSE ) + return cOCT6100_ERR_CHANNEL_ENABLE_EXT_TONE_DETECTION; + + /* Check that extented tone detection is actually enabled by the user. */ + if ( ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) && + ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableExtToneDetection == FALSE ) ) + return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DISABLED; + + + + /*==============================================================================*/ + /* Check the TDM configuration parameters.*/ + + ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, pTdmConfig ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Now validate the VQE parameters */ + + ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, pVqeConfig, f_pChannelOpen->fEnableToneDisabler ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Verify if the echo operation mode selected can be applied. */ + if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + && ( pVqeConfig->fEnableNlp == FALSE ) ) + return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; + + /*==============================================================================*/ + + /*==============================================================================*/ + /* Finally, validate the CODEC configuration.*/ + + if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + ulDecoderNumTssts = pTdmConfig->ulRinNumTssts; + else /* pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + ulDecoderNumTssts = pTdmConfig->ulSinNumTssts; + + ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, pCodecConfig, ulDecoderNumTssts, &f_pChanIndexConf->usPhasingTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + + /* make sure that if silence suppression is activated, the NLP is enabled.*/ + if ( pCodecConfig->fEnableSilenceSuppression == TRUE && pVqeConfig->fEnableNlp == FALSE ) + return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; + + /* Verify if law conversion is allowed. */ + if ( pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING || + pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING ) + { + /* No law conversion can occurs if one ADPCM memory is not reserved.*/ + if ( pTdmConfig->ulRinPcmLaw != pTdmConfig->ulRoutPcmLaw ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; + + if ( pTdmConfig->ulSinPcmLaw != pTdmConfig->ulSoutPcmLaw ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; + } + + /* Verify if the config supports extended tone detection.*/ + if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) + { + if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; + } + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveChannelResources + +Description: Reserves all resources needed for the new channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelOpen Pointer to echo cancellation channel configuration structure. +f_pulChannelIndex Allocated entry in ECHO channel list. +f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveChannelResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; + tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; + + UINT32 ulResult; + UINT32 ulTempVar; + UINT32 ulFreeMixerEventCnt; + + BOOL fRinTsstEntry = FALSE; + BOOL fSinTsstEntry = FALSE; + BOOL fRoutTsstEntry = FALSE; + BOOL fSoutTsstEntry = FALSE; + + BOOL fRinRoutTsiMemEntry = FALSE; + BOOL fSinSoutTsiMemEntry = FALSE; + + BOOL fEchoChanEntry = FALSE; + + PUINT16 pusRinRoutConversionMemIndex = NULL; + PUINT16 pusSinSoutConversionMemIndex = NULL; + BOOL fRinRoutConversionMemEntry = FALSE; + BOOL fSinSoutConversionMemEntry = FALSE; + + BOOL fExtToneChanEntry = FALSE; + BOOL fExtToneTsiEntry = FALSE; + BOOL fExtToneMixerEntry = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain a local pointer to the configuration structures.*/ + pTdmConfig = &f_pChannelOpen->TdmConfig; + pCodecConfig = &f_pChannelOpen->CodecConfig; + + /*===============================================================================*/ + /* Reserve Echo and TSI entries. */ + + ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, + &f_pChanIndexConf->usEchoChanIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fEchoChanEntry = TRUE; + + /* Set the echo, encoder and decoder memory indexes.*/ + f_pChanIndexConf->usEchoMemIndex = f_pChanIndexConf->usEchoChanIndex; + + /* Reserve an entry for the RIN/ROUT tsi chariot memory. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &f_pChanIndexConf->usRinRoutTsiMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRinRoutTsiMemEntry = TRUE; + + /* Reserve an entry for the SIN/SOUT tsi chariot memory. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &f_pChanIndexConf->usSinSoutTsiMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSinSoutTsiMemEntry = TRUE; + + /* Reserve an ADPCM memory block for compression if required.*/ + if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; + } + else if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; + } + + /* Reserve an ADPCM memory block for decompression if required.*/ + if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; + } + else if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) + { + pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; + } + + + /* Reserve the conversion memories. */ + if ( pusRinRoutConversionMemIndex != NULL ) + { + /* Reserve a conversion memory for the Rin/Rout stream. */ + ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, + pusRinRoutConversionMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRinRoutConversionMemEntry = TRUE; + } + } + else + { + /* No conversion memory reserved.*/ + f_pChanIndexConf->usRinRoutConversionMemIndex = cOCT6100_INVALID_INDEX; + } + + if ( ( pusSinSoutConversionMemIndex != NULL ) && + ( ulResult == cOCT6100_ERR_OK ) ) + { + /* Reserve a conversion memory for the Sin/Sout stream. */ + ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, + pusSinSoutConversionMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSinSoutConversionMemEntry = TRUE; + } + } + else + { + /* No conversion memory reserved.*/ + f_pChanIndexConf->usSinSoutConversionMemIndex = cOCT6100_INVALID_INDEX; + } + + /* Reserve any resources required if the extended Tone detection is enabled.*/ + if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) + { + ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, + &f_pChanIndexConf->usExtToneChanIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fExtToneChanEntry = TRUE; + + /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &f_pChanIndexConf->usExtToneTsiIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fExtToneTsiEntry = TRUE; + + /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, + &f_pChanIndexConf->usExtToneMixerIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fExtToneMixerEntry = TRUE; + } + } + } + else + { + f_pChanIndexConf->usExtToneChanIndex = cOCT6100_INVALID_INDEX; + f_pChanIndexConf->usExtToneMixerIndex = cOCT6100_INVALID_INDEX; + f_pChanIndexConf->usExtToneTsiIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + /* Return an error other then a Fatal.*/ + ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; + } + } + else + { + /* Return an error other then a Fatal.*/ + ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; + } + } + + /*===============================================================================*/ + + /*===============================================================================*/ + /* Now reserve the TSST entries if required.*/ + + /* Reserve the Rin TSST entry */ + if ( (ulResult == cOCT6100_ERR_OK ) && + (pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED && + pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED) ) + { + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pTdmConfig->ulRinTimeslot, + pTdmConfig->ulRinStream, + pTdmConfig->ulRinNumTssts, + cOCT6100_INPUT_TSST, + &f_pChanIndexConf->usRinTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + fRinTsstEntry = TRUE; + } + else + { + f_pChanIndexConf->usRinTsstIndex = cOCT6100_INVALID_INDEX; + } + + + if ( (ulResult == cOCT6100_ERR_OK ) && + (pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED && + pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED) ) + { + /* Reserve the Sin TSST entry.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pTdmConfig->ulSinTimeslot, + pTdmConfig->ulSinStream, + pTdmConfig->ulSinNumTssts, + cOCT6100_INPUT_TSST, + &f_pChanIndexConf->usSinTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + fSinTsstEntry = TRUE; + } + else + { + f_pChanIndexConf->usSinTsstIndex = cOCT6100_INVALID_INDEX; + } + + if ( (ulResult == cOCT6100_ERR_OK ) && + (pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED && + pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED) ) + { + /* Reserve the Rout TSST entry.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pTdmConfig->ulRoutTimeslot, + pTdmConfig->ulRoutStream, + pTdmConfig->ulRoutNumTssts, + cOCT6100_OUTPUT_TSST, + &f_pChanIndexConf->usRoutTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + fRoutTsstEntry = TRUE; + } + else + { + f_pChanIndexConf->usRoutTsstIndex = cOCT6100_INVALID_INDEX; + } + + + if ( (ulResult == cOCT6100_ERR_OK ) && + (pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED && + pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED) ) + { + /* Reserve the Sout TSST entry.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pTdmConfig->ulSoutTimeslot, + pTdmConfig->ulSoutStream, + pTdmConfig->ulSoutNumTssts, + cOCT6100_OUTPUT_TSST, + &f_pChanIndexConf->usSoutTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + fSoutTsstEntry = TRUE; + } + else + { + f_pChanIndexConf->usSoutTsstIndex = cOCT6100_INVALID_INDEX; + } + + /*===============================================================================*/ + + + /*===============================================================================*/ + /* Check if there are a couple of mixer events available for us. */ + + if ( ulResult == cOCT6100_ERR_OK ) + { + UINT32 ulMixerEventCntNeeded = 0; + + /* Calculate how many mixer events are needed. */ + if ( f_pChanIndexConf->usRinTsstIndex == cOCT6100_INVALID_INDEX ) + ulMixerEventCntNeeded++; + + if ( f_pChanIndexConf->usSinTsstIndex == cOCT6100_INVALID_INDEX ) + ulMixerEventCntNeeded++; + + /* If at least 1 mixer event is needed, check if those are available. */ + if ( ulMixerEventCntNeeded != 0 ) + { + ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); + if ( ulResult == cOCT6100_ERR_OK ) + { + /* The API might need more mixer events if the ports have to be muted. */ + /* Check if these are available. */ + if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) + { + ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; + } + } + } + } + + /*===============================================================================*/ + + + /*===============================================================================*/ + /* Release the resources if something went wrong */ + if ( ulResult != cOCT6100_ERR_OK ) + { + /*===============================================================================*/ + /* Release the previously reserved resources .*/ + if( fRinTsstEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->ulRinTimeslot, + pTdmConfig->ulRinStream, + pTdmConfig->ulRinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fSinTsstEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->ulSinTimeslot, + pTdmConfig->ulSinStream, + pTdmConfig->ulSinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fRoutTsstEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->ulRoutTimeslot, + pTdmConfig->ulRoutStream, + pTdmConfig->ulRoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fSoutTsstEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->ulSoutTimeslot, + pTdmConfig->ulSoutStream, + pTdmConfig->ulSoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fRinRoutTsiMemEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, + f_pChanIndexConf->usRinRoutTsiMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fSinSoutTsiMemEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, + f_pChanIndexConf->usSinSoutTsiMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /*===============================================================================*/ + + /*===============================================================================*/ + /* Release the previously reserved echo resources .*/ + if( fEchoChanEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, + f_pChanIndexConf->usEchoChanIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /*===============================================================================*/ + + /*===============================================================================*/ + /* Release the previously reserved resources for the extended tone detection.*/ + if( fExtToneChanEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, + f_pChanIndexConf->usExtToneChanIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fExtToneTsiEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, + f_pChanIndexConf->usExtToneTsiIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fExtToneMixerEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + f_pChanIndexConf->usExtToneMixerIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + /*===============================================================================*/ + + /*===============================================================================*/ + /* Release the conversion resources. */ + if( fRinRoutConversionMemEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, + f_pChanIndexConf->usRinRoutConversionMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if( fSinSoutConversionMemEntry == TRUE ) + { + ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, + f_pChanIndexConf->usSinSoutConversionMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /*===============================================================================*/ + + return ulResult; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteChannelStructs + +Description: Performs all the required structure writes to configure the + new echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelOpen Pointer to echo cancellation channel configuration structure. +f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteChannelStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; + tOCT6100_WRITE_PARAMS WriteParams; + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulResult; + UINT32 ulDwordAddress; + UINT32 ulDwordData; + BOOL fConversionEnabled = FALSE; + BOOL fProgramAdpcmMem; + UINT32 ulCompType = 0; + UINT32 ulPcmLaw; + UINT16 usTempTsiMemIndex; + UINT16 usConversionMemIndex; + UINT32 ulToneEventNumber; + BOOL fSSTone; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain a local pointer to the TDM configuration structure.*/ + pTdmConfig = &f_pChannelOpen->TdmConfig; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ); + + /*==============================================================================*/ + /* Configure the Tsst control memory.*/ + + /* Set the RIN Tsst control entry.*/ + if ( f_pChanIndexConf->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_pChanIndexConf->usRinTsstIndex, + f_pChanIndexConf->usRinRoutTsiMemIndex, + pTdmConfig->ulRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Set the ROUT Tsst control entry.*/ + if ( f_pChanIndexConf->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_pChanIndexConf->usRoutTsstIndex, + f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, + pTdmConfig->ulRoutNumTssts, + f_pChanIndexConf->usRinRoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Set the SIN Tsst control entry.*/ + if ( f_pChanIndexConf->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_pChanIndexConf->usSinTsstIndex, + f_pChanIndexConf->usSinSoutTsiMemIndex, + pTdmConfig->ulSinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Set the SOUT Tsst control entry.*/ + if ( f_pChanIndexConf->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_pChanIndexConf->usSoutTsstIndex, + f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, + pTdmConfig->ulSoutNumTssts, + f_pChanIndexConf->usSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*==============================================================================*/ + + /*==============================================================================*/ + /* Configure the ADPCM control memory for the Decoder.*/ + + /* Set the codec state flags.*/ + f_pChanIndexConf->fRinRoutCodecActive = FALSE; + f_pChanIndexConf->fSinSoutCodecActive = FALSE; + + if ( f_pChannelOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING ) + { + fProgramAdpcmMem = TRUE; + + switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) + { + case cOCT6100_G711_64KBPS: + ulCompType = 0x8; + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) + fProgramAdpcmMem = FALSE; + } + else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + { + if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) + fProgramAdpcmMem = FALSE; + } + break; + case cOCT6100_G726_40KBPS: + ulCompType = 0x3; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_32KBPS: + ulCompType = 0x2; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_24KBPS: + ulCompType = 0x1; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_16KBPS: + ulCompType = 0x0; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_2C_ENCODED: + ulCompType = 0x4; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_3C_ENCODED: + ulCompType = 0x5; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_4C_ENCODED: + ulCompType = 0x6; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_ENCODED: + ulCompType = 0x9; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G726_ENCODED: + ulCompType = 0xA; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_2C_ENCODED: + ulCompType = 0xC; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_3C_ENCODED: + ulCompType = 0xD; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_4C_ENCODED: + ulCompType = 0xE; + fConversionEnabled = TRUE; + break; + default: + return cOCT6100_ERR_FATAL_D4; + } + + if ( fProgramAdpcmMem == TRUE ) + { + /* Set the chariot memory based on the selected port.*/ + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; + ulPcmLaw = pTdmConfig->ulRoutPcmLaw; /* Set the law for later use */ + + /* Set the codec state flags.*/ + f_pChanIndexConf->fRinRoutCodecActive = TRUE; + + /* Set the conversion memory index to use for decompression */ + usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; + } + else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + { + usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; + ulPcmLaw = pTdmConfig->ulSoutPcmLaw; /* Set the law for later use */ + + /* Set the codec state flags.*/ + f_pChanIndexConf->fSinSoutCodecActive = TRUE; + + /* Set the conversion memory index to use for decompression */ + usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; + } + + ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, + usConversionMemIndex, + ulCompType, + usTempTsiMemIndex, + ulPcmLaw, + f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Configure the ADPCM control memory for the Encoder */ + + if ( f_pChannelOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING ) + { + fProgramAdpcmMem = TRUE; + + switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) + { + case cOCT6100_G711_64KBPS: + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + if ( pTdmConfig->ulRoutPcmLaw == cOCT6100_PCM_U_LAW ) + ulCompType = 0x4; + else + ulCompType = 0x5; + + /* Check for law conversion.*/ + if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) + fProgramAdpcmMem = FALSE; + } + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + if ( pTdmConfig->ulSoutPcmLaw == cOCT6100_PCM_U_LAW ) + ulCompType = 0x4; + else + ulCompType = 0x5; + + /* Check for law conversion.*/ + if ( pTdmConfig->ulSinPcmLaw == pTdmConfig->ulSoutPcmLaw ) + fProgramAdpcmMem = FALSE; + } + + break; + case cOCT6100_G726_40KBPS: + ulCompType = 0x3; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_32KBPS: + ulCompType = 0x2; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_24KBPS: + ulCompType = 0x1; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_16KBPS: + ulCompType = 0x0; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_4_1: + ulCompType = 0xD; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_3_2: + ulCompType = 0xA; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_2_3: + ulCompType = 0x6; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_4_0: + ulCompType = 0xE; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_3_1: + ulCompType = 0xB; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_2_2: + ulCompType = 0x7; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_24KBPS_3_0: + ulCompType = 0xC; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_24KBPS_2_1: + ulCompType = 0x8; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_16KBPS_2_0: + ulCompType = 0x9; + fConversionEnabled = TRUE; + break; + + default: + return cOCT6100_ERR_FATAL_D5; + } + + /* Program the APDCM memory only if ADPCM is requried.*/ + if ( fProgramAdpcmMem == TRUE || f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Set the chariot memory based on the selected port.*/ + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; + + /* Set the codec state flags.*/ + f_pChanIndexConf->fRinRoutCodecActive = TRUE; + + /* Set the conversion memory index to use for compression */ + usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; + } + + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; + + /* Set the codec state flags.*/ + f_pChanIndexConf->fSinSoutCodecActive = TRUE; + + /* Set the conversion memory index to use for compression */ + usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; + } + + ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, + usConversionMemIndex, + ulCompType, + usTempTsiMemIndex, + f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, + f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, + f_pChanIndexConf->usPhasingTsstIndex, + f_pChannelOpen->CodecConfig.ulPhasingType, + f_pChannelOpen->CodecConfig.ulPhase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Clearing the tone events bit vector */ + + ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usEchoChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); + ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; + ulDwordData = 0x00000000; + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulDwordAddress += 4; + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Write the VQE memory */ + + ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, + &f_pChannelOpen->VqeConfig, + f_pChannelOpen, + f_pChanIndexConf->usEchoChanIndex, + f_pChanIndexConf->usEchoMemIndex, + TRUE, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + /*==============================================================================*/ + /* Write the echo memory */ + + ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, + pTdmConfig, + f_pChannelOpen, + f_pChanIndexConf->usEchoMemIndex, + f_pChanIndexConf->usRinRoutTsiMemIndex, + f_pChanIndexConf->usSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + + /*==============================================================================*/ + /* Mute channel if required, this is done on a port basis */ + + /* Initialize the silence indexes to invalid for now. */ + pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; + + /* Set the TSI memory indexes. */ + pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; + pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, + f_pChanIndexConf->usEchoChanIndex, + f_pChanIndexConf->usRinTsstIndex, + f_pChanIndexConf->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the dominant speaker to unassigned, if required. */ + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == TRUE ) + { + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* If necessary, configure the extended tone detection channel.*/ + + if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) + { + UINT32 ulTempSinLaw; + UINT32 ulTempSoutLaw; + UINT32 ulTempEchoOpMode; + + /* save the original law.*/ + ulTempSinLaw = pTdmConfig->ulSinPcmLaw; + ulTempSoutLaw = pTdmConfig->ulSoutPcmLaw; + ulTempEchoOpMode = f_pChannelOpen->ulEchoOperationMode; + + /* Now, make sure the Sin and Sout law are the same as the Rin law.*/ + + pTdmConfig->ulSinPcmLaw = pTdmConfig->ulRinPcmLaw; + pTdmConfig->ulSoutPcmLaw = pTdmConfig->ulRinPcmLaw; + + f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_NORMAL; + + /* Write the Echo and VQE memory of the extended channel.*/ + + ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, + pTdmConfig, + &f_pChannelOpen->VqeConfig, + f_pChannelOpen, + f_pChanIndexConf->usExtToneChanIndex, + f_pChanIndexConf->usExtToneChanIndex, + cOCT6100_API_EXT_TONE_EXTRA_TSI, + f_pChanIndexConf->usExtToneTsiIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now, write the mixer event used to copy the RIN signal of the original channel + into the SIN signal of the exteded channel. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_pChanIndexConf->usExtToneMixerIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= f_pChanIndexConf->usRinRoutTsiMemIndex; + WriteParams.usWriteData |= pTdmConfig->ulRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = f_pChanIndexConf->usExtToneTsiIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now insert the Sin copy event into the list.*/ + + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_pChanIndexConf->usExtToneMixerIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_pChanIndexConf->usEchoChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*=======================================================================*/ + + /*==============================================================================*/ + /* Clearing the tone events bit vector */ + + ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); + ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; + ulDwordData = 0x00000000; + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulDwordAddress += 4; + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + /* Write back the original values in the channel open structure.*/ + + pTdmConfig->ulSinPcmLaw = ulTempSinLaw; + pTdmConfig->ulSoutPcmLaw = ulTempSoutLaw; + + f_pChannelOpen->ulEchoOperationMode = ulTempEchoOpMode; + } + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* If necessary, configure the SS tone detection. */ + + for ( ulToneEventNumber = 0; ulToneEventNumber < cOCT6100_MAX_TONE_EVENT; ulToneEventNumber++ ) + { + /* Check if the current tone is a SS tone. */ + ulResult = Oct6100ApiIsSSTone( + f_pApiInstance, + f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID, + &fSSTone ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( fSSTone == TRUE ) + { + /* Write to all resources needed to activate tone detection on this SS tone. */ + ulResult = Oct6100ApiWriteToneDetectEvent( + f_pApiInstance, + f_pChanIndexConf->usEchoChanIndex, + ulToneEventNumber, + + cOCT6100_INVALID_INDEX ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /*==============================================================================*/ + + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateChannelEntry + +Description: Updates the new channel in the ECHO channel list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelOpen Pointer to echo cancellation channel configuration structure. +f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiUpdateChannelEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; + tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; + tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; + + /* Obtain a pointer to the config structures of the tPOCT6100_CHANNEL_OPEN structure. */ + pTdmConfig = &f_pChannelOpen->TdmConfig; + pVqeConfig = &f_pChannelOpen->VqeConfig; + pCodecConfig = &f_pChannelOpen->CodecConfig; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ) + + /*=======================================================================*/ + /* Copy the channel's configuration and allocated resources. */ + pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; + pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); + pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); + pChanEntry->fEnableExtToneDetection = (UINT8)( f_pChannelOpen->fEnableExtToneDetection & 0xFF ); + + /* Save the VQE configuration.*/ + pChanEntry->VqeConfig.byComfortNoiseMode = (UINT8)( pVqeConfig->ulComfortNoiseMode & 0xFF ); + pChanEntry->VqeConfig.fEnableNlp = (UINT8)( pVqeConfig->fEnableNlp & 0xFF ); + pChanEntry->VqeConfig.fEnableTailDisplacement = (UINT8)( pVqeConfig->fEnableTailDisplacement ); + pChanEntry->VqeConfig.usTailDisplacement = (UINT16)( pVqeConfig->ulTailDisplacement & 0xFFFF ); + pChanEntry->VqeConfig.usTailLength = (UINT16)( pVqeConfig->ulTailLength & 0xFFFF ); + + pChanEntry->VqeConfig.fSinDcOffsetRemoval = (UINT8)( pVqeConfig->fSinDcOffsetRemoval & 0xFF ); + pChanEntry->VqeConfig.fRinDcOffsetRemoval = (UINT8)( pVqeConfig->fRinDcOffsetRemoval & 0xFF ); + pChanEntry->VqeConfig.fRinLevelControl = (UINT8)( pVqeConfig->fRinLevelControl & 0xFF ); + pChanEntry->VqeConfig.chRinLevelControlGainDb = (INT8)( pVqeConfig->lRinLevelControlGainDb & 0xFF ); + pChanEntry->VqeConfig.fSoutLevelControl = (UINT8)( pVqeConfig->fSoutLevelControl & 0xFF ); + pChanEntry->VqeConfig.chSoutLevelControlGainDb = (INT8)( pVqeConfig->lSoutLevelControlGainDb & 0xFF ); + pChanEntry->VqeConfig.fRinAutomaticLevelControl = (UINT8)( pVqeConfig->fRinAutomaticLevelControl & 0xFF ); + pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb = (INT8)( pVqeConfig->lRinAutomaticLevelControlTargetDb & 0xFF ); + pChanEntry->VqeConfig.fSoutAutomaticLevelControl = (UINT8)( pVqeConfig->fSoutAutomaticLevelControl & 0xFF ); + pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb = (INT8)( pVqeConfig->lSoutAutomaticLevelControlTargetDb & 0xFF ); + pChanEntry->VqeConfig.fRinHighLevelCompensation = (UINT8)( pVqeConfig->fRinHighLevelCompensation & 0xFF ); + pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb = (INT8)( pVqeConfig->lRinHighLevelCompensationThresholdDb & 0xFF ); + pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction = (UINT8)( pVqeConfig->fSoutAdaptiveNoiseReduction & 0xFF ); + pChanEntry->VqeConfig.fSoutNoiseBleaching = (UINT8)( pVqeConfig->fSoutNoiseBleaching & 0xFF ); + pChanEntry->VqeConfig.fSoutConferencingNoiseReduction = (UINT8)( pVqeConfig->fSoutConferencingNoiseReduction & 0xFF ); + + pChanEntry->VqeConfig.fAcousticEcho = (UINT8)( pVqeConfig->fAcousticEcho & 0xFF ); + + pChanEntry->VqeConfig.fDtmfToneRemoval = (UINT8)( pVqeConfig->fDtmfToneRemoval & 0xFF ); + + pChanEntry->VqeConfig.chDefaultErlDb = (INT8)( pVqeConfig->lDefaultErlDb & 0xFF ); + pChanEntry->VqeConfig.chAecDefaultErlDb = (INT8)( pVqeConfig->lAecDefaultErlDb & 0xFF ); + pChanEntry->VqeConfig.usAecTailLength = (UINT16)( pVqeConfig->ulAecTailLength & 0xFFFF ); + pChanEntry->VqeConfig.byNonLinearityBehaviorA = (UINT8)( pVqeConfig->ulNonLinearityBehaviorA & 0xFF ); + pChanEntry->VqeConfig.byNonLinearityBehaviorB = (UINT8)( pVqeConfig->ulNonLinearityBehaviorB & 0xFF ); + pChanEntry->VqeConfig.byDoubleTalkBehavior = (UINT8)( pVqeConfig->ulDoubleTalkBehavior & 0xFF ); + pChanEntry->VqeConfig.chAnrSnrEnhancementDb = (INT8)( pVqeConfig->lAnrSnrEnhancementDb & 0xFF ); + pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation = (UINT8)( pVqeConfig->ulAnrVoiceNoiseSegregation & 0xFF ); + pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay = (UINT16)( pVqeConfig->ulToneDisablerVqeActivationDelay & 0xFFFF ); + + pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); + pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutNaturalListenerEnhancementGainDb & 0xFF ); + pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement = (UINT8)( pVqeConfig->fSoutNaturalListenerEnhancement & 0xFF ); + pChanEntry->VqeConfig.fRoutNoiseReduction = (UINT8)( pVqeConfig->fRoutNoiseReduction & 0xFF ); + pChanEntry->VqeConfig.fEnableMusicProtection = (UINT8)( pVqeConfig->fEnableMusicProtection & 0xFF ); + pChanEntry->VqeConfig.fIdleCodeDetection = (UINT8)( pVqeConfig->fIdleCodeDetection & 0xFF ); + + /* Save the codec information.*/ + pChanEntry->CodecConfig.byAdpcmNibblePosition = (UINT8)( pCodecConfig->ulAdpcmNibblePosition & 0xFF ); + + pChanEntry->CodecConfig.byDecoderPort = (UINT8)( pCodecConfig->ulDecoderPort & 0xFF ); + pChanEntry->CodecConfig.byDecodingRate = (UINT8)( pCodecConfig->ulDecodingRate & 0xFF ); + pChanEntry->CodecConfig.byEncoderPort = (UINT8)( pCodecConfig->ulEncoderPort & 0xFF ); + pChanEntry->CodecConfig.byEncodingRate = (UINT8)( pCodecConfig->ulEncodingRate & 0xFF ); + + pChanEntry->CodecConfig.fEnableSilenceSuppression = (UINT8)( pCodecConfig->fEnableSilenceSuppression & 0xFF ); + pChanEntry->CodecConfig.byPhase = (UINT8)( pCodecConfig->ulPhase & 0xFF ); + pChanEntry->CodecConfig.byPhasingType = (UINT8)( pCodecConfig->ulPhasingType & 0xFF ); + + /* Save the RIN settings.*/ + pChanEntry->TdmConfig.byRinPcmLaw = (UINT8)( pTdmConfig->ulRinPcmLaw & 0xFF ); + pChanEntry->TdmConfig.usRinTimeslot = (UINT16)( pTdmConfig->ulRinTimeslot & 0xFFFF ); + pChanEntry->TdmConfig.usRinStream = (UINT16)( pTdmConfig->ulRinStream & 0xFFFF ); + + /* Save the SIN settings.*/ + pChanEntry->TdmConfig.bySinPcmLaw = (UINT8)( pTdmConfig->ulSinPcmLaw & 0xFF ); + pChanEntry->TdmConfig.usSinTimeslot = (UINT16)( pTdmConfig->ulSinTimeslot & 0xFFFF ); + pChanEntry->TdmConfig.usSinStream = (UINT16)( pTdmConfig->ulSinStream & 0xFFFF ); + + /* Save the ROUT settings.*/ + pChanEntry->TdmConfig.byRoutPcmLaw = (UINT8)( pTdmConfig->ulRoutPcmLaw & 0xFF ); + pChanEntry->TdmConfig.usRoutTimeslot = (UINT16)( pTdmConfig->ulRoutTimeslot & 0xFFFF ); + pChanEntry->TdmConfig.usRoutStream = (UINT16)( pTdmConfig->ulRoutStream & 0xFFFF ); + + pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; + pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; + + /* Save the SOUT settings.*/ + pChanEntry->TdmConfig.bySoutPcmLaw = (UINT8)( pTdmConfig->ulSoutPcmLaw & 0xFF ); + pChanEntry->TdmConfig.usSoutTimeslot = (UINT16)( pTdmConfig->ulSoutTimeslot & 0xFFFF ); + pChanEntry->TdmConfig.usSoutStream = (UINT16)( pTdmConfig->ulSoutStream & 0xFFFF ); + + pChanEntry->TdmConfig.byRinNumTssts = (UINT8)( pTdmConfig->ulRinNumTssts & 0xFF ); + pChanEntry->TdmConfig.bySinNumTssts = (UINT8)( pTdmConfig->ulSinNumTssts & 0xFF ); + pChanEntry->TdmConfig.byRoutNumTssts = (UINT8)( pTdmConfig->ulRoutNumTssts & 0xFF ); + pChanEntry->TdmConfig.bySoutNumTssts = (UINT8)( pTdmConfig->ulSoutNumTssts & 0xFF ); + pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; + pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; + + /* Save the extended Tone detection information.*/ + pChanEntry->usExtToneChanIndex = f_pChanIndexConf->usExtToneChanIndex; + pChanEntry->usExtToneMixerIndex = f_pChanIndexConf->usExtToneMixerIndex; + pChanEntry->usExtToneTsiIndex = f_pChanIndexConf->usExtToneTsiIndex; + + if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) + { + tPOCT6100_API_CHANNEL pExtToneChanEntry; + + /* Set the mode of the original channel. He is the channel performing detection on the + SIN port. The extended channel will perform detection on the RIN port.*/ + pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_SIN_PORT_MODE; + + /* Now, program the associated channel.*/ + + /* Obtain a pointer to the extended tone detection channel entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pExtToneChanEntry, f_pChanIndexConf->usExtToneChanIndex ); + + pExtToneChanEntry->fReserved = TRUE; + pExtToneChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_RIN_PORT_MODE; /* Detect on RIN port.*/ + pExtToneChanEntry->usExtToneChanIndex = f_pChanIndexConf->usEchoChanIndex; + + pExtToneChanEntry->aulToneConf[ 0 ] = 0; + pExtToneChanEntry->aulToneConf[ 1 ] = 0; + + } + else + { + /* No extended tone detection supported.*/ + pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; + } + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Store hardware related information.*/ + pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; + pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; + pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; + + /* We are not being tapped for now. */ + pChanEntry->fBeingTapped = FALSE; + + pChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; + pChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; + + /* The copy event has not yet been created. */ + pChanEntry->fCopyEventCreated = FALSE; + + pChanEntry->usRinRoutConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; + pChanEntry->usSinSoutConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; + + pChanEntry->usPhasingTsstIndex = f_pChanIndexConf->usPhasingTsstIndex; + + pChanEntry->fSinSoutCodecActive = f_pChanIndexConf->fSinSoutCodecActive; + pChanEntry->fRinRoutCodecActive = f_pChanIndexConf->fRinRoutCodecActive; + + + + pChanEntry->usEchoMemIndex = f_pChanIndexConf->usEchoMemIndex; + + pChanEntry->usRinTsstIndex = f_pChanIndexConf->usRinTsstIndex; + pChanEntry->usSinTsstIndex = f_pChanIndexConf->usSinTsstIndex; + pChanEntry->usRoutTsstIndex = f_pChanIndexConf->usRoutTsstIndex; + pChanEntry->usSoutTsstIndex = f_pChanIndexConf->usSoutTsstIndex; + + pChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + pChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Nothing muted for now. */ + pChanEntry->usMutedPorts = cOCT6100_CHANNEL_MUTE_PORT_NONE; + + /* Set all the GW feature initial value.*/ + /* Bridge info */ + pChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; + pChanEntry->fMute = FALSE; + + pChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; + pChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; + + /* Buffer playout info.*/ + pChanEntry->fRinBufPlaying = FALSE; + pChanEntry->fSoutBufPlaying = FALSE; + + /* Tone detection state. */ + /* This array is configured as follow.*/ + /* Index 0 contain event 0 to 31 (msb = event 31) and Index 1 contain index 32 - 55 */ + pChanEntry->aulToneConf[ 0 ] = 0; + pChanEntry->aulToneConf[ 1 ] = 0; + pChanEntry->ulLastSSToneDetected = cOCT6100_INVALID_VALUE; + pChanEntry->ulLastSSToneTimestamp = cOCT6100_INVALID_VALUE; + + /* Initialize the bidirectional flag.*/ + pChanEntry->fBiDirChannel = FALSE; + + /*=======================================================================*/ + /* Init some of the stats.*/ + + pChanEntry->sMaxERL = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->sMaxERLE = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->usMaxEchoDelay = cOCT6100_INVALID_STAT_W; + pChanEntry->usNumEchoPathChangesOfst = 0; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the dependency of the phasing TSST if one is associated to the chanel.*/ + + if ( f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + tPOCT6100_API_PHASING_TSST pPhasingEntry; + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanIndexConf->usPhasingTsstIndex ); + + pPhasingEntry->usDependencyCnt++; + } + /*=======================================================================*/ + + /*=======================================================================*/ + + /* Form handle returned to user. */ + *f_pChannelOpen->pulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanIndexConf->usEchoChanIndex; + + /* Finally, mark the channel as open. */ + pChanEntry->fReserved = TRUE; + pChanEntry->usExtraSinTsiDependencyCnt = 0; + + /* Increment the number of channel open.*/ + f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels++; + + /*=======================================================================*/ + + return cOCT6100_ERR_OK; +} + + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelCloseSer + +Description: Closes a echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelClose Pointer to echo cancellation channel close structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelCloseSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) +{ + UINT16 usChannelIndex; + + + UINT32 ulResult; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertChannelParams( f_pApiInstance, + f_pChannelClose, + + &usChannelIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the echo cancellation channel. */ + ulResult = Oct6100ApiInvalidateChannelStructs( f_pApiInstance, + + usChannelIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the echo cancellation channel. */ + ulResult = Oct6100ApiReleaseChannelResources( f_pApiInstance, usChannelIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Invalidate the handle.*/ + f_pChannelClose->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertChannelParams + +Description: Validate the handle given by the user and verify the state of + the channel about to be closed. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelClose Pointer to echo cancellation channel close structure. +f_pulFpgaChanIndex Pointer to the FPGA channel index associated to this channel. +f_pusChanIndex Pointer to the index of the channel within the API instance. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertChannelParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose, + + IN OUT PUINT16 f_pusChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulEntryOpenCnt; + + /* Get local pointer(s). */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Check the provided handle. */ + if ( (f_pChannelClose->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelClose->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelClose->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + if ( pChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; + + /*=======================================================================*/ + + /* Check if the channel is bound to a bridge. */ + if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_ACTIVE_DEPENDENCIES; + + + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiInvalidateChannelStructs + +Description: Closes a echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_ulFpgaChanIndex Index of the channel within the SCN_PLC FPGA. +f_usChanIndex Index of the channel within the API instance. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiInvalidateChannelStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + + IN UINT16 f_usChanIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_CHANNEL_TDM pTdmConfig; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_WRITE_SMEAR_PARAMS SmearParams; + UINT32 ulResult; + UINT16 usCurrentEntry; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); + + /* Obtain local pointer to the TDM configuration of the channel */ + pTdmConfig = &pChanEntry->TdmConfig; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + SmearParams.pProcessContext = f_pApiInstance->pProcessContext; + + SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Deactivate the TSST control memory if used. */ + + /* RIN port.*/ + if ( pTdmConfig->usRinTimeslot != cOCT6100_UNASSIGNED ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* SIN port.*/ + if ( pTdmConfig->usSinTimeslot != cOCT6100_UNASSIGNED ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*=======================================================================*/ + /* ROUT port.*/ + + if ( pTdmConfig->usRoutTimeslot != cOCT6100_UNASSIGNED ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Now the broadcast TSST.*/ + usCurrentEntry = pTdmConfig->usRoutBrdcastTsstFirstEntry; + while( usCurrentEntry != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); + + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move to the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + } + /*=======================================================================*/ + + /*=======================================================================*/ + /* SOUT port.*/ + + if ( pTdmConfig->usSoutTimeslot != cOCT6100_UNASSIGNED ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Now the broadcast TSST.*/ + usCurrentEntry = pTdmConfig->usSoutBrdcastTsstFirstEntry; + while( usCurrentEntry != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); + + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move to the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + } + /*=======================================================================*/ + + + /*------------------------------------------------------------------------------*/ + /* Deactivate the ECHO control memory entry.*/ + + /* Set the input Echo control entry to unused.*/ + WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*------------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------------*/ + /* Deactivate the conversion control memories if used. */ + + if ( pChanEntry->usRinRoutConversionMemIndex != cOCT6100_INVALID_INDEX ) + { + /* Rin/Rout stream conversion memory was used */ + ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, pChanEntry->usRinRoutConversionMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + if ( pChanEntry->usSinSoutConversionMemIndex != cOCT6100_INVALID_INDEX ) + { + /* Sin/Sout stream conversion memory was used */ + ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, pChanEntry->usSinSoutConversionMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*------------------------------------------------------------------------------*/ + + + /*------------------------------------------------------------------------------*/ + /* Clear the silence copy events if they were created. */ + + /* Unmute the Rin port if it was muted. */ + if ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + /* Unmute the Sin port if it was muted. */ + if ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usSinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usSinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_E0; + + pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + /*------------------------------------------------------------------------------*/ + + /* Synch all the buffer playout field.*/ + if ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE ) + { + Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); + + BufferPlayoutStop.ulChannelHndl = cOCT6100_INVALID_HANDLE; + BufferPlayoutStop.fStopCleanly = FALSE; + + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + pChanEntry->usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + pChanEntry->usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + + + + + /* Free all resources reserved for extended tone detection.*/ + if ( pChanEntry->fEnableExtToneDetection == TRUE ) + { + /*------------------------------------------------------------------------------*/ + /* Deactivate the ECHO control memory entry of the extended channel.*/ + + /* Set the input Echo control entry to unused.*/ + WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( pChanEntry->usExtToneChanIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*------------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------------*/ + /* Remove the mixer event used to copy the RIN signal to the SIN port of the extended + channel.*/ + + /* Clear the Copy event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usExtToneMixerIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usExtToneMixerIndex, + cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*------------------------------------------------------------------------------*/ + + } + + /*------------------------------------------------------------------------------*/ + /* Reset PGSP */ + + WriteParams.ulWriteAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + WriteParams.usWriteData = 0x0800; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*------------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------------*/ + /* Clear the VQE memory. */ + + SmearParams.ulWriteAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst + 0x20; + SmearParams.usWriteData = 0x0000; + SmearParams.ulWriteLength = 2; + + mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*------------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------------*/ + /* Clear the AF information memory. */ + + SmearParams.ulWriteAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( pChanEntry->usEchoMemIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + SmearParams.usWriteData = 0x0000; + SmearParams.ulWriteLength = 12; + + mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*------------------------------------------------------------------------------*/ + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseChannelResources + +Description: Release and clear the API entry associated to the echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usChannelIndex Index of the echo cancellation channel in the API list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseChannelResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChannelIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_CHANNEL_TDM pTdmConfig; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + UINT32 ulResult; + UINT16 usCurrentEntry; + UINT32 ulTimeslot; + UINT32 ulStream; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChannelIndex ); + + /* Obtain local pointer to the TDM configurationof the channel */ + pTdmConfig = &pChanEntry->TdmConfig; + + /* Release the two TSI chariot memory entries.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usRinRoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_2; + + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_3; + + /* Now release the ECHO channel and control memory entries.*/ + ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, f_usChannelIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_4; + + /* Release the conversion resources.*/ + if ( pChanEntry->usRinRoutConversionMemIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usRinRoutConversionMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_B9; + + pChanEntry->usRinRoutConversionMemIndex = cOCT6100_INVALID_INDEX; + } + + if ( pChanEntry->usSinSoutConversionMemIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usSinSoutConversionMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_BA; + + pChanEntry->usSinSoutConversionMemIndex = cOCT6100_INVALID_INDEX; + } + + /*=========================================================================*/ + /* Release the TSST control memory entries if any were reserved.*/ + if ( pTdmConfig->usRinTimeslot != cOCT6100_UNASSIGNED) + { + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->usRinTimeslot, + pTdmConfig->usRinStream, + pTdmConfig->byRinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_5; + } + + if ( pTdmConfig->usSinTimeslot != cOCT6100_UNASSIGNED) + { + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->usSinTimeslot, + pTdmConfig->usSinStream, + pTdmConfig->bySinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_6; + } + + /*=======================================================================*/ + /* Release all the TSSTs associated to the ROUT port of this channel. */ + if ( pTdmConfig->usRoutTimeslot != cOCT6100_UNASSIGNED) + { + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->usRoutTimeslot, + pTdmConfig->usRoutStream, + pTdmConfig->byRoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_7; + } + + /* Now release the Broadcast TSSTs. */ + usCurrentEntry = pTdmConfig->usRoutBrdcastTsstFirstEntry; + while( usCurrentEntry != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); + + ulTimeslot = pTsstEntry->usTsstValue >> 5; + ulStream = pTsstEntry->usTsstValue & 0x1F; + + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + ulTimeslot, + ulStream, + cOCT6100_NUMBER_TSSTS_1, + cOCT6100_OUTPUT_TSST, + usCurrentEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_8; + + /* Move to the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + + /* Invalidate the current entry.*/ + pTsstEntry->usTsstMemoryIndex = 0xFFFF; + pTsstEntry->usTsstValue = 0xFFFF; + pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Release all the TSSTs associated to the SOUT port of this channel. */ + if ( pTdmConfig->usSoutTimeslot != cOCT6100_UNASSIGNED) + { + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pTdmConfig->usSoutTimeslot, + pTdmConfig->usSoutStream, + pTdmConfig->bySoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_9; + } + + /* Now release the Broadcast TSSTs. */ + usCurrentEntry = pTdmConfig->usSoutBrdcastTsstFirstEntry; + while( usCurrentEntry != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); + + ulTimeslot = pTsstEntry->usTsstValue >> 5; + ulStream = pTsstEntry->usTsstValue & 0x1F; + + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + ulTimeslot, + ulStream, + cOCT6100_NUMBER_TSSTS_1, + cOCT6100_OUTPUT_TSST, + usCurrentEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A; + + /* Move to the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + + /* Invalidate the current entry.*/ + pTsstEntry->usTsstMemoryIndex = 0xFFFF; + pTsstEntry->usTsstValue = 0xFFFF; + pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; + } + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the dependency of the phasing TSST if one is associated to the chanel.*/ + + if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + tPOCT6100_API_PHASING_TSST pPhasingEntry; + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, pChanEntry->usPhasingTsstIndex ); + + pPhasingEntry->usDependencyCnt--; + } + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Release any resources reserved for the extended tone detection.*/ + + if ( pChanEntry->fEnableExtToneDetection == TRUE ) + { + tPOCT6100_API_CHANNEL pExtToneChanEntry; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pExtToneChanEntry, pChanEntry->usExtToneChanIndex ); + + /* Release the ECHO channel and control memory entries.*/ + ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, pChanEntry->usExtToneChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_C1; + + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtToneTsiIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_C2; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usExtToneMixerIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_C3; + + /* Now release the channel entry */ + pExtToneChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; + pExtToneChanEntry->fReserved = FALSE; + + /* Set the current entry to disable, just in case.*/ + pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; + } + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Update the channel's list entry. */ + + /* Clear the NLP dword array. */ + Oct6100UserMemSet( pChanEntry->aulNlpConfDword, 0, sizeof( pChanEntry->aulNlpConfDword ) ); + + /* Clear the echo operation mode. */ + pChanEntry->byEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; + + /* Mark the channel as closed. */ + pChanEntry->fReserved = FALSE; + pChanEntry->byEntryOpenCnt++; + + /* Decrement the number of channel open.*/ + f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels--; + + /*=======================================================================*/ + + return cOCT6100_ERR_OK; + +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelModifySer + +Description: Modify an echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelModify Pointer to channel configuration structure. The handle + identifying the buffer in all future function calls is + returned in this structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelModifySer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) +{ + UINT16 usChanIndex; + UINT32 ulResult; + UINT16 usNewRinTsstIndex; + UINT16 usNewSinTsstIndex; + UINT16 usNewRoutTsstIndex; + UINT16 usNewSoutTsstIndex; + UINT8 fSinSoutCodecActive = FALSE; + UINT8 fRinRoutCodecActive = FALSE; + UINT16 usNewPhasingTsstIndex; + tOCT6100_CHANNEL_OPEN TempChanOpen; + + /* Check the user's configuration of the echo cancellation channel for errors. */ + ulResult = Oct6100ApiCheckChannelModify( f_pApiInstance, + f_pChannelModify, + &TempChanOpen, + &usNewPhasingTsstIndex, + &usChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the echo cancellation channel. */ + ulResult = Oct6100ApiModifyChannelResources( f_pApiInstance, + f_pChannelModify, + usChanIndex, + &usNewRinTsstIndex, + &usNewSinTsstIndex, + &usNewRoutTsstIndex, + &usNewSoutTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write all necessary structures to activate the echo cancellation channel. */ + ulResult = Oct6100ApiModifyChannelStructs( f_pApiInstance, + f_pChannelModify, + &TempChanOpen, + usChanIndex, + usNewPhasingTsstIndex, + &fSinSoutCodecActive, + &fRinRoutCodecActive, + usNewRinTsstIndex, + usNewSinTsstIndex, + usNewRoutTsstIndex, + usNewSoutTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new echo cancellation channels's entry in the ECHO channel list. */ + ulResult = Oct6100ApiModifyChannelEntry( f_pApiInstance, + f_pChannelModify, + &TempChanOpen, + usChanIndex, + usNewPhasingTsstIndex, + fSinSoutCodecActive, + fRinRoutCodecActive, + usNewRinTsstIndex, + usNewSinTsstIndex, + usNewRoutTsstIndex, + usNewSoutTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckChannelModify + +Description: Checks the user's echo cancellation channel modify structure for errors. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelModify Pointer to echo cancellation channel modify structure. +f_pTempChanOpen Pointer to a channel open structure. +f_pusNewPhasingTsstIndex Pointer to a new phasing TSST index within the API instance. +f_pusChanIndex Pointer to the channel index within the API instance channel list + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckChannelModify( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify, + IN tPOCT6100_CHANNEL_OPEN f_pTempChanOpen, + OUT PUINT16 f_pusNewPhasingTsstIndex, + OUT PUINT16 f_pusChanIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulResult; + UINT32 ulEntryOpenCnt; + UINT32 ulDecoderNumTssts; + + /* Check the provided handle. */ + if ( (f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelModify->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Check the general modify parameters. */ + + if ( f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && + f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) + return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; + + /* Check the 2100Hz echo disabling configuration.*/ + if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->fEnableToneDisabler != TRUE && + f_pChannelModify->fEnableToneDisabler != FALSE ) + return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; + + /* Check the disable tone detection flag. */ + if ( f_pChannelModify->fDisableToneDetection != TRUE && + f_pChannelModify->fDisableToneDetection != FALSE ) + return cOCT6100_ERR_CHANNEL_DISABLE_TONE_DETECTION; + + /* Check the stop buffer playout flag. */ + if ( f_pChannelModify->fStopBufferPlayout != TRUE && + f_pChannelModify->fStopBufferPlayout != FALSE ) + return cOCT6100_ERR_CHANNEL_STOP_BUFFER_PLAYOUT; + + /* Check the remove conference bridge participant flag. */ + if ( f_pChannelModify->fRemoveConfBridgeParticipant != TRUE && + f_pChannelModify->fRemoveConfBridgeParticipant != FALSE ) + return cOCT6100_ERR_CHANNEL_REMOVE_CONF_BRIDGE_PARTICIPANT; + + /* Check the remove broadcast timeslots flag. */ + if ( f_pChannelModify->fRemoveBroadcastTssts != TRUE && + f_pChannelModify->fRemoveBroadcastTssts != FALSE ) + return cOCT6100_ERR_CHANNEL_REMOVE_BROADCAST_TSSTS; + + if ( f_pChannelModify->fCodecConfigModified != TRUE && + f_pChannelModify->fCodecConfigModified != FALSE ) + return cOCT6100_ERR_CHANNEL_MODIFY_CODEC_CONFIG; + + if ( f_pChannelModify->fVqeConfigModified != TRUE && + f_pChannelModify->fVqeConfigModified != FALSE ) + return cOCT6100_ERR_CHANNEL_MODIFY_VQE_CONFIG; + + if ( f_pChannelModify->fTdmConfigModified != TRUE && + f_pChannelModify->fTdmConfigModified != FALSE ) + return cOCT6100_ERR_CHANNEL_MODIFY_TDM_CONFIG; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Verify if any law change was requested. If so reprogram all structures.*/ + + if (( f_pChannelModify->fTdmConfigModified == TRUE ) && + ( f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING )) + { + f_pChannelModify->fVqeConfigModified = TRUE; + f_pChannelModify->fCodecConfigModified = TRUE; + } + /*=======================================================================*/ + + ulResult = Oct6100ApiUpdateOpenStruct( f_pApiInstance, f_pChannelModify, f_pTempChanOpen, pChanEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* All further check will now be performed using the TempOpenChan structure in order + to reuse the checks written for the open channel structure.*/ + + + + /* Check the TDM config.*/ + if ( f_pChannelModify->fTdmConfigModified == TRUE ) + { + tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdm; + tPOCT6100_CHANNEL_OPEN_TDM pOpenTdm; + + pModifyTdm = &f_pChannelModify->TdmConfig; + pOpenTdm = &f_pTempChanOpen->TdmConfig; + + ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, + pOpenTdm ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if that Stream and Timeslot values are valid.*/ + + /* Check the RIN port.*/ + if ( f_pChannelModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; + + if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_RIN_STREAM; + + if ( pChanEntry->fBeingTapped == TRUE ) + { + /* Check that the Rin stream + timeslot are not being assigned. */ + if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_RIN_STREAM; + + if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; + } + } + + /* Check the SIN port.*/ + if ( f_pChannelModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; + + if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_SIN_STREAM; + + /* Check the ROUT port.*/ + if ( f_pChannelModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; + + if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_ROUT_STREAM; + + /* Check the SOUT port.*/ + if ( f_pChannelModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; + + if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + return cOCT6100_ERR_CHANNEL_SOUT_STREAM; + + /* Verify if the channel is currently part of a bidirectional channel, and if */ + /* so perform the required checks. */ + if ( pChanEntry->fBiDirChannel == TRUE ) + { + /* Check the ports that must remain unassigned.*/ + if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; + if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; + + /* Check that no PCM law change is requested.*/ + if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; + if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; + } + + /* If this channel is on a conference bridge, a few more things must be checked. */ + if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + { + /* If conferencing, law conversion cannot be applied. */ + /* This check is done only if both input and output ports are assigned. */ + if ( ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) + && ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) ) + { + /* Laws must be the same! */ + if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; + } + + /* Check for Sin. */ + if ( ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) + && ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) ) + { + /* Laws must be the same! */ + if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; + } + + /* Check if ADPCM is requested. */ + if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && + f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) + { + /* No ADPCM in a conference bridge! */ + return cOCT6100_ERR_CHANNEL_ENCODING_RATE; + } + + if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && + f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) + { + /* No ADPCM in a conference bridge! */ + return cOCT6100_ERR_CHANNEL_DECODING_RATE; + } + } + + if ( f_pTempChanOpen->CodecConfig.ulEncoderPort == cOCT6100_NO_ENCODING || + f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_NO_DECODING ) + { + /* Make sure no law conversion is attempted since it is not supported by the device.*/ + if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; + if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; + } + + if ( pChanEntry->fEnableExtToneDetection == TRUE && + f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; + + /* A few special checks must be done if the configuration is to be applied */ + /* to all opened channels. */ + if ( f_pChannelModify->fApplyToAllChannels == TRUE ) + { + /* When the configuration to be applied is for all channels, */ + /* check that the stream and timeslot parameters are not being assigned. */ + + /* Check the Rout port. */ + if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Check that the Rout ports is being unassigned. */ + if ( f_pTempChanOpen->TdmConfig.ulRoutStream != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_ROUT_STREAM_UNASSIGN; + if ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT_UNASSIGN; + } + + /* Check the Rin port. */ + if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Check that the Rin ports is being unassigned. */ + if ( f_pTempChanOpen->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_RIN_STREAM_UNASSIGN; + if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT_UNASSIGN; + } + + /* Check the Sout port. */ + if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Check that the Sout ports is being unassigned. */ + if ( f_pTempChanOpen->TdmConfig.ulSoutStream != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_SOUT_STREAM_UNASSIGN; + if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT_UNASSIGN; + } + + /* Check the Sin port. */ + if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Check that the Sin ports is being unassigned. */ + if ( f_pTempChanOpen->TdmConfig.ulSinStream != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_SIN_STREAM_UNASSIGN; + if ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) + return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT_UNASSIGN; + } + } + } + + /* Check the VQE config.*/ + if ( f_pChannelModify->fVqeConfigModified == TRUE ) + { + ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, + &f_pTempChanOpen->VqeConfig, + f_pTempChanOpen->fEnableToneDisabler ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Verify if the echo operation mode selected can be applied. */ + if ( ( f_pTempChanOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + && ( f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) ) + return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; + + /* Check the Codec config.*/ + if ( f_pChannelModify->fCodecConfigModified == TRUE ) + { + if ( f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulRinNumTssts; + else /* f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulSinNumTssts; + + ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, + &f_pTempChanOpen->CodecConfig, + ulDecoderNumTssts, + f_pusNewPhasingTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + + /* make sure that if silence suppression is activated, the NLP is enabled.*/ + if ( f_pTempChanOpen->CodecConfig.fEnableSilenceSuppression == TRUE && f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) + return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; + + /* Verify if the channel is currently part of a bidirectional channel, and if so perform + the required checks.*/ + if ( pChanEntry->fBiDirChannel == TRUE ) + { + /* Check the ports that must remain unassigned.*/ + if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && + f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_CHANNEL_ENCODING_RATE; + + if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && + f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_CHANNEL_DECODING_RATE; + } + + } + /*=======================================================================*/ + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiModifyChannelResources + +Description: Reserves any new resources needed for the channel +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelModify Pointer to echo cancellation channel configuration structure. +f_usChanIndex Allocated entry in ECHO channel list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiModifyChannelResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, + IN UINT16 f_usChanIndex, + OUT PUINT16 f_pusNewRinTsstIndex, + OUT PUINT16 f_pusNewSinTsstIndex, + OUT PUINT16 f_pusNewRoutTsstIndex, + OUT PUINT16 f_pusNewSoutTsstIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + + tPOCT6100_API_CHANNEL_TDM pApiTdmConf; + tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdmConf; + + UINT32 ulResult = cOCT6100_ERR_OK; + UINT32 ulTempVar = cOCT6100_ERR_OK; + UINT32 ulFreeMixerEventCnt; + + BOOL fRinReleased = FALSE; + BOOL fSinReleased = FALSE; + BOOL fRoutReleased = FALSE; + BOOL fSoutReleased = FALSE; + + BOOL fRinReserved = FALSE; + BOOL fSinReserved = FALSE; + BOOL fRoutReserved = FALSE; + BOOL fSoutReserved = FALSE; + + BOOL fReserveRin = FALSE; + BOOL fReserveSin = FALSE; + BOOL fReserveRout = FALSE; + BOOL fReserveSout = FALSE; + + BOOL fRinRoutConversionMemReserved = FALSE; + BOOL fSinSoutConversionMemReserved = FALSE; + + + UINT32 ulRinNumTssts = 1; + UINT32 ulSinNumTssts = 1; + UINT32 ulRoutNumTssts = 1; + UINT32 ulSoutNumTssts = 1; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_CHANNEL_MODIFY structure. */ + pModifyTdmConf = &f_pChannelModify->TdmConfig; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_API_CHANNEL structure. */ + pApiTdmConf = &pChanEntry->TdmConfig; + + /*===============================================================================*/ + /* Modify TSST resources if required.*/ + if ( f_pChannelModify->fTdmConfigModified == TRUE ) + { + /* First release any entry that need to be released.*/ + if ( ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) + { + if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Release the previously reserved entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pChanEntry->TdmConfig.usRinTimeslot, + pChanEntry->TdmConfig.usRinStream, + pChanEntry->TdmConfig.byRinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRinReleased = TRUE; + } + } + + fReserveRin = TRUE; + } + + /* Release SIN port.*/ + if ( ( ulResult == cOCT6100_ERR_OK ) + && ( ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) ) + { + if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Release the previously reserved entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pChanEntry->TdmConfig.usSinTimeslot, + pChanEntry->TdmConfig.usSinStream, + pChanEntry->TdmConfig.bySinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSinReleased = TRUE; + } + } + + fReserveSin = TRUE; + } + + /* Release ROUT port.*/ + if ( ( ulResult == cOCT6100_ERR_OK ) + && ( ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) ) + { + if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Release the previously reserved entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pChanEntry->TdmConfig.usRoutTimeslot, + pChanEntry->TdmConfig.usRoutStream, + pChanEntry->TdmConfig.byRoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRoutReleased = TRUE; + } + } + + fReserveRout = TRUE; + } + + /* Release the SOUT port.*/ + if ( ( ulResult == cOCT6100_ERR_OK ) + && ( ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) ) + { + if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Release the previously reserved entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + pChanEntry->TdmConfig.usSoutTimeslot, + pChanEntry->TdmConfig.usSoutStream, + pChanEntry->TdmConfig.bySoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSoutReleased = TRUE; + } + } + + fReserveSout = TRUE; + } + + /* Now reserve any new entry required.*/ + + /* Modify RIN port.*/ + if ( ( fReserveRin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) + { + if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_UNASSIGNED ) + { + /* Check what number of TSSTs should be reserved this time. */ + if ( pModifyTdmConf->ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ulRinNumTssts = pApiTdmConf->byRinNumTssts; + } + else /* if ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* New number of TSSTs. */ + ulRinNumTssts = pModifyTdmConf->ulRinNumTssts; + } + + if ( pModifyTdmConf->ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Reserve the new number of TSSTs. */ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pApiTdmConf->usRinTimeslot, + pApiTdmConf->usRinStream, + ulRinNumTssts, + cOCT6100_INPUT_TSST, + f_pusNewRinTsstIndex, + NULL ); + } + else /* if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* Reserve the new TSST.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pModifyTdmConf->ulRinTimeslot, + pModifyTdmConf->ulRinStream, + ulRinNumTssts, + cOCT6100_INPUT_TSST, + f_pusNewRinTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRinReserved = TRUE; + } + } + } + else + { + *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; + } + + /* Modify SIN port.*/ + if ( ( fReserveSin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) + { + if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_UNASSIGNED ) + { + /* Check what number of TSSTs should be reserved this time. */ + if ( pModifyTdmConf->ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ulSinNumTssts = pApiTdmConf->bySinNumTssts; + } + else /* if ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* New number of TSSTs. */ + ulSinNumTssts = pModifyTdmConf->ulSinNumTssts; + } + + if ( pModifyTdmConf->ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Reserve the new number of TSSTs. */ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pApiTdmConf->usSinTimeslot, + pApiTdmConf->usSinStream, + ulSinNumTssts, + cOCT6100_INPUT_TSST, + f_pusNewSinTsstIndex, + NULL ); + } + else /* if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* Reserve the new TSST.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pModifyTdmConf->ulSinTimeslot, + pModifyTdmConf->ulSinStream, + ulSinNumTssts, + cOCT6100_INPUT_TSST, + f_pusNewSinTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSinReserved = TRUE; + } + } + } + else + { + *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; + } + + /* Modify ROUT port.*/ + if ( ( fReserveRout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) + { + if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_UNASSIGNED ) + { + /* Check what number of TSSTs should be reserved this time. */ + if ( pModifyTdmConf->ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ulRoutNumTssts = pApiTdmConf->byRoutNumTssts; + } + else /* if ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* New number of TSSTs. */ + ulRoutNumTssts = pModifyTdmConf->ulRoutNumTssts; + } + + if ( pModifyTdmConf->ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Reserve the new number of TSSTs. */ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pApiTdmConf->usRoutTimeslot, + pApiTdmConf->usRoutStream, + ulRoutNumTssts, + cOCT6100_OUTPUT_TSST, + f_pusNewRoutTsstIndex, + NULL ); + } + else /* if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* Reserve the new TSST.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pModifyTdmConf->ulRoutTimeslot, + pModifyTdmConf->ulRoutStream, + ulRoutNumTssts, + cOCT6100_OUTPUT_TSST, + f_pusNewRoutTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRoutReserved = TRUE; + } + } + } + else + { + *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; + } + + /* Modify SOUT port.*/ + if ( ( fReserveSout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) + { + if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_UNASSIGNED ) + { + /* Check what number of TSSTs should be reserved this time. */ + if ( pModifyTdmConf->ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ulSoutNumTssts = pApiTdmConf->bySoutNumTssts; + } + else /* if ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* New number of TSSTs. */ + ulSoutNumTssts = pModifyTdmConf->ulSoutNumTssts; + } + + if ( pModifyTdmConf->ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* Reserve the new number of TSSTs. */ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pApiTdmConf->usSoutTimeslot, + pApiTdmConf->usSoutStream, + ulSoutNumTssts, + cOCT6100_OUTPUT_TSST, + f_pusNewSoutTsstIndex, + NULL ); + } + else /* if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ + { + /* Reserve the new TSST.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + pModifyTdmConf->ulSoutTimeslot, + pModifyTdmConf->ulSoutStream, + ulSoutNumTssts, + cOCT6100_OUTPUT_TSST, + f_pusNewSoutTsstIndex, + NULL ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSoutReserved = TRUE; + } + } + } + else + { + *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; + } + + + } + + if ( f_pChannelModify->fCodecConfigModified == TRUE ) + { + if ( ulResult == cOCT6100_ERR_OK && + pChanEntry->usRinRoutConversionMemIndex == cOCT6100_INVALID_INDEX && + ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT || + f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ) + { + /* Reserve an ADPCM memory block.*/ + ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usRinRoutConversionMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fRinRoutConversionMemReserved = TRUE; + } + } + + if ( ulResult == cOCT6100_ERR_OK && + pChanEntry->usSinSoutConversionMemIndex == cOCT6100_INVALID_INDEX && + ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT || + f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) ) + { + /* Reserve an ADPCM memory block.*/ + ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usSinSoutConversionMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fSinSoutConversionMemReserved = TRUE; + } + } + } + + + /*===============================================================================*/ + /* Check if there are a couple of mixer events available for us. */ + + if ( ulResult == cOCT6100_ERR_OK ) + { + UINT32 ulMixerEventCntNeeded = 0; + + /* Calculate how many mixer events are needed. */ + if ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + { + /* If the channel is in bidir mode, do not create the Rin silence event!!! */ + if ( pChanEntry->fBiDirChannel == FALSE ) + { + if ( ( *f_pusNewRinTsstIndex == cOCT6100_INVALID_INDEX ) + && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) + ulMixerEventCntNeeded++; + } + } + + if ( ( *f_pusNewSinTsstIndex == cOCT6100_INVALID_INDEX ) + && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) + { + ulMixerEventCntNeeded++; + } + + /* If at least 1 mixer event is needed, check if those are available. */ + if ( ulMixerEventCntNeeded != 0 ) + { + ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); + if ( ulResult == cOCT6100_ERR_OK ) + { + /* The API might need more mixer events if the ports have to be muted. */ + /* Check if these are available. */ + if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) + { + ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; + } + } + } + } + + /*===============================================================================*/ + + /* Verify if an error occured. */ + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Release any resources newly reserved.*/ + if ( fRinReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pModifyTdmConf->ulRinTimeslot, + pModifyTdmConf->ulRinStream, + ulRinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the SIN port.*/ + if ( fSinReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pModifyTdmConf->ulSinTimeslot, + pModifyTdmConf->ulSinStream, + ulSinNumTssts, + cOCT6100_INPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the ROUT port.*/ + if ( fRoutReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pModifyTdmConf->ulRoutTimeslot, + pModifyTdmConf->ulRoutStream, + ulRoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the SOUT port.*/ + if ( fSoutReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, + pModifyTdmConf->ulSoutTimeslot, + pModifyTdmConf->ulSoutStream, + ulSoutNumTssts, + cOCT6100_OUTPUT_TSST, + cOCT6100_INVALID_INDEX ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* Now make sure any resources released gets reserved back again.*/ + + /* For the RIN port.*/ + if ( fRinReleased == TRUE ) + { + /* Reserve the new TSST.*/ + ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, + pChanEntry->TdmConfig.usRinTimeslot, + pChanEntry->TdmConfig.usRinStream, + pChanEntry->TdmConfig.byRinNumTssts, + cOCT6100_INPUT_TSST, + &pChanEntry->usRinTsstIndex, + NULL ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the SIN port.*/ + if ( fSinReleased == TRUE ) + { + /* Reserve the new TSST.*/ + ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, + pChanEntry->TdmConfig.usSinTimeslot, + pChanEntry->TdmConfig.usSinStream, + pChanEntry->TdmConfig.bySinNumTssts, + cOCT6100_INPUT_TSST, + &pChanEntry->usSinTsstIndex, + NULL ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the ROUT port.*/ + if ( fRoutReleased == TRUE ) + { + /* Reserve the new TSST.*/ + ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, + pChanEntry->TdmConfig.usRoutTimeslot, + pChanEntry->TdmConfig.usRoutStream, + pChanEntry->TdmConfig.byRoutNumTssts, + cOCT6100_OUTPUT_TSST, + &pChanEntry->usRoutTsstIndex, + NULL ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* For the SOUT port.*/ + if ( fSoutReleased == TRUE ) + { + /* Reserve the new TSST.*/ + ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, + pChanEntry->TdmConfig.usSoutTimeslot, + pChanEntry->TdmConfig.usSoutStream, + pChanEntry->TdmConfig.bySoutNumTssts, + cOCT6100_OUTPUT_TSST, + &pChanEntry->usSoutTsstIndex, + NULL ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* Release the conversion memories if they were reserved.*/ + if ( fRinRoutConversionMemReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, + pChanEntry->usRinRoutConversionMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fSinSoutConversionMemReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, + pChanEntry->usSinSoutConversionMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /* Now return the error.*/ + return ulResult; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiModifyChannelStructs + +Description: Performs all the required structure writes to configure the + echo cancellation channel based on the new modifications. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelModify Pointer to echo cancellation channel configuration structure. +f_pChannelOpen Pointer to a structure used to store the multiple resources indexes. +f_usChanIndex Index of the channel within the API's channel list. +f_usNewPhasingTsstIndex Index of the new phasing TSST. +f_pfSinSoutCodecActive Pointer to the state of the SIN/SOUT codec. +f_pfRinRoutCodecActive Pointer to the state of the RIN/ROUT codec. +f_usNewRinTsstIndex New RIN TSST memory index. +f_usNewSinTsstIndex New SIN TSST memory index. +f_usNewRoutTsstIndex New ROUT TSST memory index. +f_usNewSoutTsstIndex New SOUT TSST memory index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiModifyChannelStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usNewPhasingTsstIndex, + OUT PUINT8 f_pfSinSoutCodecActive, + OUT PUINT8 f_pfRinRoutCodecActive, + IN UINT16 f_usNewRinTsstIndex, + IN UINT16 f_usNewSinTsstIndex, + IN UINT16 f_usNewRoutTsstIndex, + IN UINT16 f_usNewSoutTsstIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_READ_PARAMS ReadParams; + tOCT6100_WRITE_PARAMS WriteParams; + tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; + tPOCT6100_API_CHANNEL_TDM pApiTdmConf; + tPOCT6100_API_CHANNEL_VQE pApiVqeConf; + + UINT32 ulResult; + UINT16 usReadData; + + UINT16 usSinTsstIndex; + UINT16 usRinTsstIndex; + + UINT32 ulToneConfIndex; + BOOL fClearPlayoutPointers = FALSE; + + BOOL fConversionEnabled = FALSE; + + + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ + pApiCodecConf = &pChanEntry->CodecConfig; + pApiTdmConf = &pChanEntry->TdmConfig; + pApiVqeConf = &pChanEntry->VqeConfig; + + /*=======================================================================*/ + /* Init the RIN and SIN TSST index */ + + usRinTsstIndex = pChanEntry->usRinTsstIndex; + usSinTsstIndex = pChanEntry->usSinTsstIndex; + + + /*==============================================================================*/ + /* Clear the TSST that will be release.*/ + + if ( f_pChannelModify->fTdmConfigModified == TRUE ) + { + /* Modify RIN port.*/ + if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Clear the previous entry */ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Modify SIN port.*/ + if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Clear the previous entry */ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Modify ROUT port.*/ + if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Clear the previous entry */ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Modify SOUT port.*/ + if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING) + { + if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Clear the previous entry */ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Now, Configure the Tsst control memory.*/ + + if ( f_pChannelModify->fTdmConfigModified == TRUE ) + { + /* Modify RIN port.*/ + if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + usRinTsstIndex = f_usNewRinTsstIndex; + + if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_usNewRinTsstIndex, + pChanEntry->usExtraRinTsiMemIndex, + f_pChannelOpen->TdmConfig.ulRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_usNewRinTsstIndex, + pChanEntry->usRinRoutTsiMemIndex, + f_pChannelOpen->TdmConfig.ulRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + if ( f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) + { + if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usRinTsstIndex, + pChanEntry->usExtraRinTsiMemIndex, + f_pChannelOpen->TdmConfig.ulRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else + { + if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usRinTsstIndex, + pChanEntry->usRinRoutTsiMemIndex, + f_pChannelOpen->TdmConfig.ulRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Modify SIN port.*/ + if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + usSinTsstIndex = f_usNewSinTsstIndex; + + if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_usNewSinTsstIndex, + pChanEntry->usExtraSinTsiMemIndex, + f_pChannelOpen->TdmConfig.ulSinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + f_usNewSinTsstIndex, + pChanEntry->usSinSoutTsiMemIndex, + f_pChannelOpen->TdmConfig.ulSinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + if ( f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && + f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) + { + if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usSinTsstIndex , + pChanEntry->usExtraSinTsiMemIndex, + f_pChannelOpen->TdmConfig.ulSinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else + { + if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usSinTsstIndex , + pChanEntry->usSinSoutTsiMemIndex, + f_pChannelOpen->TdmConfig.ulSinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Modify ROUT port.*/ + if ( ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) + { + if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + if ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* If this output port is not muted. */ + if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_usNewRoutTsstIndex, + pApiCodecConf->byAdpcmNibblePosition, + f_pChannelModify->TdmConfig.ulRoutNumTssts, + pChanEntry->usRinRoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else + { + /* If this output port is not muted. */ + if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_usNewRoutTsstIndex, + pApiCodecConf->byAdpcmNibblePosition, + pApiTdmConf->byRoutNumTssts, + pChanEntry->usRinRoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + } + + /* Modify SOUT port.*/ + if ( ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + || ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + ) + { + if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + if ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + /* If this output port is not muted. */ + if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_usNewSoutTsstIndex, + pApiCodecConf->byAdpcmNibblePosition, + f_pChannelModify->TdmConfig.ulSoutNumTssts, + pChanEntry->usSinSoutTsiMemIndex ); + + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else + { + /* If this output port is not muted. */ + if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) + { + /* Write the new entry now.*/ + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + f_usNewSoutTsstIndex, + pApiCodecConf->byAdpcmNibblePosition, + pApiTdmConf->bySoutNumTssts, + pChanEntry->usSinSoutTsiMemIndex ); + + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + } + + + + } + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Modify the Encoder/Decoder memory if required.*/ + + if ( f_pChannelModify->fCodecConfigModified == TRUE ) + { + UINT32 ulCompType = 0; + UINT16 usTempTsiMemIndex; + UINT16 usDecoderMemIndex; + UINT16 usEncoderMemIndex; + UINT32 ulPcmLaw; + UINT16 usPhasingIndex; + BOOL fModifyAdpcmMem = TRUE; + + /*==============================================================================*/ + /* Reprogram the Decoder memory.*/ + + if ( pChanEntry->CodecConfig.byDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + usDecoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; + } + else + { + usDecoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; + } + + if ( pChanEntry->CodecConfig.byEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + usEncoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; + } + else + { + usEncoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; + } + + if ( usDecoderMemIndex != cOCT6100_INVALID_INDEX ) + { + switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) + { + case cOCT6100_G711_64KBPS: + ulCompType = 0x8; + + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) + fModifyAdpcmMem = FALSE; + + /* Check if both ports are assigned. If not, no law conversion needed here.. */ + if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) + || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) + fModifyAdpcmMem = FALSE; + } + else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + { + if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) + fModifyAdpcmMem = FALSE; + + /* Check if both ports are assigned. If not, no law conversion needed here.. */ + if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) + || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) + fModifyAdpcmMem = FALSE; + } + + break; + case cOCT6100_G726_40KBPS: + ulCompType = 0x3; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_32KBPS: + ulCompType = 0x2; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_24KBPS: + ulCompType = 0x1; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_16KBPS: + ulCompType = 0x0; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_2C_ENCODED: + ulCompType = 0x4; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_3C_ENCODED: + ulCompType = 0x5; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_4C_ENCODED: + ulCompType = 0x6; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_ENCODED: + ulCompType = 0x9; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G726_ENCODED: + ulCompType = 0xA; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_2C_ENCODED: + ulCompType = 0xC; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_3C_ENCODED: + ulCompType = 0xD; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G711_G727_4C_ENCODED: + ulCompType = 0xE; + fConversionEnabled = TRUE; + break; + + default: + return cOCT6100_ERR_FATAL_D6; + } + + if ( fModifyAdpcmMem == TRUE ) + { + /* Set the chariot memory based on the selected port.*/ + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; + ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ + + /* Flag the entry as active.*/ + *f_pfRinRoutCodecActive = TRUE; + } + else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + { + usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; + ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ + + /* Flag the entry as active.*/ + *f_pfSinSoutCodecActive = TRUE; + } + + ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, + usDecoderMemIndex, + ulCompType, + usTempTsiMemIndex, + ulPcmLaw, + pApiCodecConf->byAdpcmNibblePosition ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, + usDecoderMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Flag the entry as deactivated.*/ + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + *f_pfRinRoutCodecActive = FALSE; + } + else + { + *f_pfSinSoutCodecActive = FALSE; + } + } + } + + /*==============================================================================*/ + + + + + /*==============================================================================*/ + /* Reprogram the Encoder memory.*/ + + if ( usEncoderMemIndex != cOCT6100_INVALID_INDEX ) + { + + fModifyAdpcmMem = TRUE; + + /* Set the chariot memory based on the selected port.*/ + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; + ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ + } + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; + ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ + } + + /* Set the phasing index .*/ + if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + usPhasingIndex = f_usNewPhasingTsstIndex; + else + usPhasingIndex = pChanEntry->usPhasingTsstIndex; + + switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) + { + case cOCT6100_G711_64KBPS: + if ( ulPcmLaw == cOCT6100_PCM_U_LAW ) + ulCompType = 0x4; + else /* ulPcmLaw == cOCT6100_PCM_A_LAW */ + ulCompType = 0x5; + + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) + fModifyAdpcmMem = FALSE; + + /* Check if both ports are assigned. If not, no law conversion needed here.. */ + if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) + || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) + fModifyAdpcmMem = FALSE; + } + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) + fModifyAdpcmMem = FALSE; + + /* Check if both ports are assigned. If not, no law conversion needed here.. */ + if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) + || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) + fModifyAdpcmMem = FALSE; + } + break; + case cOCT6100_G726_40KBPS: + ulCompType = 0x3; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_32KBPS: + ulCompType = 0x2; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_24KBPS: + ulCompType = 0x1; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G726_16KBPS: + ulCompType = 0x0; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_4_1: + ulCompType = 0xD; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_3_2: + ulCompType = 0xA; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_40KBPS_2_3: + ulCompType = 0x6; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_4_0: + ulCompType = 0xE; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_3_1: + ulCompType = 0xB; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_32KBPS_2_2: + ulCompType = 0x7; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_24KBPS_3_0: + ulCompType = 0xC; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_24KBPS_2_1: + ulCompType = 0x8; + fConversionEnabled = TRUE; + break; + + case cOCT6100_G727_16KBPS_2_0: + ulCompType = 0x9; + fConversionEnabled = TRUE; + break; + + default: + return cOCT6100_ERR_FATAL_D7; + } + + if ( fModifyAdpcmMem == TRUE ) + { + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + *f_pfRinRoutCodecActive = TRUE; + } + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + *f_pfSinSoutCodecActive = TRUE; + } + + ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, + usEncoderMemIndex, + ulCompType, + usTempTsiMemIndex, + f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, + pApiCodecConf->byAdpcmNibblePosition, + usPhasingIndex, + f_pChannelOpen->CodecConfig.ulPhasingType, + f_pChannelOpen->CodecConfig.ulPhase ); + + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, + usEncoderMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + *f_pfRinRoutCodecActive = FALSE; + } + else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + *f_pfSinSoutCodecActive = FALSE; + } + } + } + + /*==============================================================================*/ + } + + + + + /*==============================================================================*/ + /* Modify the VQE parameter if required.*/ + + if ( ( f_pChannelModify->fVqeConfigModified == TRUE ) + || ( (UINT8)f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) + || ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) + { + ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, + &f_pChannelOpen->VqeConfig, + f_pChannelOpen, + f_usChanIndex, + pChanEntry->usEchoMemIndex, + FALSE, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*==============================================================================*/ + /* Modify the Echo memory if required.*/ + if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || + f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, + &f_pChannelOpen->TdmConfig, + f_pChannelOpen, + pChanEntry->usEchoMemIndex, + pChanEntry->usRinRoutTsiMemIndex, + pChanEntry->usSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Synch all the buffer playout field if needed by echo operation mode. */ + /* Note that Oct6100ApiWriteVqeMemory does not clear the playout pointers */ + /* since the flag is set to FALSE. */ + if ( ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE ) + && ( ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) + || ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ) ) + { + /* Buffer playout must be stopped. */ + fClearPlayoutPointers = TRUE; + } + } + + /*==============================================================================*/ + /* Modify the Mixer events if law changes are requested. */ + + if ( pChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX && + f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Modify the value according to the new law.*/ + if ( f_pChannelModify->TdmConfig.ulSinPcmLaw == cOCT6100_PCM_A_LAW ) + WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); + else + WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); + + /* Write back the new value.*/ + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + if ( pChanEntry->usSoutCopyEventIndex != cOCT6100_INVALID_INDEX && + f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Modify the value according to the new law.*/ + if ( f_pChannelModify->TdmConfig.ulSoutPcmLaw == cOCT6100_PCM_A_LAW ) + WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); + else + WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); + + /* Write back the new value.*/ + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*==============================================================================*/ + /* Mute channel if required, this is done on a port basis */ + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, + f_usChanIndex, + usRinTsstIndex, + usSinTsstIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + /* Completely disable tone detection? */ + if ( f_pChannelModify->fDisableToneDetection == TRUE ) + { + /* Check if tone detection has been enabled on this channel. */ + for ( ulToneConfIndex = 0; ulToneConfIndex < ( sizeof( pChanEntry->aulToneConf ) / sizeof(UINT32) ); ulToneConfIndex ++ ) + { + /* Check if some tone has been activated on this channel. */ + if ( pChanEntry->aulToneConf[ ulToneConfIndex ] != 0 ) + { + tOCT6100_TONE_DETECTION_DISABLE ToneDetectDisable; + + /* Call the default function to make sure all parameters are assigned default values. */ + ulResult = Oct6100ToneDetectionDisableDef( &ToneDetectDisable ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Form channel handle. */ + ToneDetectDisable.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* Disable all tones activated on this channel. */ + ToneDetectDisable.fDisableAll = TRUE; + + /* Call tone detection serialized function. */ + ulResult = Oct6100ToneDetectionDisableSer( f_pApiInstance, &ToneDetectDisable ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Get out of the loop, tone detection has been disabled! */ + break; + } + } + } + + /* Hard-stop buffer playout? */ + if ( f_pChannelModify->fStopBufferPlayout == TRUE ) + { + /* Check if playout has been started on the Rout port. */ + if ( ( pChanEntry->fRinBufPlaying == TRUE ) || ( pChanEntry->fRinBufAdded == TRUE ) ) + { + tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; + + /* Call the default function to make sure all parameters are assigned default values. */ + ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Hard stop request. */ + PlayoutStop.fStopCleanly = FALSE; + + /* Form channel handle. */ + PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* For the Rout port. */ + PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + + /* Call buffer playout stop serialized function. */ + ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + /* The chip might still be playing a last buffer. Make sure it hard-stops! */ + fClearPlayoutPointers = TRUE; + } + + /* Check if playout has been started on the Sout port. */ + if ( ( pChanEntry->fSoutBufPlaying == TRUE ) || ( pChanEntry->fSoutBufAdded == TRUE ) ) + { + tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; + + /* Call the default function to make sure all parameters are assigned default values. */ + ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Hard stop request. */ + PlayoutStop.fStopCleanly = FALSE; + + /* Form channel handle. */ + PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* For the Rout port. */ + PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; + + /* Call buffer playout stop serialized function. */ + ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + /* The chip might still be playing a last buffer. Make sure it hard-stops! */ + fClearPlayoutPointers = TRUE; + } + } + + /* Remove participant from bridge? */ + if ( f_pChannelModify->fRemoveConfBridgeParticipant == TRUE ) + { + /* Check if this channel is on a bridge. */ + if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + { + /* Channel is on a bridge, remove it. */ + tOCT6100_CONF_BRIDGE_CHAN_REMOVE BridgeChanRemove; + + /* Call the default function to make sure all parameters are assigned default values. */ + ulResult = Oct6100ConfBridgeChanRemoveDef( &BridgeChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Form channel handle. */ + BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* Do not remove all channels, only the one specified. */ + BridgeChanRemove.fRemoveAll = FALSE; + + /* No need to assign conference bridge handle, the remove function will figure it out. */ + + /* Call conference bridge channel remove serialized function. */ + ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY ) + { + tPOCT6100_API_CHANNEL pTapChanEntry; + + /* Get a pointer to the tap channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapChanEntry, pChanEntry->usTapChanIndex ) + + /* Form tap channel handle. */ + BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pTapChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | pChanEntry->usTapChanIndex; + + ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Re-form original channel handle. */ + BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + return ulResult; + } + } + } + } + + /* Remove all broadcast TSSTs? */ + if ( f_pChannelModify->fRemoveBroadcastTssts == TRUE ) + { + /* Check if broadcast TSSTs were used on the Rout port. */ + if ( pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) + { + tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; + + ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Form channel handle. */ + BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* Remove all broadcast TSSTs associated to the current channel. */ + BroadcastTsstRemove.fRemoveAll = TRUE; + + /* On the Rout port. */ + BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_ROUT; + + ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + + /* Check if broadcast TSSTs were used on the Sout port. */ + if ( pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) + { + tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; + + ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Form channel handle. */ + BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; + + /* Remove all broadcast TSSTs associated to the current channel. */ + BroadcastTsstRemove.fRemoveAll = TRUE; + + /* On the Sout port. */ + BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_SOUT; + + ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Check if have to make sure buffer playout is stopped. */ + if ( fClearPlayoutPointers == TRUE ) + { + tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; + + Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); + + BufferPlayoutStop.fStopCleanly = FALSE; + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + pChanEntry->usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + pChanEntry->usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiModifyChannelEntry + +Description: Updates the channel structure in the ECHO channel list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelModify Pointer to echo cancellation channel modify structure. +f_pChannelOpen Pointer to echo cancellation channel configuration structure. +f_usChanIndex Index of the channel within the API's channel list. +f_usNewPhasingTsstIndex Index of the new phasing TSST. +f_fSinSoutCodecActive State of the SIN/SOUT codec. +f_fRinRoutCodecActive State of the RIN/ROUT codec. +f_usNewRinTsstIndex New RIN TSST memory index. +f_usNewSinTsstIndex New SIN TSST memory index. +f_usNewRoutTsstIndex New ROUT TSST memory index. +f_usNewSoutTsstIndex New SOUT TSST memory index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiModifyChannelEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usNewPhasingTsstIndex, + IN UINT8 f_fSinSoutCodecActive, + IN UINT8 f_fRinRoutCodecActive, + IN UINT16 f_usNewRinTsstIndex, + IN UINT16 f_usNewSinTsstIndex, + IN UINT16 f_usNewRoutTsstIndex, + IN UINT16 f_usNewSoutTsstIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; + tPOCT6100_API_CHANNEL_TDM pApiTdmConf; + tPOCT6100_API_CHANNEL_VQE pApiVqeConf; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ + pApiCodecConf = &pChanEntry->CodecConfig; + pApiTdmConf = &pChanEntry->TdmConfig; + pApiVqeConf = &pChanEntry->VqeConfig; + + /*=======================================================================*/ + /* Copy the channel's general configuration. */ + + pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; + pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); + pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); + + /* Save the codec state.*/ + pChanEntry->fSinSoutCodecActive = (UINT8)( f_fSinSoutCodecActive & 0xFF ); + pChanEntry->fRinRoutCodecActive = (UINT8)( f_fRinRoutCodecActive & 0xFF ); + + /*=======================================================================*/ + /* Copy the channel's TDM configuration of all the modified fields. */ + + if ( f_pChannelModify->fTdmConfigModified == TRUE ) + { + pApiTdmConf->byRinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRinPcmLaw & 0xFF ); + pApiTdmConf->bySinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSinPcmLaw & 0xFF ); + pApiTdmConf->byRoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutPcmLaw & 0xFF ); + pApiTdmConf->bySoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutPcmLaw & 0xFF ); + + pApiTdmConf->byRinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRinNumTssts & 0xFF ); + pApiTdmConf->bySinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSinNumTssts & 0xFF ); + pApiTdmConf->byRoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutNumTssts & 0xFF ); + pApiTdmConf->bySoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutNumTssts & 0xFF ); + + if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + pApiTdmConf->usRinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRinStream & 0xFFFF ); + pApiTdmConf->usRinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRinTimeslot & 0xFFFF ); + pChanEntry->usRinTsstIndex = f_usNewRinTsstIndex; + } + else /* f_ulNewRinTsstIndex != cOCT6100_INVALID_INDEX */ + { + pApiTdmConf->usRinStream = cOCT6100_UNASSIGNED; + pApiTdmConf->usRinTimeslot = cOCT6100_UNASSIGNED; + pChanEntry->usRinTsstIndex = cOCT6100_INVALID_INDEX; + } + } + + if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + pApiTdmConf->usSinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSinStream & 0xFFFF ); + pApiTdmConf->usSinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSinTimeslot & 0xFFFF ); + pChanEntry->usSinTsstIndex = f_usNewSinTsstIndex; + } + else /* f_ulNewSinTsstIndex != cOCT6100_INVALID_INDEX */ + { + pApiTdmConf->usSinStream = cOCT6100_UNASSIGNED; + pApiTdmConf->usSinTimeslot = cOCT6100_UNASSIGNED; + pChanEntry->usSinTsstIndex = cOCT6100_INVALID_INDEX; + } + } + + if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + pApiTdmConf->usRoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutStream & 0xFFFF ); + pApiTdmConf->usRoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutTimeslot & 0xFFFF ); + pChanEntry->usRoutTsstIndex = f_usNewRoutTsstIndex; + } + else /* f_ulNewRoutTsstIndex != cOCT6100_INVALID_INDEX */ + { + pApiTdmConf->usRoutStream = cOCT6100_UNASSIGNED; + pApiTdmConf->usRoutTimeslot = cOCT6100_UNASSIGNED; + pChanEntry->usRoutTsstIndex = cOCT6100_INVALID_INDEX; + } + } + + if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + pApiTdmConf->usSoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutStream & 0xFFFF ); + pApiTdmConf->usSoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutTimeslot & 0xFFFF ); + pChanEntry->usSoutTsstIndex = f_usNewSoutTsstIndex; + } + else /* f_ulNewSoutTsstIndex != cOCT6100_INVALID_INDEX */ + { + pApiTdmConf->usSoutStream = cOCT6100_UNASSIGNED; + pApiTdmConf->usSoutTimeslot = cOCT6100_UNASSIGNED; + pChanEntry->usSoutTsstIndex = cOCT6100_INVALID_INDEX; + } + } + } + + /*=======================================================================*/ + /* Copy the channel's VQE configuration of all the modified fields. */ + + if ( f_pChannelModify->fVqeConfigModified == TRUE ) + { + pApiVqeConf->fEnableNlp = (UINT8)( f_pChannelOpen->VqeConfig.fEnableNlp & 0xFF ); + pApiVqeConf->byComfortNoiseMode = (UINT8)( f_pChannelOpen->VqeConfig.ulComfortNoiseMode & 0xFF ); + pApiVqeConf->fSinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval & 0xFF ); + pApiVqeConf->fRinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval & 0xFF ); + pApiVqeConf->fRinLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinLevelControl & 0xFF ); + pApiVqeConf->fSoutLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutLevelControl & 0xFF ); + pApiVqeConf->fRinAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl & 0xFF ); + pApiVqeConf->fSoutAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl & 0xFF ); + pApiVqeConf->fRinHighLevelCompensation = (UINT8)( f_pChannelOpen->VqeConfig.fRinHighLevelCompensation & 0xFF ); + + pApiVqeConf->fSoutAdaptiveNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction & 0xFF ); + pApiVqeConf->fSoutNoiseBleaching = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNoiseBleaching & 0xFF ); + pApiVqeConf->fSoutConferencingNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction & 0xFF ); + pApiVqeConf->chRinLevelControlGainDb = (INT8)( f_pChannelOpen->VqeConfig.lRinLevelControlGainDb & 0xFF ); + pApiVqeConf->chSoutLevelControlGainDb = (INT8)( f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb & 0xFF ); + pApiVqeConf->chRinAutomaticLevelControlTargetDb = (INT8)( f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb & 0xFF ); + pApiVqeConf->chSoutAutomaticLevelControlTargetDb = (INT8)( f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb & 0xFF ); + pApiVqeConf->chRinHighLevelCompensationThresholdDb = (INT8)( f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb & 0xFF ); + pApiVqeConf->fEnableTailDisplacement = (UINT8)( f_pChannelOpen->VqeConfig.fEnableTailDisplacement & 0xFF ); + pApiVqeConf->usTailDisplacement = (UINT16)( f_pChannelOpen->VqeConfig.ulTailDisplacement & 0xFFFF ); + pApiVqeConf->usTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulTailLength & 0xFFFF ); + pApiVqeConf->fAcousticEcho = (UINT8)( f_pChannelOpen->VqeConfig.fAcousticEcho & 0xFF ); + pApiVqeConf->fDtmfToneRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fDtmfToneRemoval & 0xFF ); + + pApiVqeConf->chDefaultErlDb = (INT8)( f_pChannelOpen->VqeConfig.lDefaultErlDb & 0xFF ); + pApiVqeConf->chAecDefaultErlDb = (INT8)( f_pChannelOpen->VqeConfig.lAecDefaultErlDb & 0xFF ); + pApiVqeConf->usAecTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulAecTailLength & 0xFFFF ); + pApiVqeConf->chAnrSnrEnhancementDb = (INT8)( f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb & 0xFF ); + pApiVqeConf->byAnrVoiceNoiseSegregation = (UINT8)( f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation & 0xFF ); + pApiVqeConf->usToneDisablerVqeActivationDelay = (UINT16)( f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay & 0xFFFF ); + pApiVqeConf->byNonLinearityBehaviorA = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA & 0xFF ); + pApiVqeConf->byNonLinearityBehaviorB = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB & 0xFF ); + pApiVqeConf->byDoubleTalkBehavior = (UINT8)( f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior & 0xFF ); + pApiVqeConf->bySoutAutomaticListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); + pApiVqeConf->bySoutNaturalListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb & 0xFF ); + pApiVqeConf->fSoutNaturalListenerEnhancement = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement & 0xFF ); + pApiVqeConf->fRoutNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fRoutNoiseReduction & 0xFF ); + pApiVqeConf->fEnableMusicProtection = (UINT8)( f_pChannelOpen->VqeConfig.fEnableMusicProtection & 0xFF ); + pApiVqeConf->fIdleCodeDetection = (UINT8)( f_pChannelOpen->VqeConfig.fIdleCodeDetection & 0xFF ); + } + + /*=======================================================================*/ + /* Copy the channel's CODEC configuration of all the modified fields. */ + if ( f_pChannelModify->fCodecConfigModified == TRUE ) + { + pApiCodecConf->byAdpcmNibblePosition = (UINT8)( f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition & 0xFF ); + pApiCodecConf->byEncoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulEncoderPort & 0xFF ); + pApiCodecConf->byEncodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulEncodingRate & 0xFF ); + pApiCodecConf->byDecoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulDecoderPort & 0xFF ); + pApiCodecConf->byDecodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulDecodingRate & 0xFF ); + pApiCodecConf->fEnableSilenceSuppression = (UINT8)( f_pChannelOpen->CodecConfig.fEnableSilenceSuppression & 0xFF ); + pApiCodecConf->byPhase = (UINT8)( f_pChannelOpen->CodecConfig.ulPhase & 0xFF ); + pApiCodecConf->byPhasingType = (UINT8)( f_pChannelOpen->CodecConfig.ulPhasingType & 0xFF ); + + /* Update the API phasing TSST structure */ + if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + tPOCT6100_API_PHASING_TSST pPhasingTsst; + + /* Release the previous phasing TSST if the channel was already bound to one.*/ + if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, pChanEntry->usPhasingTsstIndex ); + + pPhasingTsst->usDependencyCnt--; + } + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, f_usNewPhasingTsstIndex ); + + pPhasingTsst->usDependencyCnt++; + pChanEntry->usPhasingTsstIndex = f_usNewPhasingTsstIndex; + + } + } + + + + return cOCT6100_ERR_OK; +} + + + + + + + + + + + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelBroadcastTsstAddSer + +Description: Assign a TSST to one of the port of an echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstAdd Pointer to TSST assign structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelBroadcastTsstAddSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd ) +{ + UINT16 usChanIndex; + UINT16 usNewTsstIndex; + UINT16 usNewTsstEntry; + UINT32 ulResult; + + ulResult = Oct6100ApiCheckChanTsstAddParams( f_pApiInstance, f_pChannelTsstAdd, &usChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReserveTsstAddResources( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, &usNewTsstIndex, &usNewTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiWriteTsstAddStructs( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, usNewTsstIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiUpdateTsstAddChanEntry( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, usNewTsstIndex, usNewTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckChanTsstAddParams + +Description: Verify the validity of the tPOCT6100_CHANNEL_BROADCAST_TSST_ADD + structure. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. +f_pusChanIndex Pointer to a structure used to store the multiple resources indexes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckChanTsstAddParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, + OUT PUINT16 f_pusChanIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulResult; + UINT32 ulNumTssts = 1; + UINT32 ulEntryOpenCnt; + + /* Check the provided handle. */ + if ( (f_pChannelTsstAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelTsstAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelTsstAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + + /* validate the port parameter.*/ + if ( f_pChannelTsstAdd->ulPort != cOCT6100_CHANNEL_PORT_ROUT && + f_pChannelTsstAdd->ulPort != cOCT6100_CHANNEL_PORT_SOUT ) + return cOCT6100_ERR_CHANNEL_TSST_ADD_PORT; + + /* Get the required number of TSST based on the port.*/ + switch( f_pChannelTsstAdd->ulPort ) + { + case cOCT6100_CHANNEL_PORT_ROUT: + ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; + break; + case cOCT6100_CHANNEL_PORT_SOUT: + ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; + break; + default: + return cOCT6100_ERR_FATAL_B; + } + + /* Check the validity of the timeslot and stream. */ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + ulNumTssts, + f_pChannelTsstAdd->ulTimeslot, + f_pChannelTsstAdd->ulStream, + cOCT6100_OUTPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_TSST_ADD_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_TSST_ADD_STREAM; + } + else + { + return ulResult; + } + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveTsstAddResources + +Description: Reserve the entry for the new broadcast TSST. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. +f_usChanIndex Channel index within the API's channel list. +f_pusNewTsstIndex Pointer to the new TSST index within the API's TSST memory. +f_pusNewTsstEntry Pointer to the new TSST entry within the API's TSST list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveTsstAddResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, + IN UINT16 f_usChanIndex, + OUT PUINT16 f_pusNewTsstIndex, + OUT PUINT16 f_pusNewTsstEntry ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulResult; + UINT32 ulNumTssts = 1; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); + + switch( f_pChannelTsstAdd->ulPort ) + { + case cOCT6100_CHANNEL_PORT_ROUT: + ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; + break; + case cOCT6100_CHANNEL_PORT_SOUT: + ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; + break; + default: + return cOCT6100_ERR_FATAL_C; + } + + /* Reserve the new entry.*/ + ulResult = Oct6100ApiReserveTsst( f_pApiInstance, + f_pChannelTsstAdd->ulTimeslot, + f_pChannelTsstAdd->ulStream, + ulNumTssts, + cOCT6100_OUTPUT_TSST, + f_pusNewTsstIndex, + f_pusNewTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteTsstAddStructs + +Description: Configure the TSST control memory for the new TSST entry. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. +f_usChanIndex Channel index. +f_usNewTsstIndex Tsst index in the TSST control memory. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteTsstAddStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, + IN UINT16 f_usChanIndex, + IN UINT16 f_usNewTsstIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult = cOCT6100_ERR_OK; + UINT16 usTsiMemIndex; + UINT32 ulNumTssts = 1; + + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); + + switch( f_pChannelTsstAdd->ulPort ) + { + case cOCT6100_CHANNEL_PORT_ROUT: + usTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; + ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; + break; + case cOCT6100_CHANNEL_PORT_SOUT: + usTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; + ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; + break; + default: + return cOCT6100_ERR_FATAL_D; + } + + + /* Write the new entry now.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usNewTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST; + WriteParams.usWriteData |= (UINT16)( pChanEntry->CodecConfig.byAdpcmNibblePosition << cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET ); + WriteParams.usWriteData |= (UINT16)( (ulNumTssts - 1) << cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET ); + WriteParams.usWriteData |= (UINT16)( usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK ); + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateTsstAddChanEntry + +Description: Update the associated channel API entry to add the new broacast TSST. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. +f_usChanIndex Channel index. +f_usNewTsstIndex TSST index within the TSST control memory. +f_usNewTsstEntry TSST entry within the API TSST list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiUpdateTsstAddChanEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, + IN UINT16 f_usChanIndex, + IN UINT16 f_usNewTsstIndex, + IN UINT16 f_usNewTsstEntry ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, f_usNewTsstEntry ); + + /* Update the channel entry.*/ + if ( f_pChannelTsstAdd->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + /* Add the new TSST entry to the broadcast list.*/ + pTsstEntry->usNextEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; + pTsstEntry->usTsstMemoryIndex = (UINT16)f_usNewTsstIndex; + pTsstEntry->usTsstValue = (UINT16)( (f_pChannelTsstAdd->ulTimeslot << 5) | f_pChannelTsstAdd->ulStream ); + + /* Modify the first entry pointer.*/ + pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = f_usNewTsstEntry; + + /* Increment the number of broadcast TSST. */ + pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry++; + + } + else /* f_pChannelTsstAdd->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + /* Add the new TSST entry to the broadcast list.*/ + pTsstEntry->usNextEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; + pTsstEntry->usTsstMemoryIndex = (UINT16)f_usNewTsstIndex; + pTsstEntry->usTsstValue = (UINT16)( (f_pChannelTsstAdd->ulTimeslot << 5) | f_pChannelTsstAdd->ulStream ); + + /* Modify the first entry pointer.*/ + pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = f_usNewTsstEntry; + + /* Increment the number of broadcast TSST. */ + pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry++; + } + + return cOCT6100_ERR_OK; +} + + + + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelBroadcastTsstRemoveSer + +Description: Removes a broadcast TSST from one of the output port of an + echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstRemove Pointer to TSST remove structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelBroadcastTsstRemoveSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove) +{ + UINT16 usChanIndex; + UINT16 usTsstIndex; + UINT16 usTsstEntry; + UINT16 usPrevTsstEntry; + UINT32 ulResult; + + ulResult = Oct6100ApiAssertChanTsstRemoveParams( f_pApiInstance, f_pChannelTsstRemove, &usChanIndex, &usTsstIndex, &usTsstEntry, &usPrevTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiInvalidateTsstRemoveStructs( f_pApiInstance, usChanIndex, usTsstIndex, f_pChannelTsstRemove->ulPort, f_pChannelTsstRemove->fRemoveAll ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseTsstRemoveResources( f_pApiInstance, f_pChannelTsstRemove, usChanIndex, usTsstIndex, usTsstEntry, usPrevTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertChanTsstRemoveParams + +Description: Verify the validity of the tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE + structure. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. +f_pulChanIndex Pointer to a channel index. +f_pulNewTsstIndex Pointer to a TSST index within the TSST control memory. +f_pulNewTsstEntry Pointer to a TSST entry within the API TSST list. +f_pulPrevTsstEntry Pointer to the previous TSST entry. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertChanTsstRemoveParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, + OUT PUINT16 f_pusChanIndex, + OUT PUINT16 f_pusTsstIndex, + OUT PUINT16 f_pusTsstEntry, + OUT PUINT16 f_pusPrevTsstEntry ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + UINT32 ulResult; + UINT32 ulNumTssts = 1; + UINT32 ulEntryOpenCnt; + UINT16 usCurrentEntry; + UINT16 usTsstValue; + UINT16 usNumEntry; + + /* Check the provided handle. */ + if ( (f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelTsstRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + + /* validate the port parameter.*/ + if ( f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_ROUT && + f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_SOUT ) + return cOCT6100_ERR_CHANNEL_TSST_REMOVE_PORT; + + /* Verify that the requested entry is present in the channel's port broadcast TSST.*/ + if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; + usNumEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry; + } + else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; + usNumEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry; + } + + /* Verify if at least one TSST is present on the channel port.*/ + if ( usNumEntry == 0 ) + return cOCT6100_ERR_CHANNEL_TSST_REMOVE_NO_BROADCAST_TSST; + + /* Get the required number of TSST based on the port.*/ + switch( f_pChannelTsstRemove->ulPort ) + { + case cOCT6100_CHANNEL_PORT_ROUT: + ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; + break; + case cOCT6100_CHANNEL_PORT_SOUT: + ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; + break; + default: + return cOCT6100_ERR_FATAL_E; + } + + /* Initialize the TSST entry to invalid.*/ + *f_pusTsstEntry = cOCT6100_INVALID_INDEX; + *f_pusPrevTsstEntry = cOCT6100_INVALID_INDEX; + *f_pusTsstIndex = cOCT6100_INVALID_INDEX; + + if ( f_pChannelTsstRemove->fRemoveAll != TRUE ) + { + /* Check the validity of the timeslot and Stream.*/ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + ulNumTssts, + f_pChannelTsstRemove->ulTimeslot, + f_pChannelTsstRemove->ulStream, + cOCT6100_OUTPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_TSST_REMOVE_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_TSST_REMOVE_STREAM; + } + else + { + return ulResult; + } + } + + /* Set the TSST value based on the timeslot and stream value.*/ + usTsstValue = (UINT16)( (f_pChannelTsstRemove->ulTimeslot << 5) | f_pChannelTsstRemove->ulStream ); + + while( usCurrentEntry != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); + + if ( usTsstValue == pTsstEntry->usTsstValue ) + { + /* A match was found.*/ + *f_pusTsstEntry = usCurrentEntry; + *f_pusTsstIndex = pTsstEntry->usTsstMemoryIndex; + break; + } + + /* Move on to the next entry.*/ + *f_pusPrevTsstEntry = usCurrentEntry; + usCurrentEntry = pTsstEntry->usNextEntry; + } + + if ( *f_pusTsstEntry == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_TSST_REMOVE_INVALID_TSST; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiInvalidateTsstRemoveStructs + +Description: Invalidate the entry of the broadcast TSST. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usChanIndex Channel index. +f_usTsstIndex TSST index within the TSST control memory. +f_ulPort Channel port where the TSST are removed from. (only used if remove all == TRUE) +f_fRemoveAll Remove all flag. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiInvalidateTsstRemoveStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChanIndex, + IN UINT16 f_usTsstIndex, + IN UINT32 f_ulPort, + IN BOOL f_fRemoveAll ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + if ( f_fRemoveAll == FALSE ) + { + /* Deactivate the entry now.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else /* f_fRemoveAll == TRUE */ + { + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + UINT16 usTsstEntry; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); + + /* Clear all entry associated to the selected port.*/ + if ( f_ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + usTsstEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; + else + usTsstEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; + + do + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usTsstEntry ); + + /* Deactivate the entry now.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( ( pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + usTsstEntry = pTsstEntry->usNextEntry; + + } while ( usTsstEntry != cOCT6100_INVALID_INDEX ); + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseTsstRemoveResources + +Description: Release all API resources associated to the Removed TSST and + update the channel entry accordingly. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. +f_usChanIndex Channel index. +f_usTsstIndex TSST index within the TSST control memory. +f_usTsstEntry TSST entry within the API's TSST list. +f_usPrevTsstEntry Previous TSST entry within the API's TSST list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseTsstRemoveResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, + IN UINT16 f_usChanIndex, + IN UINT16 f_usTsstIndex, + IN UINT16 f_usTsstEntry, + IN UINT16 f_usPrevTsstEntry ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + tPOCT6100_API_TSST_ENTRY pPrevTsstEntry; + UINT16 usCurrentEntry; + UINT32 ulResult; + UINT32 ulTimeslot; + UINT32 ulStream; + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); + + if ( f_pChannelTsstRemove->fRemoveAll == FALSE ) + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, f_usTsstEntry ); + + /* Update the channel entry.*/ + if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + /* Check if the entry was the first in the list.*/ + if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) + { + pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; + } + else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ + { + /* Get a pointer to the previous entry.*/ + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); + pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; + } + + /* Decrement the number of entry.*/ + pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry--; + } + else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + /* Check if the entry was the first in the list.*/ + if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) + { + pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; + } + else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ + { + /* Get a pointer to the previous entry.*/ + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); + pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; + } + + /* Decrement the number of entry.*/ + pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry--; + } + + ulTimeslot = pTsstEntry->usTsstValue >> 5; + ulStream = pTsstEntry->usTsstValue & 0x1F; + + /* Release the entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + ulTimeslot, + ulStream, + cOCT6100_NUMBER_TSSTS_1, + cOCT6100_OUTPUT_TSST, + f_usTsstEntry ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else /* f_pChannelTsstRemove->fRemoveAll == TRUE */ + { + + /* Update the channel entry.*/ + if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; + else + usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; + + do + { + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); + + ulTimeslot = pTsstEntry->usTsstValue >> 5; + ulStream = pTsstEntry->usTsstValue & 0x1F; + + /* Release the entry.*/ + ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, + ulTimeslot, + ulStream, + cOCT6100_NUMBER_TSSTS_1, + cOCT6100_OUTPUT_TSST, + usCurrentEntry ); /* Release the entry.*/ + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + usCurrentEntry = pTsstEntry->usNextEntry; + + /* Clear the previous node.*/ + pTsstEntry->usTsstMemoryIndex = 0xFFFF; + pTsstEntry->usTsstValue = 0xFFFF; + pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; + + } while ( usCurrentEntry != cOCT6100_INVALID_INDEX ); + + /* Reset the channel status.*/ + if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; + pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; + } + else + { + pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; + pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; + } + } + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiChannelGetStatsSer + +Description: Serialized function that returns all the stats of the specified + channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelStats Pointer to a channel stats structure. +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiChannelGetStatsSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_STATS f_pChannelStats ) +{ + tOCT6100_READ_PARAMS ReadParams; + tOCT6100_READ_BURST_PARAMS BurstParams; + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_TSST_ENTRY pTsstEntry; + UINT32 ulEntryOpenCnt; + UINT16 usCurrentEntry; + UINT16 usTsstCount; + UINT32 ulBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulTempData; + UINT32 ulMask; + UINT16 usChanIndex; + UINT16 ausReadData[ 32 ]; + + BYTE byRinEnergyRaw; + BYTE bySinEnergyRaw; + BYTE bySoutEnergyRaw; + INT32 lSoutEnergyIndB; + BYTE byCnEnergyRaw; + UINT16 usEchoDelayInFrames; + UINT16 usErlRaw; + + UINT32 ulResult; + UINT16 usReadData; + + /* Get local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + BurstParams.pProcessContext = f_pApiInstance->pProcessContext; + + BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + BurstParams.pusReadData = ausReadData; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + /* Check the reset stats flag.*/ + if ( f_pChannelStats->fResetStats != TRUE && f_pChannelStats->fResetStats != FALSE ) + return cOCT6100_ERR_CHANNEL_STATS_RESET; + + /* Check the provided handle. */ + if ( cOCT6100_HNDL_TAG_CHANNEL != (f_pChannelStats->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + usChanIndex = (UINT16)( f_pChannelStats->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( usChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, usChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelStats->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + + /* Check the value of the max broadcast tsst.*/ + if ( f_pChannelStats->TdmConfig.ulMaxBroadcastTssts > cOCT6100_MAX_TSSTS ) + return cOCT6100_ERR_CHANNEL_GET_STATS_MAX_BROADCAST_TSST; + + if ( f_pChannelStats->TdmConfig.ulMaxBroadcastTssts != 0 ) + { + /* Check if memory was allocated by the user for the stream and timeslot values.*/ + if ( f_pChannelStats->TdmConfig.pulRoutBroadcastTimeslot == NULL ) + return cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_TIMESLOT; + + if ( f_pChannelStats->TdmConfig.pulRoutBroadcastStream == NULL ) + return cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_STREAM; + + if ( f_pChannelStats->TdmConfig.pulSoutBroadcastTimeslot == NULL ) + return cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_TIMESLOT; + + if ( f_pChannelStats->TdmConfig.pulSoutBroadcastStream == NULL ) + return cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_STREAM; + } + + /* Copy the general configuration.*/ + f_pChannelStats->ulUserChanId = pChanEntry->ulUserChanId; + f_pChannelStats->ulEchoOperationMode = pChanEntry->byEchoOperationMode; + f_pChannelStats->fEnableToneDisabler = pChanEntry->fEnableToneDisabler; + f_pChannelStats->ulMutePortsMask = pChanEntry->usMutedPorts; + f_pChannelStats->fEnableExtToneDetection = pChanEntry->fEnableExtToneDetection; + + + + /* Copy the TDM configuration.*/ + f_pChannelStats->TdmConfig.ulNumRoutBroadcastTssts = pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry; + f_pChannelStats->TdmConfig.ulNumSoutBroadcastTssts = pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry; + + f_pChannelStats->TdmConfig.ulSinNumTssts = pChanEntry->TdmConfig.bySinNumTssts; + f_pChannelStats->TdmConfig.ulSinTimeslot = pChanEntry->TdmConfig.usSinTimeslot; + f_pChannelStats->TdmConfig.ulSinStream = pChanEntry->TdmConfig.usSinStream; + f_pChannelStats->TdmConfig.ulSinPcmLaw = pChanEntry->TdmConfig.bySinPcmLaw; + + f_pChannelStats->TdmConfig.ulSoutNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; + f_pChannelStats->TdmConfig.ulSoutTimeslot = pChanEntry->TdmConfig.usSoutTimeslot; + f_pChannelStats->TdmConfig.ulSoutStream = pChanEntry->TdmConfig.usSoutStream; + f_pChannelStats->TdmConfig.ulSoutPcmLaw = pChanEntry->TdmConfig.bySoutPcmLaw; + + /* Copy the SOUT Broadcast TSST into the Stream and timeslot array.*/ + usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; + for( usTsstCount = 0; (usTsstCount < pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry) && (usTsstCount < f_pChannelStats->TdmConfig.ulMaxBroadcastTssts); usTsstCount++ ) + { + if ( usCurrentEntry == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_FATAL_F; + + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); + + f_pChannelStats->TdmConfig.pulSoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue & 0x1F; + f_pChannelStats->TdmConfig.pulSoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue >> 5; + + /* Obtain the index of the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + } + + /* Check if all Sout Broadcast TSST were returned.*/ + if ( usTsstCount < pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry ) + { + f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = TRUE; + } + else /* usTsstCount >= pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry */ + { + f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = FALSE; + } + + f_pChannelStats->TdmConfig.ulRinNumTssts = pChanEntry->TdmConfig.byRinNumTssts; + f_pChannelStats->TdmConfig.ulRinTimeslot = pChanEntry->TdmConfig.usRinTimeslot; + f_pChannelStats->TdmConfig.ulRinStream = pChanEntry->TdmConfig.usRinStream; + f_pChannelStats->TdmConfig.ulRinPcmLaw = pChanEntry->TdmConfig.byRinPcmLaw; + + f_pChannelStats->TdmConfig.ulRoutNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; + f_pChannelStats->TdmConfig.ulRoutTimeslot = pChanEntry->TdmConfig.usRoutTimeslot; + f_pChannelStats->TdmConfig.ulRoutStream = pChanEntry->TdmConfig.usRoutStream; + f_pChannelStats->TdmConfig.ulRoutPcmLaw = pChanEntry->TdmConfig.byRoutPcmLaw; + + + /* Copy the ROUT Broadcast TSST into the Stream and timeslot array.*/ + usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; + for( usTsstCount = 0; (usTsstCount < pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry) && (usTsstCount < f_pChannelStats->TdmConfig.ulMaxBroadcastTssts); usTsstCount++ ) + { + if ( usCurrentEntry == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_FATAL_10; + + mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); + + f_pChannelStats->TdmConfig.pulRoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue & 0x1F; + f_pChannelStats->TdmConfig.pulRoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue >> 5; + + /* Obtain the index of the next entry.*/ + usCurrentEntry = pTsstEntry->usNextEntry; + } + + /* Check if all Rout Broadcast TSST were returned.*/ + if ( usTsstCount < pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry ) + { + f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = TRUE; + } + else /* usTsstCount >= pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry */ + { + f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = FALSE; + } + + /* Copy the VQE configuration.*/ + f_pChannelStats->VqeConfig.fEnableNlp = pChanEntry->VqeConfig.fEnableNlp; + f_pChannelStats->VqeConfig.ulComfortNoiseMode = pChanEntry->VqeConfig.byComfortNoiseMode; + f_pChannelStats->VqeConfig.fEnableTailDisplacement = pChanEntry->VqeConfig.fEnableTailDisplacement; + if ( pChanEntry->VqeConfig.usTailDisplacement != cOCT6100_AUTO_SELECT_TAIL ) + f_pChannelStats->VqeConfig.ulTailDisplacement = pChanEntry->VqeConfig.usTailDisplacement; + else + f_pChannelStats->VqeConfig.ulTailDisplacement = f_pApiInstance->pSharedInfo->ChipConfig.usTailDisplacement; + + if ( pChanEntry->VqeConfig.usTailLength != cOCT6100_AUTO_SELECT_TAIL ) + f_pChannelStats->VqeConfig.ulTailLength = pChanEntry->VqeConfig.usTailLength; + else + f_pChannelStats->VqeConfig.ulTailLength = f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength; + + + + f_pChannelStats->VqeConfig.fSinDcOffsetRemoval = pChanEntry->VqeConfig.fSinDcOffsetRemoval; + f_pChannelStats->VqeConfig.fRinDcOffsetRemoval = pChanEntry->VqeConfig.fRinDcOffsetRemoval; + f_pChannelStats->VqeConfig.fRinLevelControl = pChanEntry->VqeConfig.fRinLevelControl; + f_pChannelStats->VqeConfig.fSoutLevelControl = pChanEntry->VqeConfig.fSoutLevelControl; + f_pChannelStats->VqeConfig.fRinAutomaticLevelControl = pChanEntry->VqeConfig.fRinAutomaticLevelControl; + f_pChannelStats->VqeConfig.fSoutAutomaticLevelControl = pChanEntry->VqeConfig.fSoutAutomaticLevelControl; + f_pChannelStats->VqeConfig.fRinHighLevelCompensation = pChanEntry->VqeConfig.fRinHighLevelCompensation; + f_pChannelStats->VqeConfig.fSoutAdaptiveNoiseReduction = pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction; + f_pChannelStats->VqeConfig.fSoutNoiseBleaching = pChanEntry->VqeConfig.fSoutNoiseBleaching; + f_pChannelStats->VqeConfig.fSoutConferencingNoiseReduction = pChanEntry->VqeConfig.fSoutConferencingNoiseReduction; + f_pChannelStats->VqeConfig.lRinLevelControlGainDb = pChanEntry->VqeConfig.chRinLevelControlGainDb; + f_pChannelStats->VqeConfig.lSoutLevelControlGainDb = pChanEntry->VqeConfig.chSoutLevelControlGainDb; + f_pChannelStats->VqeConfig.lRinAutomaticLevelControlTargetDb = pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb; + f_pChannelStats->VqeConfig.lSoutAutomaticLevelControlTargetDb = pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb; + f_pChannelStats->VqeConfig.lRinHighLevelCompensationThresholdDb = pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb; + f_pChannelStats->VqeConfig.fAcousticEcho = pChanEntry->VqeConfig.fAcousticEcho; + f_pChannelStats->VqeConfig.fDtmfToneRemoval = pChanEntry->VqeConfig.fDtmfToneRemoval; + + f_pChannelStats->VqeConfig.lDefaultErlDb = pChanEntry->VqeConfig.chDefaultErlDb; + f_pChannelStats->VqeConfig.lAecDefaultErlDb = pChanEntry->VqeConfig.chAecDefaultErlDb; + f_pChannelStats->VqeConfig.ulAecTailLength = pChanEntry->VqeConfig.usAecTailLength; + f_pChannelStats->VqeConfig.lAnrSnrEnhancementDb = pChanEntry->VqeConfig.chAnrSnrEnhancementDb; + f_pChannelStats->VqeConfig.ulAnrVoiceNoiseSegregation = pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation; + f_pChannelStats->VqeConfig.ulToneDisablerVqeActivationDelay = pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay; + f_pChannelStats->VqeConfig.ulNonLinearityBehaviorA = pChanEntry->VqeConfig.byNonLinearityBehaviorA; + f_pChannelStats->VqeConfig.ulNonLinearityBehaviorB = pChanEntry->VqeConfig.byNonLinearityBehaviorB; + f_pChannelStats->VqeConfig.ulDoubleTalkBehavior = pChanEntry->VqeConfig.byDoubleTalkBehavior; + f_pChannelStats->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb; + f_pChannelStats->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb; + f_pChannelStats->VqeConfig.fSoutNaturalListenerEnhancement = pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement; + f_pChannelStats->VqeConfig.fRoutNoiseReduction = pChanEntry->VqeConfig.fRoutNoiseReduction; + f_pChannelStats->VqeConfig.fEnableMusicProtection = pChanEntry->VqeConfig.fEnableMusicProtection; + f_pChannelStats->VqeConfig.fIdleCodeDetection = pChanEntry->VqeConfig.fIdleCodeDetection; + + /* Copy the CODEC configuration.*/ + f_pChannelStats->CodecConfig.ulAdpcmNibblePosition = pChanEntry->CodecConfig.byAdpcmNibblePosition; + + f_pChannelStats->CodecConfig.ulEncoderPort = pChanEntry->CodecConfig.byEncoderPort; + f_pChannelStats->CodecConfig.ulEncodingRate = pChanEntry->CodecConfig.byEncodingRate; + + f_pChannelStats->CodecConfig.ulDecoderPort = pChanEntry->CodecConfig.byDecoderPort; + f_pChannelStats->CodecConfig.ulDecodingRate = pChanEntry->CodecConfig.byDecodingRate; + + f_pChannelStats->CodecConfig.fEnableSilenceSuppression = pChanEntry->CodecConfig.fEnableSilenceSuppression; + f_pChannelStats->CodecConfig.ulPhase = pChanEntry->CodecConfig.byPhase; + f_pChannelStats->CodecConfig.ulPhasingType = pChanEntry->CodecConfig.byPhasingType; + + if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + tPOCT6100_API_PHASING_TSST pPhasingTsstEntry; + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingTsstEntry, pChanEntry->usPhasingTsstIndex ); + + f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingTsstEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pChanEntry->usPhasingTsstIndex; + } + else + { + f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; + } + + + /* Reset the stats and exit if the reset flag is set.*/ + if ( f_pChannelStats->fResetStats == TRUE ) + { + pChanEntry->sMaxERLE = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->sMaxERL = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->usMaxEchoDelay = cOCT6100_INVALID_STAT_W; + } + + /*---------------------------------------------------------------------*/ + /* Update the API internal stats.*/ + + BurstParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); + BurstParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsOfst; + BurstParams.ulReadLength = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsSize / 2; /* Length in words.*/ + + mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if the energy stat are found in the new memory location. */ + if ( ( pSharedInfo->ImageInfo.fRinEnergyStat == TRUE ) + && ( pSharedInfo->ImageInfo.fSoutEnergyStat == TRUE ) ) + { + ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.byBitOffset; + ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.byFieldSize; + + ReadParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); + ReadParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + ulFeatureBytesOffset; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulFeatureBitOffset < 16 ) + ReadParams.ulReadAddress += 2; + + /* Must read in memory directly since this value is changed by hardware */ + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move data at correct position according to what was read. */ + if ( ulFeatureBitOffset < 16 ) + ulTempData = usReadData; + else + ulTempData = usReadData << 16; + + /* Clear previous value set in the feature field. */ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= ulMask; + + /* Shift to get value. */ + ulTempData = ulTempData >> ulFeatureBitOffset; + + /* Overwrite value read the old way. */ + ausReadData[ 0 ] &= 0x00FF; + ausReadData[ 0 ] |= (UINT16)( ( ulTempData << 8 ) & 0xFF00 ); + + ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.byBitOffset; + ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.byFieldSize; + + ReadParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); + ReadParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + ulFeatureBytesOffset; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulFeatureBitOffset < 16 ) + ReadParams.ulReadAddress += 2; + + /* Must read in memory directly since this value is changed by hardware */ + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move data at correct position according to what was read. */ + if ( ulFeatureBitOffset < 16 ) + ulTempData = usReadData; + else + ulTempData = usReadData << 16; + + /* Clear previous value set in the feature field. */ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= ulMask; + + /* Shift to get value. */ + ulTempData = ulTempData >> ulFeatureBitOffset; + + /* Overwrite value read the old way. */ + ausReadData[ 1 ] &= 0x00FF; + ausReadData[ 1 ] |= (UINT16)( ( ulTempData << 8 ) & 0xFF00 ); + } + + byRinEnergyRaw = (BYTE)(( ausReadData[ 0 ] >> 8 ) & 0xFF); + bySinEnergyRaw = (BYTE)(( ausReadData[ 0 ] >> 0 ) & 0xFF); + bySoutEnergyRaw = (BYTE)(( ausReadData[ 1 ] >> 8 ) & 0xFF); + byCnEnergyRaw = (BYTE)(( ausReadData[ 5 ] >> 8 ) & 0xFF); + + usEchoDelayInFrames = (UINT16)(ausReadData[ 4 ]); + usErlRaw = ausReadData[ 2 ]; + + pChanEntry->byToneDisablerStatus = (UINT8)(( ausReadData[ 5 ] >> 0 ) & 0xFF); + if ( f_pChannelStats->fResetStats == TRUE ) + { + pChanEntry->usNumEchoPathChangesOfst = (UINT16)(ausReadData[ 3 ]); + pChanEntry->usNumEchoPathChanges = 0; + } + else /* if ( f_pChannelStats->fResetStats == FALSE ) */ + { + pChanEntry->usNumEchoPathChanges = (UINT16)( ausReadData[ 3 ] - pChanEntry->usNumEchoPathChangesOfst ); + } + + pChanEntry->sComfortNoiseLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( byCnEnergyRaw ) & 0xFFFF ); + pChanEntry->sComfortNoiseLevel -= 12; + pChanEntry->sRinLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( byRinEnergyRaw ) & 0xFFFF ); + pChanEntry->sRinLevel -= 12; + pChanEntry->sSinLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( bySinEnergyRaw ) & 0xFFFF ); + pChanEntry->sSinLevel -= 12; + lSoutEnergyIndB = Oct6100ApiOctFloatToDbEnergyByte( bySoutEnergyRaw ); + lSoutEnergyIndB -= 12; + + /* Process some stats only if the channel is converged.*/ + if ( ( usEchoDelayInFrames != cOCT6100_INVALID_ECHO_DELAY ) + && ( pChanEntry->byEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN ) + && ( pChanEntry->byEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET ) ) + { + /* Update the current ERL. */ + pChanEntry->sCurrentERL = (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( usErlRaw ) & 0xFFFF ); + pChanEntry->sCurrentERLE = (INT16)( ( lSoutEnergyIndB - pChanEntry->sSinLevel ) & 0xFFFF ); + pChanEntry->usCurrentEchoDelay = (UINT16)( usEchoDelayInFrames / 8 ); /* To convert in msec.*/ + + /* Update the max value if required.*/ + if ( pChanEntry->usCurrentEchoDelay > pChanEntry->usMaxEchoDelay || + pChanEntry->usMaxEchoDelay == cOCT6100_INVALID_STAT_W ) + { + pChanEntry->usMaxEchoDelay = pChanEntry->usCurrentEchoDelay; + } + + if ( pChanEntry->sCurrentERL > pChanEntry->sMaxERL || + pChanEntry->sMaxERL == cOCT6100_INVALID_SIGNED_STAT_W ) + { + pChanEntry->sMaxERL = pChanEntry->sCurrentERL; + } + + if ( pChanEntry->sCurrentERLE > pChanEntry->sMaxERLE || + pChanEntry->sMaxERLE == cOCT6100_INVALID_SIGNED_STAT_W ) + { + pChanEntry->sMaxERLE = pChanEntry->sCurrentERLE; + } + } + else + { + pChanEntry->sCurrentERLE = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->sCurrentERL = cOCT6100_INVALID_SIGNED_STAT_W; + pChanEntry->usCurrentEchoDelay = cOCT6100_INVALID_STAT_W; + } + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat == TRUE ) + { + /* Calculate base address for auto level control + high level compensation configuration. */ + ulBaseAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + ( usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + + ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.usDwordOffset * 4; + ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.byBitOffset; + ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.byFieldSize; + + ReadParams.ulReadAddress = ulBaseAddress + ulFeatureBytesOffset; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulFeatureBitOffset < 16 ) + ReadParams.ulReadAddress += 2; + + /* Must read in memory directly since this value is changed by hardware */ + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move data at correct position according to what was read. */ + if ( ulFeatureBitOffset < 16 ) + ulTempData = usReadData; + else + ulTempData = usReadData << 16; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= ulMask; + + /* Shift to get value. */ + ulTempData = ulTempData >> ulFeatureBitOffset; + + pChanEntry->sRinAppliedGain = (INT16)( 2 * (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)( ulTempData & 0xFFFF ) ) & 0xFFFF ) ); + } + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat == TRUE ) + { + /* Calculate base address for auto level control + high level compensation configuration. */ + ulBaseAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + ( usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + + ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.usDwordOffset * 4; + ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.byBitOffset; + ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.byFieldSize; + + ReadParams.ulReadAddress = ulBaseAddress + ulFeatureBytesOffset; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulFeatureBitOffset < 16 ) + ReadParams.ulReadAddress += 2; + + /* Must read in memory directly since this value is changed by hardware */ + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move data at correct position according to what was read. */ + if ( ulFeatureBitOffset < 16 ) + ulTempData = usReadData; + else + ulTempData = usReadData << 16; + + /* Clear previous value set in the feature field. */ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= ulMask; + + /* Shift to get value. */ + ulTempData = ulTempData >> ulFeatureBitOffset; + + pChanEntry->sSoutAppliedGain = (INT16)( 2 * (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)( ulTempData & 0xFFFF ) ) & 0xFFFF ) ); + } + + /*---------------------------------------------------------------------*/ + /* Return the real stats.*/ + + f_pChannelStats->ulNumEchoPathChanges = pChanEntry->usNumEchoPathChanges; + if ( usEchoDelayInFrames != cOCT6100_INVALID_ECHO_DELAY ) + { + f_pChannelStats->fEchoCancellerConverged = TRUE; + } + else + { + f_pChannelStats->fEchoCancellerConverged = FALSE; + } + if ( pChanEntry->sCurrentERL == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lCurrentERL = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lCurrentERL = pChanEntry->sCurrentERL; + + if ( pChanEntry->sMaxERL == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lMaxERL = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lMaxERL = pChanEntry->sMaxERL; + + if ( pChanEntry->usMaxEchoDelay == cOCT6100_INVALID_STAT_W ) + f_pChannelStats->ulMaxEchoDelay = cOCT6100_INVALID_STAT; + else + f_pChannelStats->ulMaxEchoDelay = pChanEntry->usMaxEchoDelay; + + if ( pChanEntry->sRinLevel == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lRinLevel = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lRinLevel = pChanEntry->sRinLevel; + + if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) + { + if ( pChanEntry->sSinLevel == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lSinLevel = pChanEntry->sSinLevel; + } + else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ + { + /* SIN level is not supported in this image. */ + f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; + } + + f_pChannelStats->lRinAppliedGain = pChanEntry->VqeConfig.chRinLevelControlGainDb; + if ( ( f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat == TRUE ) + && ( ( pChanEntry->VqeConfig.fRinAutomaticLevelControl == TRUE ) + || ( pChanEntry->VqeConfig.fRinHighLevelCompensation == TRUE ) ) ) + { + f_pChannelStats->lRinAppliedGain = pChanEntry->sRinAppliedGain; + } + + f_pChannelStats->lSoutAppliedGain = pChanEntry->VqeConfig.chSoutLevelControlGainDb; + if ( ( f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat == TRUE ) + && ( pChanEntry->VqeConfig.fSoutAutomaticLevelControl == TRUE ) ) + { + f_pChannelStats->lSoutAppliedGain = pChanEntry->sSoutAppliedGain; + } + + if ( pChanEntry->usCurrentEchoDelay == cOCT6100_INVALID_STAT_W ) + f_pChannelStats->ulCurrentEchoDelay = cOCT6100_INVALID_STAT; + else + f_pChannelStats->ulCurrentEchoDelay = pChanEntry->usCurrentEchoDelay; + + if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) + { + if ( pChanEntry->sCurrentERLE == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lCurrentERLE = pChanEntry->sCurrentERLE; + } + else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ + { + f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; + } + + if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) + { + if ( pChanEntry->sMaxERLE == cOCT6100_INVALID_SIGNED_STAT_W ) + f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; + else + f_pChannelStats->lMaxERLE = pChanEntry->sMaxERLE; + } + else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ + { + f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; + } + + f_pChannelStats->lComfortNoiseLevel = pChanEntry->sComfortNoiseLevel; + f_pChannelStats->ulToneDisablerStatus = pChanEntry->byToneDisablerStatus; + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fSinVoiceDetectedStat == TRUE ) + { + UINT32 ulVoiceDetectedBytesOfst = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.usDwordOffset * 4; + UINT32 ulVoiceDetectedBitOfst = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.byBitOffset; + UINT32 ulVoiceDetectedFieldSize = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.byFieldSize; + + /* Set the channel root base address.*/ + UINT32 ulChannelRootBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst; + + ReadParams.ulReadAddress = ulChannelRootBaseAddress + ulVoiceDetectedBytesOfst; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulVoiceDetectedBitOfst < 16 ) + ReadParams.ulReadAddress += 2; + + /* Must read in memory directly since this value is changed by hardware */ + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Move data at correct position according to what was read. */ + if ( ulVoiceDetectedBitOfst < 16 ) + ulTempData = usReadData; + else + ulTempData = usReadData << 16; + + mOCT6100_CREATE_FEATURE_MASK( ulVoiceDetectedFieldSize, ulVoiceDetectedBitOfst, &ulMask ); + + if ( ( ulTempData & ulMask ) != 0x0 ) + f_pChannelStats->fSinVoiceDetected = TRUE; + else + f_pChannelStats->fSinVoiceDetected = FALSE; + } + + /*---------------------------------------------------------------------*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveEchoEntry + +Description: Reserves one of the echo channel API entry. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pusEchoIndex Resulting index reserved in the echo channel list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveEchoEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusEchoIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + PVOID pEchoAlloc; + UINT32 ulResult; + UINT32 ulEchoIndex; + + /* Get local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) + + ulResult = OctapiLlmAllocAlloc( pEchoAlloc, &ulEchoIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) + return cOCT6100_ERR_CHANNEL_ALL_CHANNELS_ARE_OPENED; + else + return cOCT6100_ERR_FATAL_11; + } + + *f_pusEchoIndex = (UINT16)( ulEchoIndex & 0xFFFF ); + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseEchoEntry + +Description: Releases the specified ECHO channel API entry. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_usEchoIndex Index reserved in the echo channel list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseEchoEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usEchoIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + PVOID pEchoAlloc; + UINT32 ulResult; + + /* Get local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) + + ulResult = OctapiLlmAllocDealloc( pEchoAlloc, f_usEchoIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return cOCT6100_ERR_FATAL_12; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBiDirChanEntry + +Description: Reserves one of the bidirectional channel API entry. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pusBiDirChanIndex Resulting index reserved in the bidir channel list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveBiDirChanEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusBiDirChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + PVOID pChanAlloc; + UINT32 ulResult; + UINT32 ulBiDirChanIndex; + + /* Get local pointer to shared portion of the API instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pChanAlloc ) + + ulResult = OctapiLlmAllocAlloc( pChanAlloc, &ulBiDirChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) + return cOCT6100_ERR_CHANNEL_ALL_BIDIR_CHANNELS_ARE_OPENED; + else + return cOCT6100_ERR_FATAL_9F; + } + + *f_pusBiDirChanIndex = (UINT16)( ulBiDirChanIndex & 0xFFFF ); + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBiDirChanEntry + +Description: Releases the specified bidirectional channel API entry. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_ulBiDirChanIndex Bidirectional channel index within the API's Bidir channel list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseBiDirChanEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT32 f_ulBiDirChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + PVOID pChanAlloc; + UINT32 ulResult; + + /* Get local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pChanAlloc ) + + ulResult = OctapiLlmAllocDealloc( pChanAlloc, f_ulBiDirChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return cOCT6100_ERR_FATAL_A0; + } + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckTdmConfig + +Description: This function will check the validity of the TDM config parameter + of an Open TDM config structure. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pTdmConfig TDM config of the channel. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckTdmConfig( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig ) +{ + UINT32 ulResult; + + /*==============================================================================*/ + /* Check the TDM configuration parameters.*/ + + /* Check the validity of the timeslot and Stream only if it is defined.*/ + if ( f_pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED || + f_pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED ) + { + if ( f_pTdmConfig->ulRinNumTssts != 1 && + f_pTdmConfig->ulRinNumTssts != 2 ) + return cOCT6100_ERR_CHANNEL_RIN_NUM_TSSTS; + + /* Check the RIN TDM streams, timeslots component for errors.*/ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + f_pTdmConfig->ulRinNumTssts, + f_pTdmConfig->ulRinTimeslot, + f_pTdmConfig->ulRinStream, + cOCT6100_INPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_RIN_STREAM; + } + else + { + return ulResult; + } + } + } + + /* Check the validity of the timeslot and Stream only if it is defined.*/ + if ( f_pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED || + f_pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED ) + { + if ( f_pTdmConfig->ulRoutNumTssts != 1 && + f_pTdmConfig->ulRoutNumTssts != 2 ) + return cOCT6100_ERR_CHANNEL_ROUT_NUM_TSSTS; + + /* Check the ROUT TDM streams, timeslots component for errors.*/ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + f_pTdmConfig->ulRoutNumTssts, + f_pTdmConfig->ulRoutTimeslot, + f_pTdmConfig->ulRoutStream, + cOCT6100_OUTPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_ROUT_STREAM; + } + else + { + return ulResult; + } + } + } + + /* Check the validity of the timeslot and Stream only if it is defined.*/ + if ( f_pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED || + f_pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED ) + { + if ( f_pTdmConfig->ulSinNumTssts != 1 && + f_pTdmConfig->ulSinNumTssts != 2 ) + return cOCT6100_ERR_CHANNEL_SIN_NUM_TSSTS; + + /* Check the SIN TDM streams, timeslots component for errors.*/ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + f_pTdmConfig->ulSinNumTssts, + f_pTdmConfig->ulSinTimeslot, + f_pTdmConfig->ulSinStream, + cOCT6100_INPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_SIN_STREAM; + } + else + { + return ulResult; + } + } + } + + /* Check the validity of the timeslot and Stream only if it is defined.*/ + if ( f_pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED || + f_pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED ) + { + if ( f_pTdmConfig->ulSoutNumTssts != 1 && + f_pTdmConfig->ulSoutNumTssts != 2 ) + return cOCT6100_ERR_CHANNEL_SOUT_NUM_TSSTS; + + /* Check the ROUT TDM streams, timeslots component for errors.*/ + ulResult = Oct6100ApiValidateTsst( f_pApiInstance, + f_pTdmConfig->ulSoutNumTssts, + f_pTdmConfig->ulSoutTimeslot, + f_pTdmConfig->ulSoutStream, + cOCT6100_OUTPUT_TSST ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) + { + return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; + } + else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) + { + return cOCT6100_ERR_CHANNEL_SOUT_STREAM; + } + else + { + return ulResult; + } + } + } + + /* Check the PCM law parameters.*/ + if ( f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_U_LAW && + f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_A_LAW ) + return cOCT6100_ERR_CHANNEL_RIN_PCM_LAW; + + if ( f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_U_LAW && + f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_A_LAW ) + return cOCT6100_ERR_CHANNEL_SIN_PCM_LAW; + + if ( f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_U_LAW && + f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_A_LAW ) + return cOCT6100_ERR_CHANNEL_ROUT_PCM_LAW; + + if ( f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_U_LAW && + f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_A_LAW ) + return cOCT6100_ERR_CHANNEL_SOUT_PCM_LAW; + + /*==============================================================================*/ + + + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckVqeConfig + +Description: This function will check the validity of the VQE config parameter + of an Open VQE config structure. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig VQE config of the channel. +f_fEnableToneDisabler Whether the tone disabler is active or not. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckVqeConfig( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN BOOL f_fEnableToneDisabler ) +{ + tPOCT6100_API_IMAGE_INFO pImageInfo; + + pImageInfo = &f_pApiInstance->pSharedInfo->ImageInfo; + + if ( f_pVqeConfig->fEnableNlp != TRUE && f_pVqeConfig->fEnableNlp != FALSE ) + return cOCT6100_ERR_CHANNEL_ENABLE_NLP; + + if ( f_pVqeConfig->fEnableNlp == TRUE && pImageInfo->fNlpControl == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLP_CONTROL; + + + + /* Check the comfort noise mode.*/ + if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF && pImageInfo->fComfortNoise == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_BKG_NOISE_FREEZE; + + if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_NORMAL && + f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_EXTENDED && + f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_FAST_LATCH && + f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF ) + return cOCT6100_ERR_CHANNEL_COMFORT_NOISE_MODE; + + /* Check the DC offset removal.*/ + if ( f_pVqeConfig->fSinDcOffsetRemoval != TRUE && f_pVqeConfig->fSinDcOffsetRemoval != FALSE ) + return cOCT6100_ERR_CHANNEL_SIN_DC_OFFSET_REM; + + if ( f_pVqeConfig->fSinDcOffsetRemoval == TRUE && pImageInfo->fSinDcOffsetRemoval == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_DC_OFFSET_REM; + + if ( f_pVqeConfig->fRinDcOffsetRemoval != TRUE && f_pVqeConfig->fRinDcOffsetRemoval != FALSE ) + return cOCT6100_ERR_CHANNEL_RIN_DC_OFFSET_REM; + + if ( f_pVqeConfig->fRinDcOffsetRemoval == TRUE && pImageInfo->fRinDcOffsetRemoval == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_DC_OFFSET_REM; + + /* Check the Level control.*/ + if ( f_pVqeConfig->fRinLevelControl != TRUE && f_pVqeConfig->fRinLevelControl != FALSE ) + return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL; + + if ( f_pVqeConfig->fSoutLevelControl != TRUE && f_pVqeConfig->fSoutLevelControl != FALSE ) + return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL; + + if ( ( f_pVqeConfig->lRinLevelControlGainDb < -24 ) || ( f_pVqeConfig->lRinLevelControlGainDb > 24 ) ) + return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL_GAIN; + + if ( ( f_pVqeConfig->lSoutLevelControlGainDb < -24 ) || ( f_pVqeConfig->lSoutLevelControlGainDb > 24 ) ) + return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL_GAIN; + + if ( ( f_pVqeConfig->fRinAutomaticLevelControl != TRUE ) && ( f_pVqeConfig->fRinAutomaticLevelControl != FALSE ) ) + return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL; + + if ( ( f_pVqeConfig->fRinHighLevelCompensation != TRUE ) && ( f_pVqeConfig->fRinHighLevelCompensation != FALSE ) ) + return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP; + + if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) && ( pImageInfo->fRinAutoLevelControl == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_AUTO_LC; + + if ( ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) && ( pImageInfo->fRinHighLevelCompensation == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_HIGH_LEVEL_COMP; + + if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) + { + if ( f_pVqeConfig->fRinLevelControl == TRUE ) + return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_MANUAL; + + if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) + return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_HIGH_LEVEL_COMP; + + if ( ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lRinAutomaticLevelControlTargetDb > 0 ) ) + return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL_TARGET; + } + + if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) + { + if ( f_pVqeConfig->fRinLevelControl == TRUE ) + return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_MANUAL; + + if ( ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb < -40 || f_pVqeConfig->lRinHighLevelCompensationThresholdDb > 0 ) ) + return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_THRESHOLD; + } + + if ( f_pVqeConfig->fSoutAutomaticLevelControl != TRUE && f_pVqeConfig->fSoutAutomaticLevelControl != FALSE ) + return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL; + + if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) && ( pImageInfo->fSoutAutoLevelControl == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SOUT_AUTO_LC; + + if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) + { + if ( f_pVqeConfig->fSoutLevelControl == TRUE ) + return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_MANUAL; + + if ( ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lSoutAutomaticLevelControlTargetDb > 0 ) ) + return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL_TARGET; + } + + if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != TRUE && + f_pVqeConfig->fSoutAdaptiveNoiseReduction != FALSE ) + return cOCT6100_ERR_CHANNEL_SOUT_ADAPT_NOISE_REDUCTION; + + if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && pImageInfo->fAdaptiveNoiseReduction == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR; + + if ( f_pVqeConfig->fSoutConferencingNoiseReduction != TRUE && + f_pVqeConfig->fSoutConferencingNoiseReduction != FALSE ) + return cOCT6100_ERR_CHANNEL_SOUT_CONFERENCE_NOISE_REDUCTION; + + if ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE && pImageInfo->fConferencingNoiseReduction == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_CNR; + + /* Validate Sout noise bleaching parameter. */ + if ( f_pVqeConfig->fSoutNoiseBleaching != TRUE && + f_pVqeConfig->fSoutNoiseBleaching != FALSE ) + return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING; + + /* Check if firmware supports Sout noise bleaching. */ + if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE && pImageInfo->fSoutNoiseBleaching == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NOISE_BLEACHING; + + /* If Sout noise bleaching is requested, no ANR or CNR shall be activated. */ + if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE ) + { + /* No xNR! */ + if ( ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) + || ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE ) ) + return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING_NR; + } + + /* Cannot activate both ANR and CNR when noise bleaching is present */ + if ( pImageInfo->fSoutNoiseBleaching == TRUE ) + { + if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && + f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) + return cOCT6100_ERR_CHANNEL_ANR_CNR_SIMULTANEOUSLY; + } + + /* Validate the DTMF tone removal parameter.*/ + if ( f_pVqeConfig->fDtmfToneRemoval != TRUE && f_pVqeConfig->fDtmfToneRemoval != FALSE ) + return cOCT6100_ERR_CHANNEL_TONE_REMOVAL; + + if ( f_pVqeConfig->fDtmfToneRemoval == TRUE && pImageInfo->fToneRemoval == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_REMOVAL; + + + + /* Check the Tail displacement enable.*/ + if ( f_pVqeConfig->fEnableTailDisplacement != TRUE && f_pVqeConfig->fEnableTailDisplacement != FALSE ) + return cOCT6100_ERR_CHANNEL_ENABLE_TAIL_DISPLACEMENT; + + if ( f_pVqeConfig->fEnableTailDisplacement == TRUE && pImageInfo->fTailDisplacement == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_DISPLACEMENT; + + /* Check the Tail displacement value.*/ + if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) + { + if ( f_pVqeConfig->ulTailDisplacement != cOCT6100_AUTO_SELECT_TAIL ) + { + /* Check if this feature is supported by the image. */ + if ( pImageInfo->fPerChannelTailDisplacement == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_PER_CHAN_TAIL; + + /* Check that this value is not greater then what the image supports. */ + if ( f_pVqeConfig->ulTailDisplacement > pImageInfo->usMaxTailDisplacement ) + return cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT_INVALID; + } + } + + /* Check the tail length value. */ + if ( f_pVqeConfig->ulTailLength != cOCT6100_AUTO_SELECT_TAIL ) + { + /* Check if this feature is supported by the image. */ + if ( ( pImageInfo->fPerChannelTailLength == FALSE ) + && ( (UINT16)( f_pVqeConfig->ulTailLength & 0xFFFF ) != pImageInfo->usMaxTailLength ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_LENGTH; + + if ( ( f_pVqeConfig->ulTailLength < 32 ) || ( f_pVqeConfig->ulTailLength > 128 ) + || ( ( f_pVqeConfig->ulTailLength % 4 ) != 0x0 ) ) + return cOCT6100_ERR_CHANNEL_TAIL_LENGTH; + + /* Check if the requested tail length is supported by the chip. */ + if ( f_pVqeConfig->ulTailLength > pImageInfo->usMaxTailLength ) + return cOCT6100_ERR_CHANNEL_TAIL_LENGTH_INVALID; + } + + /* Validate the acoustic echo cancellation parameter.*/ + if ( f_pVqeConfig->fAcousticEcho != TRUE && f_pVqeConfig->fAcousticEcho != FALSE ) + return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO; + + if ( f_pVqeConfig->fAcousticEcho == TRUE && pImageInfo->fAcousticEcho == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO; + + if ( f_pVqeConfig->fAcousticEcho == TRUE ) + { + /* Check if acoustic echo tail length configuration is supported in the image. */ + if ( ( f_pVqeConfig->ulAecTailLength != 128 ) && ( pImageInfo->fAecTailLength == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; + + /* Check the requested acoustic echo tail length. */ + if ( ( f_pVqeConfig->ulAecTailLength != 128 ) + && ( f_pVqeConfig->ulAecTailLength != 256 ) + && ( f_pVqeConfig->ulAecTailLength != 512 ) + && ( f_pVqeConfig->ulAecTailLength != 1024 ) ) + return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; + + if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) + { + UINT32 ulTailSum; + + /* Start with requested tail displacement. */ + if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTailSum = f_pApiInstance->pSharedInfo->ChipConfig.usTailDisplacement; + } + else + { + ulTailSum = f_pVqeConfig->ulTailDisplacement; + } + + /* Add requested tail length. */ + if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTailSum += f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength; + } + else + { + ulTailSum += f_pVqeConfig->ulTailLength; + } + + /* The tail sum must be smaller then the requested AEC tail length. */ + if ( ulTailSum > f_pVqeConfig->ulAecTailLength ) + return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_SUM; + } + } + + /* Validate the Default ERL parameter.*/ + if ( f_pVqeConfig->lDefaultErlDb != -6 && pImageInfo->fDefaultErl == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DEFAULT_ERL; + + if ( ( f_pVqeConfig->lDefaultErlDb != 0 ) && + ( f_pVqeConfig->lDefaultErlDb != -3 ) && + ( f_pVqeConfig->lDefaultErlDb != -6 ) && + ( f_pVqeConfig->lDefaultErlDb != -9 ) && + ( f_pVqeConfig->lDefaultErlDb != -12 ) ) + return cOCT6100_ERR_CHANNEL_DEFAULT_ERL; + + /* Validate the Default AEC ERL parameter.*/ + if ( f_pVqeConfig->lAecDefaultErlDb != 0 && pImageInfo->fAecDefaultErl == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_AEC_DEFAULT_ERL; + + if ( f_pVqeConfig->lAecDefaultErlDb != 0 && f_pVqeConfig->lAecDefaultErlDb != -3 && f_pVqeConfig->lAecDefaultErlDb != -6 ) + return cOCT6100_ERR_CHANNEL_AEC_DEFAULT_ERL; + + /* Validate the non-linearity A parameter.*/ + if ( f_pVqeConfig->ulNonLinearityBehaviorA != 1 && pImageInfo->fNonLinearityBehaviorA == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DOUBLE_TALK; + + if ( f_pVqeConfig->ulNonLinearityBehaviorA >= 14 ) + return cOCT6100_ERR_CHANNEL_DOUBLE_TALK; + + /* Validate the non-linearity B parameter.*/ + if ( f_pVqeConfig->ulNonLinearityBehaviorB != 0 && pImageInfo->fNonLinearityBehaviorB == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NON_LINEARITY_B; + + if ( f_pVqeConfig->ulNonLinearityBehaviorB >= 9 ) + return cOCT6100_ERR_CHANNEL_NON_LINEARITY_B; + + /* Check if configuring the double talk behavior is supported in the firmware. */ + if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && pImageInfo->fDoubleTalkBehavior == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_DOUBLE_TALK_BEHAVIOR_MODE; + + /* Validate the double talk behavior mode parameter. */ + if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_LESS_AGGRESSIVE ) + return cOCT6100_ERR_CHANNEL_DOUBLE_TALK_MODE; + + /* Validate the Sout automatic listener enhancement ratio. */ + if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 && pImageInfo->fListenerEnhancement == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ALE; + + if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb > 30 ) + return cOCT6100_ERR_CHANNEL_ALE_RATIO; + + /* Validate the Sout natural listener enhancement ratio. */ + if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != TRUE && f_pVqeConfig->fSoutNaturalListenerEnhancement != FALSE ) + return cOCT6100_ERR_CHANNEL_NLE_FLAG; + + if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE && pImageInfo->fListenerEnhancement == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLE; + + if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) + { + if ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb > 30 ) + return cOCT6100_ERR_CHANNEL_NLE_RATIO; + } + + /* Both ALE and NLE cannot be activated simultaneously. */ + if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) + && ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ) + return cOCT6100_ERR_CHANNEL_ALE_NLE_SIMULTANEOUSLY; + + /* Validate Rout noise reduction. */ + if ( f_pVqeConfig->fRoutNoiseReduction != TRUE && f_pVqeConfig->fRoutNoiseReduction != FALSE ) + return cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION; + + /* Check if Rout noise reduction is supported. */ + if ( f_pVqeConfig->fRoutNoiseReduction == TRUE && pImageInfo->fRoutNoiseReduction == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NR; + + /* Check if ANR SNRE is supported. */ + if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) && ( pImageInfo->fAnrSnrEnhancement == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SNR_ENHANCEMENT; + + /* Validate Sout ANR SNR enhancement. */ + if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -9 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -12 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -15 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -21 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -24 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -27 ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != -30 ) ) + return cOCT6100_ERR_CHANNEL_ANR_SNR_ENHANCEMENT; + + /* Validate ANR voice-noise segregation. */ + if ( f_pVqeConfig->ulAnrVoiceNoiseSegregation > 15 ) + return cOCT6100_ERR_CHANNEL_ANR_SEGREGATION; + + /* Check if ANR VN segregation is supported. */ + if ( ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != 6 ) && ( pImageInfo->fAnrVoiceNoiseSegregation == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SEGREGATION; + + /* Check if the loaded image supports tone disabler VQE activation delay. */ + if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != 300 ) + && ( pImageInfo->fToneDisablerVqeActivationDelay == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; + + /* Check if the specified tone disabler VQE activation delay is correct. */ + if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay < 300 ) + || ( ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) % 512 ) != 0 ) ) + return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; + + /* Check if the tone disabler is activated when the user requests a different activation delay. */ + if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != 300 ) + && ( f_fEnableToneDisabler == FALSE ) ) + return cOCT6100_ERR_CHANNEL_MUST_ENABLE_TONE_DISABLER; + + /* Check the enable music protection flag. */ + if ( ( f_pVqeConfig->fEnableMusicProtection != TRUE ) && ( f_pVqeConfig->fEnableMusicProtection != FALSE ) ) + return cOCT6100_ERR_CHANNEL_ENABLE_MUSIC_PROTECTION; + + /* The music protection module can only be activated if the image supports it. */ + if ( ( f_pVqeConfig->fEnableMusicProtection == TRUE ) && + ( pImageInfo->fMusicProtection == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_MUSIC_PROTECTION; + + /* Check the enable idle code detection flag. */ + if ( ( f_pVqeConfig->fIdleCodeDetection != TRUE ) && ( f_pVqeConfig->fIdleCodeDetection != FALSE ) ) + return cOCT6100_ERR_CHANNEL_IDLE_CODE_DETECTION; + + /* The idle code detection module can only be activated if the image supports it. */ + if ( ( f_pVqeConfig->fIdleCodeDetection == TRUE ) && ( pImageInfo->fIdleCodeDetection == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION; + + /* The idle code detection module can be disabled only if idle code detection configuration */ + /* is supported in the image. */ + if ( ( f_pVqeConfig->fIdleCodeDetection == FALSE ) && ( pImageInfo->fIdleCodeDetectionConfiguration == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION_CONFIG; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckCodecConfig + +Description: This function will check the validity of the Codec config parameter + of an Open Codec config structure. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pCodecConfig Codec config of the channel. +f_ulDecoderNumTssts Number of TSST for the decoder. +f_pusPhasingTsstIndex Pointer to the Phasing TSST index within the API's phasing TSST list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckCodecConfig( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_CODEC f_pCodecConfig, + IN UINT32 f_ulDecoderNumTssts, + OUT PUINT16 f_pusPhasingTsstIndex ) +{ + + /* Verify the ADPCM nibble value.*/ + if ( f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_LOW_BITS && + f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_HIGH_BITS ) + return cOCT6100_ERR_CHANNEL_ADPCM_NIBBLE; + + /* Verify the Encoder port.*/ + if ( f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_ROUT && + f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT && + f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) + return cOCT6100_ERR_CHANNEL_ENCODER_PORT; + + /* Verify the Decoder port.*/ + if ( f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_RIN && + f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_SIN && + f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) + return cOCT6100_ERR_CHANNEL_DECODER_PORT; + + /* The codec cannot be on the same stream.*/ + if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT && + f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; + + if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT && + f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) + return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; + + /* Verify if the requested functions are supported by the chip.*/ + if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && + f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) + { + if ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ENCODING; + } + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && + f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) + { + if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DECODING; + } + + /* Check if encoder port has been specified when a rate has been set. */ + if ( f_pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING && + f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_CHANNEL_ENCODER_PORT; + + /* Check if decoder port has been specified when a rate has been set. */ + if ( f_pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING && + f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) + return cOCT6100_ERR_CHANNEL_DECODER_PORT; + + /* Check Encoder related parameter if one is used.*/ + if ( f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) + { + /* Check the Encoder compression rate.*/ + if ( ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_40KBPS ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_32KBPS ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_24KBPS ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_16KBPS ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_4_1 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_3_2 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_2_3 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_4_0 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_3_1 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_2_2 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_3_0 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_2_1 ) && + ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_16KBPS_2_0 ) ) + return cOCT6100_ERR_CHANNEL_ENCODING_RATE; + + /* Verify phasing information.*/ + if ( f_pCodecConfig->ulPhasingType != cOCT6100_SINGLE_PHASING && + f_pCodecConfig->ulPhasingType != cOCT6100_DUAL_PHASING && + f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) + return cOCT6100_ERR_CHANNEL_PHASING_TYPE; + + /* Verify the silence suppression parameters.*/ + if ( f_pCodecConfig->fEnableSilenceSuppression != TRUE && + f_pCodecConfig->fEnableSilenceSuppression != FALSE ) + return cOCT6100_ERR_CHANNEL_SIL_SUP_ENABLE; + + if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && + f_pApiInstance->pSharedInfo->ImageInfo.fSilenceSuppression == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIL_SUP; + + if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && + f_pCodecConfig->ulPhasingType == cOCT6100_NO_PHASING ) + return cOCT6100_ERR_CHANNEL_PHASE_TYPE_REQUIRED; + + if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && + f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; + + if ( f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE && + f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) + return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; + + /* Silence suppression can only be performed if the encoder is using the SOUT port.*/ + if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && + f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT ) + return cOCT6100_ERR_CHANNEL_SIL_SUP_INVALID_ENCODER_PORT; + + /* Check phasing TSST info if phasing is required.*/ + if ( f_pCodecConfig->ulPhasingTsstHndl != cOCT6100_INVALID_HANDLE ) + { + tPOCT6100_API_PHASING_TSST pPhasingEntry; + UINT32 ulEntryOpenCnt; + + /* Check the provided handle. */ + if ( (f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_PHASING_TSST ) + return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; + + *f_pusPhasingTsstIndex = (UINT16)( f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusPhasingTsstIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPhasingTssts ) + return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, *f_pusPhasingTsstIndex ); + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pCodecConfig->ulPhasingTsstHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Verify if the state of the phasing TSST.*/ + if ( pPhasingEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_PHASING_TSST_NOT_OPEN; + if ( ulEntryOpenCnt != pPhasingEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; + + /* Check the specified phase value against the phasing length of the phasing TSST.*/ + if ( f_pCodecConfig->ulPhase >= pPhasingEntry->usPhasingLength ) + return cOCT6100_ERR_CHANNEL_PHASING_INVALID_PHASE; + } + else + { + *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; + } + } + else + { + *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; + } + + + /* Check Decoder related parameter if one is used.*/ + if ( f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) + { + /* Check the Decoding rate.*/ + if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS && + f_pCodecConfig->ulDecodingRate != cOCT6100_G726_40KBPS && + f_pCodecConfig->ulDecodingRate != cOCT6100_G726_32KBPS && + f_pCodecConfig->ulDecodingRate != cOCT6100_G726_24KBPS && + f_pCodecConfig->ulDecodingRate != cOCT6100_G726_16KBPS && + f_pCodecConfig->ulDecodingRate != cOCT6100_G726_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G726_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G727_2C_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G727_3C_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G727_4C_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_2C_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_3C_ENCODED && + f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_4C_ENCODED ) + return cOCT6100_ERR_CHANNEL_DECODING_RATE; + + /* Make sure that two timeslot are allocated if PCM-ECHO encoded is selected.*/ + if ( (f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G726_ENCODED || + f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_2C_ENCODED || + f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_3C_ENCODED || + f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_4C_ENCODED ) && + f_ulDecoderNumTssts != 2 ) + return cOCT6100_ERR_CHANNEL_MISSING_TSST; + } + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteInputTsstControlMemory + +Description: This function configure a TSST control memory entry in internal memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_usTsstIndex TSST index within the TSST control memory. +f_usTsiMemIndex TSI index within the TSI chariot memory. +f_ulTsstInputLaw PCM law of the input TSST. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteInputTsstControlMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usTsstIndex, + IN UINT16 f_usTsiMemIndex, + IN UINT32 f_ulTsstInputLaw ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_INPUT_TSST; + WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; + + /* Set the PCM law.*/ + WriteParams.usWriteData |= f_ulTsstInputLaw << cOCT6100_TSST_CONTROL_MEM_PCM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteOutputTsstControlMemory + +Description: This function configure a TSST control memory entry in internal memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteOutputTsstControlMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usTsstIndex, + IN UINT32 f_ulAdpcmNibblePosition, + IN UINT32 f_ulNumTssts, + IN UINT16 f_usTsiMemIndex ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST; + WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET; + WriteParams.usWriteData |= (f_ulNumTssts - 1) << cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET; + WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteEncoderMemory + +Description: This function configure a Encoded memory entry in internal memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_ulEncoderIndex Index of the encoder block within the ADPCM context memory. +f_ulCompType Compression rate of the encoder. +f_usTsiMemIndex TSI index within the TSI chariot memory used by the encoder. +f_ulEnableSilenceSuppression Silence suppression enable flag. +f_ulAdpcmNibblePosition ADPCM nibble position. +f_usPhasingTsstIndex Phasing TSST index within the API's Phassing TSST list. +f_ulPhasingType Type of the Phasing TSST. +f_ulPhase Phase used with this encoder. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteEncoderMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT32 f_ulEncoderIndex, + IN UINT32 f_ulCompType, + IN UINT16 f_usTsiMemIndex, + IN UINT32 f_ulEnableSilenceSuppression, + IN UINT32 f_ulAdpcmNibblePosition, + IN UINT16 f_usPhasingTsstIndex, + IN UINT32 f_ulPhasingType, + IN UINT32 f_ulPhase ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + /*==============================================================================*/ + /* Conversion Control Base */ + WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_ulEncoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ENCODER; + WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; + WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 2 */ + WriteParams.ulWriteAddress += 2; + + /* Set the phasing TSST number.*/ + if ( f_usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + WriteParams.usWriteData = (UINT16)( f_usPhasingTsstIndex << cOCT6100_CONVERSION_CONTROL_MEM_PHASE_OFFSET ); + else + WriteParams.usWriteData = 0; + + /* Set the phasing type and the phase value if required.*/ + switch( f_ulPhasingType ) + { + case cOCT6100_NO_PHASING: + WriteParams.usWriteData |= 0x1 << 10; + break; + case cOCT6100_SINGLE_PHASING: + WriteParams.usWriteData |= f_ulPhase; + break; + case cOCT6100_DUAL_PHASING: + WriteParams.usWriteData |= 0x1 << 11; + WriteParams.usWriteData |= f_ulPhase; + break; + default: + /* No problem. */ + break; + } + + /* Set the silence suppression flag.*/ + WriteParams.usWriteData |= f_ulEnableSilenceSuppression << cOCT6100_CONVERSION_CONTROL_MEM_SIL_SUP_OFFSET; + + /* Set the nibble position.*/ + WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 4 */ + WriteParams.ulWriteAddress += 2; + + /* Set the reset mode */ + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 6 */ + WriteParams.ulWriteAddress += 2; + + /* Set the reset mode */ + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteDecoderMemory + +Description: This function configure a Decoder memory entry in internal memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_usDecoderIndex Index of the decoder block within the ADPCM context memory. +f_ulCompType Decompression rate of the decoder. +f_usTsiMemIndex TSI index within the TSI chariot memory. +f_ulPcmLaw PCM law of the decoded samples. +f_ulAdpcmNibblePosition ADPCM nibble position. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteDecoderMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usDecoderIndex, + IN UINT32 f_ulCompType, + IN UINT16 f_usTsiMemIndex, + IN UINT32 f_ulPcmLaw, + IN UINT32 f_ulAdpcmNibblePosition ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + + + /*==============================================================================*/ + /* Conversion Control Base */ + WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usDecoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_DECODER; + WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; + WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 2 */ + WriteParams.ulWriteAddress += 2; + + /* Set the nibble position.*/ + WriteParams.usWriteData = (UINT16)( f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET ); + + /* Set the law.*/ + WriteParams.usWriteData |= f_ulPcmLaw << cOCT6100_CONVERSION_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 4 */ + WriteParams.ulWriteAddress += 2; + + /* Set the reset mode */ + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + /* Conversion Control Base + 6 */ + WriteParams.ulWriteAddress += 2; + + /* Set the reset mode */ + WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiClearConversionMemory + +Description: This function clears a conversion memory entry in internal + memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_usConversionMemIndex Index of the block within the conversion memory. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiClearConversionMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usConversionMemIndex ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_READ_PARAMS ReadParams; + UINT32 ulResult; + UINT32 ulBaseAddress; + UINT16 usReadData; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + WriteParams.usWriteData = 0; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + /*==============================================================================*/ + /* Clear the entry */ + ulBaseAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usConversionMemIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); + /* The "activate" bit at offset +6 must be cleared first. */ + WriteParams.ulWriteAddress = ulBaseAddress + 6; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Read at 0x200 to make sure there is no corruption on channel 0. */ + ReadParams.ulReadAddress = 0x200; + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Then clear the rest of the structure. */ + WriteParams.ulWriteAddress = ulBaseAddress + 4; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ulBaseAddress + 2; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ulBaseAddress; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteVqeMemory + +Description: This function configure an echo memory entry in internal memory and + external memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig Pointer to a VQE config structure. +f_pChannelOpen Pointer to a channel configuration structure. +f_usChanIndex Index of the echo channel in the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. +f_fModifyOnly Flag indicating if the configuration should be + modified only. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteVqeMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN BOOL f_fClearPlayoutPointers, + IN BOOL f_fModifyOnly ) +{ + UINT32 ulResult; + + /* Write the NLP software configuration structure. */ + ulResult = Oct6100ApiWriteVqeNlpMemory( + f_pApiInstance, + f_pVqeConfig, + f_pChannelOpen, + f_usChanIndex, + f_usEchoMemIndex, + f_fClearPlayoutPointers, + f_fModifyOnly ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write the AF software configuration structure. */ + ulResult = Oct6100ApiWriteVqeAfMemory( + f_pApiInstance, + f_pVqeConfig, + f_pChannelOpen, + f_usChanIndex, + f_usEchoMemIndex, + f_fClearPlayoutPointers, + f_fModifyOnly ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteVqeNlpMemory + +Description: This function configures the NLP related VQE features of an + echo channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig Pointer to a VQE config structure. +f_pChannelOpen Pointer to a channel configuration structure. +f_usChanIndex Index of the echo channel in the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. +f_fModifyOnly Flag indicating if the configuration should be + modified only. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteVqeNlpMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN BOOL f_fClearPlayoutPointers, + IN BOOL f_fModifyOnly ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulNlpConfigBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulMask; + UINT16 usTempData; + BOOL fEchoOperationModeChanged; + + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); + + /*==============================================================================*/ + /* Configure the CPU NLP configuration of the channel feature by feature.*/ + + ulNlpConfigBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + /* Set initial value to zero.*/ + ulTempData = 0; + + /* Configure Adaptive Noise Reduction.*/ + if ( pSharedInfo->ImageInfo.fAdaptiveNoiseReduction == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction ) + || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) + ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set adaptive noise reduction on the SOUT port.*/ + ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutAdaptiveNoiseReduction ) << ulFeatureBitOffset ); + + /* If SOUT noise bleaching is requested, ANR must be activated. */ + ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutNoiseBleaching ) << ulFeatureBitOffset ); + + /* First read the DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure Rout Noise Reduction. */ + if ( pSharedInfo->ImageInfo.fRoutNoiseReduction == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fRoutNoiseReduction != pChanEntry->VqeConfig.fRoutNoiseReduction ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAnrOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAnrOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAnrOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set noise reduction on the Rout port. */ + ulTempData |= ( ( (UINT32)f_pVqeConfig->fRoutNoiseReduction ) << ulFeatureBitOffset ); + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure Sout ANR SNR enhancement. */ + if ( pSharedInfo->ImageInfo.fAnrSnrEnhancement == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->lAnrSnrEnhancementDb != pChanEntry->VqeConfig.chAnrSnrEnhancementDb ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set ANR SNR enhancement on the Sout port. */ + switch( f_pVqeConfig->lAnrSnrEnhancementDb ) + { + case -9: ulTempData |= ( 7 << ulFeatureBitOffset ); + break; + case -12: ulTempData |= ( 6 << ulFeatureBitOffset ); + break; + case -15: ulTempData |= ( 5 << ulFeatureBitOffset ); + break; + case -21: ulTempData |= ( 3 << ulFeatureBitOffset ); + break; + case -24: ulTempData |= ( 2 << ulFeatureBitOffset ); + break; + case -27: ulTempData |= ( 1 << ulFeatureBitOffset ); + break; + case -30: ulTempData |= ( 0 << ulFeatureBitOffset ); + break; + default: ulTempData |= ( 4 << ulFeatureBitOffset ); + /* -18 */ + break; + } + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure Sout ANR voice-noise segregation. */ + if ( pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set ANR voice-noise segregation on the Sout port. */ + ulTempData |= ( ( (UINT32)f_pVqeConfig->ulAnrVoiceNoiseSegregation ) << ulFeatureBitOffset ); + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure the tone disabler VQE activation delay. */ + if ( pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set the tone disabler VQE activation delay. */ + ulTempData |= ( ( (UINT32)( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) / 512 ) ) << ulFeatureBitOffset ); + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure Conferencing Noise Reduction.*/ + if ( pSharedInfo->ImageInfo.fConferencingNoiseReduction == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->fSoutConferencingNoiseReduction != pChanEntry->VqeConfig.fSoutConferencingNoiseReduction ) + || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set conferencing noise reduction on the SOUT port. */ + ulTempData |= (f_pVqeConfig->fSoutConferencingNoiseReduction << ulFeatureBitOffset ); + + /* If SOUT noise bleaching is requested, CNR must be activated. */ + ulTempData |= (f_pVqeConfig->fSoutNoiseBleaching << ulFeatureBitOffset ); + + /* Save the DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the DC removal on RIN ports.*/ + if ( pSharedInfo->ImageInfo.fRinDcOffsetRemoval == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fRinDcOffsetRemoval != pChanEntry->VqeConfig.fRinDcOffsetRemoval ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set adaptive noise reduction on the SOUT port.*/ + ulTempData |= ( ( (UINT32)f_pVqeConfig->fRinDcOffsetRemoval ) << ulFeatureBitOffset ); + + /* The write the new DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the DC removal on SIN ports.*/ + if ( pSharedInfo->ImageInfo.fSinDcOffsetRemoval == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fSinDcOffsetRemoval != pChanEntry->VqeConfig.fSinDcOffsetRemoval ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set adaptive noise reduction on the SOUT port.*/ + ulTempData |= ( ( (UINT32)f_pVqeConfig->fSinDcOffsetRemoval ) << ulFeatureBitOffset ); + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the level control. */ + if ( ( pChanEntry->byEchoOperationMode != f_pChannelOpen->ulEchoOperationMode ) + && ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NORMAL ) ) + fEchoOperationModeChanged = TRUE; + else + fEchoOperationModeChanged = FALSE; + + /* If opening the channel, all level control configuration must be written. */ + if ( f_fModifyOnly == FALSE ) + fEchoOperationModeChanged = TRUE; + ulResult = Oct6100ApiSetChannelLevelControl( f_pApiInstance, + f_pVqeConfig, + f_usChanIndex, + f_usEchoMemIndex, + fEchoOperationModeChanged ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the background noise freeze.*/ + if ( pSharedInfo->ImageInfo.fComfortNoise == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulComfortNoiseMode != pChanEntry->VqeConfig.byComfortNoiseMode ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= ( f_pVqeConfig->ulComfortNoiseMode << ulFeatureBitOffset ); + + /* Save the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the state of the NLP */ + if ( pSharedInfo->ImageInfo.fNlpControl == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fEnableNlp != pChanEntry->VqeConfig.fEnableNlp ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpControlFieldOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->fEnableNlp == FALSE ) + ulTempData |= 0x1 << ulFeatureBitOffset; + + /* Save the new DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the tail configuration. */ + ulResult = Oct6100ApiSetChannelTailConfiguration( + f_pApiInstance, + f_pVqeConfig, + f_usChanIndex, + f_usEchoMemIndex, + f_fModifyOnly ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the Default ERL. */ + if ( ( pSharedInfo->ImageInfo.fDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == FALSE ) ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) + || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) + || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Convert the DB value to octasic's float format. (In energy) */ + if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) + && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) + { + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); + } + else + { + /* Clear the defautl ERL when using the no echo cancellation operation mode. */ + usTempData = 0x0; + } + + if ( ulFeatureFieldLength < 16 ) + usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); + + ulTempData |= ( usTempData << ulFeatureBitOffset ); + + /* Save the new DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the Acoustic echo control.*/ + if ( pSharedInfo->ImageInfo.fAcousticEcho == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AecFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AecFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field. */ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= ( ( (UINT32)f_pVqeConfig->fAcousticEcho ) << ulFeatureBitOffset ); + + /* Then save the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the Acoustic Echo Default ERL. */ + if ( ( pSharedInfo->ImageInfo.fAecDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == TRUE ) ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->lAecDefaultErlDb != pChanEntry->VqeConfig.chAecDefaultErlDb ) + || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field. */ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) + && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) + { + /* Convert the DB value to octasic's float format. (In energy) */ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lAecDefaultErlDb ); + } + else + { + /* Clear the AEC defautl ERL when using the no echo cancellation operation mode. */ + usTempData = 0x0; + } + + if ( ulFeatureFieldLength < 16 ) + usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); + + ulTempData |= ( usTempData << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the DTMF tone removal bit.*/ + if ( pSharedInfo->ImageInfo.fToneRemoval == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fDtmfToneRemoval != pChanEntry->VqeConfig.fDtmfToneRemoval ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= ( ( (UINT32)f_pVqeConfig->fDtmfToneRemoval ) << ulFeatureBitOffset ); + + /* First read the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + + + /* Set the non-linear behavior A.*/ + if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorA == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->ulNonLinearityBehaviorA != pChanEntry->VqeConfig.byNonLinearityBehaviorA ) + || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) + { + UINT16 ausLookupTable[ 14 ] = { 0x3663, 0x3906, 0x399C, 0x3A47, 0x3B06, 0x3B99, 0x3C47, 0x3D02, 0x3D99, 0x3E47, 0x3F00, 0x3F99, 0x4042, 0x4100 }; + + ulFeatureBytesOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) + ulTempData |= ( 0x0 << ulFeatureBitOffset ); + else + ulTempData |= ( ausLookupTable[ f_pVqeConfig->ulNonLinearityBehaviorA ] << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Synch all the buffer playout field.*/ + if ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE && f_fClearPlayoutPointers == TRUE ) + { + Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); + + BufferPlayoutStop.ulChannelHndl = cOCT6100_INVALID_HANDLE; + BufferPlayoutStop.fStopCleanly = TRUE; + + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + f_usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; + ulResult = Oct6100ApiInvalidateChanPlayoutStructs( + f_pApiInstance, + &BufferPlayoutStop, + f_usChanIndex, + f_usEchoMemIndex + + ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*==============================================================================*/ + /* Write the 2100 Hz Echo Disabling mode */ + + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* This is a disable bit, so it must be set only if the enable flag is set to false. */ + if ( f_pChannelOpen->fEnableToneDisabler == FALSE ) + ulTempData |= 0x1 << ulFeatureBitOffset; + + /* Save the DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Write the Nlp Trivial enable flag. */ + + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( + + ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) + { + ulTempData |= TRUE << ulFeatureBitOffset; + } + + + /* Then write the DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the double talk behavior mode. */ + if ( pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulDoubleTalkBehavior != pChanEntry->VqeConfig.byDoubleTalkBehavior ) ) ) + { + /* The field is located in the CPURO structure. */ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= (f_pVqeConfig->ulDoubleTalkBehavior << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the music protection enable. */ + if ( ( pSharedInfo->ImageInfo.fMusicProtection == TRUE ) + && ( pSharedInfo->ImageInfo.fMusicProtectionConfiguration == TRUE ) ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fEnableMusicProtection != pChanEntry->VqeConfig.fEnableMusicProtection ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + if ( f_pVqeConfig->fEnableMusicProtection == TRUE ) + ulTempData |= ( 1 << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteVqeAfMemory + +Description: This function configures the AF related VQE features of an + echo channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig Pointer to a VQE config structure. +f_pChannelOpen Pointer to a channel configuration structure. +f_usChanIndex Index of the echo channel in the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. +f_fModifyOnly Flag indicating if the configuration should be + modified only. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteVqeAfMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN BOOL f_fClearPlayoutPointers, + IN BOOL f_fModifyOnly ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulAfConfigBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulMask; + UINT16 usTempData; + + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); + + /*==============================================================================*/ + /* Write the AF CPU configuration of the channel feature by feature.*/ + + /* Calculate AF CPU configuration base address. */ + ulAfConfigBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + + /* Set initial value to zero.*/ + ulTempData = 0; + + /*==============================================================================*/ + /* Program the Maximum echo point within the Main channel memory.*/ + if ( pSharedInfo->ImageInfo.fMaxEchoPoint == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) + || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) + { + /* Write the echo tail length */ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Convert the DB value to octasic's float format.*/ + if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) + { + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); + } + else + { + /* Clear max echo point. No echo cancellation here. */ + usTempData = 0x0; + } + + if ( ulFeatureFieldLength < 16 ) + usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); + + ulTempData |= usTempData << ulFeatureBitOffset; + + /* First read the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the non-linear behavior B.*/ + if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorB == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulNonLinearityBehaviorB != pChanEntry->VqeConfig.byNonLinearityBehaviorB ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= (f_pVqeConfig->ulNonLinearityBehaviorB << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the listener enhancement feature. */ + if ( pSharedInfo->ImageInfo.fListenerEnhancement == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) + || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) + || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveAleOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) + { + UINT32 ulGainDb; + + ulGainDb = f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb / 3; + + /* Round up. */ + if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb % 3 ) != 0x0 ) + ulGainDb ++; + + ulTempData |= ( ulGainDb << ulFeatureBitOffset ); + } + else if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != 0 ) + { + UINT32 ulGainDb; + + ulGainDb = f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb / 3; + + /* Round up. */ + if ( ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb % 3 ) != 0x0 ) + ulGainDb ++; + + ulTempData |= ( ( 0x80 | ulGainDb ) << ulFeatureBitOffset ); + } + + /* Now write the DWORD where the field is located containing the new configuration. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the idle code detection enable. */ + if ( ( pSharedInfo->ImageInfo.fIdleCodeDetection == TRUE ) + && ( pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration == TRUE ) ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->fIdleCodeDetection != pChanEntry->VqeConfig.fIdleCodeDetection ) ) ) + { + /* Calculate base address in the AF software configuration. */ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + if ( f_pVqeConfig->fIdleCodeDetection == FALSE ) + ulTempData |= ( 1 << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Set the AFT control field. */ + if ( pSharedInfo->ImageInfo.fAftControl == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AftControlOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AftControlOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AftControlOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* If the operation mode is no echo, set the field such that echo cancellation is disabled. */ + if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + { + ulTempData |= ( 0x1234 << ulFeatureBitOffset ); + } + else if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) + { + /* For clarity. */ + ulTempData |= ( 0x0 << ulFeatureBitOffset ); + } + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfigBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteEchoMemory + +Description: This function configure an echo memory entry in internal memory.and + external memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pTdmConfig Pointer to a TDM config structure. +f_pChannelOpen Pointer to a channel configuration structure. +f_usEchoIndex Echo channel index within the SSPX memory. +f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory +f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteEchoMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usEchoIndex, + IN UINT16 f_usRinRoutTsiIndex, + IN UINT16 f_usSinSoutTsiIndex ) + +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulBaseAddress; + UINT32 ulRinPcmLaw; + UINT32 ulRoutPcmLaw; + UINT32 ulSinPcmLaw; + UINT32 ulSoutPcmLaw; + + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Set immediately the PCM law to be programmed in the SSPX and NLP memory.*/ + if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) + { + ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; + ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; + ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; + ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; + } + else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ + { + ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; + ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; + ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; + ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; + } + + /*==============================================================================*/ + /* Configure the Global Static Configuration of the channel.*/ + + ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET; + + /* Set the PGSP context base address. */ + ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET; + + WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET; + WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the PGSP init context base address. */ + ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF; + + WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET; + WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the RIN circular buffer base address. */ + ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst) & 0x07FFFF00; + ulTempData |= ( ulRoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); + + /* Set the circular buffer size.*/ + if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 ) + return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE; + ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8; + + WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET; + WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the SIN circular buffer base address. */ + ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst) & 0x07FFFF00; + ulTempData |= ( ulSinPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); + + WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET; + WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the SOUT circular buffer base address. */ + ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst ) & 0x07FFFF00; + ulTempData |= ( ulSoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); + + WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET; + WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* ECHO SSPX Memory configuration.*/ + + WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( f_usEchoIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); + + /* ECHO memory BASE + 2 */ + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = 0x0000; + + /* Set the echo control field.*/ + if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) + || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) + { + WriteParams.usWriteData |= cOCT6100_ECHO_OP_MODE_NORMAL << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; + } + else if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL ) + { + WriteParams.usWriteData |= f_pChannelOpen->ulEchoOperationMode << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; + } + + /* Set the SIN/SOUT law.*/ + WriteParams.usWriteData |= ulSinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; + WriteParams.usWriteData |= ulSoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; + + /* Set the TSI chariot memory field.*/ + WriteParams.usWriteData |= f_usSinSoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* ECHO memory BASE */ + WriteParams.ulWriteAddress -= 2; + WriteParams.usWriteData = cOCT6100_ECHO_CONTROL_MEM_ACTIVATE_ENTRY; + + /* Set the RIN/ROUT law.*/ + WriteParams.usWriteData |= ulRinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; + WriteParams.usWriteData |= ulRoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; + + /* Set the RIN external echo control bit.*/ + if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_EXTERNAL ) + WriteParams.usWriteData |= cOCT6100_ECHO_CONTROL_MEM_EXTERNAL_AF_CTRL; + + /* Set the TSI chariot memory field.*/ + WriteParams.usWriteData |= f_usRinRoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateOpenStruct + +Description: This function will copy the new parameter from the modify structure + into a channel open structure to be processed later by the same path + as the channel open function. + If a parameter is set to keep previous, it's current value will be + extracted from the channel entry in the API. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- + +IN f_pApiInstance Pointer to an API instance structure. +IN f_pChanModify Pointer to a channel modify structure. +IN OUT f_pChanOpen Pointer to a channel open structure. +IN f_pChanEntry Pointer to an API channel structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiUpdateOpenStruct( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MODIFY f_pChanModify, + IN OUT tPOCT6100_CHANNEL_OPEN f_pChanOpen, + IN tPOCT6100_API_CHANNEL f_pChanEntry ) +{ + + /* Check the generic Echo parameters.*/ + if ( f_pChanModify->ulEchoOperationMode == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->ulEchoOperationMode = f_pChanEntry->byEchoOperationMode; + else + f_pChanOpen->ulEchoOperationMode = f_pChanModify->ulEchoOperationMode; + + + if ( f_pChanModify->fEnableToneDisabler == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->fEnableToneDisabler = f_pChanEntry->fEnableToneDisabler; + else + f_pChanOpen->fEnableToneDisabler = f_pChanModify->fEnableToneDisabler; + + + if ( f_pChanModify->ulUserChanId == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->ulUserChanId = f_pChanEntry->ulUserChanId; + else + f_pChanOpen->ulUserChanId = f_pChanModify->ulUserChanId; + + + + /*======================================================================*/ + /* Now update the TDM config.*/ + /* Rin PCM LAW */ + if ( f_pChanModify->TdmConfig.ulRinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanEntry->TdmConfig.byRinPcmLaw; + else + f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanModify->TdmConfig.ulRinPcmLaw; + + /* Sin PCM LAW */ + if ( f_pChanModify->TdmConfig.ulSinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanEntry->TdmConfig.bySinPcmLaw; + else + f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanModify->TdmConfig.ulSinPcmLaw; + + /* Rout PCM LAW */ + if ( f_pChanModify->TdmConfig.ulRoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanEntry->TdmConfig.byRoutPcmLaw; + else + f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanModify->TdmConfig.ulRoutPcmLaw; + + /* Sout PCM LAW */ + if ( f_pChanModify->TdmConfig.ulSoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanEntry->TdmConfig.bySoutPcmLaw; + else + f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanModify->TdmConfig.ulSoutPcmLaw; + + + /* Rin Timeslot */ + if ( f_pChanModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanEntry->TdmConfig.usRinTimeslot; + else + f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanModify->TdmConfig.ulRinTimeslot; + + /* Rin Stream */ + if ( f_pChanModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRinStream = f_pChanEntry->TdmConfig.usRinStream; + else + f_pChanOpen->TdmConfig.ulRinStream = f_pChanModify->TdmConfig.ulRinStream; + + /* Rin Num TSSTs */ + if ( f_pChanModify->TdmConfig.ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanEntry->TdmConfig.byRinNumTssts; + else + f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanModify->TdmConfig.ulRinNumTssts; + + + /* Sin Timeslot */ + if ( f_pChanModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanEntry->TdmConfig.usSinTimeslot; + else + f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanModify->TdmConfig.ulSinTimeslot; + + /* Sin Stream */ + if ( f_pChanModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSinStream = f_pChanEntry->TdmConfig.usSinStream; + else + f_pChanOpen->TdmConfig.ulSinStream = f_pChanModify->TdmConfig.ulSinStream; + + /* Sin Num TSSTs */ + if ( f_pChanModify->TdmConfig.ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanEntry->TdmConfig.bySinNumTssts; + else + f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanModify->TdmConfig.ulSinNumTssts; + + + /* Rout Timeslot */ + if ( f_pChanModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanEntry->TdmConfig.usRoutTimeslot; + else + f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanModify->TdmConfig.ulRoutTimeslot; + + /* Rout Stream */ + if ( f_pChanModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRoutStream = f_pChanEntry->TdmConfig.usRoutStream; + else + f_pChanOpen->TdmConfig.ulRoutStream = f_pChanModify->TdmConfig.ulRoutStream; + + /* Rout Num TSSTs */ + if ( f_pChanModify->TdmConfig.ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanEntry->TdmConfig.byRoutNumTssts; + else + f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanModify->TdmConfig.ulRoutNumTssts; + + + /* Sout Timeslot */ + if ( f_pChanModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanEntry->TdmConfig.usSoutTimeslot; + else + f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanModify->TdmConfig.ulSoutTimeslot; + + /* Sout Stream */ + if ( f_pChanModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSoutStream = f_pChanEntry->TdmConfig.usSoutStream; + else + f_pChanOpen->TdmConfig.ulSoutStream = f_pChanModify->TdmConfig.ulSoutStream; + + /* Sout Num TSSTs */ + if ( f_pChanModify->TdmConfig.ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanEntry->TdmConfig.bySoutNumTssts; + else + f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanModify->TdmConfig.ulSoutNumTssts; + + /*======================================================================*/ + + /*======================================================================*/ + /* Now update the VQE config.*/ + + if ( f_pChanModify->VqeConfig.ulComfortNoiseMode == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanEntry->VqeConfig.byComfortNoiseMode; + else + f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanModify->VqeConfig.ulComfortNoiseMode; + + if ( f_pChanModify->VqeConfig.fEnableNlp == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fEnableNlp = f_pChanEntry->VqeConfig.fEnableNlp; + else + f_pChanOpen->VqeConfig.fEnableNlp = f_pChanModify->VqeConfig.fEnableNlp; + + if ( f_pChanModify->VqeConfig.fEnableTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanEntry->VqeConfig.fEnableTailDisplacement; + else + f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanModify->VqeConfig.fEnableTailDisplacement; + + if ( f_pChanModify->VqeConfig.ulTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanEntry->VqeConfig.usTailDisplacement; + else + f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanModify->VqeConfig.ulTailDisplacement; + + /* Tail length cannot be modifed. */ + f_pChanOpen->VqeConfig.ulTailLength = f_pChanEntry->VqeConfig.usTailLength; + + + + if ( f_pChanModify->VqeConfig.fRinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanEntry->VqeConfig.fRinDcOffsetRemoval; + else + f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanModify->VqeConfig.fRinDcOffsetRemoval; + + + if ( f_pChanModify->VqeConfig.fRinLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanEntry->VqeConfig.fRinLevelControl; + else + f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanModify->VqeConfig.fRinLevelControl; + + + if ( f_pChanModify->VqeConfig.fRinAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanEntry->VqeConfig.fRinAutomaticLevelControl; + else + f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanModify->VqeConfig.fRinAutomaticLevelControl; + + + if ( f_pChanModify->VqeConfig.fRinHighLevelCompensation == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanEntry->VqeConfig.fRinHighLevelCompensation; + else + f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanModify->VqeConfig.fRinHighLevelCompensation; + + + if ( f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb; + else + f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb; + + + if ( f_pChanModify->VqeConfig.fSinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanEntry->VqeConfig.fSinDcOffsetRemoval; + else + f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanModify->VqeConfig.fSinDcOffsetRemoval; + + + if ( f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction; + else + f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction; + + + if ( f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanEntry->VqeConfig.fSoutConferencingNoiseReduction; + else + f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction; + + + if ( f_pChanModify->VqeConfig.fSoutNoiseBleaching == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanEntry->VqeConfig.fSoutNoiseBleaching; + else + f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanModify->VqeConfig.fSoutNoiseBleaching; + + + if ( f_pChanModify->VqeConfig.fSoutLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanEntry->VqeConfig.fSoutLevelControl; + else + f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanModify->VqeConfig.fSoutLevelControl; + + + if ( f_pChanModify->VqeConfig.fSoutAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanEntry->VqeConfig.fSoutAutomaticLevelControl; + else + f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanModify->VqeConfig.fSoutAutomaticLevelControl; + + + if ( f_pChanModify->VqeConfig.lRinLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanEntry->VqeConfig.chRinLevelControlGainDb; + else + f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanModify->VqeConfig.lRinLevelControlGainDb; + + + if ( f_pChanModify->VqeConfig.lSoutLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanEntry->VqeConfig.chSoutLevelControlGainDb; + else + f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanModify->VqeConfig.lSoutLevelControlGainDb; + + + if ( f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb; + else + f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb; + + + if ( f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb; + else + f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb; + + + if ( f_pChanModify->VqeConfig.lDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanEntry->VqeConfig.chDefaultErlDb; + else + f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanModify->VqeConfig.lDefaultErlDb; + + + if ( f_pChanModify->VqeConfig.lAecDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) + f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanEntry->VqeConfig.chAecDefaultErlDb; + else + f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanModify->VqeConfig.lAecDefaultErlDb; + + + if ( f_pChanModify->VqeConfig.ulAecTailLength == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanEntry->VqeConfig.usAecTailLength; + else + f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanModify->VqeConfig.ulAecTailLength; + + + if ( f_pChanModify->VqeConfig.fAcousticEcho == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanEntry->VqeConfig.fAcousticEcho; + else + f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanModify->VqeConfig.fAcousticEcho; + + + if ( f_pChanModify->VqeConfig.fDtmfToneRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanEntry->VqeConfig.fDtmfToneRemoval; + else + f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanModify->VqeConfig.fDtmfToneRemoval; + + + + + + if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorA == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanEntry->VqeConfig.byNonLinearityBehaviorA; + else + f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanModify->VqeConfig.ulNonLinearityBehaviorA; + + + if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorB == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanEntry->VqeConfig.byNonLinearityBehaviorB; + else + f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanModify->VqeConfig.ulNonLinearityBehaviorB; + + + if ( f_pChanModify->VqeConfig.ulDoubleTalkBehavior == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanEntry->VqeConfig.byDoubleTalkBehavior; + else + f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanModify->VqeConfig.ulDoubleTalkBehavior; + + + if ( f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb; + else + f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb; + + + if ( f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb; + else + f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb; + + + if ( f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement; + else + f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement; + + + if ( f_pChanModify->VqeConfig.fRoutNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanEntry->VqeConfig.fRoutNoiseReduction; + else + f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanModify->VqeConfig.fRoutNoiseReduction; + + + if ( f_pChanModify->VqeConfig.lAnrSnrEnhancementDb == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanEntry->VqeConfig.chAnrSnrEnhancementDb; + else + f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanModify->VqeConfig.lAnrSnrEnhancementDb; + + + if ( f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation; + else + f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation; + + + if ( f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay; + else + f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay; + + + if ( f_pChanModify->VqeConfig.fEnableMusicProtection == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanEntry->VqeConfig.fEnableMusicProtection; + else + f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanModify->VqeConfig.fEnableMusicProtection; + + + if ( f_pChanModify->VqeConfig.fIdleCodeDetection == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanEntry->VqeConfig.fIdleCodeDetection; + else + f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanModify->VqeConfig.fIdleCodeDetection; + + /*======================================================================*/ + + + /*======================================================================*/ + /* Finaly the codec config.*/ + + if ( f_pChanModify->CodecConfig.ulDecoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanEntry->CodecConfig.byDecoderPort; + else + f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanModify->CodecConfig.ulDecoderPort; + + + if ( f_pChanModify->CodecConfig.ulDecodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanEntry->CodecConfig.byDecodingRate; + else + f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanModify->CodecConfig.ulDecodingRate; + + + if ( f_pChanModify->CodecConfig.ulEncoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanEntry->CodecConfig.byEncoderPort; + else + f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanModify->CodecConfig.ulEncoderPort; + + + if ( f_pChanModify->CodecConfig.ulEncodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanEntry->CodecConfig.byEncodingRate; + else + f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanModify->CodecConfig.ulEncodingRate; + + if ( f_pChanModify->CodecConfig.fEnableSilenceSuppression == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanEntry->CodecConfig.fEnableSilenceSuppression; + else + f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanModify->CodecConfig.fEnableSilenceSuppression; + + if ( f_pChanModify->CodecConfig.ulPhasingType == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulPhasingType = f_pChanEntry->CodecConfig.byPhasingType; + else + f_pChanOpen->CodecConfig.ulPhasingType = f_pChanModify->CodecConfig.ulPhasingType; + + if ( f_pChanModify->CodecConfig.ulPhase == cOCT6100_KEEP_PREVIOUS_SETTING ) + f_pChanOpen->CodecConfig.ulPhase = f_pChanEntry->CodecConfig.byPhase; + else + f_pChanOpen->CodecConfig.ulPhase = f_pChanModify->CodecConfig.ulPhase; + + if ( f_pChanModify->CodecConfig.ulPhasingTsstHndl == cOCT6100_KEEP_PREVIOUS_SETTING ) + { + if ( f_pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) + { + tPOCT6100_API_PHASING_TSST pPhasingEntry; + + mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanEntry->usPhasingTsstIndex ); + + /* Now recreate the Phasing TSST handle.*/ + f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanEntry->usPhasingTsstIndex; + } + else + { + f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; + } + } + else + { + f_pChanOpen->CodecConfig.ulPhasingTsstHndl = f_pChanModify->CodecConfig.ulPhasingTsstHndl; + } + + f_pChanOpen->CodecConfig.ulAdpcmNibblePosition = f_pChanEntry->CodecConfig.byAdpcmNibblePosition; + /*======================================================================*/ + + return cOCT6100_ERR_OK; +} + + + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiRetrieveNlpConfDword + +Description: This function is used by the API to store on a per channel basis + the various confguration DWORD from the device. The API performs + less read to the chip that way since it is always in synch with the + chip. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChanEntry Pointer to an API channel structure.. +f_ulAddress Address that needs to be modified.. +f_pulConfigDword Pointer to the content stored in the API located at the + desired address. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiRetrieveNlpConfDword( + + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_API_CHANNEL f_pChanEntry, + IN UINT32 f_ulAddress, + OUT PUINT32 f_pulConfigDword ) +{ + UINT32 ulResult; + UINT32 ulFirstEmptyIndex = 0xFFFFFFFF; + UINT32 i; + + /* Search for the Dword.*/ + for ( i = 0; i < cOCT6100_MAX_NLP_CONF_DWORD; i++ ) + { + if ( ( ulFirstEmptyIndex == 0xFFFFFFFF ) && ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == 0x0 ) ) + ulFirstEmptyIndex = i; + + if ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == f_ulAddress ) + { + /* We found the matching Dword.*/ + *f_pulConfigDword = f_pChanEntry->aulNlpConfDword[ i ][ 1 ]; + return cOCT6100_ERR_OK; + } + } + + if ( i == cOCT6100_MAX_NLP_CONF_DWORD && ulFirstEmptyIndex == 0xFFFFFFFF ) + return cOCT6100_ERR_FATAL_8E; + + /* We did not found any entry, let's create a new entry.*/ + f_pChanEntry->aulNlpConfDword[ ulFirstEmptyIndex ][ 0 ] = f_ulAddress; + + + /* Read the DWORD where the field is located.*/ + ulResult = Oct6100ApiReadDword( f_pApiInstance, + f_ulAddress, + f_pulConfigDword ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiSaveNlpConfDword + +Description: This function stores a configuration Dword within an API channel + structure and then writes it into the chip. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChanEntry Pointer to an API channel structure.. +f_ulAddress Address that needs to be modified.. +f_pulConfigDword content to be stored in the API located at the + desired address. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiSaveNlpConfDword( + + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_API_CHANNEL f_pChanEntry, + IN UINT32 f_ulAddress, + IN UINT32 f_ulConfigDword ) +{ + UINT32 ulResult; + UINT32 i; + + /* Search for the Dword.*/ + for ( i = 0; i < cOCT6100_MAX_NLP_CONF_DWORD; i++ ) + { + + if ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == f_ulAddress ) + { + /* We found the matching Dword.*/ + f_pChanEntry->aulNlpConfDword[ i ][ 1 ] = f_ulConfigDword; + break; + } + } + + if ( i == cOCT6100_MAX_NLP_CONF_DWORD ) + return cOCT6100_ERR_FATAL_8F; + + + /* Write the config DWORD.*/ + ulResult = Oct6100ApiWriteDword( f_pApiInstance, + f_ulAddress, + f_ulConfigDword ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelCreateBiDirSer + +Description: Creates a bidirectional echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelCreateBiDir Pointer to a create bidirectionnal channel structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelCreateBiDirSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) +{ + UINT16 usFirstChanIndex; + UINT16 usFirstChanExtraTsiIndex; + UINT16 usFirstChanSinCopyEventIndex; + UINT16 usFirstChanSoutCopyEventIndex; + UINT16 usSecondChanIndex; + UINT16 usSecondChanExtraTsiIndex; + UINT16 usSecondChanSinCopyEventIndex; + UINT16 usSecondChanSoutCopyEventIndex; + UINT16 usBiDirChanIndex; + UINT32 ulResult; + + /* Check the user's configuration of the bidir channel for errors. */ + ulResult = Oct6100ApiCheckChannelCreateBiDirParams( f_pApiInstance, + f_pChannelCreateBiDir, + &usFirstChanIndex, + &usFirstChanExtraTsiIndex, + &usFirstChanSinCopyEventIndex, + &usSecondChanIndex, + &usSecondChanExtraTsiIndex, + &usSecondChanSinCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the bidir channel. */ + ulResult = Oct6100ApiReserveChannelCreateBiDirResources(f_pApiInstance, + &usBiDirChanIndex, + &usFirstChanExtraTsiIndex, + &usFirstChanSinCopyEventIndex, + &usFirstChanSoutCopyEventIndex, + &usSecondChanExtraTsiIndex, + &usSecondChanSinCopyEventIndex, + &usSecondChanSoutCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write all necessary structures to activate the echo cancellation channel. */ + ulResult = Oct6100ApiWriteChannelCreateBiDirStructs( f_pApiInstance, + usFirstChanIndex, + usFirstChanExtraTsiIndex, + usFirstChanSinCopyEventIndex, + usFirstChanSoutCopyEventIndex, + usSecondChanIndex, + usSecondChanExtraTsiIndex, + usSecondChanSinCopyEventIndex, + usSecondChanSoutCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new echo cancellation channels's entry in the ECHO channel list. */ + ulResult = Oct6100ApiUpdateBiDirChannelEntry( f_pApiInstance, + f_pChannelCreateBiDir, + usBiDirChanIndex, + usFirstChanIndex, + usFirstChanExtraTsiIndex, + usFirstChanSinCopyEventIndex, + usFirstChanSoutCopyEventIndex, + usSecondChanIndex, + usSecondChanExtraTsiIndex, + usSecondChanSinCopyEventIndex, + usSecondChanSoutCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckChannelCreateBiDirParams + +Description: Checks the user's parameter passed to the create bidirectional channel + function. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelCreateBiDir Pointer to a create bidirectionnal channel structure. +f_pusFirstChanIndex Pointer to the first channel index. +f_pusFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. +f_pusFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. +f_pusSecondChanIndex Pointer to the second channel index. +f_pusSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. +f_pusSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckChannelCreateBiDirParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, + OUT PUINT16 f_pusFirstChanIndex, + OUT PUINT16 f_pusFirstChanExtraTsiIndex, + OUT PUINT16 f_pusFirstChanSinCopyEventIndex, + OUT PUINT16 f_pusSecondChanIndex, + OUT PUINT16 f_pusSecondChanExtraTsiIndex, + OUT PUINT16 f_pusSecondChanSinCopyEventIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pFirstChanEntry; + tPOCT6100_API_CHANNEL pSecondChanEntry; + UINT32 ulEntryOpenCnt; + + /* Obtain shared resources pointer.*/ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* validate the bidirectional channel handle memory.*/ + if ( f_pChannelCreateBiDir->pulBiDirChannelHndl == NULL ) + return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; + + /* Check if bi-dir channels are activated. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxBiDirChannels == 0 ) + return cOCT6100_ERR_CHANNEL_BIDIR_DISABLED; + + /*=======================================================================*/ + /* Verify the first channel handle. */ + + if ( (f_pChannelCreateBiDir->ulFirstChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; + + *f_pusFirstChanIndex = (UINT16)( f_pChannelCreateBiDir->ulFirstChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusFirstChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, *f_pusFirstChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelCreateBiDir->ulFirstChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pFirstChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pFirstChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; + + /* Check the specific state of the channel.*/ + if ( pFirstChanEntry->fRinRoutCodecActive == TRUE || pFirstChanEntry->fSinSoutCodecActive == TRUE ) + return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; + if ( pFirstChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CHANNEL_ALREADY_BIDIR; + + if ( pFirstChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_FIRST_CHAN_IN_CONFERENCE; + + if ( pFirstChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_FIRST_CHAN_SOUT_PORT; + if ( pFirstChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_FIRST_CHAN_RIN_PORT; + + /* Return the desired info.*/ + *f_pusFirstChanExtraTsiIndex = pFirstChanEntry->usExtraSinTsiMemIndex; + *f_pusFirstChanSinCopyEventIndex = pFirstChanEntry->usSinCopyEventIndex; + /*=======================================================================*/ + + /*=======================================================================*/ + /* Verify the second channel handle. */ + + if ( (f_pChannelCreateBiDir->ulSecondChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; + + *f_pusSecondChanIndex = (UINT16)( f_pChannelCreateBiDir->ulSecondChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusSecondChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, *f_pusSecondChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelCreateBiDir->ulSecondChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pSecondChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pSecondChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; + + /* Check the specific state of the channel.*/ + if ( pSecondChanEntry->fRinRoutCodecActive == TRUE || pSecondChanEntry->fSinSoutCodecActive == TRUE ) + return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; + if ( pSecondChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CHANNEL_ALREADY_BIDIR; + + if ( pSecondChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_SECOND_CHAN_SOUT_PORT; + if ( pSecondChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_SECOND_CHAN_RIN_PORT; + + if ( pSecondChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CHANNEL_SECOND_CHAN_IN_CONFERENCE; + + /* Return the desired info.*/ + *f_pusSecondChanExtraTsiIndex = pSecondChanEntry->usExtraSinTsiMemIndex; + *f_pusSecondChanSinCopyEventIndex = pSecondChanEntry->usSinCopyEventIndex; + /*=======================================================================*/ + + /* Check the law compatibility.*/ + if ( pFirstChanEntry->TdmConfig.bySoutPcmLaw != pSecondChanEntry->TdmConfig.byRinPcmLaw || + pFirstChanEntry->TdmConfig.byRinPcmLaw != pSecondChanEntry->TdmConfig.bySoutPcmLaw ) + return cOCT6100_ERR_CHANNEL_BIDIR_PCM_LAW; + + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveChannelCreateBiDirResources + +Description: Reserves all resources needed for the new bidirectional channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pusBiDirChanIndex Pointer to the index of the bidirectionnal channel within the API instance. +f_pusFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. +f_pusFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. +f_pusFirstChanSoutCopyEventIndex Pointer to the first channel Sout copy event index. +f_pusSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. +f_pusSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. +f_pusSecondChanSoutCopyEventIndex Pointer to the second channel Sout copy event index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveChannelCreateBiDirResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusBiDirChanIndex, + IN OUT PUINT16 f_pusFirstChanExtraTsiIndex, + IN OUT PUINT16 f_pusFirstChanSinCopyEventIndex, + OUT PUINT16 f_pusFirstChanSoutCopyEventIndex, + IN OUT PUINT16 f_pusSecondChanExtraTsiIndex, + IN OUT PUINT16 f_pusSecondChanSinCopyEventIndex, + OUT PUINT16 f_pusSecondChanSoutCopyEventIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult = cOCT6100_ERR_OK; + UINT32 ulTempVar; + + BOOL fBiDirChanIndex = FALSE; + BOOL fFirstExtraTsi = FALSE; + BOOL fSecondExtraTsi = FALSE; + BOOL fFirstSinCopyEvent = FALSE; + BOOL fSecondSinCopyEvent = FALSE; + BOOL fFirstSoutCopyEvent = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /*===============================================================================*/ + /* Verify and reserve the resources that might already by allocated. */ + + if ( *f_pusFirstChanExtraTsiIndex == cOCT6100_INVALID_INDEX ) + { + /* Reserve the first Extra TSI memory entry */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + f_pusFirstChanExtraTsiIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fFirstExtraTsi = TRUE; + } + + if ( *f_pusFirstChanSinCopyEventIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) + { + /* Reserve the Sin copy event for the first channel.*/ + ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, + f_pusFirstChanSinCopyEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fFirstSinCopyEvent = TRUE; + } + + if ( *f_pusSecondChanExtraTsiIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) + { + /* Reserve the second Extra TSI memory entry */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + f_pusSecondChanExtraTsiIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fSecondExtraTsi = TRUE; + } + + if ( *f_pusSecondChanSinCopyEventIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) + { + /* Reserve the Sin copy event for the second channel.*/ + ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, + f_pusSecondChanSinCopyEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fSecondSinCopyEvent = TRUE; + } + /*===============================================================================*/ + + + /*===============================================================================*/ + /* Now reserve all the resources specific to bidirectional channels */ + + if ( ulResult == cOCT6100_ERR_OK ) + { + ulResult = Oct6100ApiReserveBiDirChanEntry( f_pApiInstance, + f_pusBiDirChanIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fBiDirChanIndex = TRUE; + + /* Reserve the first channel Sout copy mixer event.*/ + ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, + f_pusFirstChanSoutCopyEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fFirstSoutCopyEvent = TRUE; + + /* Reserve the second channel Sout copy mixer event.*/ + ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, + f_pusSecondChanSoutCopyEventIndex ); + } + } + } + + /*===============================================================================*/ + + + /*===============================================================================*/ + /* Release the resources if something went wrong */ + if ( ulResult != cOCT6100_ERR_OK ) + { + /*===============================================================================*/ + /* Release the previously reserved echo resources .*/ + if ( fBiDirChanIndex == TRUE ) + { + ulTempVar = Oct6100ApiReleaseBiDirChanEntry( f_pApiInstance, + *f_pusBiDirChanIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fFirstExtraTsi == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, + *f_pusFirstChanExtraTsiIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fSecondExtraTsi == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, + *f_pusSecondChanExtraTsiIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fFirstSinCopyEvent == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + *f_pusFirstChanSinCopyEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fSecondSinCopyEvent == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + *f_pusSecondChanSinCopyEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fFirstSoutCopyEvent == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + *f_pusFirstChanSoutCopyEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + /*===============================================================================*/ + + return ulResult; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteChannelCreateBiDirStructs + +Description: Performs all the required structure writes to configure the + new echo cancellation channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usFirstChanIndex Pointer to the first channel index. +f_usFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. +f_usFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. +f_usFirstChanSoutCopyEventIndex Pointer to the first channel Sout copy event index. +f_usFirstChanIndex Pointer to the second channel index. +f_usSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. +f_usSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. +f_usSecondChanSoutCopyEventIndex Pointer to the second channel Sout copy event index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteChannelCreateBiDirStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usFirstChanIndex, + IN UINT16 f_usFirstChanExtraTsiIndex, + IN UINT16 f_usFirstChanSinCopyEventIndex, + IN UINT16 f_usFirstChanSoutCopyEventIndex, + IN UINT16 f_usSecondChanIndex, + IN UINT16 f_usSecondChanExtraTsiIndex, + IN UINT16 f_usSecondChanSinCopyEventIndex, + IN UINT16 f_usSecondChanSoutCopyEventIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pFirstChanEntry; + tPOCT6100_API_CHANNEL pSecondChanEntry; + + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /*==============================================================================*/ + /* Get a pointer to the two channel entry.*/ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); + + /*==============================================================================*/ + /* Configure the Tsst control memory and add the Sin copy event if necessary.*/ + + /*=======================================================================*/ + /* Program the Sin Copy event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usFirstChanSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= f_usFirstChanExtraTsiIndex; + WriteParams.usWriteData |= pFirstChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( pFirstChanEntry->usSinSoutTsiMemIndex ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Configure the TSST memory.*/ + if ( pFirstChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pFirstChanEntry->usSinTsstIndex, + f_usFirstChanExtraTsiIndex, + pFirstChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Now insert the event into the event list.*/ + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usFirstChanSinCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_usFirstChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + + /*==============================================================================*/ + /* Configure the Tsst control memory and add the Sin copy event if necessary.*/ + + /*=======================================================================*/ + /* Program the Sin Copy event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSecondChanSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= f_usSecondChanExtraTsiIndex; + WriteParams.usWriteData |= pSecondChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = (UINT16)( pSecondChanEntry->usSinSoutTsiMemIndex ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Configure the TSST memory.*/ + if ( pSecondChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pSecondChanEntry->usSinTsstIndex, + f_usSecondChanExtraTsiIndex, + pSecondChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Now insert the event into the event list.*/ + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usSecondChanSinCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_usSecondChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + + /*==============================================================================*/ + /* Now, let's configure the two Sout copy events.*/ + + /* First event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usFirstChanSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= pFirstChanEntry->usSinSoutTsiMemIndex; + WriteParams.usWriteData |= pFirstChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pSecondChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usFirstChanSoutCopyEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY, + f_usFirstChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + /* Second event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSecondChanSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= pSecondChanEntry->usSinSoutTsiMemIndex; + WriteParams.usWriteData |= pSecondChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pFirstChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usSecondChanSoutCopyEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY, + f_usSecondChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + /* Clear + release the silence events if they were created. */ + + if ( pFirstChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pFirstChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_E0; + + pFirstChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + if ( pSecondChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pSecondChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_E0; + + pSecondChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBiDirChannelEntry + +Description: Updates the new bidir channel and the channel used to create that channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiUpdateBiDirChannelEntry( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, + IN UINT16 f_usBiDirChanIndex, + IN UINT16 f_usFirstChanIndex, + IN UINT16 f_usFirstChanExtraTsiIndex, + IN UINT16 f_usFirstChanSinCopyEventIndex, + IN UINT16 f_usFirstChanSoutCopyEventIndex, + IN UINT16 f_usSecondChanIndex, + IN UINT16 f_usSecondChanExtraTsiIndex, + IN UINT16 f_usSecondChanSinCopyEventIndex, + IN UINT16 f_usSecondChanSoutCopyEventIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pFirstChanEntry; + tPOCT6100_API_CHANNEL pSecondChanEntry; + tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, f_usBiDirChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); + + /*=======================================================================*/ + /* Copy the channel's configuration and allocated resources. */ + + pFirstChanEntry->usExtraSinTsiMemIndex = f_usFirstChanExtraTsiIndex; + pFirstChanEntry->usSinCopyEventIndex = f_usFirstChanSinCopyEventIndex; + pFirstChanEntry->usSoutCopyEventIndex = f_usFirstChanSoutCopyEventIndex; + + pSecondChanEntry->usExtraSinTsiMemIndex = f_usSecondChanExtraTsiIndex; + pSecondChanEntry->usSinCopyEventIndex = f_usSecondChanSinCopyEventIndex; + pSecondChanEntry->usSoutCopyEventIndex = f_usSecondChanSoutCopyEventIndex; + + /* Save the channel info in the bidir channel.*/ + pBiDirChanEntry->usFirstChanIndex = f_usFirstChanIndex; + pBiDirChanEntry->usSecondChanIndex = f_usSecondChanIndex; + + /* Increment the extra TSI memory dependency count.*/ + pFirstChanEntry->usExtraSinTsiDependencyCnt++; + pSecondChanEntry->usExtraSinTsiDependencyCnt++; + + /* Set the bidir flag in the channel structure.*/ + pFirstChanEntry->fBiDirChannel = TRUE; + pSecondChanEntry->fBiDirChannel = TRUE; + + /*=======================================================================*/ + + /* Form handle returned to user. */ + *f_pChannelCreateBiDir->pulBiDirChannelHndl = cOCT6100_HNDL_TAG_BIDIR_CHANNEL | (pBiDirChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBiDirChanIndex; + + /* Finally, mark the channel as open. */ + pBiDirChanEntry->fReserved = TRUE; + + /* Increment the number of channel open.*/ + f_pApiInstance->pSharedInfo->ChipStats.usNumberBiDirChannels++; + + /*=======================================================================*/ + + return cOCT6100_ERR_OK; +} + + + + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelDestroyBiDirSer + +Description: Closes a bidirectional channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelDestroyBiDir Pointer to a destroy bidirectionnal channel structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelDestroyBiDirSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) +{ + UINT16 usBiDirChanIndex; + UINT16 usFirstChanIndex; + UINT16 usSecondChanIndex; + + UINT32 ulResult; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertDestroyBiDirChanParams( f_pApiInstance, + f_pChannelDestroyBiDir, + &usBiDirChanIndex, + &usFirstChanIndex, + &usSecondChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the echo cancellation channel. */ + ulResult = Oct6100ApiInvalidateBiDirChannelStructs( f_pApiInstance, + usFirstChanIndex, + usSecondChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the echo cancellation channel. */ + ulResult = Oct6100ApiReleaseBiDirChannelResources( f_pApiInstance, + usBiDirChanIndex, + usFirstChanIndex, + usSecondChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Invalidate the handle.*/ + f_pChannelDestroyBiDir->ulBiDirChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertDestroyBiDirChanParams + +Description: Validate the handle given by the user and verify the state of + the channel about to be closed. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pChannelDestroyBiDir Pointer to a destroy bidirectional channel structure. +f_pusBiDirChanIndex Pointer to the bidir channel entry within the API's list. +f_pusFirstChanIndex Pointer to the first channel index part of the bidir channel. +f_pusFirstChanIndex Pointer to the second channel index part of the bidir channel. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertDestroyBiDirChanParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir, + IN OUT PUINT16 f_pusBiDirChanIndex, + IN OUT PUINT16 f_pusFirstChanIndex, + IN OUT PUINT16 f_pusSecondChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; + UINT32 ulEntryOpenCnt; + + /* Get local pointer(s). */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Check the provided handle. */ + if ( (f_pChannelDestroyBiDir->ulBiDirChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_BIDIR_CHANNEL ) + return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; + + *f_pusBiDirChanIndex = (UINT16)( f_pChannelDestroyBiDir->ulBiDirChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusBiDirChanIndex >= pSharedInfo->ChipConfig.usMaxBiDirChannels ) + return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the bidir channel's list entry. */ + + mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, *f_pusBiDirChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelDestroyBiDir->ulBiDirChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pBiDirChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_BIDIR_CHAN_NOT_OPEN; + if ( ulEntryOpenCnt != pBiDirChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; + + /*=======================================================================*/ + + /* Return the index of the channel used to create this bidirectional channel.*/ + *f_pusFirstChanIndex = pBiDirChanEntry->usFirstChanIndex; + *f_pusSecondChanIndex = pBiDirChanEntry->usSecondChanIndex; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiInvalidateBiDirChannelStructs + +Description: Destroy the link between the two channels. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiInvalidateBiDirChannelStructs( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usFirstChanIndex, + IN UINT16 f_usSecondChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pFirstChanEntry; + tPOCT6100_API_CHANNEL pSecondChanEntry; + + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Get pointers to the API entry of the two channel used to create the bidir channel.*/ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); + + /* Clear the SIN copy event of the first channel and release the Extra TSI memory if + this feature was the only one using it. */ + if ( pFirstChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /*=======================================================================*/ + /* Clear the Sin Copy event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pFirstChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Configure the TSST memory.*/ + if ( pFirstChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pFirstChanEntry->usSinTsstIndex, + pFirstChanEntry->usSinSoutTsiMemIndex, + pFirstChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pFirstChanEntry->usSinCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + } + + /* Clear the SIN copy event of the first channel and release the Extra TSI memory if + this feature was the only one using it. */ + if ( pSecondChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /*=======================================================================*/ + /* Clear the Sin Copy event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSecondChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Configure the TSST memory.*/ + if ( pSecondChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pSecondChanEntry->usSinTsstIndex, + pSecondChanEntry->usSinSoutTsiMemIndex, + pSecondChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pSecondChanEntry->usSinCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + } + + /* Now remove the sout copy of the first channel.*/ + + /*=======================================================================*/ + /* Clear the Sout Copy event of the first channel.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pFirstChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*=======================================================================*/ + + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pFirstChanEntry->usSoutCopyEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + /* Now remove the sout copy of the second channel.*/ + + /*=======================================================================*/ + /* Clear the Sout Copy event of the second channel.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSecondChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*=======================================================================*/ + + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pSecondChanEntry->usSoutCopyEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBiDirChannelResources + +Description: Release and clear the API entry associated to the bidirectional channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usBiDirChanIndex Index of the bidirectionnal channel in the API's bidir channel list. +f_usFirstChanIndex Index of the first channel used to create the bidir channel. +f_usSecondChanIndex Index of the second channel used to create the bidir channel. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseBiDirChannelResources( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBiDirChanIndex, + IN UINT16 f_usFirstChanIndex, + IN UINT16 f_usSecondChanIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; + tPOCT6100_API_CHANNEL pFirstChanEntry; + tPOCT6100_API_CHANNEL pSecondChanEntry; + tPOCT6100_API_MIXER_EVENT pTempEventEntry; + UINT32 ulResult; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, f_usBiDirChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); + + /* Release the bidir entry.*/ + ulResult = Oct6100ApiReleaseBiDirChanEntry( f_pApiInstance, f_usBiDirChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_AC; + + /* Release the Extra TSI memory and the SIN copy event if required.*/ + if ( pFirstChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the two TSI chariot memory entries.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pFirstChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A3; + + /* Relese the SIN copy event.*/ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usSinCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A4; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pFirstChanEntry->usSinCopyEventIndex ); + + /* Invalidate the entry.*/ + pTempEventEntry->fReserved = FALSE; + pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + pFirstChanEntry->usExtraSinTsiDependencyCnt--; + pFirstChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + pFirstChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + } + else + { + pFirstChanEntry->usExtraSinTsiDependencyCnt--; + } + + if ( pSecondChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the two TSI chariot memory entries.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pSecondChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A5; + + /* Relese the SIN copy event.*/ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usSinCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A6; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pSecondChanEntry->usSinCopyEventIndex ); + /* Invalidate the entry.*/ + pTempEventEntry->fReserved = FALSE; + pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + pSecondChanEntry->usExtraSinTsiDependencyCnt--; + pSecondChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + pSecondChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + } + else + { + pSecondChanEntry->usExtraSinTsiDependencyCnt--; + } + + /* Release the SOUT copy event of the first channel.*/ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usSoutCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A7; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pSecondChanEntry->usSoutCopyEventIndex ); + /* Invalidate the entry.*/ + pTempEventEntry->fReserved = FALSE; + pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + + /* Release the SOUT copy event of the second channel.*/ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usSoutCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_A8; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pSecondChanEntry->usSoutCopyEventIndex ); + /* Invalidate the entry.*/ + pTempEventEntry->fReserved = FALSE; + pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + + /*=======================================================================*/ + /* Update the first channel's list entry. */ + + /* Mark the channel as closed. */ + pFirstChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; + pFirstChanEntry->fBiDirChannel = FALSE; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the second channel's list entry. */ + + /* Mark the channel as closed. */ + pSecondChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; + pSecondChanEntry->fBiDirChannel = FALSE; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the bidirectional channel's list entry. */ + + /* Mark the channel as closed. */ + pBiDirChanEntry->fReserved = FALSE; + pBiDirChanEntry->byEntryOpenCnt++; + + pBiDirChanEntry->usFirstChanIndex = cOCT6100_INVALID_INDEX; + pBiDirChanEntry->usSecondChanIndex = cOCT6100_INVALID_INDEX; + + /* Decrement the number of channel open.*/ + f_pApiInstance->pSharedInfo->ChipStats.usNumberBiDirChannels--; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Check if some of the ports must be muted back. */ + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, + f_usFirstChanIndex, + pFirstChanEntry->usRinTsstIndex, + pFirstChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, + f_usSecondChanIndex, + pSecondChanEntry->usRinTsstIndex, + pSecondChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + return cOCT6100_ERR_OK; +} + +INT32 Oct6100ApiOctFloatToDbEnergyByte(UINT8 x) +{ + INT32 lResult; + + lResult = Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)(x << 8) ); + return lResult; +} + +INT32 Oct6100ApiOctFloatToDbEnergyHalf(UINT16 x) +{ + INT32 y; + UINT16 m; + + y = (((x >> 8) & 0x7F) - 0x41) * 3; + + m = (UINT16)((x & 0x00E0) >> 5); + if (m < 2) y += 0; + else if (m < 5) y += 1; + else y += 2; + + return y; +} + +UINT16 Oct6100ApiDbAmpHalfToOctFloat(INT32 x) +{ + INT32 db_div6; + INT32 db_mod6; + UINT16 rval; + INT32 x_unsigned; + + if(x < 0) + { + x_unsigned = -x; + } + else + { + x_unsigned = x; + } + + db_div6 = x_unsigned / 6; + db_mod6 = x_unsigned % 6; + + if(x < 0) + { + if(db_mod6 == 0) + { + /* Change nothing! */ + db_div6 = -db_div6; + } + else + { + /* When we are negative, round down, and then adjust modulo. For example, if + x is -1, then db_div6 is 0 and db_mod6 is 1. We adjust so db_div6 = -1 and + db_mod6 = 5, which gives the correct adjustment. */ + db_div6 = -db_div6-1; + db_mod6 = 6 - db_mod6; + } + } + + rval = (UINT16)(0x4100 + db_div6 * 0x100); + + if(db_mod6 == 0) + { + rval += 0x0000; + } + else if(db_mod6 == 1) + { + rval += 0x0020; + } + else if(db_mod6 == 2) + { + rval += 0x0040; + } + else if(db_mod6 == 3) + { + rval += 0x0070; + } + else if(db_mod6 == 4) + { + rval += 0x0090; + } + else /* if(db_mod6 == 5) */ + { + rval += 0x00D0; + } + + return rval; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteDebugChanMemory + +Description: This function configure a debug channel echo memory entry + in internal memory.and external memory. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pTdmConfig Pointer to a TDM configuration structure. +f_pVqeConfig Pointer to a VQE configuration structure. +f_pChannelOpen Pointer to a channel configuration structure. +f_usChanIndex Index of the echo channel in the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory. +f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteDebugChanMemory( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN UINT16 f_usRinRoutTsiIndex, + IN UINT16 f_usSinSoutTsiIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult; + + /* Obtain pointer to local portion of the instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /*==============================================================================*/ + /* Write the VQE configuration of the debug channel. */ + + ulResult = Oct6100ApiWriteVqeMemory( + f_pApiInstance, + f_pVqeConfig, + f_pChannelOpen, + f_usChanIndex, + f_usEchoMemIndex, + TRUE, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + + /*==============================================================================*/ + + /* Write the echo memory configuration of the debug channel. */ + ulResult = Oct6100ApiWriteEchoMemory( + f_pApiInstance, + f_pTdmConfig, + f_pChannelOpen, + f_usEchoMemIndex, + f_usRinRoutTsiIndex, + f_usSinSoutTsiIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*==============================================================================*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiDebugChannelOpen + +Description: Internal function used to open a debug channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiDebugChannelOpen( + IN tPOCT6100_INSTANCE_API f_pApiInstance ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_CHANNEL_OPEN TempChanOpen; + + UINT32 ulResult; + UINT16 usChanIndex; + UINT16 usDummyEchoIndex; + + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Let's program the channel memory.*/ + Oct6100ChannelOpenDef( &TempChanOpen ); + + TempChanOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_HT_RESET; /* Activate the channel in reset.*/ + TempChanOpen.VqeConfig.fEnableNlp = FALSE; + TempChanOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; + TempChanOpen.VqeConfig.fSinDcOffsetRemoval = FALSE; + TempChanOpen.VqeConfig.fRinDcOffsetRemoval = FALSE; + TempChanOpen.VqeConfig.lDefaultErlDb = 0; + + /* Loop to reserve the proper entry for the debug channel */ + for( usChanIndex = 0; usChanIndex < ( pSharedInfo->DebugInfo.usRecordChanIndex + 1 ); usChanIndex ++ ) + { + ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, &usDummyEchoIndex ); + if( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Loop to free all entries except the one for the debug channel */ + for( usChanIndex = pSharedInfo->DebugInfo.usRecordChanIndex; usChanIndex > 0; ) + { + usChanIndex--; + ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, usChanIndex ); + if( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, + &TempChanOpen.TdmConfig, + &TempChanOpen.VqeConfig, + &TempChanOpen, + pSharedInfo->DebugInfo.usRecordChanIndex, + pSharedInfo->DebugInfo.usRecordMemIndex, + pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex, + pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiMuteChannelPort + +Description: This function will verify if a input TSST is bound to the RIN and + SIN port. If not, the port will be muted. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiMutePorts( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usEchoIndex, + IN UINT16 f_usRinTsstIndex, + IN UINT16 f_usSinTsstIndex, + IN BOOL f_fCheckBridgeIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usEchoIndex ); + + /* Mute the Rin port. */ + if ( ( f_fCheckBridgeIndex == FALSE ) + || ( ( f_fCheckBridgeIndex == TRUE ) && ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ) ) + { + /* If the channel is in bidir mode, do not create the Rin silence event!!! */ + if ( pChanEntry->fBiDirChannel == FALSE ) + { + if ( ( ( f_usRinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) + && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) + { + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, + &pChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now, write the mixer event used to copy the RIN signal of the silence channel + into the RIN signal of the current channel. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usRinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= 1534; + WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now insert the Sin copy event into the list.*/ + + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + pChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY, + f_usEchoIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Mute the Sin port. */ + if ( ( ( f_usSinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) + && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) + { + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, + &pChanEntry->usSinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now, write the mixer event used to copy the SIN signal of the silence channel + into the SIN signal of the current channel. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= 1534; + WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now insert the Sin copy event into the list.*/ + + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + pChanEntry->usSinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY, + f_usEchoIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Unmute the Rin port if it was muted. */ + if ( ( ( f_usRinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) + && ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_E1; + + pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + /* Unmute the Sin port if it was muted. */ + if ( ( ( f_usSinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) + && ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usSinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usSinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_E2; + + pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiSetChannelLevelControl + +Description: This function will configure the level control on a given + channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig VQE config of the channel. +f_usChanIndex Index of the channel within the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_fClearAlcHlcStatusBit If this is set, the ALC-HLC status bit must be + incremented. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiSetChannelLevelControl( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN BOOL f_fClearAlcHlcStatusBit ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulMask; + UINT32 i; + UINT16 usTempData; + UINT8 byLastStatus; + BOOL fDisableAlcFirst; + + /* Get local pointer to shared portion of the API instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain a pointer to the channel list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); + + /* Before doing anything, check if the configuration has changed. */ + if ( ( f_fClearAlcHlcStatusBit == TRUE ) + || ( f_pVqeConfig->fRinLevelControl != pChanEntry->VqeConfig.fRinLevelControl ) + || ( f_pVqeConfig->lRinLevelControlGainDb != pChanEntry->VqeConfig.chRinLevelControlGainDb ) + || ( f_pVqeConfig->fRinAutomaticLevelControl != pChanEntry->VqeConfig.fRinAutomaticLevelControl ) + || ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb ) + || ( f_pVqeConfig->fRinHighLevelCompensation != pChanEntry->VqeConfig.fRinHighLevelCompensation ) + || ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb != pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb ) + || ( f_pVqeConfig->fSoutLevelControl != pChanEntry->VqeConfig.fSoutLevelControl ) + || ( f_pVqeConfig->lSoutLevelControlGainDb != pChanEntry->VqeConfig.chSoutLevelControlGainDb ) + || ( f_pVqeConfig->fSoutAutomaticLevelControl != pChanEntry->VqeConfig.fSoutAutomaticLevelControl ) + || ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb ) + || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) + || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) + || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) + { + /* Calculate base address for manual level control configuration. */ + ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + /* Set the Level control on RIN port.*/ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( ( f_pVqeConfig->fRinLevelControl == TRUE ) + || ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) + || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) + { + /* Set the level control value.*/ + if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) + || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) + ulTempData |= ( 0xFF << ulFeatureBitOffset ); + else + { + /* Convert the dB value into OctFloat format.*/ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lRinLevelControlGainDb ); + usTempData -= 0x3800; + usTempData &= 0x0FF0; + usTempData >>= 4; + + ulTempData |= ( usTempData << ulFeatureBitOffset ); + } + } + else /* ( ( f_pVqeConfig->fRinLevelControl == FALSE ) && ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) && ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) ) */ + { + ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); + } + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set the Level control on SOUT port.*/ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutLevelControlOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( ( f_pVqeConfig->fSoutLevelControl == TRUE ) + || ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) + || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) + || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) + { + /* Set the level control value.*/ + if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) + || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) + || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) + ulTempData |= ( 0xFF << ulFeatureBitOffset ); + else + { + /* Convert the dB value into OctFloat format.*/ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lSoutLevelControlGainDb ); + usTempData -= 0x3800; + usTempData &= 0x0FF0; + usTempData >>= 4; + + ulTempData |= ( usTempData << ulFeatureBitOffset ); + } + } + else + { + ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); + } + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Calculate base address for auto level control + high level compensation configuration. */ + ulBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + + /* Check which one is to be disabled first. */ + if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) + fDisableAlcFirst = FALSE; + else + fDisableAlcFirst = TRUE; + + for ( i = 0; i < 2; i ++ ) + { + /* Set the auto level control target Db for the Rin port. */ + if ( ( ( i == 0 ) && ( fDisableAlcFirst == TRUE ) ) || ( ( i == 1 ) && ( fDisableAlcFirst == FALSE ) ) ) + { + if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) + { + /* Convert the dB value into OctFloat format.*/ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinAutomaticLevelControlTargetDb ); + + /* Set auto level control target on the Rin port. */ + ulTempData |= ( usTempData << ulFeatureBitOffset ); + } + else /* if ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) */ + { + /* Disable auto level control. */ + ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); + } + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else + { + /* Set the high level compensation threshold Db for the Rin port. */ + if ( pSharedInfo->ImageInfo.fRinHighLevelCompensation == TRUE ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) + { + /* Convert the dB value into OctFloat format.*/ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinHighLevelCompensationThresholdDb ); + + /* Set high level compensation threshold on the Rin port. */ + ulTempData |= ( usTempData << ulFeatureBitOffset ); + } + else /* if ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) */ + { + /* Disable high level compensation. */ + ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); + } + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Set the auto level control target Db for the Sout port. */ + if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) + { + /* Convert the dB value into OctFloat format.*/ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lSoutAutomaticLevelControlTargetDb ); + + /* Set auto level control target on the Sout port. */ + ulTempData |= ( usTempData << ulFeatureBitOffset ); + } + else /* if ( f_pVqeConfig->fSoutAutomaticLevelControl == FALSE ) */ + { + /* Disable auto level control. */ + ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); + } + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Set the high level compensation threshold Db for the Sout port. */ + if ( pSharedInfo->ImageInfo.fSoutHighLevelCompensation == TRUE ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Disable high level compensation on Sout for now. */ + ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Check if have to clear the ALC-HLC status. */ + if ( ( pSharedInfo->ImageInfo.fAlcHlcStatus == TRUE ) + && ( f_fClearAlcHlcStatusBit == TRUE ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Get previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + /* Retrieve last status. */ + byLastStatus = (UINT8)( ( ( ulTempData & ulMask ) >> ulFeatureBitOffset ) & 0xFF ); + + /* Increment to reset context. */ + byLastStatus ++; + + /* Just in case, not to overwrite some context in external memory. */ + byLastStatus &= ( 0x1 << ulFeatureFieldLength ) - 1; + + /* Clear last status. */ + ulTempData &= (~ulMask); + + /* Set new status. */ + ulTempData |= ( byLastStatus << ulFeatureBitOffset ); + + /* Save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiSetChannelTailConfiguration + +Description: This function will configure the tail displacement and length + on a given channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pVqeConfig VQE config of the channel. +f_usChanIndex Index of the channel within the API instance. +f_usEchoMemIndex Index of the echo channel within the SSPX memory. +f_fModifyOnly Function called from a modify or open? + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiSetChannelTailConfiguration( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, + IN UINT16 f_usChanIndex, + IN UINT16 f_usEchoMemIndex, + IN BOOL f_fModifyOnly ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulNlpConfBaseAddress; + UINT32 ulAfConfBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulMask; + UINT32 ulTailSum; + BOOL fTailDisplacementModified = FALSE; + + /* Get local pointer to shared portion of the API instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Obtain a pointer to the channel list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); + + /* Calculate base addresses of NLP + AF configuration structure for the specified channel. */ + ulNlpConfBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + ulAfConfBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainIoMemOfst; + + /* Set the tail displacement.*/ + if ( pSharedInfo->ImageInfo.fTailDisplacement == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->fEnableTailDisplacement != pChanEntry->VqeConfig.fEnableTailDisplacement ) + || ( f_pVqeConfig->ulTailDisplacement != pChanEntry->VqeConfig.usTailDisplacement ) + || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) + { + /* Remember that the tail displacement parameters were changed. */ + fTailDisplacementModified = TRUE; + + /* Check if we must set the tail displacement value. */ + if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) + && ( pSharedInfo->ImageInfo.fPerChannelTailDisplacement == TRUE ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) + && ( f_pVqeConfig->ulTailDisplacement != 0x0 ) ) + { + if ( pSharedInfo->ImageInfo.fAfTailDisplacement == FALSE ) + { + if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); + } + else + { + ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); + } + } + else /* if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) */ + { + /* If AEC is not activated, this must be set to the requested tail displacement. */ + if ( f_pVqeConfig->fAcousticEcho == FALSE ) + { + if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; + } + else + { + ulTailSum = f_pVqeConfig->ulTailDisplacement; + } + + if ( ulTailSum == 0 ) + { + ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); + } + else if ( ulTailSum <= 128 ) + { + ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); + } + else if ( ulTailSum <= 384 ) + { + ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); + } + else /* if ( ulTailSum <= 896 ) */ + { + ulTempData |= ( ( 7 ) << ulFeatureBitOffset ); + } + } + else /* if ( f_pVqeConfig->fAcousticEcho == FALSE ) */ + { + /* Otherwise, the tail displacement is configured differently. This field stays to 0. */ + ulTempData |= ( 0x0 << ulFeatureBitOffset ); + } + } + } + + /* Then save the new DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) + { + /* Set the tail displacement offset in the AF. */ + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); + } + else + { + ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); + } + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + ulFeatureBytesOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.TailDisplEnableOfst.byFieldSize; + + /* First read the DWORD where the field is located.*/ + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + ulTempData |= ( ( (UINT32)f_pVqeConfig->fEnableTailDisplacement ) << ulFeatureBitOffset ); + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the tail length. */ + if ( pSharedInfo->ImageInfo.fPerChannelTailLength == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( ( f_fModifyOnly == TRUE ) + && ( f_pVqeConfig->ulTailLength != pChanEntry->VqeConfig.usTailLength ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + /* Check if must automatically select maximum or if must use user specific value. */ + if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTempData |= ( ( ( pSharedInfo->ImageInfo.usMaxTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); + } + else + { + ulTempData |= ( ( ( f_pVqeConfig->ulTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); + } + + /* Then save the DWORD where the field is located.*/ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulAfConfBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure AEC tail length. */ + if ( pSharedInfo->ImageInfo.fAecTailLength == TRUE ) + { + /* Check if the configuration has been changed. */ + if ( ( f_fModifyOnly == FALSE ) + || ( fTailDisplacementModified == TRUE ) + || ( ( f_fModifyOnly == TRUE ) + && ( ( f_pVqeConfig->ulAecTailLength != pChanEntry->VqeConfig.usAecTailLength ) + || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + ulTempData &= (~ulMask); + + /* Set acoustic echo tail length. */ + if ( f_pVqeConfig->fAcousticEcho == TRUE ) + { + switch( f_pVqeConfig->ulAecTailLength ) + { + case 1024: + ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); + break; + case 512: + ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); + break; + case 256: + ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); + break; + case 128: + default: + ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); + break; + } + } + else if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) + { + /* No acoustic echo case. */ + + /* Start with requested tail displacement. */ + if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; + } + else + { + ulTailSum = f_pVqeConfig->ulTailDisplacement; + } + + /* Add requested tail length. */ + if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) + { + ulTailSum += pSharedInfo->ImageInfo.usMaxTailLength; + } + else + { + ulTailSum += f_pVqeConfig->ulTailLength; + } + + /* Round this value up. */ + if ( ulTailSum <= 128 ) + { + ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); + } + else if ( ulTailSum <= 256 ) + { + ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); + } + else if ( ulTailSum <= 512 ) + { + ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); + } + else /* if ( ulTailSum <= 1024 ) */ + { + ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); + } + } + else + { + /* Keep this to zero. */ + ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); + } + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulNlpConfBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelMuteSer + +Description: This function will mute some of the ports on a given + channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelMute What channel/ports to mute. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelMuteSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MUTE f_pChannelMute ) +{ + UINT32 ulResult; + UINT16 usChanIndex; + UINT16 usPortMask; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertChannelMuteParams( f_pApiInstance, + f_pChannelMute, + &usChanIndex, + &usPortMask ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Call the actual channel mute ports function. */ + ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, + usChanIndex, + usPortMask, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertChannelMuteParams + +Description: Check the user parameters passed to the channel mute function. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelMute What channel/ports to mute. +f_pusChanIndex Resulting channel index where the muting should + be applied. +f_pusPorts Port mask on which to apply the muting. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertChannelMuteParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_MUTE f_pChannelMute, + OUT PUINT16 f_pusChanIndex, + OUT PUINT16 f_pusPorts ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulEntryOpenCnt; + + /* Get local pointer(s). */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Check the provided handle. */ + if ( (f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + if ( pChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; + + /*=======================================================================*/ + + /* Check the provided port mask. */ + + if ( ( f_pChannelMute->ulPortMask & + ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | + cOCT6100_CHANNEL_MUTE_PORT_RIN | + cOCT6100_CHANNEL_MUTE_PORT_ROUT | + cOCT6100_CHANNEL_MUTE_PORT_SIN | + cOCT6100_CHANNEL_MUTE_PORT_SOUT | + cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) + return cOCT6100_ERR_CHANNEL_MUTE_MASK; + + /* Sin + Sin with features cannot be muted simultaneously. */ + if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) + && ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) + return cOCT6100_ERR_CHANNEL_MUTE_MASK_SIN; + + /* Check if Sin mute with features is supported by the firmware. */ + if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) + && ( pSharedInfo->ImageInfo.fSinMute == FALSE ) ) + return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_MUTE_FEATURES; + + /* Return the ports to the calling function. */ + *f_pusPorts = (UINT16)( f_pChannelMute->ulPortMask & 0xFFFF ); + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ChannelUnMuteSer + +Description: This function will unmute some of the ports on a given + channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelUnMute What channel/ports to unmute. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ChannelUnMuteSer( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) +{ + UINT32 ulResult; + UINT16 usChanIndex; + UINT16 usPortMask; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertChannelUnMuteParams( f_pApiInstance, + f_pChannelUnMute, + &usChanIndex, + &usPortMask ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Call the actual channel mute ports function. */ + ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, + usChanIndex, + usPortMask, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertChannelUnMuteParams + +Description: Check the user parameters passed to the channel unmute function. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pChannelUnMute What channel/ports to Unmute. +f_pusChanIndex Resulting channel index where the muting should + be applied. +f_pusPorts Port mask on which to apply the muting. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertChannelUnMuteParams( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute, + OUT PUINT16 f_pusChanIndex, + OUT PUINT16 f_pusPorts ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + UINT32 ulEntryOpenCnt; + + /* Get local pointer(s). */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Check the provided handle. */ + if ( (f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + *f_pusChanIndex = (UINT16)( f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + + /*=======================================================================*/ + /* Get a pointer to the channel's list entry. */ + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = ( f_pChannelUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CHANNEL_NOT_OPEN; + if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; + if ( pChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; + + /*=======================================================================*/ + + /* Check the provided port mask. */ + + if ( ( f_pChannelUnMute->ulPortMask & + ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | + cOCT6100_CHANNEL_MUTE_PORT_RIN | + cOCT6100_CHANNEL_MUTE_PORT_ROUT | + cOCT6100_CHANNEL_MUTE_PORT_SIN | + cOCT6100_CHANNEL_MUTE_PORT_SOUT | + cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) + return cOCT6100_ERR_CHANNEL_MUTE_MASK; + + /* Return the ports to the calling function. */ + *f_pusPorts = (UINT16)( f_pChannelUnMute->ulPortMask & 0xFFFF ); + + return cOCT6100_ERR_OK; +} + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiMuteChannelPorts + +Description: Mute or Unmute the specified ports, according to the mask. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_usChanIndex Resulting channel index where the muting should + be applied. +f_usPortMask Port mask on which to apply the muting/unmuting. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiMuteChannelPorts( + IN tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChanIndex, + IN UINT16 f_usPortMask, + IN BOOL f_fMute ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pChanEntry; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + + UINT32 ulTempData; + UINT32 ulBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulMask; + BOOL fDisableSinWithFeatures = FALSE; + BOOL fEnableSinWithFeatures = FALSE; + + /* Get local pointer(s). */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + /* Rin port. */ + if ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) + { + /* Mute this port. */ + pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_RIN; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + { + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; + return ulResult; + } + } + else if ( ( f_fMute == FALSE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) + { + /* Unmute this port. */ + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Rout port. */ + if ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) ) + { + /* Mute this port. */ + + if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_ROUT; + } + else if ( ( f_fMute == FALSE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) ) + { + /* Unmute this port. */ + + if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + pChanEntry->usRoutTsstIndex, + pChanEntry->CodecConfig.byAdpcmNibblePosition, + pChanEntry->TdmConfig.byRoutNumTssts, + pChanEntry->usRinRoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_ROUT; + } + + /* Sin port. */ + if ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) + { + /* Mute this port. */ + pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + { + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; + return ulResult; + } + } + else if ( + ( ( f_fMute == FALSE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) + || + ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) ) + { + /* Unmute this port. */ + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; + + ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Sout port. */ + if ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) ) + { + /* Mute this port. */ + + if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SOUT; + } + else if ( ( f_fMute == FALSE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) ) + { + /* Unmute this port. */ + + if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, + pChanEntry->usSoutTsstIndex, + pChanEntry->CodecConfig.byAdpcmNibblePosition, + pChanEntry->TdmConfig.bySoutNumTssts, + pChanEntry->usSinSoutTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SOUT; + } + + /* Sin with features port. */ + if ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) == 0x0 ) ) + { + /* Mute this port. */ + pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; + fEnableSinWithFeatures = TRUE; + } + else if ( + ( ( f_fMute == FALSE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) + || + ( ( f_fMute == TRUE ) + && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) + && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) ) + { + /* Unmute this port. */ + pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; + + fDisableSinWithFeatures = TRUE; + } + + /* Check if must enable or disable SIN mute with features. */ + if ( fDisableSinWithFeatures == TRUE || fEnableSinWithFeatures == TRUE ) + { + ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + if ( pSharedInfo->ImageInfo.fSinMute == TRUE ) + { + ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinMuteOfst.usDwordOffset * 4; + ulFeatureBitOffset = pSharedInfo->MemoryMap.SinMuteOfst.byBitOffset; + ulFeatureFieldLength = pSharedInfo->MemoryMap.SinMuteOfst.byFieldSize; + + mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear previous value set in the feature field.*/ + mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); + + /* Clear the mute flag. */ + ulTempData &= (~ulMask); + + /* Set the mute flag on the Sin port.*/ + if ( fEnableSinWithFeatures == TRUE ) + ulTempData |= ( 0x1 << ulFeatureBitOffset ); + + /* Write the new DWORD where the field is located. */ + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + return cOCT6100_ERR_OK; +} |