2 /*
3 Copyright (c) 2016, 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 */
35 #if 0
36 /*
37 * ======== audioStreamOutProc.c ========
38 */
40 #include <string.h> // for memset
41 #include <xdc/runtime/Log.h>
42 #include <xdc/runtime/Error.h>
43 #include <xdc/runtime/Memory.h>
44 #include <ti/sysbios/knl/Clock.h>
45 #include <ti/sysbios/knl/Task.h>
47 #include "paferr.h"
48 #include <acp_mds.h>
49 #include <pcm.h>
50 #include <pce.h>
51 #include <pafsio_ialg.h>
52 #include <stdasp.h>
53 #include <doberr.h>
54 #include "asperr.h"
56 #include "common.h"
57 #include "aspMsg_common.h"
58 #include "aspMsg_master.h"
59 #include "aspDecOpCircBuf_master.h"
60 #include "audioStreamProc_common.h"
61 #include "audioStreamOutProc.h"
63 // FL: debug
64 #include "evmc66x_gpio_dbg.h"
65 #define ENC_Handle PCE_Handle /* works for all: PCE */
67 extern UInt32 gCbReadAfErr ; // read circular buffer error count, not including underflows
68 extern UInt32 gDecOpCbRdAfUnd ; // decoder output circular buffer underflow count
69 extern UInt32 gMaxDecOpCbRdAfUnd; // max (consecutive) decoder output circular buffer underflow count
71 extern PAF_AST_OutIO *outIOtemp; /* Output I/O */
73 Int
74 asopDecodeInit(
75 const PAF_ASOT_Params *pP,
76 const PAF_ASOT_Patchs *pQ,
77 PAF_ASOT_Config *pC,
78 asopDecProc_t *dec
79 )
80 {
81 PAF_AST_Config *pAstCfg;
82 PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */
83 Int as; /* Audio Stream Number (1, 2, etc.) */
84 Int z; /* decode counter */
85 Int errno; /* error number */
86 Int zO, zS;
88 pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
90 // Reset audio frame pointers to original values
91 // (may be needed if error occurred).
92 for (z=STREAM1; z < STREAMN; z++)
93 {
94 Int ch;
95 for (ch=PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++)
96 {
97 if (pAstCfg->xStr[z].audioFrameChannelPointers[ch])
98 {
99 pAstCfg->xStr[z].audioFrameChannelPointers[ch] =
100 pAstCfg->xStr[z].origAudioFrameChannelPointers[ch];
101 }
102 }
103 }
105 // Reset audio frame meta data elements
106 {
107 Int i;
109 for (z=STREAM1; z < STREAMN; z++)
110 {
111 pAstCfg->xStr[z].pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE;
112 pAstCfg->xStr[z].pAudioFrame->numPrivateMetadata = 0;
113 pAstCfg->xStr[z].pAudioFrame->bsMetadata_offset = 0;
114 pAstCfg->xStr[z].pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData;
116 for (i=0; i<pP->pMetadataBufStatus->NumBuf; i++)
117 {
118 pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].offset = 0;
119 pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].size = 0;
120 }
121 }
122 }
124 as = pAstCfg->as;
125 pCbCtl = &pC->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
127 for (z=DECODE1; z < DECODEN; z++)
128 {
129 // Start decoder output circular buffer reads
130 errno = cbReadStart(pCbCtl, z);
131 if (errno) {
132 TRACE_TERSE1("PAF_ASOT_decodeInit:cbReadStart() error=%d", errno);
133 SW_BREAKPOINT; // FL: debug
134 return errno;
135 }
137 gCbReadAfErr = 0; // reset read circular buffer error count
138 gDecOpCbRdAfUnd = 0; // reset decoder output circular buffer underflow count
139 gMaxDecOpCbRdAfUnd = 0; // reset max decoder output circular buffer underflow count
141 // FL: debug
142 //cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeInit:cbReadStart");
143 }
145 // TODO: move this to start of this function so that it doesn't affect IO timing
146 for (z=ENCODE1; z < ENCODEN; z++)
147 {
148 zO = pP->outputsFromEncodes[z];
149 zS = pP->streamsFromEncodes[z];
150 //if (pAstCfg->xOut[zO].hTxSio && pAstCfg->xEnc[z].encodeStatus.mode)
151 if (outIOtemp[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode)
152 {
153 Int select = pAstCfg->xEnc[z].encodeStatus.select;
154 ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
155 ENC_Handle enc = (ENC_Handle )encAlg;
156 TRACE_VERBOSE1("AS%d: PAF_ASOT_decodeInit: initializing encode", as+zS);
157 if (encAlg->fxns->algActivate)
158 {
159 encAlg->fxns->algActivate (encAlg);
160 }
161 if (enc->fxns->reset
162 && (errno = enc->fxns->reset(enc, NULL,
163 &pAstCfg->xEnc[z].encodeControl, &pAstCfg->xEnc[z].encodeStatus)))
164 {
165 return errno;
166 }
167 }
168 }
170 //JXTODO: move decodeInfo1 to output task state machine
171 /*if (errno = pP->fxns->decodeInfo1(pP, pQ, pC, frame, block))
172 {
173 TRACE_VERBOSE1("PAF_ASOT_decodeProcessing: INIT, errno 0x%x. break after decodeInfo1", errno);
174 break;
175 }*/
177 dec->frame = 0;
178 dec->block = 0;
180 return ASOP_DECODE_NO_ERR;
181 } /* asopDecodeInit */
184 // -----------------------------------------------------------------------------
185 // ASOT Decoding Function - Info Processing, Initial
186 //
187 // Name: PAF_ASOT_decodeInfo1
188 // Purpose: Decoding Function for processing information in a manner that
189 // is unique to initial frames of input data.
190 // From: AST Parameter Function -> decodeProcessing
191 // Uses: See code.
192 // States: x
193 // Return: Error number in standard or SIO form (0 on success).
194 // Trace: Message Log "trace" in Debug Project Configuration reports:
195 // * State information as per parent.
196 //
197 // (***) FL: setup output (ASP chain reset, ENC reset, setCheckRateX, start output)
198 // Contained in INFO1 in combined FSM.
199 // Establish secondary timing
200 Int
201 asopDecodeInfo1(
202 const PAF_ASOT_Params *pP,
203 const PAF_ASOT_Patchs *pQ,
204 PAF_ASOT_Config *pC,
205 Int frame
206 )
207 {
208 PAF_AST_Config *pAstCfg;
209 Int z; /* decode/encode counter */
210 Int errno; /* error number */
212 pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
214 // run the chain of ASP's on the stream.
215 TRACE_VERBOSE0("PAF_ASOT_decodeInfo1: calling streamChainFunction.");
216 if (errno = pP->fxns->streamChainFunction(pP, pQ, pC,
217 PAF_ASP_CHAINFRAMEFXNS_RESET, 1, frame))
218 {
219 TRACE_TERSE1("PAF_ASOT_decodeInfo1: streamChainFunction returns errno 0x%x ", errno);
220 return errno;
221 }
223 TRACE_VERBOSE0("PAF_ASOT_decodeInfo1: calling enc->info.");
224 for (z=ENCODE1; z < ENCODEN; z++)
225 {
226 Int zO = pP->outputsFromEncodes[z];
227 if (outIOtemp[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode)
228 {
229 Int select = pAstCfg->xEnc[z].encodeStatus.select;
230 ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
231 ENC_Handle enc = (ENC_Handle )encAlg;
232 if (enc->fxns->info
233 && (errno = enc->fxns->info(enc, NULL,
234 &pAstCfg->xEnc[z].encodeControl, &pAstCfg->xEnc[z].encodeStatus)))
235 {
236 TRACE_TERSE1("PAF_ASOT_decodeInfo1: info returns errno 0x%x ", errno);
237 return errno;
238 }
239 }
240 }
242 if (errno = pP->fxns->setCheckRateX(pP, pQ, pC, 0))
243 {
244 // ignore if rateX has changed since we haven't, but are about to,
245 // start the output. If we didn't ignore this case then the state machine
246 // would restart unnecessarily, e.g. in the case of SRC, resulting in
247 // added latency.
248 if (errno != ASPERR_INFO_RATECHANGE)
249 {
250 TRACE_TERSE1("PAF_ASOT_decodeInfo1: setCheckRateX returns errno 0x%x, not RATECHANGE", errno);
251 return errno;
252 }
253 else
254 {
255 TRACE_TERSE0("PAF_ASOT_decodeInfo1: RATECHANGE returns RATECHANGE, ignoring");
256 }
257 }
258 /*
259 if (errno = pP->fxns->startOutput(pP, pQ, pC)) // PAF_ASOT_startOutput, SIO_issue() call inside
260 {
261 if (errno == 0x105)
262 {
263 TRACE_TERSE1("PAF_ASOT_decodeInfo1: startOutput returns RING BUFFER FULL (0x%x)", errno);
264 }
265 else
266 {
267 TRACE_TERSE1("PAF_ASOT_decodeInfo1: startOutput returns errno 0x%x", errno);
268 }
269 return errno;
270 }
271 */
272 return ASOP_DECODE_NO_ERR;
273 } /* asopDecodeInfo1 */
275 // -----------------------------------------------------------------------------
276 // ASOT Decoding Function Helper - SIO Driver Start
277 //
278 // Name: PAF_ASOT_startOutput
279 // Purpose: Decoding Function for initiating output.
280 // From: AST Parameter Function -> decodeInfo1
281 // Uses: See code.
282 // States: x
283 // Return: Error number in standard or SIO form (0 on success).
284 // Trace: Message Log "trace" in Debug Project Configuration reports:
285 // * State information as per parent.
286 // * SIO control errors.
287 //
288 #define DEC_OUTNUMBUF_MAP(X) \
289 pP->poutNumBufMap[z]->map[(X) >= pP->poutNumBufMap[z]->length ? 0 : (X)]
291 Int
292 asopStartOutput(
293 const PAF_ASOT_Params *pP,
294 const PAF_ASOT_Patchs *pQ,
295 PAF_ASOT_Config *pC
296 )
297 {
298 PAF_AST_Config *pAstCfg;
299 Int as; /* Audio Stream Number (1, 2, etc.) */
300 Int z; /* output counter */
301 Int nbufs;
302 Int zE, zS, zX;
303 Int zMD;
304 PAF_SIO_IALG_Obj *pObj;
305 PAF_SIO_IALG_Config *pAlgConfig;
308 pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
309 as = pAstCfg->as;
310 zMD = pAstCfg->masterDec;
312 for (z=OUTPUT1; z < OUTPUTN; z++)
313 {
314 if (outIOtemp[z].hIoPhy)
315 {
316 // determine associated encoder and stream
317 zE = z;
318 zS = z;
319 for (zX = ENCODE1; zX < ENCODEN; zX++)
320 {
321 if (pP->outputsFromEncodes[zX] == z)
322 {
323 zE = zX;
324 zS = pP->streamsFromEncodes[zE];
325 break;
326 }
327 }
329 // Set sample count so that DOB knows how much data to send
330 pAstCfg->xOut[z].outBufConfig.lengthofFrame =
331 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
333 if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
334 {
335 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
336 pAlgConfig = &pObj->config;
337 memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA,
338 pAlgConfig->pMemRec[0].size);
339 }
341 // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master
342 // decoder. How should we handle the sourceProgram for multiple decoders?
343 // Override as needed
344 nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram);
345 if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0)
346 {
347 nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram];
348 }
349 //JXTODO: add similar thing to be figured out
350 //SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs);
352 //JXTODO: data transfer start to be moved to output task state machine
353 /*if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
354 &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0))
355 {
356 SIO_idle(pAstCfg->xOut[z].hTxSio);
357 TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno);
358 return errno;
359 } */
361 //JXTODO: add similar thing to be figured out
362 #if 0
363 if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
364 (errno = SIO_ctrl (pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0)))
365 {
366 errno = (errno & 0xff) | ASPERR_MUTE;
367 /* convert to sensical errno */
368 TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno);
369 return (errno);
370 }
371 else
372 {
373 pAstCfg->xOut[z].outBufStatus.audio
374 = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND;
375 }
376 #endif
377 TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS);
378 }
379 }
381 return ASOP_DECODE_NO_ERR;
382 } /* asopStartOutput */
384 // -----------------------------------------------------------------------------
385 // ASOT Decoding Function - Encode Processing
386 //
387 // Name: PAF_ASOT_decodeEncode
388 // Purpose: Decoding Function for processing of audio frame data by the
389 // Encode Algorithm.
390 // From: AST Parameter Function -> decodeProcessing
391 // Uses: See code.
392 // States: x
393 // Return: Error number in standard or SIO form (0 on success).
394 // Trace: Message Log "trace" in Debug Project Configuration reports:
395 // * State information as per parent.
396 //
397 Int
398 asopDecodeEncode(
399 const PAF_ASOT_Params *pP,
400 const PAF_ASOT_Patchs *pQ,
401 PAF_ASOT_Config *pC,
402 Int frame,
403 Int block
404 )
405 {
406 PAF_AST_Config *pAstCfg;
407 Int as; /* Audio Stream Number (1, 2, etc.) */
408 Int z; /* encode/output counter */
409 Int errno; /* error number */
410 Int zX, zE, zS;
411 ioPhyCtl_t ioPhyCtl;
413 pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
414 as = pAstCfg->as;
416 // Await output buffers (but not first time)
417 for (z=OUTPUT1; z < OUTPUTN; z++)
418 {
419 // determine encoder associated with this output
420 zE = z;
421 for (zX = ENCODE1; zX < ENCODEN; zX++)
422 {
423 if (pP->outputsFromEncodes[zX] == z)
424 {
425 zE = zX;
426 break;
427 }
428 }
429 zS = pP->streamsFromEncodes[zE];
431 if (outIOtemp[z].hIoPhy) // TODO: put hIoPhy into structure or replace with API call to check if I/O is ready
432 {
433 // update length (e.g. ARC may have changed)
434 pAstCfg->xOut[z].outBufConfig.lengthofFrame =
435 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
436 TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- idle", as+zS, block);
438 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
439 ioPhyCtl.params.xferFrameSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame
440 * ASOP_OUTBUF_STRIDE * ASOP_NUM_BYTES_PCM_SAMPLE;
441 ioPhyControl(outIOtemp[z].hIoPhy, &ioPhyCtl);
443 #if 0
444 errno = SIO_reclaim(pAstCfg->xOut[z].hTxSio,(Ptr *) &pAstCfg->xOut[z].pOutBuf, NULL);
445 if (errno < 0)
446 {
447 SIO_idle(pAstCfg->xOut[z].hTxSio);
448 TRACE_TERSE2("PAF_ASOT_decodeEncode: AS%d: SIO_reclaim returns error %d", as+zS, -errno);
449 return -errno; // SIO negates error codes
450 }
451 #endif
452 // TODO: use pC->xOut[z].pOutBuf in following ->encode call
454 #if 0 // (***) FL: shows timing of Input Rx SIO reclaim after decoding has started (autodet complete)
455 // (***) debug // B8
456 {
457 static Uint8 toggleState = 0;
458 if (toggleState == 0)
459 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
460 else
461 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
462 toggleState = ~(toggleState);
463 }
464 #endif
466 //
467 // Simulate Tx SIO_reclaim() pend
468 //
469 //Semaphore_pend(semaphoreTxAudio, BIOS_WAIT_FOREVER);
470 gTaskAsopCnt++;
471 //curTime = Clock_getTicks();
472 //System_printf("System time in TaskAsipFxn Tx audio = %lu\n", (ULong)curTime);
473 //Log_info1("outputEncode():Tx SIO reclaim(), system time = %u", curTime);
474 }
475 else
476 {
477 TRACE_VERBOSE2("AS%d: PAF_ASOT_decodeEncode: processing block %d -- idle <ignored>", as+zS, block);
478 }
479 }
481 // Encode data
482 for (z=ENCODE1; z < ENCODEN; z++)
483 {
484 Int zO = pP->outputsFromEncodes[z];
485 Int zS = pP->streamsFromEncodes[z];
486 (void)zS; // clear compiler warning in case not used with tracing disabled
487 if (outIOtemp[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode) // TODO: put hIoPhy into structure or replace with API call to check if I/O is ready
488 {
489 Int select = pAstCfg->xEnc[z].encodeStatus.select;
490 ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
491 ENC_Handle enc = (ENC_Handle )encAlg;
492 if (select != pAstCfg->xEnc[z].encodeControl.encActive)
493 {
494 pAstCfg->xEnc[z].encodeControl.encActive = select;
495 TRACE_TERSE0("PAF_ASOT_decodeEncode: return error");
496 return (-1);
497 }
498 TRACE_GEN2("AS%d: PAF_ASOT_decodeEncode: processing block %d -- encode", as+zS, block);
500 // (MID 1933) temp. workaround for PCE2
501 //pAstCfg->xEnc[z].encodeInStruct.pAudioFrame->data.nChannels = PAF_MAXNUMCHAN;
502 pAstCfg->xEnc[z].encodeInStruct.pAudioFrame->data.nChannels = 2; //JXTODO: make this correct
504 /*
505 #if (CURRENT_TRACE_MASK & TRACE_MASK_DATA)
506 {
507 PAF_AudioFrame *pAudioFrame = pC->xEnc[z].encodeInStruct.pAudioFrame;
508 int *wp;
509 wp = (int*)pAudioFrame->data.sample[0];
510 TRACE_DATA((&TR_MOD, "as1-f2: AS%d PAF_ASOT_outputEncode: encoding from ch 0 0x%x. line %d", z, wp, __LINE__));
511 TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch0)", wp[0], wp[16], wp[99]));
512 wp = (int*)pAudioFrame->data.sample[1];
513 TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoding from ch 1 0x%x. line %d", wp, __LINE__));
514 TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch1)", wp[0], wp[16], wp[99]));
515 wp = (int*)pAudioFrame->data.sample[2];
516 TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoding from ch 2 0x%x. line %d", wp, __LINE__));
517 TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch2)", wp[0], wp[16], wp[99]));
518 }
519 #endif
520 */
522 if (enc->fxns->encode)
523 {
524 pAstCfg->xEnc[z].encodeOutStruct.bypassFlag =
525 pP->z_pEncodeStatus[z]->encBypass;
526 if (errno = enc->fxns->encode(enc, NULL,
527 &pAstCfg->xEnc[z].encodeInStruct, &pAstCfg->xEnc[z].encodeOutStruct))
528 {
529 if (errno != PCEERR_OUTPUT_POINTERNULL) // errno = PCEERR_OUTPUT_RESULTRANGE
530 {
531 TRACE_TERSE1("PAF_ASOT_decodeEncode: return error %d line %d", errno);
532 return errno;
533 }
534 }
535 /* #if (CURRENT_TRACE_MASK & TRACE_MASK_DATA)
536 else
537 {
538 int *wp = (int*)pC->xOut[z].pOutBuf->pntr.pVoid;
539 TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoded to 0x%x. line %d", wp, __LINE__));
540 TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x", wp[0], wp[16], wp[99]));
541 }
542 #endif
543 */
544 }
545 }
546 else
547 {
548 TRACE_VERBOSE2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- encode <ignored>",
549 as+pP->streamsFromEncodes[z], block);
550 }
551 }
553 // add debug code to dump output samples to memory
555 // Transmit data
556 for (z=OUTPUT1; z < OUTPUTN; z++)
557 {
558 // determine encoder associated with this output
559 zE = z;
560 for (zX = ENCODE1; zX < ENCODEN; zX++)
561 {
562 if (pP->outputsFromEncodes[zX] == z)
563 {
564 zE = zX;
565 break;
566 }
567 }
568 zS = pP->streamsFromEncodes[zE];
570 #if 0
571 if (pAstCfg->xOut[z].hTxSio)
572 {
573 TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- output", as+zS, block);
574 errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
575 &pAstCfg->xOut[z].outBufConfig, sizeof (pAstCfg->xOut[z].outBufConfig), 0);
576 if (errno)
577 {
578 SIO_idle(pAstCfg->xOut[z].hTxSio);
579 if (errno == 0x105) // 0x105 == RINGIO_EBUFFULL
580 {
581 // statStruct_LogFullRing(STATSTRUCT_AS1_F2);
582 TRACE_TERSE1("PAF_ASOT_decodeEncode: SIO_idle returned RINGIO_EBUFFULL (0x%x)", errno);
583 }
584 if (errno > 0)
585 {
586 TRACE_TERSE1("PAF_ASOT_decodeEncode: return error 0x%x line %d", errno);
587 return (ASPERR_ISSUE + (z << 4));
588 }
589 else if (errno < 0)
590 {
591 TRACE_TERSE1("PAF_ASOT_decodeEncode: return neg error 0x%x line %d", -errno);
592 return -errno; // SIO negates error codes
593 }
594 }
595 if (errno > 0)
596 {
597 return (ASPERR_ISSUE + (z << 4));
598 }
599 else if (errno < 0)
600 {
601 return -errno; // SIO negates error codes
602 }
603 }
604 else
605 {
606 TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- output <ignored>", as+zS, block);
607 }
608 #endif
609 }
611 return ASOP_DECODE_NO_ERR;
612 } /* asopDecodeEncode */
615 // -----------------------------------------------------------------------------
616 // ASOT Decoding Function - Stream-Final Processing
617 //
618 // Name: PAF_ASOT_decodeComplete
619 // Purpose: Decoding Function for terminating the decoding process.
620 // From: AST Parameter Function -> decodeProcessing
621 // Uses: See code.
622 // States: x
623 // Return: 0.
624 // Trace: Message Log "trace" in Debug Project Configuration reports:
625 // * State information as per parent.
626 //
627 Int
628 asopDecodeComplete(
629 const PAF_ASOT_Params *pP,
630 const PAF_ASOT_Patchs *pQ,
631 PAF_ASOT_Config *pC,
632 ALG_Handle decAlg[],
633 Int frame,
634 Int block
635 )
636 {
637 PAF_AST_Config *pAstCfg;
638 PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */
639 Int as; /* Audio Stream Number (1, 2, etc.) */
640 Int z; /* decode/encode counter */
641 Int errno; /* error number */
644 pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
645 as = pAstCfg->as;
646 (void)as; // clear compiler warning in case not used with tracing disabled
648 pCbCtl = &pC->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
650 for (z=DECODE1; z < DECODEN; z++)
651 {
652 // Stop decoder output circular buffer reads
653 errno = cbReadStop(pCbCtl, z);
654 if (errno)
655 {
656 TRACE_TERSE1("PAF_ASOT_decodeComplete:cbReadStop() error=%d", errno);
657 SW_BREAKPOINT; // FL: debug
658 return errno;
659 }
660 // FL: debug
661 cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeComplete:cbReadStop");
662 }
664 pP->fxns->streamChainFunction(pP, pQ, pC, PAF_ASP_CHAINFRAMEFXNS_FINAL, 0, frame);
666 for (z=ENCODE1; z < ENCODEN; z++)
667 {
668 Int zO = pP->outputsFromEncodes[z];
669 if (outIOtemp[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode)
670 {
671 Int select = pAstCfg->xEnc[z].encodeStatus.select;
672 ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
673 #ifdef PAF_ASP_FINAL
674 ENC_Handle enc = (ENC_Handle)encAlg;
675 #endif /* PAF_ASP_FINAL */
676 TRACE_VERBOSE1("PAF_ASOT_decodeComplete: AS%d: finalizing encode", as+z);
677 #ifdef PAF_ASP_FINAL
678 if (enc->fxns->final)
679 enc->fxns->final(enc, NULL, &pAstCfg->xEnc[z].encodeControl,
680 &pAstCfg->xEnc[z].encodeStatus);
681 #endif /* PAF_ASP_FINAL */
682 if (encAlg->fxns->algDeactivate)
683 {
684 encAlg->fxns->algDeactivate(encAlg);
685 }
686 }
687 else
688 {
689 TRACE_VERBOSE1("PAF_ASOT_decodeComplete: AS%d: finalizing encode <ignored>", as+z);
690 }
691 }
693 // wait for remaining data to be output
694 //pP->fxns->stopOutput(pP, pQ, pC); //JXTODO: implement similar function using new I/O components
696 return 0;
697 } //asopDecodeComplete
699 Int
700 asotDecodeStream(
701 const PAF_ASOT_Params *pP,
702 const PAF_ASOT_Patchs *pQ,
703 PAF_ASOT_Config *pAsotCfg,
704 Int frame,
705 Int block
706 )
707 {
708 PAF_AST_Config *pAstCfg;
709 PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */
710 Int z; /* decode/stream counter */
711 PAF_AudioFrame *pAfRd;
712 Int cbErrno;
713 Int errno;
716 pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
718 pCbCtl = &pAsotCfg->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
720 for (z=DECODE1; z < DECODEN; z++)
721 {
722 Int zS = pP->streamsFromDecodes[z];
724 //
725 // Read decoder output circular buffer
726 //
727 pAfRd = pAstCfg->xStr[zS].pAudioFrame;
728 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
729 cbErrno = cbReadAf(pCbCtl, z, pAfRd);
730 if ((cbErrno < 0) && (cbErrno != ASP_DECOP_CB_READ_UNDERFLOW))
731 {
732 gCbReadAfErr++;
733 TRACE_TERSE1("PAF_ASOT_decodeStream:cbReadAf() error=%d", cbErrno);
734 //SW_BREAKPOINT; // FL: debug
735 return cbErrno;
736 }
738 // Handle underflows
739 if (cbErrno == ASP_DECOP_CB_READ_UNDERFLOW)
740 {
741 // FL: some number of underflows alway occur on start of stream when ASOT only depends on configured Output.
742 // DDP: ~2 underflows
743 // MAT-THD: ~16 underflows
744 // Need to check behavior of cbReset().
745 // Need to check behavior on exit/re-entry into Output processing.
747 gDecOpCbRdAfUnd++; // increment circular buffer underflow count
748 if (gDecOpCbRdAfUnd >= DEC_OP_CB_RDAF_UND_THR)
749 {
750 // Underflow count above threshold.
751 // (1) set max underflow count to threshold
752 // (2) reset underflow count
753 // (3) reset circular buffer
755 gMaxDecOpCbRdAfUnd = DEC_OP_CB_RDAF_UND_THR; // update max underflow count
756 gDecOpCbRdAfUnd = 0; // reset underflow count
758 // Reset circular buffer
759 cbReset(pCbCtl, z);
760 Log_info0("PAF_ASOT_decodeStream:cbReset");
762 return cbErrno;
763 }
764 }
765 else if ((cbErrno == ASP_DECOP_CB_SOK) && (gDecOpCbRdAfUnd > 0))
766 {
767 // No underflow detected.
768 // update max underflow count,
769 // reset underflow count
771 // update max underflow count
772 if (gDecOpCbRdAfUnd > gMaxDecOpCbRdAfUnd)
773 {
774 gMaxDecOpCbRdAfUnd = gDecOpCbRdAfUnd;
775 }
776 gDecOpCbRdAfUnd = 0; // reset circular buffer underflow count
777 }
778 //Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete.");
779 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
780 Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete.");
782 #if 0 // (***) FL: shows timing of CB read
783 // (***) debug // B8
784 {
785 static Uint8 toggleState = 0;
786 if (toggleState == 0)
787 GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
788 else
789 GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
790 toggleState = ~(toggleState);
791 }
792 #endif
794 // FL: debug
795 cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeStream:cbReadAf");
796 //if (capAfWrite(pAfRd, 0) != CAP_AF_SOK)
797 //{
798 // Log_info0("capAfWrite() error");
799 //}
800 }
801 /*
802 TRACE_VERBOSE0("PAF_ASOT_outputStream: calling streamChainFunction.");
803 errno = pP->fxns->streamChainFunction(pP, pQ, pAsotCfg,
804 PAF_ASP_CHAINFRAMEFXNS_APPLY, 1, block);
805 if (errno)
806 {
807 TRACE_TERSE1("PAF_ASOT_outputStream: streamChainFunction returns errno 0x%x ", errno);
808 return errno;
809 }
810 */
811 return 0;
813 } //asotDecodeStream
814 /* nothing past this point */
815 #endif