]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blobdiff - pasdk/test_dsp/framework/audioStreamOutProc.c
PASDK-402:Add writeDECCommandRestart updates
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamOutProc.c
index 21cc1172655204b3d7993027b4a3e28ba5b28234..e45912efc8f25a79aaece85b444368d06d42775f 100644 (file)
@@ -67,10 +67,64 @@ Int32 gNumPfpAsot1=0; // debug
 
 // FL: debug
 #include "evmc66x_gpio_dbg.h"
+#include "dbgCapAf.h"
 
 
+// -----------------------------------------------------------------------------
+// Debugging Trace Control, local to this file.
+// 
+#include "logp.h"
+
 #define TRACE_TIME(a)
 
+// Allow a developer to selectively enable tracing.
+#define CURRENT_TRACE_MASK      0x07
+
+#define TRACE_MASK_TERSE        0x01   // only flag errors and show init
+#define TRACE_MASK_GENERAL      0x02   // half dozen lines per frame
+#define TRACE_MASK_VERBOSE      0x04   // trace full operation
+
+#if !(CURRENT_TRACE_MASK & TRACE_MASK_TERSE)
+    #undef  TRACE_TERSE0
+    #undef  TRACE_TERSE1
+    #undef  TRACE_TERSE2
+    #undef  TRACE_TERSE3
+    #undef  TRACE_TERSE4
+    #define TRACE_TERSE0(a)
+    #define TRACE_TERSE1(a,b)
+    #define TRACE_TERSE2(a,b,c)
+    #define TRACE_TERSE3(a,b,c,d)
+    #define TRACE_TERSE4(a,b,c,d,e)
+#endif
+    
+#if !(CURRENT_TRACE_MASK & TRACE_MASK_GENERAL)
+    #undef  TRACE_GEN0
+    #undef  TRACE_GEN1
+    #undef  TRACE_GEN2
+    #undef  TRACE_GEN3
+    #undef  TRACE_GEN4
+    #define TRACE_GEN0(a)
+    #define TRACE_GEN1(a,b)
+    #define TRACE_GEN2(a,b,c)
+    #define TRACE_GEN3(a,b,c,d)
+    #define TRACE_GEN4(a,b,c,d,e)
+#endif
+
+#if !(CURRENT_TRACE_MASK & TRACE_MASK_VERBOSE)
+    #undef  TRACE_VERBOSE0
+    #undef  TRACE_VERBOSE1
+    #undef  TRACE_VERBOSE2
+    #undef  TRACE_VERBOSE3
+    #undef  TRACE_VERBOSE4
+    #define TRACE_VERBOSE0(a)
+    #define TRACE_VERBOSE1(a,b)
+    #define TRACE_VERBOSE2(a,b,c)
+    #define TRACE_VERBOSE3(a,b,c,d)
+    #define TRACE_VERBOSE4(a,b,c,d,e)
+#endif
+
+// .............................................................................
+
 //
 // Audio Stream Definitions
 //
@@ -243,7 +297,12 @@ UInt32 gDecOpCbRdAfUnd      =0; // decoder output circular buffer underflow coun
 UInt32 gMaxDecOpCbRdAfUnd   =0; // max (consecutive) decoder output circular buffer underflow count
 UInt32 gMasterCbResetCnt    =0; // master circular buffer reset count
 
+// For writeDECCommandRestart
+extern volatile UInt32 gCommandOutputTask_SYNC;
+extern volatile UInt32 gCommandOutputTask_ACK;
+
 // Global debug counters */
+UInt32 gAsopTxSioReclaimCnt         =0;
 UInt32 gAsopInitOutProcCnt          =0;
 UInt32 gAsopInitSyncDecResetCnt     =0;
 UInt32 gAsopInitSyncDecInfo1Cnt     =0;
@@ -256,8 +315,6 @@ UInt32 gAsopEncodeCnt               =0;
 UInt32 gAsopFinalCnt                =0;
 UInt32 gAsopOutSioUpdateCnt         =0;
 UInt32 gAsopQuitCnt                 =0;
-UInt32 gAsopTxSioReclaimCnt         =0;
-
 
 /*
  *  ======== taskAsopFxn ========
@@ -274,16 +331,18 @@ Void taskAsopFxn(
     Int as;                         /* Audio Stream Number (1, 2, etc.) */
     Int z;                          /* input/encode/stream/decode/output counter */
     Int i;                          /* phase */
