]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_arm/framework/aspDecOpCircBuf_slave.c
7a80156fa85a29a7dac4066619ee2ccfbe28d8c5
[processor-sdk/performance-audio-sr.git] / pasdk / test_arm / framework / aspDecOpCircBuf_slave.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>
42 #include "common.h"
43 #include "paftyp.h"
44 //#include "pafdec.h"
45 //#include "pafsp.h"
46 #include "aspDecOpCircBuf_slave.h"
48 #include "evmc66x_gpio_dbg.h" // Debug
50 // Init last audio frame configuration info 
51 static Void cbInitLastAfInfo(
52     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
53     PAF_AudioFrame *pAfInit     // audio frame used for init
54 );
57 #if 0 // FL: moved to common
58 // Initialize circular buffer control
59 Int cbCtlInit(
60     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
61     PAF_AST_DecOpCircBuf **pXDecOpCb    // address of decoder output circular buffer base pointer
62 )
63 {
64     GateMP_Handle gateHandle;
65     Int status;
66     
67     do {
68         status = GateMP_open(ASP_DECODE_CB_GATE_NAME, &gateHandle);
69     } while (status == GateMP_E_NOTFOUND);
70     if (status == GateMP_S_SUCCESS)
71     {
72         pCbCtl->gateHandle = gateHandle;
73     }
74     else
75     {
76         pCbCtl->gateHandle = NULL;
77         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
78     }
79     
80     pCbCtl->numCb = numCb;          // init number of circular buffers
81     pCbCtl->pXDecOpCb = pXDecOpCb;  // init base address of circular buffers
82     
83     return ASP_DECOP_CB_SOK;
84 }
85 #endif
87 // debug
88 //Int8 gCbInitDecWriteCnt=0;
89 //Int8 gCbInitDecWriteThdCnt=0;
91 /// Initialize circular buffer for Decoder writes
92 Int cbInitDecWrite(
93     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
94     Int8 cbIdx,                         // decoder output circular buffer index
95     Int8 sourceSelect,                  // source select (PCM, DDP, etc.)
96     Int16 decOpFrameLen,                // decoder output frame length (PCM samples)
97     Int8 resetRwFlags,                  // whether to reset reader, writer, and drain flags
98     PAF_AudioFrame *pDecInitAf          // pointer to Dec output audio frame used for CB initialization
99 )
101     IArg key;
102     GateMP_Handle gateHandle;
103     PAF_AST_DecOpCircBuf *pCb;
104     PAF_AudioFrame *pAfCb;
105     PAF_AudioData *pPcmBuf;
106     UInt8 *pMetaBuf;
107     Int8 n;
108     Int8 i;
110     //gCbInitDecWriteCnt++; // debug
111     
112     // Get gate handle
113     gateHandle = pCbCtl->gateHandle;
114     // Enter gate
115     key = GateMP_enter(gateHandle);
117     // Get circular buffer base pointer
118     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
119     
120     // Invalidate circular buffer configuration
121     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
122     Cache_wait();
124     //Log_info1("cbInitDecWrite:afCb=0x%04x", (IArg)pCb->afCb); // debug
126     // Set source select
127     pCb->sourceSel = sourceSelect;
129     // Set input frame length
130     pCb->decOpFrameLen = decOpFrameLen;
131     
132     //pCb->afInitialLag = 0;  // default No lag
133     //pCb->afLagIdx = 0;
134     // Initialize CB primed flag
135     pCb->primedFlag = 0;
136     // Initialize delta samples
137     pCb->deltaSamps = 0;
138     
139     // Initialize circular buffer:
140     //  - maximum number of AFs
141     //  - target nominal delay
142     //  - AF write, read indices
143     //  - maximum AF channel and sample counts
144     if (sourceSelect == PAF_SOURCE_PCM)
145     {
146         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM;
147         
148         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
149         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM;
150         
151         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM;
152         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM;
153         pCb->pcmRdIdx = 0;
154         pCb->prvMdRdIdx = 0;
155         
156         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH;
157         pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;        
158     }
159     else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3))
160     {
161         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP;
162         
163         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP;
164         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_DDP;
165         
166         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP;
167         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP;
168         pCb->pcmRdIdx = 0;
169         pCb->prvMdRdIdx = 0;
170         
171         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP;
172         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP;
173     }
174     else if (sourceSelect == PAF_SOURCE_THD)
175     {
176         //gCbInitSourceSelThdCnt++; //debug
177         
178         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;
179         
180         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD;
181         // FL: (***) set nominal delay per sampling rate -- need to review these settings
182         switch (pDecInitAf->sampleRate)
183         {
184             case PAF_SAMPLERATE_44100HZ:
185             case PAF_SAMPLERATE_48000HZ:
186                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
187                 break;
188             case PAF_SAMPLERATE_88200HZ:
189             case PAF_SAMPLERATE_96000HZ:
190                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_96kTHD;
191                 break;
192             case PAF_SAMPLERATE_176400HZ:
193             case PAF_SAMPLERATE_192000HZ:
194                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_192kTHD;
195                 break;
196             default:
197                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
198                 break;
199         }
200         
201         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD;
202         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD;
203         pCb->pcmRdIdx = 0;
204         pCb->prvMdRdIdx = 0;
205         
206         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT;
207         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT;        
208     }
209     else
210     {
211         //
212         // Currently unsupported source select
213         //
214         
215         SW_BREAKPOINT; // debug
216         
217         // Leave the gate
218         GateMP_leave(gateHandle, key);
220         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
221     }
222     
223     // Initialize audio frames
224     for (n = 0; n < pCb->maxNumAfCb; n++)
225     {
226         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
227         
228         // Dec init AF sample count not correct for CB AFs.
229         // Dec Op frame length is computed in framework based on selected source.
230         pAfCb->sampleCount = decOpFrameLen;
232         // initialize CB AF using Dec init AF
233         pAfCb->sampleDecode = pDecInitAf->sampleDecode;
234         PAF_PROCESS_COPY(pAfCb->sampleProcess, pDecInitAf->sampleProcess);
235         pAfCb->sampleRate = pDecInitAf->sampleRate;
236         pAfCb->channelConfigurationRequest.full = pDecInitAf->channelConfigurationRequest.full;
237         pAfCb->channelConfigurationStream.full = pDecInitAf->channelConfigurationStream.full;
238         
239         // initialize metadata information updated by decoder
240         pAfCb->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
241         pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
242         pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
243         pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
244     }
245     
246     // Initialize circular buffer current number of frames
247     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
248     
249     // Initialize audio frame PCM buffers
250     pPcmBuf = pCb->pcmBuf;
251     pMetaBuf = pCb->metaBuf;
252     for (n=0; n<pCb->maxNumAfCb; n++)
253     {
254         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
255         
256         pAfCb->data.nChannels = pCb->maxAFChanNum;
257         pAfCb->data.nSamples = decOpFrameLen;
258         for (i=0; i<pCb->maxAFChanNum; i++)
259         {
260             pAfCb->data.sample[i] = pPcmBuf;
261             memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount);
262             pPcmBuf += pCb->maxAFSampCount;
263             
264             pAfCb->data.samsiz[i] = 0;
265         }
266         
267         // Initialize metadata buffers
268         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
269         {
270             pAfCb->pafPrivateMetadata[i].offset = 0; 
271             pAfCb->pafPrivateMetadata[i].size   = 0; 
272             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
273             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
274         }
275     }
276     
277     // Initialize last audio frame configuration info
278     cbInitLastAfInfo(pCb, pDecInitAf);
279     
280     // Reset read/write flags
281     if (resetRwFlags != 0)
282     {
283         pCb->writerActiveFlag = 0;
284         pCb->readerActiveFlag = 0;
285         pCb->drainFlag = 0;
286     }
287     
288     // Reset stats
289     pCb->readAfWriterInactiveCnt = 0;
290     pCb->readAfNdCnt = 0;
291     pCb->wrtAfReaderInactiveCnt = 0;
292     pCb->wrtAfZeroSampsCnt = 0;
293     pCb->errUndCnt = 0;
294     pCb->errOvrCnt = 0;
295     
296     // Write back circular buffer configuration
297     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
298     // Write back AF circular buffer
299     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
300     // Write back PCM data
301     for (n=0; n<pCb->maxNumAfCb; n++)
302     {
303         pAfCb = &pCb->afCb[n];
304         Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
305         Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
306         for (i=0; i<pCb->maxAFChanNum; i++)
307         {
308             Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
309         }
310     }
311     Cache_wait();
313     // Leave the gate
314     GateMP_leave(gateHandle, key);
315     
316     return ASP_DECOP_CB_SOK;
319 //Int8 gCbWriteStartCnt=0; // debug
321 // Start writes to circular buffer
322 Int cbWriteStart(
323     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
324     Int8 cbIdx                          // decoder output circular buffer index
327     IArg key;
328     GateMP_Handle gateHandle;
329     PAF_AST_DecOpCircBuf *pCb;
330     PAF_AudioFrame *pAfCb;
331     Int8 n;
332     //Int8 i;
334     //gCbWriteStartCnt++; // debug
335     
336     // Get gate handle
337     gateHandle = pCbCtl->gateHandle;
338     // Enter gate
339     key = GateMP_enter(gateHandle);
341     // Get circular buffer base pointer
342     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
344     // Invalidate circular buffer configuration.
345     // NOTE: Probably only a subset of this information needs to be updated.
346     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
347     Cache_wait();
348     
349     //Log_info1("cbWriteStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
350     
351     // Invalidate AF circular buffer
352     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
353     for (n=0; n<pCb->maxNumAfCb; n++)
354     {
355         pAfCb = &pCb->afCb[n];
356         Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
357     }
358     Cache_wait();
359             
360     // update flags
361     pCb->writerActiveFlag = 1;
362     pCb->drainFlag = 0;
363     //pCb->afLagIdx = 0;
364     
365     // Write back circular buffer configuration
366     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
367     Cache_wait();
369     // Leave the gate
370     GateMP_leave(gateHandle, key);
372     return ASP_DECOP_CB_SOK;
373 };
375 // Stop writes to circular buffer
376 Int cbWriteStop(
377     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
378     Int8 cbIdx                          // decoder output circular buffer index
381     IArg key;
382     GateMP_Handle gateHandle;
383     PAF_AST_DecOpCircBuf *pCb;
385     // Get gate handle
386     gateHandle = pCbCtl->gateHandle;
387     // Enter gate
388     key = GateMP_enter(gateHandle);
390     // Get circular buffer base pointer
391     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
393     // Invalidate circular buffer configuration
394     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
395     Cache_wait();
397     //Log_info1("cbWriteStop:afCb=0x%04x", (IArg)pCb->afCb);  // debug
398     
399     // update flags
400     pCb->writerActiveFlag = 0;
401     pCb->drainFlag = 1;
403     // Write back circular buffer configuration
404     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
405     Cache_wait();
406     
407     // Leave the gate
408     GateMP_leave(gateHandle, key);
410     return ASP_DECOP_CB_SOK;
413 // debug
414 //Int16 gSampleCountBuf[10];
415 //Int16 gCalcDeltaSampsBuf[10];
416 //Int8 gPrimedFlagCnt=0;
418 // (***) FL: revisit
419 // Write audio frame to circular buffer
420 Int cbWriteAf(
421     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
422     Int8 cbIdx,                         // decoder output circular buffer index
423     PAF_AudioFrame *pAfWrt              // audio frame from which to write
426     IArg key;
427     GateMP_Handle gateHandle;
428     PAF_AST_DecOpCircBuf *pCb;
429     PAF_AudioFrame *pAfCb;
430     PAF_ChannelMask_HD streamMask;
431     Int8 i;
432     Int16 j;
433     PAF_AudioData *pPcmBuf;UInt8 *pMetaBuf; int nextWrtIdx;PAF_AudioFrame *pAfCbNextAf; 
435     // Get gate handle
436     gateHandle = pCbCtl->gateHandle;
437     // Enter gate
438     key = GateMP_enter(gateHandle);
440     //Log_info2("cbWriteAf:gate enter, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
442     // Get circular buffer base pointer
443     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
444     //Log_info1("cbWriteAf:pCb=0x%04x", (IArg)pCb); // debug
446     // Invalidate circular buffer configuration.
447     // NOTE: Probably only a subset of this information needs to be updated.
448     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
449     Cache_wait();
451     //Log_info1("cbWriteAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
452     //Log_info2("cbWriteAf:pCb->readerActiveFlag=%d, pCb->writerActiveFlag=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->writerActiveFlag); // debug
454     //if (pCb->readerActiveFlag == 1)
455     //{
456     //    //
457     //    // Normal case, reader active.
458     //    //
459         
460         if (pAfWrt->sampleCount != 0)
461         {
462             //Log_info2("cbWriteAf:pCb->numAfCb=%d, pCb->maxNumAfCb=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->maxNumAfCb); // debug
464             // check overflow
465             //while (pCb->numAfCb >= pCb->maxNumAfCb); // debug
466             if (pCb->numAfCb >= pCb->maxNumAfCb)
467             {
468                 pCb->errOvrCnt++;
470                 //SW_BREAKPOINT;
471                 Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb);
473                 // Write back circular buffer configuration
474                 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
475                 Cache_wait();
477                 // Leave the gate
478                 GateMP_leave(gateHandle, key);
480                 //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
482                 return ASP_DECOP_CB_WRITE_OVERFLOW;
483             }
485             pAfCb = &pCb->afCb[pCb->afWrtIdx];
486             pPcmBuf = pAfCb->data.sample[0];
487             pMetaBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;
488             if ((pPcmBuf + (pAfWrt->sampleCount * pCb->maxAFChanNum)) >= (pCb->pcmBufEnd))
489             {
490                 pPcmBuf = pCb->pcmBuf;
491             }
493             for (i=0; i<pCb->maxAFChanNum; i++)
494             {
495                 pAfCb->data.sample[i] = pPcmBuf;
496                 pPcmBuf += pAfWrt->sampleCount;
497                 pAfCb->data.samsiz[i] = 0;
498             }
499             Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
500             Cache_wait();
502             //for (i=0; i<pCb->maxAFChanNum; i++){
503             //}
504             for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
505             {
506                 pAfCb->pafPrivateMetadata[i].offset = 0;
507                 pAfCb->pafPrivateMetadata[i].size   = 0;
508                 pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
509                 pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
510             }
512             nextWrtIdx = 0;
513             if ((pCb->afWrtIdx +1) >= pCb->maxNumAfCb)
514             {
515                 //Log_info0("cbWriteAf: AF Wrap around **** ");
516                 // next audio frame will be audio frame 0
517                 nextWrtIdx = 0;
518             }
519             else
520             {
521                 // next audio frame will be current audio frame + 1
522                 nextWrtIdx = pCb->afWrtIdx + 1;
523             }
525             pAfCbNextAf = &pCb->afCb[nextWrtIdx]; // +1 or last AF if overflow
526             pAfCbNextAf->data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount];// pAfCb->data.sample[15] + (pAfCb->sampleCount * sizeof(PAF_AudioData));
528             // write audio frame information updated by decoder
529             pAfCb->sampleDecode = pAfWrt->sampleDecode;
530             PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
531             pAfCb->sampleRate = pAfWrt->sampleRate;
532             pAfCb->sampleCount = pAfWrt->sampleCount;
533             pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
534             pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
535             // write metadata information updated by decoder
536             pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
537             pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
538             pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
539             pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
540             // write PCM samples
541             streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
542             for (i = 0; i < pCb->maxAFChanNum; i++)
543             {
544                 if ((streamMask >> i) & 0x1)
545                 {
546                     for (j = 0; j < pAfWrt->sampleCount; j++)
547                     {
548                         pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
549                     }
551                     pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
552                 }
553             }
555             #ifdef CB_RW_OP_CAP_PP // debug
556             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
557             {
558                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
559                 {
560                     // log sample count
561                     pCb->cb_samples_op[pCb->cb_opCnt] = pAfWrt->sampleCount;
562                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_W;
563                     // log idxs
564                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
565                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
566                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
567                     pCb->cb_opCnt++;
568                 }
569             }
570             #endif
572             // prepare metadata buffer pointers according to the metadata and buffer sizes
573             for (i=0; i < pAfWrt->numPrivateMetadata; i++)
574             {
575                 UInt8 *nextMdBuf;
576                 if(i == 0)
577                     nextMdBuf = (pAfCb->pafPrivateMetadata[0].pMdBuf + pAfWrt->pafPrivateMetadata[0].size);
578                 else
579                     nextMdBuf = (pAfCb->pafPrivateMetadata[i-1].pMdBuf + pAfWrt->pafPrivateMetadata[i-1].size);
580                 if(nextMdBuf >= pCb->metaBufEnd) // metadata buffer overflow
581                 {
582                     pAfCb->pafPrivateMetadata[i].pMdBuf = pCb->metaBuf;
583                 }
584                 else if(i != 0)
585                 {
586                     pAfCb->pafPrivateMetadata[i].pMdBuf = nextMdBuf;
587                 }
588                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
589             }
591             // Write metadata to circular buffer
592             for (i = 0; i < pAfWrt->numPrivateMetadata; i++) // only copy numPrivateMetadata
593             {
594                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset;
595                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size;
596                 memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size);
597             }
599             Cache_inv(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
600             Cache_wait();
601             for (i=0; i<pAfCb->numPrivateMetadata; i++) // only write back numPrivateMetadata
602             {
603                 //Log_info4("cbWriteAf: AF: %d nummd: %d offset: %d size: %d ", pCb->afWrtIdx, pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[i].offset,  pAfCb->pafPrivateMetadata[i].size);
604                 Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
605             }
606             // update audio frame write index
607             pCb->afWrtIdx++;
608             if (pCb->afWrtIdx >= pCb->maxNumAfCb)
609             {
610                 pCb->afWrtIdx = 0;
611             }
613             pCb->afCb[pCb->afWrtIdx].data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount];
614             if(pAfWrt->numPrivateMetadata > 0)
615             {
616                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].pMdBuf + pAfWrt->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].size;
617             }
618             else
619             {
620                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;
621                 Cache_wb(pCb->afCb , ASP_DECOP_CB_MAX_NUM_PCM_FRAMES*sizeof(PAF_AudioFrame *), Cache_Type_ALLD, 0);
622                 Cache_wait();
623             }
624             Cache_inv(pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
625             Cache_wait();
626             // update number of audio frames in circular buffer
627             pCb->numAfCb++;
628             
629             // Update CB Lag index 
630             //if (pCb->afLagIdx < pCb->afInitialLag)
631             //{
632             //    pCb->afLagIdx += 1;
633             //}
634             
635             // Update CB primed flag
636             // calculate number of delta samples before allowing CB read
637             if (pCb->primedFlag == 0)
638             {
639                 pCb->primedFlag = 1;
640                 
641                 // Calculate number of output frames to block reader.
642                 // This is sample count reader waits before allowed to actually read samples from the CB.
643                 //pCb->deltaSamps = (pCb->targetNDSamps - pAfWrt->sampleCount + (pCb->strFrameLen-1)) / pCb->strFrameLen * pCb->strFrameLen;
644                 // FL: CB read decrements by strFrameLen and tests for >0, so rounding to strFrameLen is unnecessary
645                 pCb->deltaSamps = pCb->targetNDSamps - pAfWrt->sampleCount;
646                 
647                 // debug
648                 //gSampleCountBuf[gPrimedFlagCnt] = pAfWrt->sampleCount;
649                 //gCalcDeltaSampsBuf[gPrimedFlagCnt] = pCb->deltaSamps;
650                 //if (gPrimedFlagCnt < 10)
651                 //    gPrimedFlagCnt++;
652             }
654             // Write back circular buffer configuration
655             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
656             // write back audio frame
657             Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
658             Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
659             Cache_wb(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0);
660             Cache_wait();
661             // write back PCM data
662             for (i = 0; i < pCb->maxAFChanNum; i++)
663             {
664                 if ((streamMask >> i) & 0x1)
665                 {
666                     Cache_wb(pAfCb->data.sample[i], pAfWrt->sampleCount * sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
667                 }
668             }
669             Cache_wait();
671 #if 0 // (***) FL: shows timing of CB write
672             // debug
673             {
674                 static Uint8 toggleState = 0;
675                if (toggleState == 0)
676                    GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99);
677                else
678                    GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99);
679                toggleState = ~(toggleState);
680             }
681 #endif
683             Log_info3("wrote %d samples into AF %d sourceSel: %d", pAfCb->sampleCount, pCb->afWrtIdx, pCb->sourceSel);
684             Log_info4("CBWMETA num=%d  size=%d  offset=%d chrequest=0x%04x", pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[0].size, pAfCb->pafPrivateMetadata[0].offset, pAfCb->channelConfigurationRequest.full);
685         }
686         else
687         {
688             //
689             // Skip write in case of 0 sample count
690             //
691             
692             // writing audio frame w/ zero samples
693             // update stat
694             pCb->wrtAfZeroSampsCnt++;
696             // Write back circular buffer configuration
697             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
698             Cache_wait();
699         }
700     //}
701     //else if (pCb->readerActiveFlag == 0)
702     if (pCb->readerActiveFlag == 0)
703     {
704         //
705         // Reader inactive, don't write to circular buffer or check OVRflow.
706         //
707         
708         // writing AF w/ inactive reader
709         // update stat
710         pCb->wrtAfReaderInactiveCnt++;
712         // Write back circular buffer configuration
713         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
714         Cache_wait();
715     }
717     // Leave the gate
718     GateMP_leave(gateHandle, key);
720     //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
722     return ASP_DECOP_CB_SOK;
725 #if 0
726 // Get next audio frame to write in circular buffer
727 Int cbGetNextWriteAf(
728     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
729     Int8 cbIdx,                         // decoder output circular buffer index
730     PAF_AudioFrame **ppAfWrt            // audio frame next to be written
733     IArg key;
734     GateMP_Handle gateHandle;
735     PAF_AST_DecOpCircBuf *pCb;
737     // Get gate handle
738     gateHandle = pCbCtl->gateHandle;
739     // Enter gate
740     key = GateMP_enter(gateHandle);
742     // Get circular buffer base pointer
743     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
745     // get pointer to current audio frame in circular buffer
746     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
747     
748     // update audio frame write index
749     pCb->afWrtIdx++;
750     if (pCb->afWrtIdx > pCb->maxNumAfCb)
751     {
752         pCb->afWrtIdx = 0;
753     }    
754     
755     // Leave the gate
756     GateMP_leave(gateHandle, key);
758     return ASP_DECOP_CB_SOK;
760 #endif
762 // Init last audio frame configuration info 
763 static Void cbInitLastAfInfo(
764     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
765     PAF_AudioFrame *pAfInit     // audio frame used for init
768     memset(&pCb->lastAf, 0, sizeof(PAF_AudioFrame));
769     
770     pCb->lastAf.sampleDecode = pAfInit->sampleDecode;
771     pCb->lastAf.sampleRate = pAfInit->sampleRate;
772     pCb->lastAf.channelConfigurationRequest.full = pAfInit->channelConfigurationRequest.full;
773     pCb->lastAf.channelConfigurationStream.full = pAfInit->channelConfigurationStream.full;