a8fa7ad9b118dbefe8630abd58d463ab66906110
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / aspDecOpCircBuf_master.c
2 /*
3 Copyright (c) 2017, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without 
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 #include <string.h> // for memset()
37 #include <xdc/std.h>
38 #include <xdc/runtime/Log.h>
39 #include <ti/sysbios/hal/Cache.h>
40 #include <ti/uia/events/UIAEvt.h>
41 #include <ti/ipc/GateMP.h>
43 #include "common.h"
44 #include "paftyp.h"
45 #include "pafdec.h"
46 #include "aspDecOpCircBuf_master.h"
48 #include "evmc66x_gpio_dbg.h" // Debug
50 #ifdef CB_RW_OP_CAP_PP // debug
51 // Global variables
52 Uint32 *gCB_samples_op = NULL;
53 Uint8 *gCB_op_owner = NULL;
54 Uint32 *gCB_opCnt = 0;
55 Uint8 *gCB_afRdIdx = NULL;
56 Uint8 *gCB_afWrtIdx = NULL;
57 Uint8 *gCB_numAfCb = NULL;
58 #endif
60 #if 0
61 // Generate mute AF on circular buffer read
62 static Void cbReadAfMute(
63     PAF_AudioFrame *pAfRd,      // audio frame into which to read
64     Int16 strFrameLen           // stream frame length (output transaction size)
65 );
66 #endif
68 // Init last audio frame configuration info 
69 static Void cbInitLastAfInfo(
70     PAF_AudioFrame *pAfRd      // last audio frame stored in CB instance
71 );
73 // Update last audio frame configuration info 
74 static Void cbUpdateLastAfInfo(
75     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
76     PAF_AudioFrame *pAfUpd      // audio frame used for update
77 );
79 // Generate mute AF on circular buffer read using the last AF configuration info 
80 static Void cbReadMuteWithLastAfInfo (
81     PAF_AST_DecOpCircBuf *pCb,    // decoder output circular buffer control
82     PAF_AudioFrame *pAfRd         // audio frame into which to read
83 );
85 #if 0 // FL: moved to common
86 // Initialize circular buffer control
87 Int cbCtlInit(
88     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
89     Int8 numCb,                         // number of circular buffers
90     PAF_AST_DecOpCircBuf **pXDecOpCb    // address of decoder output circular buffer base pointer
91 )
92 {
93     GateMP_Params gateParams;
94     GateMP_Handle gateHandle;
95     
96     GateMP_Params_init(&gateParams);
97     gateParams.localProtect = GateMP_LocalProtect_THREAD;
98     gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM;
99     gateParams.name = ASP_DECODE_CB_GATE_NAME;
100     gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID;
101     gateHandle = GateMP_create(&gateParams);
102     if (gateHandle != NULL)
103     {
104         pCbCtl->gateHandle = gateHandle;
105     }
106     else
107     {
108         pCbCtl->gateHandle = NULL;
109         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
110     }
111     
112     pCbCtl->numCb = numCb;          // init number of circular buffers
113     pCbCtl->pXDecOpCb = pXDecOpCb;  // init base address of circular buffers
114     
115     return ASP_DECOP_CB_SOK;    
117 #endif
119 // Initialize circular buffer
120 Int cbInit(
121     PAF_AST_DecOpCircBuf *pCb
124     PAF_AudioFrame *pAfCb;
125     PAF_AudioData *pPcmBuf;
126     UInt8 *pMetaBuf;
127     Int8 n;
128     Int8 i;
130     // set source select
131     pCb->sourceSel = DEF_SOURCE_SEL;
133     // set input frame length
134     pCb->decOpFrameLen = DEF_DEC_OP_FRAME_LEN;
135     
136     // set output frame length
137     pCb->strFrameLen = DEF_STR_FRAME_LEN;
138     
139     // initialize circular buffer maximum number of audio frames
140     pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;//ASP_DECOP_CB_MAX_NUM_AF_PCM;
141     pCb->afWrtIdx = ASP_DECOP_CB_INIT_LAG_PCM;
142     pCb->afRdIdx = 0;
143     pCb->pcmRdIdx = 0;
145     // Initialize CB primed flag
146     pCb->primedFlag = 0;
147     // Initialize delta samples
148     pCb->deltaSamps = 0;
149     
150     // set default value to PCM configuration
151     pCb->maxAFChanNum   = ASP_DECOP_CB_MAX_NUM_PCM_CH;
152     pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;
153     // initialize audio frames
154     for (n=0; n<pCb->maxNumAfCb; n++)
155     {
156         pAfCb = &pCb->afCb[n];
157         pAfCb->sampleDecode = PAF_SOURCE_PCM;
158         PAF_PROCESS_ZERO(pAfCb->sampleProcess);
159         pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
160         pAfCb->sampleCount = DEF_DEC_OP_FRAME_LEN;
161         pAfCb->channelConfigurationRequest.full = 0;
162         pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
163         pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
164         pAfCb->channelConfigurationStream.full = 0;
165         pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
166         pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
167     }
169     // initialize circular buffer current number of frames
170     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
171     
172     // initialize audio frame PCM buffers
173     pPcmBuf = pCb->pcmBuf;
174     pMetaBuf = pCb->metaBuf;
175     for (n=0; n<pCb->maxNumAfCb; n++)
176     {
177         pAfCb = &pCb->afCb[n];
178         pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH;
179         pAfCb->data.nSamples = DEF_DEC_OP_FRAME_LEN;
180         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
181         {
182             pAfCb->data.sample[i] = pPcmBuf;
183             memset(pAfCb->data.sample[i], 0, DEF_DEC_OP_FRAME_LEN);
184             pPcmBuf += DEF_DEC_OP_FRAME_LEN;
185             
186             pAfCb->data.samsiz[i] = 0;
187         }
188         
189         // write metadata information updated by decoder
190         pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
191         pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
192         pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
193         pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
194         
195         // Initialize metadata buffers
196         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
197         {
198             pAfCb->pafPrivateMetadata[i].offset = 0; 
199             pAfCb->pafPrivateMetadata[i].size   = 0; 
200             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
201             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
202         }
203     }
204     
205     // reset read/write flags
206     pCb->writerActiveFlag = 0;
207     pCb->readerActiveFlag = 0;
208     pCb->drainFlag = 0;
209     
210     // reset stats
211     pCb->readAfWriterInactiveCnt = 0;
212     pCb->readAfNdCnt = 0;
213     pCb->wrtAfReaderInactiveCnt = 0;
214     pCb->wrtAfZeroSampsCnt = 0;
215     pCb->errUndCnt = 0;
216     pCb->errOvrCnt = 0;
217     
218     #ifdef CB_RW_OP_CAP_PP // debug
219     // Get address in global variables
220     gCB_samples_op = pCb->cb_samples_op;
221     gCB_op_owner = pCb->cb_op_owner;
222     gCB_opCnt = &pCb->cb_opCnt;
223     gCB_afRdIdx = pCb->cb_afRdIdx;
224     gCB_afWrtIdx = pCb->cb_afWrtIdx;
225     gCB_numAfCb = pCb->cb_numAfCb;
226     #endif
228     cbInitLastAfInfo(&pCb->lastAf);
230     // Write back circular buffer configuration
231     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
232     // Write back AF circular buffer
233     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
234     // Write back PCM data
235     for (n=0; n<pCb->maxNumAfCb; n++)
236     {
237         pAfCb = &pCb->afCb[n];
238         Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
239         Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
240         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
241         {
242             Cache_wb(pAfCb->data.sample[i], DEF_DEC_OP_FRAME_LEN*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
243         }
244     }
245     Cache_wait();
247     return ASP_DECOP_CB_SOK;
251 #if 0 // FL: moved to ARM
252 // debug
253 //Int8 gCbInitSourceSelCnt=0;
254 //Int8 gCbInitSourceSelThdCnt=0;
256 // Initialize circular buffer based on selected source
257 Int cbInitSourceSel(
258     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
259     Int8 cbIdx,                         // decoder output circular buffer index
260     Int8 sourceSelect,                  // source select (PCM, DDP, etc.)
261     Int16 decOpFrameLen,                // decoder output frame length (PCM samples)
262     Int16 strFrameLen,                  // stream frame length (PCM samples)
263     Int8 resetRwFlags                   // whether to reset reader, writer, and drain flags
266     IArg key;
267     GateMP_Handle gateHandle;
268     PAF_AST_DecOpCircBuf *pCb;
269     PAF_AudioFrame *pAfCb;
270     PAF_AudioData *pPcmBuf;
271     UInt8 *pMetaBuf;
272     Int8 n;
273     Int8 i;
275     //gCbInitSourceSelCnt++; // debug
276     
277     // Get gate handle
278     gateHandle = pCbCtl->gateHandle;
279     // Enter gate
280     key = GateMP_enter(gateHandle);
282     // Get circular buffer base pointer
283     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
284     
285     // Invalidate circular buffer configuration
286     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
287     Cache_wait();
289     //Log_info1("cbInitSourceSel:afCb=0x%04x", (IArg)pCb->afCb); // debug
291     // set source select
292     pCb->sourceSel = sourceSelect;
294     // set input frame length
295     pCb->decOpFrameLen = decOpFrameLen;
296     
297     // set output frame length
298     pCb->strFrameLen = strFrameLen;
300     //pCb->afInitialLag = 0;  // default No lag
301     //pCb->afLagIdx = 0;
302     // Initialize CB primed flag
303     pCb->primedFlag = 0;
304     // Initialize delta samples
305     pCb->deltaSamps = 0;
306     
307     // initialize circular buffer maximum number of audio frames
308     if (sourceSelect == PAF_SOURCE_PCM)
309     {
310         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM;
311         
312         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
313         // Initialize target nominal delay
314         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM;
315         
316         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM;
317         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM;
318         pCb->pcmRdIdx = 0;
319         
320         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH;
321         pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;
322         
323         // initialize audio frames
324         for (n=0; n<pCb->maxNumAfCb; n++)
325         {
326             pAfCb = &pCb->afCb[n];
327             pAfCb->sampleDecode = sourceSelect;
328             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
329             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
330             pAfCb->sampleCount = decOpFrameLen;
331             pAfCb->channelConfigurationRequest.full = 0;
332             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
333             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
334             pAfCb->channelConfigurationStream.full = 0;
335             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
336             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
337             
338             // write metadata information updated by decoder
339             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
340             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
341             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
342             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
343         }
344     }
345     else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3))
346     {
347         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP;
348         
349         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP;
350         // Initialize target nominal delay
351         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kDDP;
352         
353         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP;
354         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP;
355         pCb->pcmRdIdx = 0;
356         
357         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP;
358         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP;
359         
360         // initialize audio frames
361         for (n=0; n<pCb->maxNumAfCb; n++)
362         {
363             pAfCb = &pCb->afCb[n];
364             pAfCb->sampleDecode = sourceSelect;
365             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
366             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
367             pAfCb->sampleCount = decOpFrameLen;
368             pAfCb->channelConfigurationRequest.full = 0;
369             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
370             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
371             pAfCb->channelConfigurationStream.full = 0;
372             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
373             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
374             
375             // write metadata information updated by decoder
376             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
377             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
378             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
379             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
380         }
381     }
382     else if (sourceSelect == PAF_SOURCE_THD)
383     {
384         //gCbInitSourceSelThdCnt++; //debug
385         
386         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;
387         
388         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD;
389         // Initialize target nominal delay
390         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
391         
392         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD;
393         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD;
394         pCb->pcmRdIdx = 0;
395         
396         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT;
397         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT;
398         
399         // initialize audio frames
400         for (n=0; n<pCb->maxNumAfCb; n++)
401         {
402             pAfCb = &pCb->afCb[n];
403             pAfCb->sampleDecode = sourceSelect;
404             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
405             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
406             pAfCb->sampleCount = decOpFrameLen;
407             pAfCb->channelConfigurationRequest.full = 0;
408             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
409             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
410             pAfCb->channelConfigurationStream.full = 0;
411             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
412             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
413             
414             // write metadata information updated by decoder
415             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
416             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
417             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
418             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
419         }
420     }
421     else
422     {
423         SW_BREAKPOINT;
424         
425         // Leave the gate
426         GateMP_leave(gateHandle, key);
428         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
429     }
431     // initialize circular buffer current number of frames
432     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
433     
434     // initialize audio frame PCM buffers
435     pPcmBuf = pCb->pcmBuf;
436     pMetaBuf = pCb->metaBuf;
437     for (n=0; n<pCb->maxNumAfCb; n++)
438     {
439         pAfCb = &pCb->afCb[n];
440         pAfCb->data.nChannels = pCb->maxAFChanNum;
441         pAfCb->data.nSamples = decOpFrameLen;
442         for (i=0; i<pCb->maxAFChanNum; i++)
443         {
444             pAfCb->data.sample[i] = pPcmBuf;
445             memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount);
446             pPcmBuf += pCb->maxAFSampCount;
447             
448             pAfCb->data.samsiz[i] = 0;
449         }
450         
451         // Initialize metadata buffers
452         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
453         {
454             pAfCb->pafPrivateMetadata[i].offset = 0; 
455             pAfCb->pafPrivateMetadata[i].size   = 0; 
456             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
457             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
458         }
459     }
460     
461     // reset read/write flags
462     if (resetRwFlags)
463     {
464         pCb->writerActiveFlag = 0;
465         pCb->readerActiveFlag = 0;
466         pCb->drainFlag = 0;
467     }
468     
469     // reset stats
470     pCb->readAfWriterInactiveCnt = 0;
471     pCb->readAfNdCnt = 0;
472     pCb->wrtAfReaderInactiveCnt = 0;
473     pCb->wrtAfZeroSampsCnt = 0;
474     pCb->errUndCnt = 0;
475     pCb->errOvrCnt = 0;
476     
477     // Write back circular buffer configuration
478     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
479     // Write back AF circular buffer
480     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
481     // Write back PCM data
482     for (n=0; n<pCb->maxNumAfCb; n++)
483     {
484         pAfCb = &pCb->afCb[n];
485         Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
486         Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
487         for (i=0; i<pCb->maxAFChanNum; i++)
488         {
489             Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
490         }
491     }
492     Cache_wait();
494     // Leave the gate
495     GateMP_leave(gateHandle, key);
496     
497     return ASP_DECOP_CB_SOK;
499 #endif
501 // Start reads from circular buffer
502 Int cbReadStart(
503     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
504     Int8 cbIdx                          // decoder output circular buffer index
507     IArg key;
508     GateMP_Handle gateHandle;
509     PAF_AST_DecOpCircBuf *pCb;
511     // Get gate handle
512     gateHandle = pCbCtl->gateHandle;
513     // Enter gate
514     key = GateMP_enter(gateHandle);
516     // Get circular buffer base pointer
517     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
518     
519     // Invalidate circular buffer configuration
520     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
521     Cache_wait();
522     
523     //Log_info1("cbReadStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
525     // update flags
526     pCb->readerActiveFlag = 1;
527     
528     // Write back circular buffer configuration
529     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
530     Cache_wait();
532     // Leave the gate
533     GateMP_leave(gateHandle, key);
535     return ASP_DECOP_CB_SOK;
538 // Stop reads from circular buffer
539 Int cbReadStop(
540     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
541     Int8 cbIdx                          // decoder output circular buffer index
544     IArg key;
545     GateMP_Handle gateHandle;
546     PAF_AST_DecOpCircBuf *pCb;
548     // Get gate handle
549     gateHandle = pCbCtl->gateHandle;
550     // Enter gate
551     key = GateMP_enter(gateHandle);
553     // Get circular buffer base pointer
554     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
556     // Invalidate circular buffer configuration
557     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
558     Cache_wait();
559     
560     //Log_info1("cbReadStop:afCb=0x%04x", (IArg)pCb->afCb); // debug
562     // update flags
563     pCb->readerActiveFlag = 0;
564     
565     // Write back circular buffer configuration
566     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
567     Cache_wait();
569     // Leave the gate
570     GateMP_leave(gateHandle, key);
572     return ASP_DECOP_CB_SOK;
575 // debug
576 //Int16 gDeltaSampsBuf[20];
577 //Int8 gDeltaSampsBufIdx=0;
579 // Read audio frame from circular buffer
580 Int cbReadAf(
581     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
582     Int8 cbIdx,                         // decoder output circular buffer index
583     PAF_AudioFrame *pAfRd               // audio frame into which to read
586     IArg key;
587     GateMP_Handle gateHandle;
588     PAF_AST_DecOpCircBuf *pCb;
589     PAF_AudioFrame *pAfCb;
590     PAF_ChannelMask_HD streamMask;
591     Int8 i;
592     Int16 j;
593     Int8 numMetadata = 0;
594     
595     // Get gate handle
596     gateHandle = pCbCtl->gateHandle;
597     // Enter gate
598     key = GateMP_enter(gateHandle);
600     // Get circular buffer base pointer
601     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
603     // Invalidate circular buffer configuration.
604     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
605     Cache_wait();
607     //Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
609     // Check (writerActiveFlag,drainFlag)=(1,1)
610     if ((pCb->writerActiveFlag == 1) && (pCb->drainFlag == 1))
611     {
612         //
613         // This shouldn't occur:
614         // writer is active AND draining circular buffer
615         //
616         
617         //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // FL: debug
618         SW_BREAKPOINT; // FL: debug
619         
620         // Leave the gate
621         GateMP_leave(gateHandle, key);
622         
623         return ASP_DECOP_CB_READ_INVSTATE;
624     }
626     // Check (writerActiveFlag,drainFlag)=(0,0)
627     //if (((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) || (pCb->afLagIdx < pCb->afInitialLag))
628     if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0))
629     {
630         //
631         // Writer inactive, not draining circular buffer.
632         // Skip UNDerflow check, mute output.
633         //
634         
635         pCb->readAfWriterInactiveCnt++;
636         
637         //cbReadAfMute(pAfRd, pCb->strFrameLen);
638         cbReadMuteWithLastAfInfo(pCb, pAfRd);
639         
640         // Write back circular buffer configuration.
641         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
642         Cache_wait();    
644         // Leave the gate
645         GateMP_leave(gateHandle, key);
647         return ASP_DECOP_CB_SOK;
648     }
649     
650     //if ((pCb->primedFlag == 0) || ((pCb->primedFlag==1) && (pCb->deltaSamps > 0))
651     if ((pCb->primedFlag == 0) || (pCb->deltaSamps > 0))
652     {
653         pCb->readAfNdCnt++;
654         
655         if (pCb->primedFlag == 1)
656         {
657             pCb->deltaSamps = pCb->deltaSamps - pCb->strFrameLen;
658             
659             // debug
660             //gDeltaSampsBuf[gDeltaSampsBufIdx] = pCb->deltaSamps;
661             //if (gDeltaSampsBufIdx < 20)
662             //    gDeltaSampsBufIdx++;
663         }
664         
665         cbReadMuteWithLastAfInfo(pCb, pAfRd);
666         
667         // Write back circular buffer configuration.
668         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
669         Cache_wait();    
670         
671         // Leave the gate
672         GateMP_leave(gateHandle, key);
674         return ASP_DECOP_CB_SOK;
675     }
676     
677     // (writerActiveFlag,drainFlag)= (0,0) and (1,1) checked above
678     // (writerActiveFlag,drainFlag)=(1,0) and (0,1) are left
679     // Checking (writerActiveFlag,drainFlag)=(1,0) state here
680     if (pCb->writerActiveFlag == 1)
681     {
682         // check underflow
683         if (pCb->numAfCb <= 0)
684         {
685             // 
686             // Increment underflow count.
687             // Mute output on underflow.
688             //
689             pCb->errUndCnt++;
690             //cbReadAfMute(pAfRd, pCb->strFrameLen);
691             cbReadMuteWithLastAfInfo(pCb, pAfRd);
692             //SW_BREAKPOINT; // FL: debug
693             
694             // debug
695             {
696                 static Uint8 toggleState = 0;
697                 if (toggleState == 0)
698                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
699                 else
700                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
701                 toggleState = ~(toggleState);
702             }
704             #ifdef CB_RW_OP_CAP_PP // debug
705             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
706             {
707                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
708                 {
709                     // log sample count
710                     pCb->cb_samples_op[pCb->cb_opCnt] = 0;  // due to underflow
711                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
712                     // log idxs
713                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
714                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
715                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
716                     pCb->cb_opCnt++;
717                 }
718             }
719             #endif
721             // Write back circular buffer configuration.
722             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
723             Cache_wait();    
724             
725             // Leave the gate
726             GateMP_leave(gateHandle, key);
727             
728             return ASP_DECOP_CB_READ_UNDERFLOW;
729         }
730     }
731     
732     // Checking (writerActiveFlag,drainFlag)=(1,0) state above and here
733     // Checking (writerActiveFlag,drainFlag)=(0,1) state here
734     if ((pCb->writerActiveFlag == 1) || (pCb->drainFlag == 1))
735     {
736         //
737         // Writer active or draining remaining frames in circular buffer.
738         // Get next output audio frame.
739         //
740         
741         // get pointer to current audio frame in circular buffer
742         pAfCb = &pCb->afCb[pCb->afRdIdx];
744         // Invalidate audio frame
745         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
746         Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
747         for (i=0; i<pAfCb->numPrivateMetadata; i++) // only invalidate numPrivateMetadata
748         {
749             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size
750         }
751         Cache_wait();
753         // compute stream mask
754         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
756         // Invalidate channel pointers
757         Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
758         Cache_wait();
760         // Invalidate PCM data
761         for (i = 0; i < pCb->maxAFChanNum; i++)
762         {
763             if ((streamMask >> i) & 0x1)
764             {
765                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
766             }
767         }
768         Cache_wait();        
769         
770         // read audio frame information updated by decoder
771         pAfRd->sampleDecode = pAfCb->sampleDecode;
772         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
773         pAfRd->sampleRate = pAfCb->sampleRate;
774         pAfRd->sampleCount = pCb->strFrameLen;
775         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
776         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
777         
778         // read metadata information updated by decoder
779         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
780         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
781         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
782         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
783         
784         #ifdef CB_RW_OP_CAP_PP // debug
785         if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
786         {
787             if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
788             {
789                 // log sample count
790                 pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount;
791                 pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
792                 // log idxs
793                 pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
794                 pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
795                 pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
796                 pCb->cb_opCnt++;
797             }
798         }
799         #endif
801         //// update Last Cb info as per actual stream
802         //pCb->lastAf.sampleCount = pCb->strFrameLen; // FL: last AF sample count isn't used (see cbReadMuteWithLastAfInfo())
803         //pCb->lastAf.sampleRate = pAfCb->sampleRate; // FL: moved inside cbUpdateLastAfInfo() along with other params from memcpy below
804         // Update last audio frame configuration info
805         cbUpdateLastAfInfo(pCb, pAfRd);
807         // read PCM samples
808         for (i = 0; i < pCb->maxAFChanNum; i++)
809         {
810             if ((streamMask >> i) & 0x1)
811             {
812                 for (j = 0; j < pCb->strFrameLen; j++)
813                 {
814                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
815                 }
817                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
818             }
819         }
820         
821         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
822         {
823             pAfRd->pafPrivateMetadata[i].offset = 0;
824             pAfRd->pafPrivateMetadata[i].size   = 0;
825         }
826         
827         // read metadata
828         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // only read numPrivateMetadata
829         {
830             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
831                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
832                  &&(pAfCb->pafPrivateMetadata[i].size))
833             {
834                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
835                 pAfRd->pafPrivateMetadata[numMetadata].offset = pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
836                 pAfRd->pafPrivateMetadata[numMetadata].size   = pAfCb->pafPrivateMetadata[i].size;
837                 memcpy(pAfRd->pafPrivateMetadata[numMetadata].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
838                 numMetadata++; //number of metadata associated with current 256 segment of audio samples
839             }
840             else //reset un-used buf
841             {
842                 pAfRd->pafPrivateMetadata[i].offset = 0;
843                 pAfRd->pafPrivateMetadata[i].size   = 0;
844             }
846         }
847         pAfRd->numPrivateMetadata = numMetadata; //number of metadata associated with current 256 segment of audio samples
848         
849         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
850         if (pCb->pcmRdIdx >= pAfCb->sampleCount) 
851         {
852             // update audio frame read index
853             pCb->afRdIdx++;
854             if (pCb->afRdIdx >= pCb->maxNumAfCb)
855             {
856                 pCb->afRdIdx = 0;
857             }
858             
859             // update PCM read index
860             pCb->pcmRdIdx = 0;
861             
862             // update number of audio frames in circular buffer
863             pCb->numAfCb--;
864         }
865         
866         // FL: this update of Last AF is handled above
867         //memcpy (&pCb->lastAf, pAfRd, sizeof(PAF_AudioFrame));
869         {
870             static Uint8 toggleState = 0;
871             if (toggleState == 0)
872                 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
873             else
874                 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
875             toggleState = ~(toggleState);
876         }
877     }
878     
879     if (pCb->drainFlag == 1)
880     {
881         //
882         // Writer inactive, but remaining frames in circular buffer.
883         // Update drain flag.
884         //
885         if (pCb->numAfCb <= 0)
886         {
887             pCb->drainFlag = 0;
888         }
889     }
890     
891     // Write back circular buffer configuration.
892     // NOTE: Probably only a subset of this information needs to be updated.
893     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
894     Cache_wait();    
895         
896     // Leave the gate
897     GateMP_leave(gateHandle, key);
899     return ASP_DECOP_CB_SOK;
902 #if 0
903 // Generate mute AF on circular buffer read
904 static Void cbReadAfMute(
905     PAF_AudioFrame *pAfRd,      // audio frame into which to read
906     Int16 strFrameLen           // stream frame length (output transaction size)
909     PAF_ChannelMask_HD streamMask;
910     Int8 i;
911     
912     pAfRd->sampleDecode = PAF_SOURCE_PCM;
913     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
914     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
915     pAfRd->sampleCount = strFrameLen;
916     pAfRd->channelConfigurationRequest.full = 0;
917     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
918     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
919     pAfRd->channelConfigurationStream.full = 0;
920     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
921     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
922     
923     // compute stream mask
924     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
925     // Clear PCM data
926     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
927     {
928         if ((streamMask >> i) & 0x1)
929         {
930             memset(pAfRd->data.sample[i], 0, strFrameLen*sizeof(PAF_AudioData));
931         }
932         pAfRd->data.samsiz[i] = 0;
933     }
934     // write metadata information updated by decoder
935     pAfRd->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
936     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
937     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
938     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
940 #endif
942 // Init last audio frame configuration info 
943 static Void cbInitLastAfInfo(
944     PAF_AudioFrame *pAfRd      // last audio frame stored in CB instance
947     pAfRd->sampleDecode = PAF_SOURCE_PCM;
948     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
949     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
950     pAfRd->sampleCount = DEF_DEC_OP_FRAME_LEN;
951     pAfRd->channelConfigurationRequest.full = 0;
952     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
953     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
954     pAfRd->channelConfigurationStream.full = 0;
955     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
956     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
958     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
959     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
960     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
961     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
964 // Update last audio frame configuration info 
965 static Void cbUpdateLastAfInfo(
966     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
967     PAF_AudioFrame *pAfUpd      // audio frame used for update
970     // FL: full copy shouldn't be necessary
971     //  Note currently (data.nChannels, data.nSamples)=(32,256) is fixed in ASOT stream AF.
972     //  There parameters aren't copied from CB on CB read.
973     //memcpy (&pCb->lastAf, pAfUpd, sizeof(PAF_AudioFrame));
975     // These are parameters used in cbReadMuteWithLastAfInfo()
976     pCb->lastAf.sampleDecode = pAfUpd->sampleDecode;
977     pCb->lastAf.sampleRate = pAfUpd->sampleRate;
978     pCb->lastAf.channelConfigurationRequest.full = pAfUpd->channelConfigurationRequest.full;
979     pCb->lastAf.channelConfigurationStream.full = pAfUpd->channelConfigurationStream.full;
982 // Generate mute AF on circular buffer read using the last AF configuration info 
983 static Void cbReadMuteWithLastAfInfo (
984     PAF_AST_DecOpCircBuf *pCb,    // decoder output circular buffer control
985     PAF_AudioFrame *pAfRd         // audio frame into which to read
988     PAF_ChannelMask_HD streamMask;
989     Int8 i;
991     pAfRd->sampleDecode = pCb->lastAf.sampleDecode;
992     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
993     pAfRd->sampleRate  = pCb->lastAf.sampleRate;
994     pAfRd->sampleCount = pCb->strFrameLen;
995     pAfRd->channelConfigurationRequest.full     = pCb->lastAf.channelConfigurationRequest.full;
996     //pAfRd->channelConfigurationRequest.part.sat = pCb->lastAf.channelConfigurationRequest.part.sat; // FL: not necessary since full in union already copied
997     //pAfRd->channelConfigurationRequest.part.sub = pCb->lastAf.channelConfigurationRequest.part.sub;
998     pAfRd->channelConfigurationStream.full      = pCb->lastAf.channelConfigurationStream.full;
999     //pAfRd->channelConfigurationStream.part.sat  = pCb->lastAf.channelConfigurationStream.part.sat;
1000     //pAfRd->channelConfigurationStream.part.sub  = pCb->lastAf.channelConfigurationStream.part.sub;
1001     
1002     // compute stream mask
1003     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
1004     // Clear PCM data
1005     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
1006     {
1007         if ((streamMask >> i) & 0x1)
1008         {
1009             memset(pAfRd->data.sample[i], 0, pAfRd->sampleCount*sizeof(PAF_AudioData));
1010         }
1011         pAfRd->data.samsiz[i] = 0;
1012     }
1013     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
1014     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1015     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1016     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1019 // Check circular buffer drain state
1020 Int cbCheckDrainState(
1021     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
1022     Int8 cbIdx,                         // decoder output circular buffer index, or indicator combined drain state desired
1023     Int8 *pDrainedFlag                  // output drain state indicator (combined or for selected circular buffer)
1026     IArg key;
1027     GateMP_Handle gateHandle;
1028     PAF_AST_DecOpCircBuf *pCb;
1029     Int8 drainedFlag;
1030     Int8 i;
1031     
1032     // Get gate handle
1033     gateHandle = pCbCtl->gateHandle;
1034     // Enter gate
1035     key = GateMP_enter(gateHandle);
1037     if (cbIdx != ASP_DECOP_CHECK_DRAINSTATE_ALL)
1038     {
1039         //
1040         // Check drain state for selected circular buffer
1041         //
1042         
1043         // Get circular buffer base pointer
1044         pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
1046         // Invalidate circular buffer configuration
1047         Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1048         Cache_wait();
1050         drainedFlag = !pCb->writerActiveFlag && !pCb->drainFlag;
1051     }
1052     else
1053     {
1054         //
1055         // Check combined drain state for all circular buffers.
1056         // Combined drain state is logical AND of drain state for all circular buffers.
1057         //
1059         drainedFlag = 1; // init combined drained flag to TRUE
1060         for (i = 0; i < pCbCtl->numDecOpCb; i++)
1061         {
1062             // Get circular buffer base pointer
1063             pCb = &((*pCbCtl->pXDecOpCb)[i]);
1065             // Invalidate circular buffer configuration
1066             Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1067             Cache_wait();
1068             
1069             // Update combined drain state
1070             drainedFlag = drainedFlag && (!pCb->writerActiveFlag && !pCb->drainFlag);
1071         }
1072     }
1073     
1074     *pDrainedFlag = drainedFlag;
1075     
1076     // Leave the gate
1077     GateMP_leave(gateHandle, key);
1079     return ASP_DECOP_CB_SOK;