-    Int errno;                      /* error number */
     Int zMS;
-    Int loopCount = 0;  // used to stop trace to see startup behavior.        
-    Int outSel;
+    Int errno;                      // error number
+    Int8 procSleep;                 // whether to sleep: 0: No, 1: Yes
+    Int8 procOutDevSel;             // whether to perform output device selection: 0: No, 1:Yes
+    Int outSel;                     // whether output device selected
     enum { INIT_OUT_PROC_STATE, 
            INITSYNC_DEC_RESET_STATE, INITSYNC_DEC_INFO1_STATE, INITSYNC_DEC_DECODE1_STATE, 
            INITSYNC_RESYNC_STATE, 
            OUT_PROC_STATE } state;
     PAF_AudioFrame decResetAf;
     PAF_AudioFrame decInfo1Af;
+    Int loopCount = 0;              // used to stop trace to see startup behavior.
     
 
     Log_info0("Enter taskAsopFxn()");    
@@ -300,7 +359,7 @@ Void taskAsopFxn(
 
     if (!pQ)
     {
-        TRACE_TERSE0("TaskAsip: No Patchs defined. Exiting.");
+        TRACE_TERSE0("TaskAsop: No Patchs defined. Exiting.");
         LINNO_RPRT(TaskAsop, -1);
         return;
     }    
@@ -378,11 +437,13 @@ Void taskAsopFxn(
     //   
     for (z=STREAM1; z < STREAMN; z++)
     {
-        TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z);
+        TRACE_VERBOSE1("TaskAsop: AS%d: running", as+z);
     }
     
-    state = INIT_OUT_PROC_STATE;    // initialize state
-    errno = 0;                      // reset error indicator
+    errno = 0;                      // init error indicator -- no error
+    procSleep = 1;                  // init sleep flag -- sleep
+    procOutDevSel = 1;              // init device output selection flag -- perform output device selection
+    state = INIT_OUT_PROC_STATE;    // init state
     for (;;)
     {
         loopCount++;
@@ -392,6 +453,20 @@ Void taskAsopFxn(
         // Check forward (ASIT) error here, TBD
         //
         
+        // Even if we are not in error state, we check if writeDECCommandRestar issued or not
+        if (gCommandOutputTask_SYNC) {
+            TRACE_TERSE0("TaskAsop: ack for writeDECCommandRestart ... Wait for the command deasserted");
+            gCommandOutputTask_ACK = 1;
+            while (gCommandOutputTask_SYNC) {
+                Task_sleep(1);
+            }
+            TRACE_TERSE0("TaskAsop: ack for writeDECCommandRestart ... Sync-ed! Startover the process");
+            procSleep = 1;                  // init sleep flag -- sleep
+            procOutDevSel = 1;              // init device output selection flag -- perform output device selection
+            state = INIT_OUT_PROC_STATE;    // init state -- starover
+            errno = ASOP_DP_FORWARD_ERR;    // Override the error -- for flushing SIO output device
+        }
+        
         // any error forces idling of output
         if (errno) 
         {
@@ -405,31 +480,49 @@ Void taskAsopFxn(
         
             TRACE_TERSE1("TaskAsop: Trace stopped at loop %d.", loopCount);
             ERRNO_RPRT(TaskAsop, errno);
-        }        
+        }
         
-        TRACE_VERBOSE1("TaskAsop: AS%d: ... sleeping ...", as+zMS);
-        Task_sleep(1);
-
-        // select output devices
-        TRACE_GEN1("TaskAsop: AS%d: Output device selection ...", as+zMS);
-        errno = pP->fxns->selectDevices(pP, pQ, pAsotCfg);
-        if (errno)
+        if (procSleep == 1)
         {
-            TRACE_TERSE2("TaskAsop: AS%d: selectDevices returned errno = 0x%04x", as+zMS, errno);
-            continue;
+            TRACE_VERBOSE1("TaskAsop: AS%d: ... sleeping ...", as+zMS);
+            Task_sleep(1);
         }
 
-        // if no output selected skip remaining processing
-        errno = checkOutSel(pP, pAsotCfg, &outSel);
-        if (errno < 0)
+        if (procOutDevSel == 1)
         {
-            TRACE_TERSE2("TaskAsop: AS%d: checkOutSel returned errno = 0x%04x", as+zMS, errno);
-            continue;
-        }
-        else if (!outSel)
-        {
-            TRACE_VERBOSE1("TaskAsop: AS%d: No output selected...", as+zMS);            
-            continue;
+            // select output devices
+            TRACE_GEN1("TaskAsop: AS%d: Output device selection ...", as+zMS);
+            errno = pP->fxns->selectDevices(pP, pQ, pAsotCfg);
+            if (errno)
+            {
+                TRACE_TERSE2("TaskAsop: AS%d: selectDevices returned errno = 0x%04x", as+zMS, errno);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+
+                continue;
+            }
+
+            // if no output selected skip remaining processing
+            errno = checkOutSel(pP, pAsotCfg, &outSel);
+            if (errno < 0)
+            {
+                TRACE_TERSE2("TaskAsop: AS%d: checkOutSel returned errno = 0x%04x", as+zMS, errno);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+
+                continue;
+            }
+            else if (!outSel)
+            {
+                TRACE_VERBOSE1("TaskAsop: AS%d: No output selected...", as+zMS);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+                
+                continue;
+            }
         }
         
         switch (state)
@@ -445,10 +538,14 @@ Void taskAsopFxn(
                 if (errno < 0)
                 {
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else
                 {
                     state = INITSYNC_DEC_RESET_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
                 }
             
                 break;
@@ -467,21 +564,30 @@ Void taskAsopFxn(
                 if (errno < 0)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE errno=%d", errno);
+
                     // sync error -- start over
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else if (errno == ASOP_INITSYNC_NOTREADY)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE not sync'd errno=%d", errno);
+
                     // sync not ready -- try again
                     state = INITSYNC_DEC_RESET_STATE;
                     errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else // errno==0
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE sync'd, errno=%d", errno);
+
                     // sync'd -- move on
                     state = INITSYNC_DEC_INFO1_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
                 }
                 
                 break;
@@ -500,21 +606,30 @@ Void taskAsopFxn(
                 if (errno < 0)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE errno=%d", errno);
+                    
                     // sync error -- start over
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else if (errno == ASOP_INITSYNC_NOTREADY)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE not sync'd errno=%d", errno);
+
                     // sync not ready -- try again
                     state = INITSYNC_DEC_INFO1_STATE;
                     errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 0;
                 }
                 else // errno = 0
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE sync'd errno=%d", errno);
+
                     // sync'd -- move on
                     state = INITSYNC_DEC_DECODE1_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
                 }
                 
                 break;
@@ -533,21 +648,30 @@ Void taskAsopFxn(
                 if (errno < 0)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE errno=%d", errno);
+
                     // sync error -- start over
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else if (errno == ASOP_INITSYNC_NOTREADY)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE not sync'd errno=%d", errno);
+
                     // sync not ready -- try again
                     state = INITSYNC_DEC_DECODE1_STATE;
                     errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 0;
                 }
                 else // errno = 0
                 {
                     Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE sync'd errno=%d", errno);
+
                     // sync'd -- move on
                     state = OUT_PROC_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
                 }
                 
                 break;
@@ -568,14 +692,20 @@ Void taskAsopFxn(
                 if (errno < 0)
                 {
                     Log_info1("TaskAsop: state=INITSYNC_RESYNC_STATE errno=%d", errno);
+
                     // sync error -- start over
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 else
                 {
                     Log_info1("TaskAsop: state=INITSYNC_RESYNC_STATE sync'd errno=%d", errno);
+
                     // re-sync'd -- move on
                     state = OUT_PROC_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
                 }
                     
                 break;
@@ -603,11 +733,15 @@ Void taskAsopFxn(
                     {
                         // forward (ASIT) error -- start over
                         state = INIT_OUT_PROC_STATE;
+                        procSleep = 1;
+                        procOutDevSel = 1;
                     }
                     else
                     {
                         // local (ASOT) error
                         state = INITSYNC_RESYNC_STATE;    
+                        procSleep = 1;
+                        procOutDevSel = 0; // disallow device re-select if local error during output processing
                     }        
                 }
                 else if (errno > 0)
@@ -624,6 +758,8 @@ Void taskAsopFxn(
                         // skip re-sync
                         // resume output processing after new output selected
                         state = OUT_PROC_STATE;
+                        procSleep = 1;
+                        procOutDevSel = 1;
                     }
                 }
                 else
@@ -639,6 +775,8 @@ Void taskAsopFxn(
                     // no error returned if CB drained 
                     // (i.e. CB drained is normal behavior)
                     state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
                 }
                 
                 break;
@@ -1637,6 +1775,8 @@ PAF_ASOT_selectDevices(
             }
         }
 
+/* No need to start-clocks here, since only selecting the device. */
+#if 0
         // if device selected and valid then enable stat tracking if
         // required and start clocking
         if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio)) 
@@ -1653,6 +1793,7 @@ PAF_ASOT_selectDevices(
                 }
             }
         }
