summaryrefslogtreecommitdiff
path: root/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c')
-rw-r--r--software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c3275
1 files changed, 3275 insertions, 0 deletions
diff --git a/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c
new file mode 100644
index 0000000..c815095
--- /dev/null
+++ b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c
@@ -0,0 +1,3275 @@
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+File: oct6100_playout_buf.c
+
+ Copyright (c) 2001-2005 Octasic Inc.
+
+Description:
+
+ This file contains functions used to manage buffer playout.
+
+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: 109 $
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+
+
+/***************************** 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_channel_inst.h"
+#include "oct6100api/oct6100_playout_buf_inst.h"
+
+#include "oct6100api/oct6100_interrupts_pub.h"
+#include "oct6100api/oct6100_chip_open_pub.h"
+#include "oct6100api/oct6100_channel_pub.h"
+#include "oct6100api/oct6100_events_pub.h"
+#include "oct6100api/oct6100_playout_buf_pub.h"
+
+#include "oct6100_chip_open_priv.h"
+#include "oct6100_miscellaneous_priv.h"
+#include "oct6100_memory_priv.h"
+#include "oct6100_channel_priv.h"
+#include "oct6100_events_priv.h"
+#include "oct6100_playout_buf_priv.h"
+
+/**************************** PUBLIC FUNCTIONS *****************************/
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferPlayoutLoad
+
+Description: This function loads a playout buffer into 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_pBufferLoad Pointer to buffer playout load structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutLoadDef(
+ tPOCT6100_BUFFER_LOAD f_pBufferLoad )
+{
+ f_pBufferLoad->pbyBufferPattern = NULL;
+ f_pBufferLoad->ulBufferSize = 128;
+ f_pBufferLoad->ulBufferPcmLaw = cOCT6100_PCM_U_LAW;
+
+ f_pBufferLoad->pulBufferIndex = NULL;
+ f_pBufferLoad->pulPlayoutFreeMemSize = NULL;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutLoad(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_LOAD f_pBufferLoad )
+{
+ 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 = Oct6100BufferLoadSer( f_pApiInstance, f_pBufferLoad, TRUE, cOCT6100_INVALID_INDEX );
+ }
+ 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: Oct6100BufferPlayoutLoadBlockInit
+
+Description: This function allows the user to initialize loading a buffer
+ into external memory using blocks.
+
+-------------------------------------------------------------------------------
+| 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_pBufferLoadBlockInit Pointer to buffer playout load block init structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutLoadBlockInitDef(
+ tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit )
+{
+ f_pBufferLoadBlockInit->ulBufferSize = 128;
+ f_pBufferLoadBlockInit->ulBufferPcmLaw = cOCT6100_PCM_U_LAW;
+
+ f_pBufferLoadBlockInit->pulBufferIndex = NULL;
+ f_pBufferLoadBlockInit->pulPlayoutFreeMemSize = NULL;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutLoadBlockInit(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit )
+{
+ 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 = Oct6100BufferLoadBlockInitSer( f_pApiInstance, f_pBufferLoadBlockInit );
+ }
+ 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: Oct6100BufferPlayoutLoadBlock
+
+Description: This function allows the user to load a buffer block into
+ 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_pBufferLoadBlock Pointer to buffer playout load block structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutLoadBlockDef(
+ tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock )
+{
+ f_pBufferLoadBlock->ulBufferIndex = cOCT6100_INVALID_VALUE;
+ f_pBufferLoadBlock->ulBlockLength = cOCT6100_INVALID_VALUE;
+ f_pBufferLoadBlock->ulBlockOffset = cOCT6100_INVALID_VALUE;
+
+ f_pBufferLoadBlock->pbyBufferPattern = NULL;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutLoadBlock(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock )
+{
+ 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 = Oct6100BufferLoadBlockSer( f_pApiInstance, f_pBufferLoadBlock );
+ }
+ 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: Oct6100BufferPlayoutUnload
+
+Description: This function unloads a playout buffer from 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_pBufferUnload Pointer to buffer playout unload structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutUnloadDef(
+ tPOCT6100_BUFFER_UNLOAD f_pBufferUnload )
+{
+ f_pBufferUnload->ulBufferIndex = cOCT6100_INVALID_VALUE;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutUnload(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_UNLOAD f_pBufferUnload )
+{
+ 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 = Oct6100BufferUnloadSer( f_pApiInstance, f_pBufferUnload, TRUE );
+ }
+ 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: Oct6100BufferPlayoutAdd
+
+Description: This function adds a buffer to a port's playout list on the
+ selected 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_pBufferPlayoutAdd Pointer to buffer playout add structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutAddDef(
+ tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd )
+{
+ f_pBufferPlayoutAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+ f_pBufferPlayoutAdd->ulBufferIndex = cOCT6100_INVALID_VALUE;
+
+ f_pBufferPlayoutAdd->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT;
+ f_pBufferPlayoutAdd->ulMixingMode = cOCT6100_MIXING_MINUS_6_DB;
+ f_pBufferPlayoutAdd->lGainDb = 0;
+
+ f_pBufferPlayoutAdd->fRepeat = FALSE;
+ f_pBufferPlayoutAdd->ulRepeatCount = cOCT6100_REPEAT_INFINITELY;
+
+ f_pBufferPlayoutAdd->ulDuration = cOCT6100_INVALID_VALUE;
+
+ f_pBufferPlayoutAdd->ulBufferLength = cOCT6100_AUTO_SELECT;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutAdd(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd )
+{
+ 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 = Oct6100BufferPlayoutAddSer( f_pApiInstance, f_pBufferPlayoutAdd );
+ }
+ 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: Oct6100BufferPlayoutStart
+
+Description: This function enables playout of the specified buffer on the
+ requested 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_pBufferPlayoutStart Pointer to buffer playout start structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutStartDef(
+ tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart )
+{
+ f_pBufferPlayoutStart->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+ f_pBufferPlayoutStart->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT;
+ f_pBufferPlayoutStart->fNotifyOnPlayoutStop = FALSE;
+ f_pBufferPlayoutStart->ulUserEventId = cOCT6100_INVALID_VALUE;
+ f_pBufferPlayoutStart->fAllowStartWhileActive = FALSE;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutStart(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart )
+{
+ 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 = Oct6100BufferPlayoutStartSer( f_pApiInstance, f_pBufferPlayoutStart, cOCT6100_BUFFER_PLAYOUT_EVENT_STOP );
+ }
+ 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: Oct6100BufferPlayoutStop
+
+Description: This function disables playout of a buffer on 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_pBufferPlayoutStop Pointer to buffer playout stop structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutStopDef(
+ tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop )
+{
+ f_pBufferPlayoutStop->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+ f_pBufferPlayoutStop->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT;
+ f_pBufferPlayoutStop->fStopCleanly = TRUE;
+ f_pBufferPlayoutStop->pfAlreadyStopped = NULL;
+ f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = NULL;
+
+ return cOCT6100_ERR_OK;
+}
+
+UINT32 Oct6100BufferPlayoutStop(
+ tPOCT6100_INSTANCE_API f_pApiInstance,
+ tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop )
+{
+ 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 = Oct6100BufferPlayoutStopSer( f_pApiInstance, f_pBufferPlayoutStop );
+ }
+ 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: Oct6100ApiGetPlayoutBufferSwSizes
+
+Description: Gets the sizes of all portions of the API instance pertinent
+ to the management of playout buffers.
+
+-------------------------------------------------------------------------------
+| Argument | Description
+-------------------------------------------------------------------------------
+f_pOpenChip Pointer to chip configuration struct.
+f_pInstSizes Pointer to struct containing instance sizes.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiGetPlayoutBufferSwSizes(
+ IN tPOCT6100_CHIP_OPEN f_pOpenChip,
+ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes )
+{
+ UINT32 ulTempVar;
+ UINT32 ulResult;
+
+ /* Calculate memory needed for playout buffer list. */
+ f_pInstSizes->ulPlayoutBufList = f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER );
+
+ f_pInstSizes->ulPlayoutBufMemoryNodeList = 0;
+
+ /* Calculate memory needed for playout buffer allocation software. */
+ if ( f_pOpenChip->ulMaxPlayoutBuffers > 0 )
+ {
+ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxPlayoutBuffers, &f_pInstSizes->ulPlayoutBufAlloc );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return cOCT6100_ERR_FATAL_3C;
+
+ f_pInstSizes->ulPlayoutBufMemoryNodeList = 2 * f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE );
+ }
+ else
+ {
+ f_pInstSizes->ulPlayoutBufAlloc = 0;
+ }
+
+ /* Calculate memory needed for list and allocation software serialization. */
+ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufList, ulTempVar )
+ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufAlloc, ulTempVar )
+ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufMemoryNodeList, ulTempVar )
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiPlayoutBufferSwInit
+
+Description: Initializes all elements of the instance structure associated
+ to playout buffers.
+
+-------------------------------------------------------------------------------
+| 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 Oct6100ApiPlayoutBufferSwInit(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance )
+{
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tPOCT6100_API_BUFFER pBufferList;
+ PVOID pBufferPlayoutAlloc;
+ UINT32 ulMaxBufferPlayout;
+ UINT32 ulResult, i;
+
+ /* Get local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ /* Get the maximum number of buffer playout. */
+ ulMaxBufferPlayout = pSharedInfo->ChipConfig.usMaxPlayoutBuffers;
+
+ /* Set all entries in the buffer playout list to unused. */
+ mOCT6100_GET_BUFFER_LIST_PNT( pSharedInfo, pBufferList )
+
+ for ( i = 0; i < ulMaxBufferPlayout; i++ )
+ {
+ pBufferList[ i ].fReserved = FALSE;
+ pBufferList[ i ].ulBufferSize = 0;
+ pBufferList[ i ].ulBufferBase = cOCT6100_INVALID_VALUE;
+ pBufferList[ i ].usDependencyCnt = 0;
+ pBufferList[ i ].byBufferPcmLaw = cOCT6100_PCM_U_LAW;
+
+ }
+
+ /* Initialize the buffer playout allocation software to "all free". */
+ if ( ulMaxBufferPlayout > 0 )
+ {
+ mOCT6100_GET_BUFFER_ALLOC_PNT( pSharedInfo, pBufferPlayoutAlloc )
+
+ ulResult = OctapiLlmAllocInit( &pBufferPlayoutAlloc, ulMaxBufferPlayout );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return cOCT6100_ERR_FATAL_3D;
+ }
+
+ /* Initialize the amount of free memory used by playout. */
+ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed = 0;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferLoadSer
+
+Description: Loads a buffer in 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_pBufferLoad Pointer to buffer configuration structure. The handle
+ identifying the buffer in all future function calls is
+ returned in this structure.
+
+f_fReserveListStruct Flag indicating if a list structure should be reserved
+ or if the structure has been reserved before. If this
+ is set, the f_ulBufIndex variable must also be set.
+
+f_ulBufIndex If the f_fReserveListStruct flag is set, this index
+ will identify the buffer playout list structure
+ that must be used to load the specified buffer.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferLoadSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad,
+ IN BOOL f_fReserveListStruct,
+ IN UINT32 f_ulBufIndex )
+{
+ UINT32 ulBufferIndex;
+ UINT32 ulBufferBase;
+ UINT32 ulResult;
+
+ /* Check the user's configuration of the buffer for errors. */
+ ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, f_pBufferLoad, TRUE );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Reserve all resources needed by the buffer. */
+ ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, f_pBufferLoad, f_fReserveListStruct, f_ulBufIndex, &ulBufferIndex, &ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Write the buffer in external memory. */
+ ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase, f_pBufferLoad->ulBufferSize, f_pBufferLoad->pbyBufferPattern );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Update the new buffer's entry in the buffer list. */
+ ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, f_pBufferLoad, ulBufferIndex, ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferLoadBlockInitSer
+
+Description: Reserve resources for loading a buffer into 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_pBufferLoadBlockInit Pointer to buffer configuration structure. The
+ handle identifying the buffer in all future
+ function calls is returned in this structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferLoadBlockInitSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit )
+{
+ UINT32 ulBufferIndex;
+ UINT32 ulBufferBase;
+ UINT32 ulResult;
+ tOCT6100_BUFFER_LOAD BufferLoad;
+
+ Oct6100BufferPlayoutLoadDef( &BufferLoad );
+
+ /* Not to replicate the code, we use the BufferLoad functions directly. */
+ BufferLoad.pulBufferIndex = f_pBufferLoadBlockInit->pulBufferIndex;
+ BufferLoad.pulPlayoutFreeMemSize = f_pBufferLoadBlockInit->pulPlayoutFreeMemSize;
+ BufferLoad.ulBufferPcmLaw = f_pBufferLoadBlockInit->ulBufferPcmLaw;
+ BufferLoad.ulBufferSize = f_pBufferLoadBlockInit->ulBufferSize;
+ BufferLoad.pbyBufferPattern = NULL; /* Must not check this for now */
+
+ /* Check the user's configuration of the buffer for errors, but do */
+ /* not check if the buffer pointer is NULL. It is NULL for sure! */
+ ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, &BufferLoad, FALSE );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Reserve all resources needed by the buffer. */
+ ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, &BufferLoad, TRUE, cOCT6100_INVALID_INDEX, &ulBufferIndex, &ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Update the new buffer's entry in the buffer list. */
+ ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, &BufferLoad, ulBufferIndex, ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferLoadBlockSer
+
+Description: Loads a buffer in external memory using blocks.
+
+-------------------------------------------------------------------------------
+| 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_pBufferLoadBlock Pointer to buffer block to be loaded into external
+ memory descriptor.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferLoadBlockSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock )
+{
+ UINT32 ulBufferBase;
+ UINT32 ulResult;
+
+ /* Check the user's configuration for errors. */
+ ulResult = Oct6100ApiCheckBufferLoadBlockParams( f_pApiInstance, f_pBufferLoadBlock, &ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Write the buffer in external memory at the appropriate offset - must do some pointer arithmetic. */
+ ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase + f_pBufferLoadBlock->ulBlockOffset,
+ f_pBufferLoadBlock->ulBlockLength, f_pBufferLoadBlock->pbyBufferPattern + f_pBufferLoadBlock->ulBlockOffset );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiCheckBufferParams
+
+Description: Checks the user's buffer playout load 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_pBufferLoad Pointer to buffer configuration structure.
+f_fCheckBufferPtr Check if the buffer pointer is NULL or not.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiCheckBufferParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad,
+ IN BOOL f_fCheckBufferPtr )
+{
+ /* Check for errors. */
+ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED;
+
+ if ( f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayout == FALSE )
+ return cOCT6100_ERR_NOT_SUPPORTED_BUFFER_PLAYOUT;
+
+ if ( f_pBufferLoad->pulBufferIndex == NULL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX;
+
+ if( f_fCheckBufferPtr )
+ {
+ if ( f_pBufferLoad->pbyBufferPattern == NULL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN;
+ }
+
+ if ( f_pBufferLoad->ulBufferSize < cOCT6100_MINIMUM_BUFFER_SIZE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL;
+
+ if ( ( f_pBufferLoad->ulBufferSize % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE;
+
+ if ( f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_U_LAW &&
+ f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_A_LAW )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PCM_LAW;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiCheckBufferLoadBlockParams
+
+Description: Checks the user's buffer playout load block 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_pBufferLoadBlock Pointer to buffer block descriptor.
+f_pulBufferBase Pointer to the base address of the buffer in external
+ memory.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiCheckBufferLoadBlockParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock,
+ OUT PUINT32 f_pulBufferBase )
+{
+ /* Check for errors. */
+ tPOCT6100_API_BUFFER pBufEntry;
+
+ if ( f_pBufferLoadBlock->ulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX;
+
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_pBufferLoadBlock->ulBufferIndex )
+
+ if ( pBufEntry->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN;
+
+ if ( ( f_pBufferLoadBlock->ulBlockLength % 2 ) != 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_LENGTH_INVALID;
+
+ if ( ( f_pBufferLoadBlock->ulBlockOffset % 2 ) != 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_OFFSET_INVALID;
+
+ if ( f_pBufferLoadBlock->pbyBufferPattern == NULL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN;
+
+ /* Check boundaries */
+ if ( ( f_pBufferLoadBlock->ulBlockLength + f_pBufferLoadBlock->ulBlockOffset ) > pBufEntry->ulBufferSize )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE;
+
+ *f_pulBufferBase = pBufEntry->ulBufferBase;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiReserveBufferResources
+
+Description: Reserves all resources needed for the new buffer.
+
+-------------------------------------------------------------------------------
+| 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_pBufferLoad Pointer to buffer configuration structure.
+
+f_fReserveListStruct Flag indicating if a list structure should be reserved
+ or if the structure has been reserved before.
+
+f_ulBufIndex If the f_fReserveListStruct flag is set, this index
+ will identifying the buffer playout list structure
+ that must be used to load the specified buffer.
+
+f_pulBufferIndex Allocated entry in buffer playout list.
+
+f_pulBufferBase Allocated external memory block for the buffer.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiReserveBufferResources(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_LOAD f_pBufferLoad,
+ IN BOOL f_fReserveListStruct,
+ IN UINT32 f_ulBufIndex,
+ OUT PUINT32 f_pulBufferIndex,
+ OUT PUINT32 f_pulBufferBase )
+{
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ UINT32 ulResult = cOCT6100_ERR_OK;
+ UINT32 ulTempVar;
+
+ /* Obtain local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ /* Reserve an entry in the buffer list. */
+ if ( f_fReserveListStruct == TRUE )
+ {
+ ulResult = Oct6100ApiReserveBufPlayoutListEntry( f_pApiInstance, f_pulBufferIndex );
+ }
+ else
+ {
+ *f_pulBufferIndex = f_ulBufIndex;
+ }
+ if ( ulResult == cOCT6100_ERR_OK )
+ {
+ /* Find a free block to store the buffer. */
+ ulResult = Oct6100ApiReserveBufferPlayoutMemory( f_pApiInstance, f_pBufferLoad->ulBufferSize, f_pulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ {
+ /* Release the list entry. */
+ if ( f_fReserveListStruct == TRUE )
+ {
+ ulTempVar = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, *f_pulBufferIndex );
+ if ( ulTempVar != cOCT6100_ERR_OK )
+ return ulTempVar;
+ }
+ }
+ }
+
+ return ulResult;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiWriteBufferInMemory
+
+Description: Writes the buffer in 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_ulBufferBase Allocated external memory address for the buffer.
+
+f_ulBufferLength Length in bytes of the buffer to be copied in memory.
+
+f_pbyBuffer Address where the buffer should be copied from.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiWriteBufferInMemory(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN UINT32 f_ulBufferBase,
+ IN UINT32 f_ulBufferLength,
+ IN PUINT8 f_pbyBuffer )
+{
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tOCT6100_WRITE_BURST_PARAMS BurstParams;
+ tOCT6100_WRITE_PARAMS WriteParams;
+ UINT32 ulResult;
+ UINT32 ulNumWrites;
+ PUINT16 pusSuperArray;
+ PUINT8 pbyPlayoutBuffer;
+ UINT32 ulByteCount = 0;
+ UINT32 i;
+
+ /* Get local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ /* Set the process context and user chip ID parameters once and for all. */
+ BurstParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+
+ WriteParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+
+ /* Write the buffer in external memory. */
+ ulNumWrites = f_ulBufferLength / 2;
+
+ BurstParams.ulWriteAddress = f_ulBufferBase;
+ BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray;
+
+ pusSuperArray = pSharedInfo->MiscVars.ausSuperArray;
+ pbyPlayoutBuffer = f_pbyBuffer;
+
+ /* Check if we can maximize the bandwidth through the CPU port. */
+ if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 )
+ {
+ WriteParams.ulWriteAddress = 0x234;
+ WriteParams.usWriteData = 0x08ff;
+ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+
+ while ( ulNumWrites != 0 )
+ {
+ if ( ulNumWrites >= pSharedInfo->ChipConfig.usMaxRwAccesses )
+ BurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses;
+ else
+ BurstParams.ulWriteLength = ulNumWrites;
+
+ for ( i = 0; i < BurstParams.ulWriteLength; i++ )
+ {
+ pusSuperArray[ i ] = ( UINT16 )(( pbyPlayoutBuffer [ ulByteCount++ ]) << 8);
+ pusSuperArray[ i ] |= ( UINT16 )pbyPlayoutBuffer [ ulByteCount++ ];
+ }
+
+ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult )
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength;
+ ulNumWrites -= BurstParams.ulWriteLength;
+
+ }
+
+ /* Make sure we revert back the changes made to the CPU bandwidth register. */
+ if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 )
+ {
+ WriteParams.ulWriteAddress = 0x234;
+ WriteParams.usWriteData = 0x0804;
+ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiUpdateBufferEntry
+
+Description: Updates the new buffer's entry in the buffer playout 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_pBufferLoad Pointer to buffer configuration structure.
+f_ulBufferIndex Allocated entry in buffer playout list.
+f_ulBufferBase Allocated external memory block for the buffer.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiUpdateBufferEntry(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad,
+ IN UINT32 f_ulBufferIndex,
+ IN UINT32 f_ulBufferBase )
+{
+ tPOCT6100_API_BUFFER pBufEntry;
+ UINT32 ulBufferSize = f_pBufferLoad->ulBufferSize;
+
+ /* Obtain a pointer to the new buffer's list entry. */
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex )
+
+ /* Copy the buffer's configuration and allocated resources. */
+ pBufEntry->ulBufferSize = f_pBufferLoad->ulBufferSize;
+ pBufEntry->byBufferPcmLaw = (UINT8)( f_pBufferLoad->ulBufferPcmLaw & 0xFF );
+ pBufEntry->ulBufferBase = f_ulBufferBase;
+
+ /* Update the entries flags. */
+ pBufEntry->usDependencyCnt = 0;
+
+ /* Mark the buffer as opened. */
+ pBufEntry->fReserved = TRUE;
+
+ /* Increment the number of buffer loaded into the chip.*/
+ f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers++;
+
+ /* Refresh the amount of memory used by buffer playout. */
+
+ /* Reserved size is divisible by 64. */
+ if ( ulBufferSize % 64 )
+ ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) );
+ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed += ulBufferSize;
+
+ /* Return the buffer index to the user. */
+ *f_pBufferLoad->pulBufferIndex = f_ulBufferIndex;
+
+ /* Return the amount of free memory left in the chip. */
+ /* Note that this value does not give the "fragmentation" state of the available memory. */
+ /* This value only gives the amount of free memory */
+ if( f_pBufferLoad->pulPlayoutFreeMemSize )
+ *f_pBufferLoad->pulPlayoutFreeMemSize = ( f_pApiInstance->pSharedInfo->MiscVars.ulTotalMemSize - ( f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress - cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ) - ( f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed );
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferUnloadSer
+
+Description: Unloads a buffer from 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_pBufferUnload Pointer to buffer unload structure.
+f_fReleaseListStruct Whether to release the buffer playout list structure
+ or not.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferUnloadSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload,
+ IN BOOL f_fReleaseListStruct )
+{
+ UINT32 ulBufferIndex;
+ UINT32 ulBufferBase;
+ UINT32 ulResult;
+
+ /* Verify that all the parameters given match the state of the API. */
+ ulResult = Oct6100ApiAssertBufferParams( f_pApiInstance, f_pBufferUnload, &ulBufferIndex, &ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Release all resources associated to the unloaded buffer. */
+ ulResult = Oct6100ApiReleaseBufferResources( f_pApiInstance, ulBufferIndex, ulBufferBase, f_fReleaseListStruct );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiAssertBufferParams
+
+Description: Checks the buffer playout unload 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_pBufferUnload Pointer to buffer unload structure.
+f_pulBufferIndex Pointer to the index of the buffer in the API's buffers list.
+f_pulBufferBase Pointer to the base address of the buffer in external memory.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiAssertBufferParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_UNLOAD f_pBufferUnload,
+ OUT PUINT32 f_pulBufferIndex,
+ OUT PUINT32 f_pulBufferBase )
+{
+ tPOCT6100_API_BUFFER pBufEntry;
+
+ *f_pulBufferIndex = f_pBufferUnload->ulBufferIndex;
+
+ if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX;
+
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, *f_pulBufferIndex )
+
+ /* Check for errors. */
+ if ( pBufEntry->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN;
+ if ( pBufEntry->usDependencyCnt != 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ACTIVE_DEPENDENCIES;
+
+ /* Return all info needed to invalidate buffer. */
+ *f_pulBufferBase = pBufEntry->ulBufferBase;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiReleaseBufferResources
+
+Description: Release resources needed by the buffer.
+
+-------------------------------------------------------------------------------
+| 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_ulBufferIndex Allocated entry in buffer playout list.
+f_ulBufferBase Allocated external memory block for the buffer.
+f_fReleaseListStruct Free the list structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiReleaseBufferResources(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN UINT32 f_ulBufferIndex,
+ IN UINT32 f_ulBufferBase,
+ IN BOOL f_fReleaseListStruct )
+{
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tPOCT6100_API_BUFFER pBufEntry;
+ UINT32 ulResult;
+ UINT32 ulBufferSize;
+
+ /* Obtain local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ /* Free the external memory reserved for the buffer. */
+ ulResult = Oct6100ApiReleaseBufferPlayoutMemory( f_pApiInstance, f_ulBufferBase );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return cOCT6100_ERR_FATAL_3E;
+
+ /* Release the entry from the buffer list. */
+ if ( f_fReleaseListStruct == TRUE )
+ ulResult = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, f_ulBufferIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex );
+
+ /* Save buffer size before releasing that entry, will be needed to calculate the amount of */
+ /* free memory left for the user. */
+ ulBufferSize = pBufEntry->ulBufferSize;
+
+ /* Flag the buffer entry as free. */
+ pBufEntry->fReserved = FALSE;
+
+ /* Decrement the number of buffer loaded into the chip. */
+ f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers--;
+
+ /* Refresh the amount of memory used by buffer playout. */
+ /* Reserved size is divisible by 64. */
+ if ( ulBufferSize % 64 )
+ ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) );
+ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed -= ulBufferSize;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferPlayoutAddSer
+
+Description: This function adds a buffer to a channel buffer 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_pBufferPlayoutAdd Pointer to buffer playout add structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutAddSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd )
+{
+ UINT32 ulBufferIndex;
+ UINT32 ulChannelIndex;
+ UINT32 ulResult;
+
+ /* Check the user's configuration of the buffer for errors. */
+ ulResult = Oct6100ApiCheckPlayoutAddParams( f_pApiInstance, f_pBufferPlayoutAdd, &ulChannelIndex, &ulBufferIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Write to all resources needed to activate buffer playout. */
+ ulResult = Oct6100ApiWriteBufferAddStructs( f_pApiInstance, f_pBufferPlayoutAdd, ulChannelIndex, ulBufferIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiCheckPlayoutAddParams
+
+Description: Check the validity of the channel and buffer requested.
+
+-------------------------------------------------------------------------------
+| 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_pBufferPlayoutAdd Pointer to buffer playout add structure.
+f_pulChannelIndex Pointer to the channel index of the selected channel.
+f_pulBufferIndex Pointer to the buffer index within the API's buffer list.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiCheckPlayoutAddParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd,
+ OUT PUINT32 f_pulChannelIndex,
+ OUT PUINT32 f_pulBufferIndex )
+{
+ tPOCT6100_API_BUFFER pBufferEntry;
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ UINT32 ulEntryOpenCnt;
+
+ /* Check for errors. */
+ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED;
+
+ if ( f_pBufferPlayoutAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ if ( f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT &&
+ f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT;
+
+ if ( f_pBufferPlayoutAdd->fRepeat != TRUE && f_pBufferPlayoutAdd->fRepeat != FALSE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT;
+
+ if ( f_pBufferPlayoutAdd->fRepeat == TRUE )
+ {
+ if ( f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY )
+ {
+ if ( f_pBufferPlayoutAdd->ulRepeatCount == 0x0
+ || f_pBufferPlayoutAdd->ulRepeatCount > cOCT6100_REPEAT_MAX)
+ {
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT_COUNT;
+ }
+ }
+ }
+
+ if ( f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_0_DB &&
+ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_6_DB &&
+ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_12_DB &&
+ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MUTE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_MIXING;
+
+ if ( ( f_pBufferPlayoutAdd->lGainDb < -24 )
+ || ( f_pBufferPlayoutAdd->lGainDb > 24 ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_GAIN_DB;
+
+ /*=====================================================================*/
+ /* Check the channel handle. */
+
+ if ( (f_pBufferPlayoutAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ *f_pulChannelIndex = f_pBufferPlayoutAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK;
+ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex )
+
+ /* Extract the entry open count from the provided handle. */
+ ulEntryOpenCnt = (f_pBufferPlayoutAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
+
+ /* Check for errors. */
+ if ( pEchoChannel->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN;
+ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ /* Check if repeat flag has been used for this port. */
+ if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) )
+ || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_REPEAT_USED;
+
+ /*=====================================================================*/
+
+ /*=====================================================================*/
+ /* Check the buffer information. */
+
+ *f_pulBufferIndex = f_pBufferPlayoutAdd->ulBufferIndex;
+ if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX;
+
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, *f_pulBufferIndex )
+
+ if ( pBufferEntry->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN;
+
+ /* Check if the play length is not larger then the currently uploaded buffer. */
+ if ( ( f_pBufferPlayoutAdd->ulBufferLength > pBufferEntry->ulBufferSize ) &&
+ ( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE;
+
+ if( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT )
+ {
+ if ( f_pBufferPlayoutAdd->ulBufferLength < cOCT6100_MINIMUM_BUFFER_SIZE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL;
+
+ if ( ( f_pBufferPlayoutAdd->ulBufferLength % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE;
+ }
+
+ /*=====================================================================*/
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiWriteBufferAddStructs
+
+Description: Write the buffer playout event in the channel's port playout
+ circular buffer.
+
+-------------------------------------------------------------------------------
+| 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_pBufferPlayoutAdd Pointer to buffer playout add structure.
+f_ulChannelIndex Index of the channel on which the buffer is to be added.
+f_ulBufferIndex Index of the buffer structure within the API's buffer list.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiWriteBufferAddStructs(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd,
+ IN UINT32 f_ulChannelIndex,
+ IN UINT32 f_ulBufferIndex )
+{
+ tPOCT6100_API_BUFFER pBufferEntry;
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tOCT6100_READ_PARAMS ReadParams;
+ UINT32 ulResult;
+ UINT32 ulTempData;
+ UINT32 ulEventBuffer;
+
+ UINT32 ulReadPtrBytesOfst;
+ UINT32 ulReadPtrBitOfst;
+ UINT32 ulReadPtrFieldSize;
+
+ UINT32 ulWritePtrBytesOfst;
+ UINT32 ulWritePtrBitOfst;
+ UINT32 ulWritePtrFieldSize;
+
+ UINT32 ulWritePtr;
+ UINT32 ulReadPtr;
+
+ UINT32 ulPlayoutBaseAddress;
+ UINT32 ulAddress;
+ UINT32 ulEventIndex;
+ UINT32 ulMask;
+
+ UINT32 ulRepeatCount = 0;
+ BOOL fRepeatCountSet = FALSE;
+ UINT32 ulDurationModulo = 0;
+ UINT32 ulEventsToCreate = 1;
+ UINT32 ulBufferDurationMs;
+
+ UINT32 ulBufferLength;
+ UINT16 usTempData = 0;
+
+ UINT16 usReadData;
+ UINT32 ulChipWritePtr;
+ UINT32 ulReadData;
+ UINT32 ulLoopCnt = 0;
+ BOOL fStillPlaying = TRUE;
+ BOOL fCheckHardStop = FALSE;
+ BOOL fOldBufferPlayoutVersion = FALSE;
+
+ UINT32 aulWaitTime[ 2 ];
+
+ /* Obtain local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex );
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex );
+
+ /* Select the buffer of interest. */
+ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst;
+ ulWritePtr = pEchoChannel->ulRinBufWritePtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4;
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset;
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize;
+
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize;
+ }
+ else /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst;
+ ulWritePtr = pEchoChannel->ulSoutBufWritePtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4;
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset;
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize;
+
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize;
+ }
+
+ /*=======================================================================*/
+ /* Calculate the repeat count. */
+
+ /* The buffer length is either the total buffer size or the value specified by the user */
+ if ( f_pBufferPlayoutAdd->ulBufferLength == cOCT6100_AUTO_SELECT )
+ {
+ ulBufferLength = pBufferEntry->ulBufferSize;
+ }
+ else
+ {
+ ulBufferLength = f_pBufferPlayoutAdd->ulBufferLength;
+ }
+
+ if ( f_pBufferPlayoutAdd->ulDuration != cOCT6100_INVALID_VALUE )
+ {
+ /* With duration and buffer length, we can find the number of times we must repeat playing this buffer. */
+ ulBufferDurationMs = ulBufferLength / cOCT6100_SAMPLES_PER_MS;
+ ulRepeatCount = f_pBufferPlayoutAdd->ulDuration / ulBufferDurationMs;
+ fRepeatCountSet = TRUE;
+
+ /* Check if buffer is larger then asked duration. */
+ if ( ulRepeatCount != 0x0 )
+ {
+ /* We might have to create more then 1 event to accomodate for the repeat-max limit. */
+ ulEventsToCreate = ( ulRepeatCount / cOCT6100_REPEAT_MAX ) + 1;
+ }
+ else
+ {
+ /* No repeat event. Maybe only the duration modulo! */
+ ulEventsToCreate = 0x0;
+ }
+
+ /* Check if must create a second event for a buffer that cannot be played completely. */
+ ulDurationModulo = f_pBufferPlayoutAdd->ulDuration % ulBufferDurationMs;
+ if ( ulDurationModulo != 0x0 )
+ {
+ ulDurationModulo *= cOCT6100_SAMPLES_PER_MS;
+ if ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY )
+ {
+ /* Round the modulo to be on a buffer size granularity. */
+ /* This will round down. */
+ ulDurationModulo = ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY ) * cOCT6100_BUFFER_SIZE_GRANULARITY;
+
+ /* If the event about to be created is smaller then the minimum buffer size, */
+ /* round up to the minimum required by the hardware. */
+ if ( ulDurationModulo < cOCT6100_MINIMUM_BUFFER_SIZE )
+ ulDurationModulo = cOCT6100_MINIMUM_BUFFER_SIZE;
+ ulEventsToCreate++;
+ }
+ else
+ {
+ /* The modulo is too small to be played. Skip. */
+ ulDurationModulo = 0;
+ }
+ }
+ }
+ else if ( f_pBufferPlayoutAdd->fRepeat == TRUE
+ && f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY )
+ {
+ /* The repeat count is set directly from the user. */
+ ulRepeatCount = f_pBufferPlayoutAdd->ulRepeatCount;
+ fRepeatCountSet = TRUE;
+ }
+
+ /*=======================================================================*/
+
+ /* Set the playout feature base address. */
+ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst;
+
+ /* Read the read pointer. */
+ ulAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst;
+
+ /* Must read in memory directly since this value is changed by hardware. */
+ ulResult = Oct6100ApiReadDword( f_pApiInstance, ulAddress, &ulTempData );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask );
+
+ /* Store the read pointer. */
+ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst;
+
+ /* Compare the pointers... Are they different? If so, there is something already in the list. */
+ if ( ulReadPtr != ulWritePtr )
+ {
+ /* Check if there is enough room for the playout events. */
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE )
+ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) )
+ {
+ /* 127 or 31 events image. */
+ if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) )
+ fCheckHardStop = TRUE;
+ }
+ else
+ {
+ /* Old 31 events image. */
+ if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) )
+ fCheckHardStop = TRUE;
+
+ fOldBufferPlayoutVersion = TRUE;
+ }
+
+ if ( fCheckHardStop == TRUE )
+ {
+ /* Ok. From what was read, the list is full. But we might still have a chance if the hard-stop */
+ /* version was used. In this case, some of the buffers in the list might */
+ /* become free in a couple of milliseconds, so try to wait for this. */
+
+ if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) )
+ || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) )
+ {
+ /* Read the 'chip' write pointer in the hardware. */
+ ReadParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+ ReadParams.pusReadData = &usReadData;
+ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst;
+
+ /* Get the write pointer in the chip. */
+ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask );
+
+ /* Store the write pointer. */
+ ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst;
+
+ /* Optimize this access by only reading the word we are interested in. */
+ if ( ulReadPtrBitOfst < 16 )
+ ReadParams.ulReadAddress += 2;
+
+ while( fStillPlaying == TRUE )
+ {
+ /* Read the read pointer until equals to the write pointer. */
+ mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Move data at correct position according to what was read. */
+ if ( ulReadPtrBitOfst < 16 )
+ ulTempData = usReadData;
+ else
+ ulTempData = usReadData << 16;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask );
+
+ /* Store the read pointer.*/
+ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst;
+
+ /* Playout has finished when the read pointer reaches the write pointer. */
+ if ( ulReadPtr == ulChipWritePtr )
+ break;
+
+ ulLoopCnt++;
+ if ( ulLoopCnt > cOCT6100_MAX_LOOP )
+ {
+ return cOCT6100_ERR_FATAL_E7;
+ }
+
+ aulWaitTime[ 0 ] = 100;
+ aulWaitTime[ 1 ] = 0;
+ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+
+ /* Clear hard-stop flag. */
+ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ /* No hard stop for now. */
+ pEchoChannel->fRinHardStop = FALSE;
+ }
+ else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */
+ {
+ /* No hard stop for now. */
+ pEchoChannel->fSoutHardStop = FALSE;
+ }
+
+ /* Now check again if the event can be added... */
+ if ( fOldBufferPlayoutVersion == FALSE )
+ {
+ if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL;
+ }
+ else /* if ( fOldBufferPlayoutVersion == TRUE ) */
+ {
+ /* Old 31 events image. */
+ if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL;
+ }
+
+ /* Good, at least another buffer can be added! Add the buffer to the list. */
+ }
+ else
+ {
+ /* Well the list is full! */
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL;
+ }
+ }
+ }
+
+ /*=======================================================================*/
+ /* Write the events. */
+
+ for ( ulEventIndex = 0; ulEventIndex < ulEventsToCreate; ulEventIndex ++ )
+ {
+ /* Set the playout event base address. */
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE )
+ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) )
+ {
+ /* 127 or 31 events image. */
+ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + (f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 )));
+ }
+ else
+ {
+ /* Old 31 events image. */
+ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + (f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & 0x1F));
+ }
+
+ /* EVENT BASE + 0 */
+ /* Make sure the xIS and xHS bits are cleared. */
+ ulTempData = 0;
+
+ /* Set the repeat count. */
+ if ( fRepeatCountSet == TRUE )
+ {
+ if ( ( ulRepeatCount != 0x0 ) && ( ulRepeatCount <= cOCT6100_REPEAT_MAX ) )
+ {
+ /* Use repeat count directly. */
+ ulTempData |= ulRepeatCount;
+
+ /* Will be used later when creating the duration modulo event. */
+ ulRepeatCount = 0;
+ }
+ else if ( ulRepeatCount != 0x0 )
+ {
+ /* Get ready for next event. */
+ ulRepeatCount -= cOCT6100_REPEAT_MAX;
+
+ /* Set maximum for this event. */
+ ulTempData |= cOCT6100_REPEAT_MAX;
+ }
+ else
+ {
+ /* Duration modulo case. Nothing to set here. */
+ }
+ }
+ else /* if ( fRepeatCountSet != TRUE ) */
+ {
+ /* Repeat only once. */
+ ulTempData |= 0x1;
+ }
+
+ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* EVENT BASE + 4 */
+ /* Set the buffer base address and playout configuration. */
+ ulAddress += 4;
+ ulTempData = pBufferEntry->ulBufferBase & 0x07FFFFFF;
+
+ /* Set play indefinitely or loop N times. */
+ if ( ( fRepeatCountSet == FALSE ) && ( f_pBufferPlayoutAdd->fRepeat == TRUE ) )
+ {
+ /* Repeat indefinitely. */
+ ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_REPEAT_OFFSET;
+
+ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ pEchoChannel->fRinBufPlayoutRepeatUsed = TRUE;
+ else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */
+ pEchoChannel->fSoutBufPlayoutRepeatUsed = TRUE;
+ }
+
+ /* Use loop N times feature. */
+ ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_LOOP_TIMES_OFFSET;
+
+ /* Set the law.*/
+ ulTempData |= ( pBufferEntry->byBufferPcmLaw << cOCT6100_PLAYOUT_EVENT_LAW_OFFSET );
+
+ /* Set the mixing configuration.*/
+ ulTempData |= f_pBufferPlayoutAdd->ulMixingMode << cOCT6100_PLAYOUT_EVENT_MIX_OFFSET;
+
+ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+
+ /* EVENT BASE + 8 */
+ /* Set the buffer size and playout gain. */
+ ulAddress += 4;
+
+ /* Check if we are setting the duration modulo. This would be the last event and this */
+ /* event is of a very specific size. */
+ if ( ( fRepeatCountSet == TRUE )
+ && ( ulEventIndex == ( ulEventsToCreate - 1 ) )
+ && ( ulDurationModulo != 0x0 ) )
+ {
+ /* The duration modulo variable contains all that is needed here. */
+ ulBufferLength = ulDurationModulo;
+ }
+ ulTempData = ulBufferLength;
+
+ /* Adjust playout gain. */
+ if ( f_pBufferPlayoutAdd->lGainDb != 0 )
+ {
+ /* Convert the dB value into OctFloat format. */
+ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pBufferPlayoutAdd->lGainDb );
+ ulTempData |= ( usTempData & 0xFF00 ) << 16;
+ }
+ else
+ {
+ ulTempData |= cOCT6100_PLAYOUT_GAIN;
+ }
+
+ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* EVENT BASE + 0xC */
+ ulAddress += 4;
+ ulTempData = ( ulBufferLength - 1 ) & 0xFFFFFFC0; /* Must be multiple of 64 bytes */
+
+ /* Adjust playout gain. */
+ if ( f_pBufferPlayoutAdd->lGainDb != 0 )
+ {
+ ulTempData |= ( usTempData & 0xFF ) << 24;
+ }
+
+ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Next event. */
+ ulWritePtr++;
+ }
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* Increment the write pointer to make it point to the next empty entry. */
+
+ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ pEchoChannel->ulRinBufWritePtr = ( pEchoChannel->ulRinBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 );
+ /* Remember that a buffer was added on the rin port. */
+ pEchoChannel->fRinBufAdded = TRUE;
+ }
+ else /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ pEchoChannel->ulSoutBufWritePtr = ( pEchoChannel->ulSoutBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 );
+ /* Remember that a buffer was added on the sout port. */
+ pEchoChannel->fSoutBufAdded = TRUE;
+ }
+
+ /*=======================================================================*/
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferPlayoutStartSer
+
+Description: Starts buffer playout on 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_pBufferPlayoutStart Pointer to buffer playout start structure.
+
+f_ulPlayoutStopEventType Playout stop event type to be generated if required.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutStartSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart,
+ IN UINT32 f_ulPlayoutStopEventType )
+{
+ UINT32 ulBufferIndex;
+ UINT32 ulChannelIndex;
+ BOOL fNotifyOnPlayoutStop;
+ UINT32 ulUserEventId;
+ BOOL fAddToCurrentlyPlayingList;
+ UINT32 ulResult;
+
+ /* Check the user's configuration of the buffer for errors. */
+ ulResult = Oct6100ApiCheckPlayoutStartParams( f_pApiInstance, f_pBufferPlayoutStart, &ulChannelIndex, &ulBufferIndex, &fNotifyOnPlayoutStop, &ulUserEventId, &fAddToCurrentlyPlayingList );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Write to all resources needed to activate buffer playout. */
+ ulResult = Oct6100ApiWriteChanPlayoutStructs( f_pApiInstance, f_pBufferPlayoutStart, ulChannelIndex, ulBufferIndex, fNotifyOnPlayoutStop, ulUserEventId, fAddToCurrentlyPlayingList, f_ulPlayoutStopEventType );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiCheckPlayoutStartParams
+
+Description: Check the validity of the channel and buffer requested.
+ Check the validity of the flags requested.
+
+-------------------------------------------------------------------------------
+| 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_pBufferPlayoutStart Pointer to buffer playout start structure.
+f_pulChannelIndex Pointer to the channel index of the selected channel.
+f_pulBufferIndex Pointer to the buffer index within the API's buffer list.
+f_pfNotifyOnPlayoutStop Pointer to the notify on playout stop flag.
+f_pulUserEventId Pointer to the user event id specified.
+f_pfAllowStartIfActive Pointer to the add to currently playing list flag.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiCheckPlayoutStartParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart,
+ OUT PUINT32 f_pulChannelIndex,
+ OUT PUINT32 f_pulBufferIndex,
+ OUT PBOOL f_pfNotifyOnPlayoutStop,
+ OUT PUINT32 f_pulUserEventId,
+ OUT PBOOL f_pfAllowStartIfActive )
+{
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ UINT32 ulEntryOpenCnt;
+
+ /* Check for errors. */
+ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED;
+
+ if ( f_pBufferPlayoutStart->ulChannelHndl == cOCT6100_INVALID_HANDLE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ if ( f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT &&
+ f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT;
+
+ if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop != FALSE
+ && f_pBufferPlayoutStart->fNotifyOnPlayoutStop != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOTIFY_ON_STOP;
+
+ if ( f_pBufferPlayoutStart->fAllowStartWhileActive != FALSE
+ && f_pBufferPlayoutStart->fAllowStartWhileActive != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ALLOW_ACTIVE;
+
+ /*=====================================================================*/
+ /* Check the channel handle. */
+
+ if ( (f_pBufferPlayoutStart->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ *f_pulChannelIndex = f_pBufferPlayoutStart->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK;
+ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex )
+
+ /* Extract the entry open count from the provided handle. */
+ ulEntryOpenCnt = (f_pBufferPlayoutStart->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
+
+ /* Check for errors. */
+ if ( pEchoChannel->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN;
+ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ /* The channel cannot be in POWER_DOWN or HT_FREEZE to start the playout. */
+ if ( ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN )
+ || ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ECHO_OP_MODE;
+
+ /* The channel's NLP must be enabled for playout to occur. */
+ if ( pEchoChannel->VqeConfig.fEnableNlp == FALSE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NLP_DISABLED;
+
+ /*=====================================================================*/
+
+ /*=====================================================================*/
+ /* Check if the user activated the buffer playout events. */
+
+ if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop == TRUE
+ && f_pApiInstance->pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize == 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_DISABLED;
+
+ /*=====================================================================*/
+
+ /*=====================================================================*/
+ /* Check if there is actually a buffer added in the list. */
+
+ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ if ( pEchoChannel->fRinBufAdded == FALSE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY;
+ }
+ else /* if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */
+ {
+ if ( pEchoChannel->fSoutBufAdded == FALSE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY;
+ }
+
+ /*=====================================================================*/
+
+ /* Return the requested information. */
+ *f_pfNotifyOnPlayoutStop = f_pBufferPlayoutStart->fNotifyOnPlayoutStop;
+ *f_pulUserEventId = f_pBufferPlayoutStart->ulUserEventId;
+ *f_pfAllowStartIfActive = f_pBufferPlayoutStart->fAllowStartWhileActive;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiWriteChanPlayoutStructs
+
+Description: Write the buffer playout event in the channel main 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_pBufferPlayoutStart Pointer to buffer playout start structure.
+f_ulChannelIndex Index of the channel within the API's channel list.
+f_ulBufferIndex Index of the buffer within the API's buffer list.
+f_fNotifyOnPlayoutStop Flag for the notify on playout stop.
+f_ulUserEventId User event id passed to the user when a playout event is generated.
+f_fAllowStartIfActive Add to currently playing list flag.
+f_ulPlayoutStopEventType Playout stop event type to be generated if required.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiWriteChanPlayoutStructs(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart,
+ IN UINT32 f_ulChannelIndex,
+ IN UINT32 f_ulBufferIndex,
+ IN BOOL f_fNotifyOnPlayoutStop,
+ IN UINT32 f_ulUserEventId,
+ IN BOOL f_fAllowStartIfActive,
+ IN UINT32 f_ulPlayoutStopEventType )
+{
+ tPOCT6100_API_BUFFER pBufferEntry;
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tOCT6100_READ_PARAMS ReadParams;
+
+ UINT32 ulResult;
+
+ UINT32 ulWritePtr;
+ UINT32 ulChipWritePtr;
+ PUINT32 pulSkipPtr;
+ UINT32 ulWritePtrBytesOfst;
+ UINT32 ulSkipPtrBytesOfst;
+ UINT32 ulWritePtrBitOfst;
+ UINT32 ulSkipPtrBitOfst;
+ UINT32 ulWritePtrFieldSize;
+ UINT32 ulSkipPtrFieldSize;
+
+ UINT32 ulIgnoreBytesOfst;
+ UINT32 ulIgnoreBitOfst;
+ UINT32 ulIgnoreFieldSize;
+
+ UINT32 ulHardSkipBytesOfst;
+ UINT32 ulHardSkipBitOfst;
+ UINT32 ulHardSkipFieldSize;
+
+ UINT32 ulReadPtrBytesOfst;
+ UINT32 ulReadPtrBitOfst;
+ UINT32 ulReadPtrFieldSize;
+
+ UINT32 ulPlayoutBaseAddress;
+ UINT32 ulAddress;
+ UINT32 ulTempData;
+ UINT32 ulMask;
+ UINT32 ulReadData;
+ UINT32 ulReadPtr;
+ UINT32 ulLoopCnt = 0;
+
+ UINT16 usReadData;
+
+ BOOL fBufferPlayoutStopDetected;
+ BOOL fWriteSkipPtr = FALSE;
+ BOOL fStillPlaying = TRUE;
+
+ UINT32 aulWaitTime[ 2 ];
+
+ /* Obtain local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex );
+ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex );
+
+ /* First off, check for buffer playout events, if requested for this channel/port. */
+ /* At the same time, if requested, check that the playout has stopped for this channel/port. */
+ if ( ( ( pEchoChannel->fRinBufPlaying == TRUE )
+ && ( ( pEchoChannel->fRinBufPlayoutNotifyOnStop == TRUE ) || ( f_fAllowStartIfActive == FALSE ) )
+ && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) )
+ || ( ( ( pEchoChannel->fSoutBufPlaying == TRUE ) || ( f_fAllowStartIfActive == FALSE ) )
+ && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == TRUE )
+ && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) )
+ {
+ /* Buffer playout might still be going on for this channel/port. */
+ ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance,
+ f_ulChannelIndex,
+ f_pBufferPlayoutStart->ulPlayoutPort,
+ pEchoChannel->fRinBufPlayoutNotifyOnStop,
+ &fBufferPlayoutStopDetected );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Check if the user requested to only start if playout is over. Return an error if */
+ /* buffer playout is still going on on this channel/port. */
+ if ( ( f_fAllowStartIfActive == FALSE ) && ( fBufferPlayoutStopDetected == FALSE ) )
+ {
+ /* No go! User should wait for the current list to stop, or call the */
+ /* Oct6100BufferPlayoutStop function. */
+ return cOCT6100_ERR_BUFFER_PLAYOUT_STILL_ACTIVE;
+ }
+ }
+
+ /* Select the buffer of interest. */
+ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ ulWritePtr = pEchoChannel->ulRinBufWritePtr;
+ pulSkipPtr = &pEchoChannel->ulRinBufSkipPtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4;
+ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4;
+ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4;
+ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4;
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4;
+
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset;
+ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset;
+ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset;
+ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset;
+
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize;
+ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize;
+ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize;
+ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize;
+ }
+ else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ ulWritePtr = pEchoChannel->ulSoutBufWritePtr;
+ pulSkipPtr = &pEchoChannel->ulSoutBufSkipPtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4;
+ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4;
+ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4;
+ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4;
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4;
+
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset;
+ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset;
+ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset;
+ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset;
+
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize;
+ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize;
+ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize;
+ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize;
+ }
+
+
+
+ /* Set the playout feature base address. */
+ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst;
+
+ /* Check if we must wait for stop to complete before starting a new list. */
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE )
+ {
+ if ( ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) )
+ || ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) )
+ {
+ /* Read the read pointer. */
+ ReadParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+ ReadParams.pusReadData = &usReadData;
+ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst;
+
+ /* Get the write pointer in the chip. */
+ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask );
+
+ /* Store the write pointer. */
+ ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst;
+
+ /* Optimize this access by only reading the word we are interested in. */
+ if ( ulReadPtrBitOfst < 16 )
+ ReadParams.ulReadAddress += 2;
+
+ while( fStillPlaying == TRUE )
+ {
+ /* Read the read pointer until equals to the write pointer. */
+ mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Move data at correct position according to what was read. */
+ if ( ulReadPtrBitOfst < 16 )
+ ulTempData = usReadData;
+ else
+ ulTempData = usReadData << 16;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask );
+
+ /* Store the read pointer. */
+ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst;
+
+ /* Playout has finished when the read pointer reaches the write pointer. */
+ if ( ulReadPtr == ulChipWritePtr )
+ break;
+
+ ulLoopCnt++;
+ if( ulLoopCnt > cOCT6100_MAX_LOOP )
+ {
+ return cOCT6100_ERR_FATAL_E6;
+ }
+
+ aulWaitTime[ 0 ] = 100;
+ aulWaitTime[ 1 ] = 0;
+ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+ }
+ }
+
+ /* Check if must clear the skip bit. */
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE )
+ {
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE )
+ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) )
+ {
+ /* Make sure the skip bit is cleared to start playout! */
+ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask );
+
+ /* Cleared! */
+ ulTempData &= ( ~ulMask );
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Make sure the hard skip bit is cleared to start playout! */
+ ulAddress = ulPlayoutBaseAddress + ulHardSkipBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulHardSkipBitOfst, &ulMask );
+
+ /* Cleared! */
+ ulTempData &= ( ~ulMask );
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+ }
+
+ /* Write the skip and write pointer to activate buffer playout. */
+
+ /* Update the skip pointer. */
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE )
+ || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) )
+ {
+ /* Old 31 events image. */
+ if ( ( ( ulWritePtr - *pulSkipPtr ) & 0x7F ) > 63 )
+ {
+ *pulSkipPtr = ( ulWritePtr - 63 ) & 0x7F;
+ fWriteSkipPtr = TRUE;
+ }
+ }
+ else
+ {
+ /* No need to update the skip pointer, a bit needs to be set when skipping. */
+ /* fWriteSkipPtr set to FALSE from variable declaration. */
+ }
+
+ if ( fWriteSkipPtr == TRUE )
+ {
+ /*=======================================================================*/
+ /* Fetch and modify the skip pointer. */
+
+ ulAddress = ulPlayoutBaseAddress + ulSkipPtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulSkipPtrFieldSize, ulSkipPtrBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+ ulTempData |= *pulSkipPtr << ulSkipPtrBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /*=======================================================================*/
+ }
+
+
+ /*=======================================================================*/
+ /* Fetch and modify the write pointer. */
+
+ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+ ulTempData |= ulWritePtr << ulWritePtrBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* Now update the state of the channel stating that the buffer playout is activated. */
+
+ /* Select the buffer of interest.*/
+ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ /* Check if the global ports active stat must be incremented. */
+ if ( pEchoChannel->fRinBufPlaying == FALSE )
+ {
+ /* Increment the number of active buffer playout ports. */
+ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++;
+ }
+
+ pEchoChannel->fRinBufPlaying = TRUE;
+ /* Keep the new notify on event flag. */
+ pEchoChannel->fRinBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF );
+ /* Keep the specified user event id. */
+ pEchoChannel->ulRinUserBufPlayoutEventId = f_ulUserEventId;
+ /* Keep type of event to be generated. */
+ pEchoChannel->byRinPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF );
+ /* No hard stop for now. */
+ pEchoChannel->fRinHardStop = FALSE;
+ /* No buffer added in the rin list for now. */
+ pEchoChannel->fRinBufAdded = FALSE;
+ /* Buffer playout is active on this channel. */
+ pEchoChannel->fBufPlayoutActive = TRUE;
+ }
+ else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ /* Check if the global ports active stat must be incremented. */
+ if ( pEchoChannel->fSoutBufPlaying == FALSE )
+ {
+ /* Increment the number of active buffer playout ports. */
+ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++;
+ }
+
+ pEchoChannel->fSoutBufPlaying = TRUE;
+ /* Keep the new notify on event flag. */
+ pEchoChannel->fSoutBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF );
+ /* Keep the specified user event id. */
+ pEchoChannel->ulSoutUserBufPlayoutEventId = f_ulUserEventId;
+ /* Keep type of event to be generated. */
+ pEchoChannel->bySoutPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF );
+ /* No hard stop for now. */
+ pEchoChannel->fSoutHardStop = FALSE;
+ /* No buffer added in the sout list for now. */
+ pEchoChannel->fSoutBufAdded = FALSE;
+ /* Buffer playout is active on this channel. */
+ pEchoChannel->fBufPlayoutActive = TRUE;
+ }
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100BufferPlayoutStopSer
+
+Description: Stops buffer playout on 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_pBufferPlayoutStop Pointer to buffer playout stop structure.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100BufferPlayoutStopSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop )
+{
+ UINT32 ulChannelIndex;
+ UINT16 usEchoMemIndex;
+ UINT32 ulResult;
+
+ /* Check the user's configuration of the buffer for errors. */
+ ulResult = Oct6100ApiAssertPlayoutStopParams(
+ f_pApiInstance,
+ f_pBufferPlayoutStop,
+ &ulChannelIndex,
+ &usEchoMemIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Write to all resources needed to deactivate buffer playout. */
+ ulResult = Oct6100ApiInvalidateChanPlayoutStructs(
+ f_pApiInstance,
+ f_pBufferPlayoutStop,
+ ulChannelIndex,
+ usEchoMemIndex
+
+ );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiAssertPlayoutStopParams
+
+Description: Check the validity of the channel and buffer requested.
+
+-------------------------------------------------------------------------------
+| 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_pBufferPlayoutStop Pointer to buffer playout stop structure.
+f_pulChannelIndex Pointer to the channel index on which playout is to be stopped.
+f_pusEchoMemIndex Pointer to the echo mem index on which playout is to be stopped.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiAssertPlayoutStopParams(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop,
+ OUT PUINT32 f_pulChannelIndex,
+ OUT PUINT16 f_pusEchoMemIndex )
+{
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ UINT32 ulEntryOpenCnt;
+
+ /* Check for errors. */
+ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED;
+
+ if ( f_pBufferPlayoutStop->ulChannelHndl == cOCT6100_INVALID_HANDLE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ if ( f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT &&
+ f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT;
+
+ if ( f_pBufferPlayoutStop->fStopCleanly != TRUE && f_pBufferPlayoutStop->fStopCleanly != FALSE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_STOP_CLEANLY;
+
+ /*=====================================================================*/
+ /* Check the channel handle. */
+
+ if ( (f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ *f_pulChannelIndex = f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK;
+ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex )
+
+ /* Extract the entry open count from the provided handle. */
+ ulEntryOpenCnt = (f_pBufferPlayoutStop->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
+
+ /* Check for errors. */
+ if ( pEchoChannel->fReserved != TRUE )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN;
+ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID;
+
+ /* Return echo memory index. */
+ *f_pusEchoMemIndex = pEchoChannel->usEchoMemIndex;
+
+ /* Check if buffer playout is active for the selected port. */
+ if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ && ( pEchoChannel->fRinBufPlaying == FALSE )
+ && ( pEchoChannel->fRinBufAdded == FALSE ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED;
+
+ if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT )
+ && ( pEchoChannel->fSoutBufPlaying == FALSE )
+ && ( pEchoChannel->fSoutBufAdded == FALSE ) )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED;
+
+ /*=====================================================================*/
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiInvalidateChanPlayoutStructs
+
+Description: Write the buffer playout event in the channel main 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_pBufferPlayoutStop Pointer to buffer playout stop structure.
+f_ulChannelIndex Index of the channel within the API's channel list.
+f_usEchoMemIndex Index of the echo channel in hardware memory.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiInvalidateChanPlayoutStructs(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop,
+ IN UINT32 f_ulChannelIndex,
+ IN UINT16 f_usEchoMemIndex
+
+ )
+{
+ tPOCT6100_API_CHANNEL pEchoChannel;
+ tPOCT6100_SHARED_INFO pSharedInfo;
+ tOCT6100_READ_PARAMS ReadParams;
+ tOCT6100_WRITE_PARAMS WriteParams;
+
+ UINT32 ulResult;
+
+ UINT32 ulWritePtrBytesOfst;
+ UINT32 ulWritePtrBitOfst;
+ UINT32 ulWritePtrFieldSize;
+ UINT32 ulSkipPtrBytesOfst;
+ UINT32 ulSkipPtrBitOfst;
+ UINT32 ulSkipPtrFieldSize;
+ UINT32 ulIgnoreBytesOfst;
+ UINT32 ulIgnoreBitOfst;
+ UINT32 ulIgnoreFieldSize;
+ UINT32 ulHardSkipBytesOfst;
+ UINT32 ulHardSkipBitOfst;
+ UINT32 ulHardSkipFieldSize;
+ UINT32 ulReadPtrBytesOfst;
+ UINT32 ulReadPtrBitOfst;
+ UINT32 ulReadPtrFieldSize;
+
+ UINT32 ulSkipPtr;
+ UINT32 ulWritePtr;
+ UINT32 ulReadPtr = 0;
+ UINT32 ulCurrentPtr;
+
+ UINT32 ulPlayoutBaseAddress;
+ UINT32 ulAddress;
+ UINT32 ulTempData;
+ UINT32 ulMask;
+ UINT32 ulReadData;
+
+ UINT16 usReadData;
+ BOOL fCheckStop = FALSE;
+
+ UINT32 ulEventBuffer;
+
+ /* Obtain local pointer to shared portion of instance. */
+ pSharedInfo = f_pApiInstance->pSharedInfo;
+
+ WriteParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
+
+ ReadParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+ ReadParams.pusReadData = &usReadData;
+
+ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex );
+
+ /* Select the port of interest. */
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ ulWritePtr = pEchoChannel->ulRinBufWritePtr;
+ ulSkipPtr = ulWritePtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4;
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset;
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize;
+
+ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4;
+ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset;
+ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize;
+
+ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4;
+ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset;
+ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize;
+
+ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4;
+ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset;
+ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize;
+
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize;
+ }
+ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ ulWritePtr = pEchoChannel->ulSoutBufWritePtr;
+ ulSkipPtr = ulWritePtr;
+
+ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4;
+ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset;
+ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize;
+
+ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4;
+ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset;
+ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize;
+
+ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4;
+ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset;
+ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize;
+
+ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4;
+ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset;
+ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize;
+
+ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4;
+ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset;
+ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize;
+ }
+
+ /* Set the playout feature base address. */
+ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst;
+
+ /* Check if something is currently playing. */
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ if ( pEchoChannel->fRinBufPlaying == TRUE )
+ {
+ /* Check if we are stopping it or if it stopped by itself. */
+ fCheckStop = TRUE;
+ }
+ else
+ {
+ /* Not playing! */
+ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL )
+ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE;
+ }
+ }
+ else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */
+ {
+ if ( pEchoChannel->fSoutBufPlaying == TRUE )
+ {
+ /* Check if we are stopping it or if it stopped by itself. */
+ fCheckStop = TRUE;
+ }
+ else
+ {
+ /* Not playing! */
+ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL )
+ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE;
+ }
+ }
+
+ if ( ( fCheckStop == TRUE ) || ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) )
+ {
+ /* Read the read pointer. */
+ ReadParams.pProcessContext = f_pApiInstance->pProcessContext;
+
+ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
+ ReadParams.pusReadData = &usReadData;
+ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst;
+
+ /* Optimize this access by only reading the word we are interested in. */
+ if ( ulReadPtrBitOfst < 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 ( ulReadPtrBitOfst < 16 )
+ ulTempData = usReadData;
+ else
+ ulTempData = usReadData << 16;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask );
+
+ /* Store the read pointer. */
+ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst;
+
+ /* Playout has finished when the read pointer reaches the write pointer. */
+ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL )
+ {
+ if ( ulReadPtr != ulWritePtr )
+ *f_pBufferPlayoutStop->pfAlreadyStopped = FALSE;
+ else /* if ( ulReadPtr == ulWritePtr ) */
+ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE;
+ }
+ }
+
+ /* If the skip bits are located in the event itself, the playout is stopped by setting the */
+ /* skip pointer to the hardware chip write pointer. Read it directly from the NLP configuration. */
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE )
+ {
+ if ( ulReadPtr != ulWritePtr )
+ {
+ /* Get the write pointer in the chip. */
+ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask );
+
+ /* Store the write pointer. */
+ ulWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst;
+ ulSkipPtr = ulWritePtr;
+ }
+ }
+
+ /* Check if must clear repeat bit. */
+ if ( ( ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) )
+ || ( ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) )
+ {
+ if ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE )
+ || ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE )
+ && ( ulWritePtr != ulReadPtr ) ) )
+ {
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst;
+ }
+ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst;
+ }
+
+ /* Set the playout event base address. */
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE )
+ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) )
+ {
+ /* 127 or 31 events image. */
+ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 )));
+ }
+ else
+ {
+ /* Old 31 events image. */
+ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & 0x1F));
+ }
+
+ /* EVENT BASE + 4 */
+ /* Playout configuration. */
+ ulAddress += 4;
+
+ ReadParams.ulReadAddress = ulAddress;
+ mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Read-clear-write the new repeat bit. */
+ usReadData &= 0x7FFF;
+
+ WriteParams.ulWriteAddress = ulAddress;
+ WriteParams.usWriteData = usReadData;
+ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+ }
+
+ /* Write the skip to the value of the write pointer to stop buffer playout. */
+
+ /*=======================================================================*/
+ /* First set the ignore skip clean bit if required. */
+
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE )
+ || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) )
+ {
+ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+
+ /* Check if the skip need to be clean or not. */
+ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE )
+ ulTempData |= 0x1 << ulIgnoreBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* Fetch and modify the write pointer. */
+
+ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+ ulTempData |= ulWritePtr << ulWritePtrBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* Fetch and modify the skip pointer. */
+
+ ulAddress = ulPlayoutBaseAddress + ulSkipPtrBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulSkipPtrFieldSize, ulSkipPtrBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+ ulTempData |= ulSkipPtr << ulSkipPtrBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* If in the new buffer playout case, things are in a different order. */
+
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE )
+ {
+ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE )
+ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) )
+ {
+ ulAddress = ulPlayoutBaseAddress + ulHardSkipBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulHardSkipFieldSize, ulHardSkipBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+
+ /* Check if the skip need to be clean or not. */
+ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE )
+ ulTempData |= 0x1 << ulHardSkipBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ /* Now is the appropriate time to skip! */
+ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst;
+
+ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ &ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+
+ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask );
+
+ ulTempData &= ( ~ulMask );
+
+ /* Set the skip bit. */
+ ulTempData |= 0x1 << ulIgnoreBitOfst;
+
+ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
+ pEchoChannel,
+ ulAddress,
+ ulTempData,
+ ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+ }
+
+ /*=======================================================================*/
+
+
+ /*=======================================================================*/
+ /* The API must set the skip bit in all the events that are queued. */
+
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE )
+ {
+ if ( fCheckStop == TRUE )
+ {
+ if ( ulReadPtr != ulWritePtr )
+ {
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst;
+ }
+ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst;
+ }
+
+ for ( ulCurrentPtr = ulReadPtr; ulCurrentPtr != ulWritePtr; )
+ {
+ /* Set the playout event base address. */
+
+ /* 127 or 31 events image. */
+ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + ( cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ulCurrentPtr );
+ ulCurrentPtr++;
+ ulCurrentPtr &= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 );
+
+ /* EVENT BASE + 0 playout configuration. */
+ WriteParams.ulWriteAddress = ulAddress;
+
+ /* Set skip bit + hard-skip bit. */
+ WriteParams.usWriteData = 0x8000;
+ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE )
+ WriteParams.usWriteData |= 0x4000;
+ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return ulResult;
+ }
+ }
+ }
+ }
+
+ /*=======================================================================*/
+ /* If stop immediatly, wait the stop before leaving the function. */
+
+ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE )
+ {
+ /* Remember that an "hard stop" was used for the next start. */
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ pEchoChannel->fRinHardStop = TRUE;
+ else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */
+ pEchoChannel->fSoutHardStop = TRUE;
+ }
+
+ /*=======================================================================*/
+ /* Update the channel entry to set the playing flag to FALSE. */
+
+ /* Select the port of interest. */
+ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT )
+ {
+ /* Check if the global ports active stat must be decremented. */
+ if ( pEchoChannel->fRinBufPlaying == TRUE )
+ {
+ /* Decrement the number of active buffer playout ports. */
+ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--;
+ }
+
+ pEchoChannel->fRinBufPlaying = FALSE;
+
+ /* Return user information. */
+ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL )
+ *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fRinBufPlayoutNotifyOnStop;
+
+ /* Make sure no new event is recorded for this channel/port. */
+ pEchoChannel->fRinBufPlayoutNotifyOnStop = FALSE;
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE )
+ {
+ pEchoChannel->ulRinBufSkipPtr = ulSkipPtr;
+ pEchoChannel->ulRinBufWritePtr = ulWritePtr;
+ }
+ else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */
+ pEchoChannel->ulRinBufSkipPtr = pEchoChannel->ulRinBufWritePtr;
+
+ /* The repeat flag can now be used. */
+ pEchoChannel->fRinBufPlayoutRepeatUsed = FALSE;
+
+ /* For sure, all buffers have now been cleared on the Rin port. */
+ pEchoChannel->fRinBufAdded = FALSE;
+
+ /* Clear optimization flag if possible. */
+ if ( ( pEchoChannel->fSoutBufPlaying == FALSE )
+ && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == FALSE ) )
+ {
+ /* Buffer playout is no more active on this channel. */
+ pEchoChannel->fBufPlayoutActive = FALSE;
+ }
+ }
+ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */
+ {
+ /* Check if the global ports active stat must be decremented. */
+ if ( pEchoChannel->fSoutBufPlaying == TRUE )
+ {
+ /* Decrement the number of active buffer playout ports. */
+ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--;
+ }
+
+ pEchoChannel->fSoutBufPlaying = FALSE;
+
+ /* Return user information. */
+ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL )
+ *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fSoutBufPlayoutNotifyOnStop;
+
+ /* Make sure no new event is recorded for this channel/port. */
+ pEchoChannel->fSoutBufPlayoutNotifyOnStop = FALSE;
+ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE )
+ {
+ pEchoChannel->ulSoutBufSkipPtr = ulSkipPtr;
+ pEchoChannel->ulSoutBufWritePtr = ulWritePtr;
+ }
+ else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */
+ pEchoChannel->ulSoutBufSkipPtr = pEchoChannel->ulSoutBufWritePtr;
+
+ /* The repeat flag can now be used. */
+ pEchoChannel->fSoutBufPlayoutRepeatUsed = FALSE;
+
+ /* For sure, all buffers have now been cleared on the Sout port. */
+ pEchoChannel->fSoutBufAdded = FALSE;
+
+ /* Clear optimization flag if possible. */
+ if ( ( pEchoChannel->fRinBufPlaying == FALSE )
+ && ( pEchoChannel->fRinBufPlayoutNotifyOnStop == FALSE ) )
+ {
+ /* Buffer playout is no more active on this channel. */
+ pEchoChannel->fBufPlayoutActive = FALSE;
+ }
+ }
+
+ /*=======================================================================*/
+
+
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiReserveBufPlayoutListEntry
+
+Description: Reserves a free entry in the Buffer playout 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_pulBufferIndex List entry reserved.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiReserveBufPlayoutListEntry(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ OUT PUINT32 f_pulBufferIndex )
+{
+ PVOID pBufPlayoutAlloc;
+ UINT32 ulResult;
+
+ mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc )
+
+ ulResult = OctapiLlmAllocAlloc( pBufPlayoutAlloc, f_pulBufferIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ {
+ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT )
+ return cOCT6100_ERR_BUFFER_PLAYOUT_ALL_BUFFERS_OPEN;
+ else
+ return cOCT6100_ERR_FATAL_40;
+ }
+
+ return cOCT6100_ERR_OK;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+Function: Oct6100ApiReleaseBufPlayoutListEntry
+
+Description: Release an entry from the Buffer playout 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_ulBufferIndex List entry to be freed.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ApiReleaseBufPlayoutListEntry(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN UINT32 f_ulBufferIndex )
+{
+ PVOID pBufPlayoutAlloc;
+ UINT32 ulResult;
+
+ mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc )
+
+ ulResult = OctapiLlmAllocDealloc( pBufPlayoutAlloc, f_ulBufferIndex );
+ if ( ulResult != cOCT6100_ERR_OK )
+ return cOCT6100_ERR_FATAL_41;
+
+ return cOCT6100_ERR_OK;
+}
+