]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_dsp/mib/mib.c
PASDK-516:First version of ASOT refactoring
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / mib / mib.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 //
37 //
38 // Stacking Input Buffer Driver implementations
39 //
40 //
41 // Derived from /c/ti/c6000/src/drivers/dgs.c
43 #include <xdc/std.h>
44 #include <xdc/cfg/global.h>
45 #include <xdc/runtime/Memory.h>
46 #include <xdc/runtime/System.h>
47 #include <xdc/runtime/Error.h>
48 #include <xdc/runtime/IHeap.h>
49 #include <ti/sysbios/knl/Queue.h>
50 #include <ti/sysbios/knl/Semaphore.h>
51 #include <ti/sysbios/heaps/HeapMem.h>
53 #include <dev2.h>
54 #include "mib.h"
55 #include "miberr.h"
56 #include <inpbuf.h>
57 #include <pafdec.h>
58 #include <pafsio.h>
59 #include <pafsio_ialg.h>
61 #include <limits.h> //INT_MAX
62 #include <string.h>
64 typedef xdc_Short MdInt;
65 typedef xdc_UShort MdUns;
66 typedef xdc_Char SmInt;
67 typedef xdc_UChar SmUns;
70 extern const ti_sysbios_heaps_HeapMem_Handle heapMemDdr3;
71 #define HEAPMALLOC (IHeap_Handle)heapMemDdr3
72 extern HeapMem_Handle DEV2_memSpaceToHeap (IALG_MemSpace space);
74 #include "pafhjt.h"
76 #include <ti/sysbios/knl/Clock.h>
77 #include <xdc/runtime/Log.h>
79 //grab from samrat.c
80 #include <paftyp.h>
81 #include <stdasp.h>
83 #include <logp.h>
84 #include <stdio.h>  // printf in case of programming error
86 // allows you to set a different trace module in pa.cfg
87 #define TR_MOD  trace
89 //#define TRACE_ENABLE
90 #ifdef TRACE_ENABLE
91   #include "dp.h"
92   #define TRACE(a)  dp a    // LOG_printf a
93 #else
94   #define TRACE(a)
95 #endif
97 extern const PAF_SampleRateHz
98 PAF_ASP_sampleRateHzTable[PAF_SAMPLERATE_N][PAF_SAMPLERATEHZ_N];
100 #define SCANATSAMPLERATELIMIT ((float) 48000.)
102 // Likely needs to be 7 when/if AC3 handling is changed to
103 // throw away fill.
104 #define NUM_CHILD_BUFFERS 6
106 Int   DIB_ctrl (DEV2_Handle device, Uns code, Arg Arg);
107 Int   DIB_idle (DEV2_Handle device, Bool Flush);
108 Int   DIB_issue (DEV2_Handle device);
109 Int   DIB_open (DEV2_Handle device, String Name);
110 Int   DIB_reclaim (DEV2_Handle device);
111 Int   DIB_getSync (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
112 Int   DIB_initFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
113 Int   DIB_requestFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
114 Int   DIB_issueChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, Int size, Int forTotal);
115 Int   DIB_reclaimChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
116 Int   DIB_reset (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
117 Int   DIB_syncScan (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout);
118 Int   DIB_waitForData (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 count);
119 Int   DIB_syncScanDTS (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout, XDAS_UInt16 *pHeaderEnd);
121 // Driver function table.
122 DIB_Fxns DIB_FXNS  = {
123     NULL,                // close not used in PA/F systems
124     DIB_ctrl,
125     DIB_idle,
126     DIB_issue,
127     DIB_open,
128     NULL,                // ready not used in PA/F systems
129     DIB_reclaim,
130     DIB_getSync,
131     DIB_initFrame,
132     DIB_requestFrame,
133     DIB_issueChild,
134     DIB_reclaimChild,
135     DIB_reset,
136     DIB_syncScan,
137     DIB_waitForData,
138     DIB_syncScanDTS
139 };
141 // macros assume pDevExt is available and pDevExt->pFxns is valid
142 #define DIB_FTABLE_getSync(_a,_b)             (*pDevExt->pFxns->getSync)(_a,_b)
143 #define DIB_FTABLE_initFrame(_a,_b)           (*pDevExt->pFxns->initFrame)(_a,_b)
144 #define DIB_FTABLE_requestFrame(_a,_b)        (*pDevExt->pFxns->requestFrame)(_a,_b)
145 #define DIB_FTABLE_issueChild(_a,_b,_c,_d)    (*pDevExt->pFxns->issueChild)(_a,_b,_c,_d)
146 #define DIB_FTABLE_reclaimChild(_a,_b)        (*pDevExt->pFxns->reclaimChild)(_a,_b)
147 #define DIB_FTABLE_reset(_a,_b)               (*pDevExt->pFxns->reset)(_a,_b)
148 #define DIB_FTABLE_syncScan(_a,_b,_c)         (*pDevExt->pFxns->syncScan)(_a,_b,_c)
149 #define DIB_FTABLE_waitForData(_a,_b,_c)      (*pDevExt->pFxns->waitForData)(_a,_b,_c)
150 #define DIB_FTABLE_syncScanDTS(_a,_b,_c,_d)   (*pDevExt->pFxns->syncScanDTS)(_a,_b,_c,_d)
152 // .............................................................................
154 //IBMODE
155 enum
157     MODE_DEFAULT = 0,
158     MODE_NO_ZERORUNRESTART = 1,
159     MODE_NO_ZERORUN = 2
160 };
162 // syncState
163 enum
165     SYNC_NONE,
166     SYNC_ONE,
167     SYNC_ONGOING,
168     SYNC_PCM,
169     SYNC_PCM_FORCED,
170     SYNC_AUTO
171 };
173 // scanState
174 enum
176     SCANNED_NONE,
177     SCANNED_IEC_PA,
178     SCANNED_IEC_PB,
179     SCANNED_IEC_PC,
180     SCANNED_DTS14_SYNC_A,
181     SCANNED_DTS14_SYNC_B,
182     SCANNED_DTS14_SYNC_C,
183     SCANNED_DTS14_SYNC_D,
184     SCANNED_DTS16_SYNC_A,
185     SCANNED_DTS16_SYNC_B,
186     SCANNED_DTS16_SYNC_C
187 };
189 // all sizes in number of 16bit words words
190 #define IEC_HEADER_SIZE   4 //PA PB PC PD
191 #define DTS14_HEADER_SIZE 6
192 #define DTS16_HEADER_SIZE 4
194 //table needed until PAF_SOURCE is reordered to match IEC numbering
195 const SmUns iecPafSource[23] =
197     PAF_SOURCE_UNKNOWN,  // 0: IEC NULL Type
198     PAF_SOURCE_AC3,      // 1: Comments on 1-15 match IEC 61937 part 2.
199     PAF_SOURCE_UNKNOWN,  // 2: IEC reserved
200     PAF_SOURCE_UNKNOWN,  // 3: IEC pause
201     PAF_SOURCE_UNKNOWN,  // 4: MPEG 1 layer 1
202     PAF_SOURCE_MP3,      // 5: MPEG layer 2 or 3
203     PAF_SOURCE_UNKNOWN,  // 6: MPEG 2 data with extension
204     PAF_SOURCE_AAC,      // 7: MPEG-2 AAC ADTS
205     PAF_SOURCE_UNKNOWN,  // 8: MPEG 2 layer 1 low sampling frequency
206     PAF_SOURCE_UNKNOWN,  // 9: MPEG 2 layer 2 or 3 low sampling frequency
207     PAF_SOURCE_UNKNOWN,  // 10: reserved
208     PAF_SOURCE_DTS,      // 11: DTS type 1 (11 bit: 512 sample repeat period)
209     PAF_SOURCE_DTS12,    // 12: DTS type 2 (12 bit: 1024 sample repeat period)
210     PAF_SOURCE_DTS13,    // 13: DTS type 3 (13 bit: 2048 sample repeat period)
211     PAF_SOURCE_DTS14,    // 14: ATRAC
212     PAF_SOURCE_UNKNOWN,  // 15: ATRAC 2/3
213     PAF_SOURCE_THD,      // 16
214     PAF_SOURCE_DTSHD,    // 17
215     PAF_SOURCE_WMA9PRO,  // 18
216     PAF_SOURCE_UNKNOWN,  // 19
217     PAF_SOURCE_UNKNOWN,  // 20
218     PAF_SOURCE_DDP,      // 21
219     PAF_SOURCE_THD,      // 22
220 };
222 // IEC framelengths (in 16bit words)
223 const MdUns iecFrameLength[23] =
225     0,
226     1536*2,
227     0, 0, 0,
228     1152*2,
229     0,
230     1024*2,
231     0, 0, 0,
232     512*2,
233     1024*2,
234     2048*2,
235     0, 0,
236     15*1024*2, //THD
237     1*1024, // DTSHD, actual framelength is adjusted by DTSsubType
238     4096*2,
239     0,0,
240     1536*2*4,
241     15*1024*2 //THD
242 };
244 #define IEC_PA       ((short) 0xF872)
245 #define IEC_PB       ((short) 0x4E1F)
246 #define DTS16_SYNC_A ((short) 0x7FFE)
247 #define DTS16_SYNC_B ((short) 0x8001)
248 #define DTS16_SYNC_C ((short) 0xFC00)
249 #define DTS14_SYNC_A ((short) 0x1FFF)
250 #define DTS14_SYNC_B ((short) 0xE800)
251 #define DTS14_SYNC_C ((short) 0x07F0)
253 #define  DTS_BURST_TYPE_I  0x008B
254 #define  DTS_BURST_TYPE_II 0x018C
255 #define  DTS_BURST_TYPE_III 0x028D
256 #define  DTS_BURST_TYPE_IV  0x0491
258 #define  DTS_BURST_TYPE_IV_CBR  0x02
259 #define  DTS_BURST_TYPE_IV_LBR  0x03
260 #define  DTS_BURST_TYPE_IV_HBR  0x04
262 #define DEFAULT_AUTOREQUESTSIZE  128
263 //#define DEFAULT_AUTOREQUESTSIZE  256
265 // This is used at a couple of locations to ensure the transfer
266 // size is sufficiently long to be useful.
267 #define NOMINAL_XFERSIZE         128 //GJ Debug
269 #define min(a, b)  (((a) < (b)) ? (a) : (b))
270 #define max(a, b)  (((a) > (b)) ? (a) : (b))
272 // debug
273 //#include "evmc66x_gpio_dbg.h"
275 // -----------------------------------------------------------------------------
277 inline void IncrementPtr (PAF_InpBufConfig *pBufConfig, Ptr *pPtr, int numWords)
279     int addr;
282     addr = (int) *pPtr + numWords*pBufConfig->sizeofElement;
283     if (addr > ((int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer - 1))
284         addr -= pBufConfig->sizeofBuffer;
286     *pPtr = (Ptr) addr;
287     return;
288 } // IncrementPtr
290 // -----------------------------------------------------------------------------
292 inline int GetNumAvail (PAF_InpBufConfig *pBufConfig)
294     int numBytes;
297     if ( (Uns) pBufConfig->head.pVoid >= (Uns) pBufConfig->pntr.pVoid)
298         numBytes = ((int)pBufConfig->head.pVoid - (int)pBufConfig->pntr.pVoid);
299     else
300         numBytes = ((int)pBufConfig->head.pVoid - (int)pBufConfig->pntr.pVoid + pBufConfig->sizeofBuffer);
302     // return in words
303     return (numBytes / pBufConfig->sizeofElement);
304 } // GetNumAvail
306 // -----------------------------------------------------------------------------
307 // compute how much data we have including outstanding requests
309 inline int GetFutureAvail (PAF_InpBufConfig *pBufConfig)
311     int numBytes;
314     if ( (Uns) pBufConfig->futureHead.pVoid >= (Uns) pBufConfig->pntr.pVoid)
315         numBytes = ((int)pBufConfig->futureHead.pVoid - (int)pBufConfig->pntr.pVoid);
316     else
317         numBytes = ((int)pBufConfig->futureHead.pVoid - (int)pBufConfig->pntr.pVoid + pBufConfig->sizeofBuffer);
319     // return in words
320     return (numBytes / pBufConfig->sizeofElement);
321 } // GetFutureAvail
323 // -----------------------------------------------------------------------------
325 Int DIB_issue (DEV2_Handle device)
327     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
328     DEV2_Frame             *srcFrame;
329     Int                    status;
330     PAF_InpBufConfig      *pBufConfig;
333     srcFrame = Queue_get (device->todevice);
334     pBufConfig = (PAF_InpBufConfig *) srcFrame->addr;
335     if (!pBufConfig || !pBufConfig->pBufStatus)
336         return SIO2_EINVAL;
338     Queue_put (device->fromdevice, (Queue_Elem *)srcFrame);
340     if (srcFrame->arg == PAF_SIO_REQUEST_NEWFRAME) {
342         // do nothing if not synced since syncing done in reclaim
343         // This is executed in force modes from the first call to PAF_AST_decodeInit
344         // which calls SIO2_issue for NEWFRAME before all other calls.
345         if (pDevExt->syncState == SYNC_NONE)
346             return 0;
348         status = DIB_FTABLE_requestFrame (device, &pDevExt->bufConfig);
349         if (status)
350             return status;
351     }
353     return 0;
354 } // DIB_issue
356 // -----------------------------------------------------------------------------
357 // Although interface allows for arbitrary BufConfigs we only support 1 -- so
358 // we can assume the one on the fromdevice is the one we want
360 extern int gIsrInputCnt;
361 extern int gIsrOutputCnt;
363 Int DIB_reclaim (DEV2_Handle device)
365     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *) device->object;
366     DEV2_Frame             *dstFrame;
367     Int                    status = 0;
368     PAF_InpBufConfig      *pBufConfig;
370     dstFrame = (DEV2_Frame *) Queue_head (device->fromdevice);
372     if (dstFrame == (DEV2_Frame *) device->fromdevice)
373         return DIBERR_UNSPECIFIED;
374     if (!dstFrame->addr)
375         return DIBERR_UNSPECIFIED;
377     // if deferred error from last request frame then return now
378     status = pDevExt->deferredError;
379     if (status) {
380         pDevExt->deferredError = 0;
381         pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
382         return status;
383     }
385     pBufConfig = (Ptr) dstFrame->addr;
386     dstFrame->size = sizeof (PAF_InpBufConfig);
388     // .........................................................................
390     if ((pDevExt->syncState == SYNC_NONE) || (dstFrame->arg == PAF_SIO_REQUEST_SYNC)) {
392         Log_info0("DIB: At case: syncState == SYNC_NONE (or PAF_SIO_REQUEST_SYNC)");
394         // pass in external buffer config which used to initialize the internal view
395         status = DIB_FTABLE_reset (device, pBufConfig);
396         if (status)
397             return status;
399         status = DIB_FTABLE_getSync (device, &pDevExt->bufConfig);
400         if (status)
401             return status;
403         // since getSync resets sourceProgram to unknown at entry
404         // sourceProgram will remain unknown if no sync is returned
405         // (i.e. no need to reset it here)
406         if (pDevExt->syncState == SYNC_NONE)
407         {
408             Log_info0("Returning DIBERR_SYNC after DIB_FTABLE_getSync");
409             return DIBERR_SYNC;
410         }
412         // get input info (frameLength/etc)
413         status = DIB_FTABLE_initFrame (device, &pDevExt->bufConfig);
415         if (status)
416         {
417             Log_info1("Returning %d after DIB_FTABLE_initFrame", status);
418             return status;
419         }
421         // request timing frame
422         status = DIB_FTABLE_requestFrame (device, &pDevExt->bufConfig);
423         if (status)
424         {
425             Log_info1("Returning %d after DIB_FTABLE_requestFrame", status);
426             return status;
427         }
428         // update external view of bufConfig. In particular for slave force PCM
429         // this insures that the first decode will be processed with deliverZeros = 1
430         // which is necessary since the first decode of slave input occurs before the
431         // first slave input frame is actually captured.
432         *pBufConfig = pDevExt->bufConfig;
434     } //((pDevExt->syncState == SYNC_NONE) || (dstFrame->arg == PAF_SIO_REQUEST_SYNC))
436     // .........................................................................
438     if (dstFrame->arg == PAF_SIO_REQUEST_NEWFRAME) {
440         Log_info0("DIB: At case = PAF_SIO_REQUEST_NEWFRAME");
442         // wait for enough data to check for sync at expected location
443         status = DIB_FTABLE_waitForData (device, &pDevExt->bufConfig, pDevExt->bufConfig.frameLength);
444         if (status)
445         {
446             Log_info2("DIB_reclaim.%d DIB_FTABLE_waitForData returned %d", __LINE__, status);
447             //TRACE((&TR_MOD, "DIB_reclaim.%d DIB_FTABLE_waitForData returned %d\n", __LINE__, status));
448             return status;
449         }
451         // if PCM, but not forced PCM, then scan for bitstream sync
452         // note that we we using the local view of bufConfig here and we update the
453         // public view afterwards.
454         if (pDevExt->syncState == SYNC_PCM) {
455             float sampleRate = PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD];
456             PAF_InpBufConfig *pBufConfig = &pDevExt->bufConfig;
457             Int ibMode = pBufConfig->pBufStatus->mode; // read mode register once
459             // normally no scanning done if sampleRate > 48kHz since bitstream input is highly unlikley.
460             if ((sampleRate <= SCANATSAMPLERATELIMIT) || pBufConfig->pBufStatus->scanAtHighSampleRateMode) {
461                 if (!pBufConfig->deliverZeros) {
462                     pDevExt->pcmTimeout = pBufConfig->lengthofData;
464                     // check zeroRunTrigger if needed
465                     if (ibMode != MODE_NO_ZERORUN) {
466                         if(pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger) {
467                             // set this flag one block late to allow for
468                             // transmission of all data in frame which contained zeroRunTrigger
469                             pBufConfig->deliverZeros = 1;
470                             pDevExt->pcmTimeout = 2 * pBufConfig->pBufStatus->unknownTimeout;
471                         } // > zeroRunTrigger
472                     } // !MODE_NO_ZERORUN
473                 } // !pBufConfig->deliverZeros
475                 // scan PCM data
476                 status = DIB_FTABLE_syncScan (device, pBufConfig, &pDevExt->pcmTimeout);
477                 if (status) {
478                     pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
479                     Log_info2("DIB_reclaim.%d DIB_FTABLE_syncScan returned %d", __LINE__, status);
480                     //TRACE((&TR_MOD, "DIB_reclaim.%d DIB_FTABLE_syncScan returned %d\n", __LINE__, status));
481                     return status;
482                 }
484                 // if scan found something other than PCM, then exit with error
485                 if (pDevExt->syncState != SYNC_PCM)
486                 {
487                     Log_info1("DIB_reclaim.%d error: syncState != SYNC_PCM", __LINE__);
488                     //TRACE((&TR_MOD, "DIB_reclaim.%d error: syncState != SYNC_PCM\n", __LINE__));
489                     return DIBERR_SYNC;
490                 }
492                 // if heeding zeroRunRestart control then return to unknown if necessary
493                 if ((ibMode == MODE_DEFAULT) &&
494                     (pDevExt->zeroCount >= 2*pBufConfig->pBufStatus->zeroRunRestart)) {
495                     // if zeroRunRestart me then reset input to unknown
496                     Log_info1("DIB_reclaim.%d error: zeroRunRestart, setting PAF_SOURCE_UNKNOWN", __LINE__);
497                     //TRACE((&TR_MOD, "DIB_reclaim.%d error: zeroRunRestart, setting PAF_SOURCE_UNKNOWN\n", __LINE__));
498                     pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
499                     return DIBERR_SYNC;
500                 }
502                 // since in skeptical state we disallow returning to PCM when end of timeout contains zeros
503                 // note that we need not check the mode here since above logic prevents deliverZeros state.
504                 if (pBufConfig->deliverZeros && (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger))
505                 {
506                     //TRACE((&TR_MOD, "DIB_reclaim.%d set pcmTimeout = unknown timeout\n", __LINE__));
507                     pDevExt->pcmTimeout = 2 * pBufConfig->pBufStatus->unknownTimeout;
508                 }
509             } //scanAtHighSampleRate
510         } //SYNC_PCM
512         // clear this flag immediately to play new audio ASAP
513         // this check is OK for forced PCM since pcmTimeout and zeroCount are not
514         // updated
515         if (pDevExt->bufConfig.deliverZeros && !pDevExt->pcmTimeout &&
516             (pDevExt->zeroCount < 2 * pDevExt->bufConfig.pBufStatus->zeroRunTrigger))
517         {
518             pDevExt->bufConfig.deliverZeros = 0;
519         }
521         // update external view of buffer with local view we do this with current 
522         // frame info before the following update to the local view for the next 
523         // frame to be captured. Need to subtract headerSize from lengthofData
524         // since, at least for THD, it is needed by decoders.
525         *pBufConfig = pDevExt->bufConfig;
526         pBufConfig->lengthofData -= pDevExt->headerSize;
527         Log_info4("DIB_reclaim.%d lengthofData = %d; InISRCNT=%d; OutISRCNT=%d", __LINE__, pBufConfig->lengthofData, gIsrInputCnt, gIsrInputCnt);
528         //TRACE((&TR_MOD, "DIB_reclaim.%d lengthofData = %d\n", __LINE__, pBufConfig->lengthofData));
530         // HACK: for DSD the frameLength needs to be the number of samples to generate.
531         if ((pDevExt->sourceSelect >= PAF_SOURCE_DSD1) &&
532             (pDevExt->sourceSelect <= PAF_SOURCE_DSD3))
533             pBufConfig->frameLength /= pBufConfig->stride;
534         Log_info2("DIB_reclaim.%d frameLength = %d", __LINE__, pBufConfig->frameLength);
535         //TRACE((&TR_MOD, "DIB_reclaim.%d frameLength = %d\n", __LINE__, pBufConfig->frameLength));
537         // set external view to point at synch position of the frame guaranteed
538         // to be captured by above waitForData. Need to condition this against PCM since
539         // in that case pSync could point anywhere in the buffer to to syncScan. E.g.
540         // if there was a partial sync then pSync would point at that rather than
541         // at the beginning of the buffer.
542         // TODO: change syncScan to only update pDevExt->pSync when there is an actual sync
543         //       so that we can use this for both PCM and bitstream
544         if (pDevExt->syncState == SYNC_ONGOING) {
545             pBufConfig->pntr = pDevExt->pSync;
546             IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pDevExt->headerSize);
547         } //SYNC_ONGOING
549         // if a bitstream then need to update tail to bitstream sync location
550         // and check for next sync at expected location
551         // quick scan for sync. if decoding IEC but sync is missing then
552         // defer error until the next frame so that we decode all frames
553         // TODO: does this assume decoders have copied the entire input frame
554         //       i.e. it is ok to adjust the input buffer pointers.
555         // if successful then this sets
556         //      pSync = address of PA (for IEC)
557         status = DIB_FTABLE_initFrame (device, &pDevExt->bufConfig);
558         if (status) {
559             if (pBufConfig->pBufStatus->lastFrameMask & (1 << pDevExt->sourceProgram)) {
560                 pDevExt->deferredError = status;
561                 Log_info1("DIB_reclaim.%d last frame\n", __LINE__);
562                 //TRACE((&TR_MOD, "DIB_reclaim.%d last frame\n", __LINE__));
563                 pBufConfig->pBufStatus->lastFrameFlag = 1;
564                 return 0;
565             }
566             else {
567                 Log_info1("DIB_reclaim.%d setting PAF_SOURCE_UNKNOWN", __LINE__);
568                 //TRACE((&TR_MOD, "DIB_reclaim.%d setting PAF_SOURCE_UNKNOWN\n", __LINE__));
569                 pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
570                 return status;
571             }
572         }
574     } //(dstFrame->arg == PAF_SIO_REQUEST_NEWFRAME)
576     // .........................................................................
578     Log_info4("DIB_reclaim.%d exit status = %d, InISRCNT = %d OutISRCNT = %d", __LINE__, status, gIsrInputCnt, gIsrOutputCnt);
579     //TRACE((&TR_MOD, "DIB_reclaim.%d exit status = %d\n", __LINE__, status));
581     return status;
582 } // DIB_reclaim
584 // -----------------------------------------------------------------------------
586 Int DIB_ctrl (DEV2_Handle  device, Uns code, Arg arg)
588     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
589     DEV2_Handle            pChild = (DEV2_Handle)&pDevExt->child;
590     Int status = 0;
593     switch (code) {
595         case PAF_SIO_CONTROL_GET_CHILD_DEVICE:
596             *((Arg *)arg) = (Arg) pChild;
597             break;
599             //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
601         case PAF_SIO_CONTROL_SET_DECSTATUSADDR:
602             pDevExt->pDecodeStatus = (PAF_DecodeStatus *) arg;
603             break;
605         case PAF_SIO_CONTROL_SET_PCMFRAMELENGTH:
606             pDevExt->pcmFrameLength = (XDAS_Int32) arg;
607             break;
609         case PAF_SIO_CONTROL_SET_SOURCESELECT:
610             pDevExt->sourceSelect = (XDAS_Int8) arg;
611             break;
613         case PAF_SIO_CONTROL_SET_AUTOREQUESTSIZE:
614             pDevExt->autoRequestSize = (XDAS_Int16) arg;
615             break;
617         case PAF_SIO_CONTROL_GET_SOURCEPROGRAM:
618             if (!arg)
619                 return DIBERR_UNSPECIFIED;
620             *((XDAS_Int8 *) arg) = pDevExt->sourceProgram;
621             break;
623         case PAF_SIO_CONTROL_SET_IALGADDR:
624             pDevExt->pSioIalg = (PAF_SIO_IALG_Obj *) arg;
625             break;
627             //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
629         case PAF_SIO_CONTROL_OPEN:
630             pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
631             pDevExt->zeroCount = 0;
632             if (pDevExt->pInpBufStatus)
633                 pDevExt->pInpBufStatus->zeroRun = 0;
634             status = DEV2_ctrl (pChild, code, arg);
635             break;
637         case PAF_SIO_CONTROL_CLOSE:
638             if (pDevExt->pInpBufStatus)
639                 pDevExt->pInpBufStatus->zeroRun = 0;
640             status = DEV2_ctrl (pChild, code, arg);
641             break;
643         // return number of DMA events vs. request size
644         // only update if not in error state (i.e. status = 0)
645         case PAF_SIO_CONTROL_GET_NUM_EVENTS:
646             if (!arg)
647                 return DIBERR_UNSPECIFIED;
648             status = DEV2_ctrl (pChild, code, arg);
649             if (!status)
650                 *((Int *)arg) -= pDevExt->pcmFrameLength;
651             break;
653         // return net samples until next DIB_waitForData() should succeed w/o blocking
654         case PAF_SIO_CONTROL_GET_NUM_REMAINING:
655             if (!arg)
656                 return DIBERR_UNSPECIFIED;
657             status = DEV2_ctrl (pChild, code, arg);
658             *((Int *)arg) -= pDevExt->numSamplesExtra;
659             break;
661         default:
662             status = DEV2_ctrl (pChild, code, arg);
663             break;
664     }
666     return status;
667 } // DIB_ctrl
669 // -----------------------------------------------------------------------------
671 Int DIB_idle (DEV2_Handle device, Bool flush)
673     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
674     Int                    status;
677     while (!Queue_empty (device->todevice))
678         Queue_enqueue (device->fromdevice, Queue_dequeue (device->todevice));
680     while (!Queue_empty (device->fromdevice))
681         Queue_enqueue (Queue_handle(&((SIO2_Handle) device)->framelist), Queue_dequeue (device->fromdevice));
683     status = DIB_FTABLE_reset (device, NULL);
684     if (status)
685         return status;
687     return 0;
688 } // DIB_idle
690 // -----------------------------------------------------------------------------
692 Int DIB_open (DEV2_Handle device, String name)
694     DIB_DeviceExtension   *pDevExt;
695     DEV2_Handle             pChild;
696     DEV2_Device            *entry;
697     DEV2_Frame             *frame;
698     Int                    status, i;
699         Error_Block eb;
701         Error_init(&eb);
703     name = DEV2_match (name, &entry);
704     if (entry == NULL) {
705         Log_info1("DEV2_match failed in DIB_open:", SIO2_ENODEV);
706         return SIO2_ENODEV;
707     }
709     // only one frame interface supported
710     if (device->nbufs != 1)
711         return SYS_EALLOC;
713     if (!(pDevExt = Memory_alloc (device->bufSeg, sizeof(DIB_DeviceExtension), 0, &eb)))
714     {
715         Log_info1("DIB Memory alloc failed in DIB_open:", SYS_EALLOC);
716         return SYS_EALLOC;
717     }
718     pDevExt->pcmFrameLength = 0;
719     pDevExt->sourceSelect  = PAF_SOURCE_NONE;
720     pDevExt->autoRequestSize = DEFAULT_AUTOREQUESTSIZE;
721     pDevExt->pInpBufStatus = NULL;
722     pDevExt->pDecodeStatus = NULL;
723     device->object = (Ptr)pDevExt;
725     pChild = (DEV2_Handle)&pDevExt->child;
726     pChild->fromdevice = Queue_create (NULL, &eb);
727     pChild->todevice = Queue_create (NULL, &eb);
728     if (pChild->fromdevice == NULL || pChild->todevice == NULL) {
729         Log_info1 ("DIB Queue_create failed in DIB_open:", SYS_EALLOC);
730         return SYS_EALLOC;
731     }
733     pChild->bufsize = 0;
734     pChild->nbufs = NUM_CHILD_BUFFERS;
735     pChild->bufSeg = device->bufSeg;
736     pChild->mode = device->mode;
737     pChild->timeout = device->timeout;
738     pChild->align = device->align;
739     pChild->devid = entry->devid;
740     pChild->params = entry->params;
741     pChild->fxns = *(DEV2_Fxns *)(entry->fxns);
742     ((SIO2_Handle)pChild)->model = ((SIO2_Handle)device)->model;
744     //Create frames and put them on the correct device queue.
745     // We only support ISSUERECLAIM mode so size = 0
746     Queue_construct(&((SIO2_Handle)pChild)->framelist, NULL); //Queue_new (&((SIO2_Handle)pChild)->framelist);
747     for (i=0; i < pChild->nbufs; i++) {
748         frame = DEV2_mkframe (0, 0, 0);
749         if (!frame)
750             return SYS_EALLOC;
751         Queue_put (Queue_handle(&((SIO2_Handle)pChild)->framelist), (Queue_Elem *) frame);
752     }
754     // open underlying device
755     status = DEV2_open (pChild, name);
756     if (status)
757         return status;
759     // use dev match to fetch function table pointer for DIB
760     name = DEV2_match ("/DIB", &entry);
761     if (entry == NULL) {
762         Log_info1 ("DEV2_match for DIB in DIB_open:", SIO2_ENODEV);
763         return SIO2_ENODEV;
764     }
765     pDevExt->pFxns = (DIB_Fxns *) entry->fxns;
767     // set IEC frame length table pointer -- change in
768     // subsequent control call (not defined) to add new IEC type
769     pDevExt->pIECFrameLength = (XDAS_UInt16 *) iecFrameLength;
771     status = DIB_FTABLE_reset (device,NULL);
772     if (status)
773         return status;
775     return status;
776 } // DIB_open
778 // -----------------------------------------------------------------------------
779 // Although this is void it is still needed since BIOS calls all DEV inits on
780 // startup.
782 Void DIB_init (Void)
784 } // DIB_init
786 // -----------------------------------------------------------------------------
787 // Notes:
788 //   1. DIB_reset is called prior to this function being called.(see DIB_reclaim)
789 //   2. (1) ==> sizeofBuffer is an integral # of 2byte samples.
790 //   3. (2) ==> if we use a request size which is divisor of sizeofBuffer there
791 //              will be no wrap-around when requesting data for scanning.
792 //   4. (3) ==> we meet the interface requirement for syncScan which has no
793 //              circular arithmetic.
795 Int DIB_getSync (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
797     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
798     DEV2_Handle             pChild = (DEV2_Handle)&pDevExt->child;
799     int status;
800     Uns timeout,  syncBufSize, syncRequestSize;
801     Int ibMode = pBufConfig->pBufStatus->mode; // read mode register once
802     Int deliverZeros;
804     //..........................................................................
806     // implement local timeout so that we don't get 'stuck' here when input
807     // is all zeros + lock
808     if (pDevExt->syncState == SYNC_NONE) {
809         Uns localTimeout;
810         // latch value before resetting to PAF_SOURCE_UNKNOWN
811         Int sourceProgram = pDevExt->sourceProgram;
813         pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
815         // if here then guaranteed to have fresh reset
817         if (pDevExt->sourceSelect == PAF_SOURCE_PCM || pDevExt->sourceSelect == PAF_SOURCE_DSD1 ||
818             pDevExt->sourceSelect == PAF_SOURCE_DSD2 || pDevExt->sourceSelect == PAF_SOURCE_DSD3) {
819             timeout = 0;
821             // no zero run counting in force modes since no scanning
822             pBufConfig->pBufStatus->zeroRun = 0;
823             pDevExt->zeroCount = 0;
824         }
825         else if ((pDevExt->sourceSelect == PAF_SOURCE_PCMAUTO) &&
826                  ((sourceProgram == PAF_SOURCE_UNKNOWN) || (sourceProgram == PAF_SOURCE_PCM))) {
827             // if sourceselect is PCMAUTO then
828             //    if current input is a bistream then scan for normal timeout period
829             //    if current input is unknown or PCM then transition immediately to PCM
830             // this provides for *no* lossed PCM, detection of bitstreams, but some noise
831             // is possible.
832             timeout = 0;
833             pDevExt->zeroCount = 0;
834         }
835         else
836             timeout = 2*pBufConfig->pBufStatus->unknownTimeout;
838         // force request size to be a divisor of sizeofBuffer
839         syncRequestSize = NOMINAL_XFERSIZE;
840         if (pBufConfig->stride > 2)
841             syncRequestSize *= pBufConfig->stride;
842         syncBufSize = pBufConfig->sizeofBuffer / ((int) (pBufConfig->sizeofBuffer/syncRequestSize));
844         if (timeout) {
845             status = DIB_FTABLE_issueChild (device, pBufConfig, syncBufSize, 0);
846             if (status)
847                 return status;
848         }
850         localTimeout = timeout;
851         while ((timeout) && (pDevExt->syncState != SYNC_ONE)) {
853             status = DIB_FTABLE_issueChild (device, pBufConfig, syncBufSize, 0);
854             if (status)
855                 return status;
857 #if 0 // debug
858             // Shows timing of Input Rx SIO reclaim during autodet
859             // ADC B5
860             {
861                 static Uint8 toggleState = 0;
862                 if (toggleState == 0)
863                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99);
864                 else
865                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99);
866                 toggleState = ~(toggleState);
867             }
868 #endif            
870             // get next block of data to scan
871             status = DIB_FTABLE_waitForData (device, pBufConfig, syncBufSize);
872             if (status)
873                 return status;
874             
875             // this function updates the tail pointer
876             status = DIB_FTABLE_syncScan (device, pBufConfig, &timeout);
877             if (status)
878                 return status;
880             // if input is zero, i.e. haven't decremented at all,
881             // then break out and use more logic and
882             if (localTimeout < syncBufSize) {
883                 // Should this be 2 *? MAW
884                 if (timeout == 2*pBufConfig->pBufStatus->unknownTimeout)
885                     break;
886             }
887             else
888             {
889                 Log_info3("DIB: Inside DIB_getSync with syncState != SYNC_ONE. localTimeout = %d, syncBufSize  = %d, timeout = %d", localTimeout,syncBufSize, timeout);
890                 localTimeout -= syncBufSize;
891             }
892         }
894         // if found sync then return to caller who will call 
895         // initFrame to get bitstream info and requestFrame for data
896         if (pDevExt->syncState != SYNC_NONE)
897             return 0;
899     } //pDevExt->syncState == SYNC_NONE
901     //..........................................................................
903     // set default to zero -- we assume decode calls will not be made
904     // before data is available since this must be master input. Will be changed below
905     // as needed
906     deliverZeros = 0;
908     if (pDevExt->syncState == SYNC_AUTO) {
909         timeout = pDevExt->pcmTimeout;
910         deliverZeros = 1;
911     }
913     // if in zero run, and heeding full zeroRun control, then return to unknown if # zeros > trigger/Restart
914     if (ibMode == MODE_DEFAULT) {
915         if ((pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger) ||
916             (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunRestart))
917             return DIBERR_SYNC;
918         // since we may have exited prematurely above we check timeout
919         if (timeout)
920             return DIBERR_SYNC;
921     }
922     // if heeding trigger but not restart then enter deliverZeros state of PCM
923     else if (ibMode == MODE_NO_ZERORUNRESTART) {
924         if (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger)
925             deliverZeros = 1;
926     }
928     // here if timeout to PCM (includes force PCM)
929     status = DIB_FTABLE_reset (device, pBufConfig);
930     if (status)
931         return status;
933     // hack -- try 32bit then 16bit if necessary
934     pBufConfig->sizeofElement = 4;
935     status = SIO2_ctrl (pChild,(Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
936     if(status) {
937         pBufConfig->sizeofElement = 2;
938         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
939         if(status)
940             return status;
941     }
943     // Force sizeofBuffer to be integral number of frame sizes. This ensures that the
944     // pcm buffers will not need a circular wrap-around. We prevent this because
945     // syncScan makes this assumption in order to perform an efficient scan.
946     {
947         int sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride*pDevExt->pcmFrameLength;
948         pBufConfig->sizeofBuffer = (pBufConfig->allocation)/sizeofStride*sizeofStride;
949     }
951     if (pDevExt->sourceSelect == PAF_SOURCE_DSD1 || pDevExt->sourceSelect == PAF_SOURCE_DSD2 ||
952         pDevExt->sourceSelect == PAF_SOURCE_DSD3)
953         pDevExt->sourceProgram = pDevExt->sourceSelect;
954     else
955         pDevExt->sourceProgram = PAF_SOURCE_PCM;
957     if (pDevExt->sourceSelect == PAF_SOURCE_PCM || pDevExt->sourceSelect == PAF_SOURCE_DSD1 ||
958         pDevExt->sourceSelect == PAF_SOURCE_DSD2 || pDevExt->sourceSelect == PAF_SOURCE_DSD3) {
959         pDevExt->syncState = SYNC_PCM_FORCED;
960         // set to one -- ensures that PCM decode calls made before data is
961         // available will result in zero output.
962         // (mostly needed for PA15 since, currently, all other frameworks
963         // require a frame of data before the first decode call.
964         deliverZeros = 1;
965     }
966     else
967         pDevExt->syncState = SYNC_PCM;
969     // update config struct
970     pBufConfig->deliverZeros = deliverZeros;
972     //..........................................................................
974     return 0;
975 } // DIB_getSync
977 // -----------------------------------------------------------------------------
979 int gWrapCtr=0;
980 Int DIB_issueChild (DEV2_Handle device, PAF_InpBufConfig  *pBufConfig, int size, int forTotal)
982     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *) device->object;
983     DEV2_Handle             pChild  = (DEV2_Handle) &pDevExt->child;
984     int                    bufEnd  = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
985     DEV2_Frame             *dstFrame;
986     int                    futureHead, status;
987     int                    i, sizes[2];
988     Ptr                    endAddr[2];
989    
992     // if seeking for total amount then adjust for difference
993     if (forTotal) 
994         size -= GetFutureAvail (pBufConfig);
996     // return success if we needn't make any requests
997     if (size <= 0)
998         return 0;
1000     // assume if eight channel then using optimized dMAX routine which requires
1001     // requests which are a mulitple of 8 to operate correctly. If not a proper
1002     // multiple then we increase the requested size as needed. This information
1003     // is communicated to other portions of DIB indirectly through the update
1004     // of the futureHead pointer (here) and head pointer (in reclaim). To these
1005     // other portions it is a don't care as we ensure enough data requested will
1006     // be available at, the now slightly deferred, reclaim point. We assume that
1007     // the buffer is a multiple of 8 and so, by using this single statement, we
1008     // ensure all requests are a mulitple 8 even if they need to be split across
1009     // the buffer wrap point.
1010     if (pBufConfig->stride == 8)
1011         size = (size + 7) & ~0x7;
1013     // convert to bytes
1014     size *= pBufConfig->sizeofElement;
1015     //size *= 4;
1017     // if request crosses circular buffer boundary then split into two requests
1018     futureHead = (int) pBufConfig->futureHead.pVoid + size;
1019     if (futureHead <= bufEnd) {
1020         sizes[0] = size;
1021         sizes[1] = 0;
1023         // If this request happens to be the rest of the buffer, then 
1024         // futureHead must be set to the beginning of the buffer.
1025         if (futureHead != bufEnd)
1026             endAddr[0] = (Ptr) futureHead;
1027         else
1028             endAddr[0] = pBufConfig->base.pVoid;
1029     }
1030     else {
1031         sizes[0] = bufEnd - (int) pBufConfig->futureHead.pVoid;
1032         sizes[1] = futureHead - bufEnd;
1033         endAddr[0] = pBufConfig->base.pVoid;
1034         endAddr[1] = (Ptr) ((int)pBufConfig->base.pVoid + sizes[1]);
1035     }
1037     for (i=0; i < 2; i++) {
1038         if (sizes[i]) {
1039             dstFrame = Queue_get (Queue_handle(&((SIO2_Handle) pChild)->framelist));
1040             if (dstFrame == (DEV2_Frame *)&((SIO2_Handle) pChild)->framelist)
1041                 return DIBERR_UNSPECIFIED;
1042             dstFrame->arg = (Arg) pBufConfig;
1044             dstFrame->addr = pBufConfig->futureHead.pVoid;
1045             dstFrame->size = sizes[i];
1046             Queue_put (pChild->todevice, (Queue_Elem *)dstFrame);
1047             status = DEV2_issue (pChild);
1048             if (status)
1049                 return DIBERR_UNSPECIFIED;
1051             pBufConfig->futureHead.pVoid = endAddr[i];
1053             if (i==1)
1054             {
1055                 gWrapCtr++;
1056                 Log_info4("DIB: Inside DIB_issueChild Wrap Around Point #%d, with Future Head: 0x%x, current addr: 0x%x, current size: %d", gWrapCtr, (xdc_IArg)pBufConfig->futureHead.pVoid, (xdc_IArg)dstFrame->addr, dstFrame->size );
1058             }
1059         }
1060     }
1062     return 0;
1063 } // DIB_issueChild
1065 // -----------------------------------------------------------------------------
1067 Int DIB_reclaimChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1069     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1070     DEV2_Handle              pChild = (DEV2_Handle)&pDevExt->child;
1071     DEV2_Frame              *srcFrame;
1072     int                     status, bufEnd;
1074     //Log_info3("DIB_reclaimChild.%d: Inside DEV2_reclaim(pChild) pChild = 0x%x DEV2_reclaim = 0x%x", __LINE__, pChild, &pChild->fxns.reclaim);
1075     //TRACE((&TR_MOD, "DIB_reclaimChild.%d: calling DEV2_reclaim(pChild) pChild = 0x%x DEV2_reclaim = 0x%x", __LINE__, pChild, &pChild->fxns.reclaim));
1076     status = DEV2_reclaim (pChild);
1077     if (status)
1078     {
1079         Log_info2("DIB_reclaimChild.%d DEV2_reclaim() returned (%d) DIBERR_UNSPECIFIED", __LINE__, status);
1080         //TRACE((&TR_MOD, "DIB_reclaimChild.%d DEV2_reclaim() returned (%d) DIBERR_UNSPECIFIED \n", __LINE__, status));
1081         return DIBERR_UNSPECIFIED;
1082     }
1084     //Log_info1("DIB_reclaimChild.%d calling Queue_get()", __LINE__);
1085     //TRACE((&TR_MOD, "DIB_reclaimChild.%d calling Queue_get()\n", __LINE__));
1086     srcFrame = Queue_get (pChild->fromdevice);
1087     //Log_info2("DIB_reclaimChild.%d calling Queue_put(), srcFrame = 0x%x", __LINE__, srcFrame);
1088     //TRACE((&TR_MOD, "DIB_reclaimChild.%d calling Queue_put(), srcFrame = 0x%x\n", __LINE__, srcFrame));
1089     Queue_put (Queue_handle(&((SIO2_Handle) pChild)->framelist), (Queue_Elem *)srcFrame);
1091     // Only for non-fill requests do we update ptrs
1092     if (srcFrame->addr != NULL) {
1093         //Log_info2("DIB_reclaimChild.%d update pointers with srcFrame->size = %d", __LINE__, srcFrame->size);
1094         //TRACE((&TR_MOD, "DIB_reclaimChild.%d update pointers\n", __LINE__));
1095         pBufConfig->head.pVoid = (Ptr) ((int)srcFrame->addr + srcFrame->size);
1097         // wrap, if necessary
1098         bufEnd = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
1099         if( (int) pBufConfig->head.pVoid >= bufEnd )
1100         {
1101             Log_info1("DIB_reclaimChild.%d wrap pointer", __LINE__);
1102             //TRACE((&TR_MOD, "DIB_reclaimChild.%d wrap pointer\n", __LINE__));
1103             pBufConfig->head.pVoid = (Ptr) ((int) pBufConfig->base.pVoid + (int) pBufConfig->head.pVoid - bufEnd);
1104         }
1105     }
1107     Log_info2("DIB_reclaimChild.%d exit with status = %d", __LINE__, status);
1108     //TRACE((&TR_MOD, "DIB_reclaimChild.%d exit with status = %d\n", __LINE__, status));
1110     return status;
1111 } // DIB_reclaimChild
1113 // -----------------------------------------------------------------------------
1114 // This function uses the local definition of frameLength and lengthofData in
1115 // pDevExt to request the next frame of data.
1117 Int DIB_requestFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1119     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1120     int status = 0;
1123     // if in steady state then update tail pointer to indicate we are done, i.e. no
1124     // longer own, the last frame of data.
1125     if (pDevExt->running > 1)
1126         IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pBufConfig->lengthofData);
1128     switch (pDevExt->syncState) {
1129         case SYNC_PCM:
1130         case SYNC_PCM_FORCED:
1131                     
1132             if (pDevExt->sourceSelect == PAF_SOURCE_DSD1)
1133                 pDevExt->frameLength = 256;
1134             else if (pDevExt->sourceSelect == PAF_SOURCE_DSD2)
1135                 pDevExt->frameLength = 128;
1136             else if (pDevExt->sourceSelect == PAF_SOURCE_DSD3)
1137                 pDevExt->frameLength = 64;
1138             else
1139                 pDevExt->frameLength = pDevExt->pcmFrameLength;
1141             pDevExt->lengthofData = pBufConfig->stride*pDevExt->frameLength;
1142             pDevExt->frameLength  = pDevExt->lengthofData;        
1144             // note that the following issueChild
1145             // doesn't *fetch* the data which will next be consumed,
1146             // but rather *replenishes* what's about to be consumed
1147             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1148             break;
1150         case SYNC_ONE:
1151             // for the first issue we need to set the tail pointer to the bitstream sync
1152             pBufConfig->pntr = pDevExt->pSync;
1153             IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pDevExt->headerSize);
1154             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->frameLength, 1);
1156             // HD codecs need extra time due to several factors
1157             //   time between first info call and starting output is non-negligible
1158             //   peak decoder MIPs
1159             //   reset time for decoders/ASPs
1160             if ((pDevExt->sourceProgram == PAF_SOURCE_DDP)   ||
1161                 (pDevExt->sourceProgram == PAF_SOURCE_DTSHD) ||
1162                 (pDevExt->sourceProgram == PAF_SOURCE_THD)   ||
1163                 (pDevExt->sourceProgram == PAF_SOURCE_DXP))
1164                 status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1166             pDevExt->syncState = SYNC_ONGOING;
1167             break;
1169         case SYNC_ONGOING:
1170             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1171             break;
1173     } //switch
1175     // update bufConfig with info for use in next reclaim call
1176     // the interface to DIB is based on a single frame. So the amount
1177     // of data requested in this issue is assumed to be what is wanted in the next
1178     // reclaim.
1179     pBufConfig->frameLength  = pDevExt->frameLength;
1180     pBufConfig->lengthofData = pDevExt->lengthofData;
1181     // enable to inspect input buffer.
1182     // if (pDevExt->lengthofData > 512)
1183     //     asm( " SWBP 0" );  // breakpoint
1186     if (pDevExt->running < 3)
1187         pDevExt->running++;
1189     // Goal is to align timing so synchronized with forthcoming
1190     // "DIB_waitForData (... pDevExt->lengthofData);"
1191     // in DIB_reclaim(), servicing PAF_SIO_REQUEST_NEWFRAME, for PAF_SOURCE_PCM/DSD?.
1192     // ** need to revise above DSD handling so it works w/ this calc. **
1193     {
1194         int futureAvail = GetFutureAvail (pBufConfig);
1195         // GetFutureAvail() returns 0 if full buffer requested or if no requests outstanding
1196         // -- 0 (empty) can't be right interpretation here, on account of foregoing issueChild()
1197         if( ! futureAvail)
1198             futureAvail = pBufConfig->sizeofBuffer / pBufConfig->sizeofElement; // total words in buffer
1199         pDevExt->numSamplesExtra = (XDAS_Int16) (futureAvail - pDevExt->frameLength);
1200     }
1202     return status;
1203 } // DIB_requestFrame
1205 // -----------------------------------------------------------------------------
1207 Int DIB_reset (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1209     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1210     DEV2_Handle              pChild = (DEV2_Handle)&pDevExt->child;
1211     int status, numChan;
1214     //?? Do we need a shutdown to handle queue problems?
1215     // or are there no problems since we use one frame
1216     status = DEV2_idle (pChild, 1);
1217     if(status)
1218         return status;
1220     if (pBufConfig) {
1221         int sizeofStride;
1222         pBufConfig->pntr       = pBufConfig->base;
1223         pBufConfig->head       = pBufConfig->base;
1224         pBufConfig->futureHead = pBufConfig->base;
1226         pBufConfig->lengthofData = 0;
1228         //devices must? support 2byte words
1229         pBufConfig->sizeofElement = 2;
1230         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
1231         if(status)
1232             return status;
1234         status = DEV2_ctrl (pChild, PAF_SIO_CONTROL_GET_NUMCHANNELS, (Arg) &numChan);
1235         if(status)
1236             return status;
1237         pBufConfig->stride = numChan;
1239         // compute and use *effective buffer size*
1240         sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride;
1241         pBufConfig->sizeofBuffer = (pBufConfig->allocation)/sizeofStride*sizeofStride;  //GJ: Debug - Account for EDMA padding
1243         //hack -- save status context for use in close
1244         pDevExt->pInpBufStatus = pBufConfig->pBufStatus;
1245         pBufConfig->pBufStatus->lastFrameFlag = 0;
1247         pDevExt->bufConfig = *pBufConfig;
1248         pDevExt->pSync = pBufConfig->base;
1249     }
1251     pDevExt->syncState = SYNC_NONE;
1252     pDevExt->scanState = SCANNED_NONE;
1253     pDevExt->pcmTimeout = 0;
1254     pDevExt->deferredError = 0;
1256     pDevExt->numSamplesSinceDTS = 0;
1257     pDevExt->numSamplesExtra = 0;
1259     pDevExt->headerSize = 0;
1260     pDevExt->running = 0;
1262     return 0;
1263 } // DIB_reset
1265 // -----------------------------------------------------------------------------
1266 // Notes:
1267 //   1. The amount of data to be scanned will not result in a buffer wrap-around
1268 //   2. (1) is currently met from the two locations that call this function
1269 //          a. DIB_getSync
1270 //          b. DIB_reclaim (for PCM)
1271 //   3. We require that pTimeout != NULL since we dereference to make a const
1273 Int DIB_syncScan (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout)
1275     DIB_DeviceExtension   * restrict pDevExt = (DIB_DeviceExtension *)device->object;
1276     MdInt * restrict pTail, * restrict pShadowTail, * restrict pSync;
1277     MdInt *pLocalTail, pc;
1278     XDAS_Int8   scanState;
1279     XDAS_UInt32 zeroCount;
1280     int stride, numLeft, i, datId;
1281     int status, foundDTS = 0;
1282     Uns scanCount, pageSize;
1283     PAF_SIO_IALG_Obj    *pObj = pDevExt->pSioIalg;
1284     PAF_SIO_IALG_Config *pAlgConfig = &pObj->config;
1285     const int timeoutChanged = (*pTimeout != 2 * pBufConfig->pBufStatus->unknownTimeout);
1286     MdInt DTSHDSubType;
1288     // .........................................................................
1290     // works for both SYNC_NONE and SYNC_PCM
1291     numLeft = min (*pTimeout, GetNumAvail(pBufConfig));
1293     pTail = pBufConfig->pntr.pMdInt;
1294     pShadowTail = pBufConfig->pntr.pMdInt;
1296     // if scratch buffer present then assume it is needed for paging
1297     pageSize = numLeft*pBufConfig->sizeofElement;
1299     Log_info3("DIB: Entered DIB_syncScan with pTail = 0x%x & numLeft = %d, timeout = %d", (xdc_IArg)pTail, numLeft, *pTimeout);
1302     if ((pAlgConfig->numRec > 1) && pAlgConfig->pMemRec[1].base && (pAlgConfig->pMemRec[1].size >= pageSize)) {
1303         pTail = pAlgConfig->pMemRec[1].base;
1304         datId = DAT_copy ((void *) pShadowTail, (void *) pTail, pageSize);
1305         DAT_wait (datId);
1306     }
1308     if (pBufConfig->sizeofElement == 4) {
1309         Log_info0("DIB: SyncScan - Inside pBufConfig->sizeofElement == 4");
1310         stride = 2;
1311         pTail += 1; // point at MSB
1312         pShadowTail += 1;
1313     }
1314     else
1315         stride = 1;
1317     // .........................................................................
1319     // scan until out of available data or a sync found
1320     scanCount = 0;
1321     zeroCount = pDevExt->zeroCount;
1322     scanState = pDevExt->scanState;
1323     pSync     = pDevExt->pSync.pMdInt;
1325     Log_info4("DIB: Entered DIB_syncScan with zeroCount = %d & scanState = %d, stride = %d, pSync = 0x%x", zeroCount, scanState, stride, (xdc_IArg)pSync);
1327     // scan until out of available data or a sync found
1328     for (i=0; i < numLeft; i++) {
1329         MdInt tail = pTail[i*stride];
1331         // assumes SCANNED_NONE = 0
1332         if (!scanState) {
1333             if (tail == IEC_PA) {
1334                 // since above code handles ongoing sync we are
1335                 //  safe to check for extended sync here. i.e.
1336                 //  two zeros before PA.
1337                 if (zeroCount >= 2) {
1338                     scanState = SCANNED_IEC_PA;
1339                     pSync = &pShadowTail[i*stride];
1340                 }
1341             }
1342             else if (tail == DTS14_SYNC_A) {
1343                 scanState = SCANNED_DTS14_SYNC_A;
1344                 pSync = &pShadowTail[i*stride];
1345             }
1346             else if (tail == DTS16_SYNC_A) {
1347                 scanState = SCANNED_DTS16_SYNC_A;
1348                 pSync = &pShadowTail[i*stride];
1349             }
1351             // limit count to prevent wrap around
1352             zeroCount = min (zeroCount+1,INT_MAX - 1);
1353             if (tail != 0x0000)
1354                 zeroCount = 0;
1356             // don't start counting until we get the first non-zero
1357             // sample while UNKNOWN. Note we don't have to worry
1358             // about the other scanCount increments since these
1359             // only occur after the first non-zero sample.
1360             //
1361             // so don't count unless
1362             //    . we are already started counting (in this call) ||
1363             //    . we started counting in an earlier scanForSync (timeout has changed) ||
1364             //    . the last sample was non-zero
1365             if (scanCount || (tail != 0x0000) || timeoutChanged)
1366             {
1367                 //Log_info3("DIB: DIB_syncScan scanCount = %d tail = %d timeoutChanged = %d", scanCount, tail, timeoutChanged);
1368                 scanCount += 1;
1369             }
1372             continue;
1373         }
1375         // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1377         switch (scanState) {
1379             case SCANNED_DTS16_SYNC_A:
1380                 if (tail == DTS16_SYNC_B) {
1381                     scanState = SCANNED_DTS16_SYNC_B;
1382                     scanCount += 1;
1383                 }
1384                 else
1385                     scanState = SCANNED_NONE;
1386                 break;
1388                 // wait for header data to get payload size via
1389                 // nblks/fsize
1390             case SCANNED_DTS16_SYNC_B:
1391                 // use extended sync
1393                 if ((short)(tail & 0xFC00) == DTS16_SYNC_C) {
1394                     scanState = SCANNED_DTS16_SYNC_C;
1395                     scanCount += 1;
1396                 }
1397                 else
1398                     scanState = SCANNED_NONE;
1399                 break;
1401                 // `````````````````````````````````````````````````````````````````````````
1402                 // check for 2nd word of DTS-14 sync
1403             case SCANNED_DTS14_SYNC_A:
1404                 if (tail == DTS14_SYNC_B) {
1405                     scanState = SCANNED_DTS14_SYNC_B;
1406                     scanCount += 1;
1407                 }
1408                 else
1409                     scanState = SCANNED_NONE;
1410                 break;
1412                 // check for 3rd word of DTS-14 sync
1413             case SCANNED_DTS14_SYNC_B:
1414                 // if here then looking for extended 38 bit sync
1415                 if ((short)(tail & 0xFFF0) == DTS14_SYNC_C) {
1416                     scanState = SCANNED_DTS14_SYNC_C;
1417                     scanCount += 1;
1418                 }
1419                 else
1420                     scanState = SCANNED_NONE;
1421                 break;
1423                 // wait for header data to get payload size via
1424                 //   nblks/fsize
1425             case SCANNED_DTS14_SYNC_C:
1426                 scanState = SCANNED_DTS14_SYNC_D;
1427                 scanCount += 1;
1428                 break;
1430                 // `````````````````````````````````````````````````````````````````````````
1431                 // if here then all of header is buffered
1432             case SCANNED_DTS16_SYNC_C:
1433             case SCANNED_DTS14_SYNC_D:
1434                 // update sync to point at beginning of DTS header as syncScanDTS uses this info
1435                 pDevExt->scanState    = scanState;
1436                 pDevExt->pSync.pMdInt = pSync;
1437                 status = DIB_FTABLE_syncScanDTS (device, pBufConfig, pTimeout, (XDAS_UInt16 *) &pShadowTail[i*stride]);
1438                 scanState = pDevExt->scanState;
1439                 if (status)
1440                     return status;
1441                 foundDTS = 1;
1442                 if (pDevExt->syncState == SYNC_ONE)
1443                     goto syncScanExit;
1444                 break;
1446                 // `````````````````````````````````````````````````````````````````````````
1448                 // note that the round about detection of IEC only
1449                 // happens for the first sync so the extra states are OK.
1450             case SCANNED_IEC_PA:
1451                 if (tail == IEC_PB) {
1452                     scanState = SCANNED_IEC_PB;
1453                     scanCount += 1;
1454                     Log_info0("DIB: SyncScan Inside case - SCANNED_IEC_PA - if path");
1455                 }
1456                 else
1457                 {
1458                     Log_info0("DIB: SyncScan Inside case - SCANNED_IEC_PA - else path");
1459                     scanState = SCANNED_NONE;
1460                 }
1461                 break;
1463             case SCANNED_IEC_PB:
1464                 // Update scanCount here since, at this point, we are confident that
1465                 // this is a proper IEC stream. Regardless if we ignore it our not.
1466                 // Therefore we want to properly signal that this data has been scanned.
1467                 scanCount += 1;
1469                 // check for IEC pause packets at this time and if required ignore them.
1470                 // By construction we are guaranteed to have tail=PC at this time.
1471                 if ((pBufConfig->pBufStatus->mode == MODE_NO_ZERORUNRESTART) ||
1472                     (pBufConfig->pBufStatus->mode == MODE_NO_ZERORUN)) {
1473                     MdInt pc = tail & 0x1F;
1475                     if ((pc == 0) || (pc == 3)) {
1476                         scanState = SCANNED_NONE;
1477                         break;
1478                     }
1479                 }
1481                 scanState = SCANNED_IEC_PC;
1482                 break;
1484             case SCANNED_IEC_PC:
1485                 pLocalTail = pSync;
1486                 IncrementPtr (pBufConfig, (Ptr *)  &pLocalTail, 2);
1487                 pc = *pLocalTail & 0x1F;
1488                 pDevExt->headerSize = IEC_HEADER_SIZE;
1490                 Log_info0("DIB: Sync Scan - Inside case: SCANNED_IEC_PC");
1491                 // Handle DTSHD subtype (LBR)
1492                 if (pc == 0x11) {
1493                     pDevExt->headerSize +=6;
1494                     DTSHDSubType = (*pLocalTail & 0x700)>>8;
1495                 }
1496                 // DDP or THD
1497                 if (pc == 21 || pc ==22) {
1498                     TRACE((&TR_MOD, "Dolby: useIECSubType is 0x%x.\n", pBufConfig->pBufStatus->useIECSubType));
1499                     if (pBufConfig->pBufStatus->useIECSubType == 1) {
1500                         unsigned char IECSubType = *pLocalTail & 0x60;
1501                         TRACE((&TR_MOD, "Dolby: IECSubType is 0x%x.\n", IECSubType));
1502                         if (IECSubType != 0) {
1503                             pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
1504                             pDevExt->frameLength = 0;
1505                         }
1506                     }
1507                 }
1508                 // don't know how to support other types
1509                 if (pc > 22)
1510                 {
1511                     Log_info1("DIB:  Unknown IEC type 0x%x encountered.\n", pc);
1512                     return DIBERR_SYNC;
1513                 }
1515                 pDevExt->syncState = SYNC_ONE;
1516                 pBufConfig->pntr.pMdInt = pSync;
1517                 pDevExt->sourceProgram = iecPafSource[pc];
1519                 Log_info2("source is %d.  pc is %d.", iecPafSource[pc], pc);
1520                 //TRACE((&TR_MOD, "source is %d.  pc is %d.\n", iecPafSource[pc], pc));
1521 #if 0 //No need to differentiate LBR subtype from DTSHD as DXP source program as LBR is handled inside DTSX decoder like other subtypes.
1522                 if (pc == 0x11 && DTSHDSubType == 3 && (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <=48000.0))
1523                     pDevExt->sourceProgram = PAF_SOURCE_DXP;    // LBR is 23
1524 #endif             
1525                 pDevExt->frameLength = pDevExt->pIECFrameLength[pc];
1526                 pDevExt->lengthofData = pDevExt->frameLength;
1527                 if (pc == 1)
1528                     pDevExt->frameLength = 4288;
1529                 else if (pc == 0x11) {
1530                     pDevExt->frameLength = (pDevExt->pIECFrameLength[pc] << DTSHDSubType);
1531                     pDevExt->lengthofData = pDevExt->frameLength;
1532                 }
1534                 goto syncScanExit;
1536         } // switch
1537     } // for
1539     // .............................................................................
1541 syncScanExit:
1542     Log_info4("DIB inside syncScanExit.  pTimeout = %d, scanCount = %d, zeroCount = %d, numLeft = %d", *pTimeout,scanCount, zeroCount, numLeft );
1543     pDevExt->zeroCount    = zeroCount;
1544     pDevExt->scanState    = scanState;
1545     pDevExt->pSync.pMdInt = pSync;
1547     if (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger)
1548         pBufConfig->pBufStatus->zeroRun = 1;
1549     else
1550         pBufConfig->pBufStatus->zeroRun = 0;
1552     // If detected an initial DTS sync in a previous buffer then add the
1553     // number of samples in this buffer to the tally.
1554     // TODO: should we add numLeft instead of lengthofData?
1555     if (!foundDTS && pDevExt->numSamplesSinceDTS)
1556         pDevExt->numSamplesSinceDTS += pBufConfig->lengthofData;
1558     if (*pTimeout > scanCount)
1559         *pTimeout -= scanCount;
1560     else {
1561         *pTimeout = 0;
1562         return 0;
1563     }
1565     // This flushes the current scanned buffer if a sync is not found
1566     // Note that this code is not executed when *pTimeout = 0. 
1567     // TODO: should this be moved elsewhere. Like in requestFrame?
1568     //       seems like this should be done in request frame for continuous modes
1569     //       and in getSync for traditional modes.
1570     //       What does it mean that this is not executed when we have timed out to PCM
1571     if (pDevExt->syncState == SYNC_NONE || pDevExt->syncState == SYNC_AUTO) {
1572         IncrementPtr (pBufConfig, (Ptr *) &pBufConfig->pntr.pMdInt, numLeft);
1573         return 0;
1574     }
1576     return 0;
1577 } // DIB_syncScan
1579 // -----------------------------------------------------------------------------
1580 // Assumes scanState is SCANNED_DTS16_SYNC_C or SCANNED_DTS14_SYNC_D
1582 Int DIB_syncScanDTS (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout, XDAS_UInt16 *pHeaderEnd)
1584     DIB_DeviceExtension  *pDevExt = (DIB_DeviceExtension *)device->object;
1585     Int sourceProgram = (pDevExt->scanState == SCANNED_DTS14_SYNC_D) ? PAF_SOURCE_DTS14  : PAF_SOURCE_DTS16;
1586     float sampleRate = PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD];
1587     MdInt *pLocalTail, pc, pd;
1588     int nblks;
1591     // compute repetition rate as predicted by DTS header
1592     pLocalTail = pDevExt->pSync.pMdInt;
1593     IncrementPtr (pBufConfig, (Ptr *) &pLocalTail, 2);
1594     pc = *pLocalTail;
1595     if (pDevExt->scanState == SCANNED_DTS16_SYNC_C)
1596         nblks = (pc & 0x01FC) >> 2;
1597     else {
1598         IncrementPtr (pBufConfig, (Ptr *) &pLocalTail, 1);
1599         pd = *pLocalTail;
1600         nblks = (pc & 0x7) << 4;
1601         nblks |= (pd & 0x3C00) >> 10;
1602     }
1604     // if samplerate > 44.1k and DTS16 bit CD then report as DTS-DVD
1605     // this is a work around to the possibility that DTS-DVD is being
1606     // sent but, due to the variance in input recording, we may have
1607     // missed the IEC header. This is predicated on the enable register
1608     if (pBufConfig->pBufStatus->reportDTS16AsDTSForLargeSampleRate &&
1609         (sampleRate > 44100) && (sourceProgram == PAF_SOURCE_DTS16))
1610         sourceProgram = PAF_SOURCE_DTS;
1612     // point at LSB, if neceesary, so that space calculation is correct
1613     if (pBufConfig->sizeofElement == 4)
1614         pHeaderEnd -= 1;
1616     // If in PCM mode then require double sync, at an appropriate spacing,
1617     // in order to determine DTS validity.
1618     if (pDevExt->syncState == SYNC_PCM) {
1619         int diff;
1621         // If we have started counting, i.e. found a previous sync,
1622         // then compute sync spacing.
1623         if (pDevExt->numSamplesSinceDTS) {
1624             // determine distance since last sync
1625             //    pHeaderEnd, which points at the end of the DTS header, is guaranteed
1626             //    to be in the active buffer. Whereas the pointer to the beginning of the header (pSync)
1627             //    may have occured in the previous buffer.
1628             diff = ((int) pHeaderEnd - (int) pBufConfig->pntr.pVoid);
1629             if (diff < 0)
1630                 diff += pBufConfig->sizeofBuffer;
1631             diff /= pBufConfig->sizeofElement;
1632             diff += pDevExt->numSamplesSinceDTS;
1634             // if spacing incorrect then reset sample count to
1635             // force next conditional to be true.
1636             if (diff != (nblks+1)*32*2)
1637                 pDevExt->numSamplesSinceDTS = 0;
1638         }
1640         // If this is the 1st sync detected or if this is the second sync
1641         // but the spacing between DTS syncs did not match that predicted by
1642         // NBLKS, then this is not DTS data. Therefore the previous DTS sync
1643         // word was not valid and so it is safe to reset the count based on
1644         // this secondary sync word. This latter sync may or may not be valid;
1645         // we don't know yet. In both cases init sync spacing count, reset
1646         // scan state, and continue. Note that there is a positive, albeit
1647         // quite small, probability of falsing in a pathological case where
1648         // the PCM data, interpreted as a DTS header and used to compute NBLKS,
1649         // actually matches the fake DTS syncs in the PCM file.
1650         if (!pDevExt->numSamplesSinceDTS) {
1651             diff = (int) pBufConfig->head.pVoid - (int) pHeaderEnd;
1652             if (diff <= 0)
1653                 diff += pBufConfig->sizeofBuffer;
1654             diff /= pBufConfig->sizeofElement;
1655             pDevExt->numSamplesSinceDTS = diff;
1656             pDevExt->scanState = SCANNED_NONE;
1657             return 0;
1658         }
1659     } //SYNC_PCM
1661     pDevExt->lengthofData = (nblks+1)*32*2;
1662     if (pDevExt->scanState == SCANNED_DTS16_SYNC_C)
1663         pDevExt->frameLength = pDevExt->lengthofData + 4;
1664     else
1665         pDevExt->frameLength = pDevExt->lengthofData + 6;
1667     pDevExt->syncState = SYNC_ONE;
1668     pBufConfig->pntr = pDevExt->pSync;
1669     pDevExt->sourceProgram = sourceProgram;
1671     return 0;
1672 } //DIB_syncScanDTS
1674 // -----------------------------------------------------------------------------
1675 // This function is responsible for verifying bitstream sync (if applicable) and
1676 // configuring the sizes of the next frame of data.
1678 Int DIB_initFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1680     DIB_DeviceExtension  * restrict pDevExt = (DIB_DeviceExtension *) device->object;
1681     MdInt * restrict pTail;
1682     MdInt pa, pb, pc;
1683     unsigned char DTSHDSubType;
1684     PAF_UnionPointer     ac3SearchPtr;
1687     // MID 810
1688     // TODO: is this needed anymore? can we combine above and this?
1689     // I don't think this is needed since pSync is guaranteed to be
1690     // valid under all cases where this function is called.
1691     if (!(pDevExt->scanState == SCANNED_DTS14_SYNC_D ||
1692           pDevExt->scanState == SCANNED_DTS16_SYNC_C ||
1693           pDevExt->scanState == SCANNED_IEC_PC ))
1694         return 0;
1696     // minimum possible distance from current IEC sync to next is 1856 words
1697     // capture this here before we update pSync following
1698     ac3SearchPtr = pDevExt->pSync; 
1700     // for steady state compute expected sync location
1701     if (pDevExt->syncState == SYNC_ONGOING) 
1702         IncrementPtr (pBufConfig, &pDevExt->pSync.pVoid, pBufConfig->lengthofData);
1704     pTail = pDevExt->pSync.pMdInt;
1705     pa = *pTail;
1706     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1707     pb = *pTail;
1708     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1709     pc = *pTail;
1710     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1712     switch (pDevExt->scanState) {
1713         // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1715         case SCANNED_DTS14_SYNC_D:
1716             // check sync (extended sync checked above for 1st sync)
1717             if ((pa != DTS14_SYNC_A) || (pb != DTS14_SYNC_B) || ((pc & 0xFC00) != (DTS14_SYNC_C & 0xFC00)))
1718                 return DIBERR_SYNC;
1719             break;
1721             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1723         case SCANNED_DTS16_SYNC_C:
1724             // check sync (extended sync checked above for 1st sync)
1725             if ((pa != DTS16_SYNC_A) || (pb != DTS16_SYNC_B))
1726                 return DIBERR_SYNC;
1727             break;
1729             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1731         case SCANNED_IEC_PC:
1732             // check for sync
1733             //    special handling for AC3 variable bit rate (VBR)
1734             //       start looking for sync at max payload sync location and
1735             //       scan forward. Note that getSync() has waited for
1736             //       sufficient data to arrive so that we can determine reliably
1737             //       the presence or absence of a correct sync.
1739             if ((pa != IEC_PA) || (pb != IEC_PB)) {
1740                 PAF_SIO_IALG_Obj    *pObj = pDevExt->pSioIalg;
1741                 PAF_SIO_IALG_Config *pAlgConfig = &pObj->config;
1742                 int scan1, scan2, searchIdx, datId;
1743                 const int bufEnd = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
1746                 // only extend IEC search in the case of AC3
1747                 if (pDevExt->sourceProgram != PAF_SOURCE_AC3)
1748                     return DIBERR_SYNC;
1750                 // move search ptr to earliest possible location of next sync
1751                 IncrementPtr (pBufConfig, &ac3SearchPtr.pVoid, 1856);
1753                 // compute number of samples between earliest possible sync location
1754                 // (ac3SearchPtr) and latest possible sync location (head)
1755                 scan1 = (int) pBufConfig->head.pVoid - (int) ac3SearchPtr.pVoid;
1756                 if (scan1 < 0) {
1757                     // here if search will wrap around so split search into two
1758                     // halves to accomodate circular buffer
1759                     scan1 = bufEnd - (int) ac3SearchPtr.pVoid;
1760                     scan2 = (int) pBufConfig->head.pVoid - (int) pBufConfig->base.pVoid;
1761                 }
1762                 else
1763                     scan2 = 0;
1765                 // page if necessary (assume so if second memRec present)
1766                 if (pAlgConfig->numRec > 1) {
1767                     // if invalid buffer or if page buffer not big enough for either split then error
1768                     if (!pAlgConfig->pMemRec[1].base ||
1769                         (pAlgConfig->pMemRec[1].size < max(scan1,scan2)))
1770                         return DIBERR_UNSPECIFIED;
1772                     pTail = (MdInt *) pAlgConfig->pMemRec[1].base;
1773                     datId = DAT_copy (ac3SearchPtr.pVoid, (void *) pTail, scan1);
1774                     DAT_wait (datId);
1775                 }
1776                 else
1777                     pTail = ac3SearchPtr.pMdInt;
1779                 // convert to number of words
1780                 scan1 /= pBufConfig->sizeofElement;
1782                 // if non-zero must be IEC header, otherwise sync error
1783                 // update pointer after check so that it remains
1784                 // pointed at first non-zero word when breaking
1785                 searchIdx = 0;
1786                 while (scan1--) {
1787                     if (*pTail != 0) {
1788                         // force skip of any possible split scan since we found non-zero word
1789                         scan2 = 0;
1790                         break;
1791                     }
1792                     *pTail++;
1793                     searchIdx++;
1794                 }
1796                 // perform second half of circular buffer search if necessary
1797                 if (scan2) {
1798                     // page if necessary, note no need to check valid buffer
1799                     // or space since this is ensured in first scan
1800                     if (pAlgConfig->numRec > 1) {
1801                         pTail = (MdInt *) pAlgConfig->pMemRec[1].base;
1802                         datId = DAT_copy (pBufConfig->base.pVoid, (void *) pTail, scan2);
1803                         DAT_wait (datId);
1804                     }
1805                     else
1806                         pTail = pBufConfig->base.pMdInt;
1808                     // convert to number of words
1809                     scan2 /= pBufConfig->sizeofElement;
1811                     while (scan2--) {
1812                         if (*pTail != 0)
1813                             break;
1814                         *pTail++;
1815                         searchIdx++;
1816                     }
1817                 }
1819                 // if using paging buffer then translate search pointer back into circular buffer
1820                 if (pAlgConfig->numRec > 1) {
1821                     pTail = ac3SearchPtr.pMdInt;
1822                     IncrementPtr (pBufConfig, (Ptr *) &pTail, searchIdx);
1823                 }
1825                 // update sync in expection of success, if it is not a sync then no
1826                 // harm since it will be ignored then reset
1827                 pDevExt->pSync.pMdInt = pTail;
1829                 // above search only scans for the first non-zero word.
1830                 // here is common check to make sure that non-zero data is an IEC sync.
1831                 pa = *pTail;
1832                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1833                 pb = *pTail;
1834                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1835                 pc = *pTail;
1836                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1837                 if ((pa != IEC_PA) || (pb != IEC_PB))
1838                     return DIBERR_SYNC;
1839             }
1841             // compute possible DTSHD sub type before masking pc
1842             DTSHDSubType = (pc & 0x700) >> 8;
1844             // mask pc to get data type only
1845             pc = pc & 0x1F;
1847             // don't know how to support other types
1848             // this also ensures that the below array access is bounded
1849             if (pc > 22)
1850                 return DIBERR_SYNC;
1852             // continuing frame must be same as current type otherwise
1853             // we return error to force reset of decode and input
1854             // classification state machines
1855             if (pDevExt->sourceProgram != iecPafSource[pc]) {
1856                 if (DTSHDSubType == 3 &&
1857                     (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <= 48000.0))  {
1858                     if (pDevExt->sourceProgram != PAF_SOURCE_DXP)
1859                         return DIBERR_SYNC;
1860                 }
1861                 else
1862                     return DIBERR_SYNC;
1863             }
1864             break;
1866             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1867     } //switch
1869     return 0;
1870 } // DIB_initFrame
1872 // -----------------------------------------------------------------------------
1874 Int DIB_waitForData (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 count )
1876     DIB_DeviceExtension  *pDevExt = (DIB_DeviceExtension *) device->object;
1877     DEV2_Handle            pChild = (DEV2_Handle) &pDevExt->child;
1878     Int status, lock;
1880     Log_info2("DIB_waitForData.%d count = %d", __LINE__, count);
1881     //TRACE((&TR_MOD, "DIB_waitForData.%d count = %d\n", __LINE__, count));
1883     while (GetNumAvail(pBufConfig) < count) {
1884         PAF_SIO_InputStatus inputStatus;
1886         // query underlying device for lock status & check lock override register
1887         // dont wait without lock
1888         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS, (Arg) &inputStatus);
1889         if (status)
1890         {
1891             Log_info2("DIB_waitForData.%d SIO2_ctrl() returned %d", __LINE__, status);
1892             //TRACE((&TR_MOD, "DIB_waitForData.%d SIO2_ctrl() returned %d\n", __LINE__, status));
1893             return status;
1894         }
1895         lock = inputStatus.lock;
1896 #ifndef IGNORE_LOCK_OVERRIDE
1897         if ((pBufConfig->pBufStatus->lockOverride & (XDAS_Int8)0x80) == 0)
1898         {
1899             Log_info1("DIB_waitForData.%d lock = lockOverride\n", __LINE__);
1900             //TRACE((&TR_MOD, "DIB_waitForData.%d lock = lockOverride\n", __LINE__));
1901             lock = pBufConfig->pBufStatus->lockOverride;
1902         }
1903 #endif
1904         if (!lock)
1905         {
1906             Log_info1("DIB_waitForData.%d no lock, return DIBERR_SYNC\n", __LINE__);
1907             //TRACE((&TR_MOD, "DIB_waitForData.%d no lock, return DIBERR_SYNC\n", __LINE__));
1908             return DIBERR_SYNC;
1909         }
1910         // check that decoding still requested -- allows for status
1911         // register to be updated via IOS to cancel autoProcessing
1912         if (pDevExt->pDecodeStatus) {
1913             if (pDevExt->pDecodeStatus->sourceSelect == PAF_SOURCE_NONE)
1914             {
1915                 Log_info1("DIB_waitForData.%d sourceSelect is NONE, return DIBERR_SYNC", __LINE__);
1916                 //TRACE((&TR_MOD, "DIB_waitForData.%d sourceSelect is NONE, return DIBERR_SYNC\n", __LINE__));
1917                 return DIBERR_SYNC;
1918             }
1919         }
1921         Log_info1("DIB_waitForData.%d calling DIB_FTABLE_reclaimChild()", __LINE__);
1922         //TRACE((&TR_MOD, "DIB_waitForData.%d calling DIB_FTABLE_reclaimChild()\n", __LINE__));
1923         status = DIB_FTABLE_reclaimChild (device, pBufConfig);
1924         if(status)
1925         {
1926             Log_info2("DIB_waitForData.%d DIB_FTABLE_reclaimChild() returned %d", __LINE__, status);
1927             //TRACE((&TR_MOD, "DIB_waitForData.%d DIB_FTABLE_reclaimChild() returned %d\n", __LINE__, status));
1928             return status;
1929         }
1930     }
1932     return 0;
1933 } // DIB_waitForData
1935 // -----------------------------------------------------------------------------
1936 #ifdef IEC_ENCODE
1938 // FS9 only supports PCM input so return error if not PCM.
1940 Int DIB_requestFrame_957 (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1942     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *) device->object;
1943     int i, head, tail, avail, status;
1946     if (pDevExt->sourceProgram != PAF_SOURCE_PCM)
1947         return DIBERR_SYNC;
1949     // if in steady state then update tail pointer to indicate we are done, i.e. no
1950     // longer own, the last frame of data. 
1951     if (pDevExt->running > 1)
1952         IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pBufConfig->lengthofData);
1954     pDevExt->lengthofData = pBufConfig->stride*pDevExt->pcmFrameLength;
1955     pDevExt->frameLength  = pDevExt->lengthofData;        
1957     // note that due to MID 1037 it is required to check the return status after this call
1958     status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1959     if (status)
1960         return status;
1962     // add extra input delay to account for peak encoder mips
1963     for (i=0; i < 4; i++) {
1964         head = (int) pBufConfig->futureHead.pVoid;
1965         tail = (int) pBufConfig->pntr.pVoid;
1966         // compute how much data we have including outstanding requests
1967         if (head >= tail)
1968             avail = head - tail;
1969         else
1970             avail = head - tail + pBufConfig->sizeofBuffer;
1972         // convert to words
1973         avail /= pBufConfig->sizeofElement;
1974         if (avail < 4*pBufConfig->lengthofData) {
1975             status = DIB_FTABLE_issueChild (device, pBufConfig, pBufConfig->lengthofData, 0);
1976             if (status)
1977                 return status;
1978         }
1979     }
1981     pBufConfig->frameLength  = pDevExt->frameLength;
1982     pBufConfig->lengthofData = pDevExt->lengthofData;
1984     if (pDevExt->running < 3)
1985         pDevExt->running++;
1987     return 0;
1988 } // DIB_requestFrame_957
1990 #endif /* IEC_ENCODE */
1992 // -----------------------------------------------------------------------------
1994 #ifdef DSD_OVER_SPDIF
1996 Int DIB_requestFrame_patch (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
1998     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1999     int status;
2001     status = DIB_requestFrame (device, pBufConfig);
2002     // For testing DSD over SPDIF i.e. 1 pin vs actual over 6 pin
2003     pDevExt->numSamplesExtra += pDevExt->lengthofData;
2004     pDevExt->lengthofData *=6;
2005     pDevExt->numSamplesExtra -= pDevExt->lengthofData;
2007     return status;
2008 } // DIB_requestFrame
2010 Int DIB_getSync_patch (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
2012     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
2013     DEV2_Handle             pChild = (DEV2_Handle)&pDevExt->child;
2014     int status;
2016     status=DIB_getSync (device, pBufConfig );
2017     if(status)
2018         return status;
2020     pBufConfig->sizeofElement = 2;
2021     status = SIO2_ctrl (pChild,(Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
2022     if (status)
2023         return status;
2025     // compute and use *effective buffer size*
2026     {
2027         int sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride;
2028         pBufConfig->sizeofBuffer = pBufConfig->allocation/sizeofStride*sizeofStride;
2029     }
2030     //..........................................................................
2032     return 0;
2033 } // DIB_getSync_patch
2035 #endif /* DSD_OVER_SPDIF */
2037 // -----------------------------------------------------------------------------