+#endif
     }
 
     return errno;
@@ -1690,7 +1831,13 @@ PAF_ASOT_decodeProcessing(
         // Check forward (ASIT) error here, TBD
         //
         
-        
+        // If writeDECCommandRestart issued, force exit the statemachine
+        if (gCommandOutputTask_SYNC) {
+            TRACE_VERBOSE1("PAF_ASOT_decodeProcessing: writeDECCommandRestart issued in state=0x%x ... exiting core loop", state);
+            errno = ASOP_DP_FORWARD_ERR;
+            break;
+        }
+
         // Check if any change in output SIO, e.g. from Output shortcut.
         // Changes will break FSM and allow Output reconfiguration.
         errno = checkOutSio(pP, pAsotCfg, &outSioUpdate);
@@ -1991,6 +2138,9 @@ PAF_ASOT_encodeCommand(
     return 0;
 } //PAF_ASOT_encodeCommand
 
+//debug -- allow dynamic config
+//Int16 gStrFrameLen=DEF_STR_FRAME_LEN; // stream frame length (PCM samples)
+
 //   Purpose:   Decoding Function for reinitializing the decoding process.
 Int
 PAF_ASOT_decodeInit(
@@ -2013,6 +2163,16 @@ PAF_ASOT_decodeInit(
 
     for (z=DECODE1; z < DECODEN; z++)
     {
+        // Initialize decoder output circular buffer for stream reads
+        //errno = cbInitStreamRead(pCbCtl, z, gStrFrameLen);
+        errno = cbInitStreamRead(pCbCtl, z);
+        if (errno)
+        {
+            TRACE_TERSE1("PAF_ASOT_decodeInit:cbInitStreamRead() error=%d", errno);
+            SW_BREAKPOINT; // debug
+            return errno;
+        }
+        
         // Start decoder output circular buffer reads
         errno = cbReadStart(pCbCtl, z);
         if (errno)
@@ -2021,6 +2181,7 @@ PAF_ASOT_decodeInit(
             SW_BREAKPOINT; // debug
             return errno;
         }
+        
         gCbReadAfErr=0;         // reset read circular buffer error count
         gDecOpCbRdAfUnd=0;      // reset decoder output circular buffer underflow count
         gMaxDecOpCbRdAfUnd=0;   // reset max decoder output circular buffer underflow count
@@ -2222,7 +2383,7 @@ PAF_ASOT_decodeStream(
     Int z;                              /* decode/stream counter */
     PAF_AudioFrame *pAfRd;
     Int cbErrno;
-    PAF_AST_DecOpCircBufStats cbStats;  /* circular buffer statistics */
+    //PAF_AST_DecOpCircBufStats cbStats;  /* circular buffer statistics */
     Int errno;
 
 
@@ -2238,25 +2399,25 @@ PAF_ASOT_decodeStream(
         // Read decoder output circular buffer
         //
         pAfRd = pAstCfg->xStr[zS].pAudioFrame;
-        //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
+        //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);       // debug
         cbErrno = cbReadAf(pCbCtl, z, pAfRd);
-        if ((cbErrno < 0) && (cbErrno != ASP_DECOP_CB_READ_UNDERFLOW))
+        //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);     // debug
+        if ((cbErrno < 0) && 
+            (cbErrno != ASP_DECOP_CB_AF_READ_UNDERFLOW) && 
+            (cbErrno != ASP_DECOP_CB_PCM_READ_UNDERFLOW))
         {
             gCbReadAfErr++;
             TRACE_TERSE1("PAF_ASOT_decodeStream:cbReadAf() error=%d", cbErrno);
-            //SW_BREAKPOINT; // FL: debug
+            //SW_BREAKPOINT; // debug
             return cbErrno;
         }
 
         // Handle underflows
-        if (cbErrno == ASP_DECOP_CB_READ_UNDERFLOW)
+        if ((cbErrno == ASP_DECOP_CB_AF_READ_UNDERFLOW) ||
+            (cbErrno == ASP_DECOP_CB_PCM_READ_UNDERFLOW))
         {
-            // FL: some number of underflows alway occur on start of stream when ASOT only depends on configured Output.
-            //     DDP: ~2 underflows
-            //     MAT-THD: ~16 underflows
-            // Need to check behavior of cbReset().
+            // (***) FL: Need to check behavior of cbReset().
             // Need to check behavior on exit/re-entry into Output processing.
-            
             gDecOpCbRdAfUnd++; // increment circular buffer underflow count
             if (gDecOpCbRdAfUnd >= DEC_OP_CB_RDAF_UND_THR) 
             {
@@ -2290,7 +2451,7 @@ PAF_ASOT_decodeStream(
             gDecOpCbRdAfUnd = 0; // reset circular buffer underflow count
         }
         //Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete.");
-        //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
+        //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);   // debug
         Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete.");
         
 #if 0 // (***) FL: shows timing of CB read
@@ -2305,17 +2466,19 @@ PAF_ASOT_decodeStream(
             }
 #endif
 
-        // FL: debug
-        // Get circular buffer statistics (debug)
+        // debug, get circular buffer statistics
         //cbGetStats(pCbCtl, z, &cbStats);
         cbGetStats(pCbCtl, z, &gCbStats);
 
-        // FL: debug
+        // debug
         cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeStream:cbReadAf");
-        //if (capAfWrite(pAfRd, 0) != CAP_AF_SOK)
-        //{
-        //    Log_info0("capAfWrite() error");
-        //}
+        
+#if 0 // debug, capture audio frame
+        if (capAfWrite(pAfRd, PAF_LEFT) != CAP_AF_SOK)
+        {
+            Log_info0("capAfWrite() error");
+        }
+#endif
     }
             
     TRACE_VERBOSE0("PAF_ASOT_outputStream: calling streamChainFunction.");
@@ -2358,7 +2521,8 @@ PAF_ASOT_decodeEncode(
     Int z;                      /* encode/output counter */
     Int errno;                  /* error number */
     Int zX, zE, zS;
-    UInt32 curTime;
+    // debug
+    //UInt32 curTime;
 
     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
     as = pAstCfg->as;
@@ -2384,7 +2548,9 @@ PAF_ASOT_decodeEncode(
             pAstCfg->xOut[z].outBufConfig.lengthofFrame = 
                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
             TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- idle", as+zS, block);
+            //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);   // debug
             errno = SIO_reclaim(pAstCfg->xOut[z].hTxSio,(Ptr *) &pAstCfg->xOut[z].pOutBuf, NULL);
+            //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);     // debug
             if (errno < 0)
             {
                 SIO_idle(pAstCfg->xOut[z].hTxSio);
@@ -2405,15 +2571,15 @@ PAF_ASOT_decodeEncode(
             }
 #endif            
 
-            gAsopTxSioReclaimCnt++;
-
             //
             // Simulate Tx SIO_reclaim() pend
             //
             //Semaphore_pend(semaphoreTxAudio, BIOS_WAIT_FOREVER);
-            curTime = Clock_getTicks();
-            //System_printf("System time in TaskAsipFxn Tx audio = %lu\n", (ULong)curTime);
+            //curTime = Clock_getTicks();
+            //System_printf("System time in TaskAsopFxn Tx audio = %lu\n", (ULong)curTime);
             //Log_info1("outputEncode():Tx SIO reclaim(), system time = %u", curTime);
+            
+            gAsopTxSioReclaimCnt++;
         }
         else 
         {
@@ -2512,8 +2678,10 @@ PAF_ASOT_decodeEncode(
         if (pAstCfg->xOut[z].hTxSio) 
         {
             TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- output", as+zS, block);
+            //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);       // debug
             errno = SIO_issue(pAstCfg->xOut[z].hTxSio, 
                 &pAstCfg->xOut[z].outBufConfig, sizeof (pAstCfg->xOut[z].outBufConfig), 0);
+            //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);     // debug
             if (errno)
             {
                 SIO_idle(pAstCfg->xOut[z].hTxSio);
@@ -2661,7 +2829,7 @@ PAF_ASOT_startOutput(
     PAF_AST_Config *pAstCfg;
     Int as;                     /* Audio Stream Number (1, 2, etc.) */
     Int z;                      /* output counter */
-    Int errno,nbufs;            /* error number */
+    Int errno,nbufs, errme;            /* error number */
     Int zE, zS, zX;
     Int zMD;
     PAF_SIO_IALG_Obj    *pObj;
@@ -2689,6 +2857,26 @@ PAF_ASOT_startOutput(
                 }
             }
 
+// Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
+
+#if 1
+            // if device selected and valid then enable stat tracking if
+                       // required and start clocking
+                       if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
+                       {
+                               TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
+                               errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
+                               if (errno)
+                               {
+                                       TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
+                                       SIO_idle(pAstCfg->xOut[z].hTxSio);
+                                       if (!errno)
+                                       {
+                                               errno = ASPERR_DEVOUT + errme;
+                                       }
+                               }
+                       }
+#endif
             // Set sample count so that DOB knows how much data to send
             pAstCfg->xOut[z].outBufConfig.lengthofFrame =
                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
@@ -2864,6 +3052,7 @@ PAF_ASOT_stopOutput(
     return errno;
 } //PAF_ASOT_stopOutput
 
+
 // -----------------------------------------------------------------------------
 // ASOT Decoding Function Helper - SIO Driver Change
 //
@@ -2912,7 +3101,6 @@ PAF_ASOT_setCheckRateX(
     {
         if (pAstCfg->xOut[z].hTxSio && (pAstCfg->xOut[z].outBufStatus.clock & 0x01)) 
         {
-
             // determine associated encoder
             zE = z;
             for (zX = ENCODE1; zX < ENCODEN; zX++) 
@@ -2938,10 +3126,10 @@ PAF_ASOT_setCheckRateX(
             }
             else
             {
-                return ( ASPERR_INFO_RATERATIO );
+                return ASPERR_INFO_RATERATIO;
             }
 
-            getVal = SIO_ctrl (pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg) &rateX);
+            getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg)&rateX);
             if (getVal == DOBERR_RATECHANGE) 
             {
                 for (zx=OUTPUT1; zx < OUTPUTN; zx++)
@@ -2958,7 +3146,7 @@ PAF_ASOT_setCheckRateX(
                 // exit this loop /function early.
                 return ASPERR_INFO_RATECHANGE;
             }
-            else if( getVal != SYS_OK )
+            else if (getVal != SYS_OK)
             {
                 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
             }
@@ -3332,6 +3520,9 @@ static Int PAF_ASOT_outputReset(
     return ASOP_SOK;
 }
 
+// FL: debug, allow modification of output frame length via JTAG
+Int16 gOutFrameLen=PAF_ASOT_FRAMELENGTH; // output frame length (PCM samples)
+
 //   Purpose:   Init-Sync Dec Info1 state function.
 //              Performes Dec Info1 Init-Sync.
 static Int PAF_ASOT_initSyncDecInfo1(
@@ -3378,8 +3569,22 @@ static Int PAF_ASOT_initSyncDecInfo1(
         //{
         //    return errno;
         //}
-        outIsCpyAf(pDecInfo1Af, pStrAf);
         
+        // Hack to set ASOT output frame length.
+            // THD sets this to 256 (hard-coded in Dec Info)
+            // DDP sets this to 0 (audio frame passthrough, 0 from ASDT AF frame length)
+            // PCM sets this to 256 (decodeControl.frameLength)
+        //pDecInfo1Af->sampleCount = 256;                      // !!!! GJ: Revisit !!!!
+        pDecInfo1Af->sampleCount = gOutFrameLen;
+        
+        outIsCpyAf(pDecInfo1Af, pStrAf);
+
+        // Hack to set ASOT output frame length
+            // THD sets this to 256 (hard-coded in Dec Info)
+            // DDP sets this to 0 (audio frame passthrough, 0 from ASDT AF frame length)
+            // PCM sets this to 256 (decodeControl.frameLength)
+        //pStrAf->sampleCount = 256;                   // !!!! GJ: Revisit !!!!
+
         // outputInfo1():
         //      - ASP chain reset,
         //      - Enc Info
@@ -3573,7 +3778,9 @@ PAF_ASOT_decodeFinalTest(
     zMD = pAsotCfg->pAstCfg->masterDec; // get master Dec index
 
     // Check circular buffer drain state
+    //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);     // debug
     errno = cbCheckDrainState(pCbCtl, zMD, &drainedFlag);
+    //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);   // debug
     if (errno < 0)
     {
         return errno;