PASDK-218:Add rudimentary Dec Op CB status and alpha command interface
[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 #if 0
69 // Init last audio frame configuration info 
70 static Void cbInitLastAfInfo(
71     PAF_AudioFrame *pAfRd      // last audio frame stored in CB instance
72 );
73 #endif
75 // Update last audio frame configuration info 
76 static Void cbUpdateLastAfInfo(
77     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
78     PAF_AudioFrame *pAfUpd      // audio frame used for update
79 );
81 // Generate mute AF on circular buffer read using the last AF configuration info 
82 static Void cbReadMuteWithLastAfInfo(
83     PAF_AST_DecOpCircBuf *pCb,    // decoder output circular buffer control
84     PAF_AudioFrame *pAfRd         // audio frame into which to read
85 );
87 #if 0 // FL: moved to common
88 // Initialize circular buffer control
89 Int cbCtlInit(
90     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
91     Int8 numCb,                         // number of circular buffers
92     PAF_AST_DecOpCircBuf **pXDecOpCb    // address of decoder output circular buffer base pointer
93 )
94 {
95     GateMP_Params gateParams;
96     GateMP_Handle gateHandle;
97     
98     GateMP_Params_init(&gateParams);
99     gateParams.localProtect = GateMP_LocalProtect_THREAD;
100     gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM;
101     gateParams.name = ASP_DECODE_CB_GATE_NAME;
102     gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID;
103     gateHandle = GateMP_create(&gateParams);
104     if (gateHandle != NULL)
105     {
106         pCbCtl->gateHandle = gateHandle;
107     }
108     else
109     {
110         pCbCtl->gateHandle = NULL;
111         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
112     }
113     
114     pCbCtl->numCb = numCb;          // init number of circular buffers
115     pCbCtl->pXDecOpCb = pXDecOpCb;  // init base address of circular buffers
116     
117     return ASP_DECOP_CB_SOK;    
119 #endif
121 // Initialize circular buffer
122 Int cbInit(
123     PAF_AST_DecOpCircBuf *pCb
126 #if 0 // FL: unused
127     PAF_AudioFrame *pAfCb;
128     PAF_AudioData *pPcmBuf;
129     UInt8 *pMetaBuf;
130     Int8 n;
131     Int8 i;
133     // set source select
134     pCb->sourceSel = DEF_SOURCE_SEL;
136     // set input frame length
137     pCb->decOpFrameLen = DEF_DEC_OP_FRAME_LEN;
138     
139     // set output frame length
140     pCb->strFrameLen = DEF_STR_FRAME_LEN;
141     
142     // initialize circular buffer maximum number of audio frames
143     pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD; //ASP_DECOP_CB_MAX_NUM_AF_PCM;
144     pCb->afWrtIdx = ASP_DECOP_CB_INIT_LAG_PCM;
145     pCb->afRdIdx = 0;
146     pCb->pcmRdIdx = 0;
148     // Initialize CB primed flag
149     pCb->primedFlag = 0;
150     // Initialize delta samples
151     pCb->deltaSamps = 0;
152     
153     // set default value to PCM configuration
154     pCb->maxAFChanNum   = ASP_DECOP_CB_MAX_NUM_PCM_CH;
155     pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;
156     // initialize audio frames
157     for (n=0; n<pCb->maxNumAfCb; n++)
158     {
159         pAfCb = &pCb->afCb[n];
160         pAfCb->sampleDecode = PAF_SOURCE_PCM;
161         PAF_PROCESS_ZERO(pAfCb->sampleProcess);
162         pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
163         pAfCb->sampleCount = DEF_DEC_OP_FRAME_LEN;
164         pAfCb->channelConfigurationRequest.full = 0;
165         pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
166         pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
167         pAfCb->channelConfigurationStream.full = 0;
168         pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
169         pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
170     }
172     // initialize circular buffer current number of frames
173     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
174     
175     // initialize audio frame PCM buffers
176     pPcmBuf = pCb->pcmBuf;
177     pMetaBuf = pCb->metaBuf;
178     for (n=0; n<pCb->maxNumAfCb; n++)
179     {
180         pAfCb = &pCb->afCb[n];
181         pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH;
182         pAfCb->data.nSamples = DEF_DEC_OP_FRAME_LEN;
183         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
184         {
185             pAfCb->data.sample[i] = pPcmBuf;
186             memset(pAfCb->data.sample[i], 0, DEF_DEC_OP_FRAME_LEN);
187             pPcmBuf += DEF_DEC_OP_FRAME_LEN;
188             
189             pAfCb->data.samsiz[i] = 0;
190         }
191         
192         // write metadata information updated by decoder
193         pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
194         pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
195         pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
196         pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
197         
198         // Initialize metadata buffers
199         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
200         {
201             pAfCb->pafPrivateMetadata[i].offset = 0; 
202             pAfCb->pafPrivateMetadata[i].size   = 0; 
203             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
204             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
205         }
206     }
207     
208     // reset read/write flags
209     pCb->writerActiveFlag = 0;
210     pCb->readerActiveFlag = 0;
211     pCb->drainFlag = 0;
212     
213     // reset stats
214     pCb->readAfWriterInactiveCnt = 0;
215     pCb->readAfNdCnt = 0;
216     pCb->wrtAfReaderInactiveCnt = 0;
217     pCb->wrtAfZeroSampsCnt = 0;
218     pCb->errUndCnt = 0;
219     pCb->errOvrCnt = 0;
220     
221     #ifdef CB_RW_OP_CAP_PP // debug
222     // Get address in global variables
223     gCB_samples_op = pCb->cb_samples_op;
224     gCB_op_owner = pCb->cb_op_owner;
225     gCB_opCnt = &pCb->cb_opCnt;
226     gCB_afRdIdx = pCb->cb_afRdIdx;
227     gCB_afWrtIdx = pCb->cb_afWrtIdx;
228     gCB_numAfCb = pCb->cb_numAfCb;
229     #endif
231     cbInitLastAfInfo(&pCb->lastAf);
233     // Write back circular buffer configuration
234     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
235     // Write back AF circular buffer
236     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
237     // Write back PCM data
238     for (n=0; n<pCb->maxNumAfCb; n++)
239     {
240         pAfCb = &pCb->afCb[n];
241         Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
242         Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
243         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
244         {
245             Cache_wb(pAfCb->data.sample[i], DEF_DEC_OP_FRAME_LEN*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
246         }
247     }
248     Cache_wait();
249 #endif
251     // set source select
252     pCb->sourceSel = PAF_SOURCE_UNKNOWN;
254     #ifdef CB_RW_OP_CAP_PP // debug
255     // Get address in global variables
256     gCB_samples_op = pCb->cb_samples_op;
257     gCB_op_owner = pCb->cb_op_owner;
258     gCB_opCnt = &pCb->cb_opCnt;
259     gCB_afRdIdx = pCb->cb_afRdIdx;
260     gCB_afWrtIdx = pCb->cb_afWrtIdx;
261     gCB_numAfCb = pCb->cb_numAfCb;
262     #endif
263     
264     // Write back circular buffer configuration
265     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
266     Cache_wait();
268     return ASP_DECOP_CB_SOK;
271 #if 0 // FL: moved to ARM
272 // debug
273 //Int8 gCbInitSourceSelCnt=0;
274 //Int8 gCbInitSourceSelThdCnt=0;
276 // Initialize circular buffer based on selected source
277 Int cbInitSourceSel(
278     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
279     Int8 cbIdx,                         // decoder output circular buffer index
280     Int8 sourceSelect,                  // source select (PCM, DDP, etc.)
281     Int16 decOpFrameLen,                // decoder output frame length (PCM samples)
282     Int16 strFrameLen,                  // stream frame length (PCM samples)
283     Int8 resetRwFlags                   // whether to reset reader, writer, and drain flags
286     IArg key;
287     GateMP_Handle gateHandle;
288     PAF_AST_DecOpCircBuf *pCb;
289     PAF_AudioFrame *pAfCb;
290     PAF_AudioData *pPcmBuf;
291     UInt8 *pMetaBuf;
292     Int8 n;
293     Int8 i;
295     //gCbInitSourceSelCnt++; // debug
296     
297     // Get gate handle
298     gateHandle = pCbCtl->gateHandle;
299     // Enter gate
300     key = GateMP_enter(gateHandle);
302     // Get circular buffer base pointer
303     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
304     
305     // Invalidate circular buffer configuration
306     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
307     Cache_wait();
309     //Log_info1("cbInitSourceSel:afCb=0x%04x", (IArg)pCb->afCb); // debug
311     // set source select
312     pCb->sourceSel = sourceSelect;
314     // set input frame length
315     pCb->decOpFrameLen = decOpFrameLen;
316     
317     // set output frame length
318     pCb->strFrameLen = strFrameLen;
320     //pCb->afInitialLag = 0;  // default No lag
321     //pCb->afLagIdx = 0;
322     // Initialize CB primed flag
323     pCb->primedFlag = 0;
324     // Initialize delta samples
325     pCb->deltaSamps = 0;
326     
327     // initialize circular buffer maximum number of audio frames
328     if (sourceSelect == PAF_SOURCE_PCM)
329     {
330         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM;
331         
332         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
333         // Initialize target nominal delay
334         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM;
335         
336         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM;
337         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM;
338         pCb->pcmRdIdx = 0;
339         
340         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH;
341         pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;
342         
343         // initialize audio frames
344         for (n=0; n<pCb->maxNumAfCb; n++)
345         {
346             pAfCb = &pCb->afCb[n];
347             pAfCb->sampleDecode = sourceSelect;
348             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
349             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
350             pAfCb->sampleCount = decOpFrameLen;
351             pAfCb->channelConfigurationRequest.full = 0;
352             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
353             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
354             pAfCb->channelConfigurationStream.full = 0;
355             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
356             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
357             
358             // write metadata information updated by decoder
359             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
360             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
361             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
362             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
363         }
364     }
365     else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3))
366     {
367         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP;
368         
369         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP;
370         // Initialize target nominal delay
371         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kDDP;
372         
373         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP;
374         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP;
375         pCb->pcmRdIdx = 0;
376         
377         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP;
378         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP;
379         
380         // initialize audio frames
381         for (n=0; n<pCb->maxNumAfCb; n++)
382         {
383             pAfCb = &pCb->afCb[n];
384             pAfCb->sampleDecode = sourceSelect;
385             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
386             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
387             pAfCb->sampleCount = decOpFrameLen;
388             pAfCb->channelConfigurationRequest.full = 0;
389             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
390             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
391             pAfCb->channelConfigurationStream.full = 0;
392             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
393             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
394             
395             // write metadata information updated by decoder
396             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
397             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
398             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
399             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
400         }
401     }
402     else if (sourceSelect == PAF_SOURCE_THD)
403     {
404         //gCbInitSourceSelThdCnt++; //debug
405         
406         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;
407         
408         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD;
409         // Initialize target nominal delay
410         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
411         
412         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD;
413         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD;
414         pCb->pcmRdIdx = 0;
415         
416         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT;
417         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT;
418         
419         // initialize audio frames
420         for (n=0; n<pCb->maxNumAfCb; n++)
421         {
422             pAfCb = &pCb->afCb[n];
423             pAfCb->sampleDecode = sourceSelect;
424             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
425             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
426             pAfCb->sampleCount = decOpFrameLen;
427             pAfCb->channelConfigurationRequest.full = 0;
428             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
429             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
430             pAfCb->channelConfigurationStream.full = 0;
431             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
432             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
433             
434             // write metadata information updated by decoder
435             pAfCb->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
436             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
437             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
438             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
439         }
440     }
441     else
442     {
443         SW_BREAKPOINT;
444         
445         // Leave the gate
446         GateMP_leave(gateHandle, key);
448         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
449     }
451     // initialize circular buffer current number of frames
452     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
453     
454     // initialize audio frame PCM buffers
455     pPcmBuf = pCb->pcmBuf;
456     pMetaBuf = pCb->metaBuf;
457     for (n=0; n<pCb->maxNumAfCb; n++)
458     {
459         pAfCb = &pCb->afCb[n];
460         pAfCb->data.nChannels = pCb->maxAFChanNum;
461         pAfCb->data.nSamples = decOpFrameLen;
462         for (i=0; i<pCb->maxAFChanNum; i++)
463         {
464             pAfCb->data.sample[i] = pPcmBuf;
465             memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount);
466             pPcmBuf += pCb->maxAFSampCount;
467             
468             pAfCb->data.samsiz[i] = 0;
469         }
470         
471         // Initialize metadata buffers
472         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
473         {
474             pAfCb->pafPrivateMetadata[i].offset = 0; 
475             pAfCb->pafPrivateMetadata[i].size   = 0; 
476             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
477             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
478         }
479     }
480     
481     // reset read/write flags
482     if (resetRwFlags)
483     {
484         pCb->writerActiveFlag = 0;
485         pCb->readerActiveFlag = 0;
486         pCb->drainFlag = 0;
487     }
488     
489     // reset stats
490     pCb->readAfWriterInactiveCnt = 0;
491     pCb->readAfNdCnt = 0;
492     pCb->wrtAfReaderInactiveCnt = 0;
493     pCb->wrtAfZeroSampsCnt = 0;
494     pCb->errUndCnt = 0;
495     pCb->errOvrCnt = 0;
496     
497     // Write back circular buffer configuration
498     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
499     // Write back AF circular buffer
500     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
501     // Write back PCM data
502     for (n=0; n<pCb->maxNumAfCb; n++)
503     {
504         pAfCb = &pCb->afCb[n];
505         Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
506         Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
507         for (i=0; i<pCb->maxAFChanNum; i++)
508         {
509             Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
510         }
511     }
512     Cache_wait();
514     // Leave the gate
515     GateMP_leave(gateHandle, key);
516     
517     return ASP_DECOP_CB_SOK;
519 #endif
521 // Initialize circular buffer for Stream reads
522 Int cbInitStreamRead(
523     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
524     Int8 cbIdx                          // decoder output circular buffer index
527     IArg key;
528     GateMP_Handle gateHandle;
529     PAF_AST_DecOpCircBuf *pCb;
530     
531     // Get gate handle
532     gateHandle = pCbCtl->gateHandle;
533     // Enter gate
534     key = GateMP_enter(gateHandle);
536     // Get circular buffer base pointer
537     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
538     
539     // Invalidate circular buffer configuration
540     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
541     Cache_wait();
543     // Set output frame length
544     pCb->strFrameLen = pCb->cbStatus.strFrameLen;
546     // Write back circular buffer configuration
547     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
548     Cache_wait();
550     // Leave the gate
551     GateMP_leave(gateHandle, key);
552     
553     //return ret;
554     return ASP_DECOP_CB_SOK;
557 // Start reads from circular buffer
558 Int cbReadStart(
559     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
560     Int8 cbIdx                          // decoder output circular buffer index
563     IArg key;
564     GateMP_Handle gateHandle;
565     PAF_AST_DecOpCircBuf *pCb;
567     // Get gate handle
568     gateHandle = pCbCtl->gateHandle;
569     // Enter gate
570     key = GateMP_enter(gateHandle);
572     // Get circular buffer base pointer
573     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
574     
575     // Invalidate circular buffer configuration
576     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
577     Cache_wait();
578     
579     //Log_info1("cbReadStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
581     // update flags
582     pCb->readerActiveFlag = 1;
583     
584     // Write back circular buffer configuration
585     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
586     Cache_wait();
588     // Leave the gate
589     GateMP_leave(gateHandle, key);
591     return ASP_DECOP_CB_SOK;
594 // Stop reads from circular buffer
595 Int cbReadStop(
596     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
597     Int8 cbIdx                          // decoder output circular buffer index
600     IArg key;
601     GateMP_Handle gateHandle;
602     PAF_AST_DecOpCircBuf *pCb;
604     // Get gate handle
605     gateHandle = pCbCtl->gateHandle;
606     // Enter gate
607     key = GateMP_enter(gateHandle);
609     // Get circular buffer base pointer
610     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
612     // Invalidate circular buffer configuration
613     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
614     Cache_wait();
615     
616     //Log_info1("cbReadStop:afCb=0x%04x", (IArg)pCb->afCb); // debug
618     // update flags
619     pCb->readerActiveFlag = 0;
620     
621     // Write back circular buffer configuration
622     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
623     Cache_wait();
625     // Leave the gate
626     GateMP_leave(gateHandle, key);
628     return ASP_DECOP_CB_SOK;
631 // debug
632 //Int16 gDeltaSampsBuf[20];
633 //Int8 gDeltaSampsBufIdx=0;
635 // Read audio frame from circular buffer
636 Int cbReadAf(
637     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
638     Int8 cbIdx,                         // decoder output circular buffer index
639     PAF_AudioFrame *pAfRd               // audio frame into which to read
642     IArg key;
643     GateMP_Handle gateHandle;           // CB gate handle to arbitrate CB r/w access
644     PAF_AST_DecOpCircBuf *pCb;          // pointer to CB
645     PAF_AudioFrame *pAfCb;              // pointer to current CB AF
646     PAF_ChannelMask_HD streamMask;      // CB AF stream mask
647     Int16 numSampsRd;                   // number of samples to read from current CB AF
648     Int16 totNumSampsRd;                // total number of samples read from CB
649     Int16 pcmWrtIdx;                    // read audio frame PCM write index
650     Int8 prvMdWrtIdx;                   // read audio frame metadata write index
651     Int8 i;
652     Int16 j;
653     
654     // Get gate handle
655     gateHandle = pCbCtl->gateHandle;
656     // Enter gate
657     key = GateMP_enter(gateHandle);
659     // Get circular buffer base pointer
660     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
662     // Invalidate circular buffer configuration.
663     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
664     Cache_wait();
666     //Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
668     //
669     // Check (writerActiveFlag,drainFlag)=(1,1)
670     //
671     if ((pCb->writerActiveFlag == 1) && (pCb->drainFlag == 1))
672     {
673         //
674         // This shouldn't occur:
675         // writer is active AND draining circular buffer
676         //
677         
678         //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // debug
679         SW_BREAKPOINT; // debug
680         
681         // Leave the gate
682         GateMP_leave(gateHandle, key);
683         
684         return ASP_DECOP_CB_READ_INVSTATE;
685     }
687     //
688     // Check (writerActiveFlag,drainFlag)=(0,0)
689     //
690     //if (((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) || (pCb->afLagIdx < pCb->afInitialLag))
691     if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0))
692     {
693         //
694         // Writer inactive, not draining circular buffer.
695         // Skip UNDerflow check, mute output.
696         //
697         
698         pCb->readAfWriterInactiveCnt++;
699         
700         // Mute output if write inactive and not draining CB
701         //cbReadAfMute(pAfRd, pCb->strFrameLen);
702         cbReadMuteWithLastAfInfo(pCb, pAfRd);
703         
704         // Write back circular buffer configuration.
705         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
706         Cache_wait();
708         // Leave the gate
709         GateMP_leave(gateHandle, key);
711         return ASP_DECOP_CB_SOK;
712     }
714     if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 1))
715     {
716         //
717         // Writer inactive, but remaining frames in circular buffer.
718         // Update drain flag.
719         //
720         
721         if (pCb->numAfCb <= 0)
722         {
723             pCb->drainFlag = 0;
725             // Mute output if CB drained
726             cbReadMuteWithLastAfInfo(pCb, pAfRd);
728             // Write back circular buffer configuration.
729             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
730             Cache_wait();    
732             // Leave the gate
733             GateMP_leave(gateHandle, key);
735             return ASP_DECOP_CB_SOK;
736         }
737     }
738     
739     //
740     // Hold off read of PCM samples from CB until Nominal Delay satisfied
741     //
742     //if ((pCb->primedFlag == 0) || ((pCb->primedFlag==1) && (pCb->deltaSamps > 0))
743     if ((pCb->primedFlag == 0) || (pCb->deltaSamps > 0))
744     {
745         pCb->readAfNdCnt++;
746         
747         if (pCb->primedFlag == 1)
748         {
749             pCb->deltaSamps = pCb->deltaSamps - pCb->strFrameLen;
750             
751             // debug
752             //gDeltaSampsBuf[gDeltaSampsBufIdx] = pCb->deltaSamps;
753             //if (gDeltaSampsBufIdx < 20)
754             //    gDeltaSampsBufIdx++;
755         }
756         
757         cbReadMuteWithLastAfInfo(pCb, pAfRd);
758         
759         // Write back circular buffer configuration.
760         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
761         Cache_wait();    
762         
763         // Leave the gate
764         GateMP_leave(gateHandle, key);
766         return ASP_DECOP_CB_SOK;
767     }
768     
769     //
770     // (writerActiveFlag,drainFlag)= (0,0) and (1,1) states checked above
771     // (writerActiveFlag,drainFlag)=(1,0) and (0,1) states are left
772     // Checking (writerActiveFlag,drainFlag)=(1,0) state here
773     //
774     if (pCb->writerActiveFlag == 1)
775     {
776         // check underflow
777         if (pCb->numAfCb <= 0)
778         {
779             // 
780             // Increment underflow count
781             //
782             pCb->errAfUndCnt++;
784             // Mute output on underflow
785             //cbReadAfMute(pAfRd, pCb->strFrameLen);
786             cbReadMuteWithLastAfInfo(pCb, pAfRd);
787             //SW_BREAKPOINT; // debug
788             
789 #if 0 // (***) FL: shows timing of CB underflow
790             // debug
791             {
792                 static Uint8 toggleState = 0;
793                 if (toggleState == 0)
794                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
795                 else
796                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
797                 toggleState = ~(toggleState);
798             }
799 #endif
801             #ifdef CB_RW_OP_CAP_PP // debug
802             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
803             {
804                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
805                 {
806                     // log sample count
807                     pCb->cb_samples_op[pCb->cb_opCnt] = 0;  // due to underflow
808                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
809                     // log idxs
810                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
811                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
812                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
813                     pCb->cb_opCnt++;
814                 }
815             }
816             #endif
818             // Write back circular buffer configuration.
819             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
820             Cache_wait();    
821             
822             // Leave the gate
823             GateMP_leave(gateHandle, key);
824             
825             return ASP_DECOP_CB_AF_READ_UNDERFLOW;
826         }
827     }
828     
829     //
830     // Checking (writerActiveFlag,drainFlag)=(1,0) state above and here
831     // Checking (writerActiveFlag,drainFlag)=(0,1) state here
832     //
833     if ((pCb->writerActiveFlag == 1) || (pCb->drainFlag == 1))
834     {
835         //
836         // Writer active or draining remaining frames in circular buffer.
837         // Read next audio frame.
838         //
840         //
841         // Read Audio Frame from CB Audio Frames.
842         // Read PCM & associated metadata from CB AFs until Read AF is filled.
843         //
844         // If multiple CB AFs are read in creating Read AF, CB AF parameters 
845         // can *change* between read CB AFs. Since only one Read AF is produced 
846         // per CB read, this is a "data collision", i.e. can't have more than 
847         // one set of CB AF parameters in Read AF.
848         //
849         // Currently applying parameters from earliest read CB AF to Read Af.
850         // This can result in delay (or skip) w.r.t. application of additional 
851         // CB AF parameters not used for creating Read AF. This is reasonable 
852         // given there's no way to "interpolate" AF parameters, e.g. how to 
853         // interpolation change in in bit-stream metadata type, or CC stream?
854         //
855         
856         // Get pointer to current CB Audio Frame
857         pAfCb = &pCb->afCb[pCb->afRdIdx];
859         // Cache invalidate CB AF
860         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
861         Cache_wait();
862         
863         // Read CB AF information updated by decoder
864         pAfRd->sampleDecode = pAfCb->sampleDecode;
865         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
866         pAfRd->sampleRate = pAfCb->sampleRate;
867         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
868         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
869         // Read CB AF bit-stream metadata information updated by decoder
870         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if private metadata is attached. */
871         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
872         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
873         
874         // Compute stream mask for current CB AF.
875         // Mask indicates which channels are present in AF.
876         // Mask needed for cache invalidate and read of PCM samples in AF.
877         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
879         // Cache invalidate CB AF samsiz (volume scaling exponent) array
880         Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
881         Cache_wait();
882         
883         // Read CB AF samsiz array
884         for (i = 0; i < pCb->maxAFChanNum; i++)
885         {
886             if ((streamMask >> i) & 0x1)
887             {
888                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
889             }
890         }
892         // FL: brute force clear of Read AF PCM data
893         // Reset Read AF PCM data
894         //for (i = 0; i < pCb->maxAFChanNum; i++)
895         //{
896         //    if ((streamMask >> i) & 0x1)
897         //    {
898         //        memset(pAfRd->data.sample[i], 0, pCb->strFrameLen);
899         //    }
900         //}
901         
902         // FL: This brute force approach shouldn't be necessary if
903         //     decoders properly set, and downstream components
904         //     properly use, number of private metadata in frame
905         // Reset Read AF metadata
906         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
907         {
908             pAfRd->pafPrivateMetadata[i].offset = 0;
909             pAfRd->pafPrivateMetadata[i].size   = 0;
910         }
911         
912         totNumSampsRd = 0;  // init total number of samples read from CB
913         pcmWrtIdx = 0;      // init Read AF PCM write index
914         prvMdWrtIdx = 0;    // init Read AF metadata write index
915         while ((totNumSampsRd < pCb->strFrameLen) && (pCb->numAfCb > 0))
916         {
917             // Compute how many PCM samples can be read from CB AF
918             //  Number of samples left in current CB AF: pAfCb->sampleCount - pCb->pcmRdIdx
919             //  Number of samples left to write to Read AF: pCb->strFrameLen - totNumSampsRd
920             numSampsRd = (pAfCb->sampleCount - pCb->pcmRdIdx) < (pCb->strFrameLen - totNumSampsRd) ? 
921                 (pAfCb->sampleCount - pCb->pcmRdIdx) : (pCb->strFrameLen - totNumSampsRd);
923             // Cache invalidate CB AF PCM sample channel pointers
924             Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
925             Cache_wait();
927             // Cache invalidate CB AF PCM samples
928             for (i = 0; i < pCb->maxAFChanNum; i++)
929             {
930                 if ((streamMask >> i) & 0x1)
931                 {
932                     Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], numSampsRd*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
933                 }
934             }
935             Cache_wait();
937             // Read PCM samples from CB AF
938             for (i = 0; i < pCb->maxAFChanNum; i++)
939             {
940                 if ((streamMask >> i) & 0x1)
941                 {
942                     for (j = 0; j < numSampsRd; j++)
943                     {
944                         pAfRd->data.sample[i][pcmWrtIdx+j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
945                     }
946                 }
947             }
949             // Cache invalidate CB AF unused metadata
950             for (i = pCb->prvMdRdIdx; i < pAfCb->numPrivateMetadata; i++)
951             {
952                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size
953             }
954             Cache_wait();
956             // Read CB AF metadata
957             while (((pCb->prvMdRdIdx < pAfCb->numPrivateMetadata) && 
958                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset >= pCb->pcmRdIdx) &&
959                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset < (pCb->pcmRdIdx + numSampsRd)) &&
960                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size)) &&
961                 (prvMdWrtIdx < PAF_MAX_NUM_PRIVATE_MD))
962             {
963                 // Write Read AF metadata offset.
964                 //  Compute relative offset of PCM samples being read from CB AF.
965                 //  Compute absolute offset of PCM samples written to Read AF by 
966                 //  adding relative offset to Read AF PCM write index.
967                 pAfRd->pafPrivateMetadata[prvMdWrtIdx].offset = 
968                     (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset - pCb->pcmRdIdx) +   // offset relative to samples being read from CB AF
969                     pcmWrtIdx;                                                              // absolute offset into samples being written to read AF
970                 // Write Read AF metadata size    
971                 pAfRd->pafPrivateMetadata[prvMdWrtIdx].size = pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size;
972                 // Write Read AF metadata payload
973                 memcpy(pAfRd->pafPrivateMetadata[prvMdWrtIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size);
974                 
975                 pCb->prvMdRdIdx++;  // update CB metadata read index
976                 prvMdWrtIdx++;      // update CB metadata write index
977             }
978             
979             // Update CB control
980             pCb->pcmRdIdx += numSampsRd; // update PCM read index
981             if (pCb->pcmRdIdx >= pAfCb->sampleCount) 
982             {
983                 // Finished reading PCM samples from current CB AF.
984                 // Move to next AF in CB.
985                 
986                 // Update audio frame read index.
987                 // Wrap index if required.
988                 pCb->afRdIdx++;
989                 if (pCb->afRdIdx >= pCb->maxNumAfCb)
990                 {
991                     pCb->afRdIdx = 0;
992                 }
993                 
994                 // Reset PCM read index
995                 pCb->pcmRdIdx = 0;
996                 // Reset metadata read index
997                 pCb->prvMdRdIdx = 0;
998                 
999                 // Update number of audio frames in circular buffer
1000                 pCb->numAfCb--;
1001             }
1002             
1003             // Update PCM write index
1004             pcmWrtIdx += numSampsRd;
1006             // Update total number of samples read
1007             totNumSampsRd += numSampsRd;
1008             
1009             if (totNumSampsRd < pCb->strFrameLen)
1010             {
1011                 //
1012                 // Need to read another AF from CB to obtain all PCM/metadata for Read AF
1013                 //
1014                 
1015                 // Get pointer to current CB Audio Frame
1016                 pAfCb = &pCb->afCb[pCb->afRdIdx];
1017                 
1018                 // Cache invalidate CB AF
1019                 Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
1020                 Cache_wait();
1021             }
1022         }
1023        
1024         pAfRd->sampleCount = totNumSampsRd;         // write Read AF sample count
1025         pAfRd->numPrivateMetadata = prvMdWrtIdx;    // write Read AF number of metadata
1026         
1027         pCb->numPcmSampsPerCh -= totNumSampsRd;     // update PCM samples per channel
1028        
1029         if (totNumSampsRd < pCb->strFrameLen)
1030         {
1031             // Clear remaining Read AF PCM samples
1032             for (i = 0; i < pCb->maxAFChanNum; i++)
1033             {
1034                 if ((streamMask >> i) & 0x1)
1035                 {
1036                     memset(&pAfRd->data.sample[i][pcmWrtIdx], 0, (pCb->strFrameLen-totNumSampsRd));
1037                 }
1038             }
1039             
1040             if (pCb->writerActiveFlag == 1)
1041             {
1042                 //
1043                 // UNDerflow, 
1044                 // read stopped due to insufficient PCM samples in CB to fill Read AF
1045                 //
1046             
1047                 // 
1048                 // Increment underflow count
1049                 //
1050                 pCb->errPcmUndCnt++;
1052                 // Mute output on underflow
1053                 cbReadMuteWithLastAfInfo(pCb, pAfRd);
1054                 
1055 #if 0 // (***) FL: shows timing of CB underflow
1056                 // debug
1057                 {
1058                     static Uint8 toggleState = 0;
1059                     if (toggleState == 0)
1060                         GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
1061                     else
1062                         GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
1063                     toggleState = ~(toggleState);
1064                 }
1065 #endif
1067                 #ifdef CB_RW_OP_CAP_PP // debug
1068                 if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
1069                 {
1070                     if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
1071                     {
1072                         // log sample count
1073                         pCb->cb_samples_op[pCb->cb_opCnt] = 0;  // due to underflow
1074                         pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
1075                         // log idxs
1076                         pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
1077                         pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
1078                         pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
1079                         pCb->cb_opCnt++;
1080                     }
1081                 }
1082                 #endif
1084                 // Write back circular buffer configuration.
1085                 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1086                 Cache_wait();    
1087                 
1088                 // Leave the gate
1089                 GateMP_leave(gateHandle, key);
1090                 
1091                 return ASP_DECOP_CB_PCM_READ_UNDERFLOW;
1092             }
1093         }
1094         
1095         // Read AF complete, update Last CB AF Info
1096         cbUpdateLastAfInfo(pCb, pAfRd);
1098 #if 0 // (***) FL: shows timing of successful CB read
1099         {
1100             static Uint8 toggleState = 0;
1101             if (toggleState == 0)
1102                 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
1103             else
1104                 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
1105             toggleState = ~(toggleState);
1106         }
1107 #endif
1109 #ifdef CB_RW_OP_CAP_PP // debug
1110         if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
1111         {
1112             if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
1113             {
1114                 // log sample count
1115                 pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount;
1116                 pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
1117                 // log idxs
1118                 pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
1119                 pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
1120                 pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
1121                 pCb->cb_opCnt++;
1122             }
1123         }
1124 #endif
1125     }
1126     
1127 #if 0
1128     if (pCb->drainFlag == 1)
1129     {
1130         //
1131         // Writer inactive, but remaining frames in circular buffer.
1132         // Update drain flag.
1133         //
1134         if (pCb->numAfCb <= 0)
1135         {
1136             pCb->drainFlag = 0;
1137         }
1138     }
1139 #endif
1140     
1141     // Write back circular buffer configuration.
1142     // NOTE: Probably only a subset of this information needs to be updated.
1143     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1144     Cache_wait();    
1145         
1146     // Leave the gate
1147     GateMP_leave(gateHandle, key);
1149     return ASP_DECOP_CB_SOK;
1152 #if 0
1153 // Generate mute AF on circular buffer read
1154 static Void cbReadAfMute(
1155     PAF_AudioFrame *pAfRd,      // audio frame into which to read
1156     Int16 strFrameLen           // stream frame length (output transaction size)
1159     PAF_ChannelMask_HD streamMask;
1160     Int8 i;
1161     
1162     pAfRd->sampleDecode = PAF_SOURCE_PCM;
1163     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1164     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
1165     pAfRd->sampleCount = strFrameLen;
1166     pAfRd->channelConfigurationRequest.full = 0;
1167     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
1168     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
1169     pAfRd->channelConfigurationStream.full = 0;
1170     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
1171     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
1172     
1173     // compute stream mask
1174     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
1175     // Clear PCM data
1176     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
1177     {
1178         if ((streamMask >> i) & 0x1)
1179         {
1180             memset(pAfRd->data.sample[i], 0, strFrameLen*sizeof(PAF_AudioData));
1181         }
1182         pAfRd->data.samsiz[i] = 0;
1183     }
1184     // write metadata information updated by decoder
1185     pAfRd->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
1186     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1187     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1188     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1190 #endif
1192 #if 0 // FL: unused
1193 // Init last audio frame configuration info 
1194 static Void cbInitLastAfInfo(
1195     PAF_AudioFrame *pAfRd      // last audio frame stored in CB instance
1198     pAfRd->sampleDecode = PAF_SOURCE_PCM;
1199     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1200     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
1201     pAfRd->sampleCount = DEF_DEC_OP_FRAME_LEN;
1202     pAfRd->channelConfigurationRequest.full = 0;
1203     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
1204     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
1205     pAfRd->channelConfigurationStream.full = 0;
1206     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
1207     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
1209     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
1210     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1211     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1212     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1214 #endif
1216 // Update last audio frame configuration info 
1217 static Void cbUpdateLastAfInfo(
1218     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
1219     PAF_AudioFrame *pAfUpd      // audio frame used for update
1222     // FL: full copy shouldn't be necessary
1223     //  Note currently (data.nChannels, data.nSamples)=(32,256) is fixed in ASOT stream AF.
1224     //  There parameters aren't copied from CB on CB read.
1225     //memcpy (&pCb->lastAf, pAfUpd, sizeof(PAF_AudioFrame));
1227     // These are parameters used in cbReadMuteWithLastAfInfo()
1228     pCb->lastAf.sampleDecode = pAfUpd->sampleDecode;
1229     pCb->lastAf.sampleRate = pAfUpd->sampleRate;
1230     pCb->lastAf.channelConfigurationRequest.full = pAfUpd->channelConfigurationRequest.full;
1231     pCb->lastAf.channelConfigurationStream.full = pAfUpd->channelConfigurationStream.full;
1234 // Generate mute AF on circular buffer read using the last AF configuration info 
1235 static Void cbReadMuteWithLastAfInfo(
1236     PAF_AST_DecOpCircBuf *pCb,    // decoder output circular buffer control
1237     PAF_AudioFrame *pAfRd         // audio frame into which to read
1240     PAF_ChannelMask_HD streamMask;
1241     Int8 i;
1243     pAfRd->sampleDecode = pCb->lastAf.sampleDecode;
1244     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1245     pAfRd->sampleRate  = pCb->lastAf.sampleRate;
1246     pAfRd->sampleCount = pCb->strFrameLen;
1247     pAfRd->channelConfigurationRequest.full     = pCb->lastAf.channelConfigurationRequest.full;
1248     //pAfRd->channelConfigurationRequest.part.sat = pCb->lastAf.channelConfigurationRequest.part.sat; // FL: not necessary since full in union already copied
1249     //pAfRd->channelConfigurationRequest.part.sub = pCb->lastAf.channelConfigurationRequest.part.sub;
1250     pAfRd->channelConfigurationStream.full      = pCb->lastAf.channelConfigurationStream.full;
1251     //pAfRd->channelConfigurationStream.part.sat  = pCb->lastAf.channelConfigurationStream.part.sat;
1252     //pAfRd->channelConfigurationStream.part.sub  = pCb->lastAf.channelConfigurationStream.part.sub;
1253     
1254     // compute stream mask
1255     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
1256     // Clear PCM data
1257     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
1258     {
1259         if ((streamMask >> i) & 0x1)
1260         {
1261             memset(pAfRd->data.sample[i], 0, pAfRd->sampleCount*sizeof(PAF_AudioData));
1262         }
1263         pAfRd->data.samsiz[i] = 0;
1264     }
1265     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
1266     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1267     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1268     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1271 // Check circular buffer drain state
1272 Int cbCheckDrainState(
1273     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
1274     Int8 cbIdx,                         // decoder output circular buffer index, or indicator combined drain state desired
1275     Int8 *pDrainedFlag                  // output drain state indicator (combined or for selected circular buffer)
1278     IArg key;
1279     GateMP_Handle gateHandle;
1280     PAF_AST_DecOpCircBuf *pCb;
1281     Int8 drainedFlag;
1282     Int8 i;
1283     
1284     // Get gate handle
1285     gateHandle = pCbCtl->gateHandle;
1286     // Enter gate
1287     key = GateMP_enter(gateHandle);
1289     if (cbIdx != ASP_DECOP_CHECK_DRAINSTATE_ALL)
1290     {
1291         //
1292         // Check drain state for selected circular buffer
1293         //
1294         
1295         // Get circular buffer base pointer
1296         pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
1298         // Invalidate circular buffer configuration
1299         Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1300         Cache_wait();
1302         drainedFlag = !pCb->writerActiveFlag && !pCb->drainFlag;
1303     }
1304     else
1305     {
1306         //
1307         // Check combined drain state for all circular buffers.
1308         // Combined drain state is logical AND of drain state for all circular buffers.
1309         //
1311         drainedFlag = 1; // init combined drained flag to TRUE
1312         for (i = 0; i < pCbCtl->numDecOpCb; i++)
1313         {
1314             // Get circular buffer base pointer
1315             pCb = &((*pCbCtl->pXDecOpCb)[i]);
1317             // Invalidate circular buffer configuration
1318             Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1319             Cache_wait();
1320             
1321             // Update combined drain state
1322             drainedFlag = drainedFlag && (!pCb->writerActiveFlag && !pCb->drainFlag);
1323         }
1324     }
1325     
1326     *pDrainedFlag = drainedFlag;
1327     
1328     // Leave the gate
1329     GateMP_leave(gateHandle, key);
1331     return ASP_DECOP_CB_SOK;