25224c1460cde14954633d307c9fb61ba9589335
[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
525     Int16 strFrameLen                   // stream frame length (PCM samples)
528     IArg key;
529     GateMP_Handle gateHandle;
530     PAF_AST_DecOpCircBuf *pCb;
531     
532     // Get gate handle
533     gateHandle = pCbCtl->gateHandle;
534     // Enter gate
535     key = GateMP_enter(gateHandle);
537     // Get circular buffer base pointer
538     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
539     
540     // Invalidate circular buffer configuration
541     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
542     Cache_wait();
544     // Set output frame length
545     pCb->strFrameLen = strFrameLen;
547     // Write back circular buffer configuration
548     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
549     Cache_wait();
551     // Leave the gate
552     GateMP_leave(gateHandle, key);
553     
554     //return ret;
555     return ASP_DECOP_CB_SOK;
558 // Start reads from circular buffer
559 Int cbReadStart(
560     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
561     Int8 cbIdx                          // decoder output circular buffer index
564     IArg key;
565     GateMP_Handle gateHandle;
566     PAF_AST_DecOpCircBuf *pCb;
568     // Get gate handle
569     gateHandle = pCbCtl->gateHandle;
570     // Enter gate
571     key = GateMP_enter(gateHandle);
573     // Get circular buffer base pointer
574     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
575     
576     // Invalidate circular buffer configuration
577     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
578     Cache_wait();
579     
580     //Log_info1("cbReadStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
582     // update flags
583     pCb->readerActiveFlag = 1;
584     
585     // Write back circular buffer configuration
586     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
587     Cache_wait();
589     // Leave the gate
590     GateMP_leave(gateHandle, key);
592     return ASP_DECOP_CB_SOK;
595 // Stop reads from circular buffer
596 Int cbReadStop(
597     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
598     Int8 cbIdx                          // decoder output circular buffer index
601     IArg key;
602     GateMP_Handle gateHandle;
603     PAF_AST_DecOpCircBuf *pCb;
605     // Get gate handle
606     gateHandle = pCbCtl->gateHandle;
607     // Enter gate
608     key = GateMP_enter(gateHandle);
610     // Get circular buffer base pointer
611     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
613     // Invalidate circular buffer configuration
614     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
615     Cache_wait();
616     
617     //Log_info1("cbReadStop:afCb=0x%04x", (IArg)pCb->afCb); // debug
619     // update flags
620     pCb->readerActiveFlag = 0;
621     
622     // Write back circular buffer configuration
623     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
624     Cache_wait();
626     // Leave the gate
627     GateMP_leave(gateHandle, key);
629     return ASP_DECOP_CB_SOK;
632 // debug
633 //Int16 gDeltaSampsBuf[20];
634 //Int8 gDeltaSampsBufIdx=0;
636 // Read audio frame from circular buffer
637 Int cbReadAf(
638     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
639     Int8 cbIdx,                         // decoder output circular buffer index
640     PAF_AudioFrame *pAfRd               // audio frame into which to read
643     IArg key;
644     GateMP_Handle gateHandle;           // CB gate handle to arbitrate CB r/w access
645     PAF_AST_DecOpCircBuf *pCb;          // pointer to CB
646     PAF_AudioFrame *pAfCb;              // pointer to current CB AF
647     PAF_ChannelMask_HD streamMask;      // CB AF stream mask
648     Int16 numSampsRd;                   // number of samples to read from current CB AF
649     Int16 totNumSampsRd;                // total number of samples read from CB
650     Int16 pcmWrtIdx;                    // read audio frame PCM write index
651     Int8 prvMdWrtIdx;                   // read audio frame metadata write index
652     Int8 i;
653     Int16 j;
654     
655     // Get gate handle
656     gateHandle = pCbCtl->gateHandle;
657     // Enter gate
658     key = GateMP_enter(gateHandle);
660     // Get circular buffer base pointer
661     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
663     // Invalidate circular buffer configuration.
664     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
665     Cache_wait();
667     //Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
669     //
670     // Check (writerActiveFlag,drainFlag)=(1,1)
671     //
672     if ((pCb->writerActiveFlag == 1) && (pCb->drainFlag == 1))
673     {
674         //
675         // This shouldn't occur:
676         // writer is active AND draining circular buffer
677         //
678         
679         //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // debug
680         SW_BREAKPOINT; // debug
681         
682         // Leave the gate
683         GateMP_leave(gateHandle, key);
684         
685         return ASP_DECOP_CB_READ_INVSTATE;
686     }
688     //
689     // Check (writerActiveFlag,drainFlag)=(0,0)
690     //
691     //if (((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) || (pCb->afLagIdx < pCb->afInitialLag))
692     if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0))
693     {
694         //
695         // Writer inactive, not draining circular buffer.
696         // Skip UNDerflow check, mute output.
697         //
698         
699         pCb->readAfWriterInactiveCnt++;
700         
701         // Mute output if write inactive and not draining CB
702         //cbReadAfMute(pAfRd, pCb->strFrameLen);
703         cbReadMuteWithLastAfInfo(pCb, pAfRd);
704         
705         // Write back circular buffer configuration.
706         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
707         Cache_wait();
709         // Leave the gate
710         GateMP_leave(gateHandle, key);
712         return ASP_DECOP_CB_SOK;
713     }
715     if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 1))
716     {
717         //
718         // Writer inactive, but remaining frames in circular buffer.
719         // Update drain flag.
720         //
721         
722         if (pCb->numAfCb <= 0)
723         {
724             pCb->drainFlag = 0;
726             // Mute output if CB drained
727             cbReadMuteWithLastAfInfo(pCb, pAfRd);
729             // Write back circular buffer configuration.
730             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
731             Cache_wait();    
733             // Leave the gate
734             GateMP_leave(gateHandle, key);
736             return ASP_DECOP_CB_SOK;
737         }
738     }
739     
740     //
741     // Hold off read of PCM samples from CB until Nominal Delay satisfied
742     //
743     //if ((pCb->primedFlag == 0) || ((pCb->primedFlag==1) && (pCb->deltaSamps > 0))
744     if ((pCb->primedFlag == 0) || (pCb->deltaSamps > 0))
745     {
746         pCb->readAfNdCnt++;
747         
748         if (pCb->primedFlag == 1)
749         {
750             pCb->deltaSamps = pCb->deltaSamps - pCb->strFrameLen;
751             
752             // debug
753             //gDeltaSampsBuf[gDeltaSampsBufIdx] = pCb->deltaSamps;
754             //if (gDeltaSampsBufIdx < 20)
755             //    gDeltaSampsBufIdx++;
756         }
757         
758         cbReadMuteWithLastAfInfo(pCb, pAfRd);
759         
760         // Write back circular buffer configuration.
761         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
762         Cache_wait();    
763         
764         // Leave the gate
765         GateMP_leave(gateHandle, key);
767         return ASP_DECOP_CB_SOK;
768     }
769     
770     //
771     // (writerActiveFlag,drainFlag)= (0,0) and (1,1) states checked above
772     // (writerActiveFlag,drainFlag)=(1,0) and (0,1) states are left
773     // Checking (writerActiveFlag,drainFlag)=(1,0) state here
774     //
775     if (pCb->writerActiveFlag == 1)
776     {
777         // check underflow
778         if (pCb->numAfCb <= 0)
779         {
780             // 
781             // Increment underflow count
782             //
783             pCb->errAfUndCnt++;
785             // Mute output on underflow
786             //cbReadAfMute(pAfRd, pCb->strFrameLen);
787             cbReadMuteWithLastAfInfo(pCb, pAfRd);
788             //SW_BREAKPOINT; // debug
789             
790 #if 0 // (***) FL: shows timing of CB underflow
791             // debug
792             {
793                 static Uint8 toggleState = 0;
794                 if (toggleState == 0)
795                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
796                 else
797                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
798                 toggleState = ~(toggleState);
799             }
800 #endif
802             #ifdef CB_RW_OP_CAP_PP // debug
803             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
804             {
805                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
806                 {
807                     // log sample count
808                     pCb->cb_samples_op[pCb->cb_opCnt] = 0;  // due to underflow
809                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
810                     // log idxs
811                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
812                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
813                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
814                     pCb->cb_opCnt++;
815                 }
816             }
817             #endif
819             // Write back circular buffer configuration.
820             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
821             Cache_wait();    
822             
823             // Leave the gate
824             GateMP_leave(gateHandle, key);
825             
826             return ASP_DECOP_CB_AF_READ_UNDERFLOW;
827         }
828     }
829     
830     //
831     // Checking (writerActiveFlag,drainFlag)=(1,0) state above and here
832     // Checking (writerActiveFlag,drainFlag)=(0,1) state here
833     //
834     if ((pCb->writerActiveFlag == 1) || (pCb->drainFlag == 1))
835     {
836         //
837         // Writer active or draining remaining frames in circular buffer.
838         // Read next audio frame.
839         //
841         //
842         // Read Audio Frame from CB Audio Frames.
843         // Read PCM & associated metadata from CB AFs until Read AF is filled.
844         //
845         // If multiple CB AFs are read in creating Read AF, CB AF parameters 
846         // can *change* between read CB AFs. Since only one Read AF is produced 
847         // per CB read, this is a "data collision", i.e. can't have more than 
848         // one set of CB AF parameters in Read AF.
849         //
850         // Currently applying parameters from earliest read CB AF to Read Af.
851         // This can result in delay (or skip) w.r.t. application of additional 
852         // CB AF parameters not used for creating Read AF. This is reasonable 
853         // given there's no way to "interpolate" AF parameters, e.g. how to 
854         // interpolation change in in bit-stream metadata type, or CC stream?
855         //
856         
857         // Get pointer to current CB Audio Frame
858         pAfCb = &pCb->afCb[pCb->afRdIdx];
860         // Cache invalidate CB AF
861         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
862         Cache_wait();
863         
864         // Read CB AF information updated by decoder
865         pAfRd->sampleDecode = pAfCb->sampleDecode;
866         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
867         pAfRd->sampleRate = pAfCb->sampleRate;
868         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
869         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
870         // Read CB AF bit-stream metadata information updated by decoder
871         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if private metadata is attached. */
872         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
873         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
874         
875         // Compute stream mask for current CB AF.
876         // Mask indicates which channels are present in AF.
877         // Mask needed for cache invalidate and read of PCM samples in AF.
878         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
880         // Cache invalidate CB AF samsiz (volume scaling exponent) array
881         Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
882         Cache_wait();
883         
884         // Read CB AF samsiz array
885         for (i = 0; i < pCb->maxAFChanNum; i++)
886         {
887             if ((streamMask >> i) & 0x1)
888             {
889                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
890             }
891         }
893         // FL: brute force clear of Read AF PCM data
894         // Reset Read AF PCM data
895         //for (i = 0; i < pCb->maxAFChanNum; i++)
896         //{
897         //    if ((streamMask >> i) & 0x1)
898         //    {
899         //        memset(pAfRd->data.sample[i], 0, pCb->strFrameLen);
900         //    }
901         //}
902         
903         // FL: This brute force approach shouldn't be necessary if
904         //     decoders properly set, and downstream components
905         //     properly use, number of private metadata in frame
906         // Reset Read AF metadata
907         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
908         {
909             pAfRd->pafPrivateMetadata[i].offset = 0;
910             pAfRd->pafPrivateMetadata[i].size   = 0;
911         }
912         
913         totNumSampsRd = 0;  // init total number of samples read from CB
914         pcmWrtIdx = 0;      // init Read AF PCM write index
915         prvMdWrtIdx = 0;    // init Read AF metadata write index
916         while ((totNumSampsRd < pCb->strFrameLen) && (pCb->numAfCb > 0))
917         {
918             // Compute how many PCM samples can be read from CB AF
919             //  Number of samples left in current CB AF: pAfCb->sampleCount - pCb->pcmRdIdx
920             //  Number of samples left to write to Read AF: pCb->strFrameLen - totNumSampsRd
921             numSampsRd = (pAfCb->sampleCount - pCb->pcmRdIdx) < (pCb->strFrameLen - totNumSampsRd) ? 
922                 (pAfCb->sampleCount - pCb->pcmRdIdx) : (pCb->strFrameLen - totNumSampsRd);
924             // Cache invalidate CB AF PCM sample channel pointers
925             Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
926             Cache_wait();
928             // Cache invalidate CB AF PCM samples
929             for (i = 0; i < pCb->maxAFChanNum; i++)
930             {
931                 if ((streamMask >> i) & 0x1)
932                 {
933                     Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], numSampsRd*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
934                 }
935             }
936             Cache_wait();
938             // Read PCM samples from CB AF
939             for (i = 0; i < pCb->maxAFChanNum; i++)
940             {
941                 if ((streamMask >> i) & 0x1)
942                 {
943                     for (j = 0; j < numSampsRd; j++)
944                     {
945                         pAfRd->data.sample[i][pcmWrtIdx+j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
946                     }
947                 }
948             }
950             // Cache invalidate CB AF unused metadata
951             for (i = pCb->prvMdRdIdx; i < pAfCb->numPrivateMetadata; i++)
952             {
953                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size
954             }
955             Cache_wait();
957             // Read CB AF metadata
958             while (((pCb->prvMdRdIdx < pAfCb->numPrivateMetadata) && 
959                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset >= pCb->pcmRdIdx) &&
960                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset < (pCb->pcmRdIdx + numSampsRd)) &&
961                 (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size)) &&
962                 (prvMdWrtIdx < PAF_MAX_NUM_PRIVATE_MD))
963             {
964                 // Write Read AF metadata offset.
965                 //  Compute relative offset of PCM samples being read from CB AF.
966                 //  Compute absolute offset of PCM samples written to Read AF by 
967                 //  adding relative offset to Read AF PCM write index.
968                 pAfRd->pafPrivateMetadata[prvMdWrtIdx].offset = 
969                     (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset - pCb->pcmRdIdx) +   // offset relative to samples being read from CB AF
970                     pcmWrtIdx;                                                              // absolute offset into samples being written to read AF
971                 // Write Read AF metadata size    
972                 pAfRd->pafPrivateMetadata[prvMdWrtIdx].size = pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size;
973                 // Write Read AF metadata payload
974                 memcpy(pAfRd->pafPrivateMetadata[prvMdWrtIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size);
975                 
976                 pCb->prvMdRdIdx++;  // update CB metadata read index
977                 prvMdWrtIdx++;      // update CB metadata write index
978             }
979             
980             // Update CB control
981             pCb->pcmRdIdx += numSampsRd; // update PCM read index
982             if (pCb->pcmRdIdx >= pAfCb->sampleCount) 
983             {
984                 // Finished reading PCM samples from current CB AF.
985                 // Move to next AF in CB.
986                 
987                 // Update audio frame read index.
988                 // Wrap index if required.
989                 pCb->afRdIdx++;
990                 if (pCb->afRdIdx >= pCb->maxNumAfCb)
991                 {
992                     pCb->afRdIdx = 0;
993                 }
994                 
995                 // Reset PCM read index
996                 pCb->pcmRdIdx = 0;
997                 // Reset metadata read index
998                 pCb->prvMdRdIdx = 0;
999                 
1000                 // Update number of audio frames in circular buffer
1001                 pCb->numAfCb--;
1002             }
1003             
1004             // Update PCM write index
1005             pcmWrtIdx += numSampsRd;
1007             // Update total number of samples read
1008             totNumSampsRd += numSampsRd;
1009             
1010             if (totNumSampsRd < pCb->strFrameLen)
1011             {
1012                 //
1013                 // Need to read another AF from CB to obtain all PCM/metadata for Read AF
1014                 //
1015                 
1016                 // Get pointer to current CB Audio Frame
1017                 pAfCb = &pCb->afCb[pCb->afRdIdx];
1018                 
1019                 // Cache invalidate CB AF
1020                 Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
1021                 Cache_wait();
1022             }
1023         }
1024        
1025         pAfRd->sampleCount = totNumSampsRd;         // write Read AF sample count
1026         pAfRd->numPrivateMetadata = prvMdWrtIdx;    // write Read AF number of metadata
1027         
1028         pCb->numPcmSampsPerCh -= totNumSampsRd;     // update PCM samples per channel
1029        
1030         if (totNumSampsRd < pCb->strFrameLen)
1031         {
1032             // Clear remaining Read AF PCM samples
1033             for (i = 0; i < pCb->maxAFChanNum; i++)
1034             {
1035                 if ((streamMask >> i) & 0x1)
1036                 {
1037                     memset(&pAfRd->data.sample[i][pcmWrtIdx], 0, (pCb->strFrameLen-totNumSampsRd));
1038                 }
1039             }
1040             
1041             if (pCb->writerActiveFlag == 1)
1042             {
1043                 //
1044                 // UNDerflow, 
1045                 // read stopped due to insufficient PCM samples in CB to fill Read AF
1046                 //
1047             
1048                 // 
1049                 // Increment underflow count
1050                 //
1051                 pCb->errPcmUndCnt++;
1053                 // Mute output on underflow
1054                 cbReadMuteWithLastAfInfo(pCb, pAfRd);
1055                 
1056 #if 0 // (***) FL: shows timing of CB underflow
1057                 // debug
1058                 {
1059                     static Uint8 toggleState = 0;
1060                     if (toggleState == 0)
1061                         GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
1062                     else
1063                         GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
1064                     toggleState = ~(toggleState);
1065                 }
1066 #endif
1068                 #ifdef CB_RW_OP_CAP_PP // debug
1069                 if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
1070                 {
1071                     if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
1072                     {
1073                         // log sample count
1074                         pCb->cb_samples_op[pCb->cb_opCnt] = 0;  // due to underflow
1075                         pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
1076                         // log idxs
1077                         pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
1078                         pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
1079                         pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
1080                         pCb->cb_opCnt++;
1081                     }
1082                 }
1083                 #endif
1085                 // Write back circular buffer configuration.
1086                 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1087                 Cache_wait();    
1088                 
1089                 // Leave the gate
1090                 GateMP_leave(gateHandle, key);
1091                 
1092                 return ASP_DECOP_CB_PCM_READ_UNDERFLOW;
1093             }
1094         }
1095         
1096         // Read AF complete, update Last CB AF Info
1097         cbUpdateLastAfInfo(pCb, pAfRd);
1099 #if 0 // (***) FL: shows timing of successful CB read
1100         {
1101             static Uint8 toggleState = 0;
1102             if (toggleState == 0)
1103                 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
1104             else
1105                 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
1106             toggleState = ~(toggleState);
1107         }
1108 #endif
1110 #ifdef CB_RW_OP_CAP_PP // debug
1111         if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
1112         {
1113             if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
1114             {
1115                 // log sample count
1116                 pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount;
1117                 pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
1118                 // log idxs
1119                 pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
1120                 pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
1121                 pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
1122                 pCb->cb_opCnt++;
1123             }
1124         }
1125 #endif
1126     }
1127     
1128 #if 0
1129     if (pCb->drainFlag == 1)
1130     {
1131         //
1132         // Writer inactive, but remaining frames in circular buffer.
1133         // Update drain flag.
1134         //
1135         if (pCb->numAfCb <= 0)
1136         {
1137             pCb->drainFlag = 0;
1138         }
1139     }
1140 #endif
1141     
1142     // Write back circular buffer configuration.
1143     // NOTE: Probably only a subset of this information needs to be updated.
1144     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1145     Cache_wait();    
1146         
1147     // Leave the gate
1148     GateMP_leave(gateHandle, key);
1150     return ASP_DECOP_CB_SOK;
1153 #if 0
1154 // Generate mute AF on circular buffer read
1155 static Void cbReadAfMute(
1156     PAF_AudioFrame *pAfRd,      // audio frame into which to read
1157     Int16 strFrameLen           // stream frame length (output transaction size)
1160     PAF_ChannelMask_HD streamMask;
1161     Int8 i;
1162     
1163     pAfRd->sampleDecode = PAF_SOURCE_PCM;
1164     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1165     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
1166     pAfRd->sampleCount = strFrameLen;
1167     pAfRd->channelConfigurationRequest.full = 0;
1168     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
1169     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
1170     pAfRd->channelConfigurationStream.full = 0;
1171     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
1172     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
1173     
1174     // compute stream mask
1175     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
1176     // Clear PCM data
1177     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
1178     {
1179         if ((streamMask >> i) & 0x1)
1180         {
1181             memset(pAfRd->data.sample[i], 0, strFrameLen*sizeof(PAF_AudioData));
1182         }
1183         pAfRd->data.samsiz[i] = 0;
1184     }
1185     // write metadata information updated by decoder
1186     pAfRd->bsMetadata_type     = PAF_bsMetadata_channelData;    /* non zero if metadata is attached. */
1187     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1188     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1189     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1191 #endif
1193 #if 0 // FL: unused
1194 // Init last audio frame configuration info 
1195 static Void cbInitLastAfInfo(
1196     PAF_AudioFrame *pAfRd      // last audio frame stored in CB instance
1199     pAfRd->sampleDecode = PAF_SOURCE_PCM;
1200     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1201     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
1202     pAfRd->sampleCount = DEF_DEC_OP_FRAME_LEN;
1203     pAfRd->channelConfigurationRequest.full = 0;
1204     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
1205     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
1206     pAfRd->channelConfigurationStream.full = 0;
1207     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
1208     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
1210     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
1211     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1212     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1213     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1215 #endif
1217 // Update last audio frame configuration info 
1218 static Void cbUpdateLastAfInfo(
1219     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
1220     PAF_AudioFrame *pAfUpd      // audio frame used for update
1223     // FL: full copy shouldn't be necessary
1224     //  Note currently (data.nChannels, data.nSamples)=(32,256) is fixed in ASOT stream AF.
1225     //  There parameters aren't copied from CB on CB read.
1226     //memcpy (&pCb->lastAf, pAfUpd, sizeof(PAF_AudioFrame));
1228     // These are parameters used in cbReadMuteWithLastAfInfo()
1229     pCb->lastAf.sampleDecode = pAfUpd->sampleDecode;
1230     pCb->lastAf.sampleRate = pAfUpd->sampleRate;
1231     pCb->lastAf.channelConfigurationRequest.full = pAfUpd->channelConfigurationRequest.full;
1232     pCb->lastAf.channelConfigurationStream.full = pAfUpd->channelConfigurationStream.full;
1235 // Generate mute AF on circular buffer read using the last AF configuration info 
1236 static Void cbReadMuteWithLastAfInfo(
1237     PAF_AST_DecOpCircBuf *pCb,    // decoder output circular buffer control
1238     PAF_AudioFrame *pAfRd         // audio frame into which to read
1241     PAF_ChannelMask_HD streamMask;
1242     Int8 i;
1244     pAfRd->sampleDecode = pCb->lastAf.sampleDecode;
1245     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
1246     pAfRd->sampleRate  = pCb->lastAf.sampleRate;
1247     pAfRd->sampleCount = pCb->strFrameLen;
1248     pAfRd->channelConfigurationRequest.full     = pCb->lastAf.channelConfigurationRequest.full;
1249     //pAfRd->channelConfigurationRequest.part.sat = pCb->lastAf.channelConfigurationRequest.part.sat; // FL: not necessary since full in union already copied
1250     //pAfRd->channelConfigurationRequest.part.sub = pCb->lastAf.channelConfigurationRequest.part.sub;
1251     pAfRd->channelConfigurationStream.full      = pCb->lastAf.channelConfigurationStream.full;
1252     //pAfRd->channelConfigurationStream.part.sat  = pCb->lastAf.channelConfigurationStream.part.sat;
1253     //pAfRd->channelConfigurationStream.part.sub  = pCb->lastAf.channelConfigurationStream.part.sub;
1254     
1255     // compute stream mask
1256     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
1257     // Clear PCM data
1258     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
1259     {
1260         if ((streamMask >> i) & 0x1)
1261         {
1262             memset(pAfRd->data.sample[i], 0, pAfRd->sampleCount*sizeof(PAF_AudioData));
1263         }
1264         pAfRd->data.samsiz[i] = 0;
1265     }
1266     pAfRd->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
1267     pAfRd->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
1268     pAfRd->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
1269     pAfRd->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
1272 // Check circular buffer drain state
1273 Int cbCheckDrainState(
1274     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
1275     Int8 cbIdx,                         // decoder output circular buffer index, or indicator combined drain state desired
1276     Int8 *pDrainedFlag                  // output drain state indicator (combined or for selected circular buffer)
1279     IArg key;
1280     GateMP_Handle gateHandle;
1281     PAF_AST_DecOpCircBuf *pCb;
1282     Int8 drainedFlag;
1283     Int8 i;
1284     
1285     // Get gate handle
1286     gateHandle = pCbCtl->gateHandle;
1287     // Enter gate
1288     key = GateMP_enter(gateHandle);
1290     if (cbIdx != ASP_DECOP_CHECK_DRAINSTATE_ALL)
1291     {
1292         //
1293         // Check drain state for selected circular buffer
1294         //
1295         
1296         // Get circular buffer base pointer
1297         pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
1299         // Invalidate circular buffer configuration
1300         Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1301         Cache_wait();
1303         drainedFlag = !pCb->writerActiveFlag && !pCb->drainFlag;
1304     }
1305     else
1306     {
1307         //
1308         // Check combined drain state for all circular buffers.
1309         // Combined drain state is logical AND of drain state for all circular buffers.
1310         //
1312         drainedFlag = 1; // init combined drained flag to TRUE
1313         for (i = 0; i < pCbCtl->numDecOpCb; i++)
1314         {
1315             // Get circular buffer base pointer
1316             pCb = &((*pCbCtl->pXDecOpCb)[i]);
1318             // Invalidate circular buffer configuration
1319             Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
1320             Cache_wait();
1321             
1322             // Update combined drain state
1323             drainedFlag = drainedFlag && (!pCb->writerActiveFlag && !pCb->drainFlag);
1324         }
1325     }
1326     
1327     *pDrainedFlag = drainedFlag;
1328     
1329     // Leave the gate
1330     GateMP_leave(gateHandle, key);
1332     return ASP_DECOP_CB_SOK;