3 #include <stdint.h>
4 #include <limits.h> //INT_MAX
6 #include "ioData.h"
7 #include "ioBuff.h"
9 //#include "ioDataLoc.h"
11 #include <ti/sysbios/hal/Cache.h>
13 #define IODATA_NUM_MEM_ALLOCS 1
14 #define IODATA_INST_ALIGN 3
16 #define IODATA_NUM_BYTES_BITSTREAM 2
17 #define IODATA_NUM_BYTES_PCMSAMPLE 4
19 #define IODATA_ELEMENT_SIZE_DEF IODATA_NUM_BYTES_BITSTREAM
21 #define TRUE 1
22 #define FALSE 0
24 #define IODATA_SYNC_PC_MASK 0x1F
25 #define IODATA_SYNC_SUBTYPE_MASK 0x700
26 #define IODATA_SYNC_SUBTYPE_SHIFT 8
27 #define IODATA_SYNC_SUBTYPE_DTSHD 0x11
28 #define IODATA_SYNC_DDP 0x15
29 #define IODATA_SYNC_THD 0x16
31 #define IODATA_MIN_NUM_ZEROS_BEFORE_PA 2
32 #define IODATA_PREAMBLE_MAX_LEN 8 // TBD
33 #define IODATA_HEADER_LENGTH_IEC 4
34 #define IODATA_HEADER_CHECK_LENGTH_IEC 2 // For IEC, only look at 2 words to check SYNC.
36 #define IEC_PA ((uint_least16_t) 0xF872)
37 #define IEC_PB ((uint_least16_t) 0x4E1F)
38 #define DTS16_SYNC_A ((uint_least16_t) 0x7FFE)
39 #define DTS16_SYNC_B ((uint_least16_t) 0x8001)
40 #define DTS16_SYNC_C ((uint_least16_t) 0xFC00)
41 #define DTS14_SYNC_A ((uint_least16_t) 0x1FFF)
42 #define DTS14_SYNC_B ((uint_least16_t) 0xE800)
43 #define DTS14_SYNC_C ((uint_least16_t) 0x07F0)
45 #define DTS_BURST_TYPE_I 0x008B
46 #define DTS_BURST_TYPE_II 0x018C
47 #define DTS_BURST_TYPE_III 0x028D
48 #define DTS_BURST_TYPE_IV 0x0491
50 #define DTS_BURST_TYPE_IV_CBR 0x02
51 #define DTS_BURST_TYPE_IV_LBR 0x03
52 #define DTS_BURST_TYPE_IV_HBR 0x04
54 #define min(a, b) (((a) < (b)) ? (a) : (b))
55 #define max(a, b) (((a) > (b)) ? (a) : (b))
57 //IBMODE
58 enum
59 {
60 IBMODE_DEFAULT = 0,
61 IBMODE_NO_ZERORUNRESTART = 1,
62 IBMODE_NO_ZERORUN = 2
63 };
65 enum {
66 AUTODET_RESET = 0,
67 AUTODET_SYNC_SEARCH_INITIAL,
68 AUTODET_SYNC_SEARCH_PCM,
69 AUTODET_SYNC_CHECK_ONGOING
70 };
72 // scanState
73 enum
74 {
75 SCANNED_NONE,
76 SCANNED_IEC_PA,
77 SCANNED_IEC_PB,
78 SCANNED_IEC_PC,
79 SCANNED_IEC_PD,
80 SCANNED_DTS14_SYNC_A,
81 SCANNED_DTS14_SYNC_B,
82 SCANNED_DTS14_SYNC_C,
83 SCANNED_DTS14_SYNC_D,
84 SCANNED_DTS16_SYNC_A,
85 SCANNED_DTS16_SYNC_B,
86 SCANNED_DTS16_SYNC_C
87 };
89 typedef struct autoDet_s {
90 int_least32_t frameLength;
91 int_least32_t timeOutCntr;
92 uint_least32_t zeroCount;
93 uint_least32_t numElementsRcvd;
94 uint_least32_t distToFrameEnd;
96 uint_least16_t preambleRef[IODATA_PREAMBLE_MAX_LEN];
97 uint_least16_t preambleBuf[IODATA_PREAMBLE_MAX_LEN];
98 int_fast32_t preambleInd;
99 uint8_t headerLength;
100 uint8_t headerCheckLen;
102 uint_least16_t scanState;
103 uint_least16_t checkState;
105 int8_t ibMode;
106 int8_t timeOutStarted;
107 int8_t preambleStartsPrevBuf;
108 int8_t syncDetected;
109 int8_t syncLost;
110 int8_t completeFrameRcvd;
111 uint_least16_t syncState;
112 uint_least16_t bitStreamInfo;
113 uint_least16_t *bitStreamSyncPtr;
114 uint_least16_t *frameDataStartTemp;
115 uint_least16_t *frameDataStartConfirm;
116 } autoDet_t;
118 typedef struct ioDataDebug_s {
119 uint_least32_t numFramesRcvd;
120 uint_least32_t numBuffUnderflow;
121 uint_least32_t numSyncLost;
123 } ioDataDebug_t;
125 typedef struct ioDataInst_s {
126 autoDet_t autoDet;
127 ioDataDebug_t dbgStats;
128 uint_least16_t autoDetState;
129 uint_least16_t *IECframeLengths;
130 uint_least16_t frameLengthPCM;
131 uint_least16_t frameLengthDef;
132 //uint_least32_t frameLength; // frame length: number of elements in a frame
133 uint_least32_t numElementsRead; // number of elements to read from input buffer
134 uint_least32_t distToFrameEnd;
135 int8_t elementSize;
136 ioBuffHandle_t ioBuffHandle;
137 uint_least32_t zeroRunTrigger;
138 uint_least32_t zeroRunRestart;
139 int_least32_t timeOutCntr;
140 uint_least32_t unknownSourceTimeOut;
142 uint_least16_t *frameDataStart;
143 size_t frameDataSize;
144 uint8_t deliverZeros;
145 uint8_t ioBuffUnderFlow;
146 uint8_t syncTimeOut;
147 void *buff1;
148 void *buff2;
149 size_t size1;
150 size_t size2;
152 } ioDataInst_t;
155 // TODO: put this data structure somewhere, or use ioDataNumAlloc & ioDataAlloc to
156 // dynamically allocate memory.
157 //ioDataInst_t ioDataInst;
159 void autoDetection(ioDataInst_t * pIoDataInst);
160 void autoDetReset(ioDataInst_t * pIoDataInst);
164 /*******************************************************************************
165 * API function: ioDataNumAlloc
166 * Returns the maximum number of memory allocation requests that ioDataAlloc()
167 * requires.
168 *******************************************************************************/
169 int ioDataNumAlloc(void)
170 {
171 return (IODATA_NUM_MEM_ALLOCS);
172 } /* ioDataNumAlloc */
174 /*******************************************************************************
175 * API function: ioDataAlloc
176 * Returns a table of memory records that describe the size, alignment, type
177 * and memory space of all buffers required by I/O DATA component.
178 *******************************************************************************/
179 int ioDataAlloc(lib_mem_rec_t *mem_tbl)
180 {
181 mem_tbl[0].size = sizeof(ioDataInst_t);
182 mem_tbl[0].alignment = IODATA_INST_ALIGN;
183 mem_tbl[0].type = LIB_PMEM_SLOW;
184 mem_tbl[0].base = NULL;
186 return (IODATA_NO_ERR);
187 } /* ioDataAlloc */
189 /*******************************************************************************
190 * API function: ioDataCreate
191 * Create an I/O DATA instance.
192 *******************************************************************************/
193 int ioDataCreate(ioDataHandle_t *handle, const lib_mem_rec_t *mem_tbl)
194 {
195 ioDataInst_t *inst;
197 if( (mem_tbl[0].size < sizeof(ioDataInst_t))
198 ||libChkAlign(mem_tbl[0].base, IODATA_INST_ALIGN) ) {
199 // to add: check memory type
200 return (IODATA_ERR_MEMORY);
201 }
203 inst = (ioDataInst_t *)mem_tbl[0].base;
205 *handle = (ioDataHandle_t)inst;
207 return (IODATA_NO_ERR);
208 } /* ioDataCreate */
210 /*=============================================================================
211 * API function: this function initializes I/O data processing.
212 =============================================================================*/
213 int ioDataInit(ioDataHandle_t handle, ioDataParam_t *cfgParams)
214 {
215 ioDataInst_t *pIoDataInst = (ioDataInst_t *)handle;
217 if(cfgParams == NULL) {
218 return (IODATA_ERR_BAD_PARAMS);
219 }
221 pIoDataInst->ioBuffHandle = cfgParams->ioBuffHandle;
222 pIoDataInst->IECframeLengths = cfgParams->frameLengthsIEC;
223 pIoDataInst->frameLengthPCM = cfgParams->frameLengthPCM;
224 pIoDataInst->frameLengthDef = cfgParams->frameLengthDef;
225 pIoDataInst->autoDet.ibMode = cfgParams->ibMode;
226 pIoDataInst->zeroRunRestart = cfgParams->zeroRunRestart;
227 pIoDataInst->zeroRunTrigger = cfgParams->zeroRunTrigger;
228 pIoDataInst->unknownSourceTimeOut = cfgParams->unknownSourceTimeOut*2;
229 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
230 pIoDataInst->dbgStats.numSyncLost = 0;
231 pIoDataInst->ioBuffUnderFlow = FALSE;
232 pIoDataInst->syncTimeOut = FALSE;
234 autoDetReset(pIoDataInst);
236 return IODATA_NO_ERR;
237 } /* ioDataInit */
240 /*=============================================================================
241 * API function: main function of I/O DATA component processing.
242 =============================================================================*/
243 int ioDataProcess(ioDataHandle_t ioDataHandle)
244 {
245 void *buff1, *buff2;
246 size_t size1, size2;
247 int status;
248 ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
250 // Get read pointers (or sub-buffers) of the input buffer
251 status = ioBuffGetReadPtrs(pIoDataInst->ioBuffHandle,
252 pIoDataInst->numElementsRead*pIoDataInst->elementSize,
253 &buff1, &size1, &buff2, &size2);
254 if(status == IOBUFF_ERR_UNDERFLOW) {
255 pIoDataInst->ioBuffUnderFlow = TRUE;
256 pIoDataInst->dbgStats.numBuffUnderflow += 1;
258 /* skip processing since there is no enough data to process */
259 return IODATA_ERR_IOBUF_UNDERFLOW;
260 }
262 // Store read pointers and sizes to instance for auto-detection to read
263 pIoDataInst->ioBuffUnderFlow = FALSE;
264 pIoDataInst->buff1 = buff1;
265 pIoDataInst->buff2 = buff2;
266 pIoDataInst->size1 = size1;
267 pIoDataInst->size2 = size2;
269 autoDetection(pIoDataInst);
271 return IODATA_NO_ERR;
272 } /* ioDataProcess */
275 /*=============================================================================
276 * API function - this function marks the sub-buffers provided by I/O BUFF as
277 * read complete. It makes API call to the associated I/O BUFF component to mark
278 * the data as reading completed.
279 =============================================================================*/
280 int ioDataReadComplete(ioDataHandle_t ioDataHandle)
281 {
282 ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
284 // If the associated I/O buffer underflows, i.e. no enough data to read, do not
285 // call I/O BUFF API to mark read complete.
286 if(pIoDataInst->ioBuffUnderFlow) {
287 return IODATA_ERR_IOBUF_UNDERFLOW;
288 }
290 ioBuffReadComplete(pIoDataInst->ioBuffHandle, pIoDataInst->buff1, pIoDataInst->size1);
292 if(pIoDataInst->buff2 != NULL) {
293 ioBuffReadComplete(pIoDataInst->ioBuffHandle, pIoDataInst->buff2, pIoDataInst->size2);
294 }
296 return IODATA_NO_ERR;
297 } /* ioDataReadComplete */
300 /*=============================================================================
301 * API function - this function allows framework to dynamically control I/O data
302 * component or get information from it.
303 =============================================================================*/
304 int ioDataControl(ioDataHandle_t ioDataHandle, ioDataCtl_t *ioDataCtl)
305 {
306 ioBuffInfo_t ioBuffInfo;
308 ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
310 switch (ioDataCtl->code)
311 {
313 // case IODATA_CTL_SET_ELEMENT_SIZE:
314 // pIoDataInst->elementSize = ioDataCtl->param.frameInfo.elementSize;
315 // break;
317 case IODATA_CTL_SET_PCM_FRAME_LENGTH:
318 pIoDataInst->numElementsRead = pIoDataInst->frameLengthPCM = ioDataCtl->param.frameLengthPcm;
319 break;
321 case IODATA_CTL_GET_INPBUFFINFO:
322 ioBuffGetInfo(pIoDataInst->ioBuffHandle, &ioBuffInfo);
323 ioDataCtl->param.dataReadInfo.buffBase = ioBuffInfo.base;
324 ioDataCtl->param.dataReadInfo.buffSize = ioBuffInfo.size;
325 ioDataCtl->param.dataReadInfo.startAddress = pIoDataInst->frameDataStart;
326 ioDataCtl->param.dataReadInfo.frameSize = pIoDataInst->frameDataSize;
327 break;
329 case IODATA_CTL_GET_AUTODET_STATUS:
330 ioDataCtl->param.autoDetStats.syncState = pIoDataInst->autoDet.syncState;
331 ioDataCtl->param.autoDetStats.deliverZeros = pIoDataInst->deliverZeros;
332 ioDataCtl->param.autoDetStats.bitStreamInfo = pIoDataInst->autoDet.bitStreamInfo;
333 ioDataCtl->param.autoDetStats.syncTimeOut = pIoDataInst->syncTimeOut;
334 break;
335 /*
336 case IODATA_CTL_GET_STEAM_INFO:
337 break;
338 */
339 default:
340 break;
341 }
343 return IODATA_NO_ERR;
344 } /* ioDataControl */
346 //========== internal functions - to be moved to a different file ==========
347 void autoDetSyncScan(ioDataInst_t * pIoDataInst);
348 void autoDetSyncCheck(ioDataInst_t * pIoDataInst);
349 void syncScan(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet);
350 void syncCheck(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet);
351 void syncCheckInit(ioDataInst_t * pIoDataInst);
352 void syncScanPcmInit(ioDataInst_t * pIoDataInst);
354 /*=============================================================================
355 * Main function of auto-detection of the I/O DATA component.
356 =============================================================================*/
357 void autoDetection(ioDataInst_t * pIoDataInst)
358 {
359 switch(pIoDataInst->autoDetState)
360 {
361 case AUTODET_SYNC_SEARCH_INITIAL:
362 /* Search for SYNC the first time */
363 autoDetSyncScan(pIoDataInst);
365 pIoDataInst->syncTimeOut = FALSE;
367 if(pIoDataInst->autoDet.syncDetected) {
368 syncCheckInit(pIoDataInst); // prepare for SYNC checking in subsequent frames
370 pIoDataInst->autoDet.frameDataStartConfirm = pIoDataInst->autoDet.frameDataStartTemp;
371 pIoDataInst->autoDet.syncState = IODATA_SYNC_ONE; // found SYNC once and to be verified
372 pIoDataInst->autoDetState = AUTODET_SYNC_CHECK_ONGOING;
373 }
374 /* Check time out counter if SYNC is not found:
375 - if autoDet.timeOutStarted == FALSE (no non-zero data has been received), look at pIoDataInst->timeOutCntr
376 - if autoDet.timeOutStarted == TRUE, look at pIoDataInst->autoDet.timeOutCntr
377 */
378 else if( ((!pIoDataInst->autoDet.timeOutStarted) && (pIoDataInst->timeOutCntr <= 0))
379 || (pIoDataInst->autoDet.timeOutCntr <= 0) ) {
380 /* Time out, decide whether to reset or go to PCM */
381 if ( (pIoDataInst->autoDet.ibMode == IBMODE_DEFAULT)
382 &&(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunRestart) ) {
383 /* Reset if zero-run is long enough */
384 autoDetReset(pIoDataInst);
385 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
386 pIoDataInst->syncTimeOut = TRUE;
387 }
388 else {
389 // inform decoder where to read PCM data
390 pIoDataInst->frameDataStart = pIoDataInst->buff1;
391 pIoDataInst->frameDataSize = pIoDataInst->size1;
392 if(pIoDataInst->buff2 != NULL) {
393 pIoDataInst->frameDataSize += pIoDataInst->size2;
394 }
396 // Go to PCM scanning - to play out PCM and keep scanning for SYNC
397 syncScanPcmInit(pIoDataInst);
398 pIoDataInst->autoDet.syncState = IODATA_SYNC_PCM;
399 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_PCM;
400 }
401 }
402 break;
404 case AUTODET_SYNC_SEARCH_PCM:
405 /* Search for SYNC while PCM is played out */
406 autoDetSyncScan(pIoDataInst);
408 /* Check if SYNC is detected or there is zero-run */
409 if(pIoDataInst->autoDet.syncDetected) {
410 autoDetReset(pIoDataInst);
411 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
412 }
413 else {
414 // inform decoder where to read PCM data
415 pIoDataInst->frameDataStart = pIoDataInst->buff1;
416 pIoDataInst->frameDataSize = pIoDataInst->frameLengthPCM*pIoDataInst->elementSize;
418 pIoDataInst->deliverZeros = FALSE;
420 if(pIoDataInst->autoDet.ibMode == IBMODE_DEFAULT) {
421 if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunTrigger) {
422 pIoDataInst->deliverZeros = TRUE;
423 }
425 if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunRestart) {
426 /* Reset if zero-run is long enough */
427 autoDetReset(pIoDataInst);
428 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
429 }
430 }
431 else if(pIoDataInst->autoDet.ibMode == IBMODE_NO_ZERORUNRESTART) {
432 if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunTrigger) {
433 pIoDataInst->deliverZeros = TRUE;
434 }
435 }
436 else {
437 // ibMode = IBMODE_NO_ZERORUN. Stay in this state and do nothing
438 }
439 }
441 break;
443 case AUTODET_SYNC_CHECK_ONGOING:
444 autoDetSyncCheck(pIoDataInst);
446 /* Check if a full frame has been received and if so, check if SYNC is maintained */
447 if(pIoDataInst->autoDet.completeFrameRcvd) {
448 if(pIoDataInst->autoDet.syncDetected) {
449 pIoDataInst->autoDet.syncState = IODATA_SYNC_BITSTREAM;
450 pIoDataInst->autoDet.completeFrameRcvd = FALSE;
452 // Inform decoder to read data from the beginning of current frame (after the preamble)
453 // Note: this address could be 1-word pass the end of input buffer and therefore needs
454 // to be wrapped around by ioBuffWrapPointer().
455 pIoDataInst->frameDataStart = ioBuffWrapPointer(pIoDataInst->ioBuffHandle,
456 pIoDataInst->autoDet.frameDataStartConfirm);
457 pIoDataInst->frameDataSize = pIoDataInst->autoDet.frameLength*pIoDataInst->elementSize;
459 // Store the beginning address of data in current frame (not including the preamble)
460 pIoDataInst->autoDet.frameDataStartConfirm = pIoDataInst->autoDet.frameDataStartTemp;
461 pIoDataInst->dbgStats.numFramesRcvd += 1;
463 // re-initialize for SYNC check
464 syncCheckInit(pIoDataInst);
465 }
466 else {
467 pIoDataInst->dbgStats.numSyncLost += 1; // what else needs to be done???
468 autoDetReset(pIoDataInst);
469 pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
470 pIoDataInst->autoDet.syncState = IODATA_SYNC_NONE;
471 }
472 }
473 else {
474 ; //pIoDataInst->autoDet.syncState = IODATA_SYNC_CHECK;
475 }
476 break;
478 default: break;
479 }
481 } /* autoDetection */
483 /*=============================================================================
484 * This function resets auto-detection.
485 =============================================================================*/
486 void autoDetReset(ioDataInst_t * pIoDataInst)
487 {
488 pIoDataInst->deliverZeros = FALSE;
489 pIoDataInst->autoDet.zeroCount = 0;
490 pIoDataInst->autoDet.syncState = IODATA_SYNC_NONE;
491 pIoDataInst->autoDet.scanState = SCANNED_NONE;
492 pIoDataInst->autoDet.timeOutStarted = FALSE;
493 pIoDataInst->autoDet.syncDetected = FALSE;
494 pIoDataInst->autoDet.timeOutCntr = pIoDataInst->unknownSourceTimeOut;
495 //pIoDataInst->autoDet.timeOutCntr = pIoDataInst->unknownSourceTimeOut*20;
496 pIoDataInst->numElementsRead = pIoDataInst->frameLengthDef;
497 pIoDataInst->elementSize = IODATA_ELEMENT_SIZE_DEF;
499 pIoDataInst->timeOutCntr = pIoDataInst->unknownSourceTimeOut;
500 //pIoDataInst->timeOutCntr = pIoDataInst->unknownSourceTimeOut*20;
501 pIoDataInst->dbgStats.numFramesRcvd = 0;
502 pIoDataInst->dbgStats.numBuffUnderflow = 0;
503 } /* autoDetReset */
505 /*=============================================================================
506 * This function re-initializes auto-detection for scanning SYNC in PCM data
507 =============================================================================*/
508 void syncScanPcmInit(ioDataInst_t * pIoDataInst)
509 {
510 //pIoDataInst->deliverZeros = FALSE;
511 //pIoDataInst->autoDet.zeroCount = 0;
512 //pIoDataInst->autoDet.scanState = SCANNED_NONE;
513 //pIoDataInst->autoDet.timeOutStarted = FALSE;
514 //pIoDataInst->autoDet.syncDetected = FALSE;
515 //pIoDataInst->autoDet.timeOutCntr = pIoDataInst->unknownSourceTimeOut*2;
516 //pIoDataInst->autoDet.timeOutCntr = pIoDataInst->unknownSourceTimeOut*20;
517 pIoDataInst->numElementsRead = pIoDataInst->frameLengthPCM;
518 //pIoDataInst->timeOutCntr = pIoDataInst->unknownSourceTimeOut*2;
519 //pIoDataInst->timeOutCntr = pIoDataInst->unknownSourceTimeOut*20;
520 pIoDataInst->elementSize = IODATA_NUM_BYTES_PCMSAMPLE;
521 } /* syncScanPcmInit */
523 /*=============================================================================
524 * Initialization for checking sync in subsequent bitstream frames.
525 =============================================================================*/
526 void syncCheckInit(ioDataInst_t * pIoDataInst)
527 {
528 int i;
529 uint_least16_t pc = pIoDataInst->autoDet.bitStreamInfo & IODATA_SYNC_PC_MASK;
531 pIoDataInst->autoDet.frameLength = pIoDataInst->IECframeLengths[pc];
532 pIoDataInst->autoDet.distToFrameEnd = pIoDataInst->autoDet.frameLength
533 - pIoDataInst->autoDet.numElementsRcvd;
535 //#ifdef ADJUST_XFER_SIZE_AFTER_AUTODET
536 #if 1
537 // Adjust the read size such that next read will contain the preamble of next
538 // frame at the end of the read. For first frame after SYNC is detected, the
539 // read size will be smaller than frame size. For subsequent frames, the read
540 // size will be equal to the frame size.
541 pIoDataInst->numElementsRead = pIoDataInst->autoDet.distToFrameEnd
542 + pIoDataInst->autoDet.headerLength;
543 #endif
545 pIoDataInst->autoDet.preambleStartsPrevBuf = FALSE;
546 pIoDataInst->autoDet.completeFrameRcvd = FALSE;
547 pIoDataInst->autoDet.syncDetected = FALSE;
548 pIoDataInst->autoDet.preambleInd = 0;
550 for(i=0; i<pIoDataInst->autoDet.headerLength; i++)
551 {
552 pIoDataInst->autoDet.preambleBuf[i] = 0x0;
553 }
554 } /* syncCheckInit */
557 /*=============================================================================
558 * This function scans for sync word (preamble) in the input buffer while
559 * checking for time out. It calls subroutine syncScan to scan the data.
560 *
561 * The read pointer(s) to the input buffer and the read sizes are provided by
562 * the I/O BUFF component and stored in auto-detection instance. The read
563 * pointers are also refered as sub-buffers.
564 *
565 * NOte: Since the input buffer may wrapp around, there may be two sub-buffers,
566 * one at the end of the input buffer and the other at the beginning,
567 * provided to auto-detection. In this case, syncScan subroutine will be
568 * called twice.
569 =============================================================================*/
570 void autoDetSyncScan(ioDataInst_t * pIoDataInst)
571 {
572 /* scan first sub-buffer for sync */
573 if((pIoDataInst->buff1 != NULL) && (pIoDataInst->size1 != 0)) {
574 syncScan(pIoDataInst->buff1, pIoDataInst->size1, pIoDataInst->elementSize,
575 &pIoDataInst->autoDet);
576 pIoDataInst->timeOutCntr -= pIoDataInst->size1/pIoDataInst->elementSize;
577 }
579 /* check if sync word is found in the first sub-buffer */
580 if(pIoDataInst->autoDet.syncDetected) {
581 /* skip scanning second sub-buffer if sync is detected */
582 if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
583 /* update the number of received elements in current frame */
584 pIoDataInst->autoDet.numElementsRcvd += pIoDataInst->size2;
585 }
586 }
587 else if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
588 /* scan second sub-buffer if there are two sub-buffers */
589 syncScan(pIoDataInst->buff2, pIoDataInst->size2, pIoDataInst->elementSize,
590 &pIoDataInst->autoDet);
591 pIoDataInst->timeOutCntr -= pIoDataInst->size2/pIoDataInst->elementSize;
592 }
593 } /* ioDataAutoDetSyncScan */
595 /*=============================================================================
596 * This function scans for sync word (preamble) in the provided sub-buffer.
597 =============================================================================*/
598 void syncScan(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet)
599 {
600 uint_least16_t *pbuf;
601 int i, stride, scanCount, zeroCount;
602 uint_least16_t scanState;
603 uint_least16_t *syncPtr;
605 pbuf = (uint_least16_t *)buff;
607 /* check element size */
608 if (elementSize == IODATA_NUM_BYTES_PCMSAMPLE) {
609 /* skip every other 16-bit number and only look at MSB of PCM samples */
610 stride = IODATA_NUM_BYTES_PCMSAMPLE / sizeof(uint_least16_t);
611 pbuf += 1;
612 }
613 else {
614 stride = 1;
615 }
617 /* get ready for scanning */
618 scanCount = 0;
619 zeroCount = pDet->zeroCount;
620 scanState = pDet->scanState;
622 /* check if part of the sync words (preamble) are found in previous call */
623 if(scanState != SCANNED_NONE) {
624 /* count this sub-buffer in the number of received elements in current frame */
625 pDet->numElementsRcvd += size/sizeof(uint_least16_t);
626 }
628 /* scan until out of available data or sync is found */
629 for (i=0; i < size/elementSize; i+=stride) {
630 uint_least16_t tail = pbuf[i];
632 if (scanState == SCANNED_NONE) {
633 if (tail == IEC_PA) {
634 /* make sure there are some zeros before PA. */
635 if (zeroCount >= IODATA_MIN_NUM_ZEROS_BEFORE_PA) {
636 scanState = SCANNED_IEC_PA;
637 syncPtr = &pbuf[i]; /* mark the position of PA */
638 }
639 }
641 if(scanState != SCANNED_NONE) {
642 /* Found first sync word. Save its address */
643 pDet->bitStreamSyncPtr = syncPtr;
645 /* number of elements in current frame that have been received
646 * in this sub-buffer, including the preamble (sync words). */
647 pDet->numElementsRcvd = size/sizeof(uint_least16_t) - i;
648 pDet->preambleRef[0] = tail; /* save this word for sync check */
649 }
651 /* update zero count and prevent wrap around */
652 zeroCount = min (zeroCount+1,INT_MAX - 1);
653 if (tail != 0x0000) {
654 zeroCount = 0;
655 }
657 // don't start counting until we get the first non-zero
658 // sample while UNKNOWN. Note we don't have to worry
659 // about the other scanCount increments since these
660 // only occur after the first non-zero sample.
661 //
662 // so don't count unless one of the following is true:
663 // . the last sample was non-zero
664 // . we are already started counting (in this call)
665 // . we started counting in an earlier scanForSync (timeout has changed)
666 //if (scanCount || (tail != 0x0000) || pDet->timeOutStarted) {
667 // scanCount += 1;
668 //}
670 if (tail != 0x0000) {
671 scanCount += 1;
672 pDet->timeOutStarted = TRUE;
673 }
674 else if (scanCount || pDet->timeOutStarted) {
675 scanCount += 1;
676 }
677 else {
678 // don't increment scanCount
679 }
681 continue;
682 }
684 // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
686 switch (scanState) {
688 case SCANNED_IEC_PA:
689 if (tail == IEC_PB) {
690 scanState = SCANNED_IEC_PB;
691 scanCount += 1;
692 pDet->preambleRef[1] = tail; /* save this word for sync check */
693 }
694 else {
695 scanState = SCANNED_NONE;
696 }
697 break;
699 case SCANNED_IEC_PB:
700 // Update scanCount here since, at this point, we are confident that
701 // this is a proper IEC stream. Regardless if we ignore it our not.
702 // Therefore we want to properly signal that this data has been scanned.
703 scanCount += 1;
705 // check for IEC pause packets at this time and if required ignore them.
706 // By construction we are guaranteed to have tail=PC at this time.
707 if ((pDet->ibMode == IBMODE_NO_ZERORUNRESTART) ||
708 (pDet->ibMode == IBMODE_NO_ZERORUN)) {
709 if ( ((tail&0x1F) == 0) || ((tail&0x1F) == 3)) {
710 scanState = SCANNED_NONE;
711 break;
712 }
713 }
715 // fall through to SCANNED_IEC_PC:
716 pDet->preambleRef[2] = tail; /* save this word for sync check */
717 pDet->bitStreamInfo = tail;
718 scanState = SCANNED_IEC_PC;
719 break;
721 case SCANNED_IEC_PC:
722 //pDevExt->headerSize = IEC_HEADER_SIZE;
723 pDet->preambleRef[3] = tail; /* save this word for sync check */
724 pDet->headerLength = IODATA_HEADER_LENGTH_IEC;
725 pDet->headerCheckLen = IODATA_HEADER_CHECK_LENGTH_IEC;
726 scanState = SCANNED_IEC_PD;
728 break;
730 case SCANNED_IEC_PD:
731 // wait untill full header is received
732 pDet->syncDetected = TRUE;
733 pDet->frameDataStartTemp = &pbuf[i];
735 break;
737 } /* switch */
739 if(pDet->syncDetected) {
740 break; // break from for loop
741 }
742 } /* for */
744 pDet->zeroCount = zeroCount;
745 pDet->scanState = scanState;
746 if (pDet->timeOutCntr > scanCount) {
747 pDet->timeOutCntr -= scanCount;
748 }
749 else {
750 pDet->timeOutCntr = 0;
751 }
753 } /* syncScan */
756 /*=============================================================================
757 * This function checks for sync word (preamble) at the expected location in the
758 * input buffer. Similar to ioDataAutoDetSyncScan, it looks into two sub-buffers
759 * when the input buffer wraps around.
760 *
761 =============================================================================*/
762 void autoDetSyncCheck(ioDataInst_t * pIoDataInst)
763 {
764 // look into first sub-buffer for preamble
765 if((pIoDataInst->buff1 != NULL) && (pIoDataInst->size1 != 0)) {
766 syncCheck(pIoDataInst->buff1, pIoDataInst->size1, pIoDataInst->elementSize,
767 &pIoDataInst->autoDet);
768 }
770 // check if first sub-buffer contains the expected preamble
771 if(pIoDataInst->autoDet.syncDetected) {
772 // skip second sub-buffer if first sub-buffer contains the expected preamble */
773 if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
774 // update the number of received elements in current frame
775 pIoDataInst->autoDet.numElementsRcvd += pIoDataInst->size2;
776 }
777 }
778 else if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
779 // look into second sub-buffer if there are two sub-buffers
780 syncCheck(pIoDataInst->buff2, pIoDataInst->size2, pIoDataInst->elementSize,
781 &pIoDataInst->autoDet);
782 }
783 } /* autoDetSyncCheck */
786 /*=============================================================================
787 * This function scans checks for sync word (preamble) in the provided sub-buffer.
788 =============================================================================*/
789 void syncCheck(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet)
790 {
791 uint_least16_t *pbuf;
792 int i, diff, restOfPreamble;
793 uint_least32_t numElements;
795 pbuf = (uint_least16_t *)buff;
796 numElements = size / elementSize; // number of elements in provided sub-buffer
798 // Check if the preamble already starts from the sub-buffer in previous call
799 if(pDet->preambleStartsPrevBuf) {
800 // Calculate number of preamble words in this sub-buffer
801 restOfPreamble = pDet->headerLength - pDet->preambleInd;
803 // Save the preamble words for sync check
804 for(i=0; i<restOfPreamble; i++)
805 {
806 pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
807 }
809 // Starts counting elements for next sync check
810 pDet->frameDataStartTemp = &pbuf[i]; // starting address of data in next frame
811 pDet->numElementsRcvd += numElements; // number of received elements
812 pDet->preambleStartsPrevBuf = FALSE; // reset flag
813 }
814 else {
815 // Preamble hasn't started from the sub-buffer in previous call.
816 // Check if this frame ends in this sub-buffer:
817 // distToFrameEnd: distance from beginning of this sub-buffer to frame end
818 // numElements: number of elements in this sub-buffer
819 if(pDet->distToFrameEnd < numElements) {
820 // Preamble of next frame is in this sub-buffer, either full or partial.
821 // First distToFrameEnd elements in the sub-buffer are the end of current
822 // frame. Preamble of next frame starts from pbuf[pDet->distToFrameEnd].
823 if(pDet->distToFrameEnd <= (numElements-pDet->headerLength)) {
824 // All the preamble words are in this sub-buffer
825 for(i=pDet->distToFrameEnd; i<pDet->distToFrameEnd+pDet->headerLength; i++)
826 {
827 // Save preamble words for sync check
828 pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
829 }
831 // Store the starting address of data in next frame.
832 // Note: &pbuf[i] could be 1 word pass the input buffer end if
833 // the last word of preamble happens to be at the end of
834 // the input buffer. In this case, this address needs to
835 // be wrapped around to the beginning of input buffer.
836 pDet->frameDataStartTemp = &pbuf[i];
837 }
838 else {
839 // Only partial preamble is in this sub-buffer.
840 // The preamble spans across this sub-buffer and next.
841 for(i=pDet->distToFrameEnd; i<numElements; i++)
842 {
843 pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
844 }
845 pDet->preambleStartsPrevBuf = TRUE;
846 }
848 // Starts counting elements for next sync check
849 pDet->numElementsRcvd = numElements - pDet->distToFrameEnd;
850 }
851 else {
852 // Current frame doesn't end here.
853 // Preamble of next frame is not in this sub-buffer
854 pDet->distToFrameEnd -= numElements;
855 }
856 }
858 // Check if full preamble of next frame has been received
859 if(pDet->preambleInd == pDet->headerLength) {
860 pDet->completeFrameRcvd = TRUE;
862 // Check if the preamble matches the reference.
863 diff = 0;
864 for(i=0; i<pDet->headerCheckLen; i++)
865 {
866 diff += pDet->preambleBuf[i] - pDet->preambleRef[i];
867 }
869 // SYNC is maintained if preamble matches reference
870 if(diff == 0) {
871 pDet->syncDetected = TRUE;
872 }
873 else {
874 pDet->syncDetected = FALSE;
875 }
877 // Reset index for next preamble check
878 //pDet->preambleInd = 0;
879 }
880 } /* syncCheck */
883 /* nothing past this point */