Added I/O components memory allocation to input and output
authorJianzhong Xu <a0869574@ti.com>
Fri, 15 Dec 2017 21:02:51 +0000 (16:02 -0500)
committerJianzhong Xu <a0869574@ti.com>
Fri, 15 Dec 2017 21:02:51 +0000 (16:02 -0500)
initPhaseMalloc. Added McASP LLD to application\itopo\evmk2g.
Standalone test works fine. PASDK functionality stays unchanged.

23 files changed:
pasdk/test_dsp/.cproject
pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.c [new file with mode: 0644]
pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.h [new file with mode: 0644]
pasdk/test_dsp/application/itopo/evmk2g/sap_d10.c
pasdk/test_dsp/application/main.c
pasdk/test_dsp/framework/audioStreamInpProc.c
pasdk/test_dsp/framework/audioStreamInpProc.h
pasdk/test_dsp/framework/audioStreamOutProc.c
pasdk/test_dsp/framework/audioStreamOutProc.h
pasdk/test_dsp/io/ioBuff.c [new file with mode: 0644]
pasdk/test_dsp/io/ioBuff.h [new file with mode: 0644]
pasdk/test_dsp/io/ioBuff_loc.h [new file with mode: 0644]
pasdk/test_dsp/io/ioConfig.h [new file with mode: 0644]
pasdk/test_dsp/io/ioData.c [new file with mode: 0644]
pasdk/test_dsp/io/ioData.h [new file with mode: 0644]
pasdk/test_dsp/io/ioPhy.c [new file with mode: 0644]
pasdk/test_dsp/io/ioPhy.h [new file with mode: 0644]
pasdk/test_dsp/io/ioPhy_loc.h [new file with mode: 0644]
pasdk/test_dsp/io/libarch.h [new file with mode: 0644]
pasdk/test_dsp/io/test/audio_tsk.c [new file with mode: 0644]
pasdk/test_dsp/io/test/frame_work.c [new file with mode: 0644]
pasdk/test_dsp/io/test/frame_work.h [new file with mode: 0644]
pasdk/test_dsp/mib/mib.c

index 00d64ecaf620fd4aa0d372cebc72b6b12d4748b4..0ec0ad6e592cf8e416ae9ad8db1ef8554ac8ac9d 100644 (file)
@@ -32,7 +32,7 @@
                                        <stringMacro name="USB_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
                                        <stringMacro name="UART_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
                                        <stringMacro name="QMSS_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
-                                       <stringMacro name="PDK_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti/pdk_k2g_1_0_6/packages"/>
+                                       <stringMacro name="PDK_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti/pdk_k2g_1_0_7/packages"/>
                                        <stringMacro name="SRIO_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
                                        <stringMacro name="SA_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
                                        <stringMacro name="PRUSS_INSTALL_PATH" type="VALUE_PATH_DIR" value="C:/ti"/>
@@ -89,7 +89,9 @@
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/csl&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/addon/audk2g/include&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/board&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/drv/mcasp&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/test_dsp/io&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/test_dsp/sap&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/test_dsp/mib&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/test_dsp/mob&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;libc.a&quot;"/>
                                                                        <listOptionValue builtIn="false" value="ti.addon.audk2g.ae66"/>
                                                                        <listOptionValue builtIn="false" value="ti.board.ae66"/>
+                                                                       <listOptionValue builtIn="false" value="ti.drv.mcasp.ae66"/>
                                                                </option>
                                                                <option id="com.ti.ccstudio.buildDefinitions.C6000_8.1.linkerID.SEARCH_PATH.1285174236" name="Add &lt;dir&gt; to library search path (--search_path, -i)" superClass="com.ti.ccstudio.buildDefinitions.C6000_8.1.linkerID.SEARCH_PATH" valueType="libPaths">
                                                                        <listOptionValue builtIn="false" value="&quot;${CG_TOOL_ROOT}/lib&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${CG_TOOL_ROOT}/include&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/addon/audk2g/lib/k2g/c66/release&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/board/lib/evmK2G/c66/release&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${PDK_INSTALL_PATH}/ti/drv/mcasp/lib/k2g/c66/release&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/paf/pa/build/c66x/release&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${PROC_AUDIO_SDK_ROOT}/pasdk/paf/pa/util/da10x_misc/c66x/release&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;${TI_MAS_DSPLIB_C66X_INSTALL_DIR}/packages/ti/dsplib/lib&quot;"/>
diff --git a/pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.c b/pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.c
new file mode 100644 (file)
index 0000000..2028dff
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2015, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file      mcasp_config.c
+ *
+ * \brief     Configures McASP module
+ *
+ */
+
+#include "mcasp_cfg.h"
+#include "ioConfig.h"
+
+#define AUDIO_DAC0_TEST
+
+/* McASP device handles */
+Ptr hMcaspDevTx;
+Ptr hMcaspDevRx;
+
+/* McASP channel handles */
+Ptr hMcaspTxChan;
+Ptr hMcaspRxChan;
+Ptr hMcaspRxChan2;
+
+/* McASP channel parameters */
+Mcasp_Params mcaspTxParams;
+Mcasp_Params mcaspRxParams;
+
+/* McASP Callback function argument */
+//uint32_t txChanMode;
+//uint32_t rxChanMode;
+
+/* Error flag */
+uint32_t gblErrFlag = 0;
+Error_Block eb;
+
+void GblErr(Mcasp_errCbStatus arg);
+
+/* External function declarations */
+extern void McaspDevice_init(void);
+extern signed char*  getGlobalAddr(signed char* addr);
+
+#ifdef IO_LOOPBACK_TEST
+extern void mcaspAppCallbackRx(void* arg, MCASP_Packet *mcasp_packet);
+extern void mcaspAppCallbackTx(void* arg, MCASP_Packet *mcasp_packet);
+#else
+void asipMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
+{
+    // to be moved to and defined in asip processing
+}
+void asopMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
+{
+    // to be moved to and defined in asop processing
+}
+#endif
+
+/* McASP HW setup for receive */
+Mcasp_HwSetupData mcaspRcvSetup = {
+       MCASP_DIR_RMASK,   /* .rmask:   0xFFFFFFFF    */
+       MCASP_DIR_RFMT,    /* .rfmt:    0x000180F0    */
+       MCASP_DIR_AFSRCTL, /* .afsrctl: 0x00000111    */
+       MCASP_DIR_RTDM,    /* .rtdm:    0x00000003    */
+       MCASP_DIR_RINTCTL, /* .rintctl: 0x00000000    */
+       MCASP_DIR_RSTAT,   /* .rstat:   0x000001FF    */
+       MCASP_DIR_REVTCTL, /* .revtctl  */
+        {
+                       MCASP_DIR_ACLKRCTL,  /* .aclkrctl:  0x00000080  */
+                       MCASP_DIR_AHCLKRCTL, /* .ahclkrctl: 0x00000000  */
+                       MCASP_DIR_RCLKCHK    /* .rclkchk:   0x00000000  */
+        }
+};
+
+/* McASP HW setup for transmit */
+Mcasp_HwSetupData mcaspXmtSetup = {
+        /* .xmask    = */ 0xFFFFFFFF, /* 16 bits are to be used     */
+        /* .xfmt     = */ 0x000180F0, /*
+                                       * 0 bit delay from framesync
+                                       * MSB first
+                                       * No extra bit padding
+                                       * Padding bit (ignore)
+                                       * slot Size is 32
+                                       * Reads from DMA port
+                                       * NO rotation
+                                       */
+        /* .afsxctl  = */ 0x00000112, /* I2S mode - 2 slot TDM
+                                       * Frame sync is one word
+                                       * Rising edge is start of frame
+                                       * Internally generated frame sync
+                                       */
+        /* .xtdm     = */ 0x00000003, /* slot 1 and 2 are active (I2S)               */
+        /* .xintctl  = */ 0x00000000, /* sync error,overrun error,clK error   */
+        /* .xstat    = */ 0x000001FF, /* reset any existing status bits       */
+        /* .xevtctl  = */ 0x00000000, /* DMA request is enabled or disabled   */
+        {
+             /* .aclkxctl  = */ 0X000000E1,
+             /* .ahclkxctl = */ 0x00004000     ,
+             /* .xclkchk   = */ 0x00000000
+        },
+
+};
+
+#ifdef INPUT_SPDIF
+/* McAsp channel parameters for receive - DIR                */
+Mcasp_ChanParams  mcaspRxChanParam =
+{
+       0x0001,                    /* Number of serializers      */
+       {Mcasp_SerializerNum_5},   /* Serializer index           */
+       &mcaspRcvSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,          /* Mode (TDM/DIT)             */
+       Mcasp_WordLength_32,
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
+       TRUE,
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked */
+       Mcasp_WordBitsSelect_MSB  /* wordBitsSelect */
+};
+#endif
+
+/* McASP LLD channel parameters for HDMI input:
+ *     When slot size of McASP is configured to 32-bit, HDMI data always come to 16 MSBs of the slot
+ *     and the 16 LSBs are filled with 0's. This is the nature of HDMI and I2S.
+ *     For PCM data, we want all 32 bits in the slot to be transferred to the input buffer:
+ *        - wordWidth = Mcasp_WordLength_32
+ *        - isDataPacked = 1,
+ *        - wordBitsSelect having no effect since wordWidth = slot size
+ *     For bit stream, we want only 16 MSBs in the slot to be transferred to the input buffer:
+ *        - wordWidth = Mcasp_WordLength_16
+ *        - isDataPacked = 1,
+ *        - wordBitsSelect = Mcasp_WordBitsSelect_MSB
+ */
+#ifdef INPUT_HDMI_4xI2S
+/* McAsp channel parameters for receive - HDMI 4XI2S layout  */
+Mcasp_ChanParams  mcaspRxChanParam =
+{
+       0x0004,                    /* number of serializers      */
+       {Mcasp_SerializerNum_12,
+        Mcasp_SerializerNum_13,
+        Mcasp_SerializerNum_14,
+        Mcasp_SerializerNum_15 }, /* serializer index           */
+       &mcaspRcvSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,          /* Mode (TDM/DIT)             */
+#ifdef INPUT_PCM_ONLY
+       Mcasp_WordLength_32,       /* 32-bit word length, whole slot (size=32) to be transfered */
+#else
+    Mcasp_WordLength_16,       /* 16-bit word length, MSB or LSB of slot to be transfered, depending on wordBitsSelect */
+#endif
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,
+       TRUE,                     /* enableHwFifo */
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked, only transfer the selected bits of slot, based on wordWidth and wordBitsSelect */
+       Mcasp_WordBitsSelect_MSB  /* wordBitsSelect, only matters if wordWidth < slot size */
+};
+#endif
+
+#ifdef INPUT_HDMI_STEREO
+/* McAsp channel parameters for receive - HDMI   1XI2S layout             */
+Mcasp_ChanParams  mcaspRxChanParam =
+{
+       0x0001,                    /* Number of serializers      */
+       {Mcasp_SerializerNum_12},   /* Serializer index           */
+       &mcaspRcvSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,          /* Mode (TDM/DIT)             */
+       Mcasp_WordLength_32,
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
+       TRUE,                     /* enableHwFifo */
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked */
+       Mcasp_WordBitsSelect_MSB  /* wordBitsSelect */
+};
+#endif
+
+/* McAsp channel parameters for transmit - DAC0              */
+#ifndef TX_MCASP_USE_MULT_SER
+Mcasp_ChanParams  mcaspTx0ChanParam =
+{
+       0x0001,                   /* number of serializers       */
+       {Mcasp_SerializerNum_0}, /* serializer index for DAC0    */
+       &mcaspXmtSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,
+       Mcasp_WordLength_32,      /* word width                  */
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
+       TRUE,
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked */
+       Mcasp_WordBitsSelect_LSB  /* wordBitsSelect */
+};
+#else
+Mcasp_ChanParams  mcaspTx0ChanParam =
+{
+       0x0004,                   /* number of serializers       */
+       {Mcasp_SerializerNum_0,
+        Mcasp_SerializerNum_1,
+        Mcasp_SerializerNum_2,
+        Mcasp_SerializerNum_3 }, /* serializer index for DAC0    */
+       &mcaspXmtSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,
+       Mcasp_WordLength_32,      /* word width                  */
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,
+       TRUE,
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked */
+       Mcasp_WordBitsSelect_LSB  /* wordBitsSelect */
+};
+#endif
+
+/* McAsp channel parameters for transmit - DAC1              */
+Mcasp_ChanParams  mcaspTx1ChanParam =
+{
+       0x0001,                   /* number of serializers       */
+       {Mcasp_SerializerNum_4},  /* serializer index for DAC0   */
+       &mcaspXmtSetup,
+       TRUE,
+       Mcasp_OpMode_TDM,
+       Mcasp_WordLength_32,      /* word width                  */
+       NULL,
+       0,
+       NULL,
+       GblErr,
+       2,                        /* number of TDM channels      */
+       Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
+       TRUE,
+       1,                        /* hwFifoEventDMARatio */
+       TRUE,                     /* isDataPacked */
+       Mcasp_WordBitsSelect_LSB  /* wordBitsSelect */
+};
+
+/* Handle to eDMA */
+extern EDMA3_DRV_Handle hEdma0;
+extern EDMA3_DRV_Handle hEdma1;
+
+/**
+ *  \brief    Function called by McASP driver in case of error
+ *
+ *  \return    None
+ */
+void GblErr(Mcasp_errCbStatus arg)
+{
+       gblErrFlag = 1;
+}
+
+
+/* DAC default configuration parameters */
+DacConfig  DAC_Cfg =
+{
+       AUDK2G_DAC_AMUTE_CTRL_DAC_DISABLE_CMD,   /* Amute event */
+       0,                          /* Amute control */
+       AUDK2G_DAC_SAMPLING_MODE_AUTO,     /* Sampling mode */
+       AUDK2G_DAC_DATA_FORMAT_I2S,        /* Data format */
+       0,                          /* Soft mute control */
+       AUDK2G_DAC_ATTENUATION_WIDE_RANGE, /* Attenuation mode */
+       AUDK2G_DAC_DEEMP_DISABLE,            /* De-emph control */
+       100                          /* Volume */
+};
+
+/**
+ *  \brief    Configures audio DAC module
+ *
+ *  \return    none
+ */
+void configAudioDAC(void)
+{
+       Audk2g_STATUS status;
+
+       audk2g_delay(10000);
+
+       /* Initialize Audio DAC module */
+       status = audioDacConfig(AUDK2G_DAC_DEVICE_ALL, &DAC_Cfg);
+       if(status != Audk2g_EOK)
+       {
+               //platform_write("Audio DAC Configuration Failed!\n");
+               //testRet(1);
+       }
+}
+
+/**
+ *  \brief   Configures McASP module and creates the channel
+ *           for audio Tx and Rx
+ *
+ *  \return    Audk2g_EOK on Success or error code
+ */
+Audk2g_STATUS mcaspAudioConfig(void)
+{
+       Int status;
+
+       hMcaspDevTx  = NULL;
+       hMcaspDevRx  = NULL;
+       hMcaspTxChan = NULL;
+       hMcaspRxChan = NULL;
+
+       /* Initialize McASP Tx and Rx parameters */
+       mcaspTxParams = Mcasp_PARAMS;
+       mcaspRxParams = Mcasp_PARAMS;
+
+       mcaspTxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x23;  // not used
+       mcaspTxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;  // not used
+       mcaspRxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;
+       mcaspRxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63; // Asynchronous. Separate clock and frame sync used by transmit and receive sections.
+
+#ifndef INPUT_SPDIF
+       mcaspRxParams.mcaspHwSetup.glb.pdir |= 0x2000000;   //Special case, since for HDMI input - mcasp0 is both Rx & Tx
+       mcaspRxParams.mcaspHwSetup.glb.amute  = 0x2;            // this to ensure one doesn't overwrite the other (rx/tx)
+       mcaspTxParams.mcaspHwSetup.glb.pdir |= 0x2000000;   //Set Amute pin as output for Tx channel
+       mcaspTxParams.mcaspHwSetup.glb.amute  = 0x2;
+#else
+       mcaspTxParams.mcaspHwSetup.glb.pdir |= 0x2000000;   //Set Amute pin as output for Tx channel
+       mcaspTxParams.mcaspHwSetup.glb.amute  = 0x2;
+#endif
+
+       /* Set the HW interrupt number */
+       //mcaspTxParams.hwiNumber = 8;
+       //mcaspRxParams.hwiNumber = 8;
+
+       /* Initialize eDMA handle */
+#ifdef INPUT_SPDIF
+       mcaspRxChanParam.edmaHandle  = hEdma1;
+#else
+       mcaspRxChanParam.edmaHandle  = hEdma0;
+#endif
+
+       mcaspTx0ChanParam.edmaHandle = hEdma0;
+       mcaspTx1ChanParam.edmaHandle = hEdma0;
+    
+#ifdef INPUT_SPDIF
+       /* Bind McASP0 for Tx */
+       status = mcaspBindDev(&hMcaspDevTx, CSL_MCASP_0, &mcaspTxParams);
+       if((status != MCASP_COMPLETED) || (hMcaspDevTx == NULL))
+       {
+               //IFPRINT(platform_write("mcaspBindDev for Tx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       /* Bind McASP2 for Rx */
+       status = mcaspBindDev(&hMcaspDevRx, CSL_MCASP_2, &mcaspRxParams);
+       if((status != MCASP_COMPLETED) || (hMcaspDevRx == NULL))
+       {
+               //IFPRINT(platform_write("mcaspBindDev for Rx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+#else /* HDMI or HDMI_STEREO */
+       /* Bind McASP0 for Rx and Tx */
+       status = mcaspBindDev(&hMcaspDevRx, CSL_MCASP_0, &mcaspRxParams);
+       if((status != MCASP_COMPLETED) || (hMcaspDevRx == NULL))
+       {
+               //IFPRINT(platform_write("mcaspBindDev for Rx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       hMcaspDevTx = hMcaspDevRx;
+#endif
+
+       /* Create McASP channel for Tx */
+       status = mcaspCreateChan(&hMcaspTxChan, hMcaspDevTx,
+                                MCASP_OUTPUT,
+#ifdef AUDIO_DAC0_TEST
+                                &mcaspTx0ChanParam,
+#else
+                                &mcaspTx1ChanParam,
+#endif
+#ifdef IO_LOOPBACK_TEST
+                                mcaspAppCallbackTx, NULL);
+#else
+                                asopMcaspCallback, NULL);
+#endif
+
+       if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))
+       {
+               //IFPRINT(platform_write("mcaspCreateChan for Tx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       /* Create McASP channel for Rx */
+       status = mcaspCreateChan(&hMcaspRxChan, hMcaspDevRx,
+                                MCASP_INPUT,
+                                &mcaspRxChanParam,
+#ifdef IO_LOOPBACK_TEST
+                                mcaspAppCallbackRx, NULL);
+#else
+                                                        asipMcaspCallback, NULL);
+#endif
+
+       if((status != MCASP_COMPLETED) || (hMcaspRxChan == NULL))
+       {
+               //IFPRINT(platform_write("mcaspCreateChan for Rx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       return (Audk2g_EOK);
+} /* mcaspAudioConfig */
+
+Audk2g_STATUS mcaspRxDeInit(void)
+{
+       mcaspDeleteChan(hMcaspRxChan);
+       hMcaspRxChan = NULL;
+
+       mcaspUnBindDev(hMcaspDevRx);
+       hMcaspDevRx = NULL;
+
+    return (Audk2g_EOK);
+}
+
+Audk2g_STATUS mcaspRxReset(void)
+{
+    if(hMcaspRxChan != NULL) {
+               mcaspDeleteChan(hMcaspRxChan);
+               hMcaspRxChan = NULL;
+    }
+
+       return (Audk2g_EOK);
+}
+
+Audk2g_STATUS mcaspRxCreate(void)
+{
+       Int status;
+
+       /* Create McASP channel for Rx */
+       status = mcaspCreateChan(&hMcaspRxChan, hMcaspDevRx,
+                                MCASP_INPUT,
+                                &mcaspRxChanParam,
+#ifdef IO_LOOPBACK_TEST
+                                mcaspAppCallbackRx, NULL);
+#else
+                                                        asipMcaspCallback, NULL);
+#endif
+
+       if((status != MCASP_COMPLETED) || (hMcaspRxChan == NULL))
+       {
+               //IFPRINT(platform_write("mcaspCreateChan for Rx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       return (Audk2g_EOK);
+}
+
+Audk2g_STATUS mcaspTxReset(void)
+{
+    if(hMcaspTxChan != NULL) {
+               mcaspDeleteChan(hMcaspTxChan);
+               hMcaspTxChan = NULL;
+    }
+
+       return (Audk2g_EOK);
+}
+
+Audk2g_STATUS mcaspTxCreate(void)
+{
+       Int status;
+
+       /* Create McASP channel for Tx */
+       status = mcaspCreateChan(&hMcaspTxChan, hMcaspDevTx,
+                                MCASP_OUTPUT,
+                                &mcaspTx0ChanParam,
+#ifdef IO_LOOPBACK_TEST
+                                mcaspAppCallbackTx, NULL);
+#else
+                                asopMcaspCallback, NULL);
+#endif
+       if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))
+       {
+               //IFPRINT(platform_write("mcaspCreateChan for Tx Failed\n"));
+               return (Audk2g_EFAIL);
+       }
+
+       return (Audk2g_EOK);
+}
+
+Audk2g_STATUS mcaspRxCfgPCM(void)
+{
+    Int status = Audk2g_EOK;
+
+    if(  (mcaspRxChanParam.wordWidth      != Mcasp_WordLength_32)
+      /*|| (mcaspRxChanParam.wordBitsSelect != Mcasp_WordBitsSelect_LSB)*/ )
+    {
+        mcaspRxReset();
+
+        mcaspRxChanParam.wordWidth      = Mcasp_WordLength_32;
+        //mcaspRxChanParam.wordBitsSelect = Mcasp_WordBitsSelect_LSB;
+
+        status = mcaspRxCreate();
+    }
+
+    return status;
+} // mcaspRxCfgPCM
+
+Audk2g_STATUS mcaspRxCfgBitstream(void)
+{
+    Int status = Audk2g_EOK;
+
+    if(  (mcaspRxChanParam.wordWidth      != Mcasp_WordLength_16)
+      /*|| (mcaspRxChanParam.wordBitsSelect != Mcasp_WordBitsSelect_MSB)*/ )
+    {
+        mcaspRxReset();
+
+        mcaspRxChanParam.wordWidth      = Mcasp_WordLength_16;
+        //mcaspRxChanParam.wordBitsSelect = Mcasp_WordBitsSelect_MSB;
+
+        status = mcaspRxCreate();
+    }
+
+    return status;
+} // mcaspRxCfgBitstream
+
+/* Nothing past this point */
diff --git a/pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.h b/pasdk/test_dsp/application/itopo/evmk2g/mcasp_cfg.h
new file mode 100644 (file)
index 0000000..5cb33ef
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file      mcasp_config.h
+ *
+ * \brief     McASP configuration header file
+ *
+ */
+
+#ifndef _MCASP_CONFIG_H_
+#define _MCASP_CONFIG_H_
+
+#include <xdc/std.h>
+#include <xdc/runtime/Memory.h>
+#include <xdc/runtime/IHeap.h>
+#include <xdc/runtime/Error.h>
+#include <xdc/runtime/Log.h>
+#include <xdc/runtime/System.h>
+
+#include <ti/sysbios/io/GIO.h>
+#include <ti/sysbios/io/IOM.h>
+#include <ti/sysbios/heaps/HeapMem.h>
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Semaphore.h>
+#include <ti/sdo/edma3/drv/edma3_drv.h>
+#include <ti/sysbios/knl/Task.h>
+#include <ti/sysbios/hal/Cache.h>
+#include <ti/sysbios/family/c64p/Hwi.h>
+
+#include <stdio.h>
+
+#include <mcasp_drv.h>
+
+#include "audio_dc_cfg.h"
+#include "edma_cfg.h"
+
+/**
+ * \brief McASP configurations for Rx - DIR
+ */
+/** Receive format unit bit mask register defult value */
+#define MCASP_DIR_RMASK      (0xFFFFFFFF)
+
+/** Receive bit stream format register defult value */
+#define MCASP_DIR_RFMT       (  ( 1 << 16)   /* RDATDLY: Transmit with 1 bit delay */ \
+                              | ( 1 << 15)   /* RXRVRS  : MSB first */                \
+                              | ( 0 << 13)   /* RPAD   : Pad extra bits with 0 */     \
+                                     | (15 << 4)    /* RSSZ   : 32-bit slot size */          \
+                              | ( 0 << 3)    /* RBUSSEL: Reads from edma port */      \
+                              | ( 0 << 0))    /* RROT   : No rotation */
+
+/** Receive frame sync control register defult value */
+#define MCASP_DIR_AFSRCTL    (  (2 << 7)    /* RMOD : 2-slot TDM */                         \
+                              | (1 << 4)    /* FRWID: Single word frame sync */             \
+                              | (0 << 1)    /* FSRM : Externally-generated rx frame sync */ \
+                              | (1 << 0))   /* FSRP : Start on falling edge */
+
+/** Receive TDM time slot 0-31 register defult value */
+#define MCASP_DIR_RTDM       (0x00000003)
+
+/** Receive interrupt control register defult value */
+#define MCASP_DIR_RINTCTL    (0x00000000)
+
+/** Receive status register defult value */
+#define MCASP_DIR_RSTAT      (0x000001FF)
+
+/** Receive DMA event control register defult value */
+#define MCASP_DIR_REVTCTL    (0x00000000)
+
+/** Receive clock control register defult value */
+#define MCASP_DIR_ACLKRCTL   (  (1 << 7)    /* CLKRP  : RX on raising edge */         \
+                              | (0 << 5)    /* CLKRM  : Externally generated ACLK */  \
+                              | (0 << 0))   /* CLKRDIV: NA */
+
+/** Receive high-frequency clock control register defult value */
+#define MCASP_DIR_AHCLKRCTL   (  (0 << 15)    /* HCLKRM  : Clock from AHCLKR pin */  \
+                               | (0 << 14)    /* HCLKRP  : Falling edge */           \
+                               | (0x400 << 0))    /* HCLKRDIV: AHCLKR = AUXCLK / 1 */
+
+/** Receive clock check control register defult value */
+#define MCASP_DIR_RCLKCHK     (0x00000000)
+
+/**
+ *  \brief   Configures McASP module and creates the channel
+ *           for audio Tx and Rx
+ *
+ *  \return    Platform_EOK on Success or error code
+ */
+Audk2g_STATUS mcaspAudioConfig(void);
+
+Audk2g_STATUS mcaspTxCreate(void);
+Audk2g_STATUS mcaspTxReset(void);
+Audk2g_STATUS mcaspRxCreate(void);
+Audk2g_STATUS mcaspRxReset(void);
+
+#endif /* _MCASP_CONFIG_H_ */
index 8a1d201e73005396b47a9be699d3fe99cac76028..27b25a64066222a5c62158f2b831ec07c39bfe73 100644 (file)
@@ -1217,4 +1217,19 @@ unsigned int HDMIGpioGetState (void) {
        return(audk2g_gpioReadInput(AUDK2G_GPIO_PORT_0, AUDK2G_AUDIO_HSR_HMINTz_GPIO));
 }
 
+XDAS_Int32 D10_init()
+{
+    XDAS_Int32 result = 0;
+
+    // perform one time hardware initialization
+    if (!initDone) {
+        result = initD10 (NULL);
+        if (result) {
+            return result;
+        }
+        initDone = 1;
+    }
+
+    return 0;
+}
 // EOF
index 41e959c7cb2e5132f5d1a10d21696b01c1bc3232..2a3a5323a8407ad51866063f01b15153428c5682 100644 (file)
@@ -56,9 +56,18 @@ All rights reserved.
 #include "pfp/pfp.h"
 #include "pfp_app.h"        /* contains all PFP ID's */
 
+#include "ioConfig.h"    //TODO: remove this header
 extern Void initDev2(Void);
 extern void evmI2CInit(uint8_t i2cportnumber); // missing in evmc66x_i2c.h
 
+#ifdef IO_LOOPBACK_TEST
+extern void McaspDevice_init();
+extern void D10_init();
+extern Audk2g_STATUS mcaspAudioConfig();
+extern void audioIoCreate(void);
+extern void ioSemaphoreCreate(void);
+#endif
+
 /*
  *  ======== main ========
  */
@@ -115,8 +124,47 @@ Int main()
         //testRet(1);
     }
 
+#ifdef PASDK_SIO_DEV
     Log_info0("initDev2");
     initDev2();
+#endif
+
+#ifdef IO_LOOPBACK_TEST
+       /* Initialize McASP HW details */
+       McaspDevice_init();
+
+    D10_init();
+
+#ifdef INPUT_SPDIF
+    // Input is DIR
+    AudStatus = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_DIR);
+#else
+    // Input is HDMI
+    AudStatus = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_I2S);
+#endif
+    if(AudStatus != Audk2g_EOK)
+    {
+        Log_info0("audk2g_AudioSelectClkSrc Failed!\n");
+    }
+    audk2g_delay(50000); // Without delay between these 2 calls system aborts.
+
+       /* Initialize McASP module */
+       status = mcaspAudioConfig();
+       if(status != Audk2g_EOK)
+       {
+               Log_info0("McASP Configuration Failed!\n");
+       }
+
+       ioSemaphoreCreate();
+
+       audioIoCreate();
+
+    Task_setPri(TaskAfp, -1);
+    Task_setPri(TaskAip, -1);
+    Task_setPri(TaskSysInit, -1);
+    Task_setPri(TaskAsip, 5);
+    Task_setPri(TaskAsop, 5);
+#endif
 
     Log_info0("IPC start");
     // Initialize IPC
index fb7b6ec41b305d481e6640ab349bead587db140c..7449c0779cb931933b0133c79eef76548e65c5eb 100644 (file)
@@ -69,6 +69,8 @@ All rights reserved.
 
 #include "pfp/pfp.h"
 #include "pfp_app.h"        /* contains all PFP ID's */
+#include "ioConfig.h"
+
 Int32 gNumPfpAsit1=0; // debug
 Int32 gNumPfpAsit2=0;
 
@@ -671,8 +673,11 @@ Void taskAsipFxnInit(
  *  ======== taskAsipFxn ========
  *  Audio Stream Input Processing task function
  */
+#ifdef PASDK_SIO_DEV
 Void taskAsipFxn(
-//    Int betaPrimeValue, // FL: revisit
+#else
+Void taskAsipFxn_Not_Used(
+#endif
     const PAF_ASIT_Params *pP,
     const PAF_ASIT_Patchs *pQ
 )
@@ -1016,6 +1021,94 @@ Void taskAsipFxn(
     //Log_info0("Exit taskAsipFxn()");
 }
 
+Int PAF_ASIT_ioCompCreate(PAF_AST_IoInp *pIoInp, int numInp, IHeap_Handle iHeapHandle)
+{
+    int i, j, num_alloc;
+    lib_mem_rec_t *mem_rec;
+    ioBuffHandle_t  ioBufHandle;
+    ioPhyHandle_t   ioPhyHandle;
+    ioDataHandle_t  ioDataHandle;
+    Error_Block     eb;
+
+    for(i=0; i<numInp; i++)
+    {
+        // Create an I/O BUFF instance
+        // Obtain number of memory blocks required by I/O BUFF
+        num_alloc = ioBuffNumAlloc();
+
+        // Obtain requirements of each memory block
+        mem_rec   = (lib_mem_rec_t *)malloc(sizeof(lib_mem_rec_t)*num_alloc);
+        if(ioBuffAlloc(mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        /* Allocate memory and create I/O BUFF instance */
+        for(j=0; j<num_alloc; j++) {
+            mem_rec[j].base = Memory_calloc(iHeapHandle, mem_rec[j].size,
+                                            (1<<mem_rec[j].alignment), &eb);
+        }
+
+        if(ioBuffCreate(&ioBufHandle, mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        pIoInp[i].hIoBuff = ioBufHandle;
+
+        free(mem_rec);
+
+        // Create an I/O PHY instance
+        // Obtain number of memory blocks required by I/O PHY
+        num_alloc = ioPhyNumAlloc();
+
+        // Obtain requirements of each memory block
+        mem_rec   = (lib_mem_rec_t *)malloc(sizeof(lib_mem_rec_t)*num_alloc);
+        if(ioPhyAlloc(mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        /* Allocate memory and create I/O PHY instance */
+        for(j=0; j<num_alloc; j++) {
+            mem_rec[j].base = Memory_calloc(iHeapHandle, mem_rec[j].size,
+                                            (1<<mem_rec[j].alignment), &eb);
+        }
+
+        if(ioPhyCreate(&ioPhyHandle, mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        pIoInp[i].hIoPhy = ioPhyHandle;
+
+        free(mem_rec);
+
+        // Create an I/O DATA instance
+        // Obtain number of memory blocks required by I/O DATA
+        num_alloc = ioDataNumAlloc();
+
+        // Obtain requirements of each memory block
+        mem_rec   = (lib_mem_rec_t *)malloc(sizeof(lib_mem_rec_t)*num_alloc);
+        if(ioDataAlloc(mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        /* Allocate memory and create I/O DATA instance */
+        for(j=0; j<num_alloc; j++) {
+            mem_rec[j].base = Memory_calloc(iHeapHandle, mem_rec[j].size,
+                                            (1<<mem_rec[j].alignment), &eb);
+        }
+
+        if(ioDataCreate(&ioDataHandle, mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        pIoInp[i].hIoData = ioDataHandle;
+
+        free(mem_rec);
+
+    } // end of for loop
+
+    return 0;
+} // PAF_ASIT_ioCompCreate
+
 // -----------------------------------------------------------------------------
 // ASIT Initialization Function - Memory Allocation
 //
@@ -1040,7 +1133,7 @@ PAF_ASIT_initPhaseMalloc(
 {
     PAF_AST_Config *pAstCfg;
     Int as;                    /* Audio Stream Number (1, 2, etc.) */
-    Int zMS;
+    Int zMS, errLineNum;
     Error_Block    eb;
        IHeap_Handle   decHeapHandle;
 
@@ -1065,6 +1158,26 @@ PAF_ASIT_initPhaseMalloc(
         INPUTN * sizeof (*pAstCfg->xInp),
         HEAP_ID_INTERNAL1_SHM, (IArg)pAstCfg->xInp);
 
+    /* Input I/O data structure memory */
+    if (!(pAsitCfg->pIoInp = Memory_calloc((IHeap_Handle)HEAP_INTERNAL1_SHM,
+        INPUTN * sizeof (*pAsitCfg->pIoInp), 4, &eb)))
+    {
+        TRACE_TERSE1("PAF_ASIT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS);
+        SW_BREAKPOINT;
+        return __LINE__;
+    }
+    TRACE_TERSE3("PAF_ASIT_initPhaseMalloc. (pAsitCfg->pIoInp) %d bytes from space %d at 0x%x.",
+        INPUTN * sizeof (*pAsitCfg->pIoInp),
+        HEAP_ID_INTERNAL1_SHM, (IArg)pAsitCfg->pIoInp);
+
+    /* I/O components memory for input */
+    errLineNum = PAF_ASIT_ioCompCreate(pAsitCfg->pIoInp, INPUTN, (IHeap_Handle)HEAP_INTERNAL1_SHM);
+    if(errLineNum)
+    {
+        SW_BREAKPOINT;
+        return errLineNum;
+    }
+
     /* Decode memory */
 #ifdef NON_CACHE_STATUS
     decHeapHandle = (IHeap_Handle)HEAP_EXTERNAL_NONCACHED_SHM;
@@ -3717,3 +3830,44 @@ static Int getFrameLengthSourceSel(
     
     return frameLength;
 }
+#define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
+
+extern const MdUns iecFrameLength[23];
+extern void * hMcaspRxChan;
+
+void asipInitIoComps(const PAF_ASIT_Params *pP, PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo)
+{
+  ioBuffParams_t ioBuffParams;
+  ioPhyParams_t  ioPhyParams;
+  ioDataParam_t  ioDataCfg;
+
+  ioBuffParams.base         = pInpBuf->inpBufConfig.base.pVoid;
+  ioBuffParams.size         = pInpBuf->inpBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
+  ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
+  ioBuffParams.nominalDelay = 30720*2;   // to remove magic number
+  if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
+      SW_BREAKPOINT;
+  }
+
+  ioPhyParams.ioBuffHandle    = pInpIo->hIoBuff;
+  ioPhyParams.xferFrameSize   = 128*8*2; // to remove magic number
+  ioPhyParams.mcaspChanHandle = hMcaspRxChan;
+  ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_WRITE;
+  if(ioPhyInit(pInpIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
+      SW_BREAKPOINT;
+  }
+
+  ioDataCfg.ioBuffHandle         = pInpIo->hIoBuff;
+  ioDataCfg.unknownSourceTimeOut = pInpBuf->inpBufConfig.pBufStatus->unknownTimeout;
+  ioDataCfg.frameLengthsIEC      = (uint_least16_t *)&iecFrameLength[0];
+  ioDataCfg.frameLengthPCM       = 512;      // to remove magic number
+  ioDataCfg.frameLengthDef       = 128*8;    // to remove magic number
+  ioDataCfg.ibMode               = pInpBuf->inpBufConfig.pBufStatus->mode;
+  ioDataCfg.zeroRunRestart       = pInpBuf->inpBufConfig.pBufStatus->zeroRunRestart;
+  ioDataCfg.zeroRunTrigger       = pInpBuf->inpBufConfig.pBufStatus->zeroRunTrigger;
+
+  if(ioDataInit(&pInpIo->hIoData, &ioDataCfg) != IODATA_NO_ERR) {
+      SW_BREAKPOINT;
+  }
+
+} /* asipInitIoComps */
index 2d765cd1af293b8f1b4960f1719b0723af1aa62d..490fc2200003d44df0d55f015ff34bf8a758f2fb 100644 (file)
@@ -48,6 +48,9 @@ All rights reserved.
 #include "audioStreamProc_config.h"
 #include "audioStreamProc_master.h"
 #include "statusOp_common.h"
+#include "ioPhy.h"
+#include "ioBuff.h"
+#include "ioData.h"
 
 // Global debug counter */
 extern Uint32 gTaskAsipCnt; // debug counter for ASP task
@@ -177,12 +180,40 @@ typedef struct PAF_ASIT_Patchs {
     //const PAF_ASP_LinkInit * const (*i_encLinkInit);
 } PAF_ASIT_Patchs;
 
+// Input I/O structure
+typedef struct PAF_AST_InpIO {
+    ioPhyHandle_t        hIoPhy;     /* handle to I/O physical layer */
+    ioBuffHandle_t       hIoBuff;    /* handle to I/O buffer management */
+    ioDataHandle_t       hIoData;    /* handle to I/O data processing */
+    const void           *pRxParams; /* pointer to D10 Rx Params */
+    Int                  swapData;
+
+    Int       syncState;
+    Int       numPrimeXfers;
+    Int       mcaspXferErr;
+/*
+    void     *mcaspRxBuf1;
+    void     *mcaspRxBuf2;
+    uint32_t  mcaspRxSize1;
+    uint32_t  mcaspRxSize2;
+    Int       mcaspRxtwoXfers;
+*/
+    // debugging counters
+    //uint32_t numXferStart;
+    //uint32_t numXferFinish;
+    //uint32_t numXferInterm;
+    uint32_t numInputOverrun;
+    uint32_t numAsipRestart;
+    uint32_t numAsipDecodeQuit;
+
+} PAF_AST_IoInp;
 // Audio Stream Input Task (ASIT) configuration
 typedef struct PAF_ASIT_Config {
     Task_Handle taskHandle;     // ASIT handle
     ACP_Handle acp;             // ASIT local ACP handle
     PAF_ASPM_Config *pAspmCfg;  // ASIT/ASOT shared configuration
     PAF_AST_Config *pAstCfg;    // ASIT/ASOT/ASDT shared configuration
+    PAF_AST_IoInp  *pIoInp;
 } PAF_ASIT_Config;
 
 
index e744cd2a7b02ce31c0e60d0fb084e27924c9e26e..3812270780926c9b68fc4587f3ea142e4d7f8e85 100644 (file)
@@ -69,6 +69,7 @@ Int32 gNumPfpAsot1=0; // debug
 #include "evmc66x_gpio_dbg.h"
 #include "dbgCapAf.h"
 
+#include "ioConfig.h"
 
 // -----------------------------------------------------------------------------
 // Debugging Trace Control, local to this file.
@@ -425,8 +426,11 @@ Void taskAsopFxnInit(
  *  ======== taskAsopFxn ========
  *  Audio Stream Output Processing task function
  */
+#ifdef PASDK_SIO_DEV
 Void taskAsopFxn(
-//    Int betaPrimeValue, // FL: revisit
+#else
+Void taskAsopFxn_Not_Used(
+#endif
     const PAF_ASOT_Params *pP,
     const PAF_ASOT_Patchs *pQ
 )
@@ -821,6 +825,69 @@ Void taskAsopFxn(
     //Log_info0("Exit taskAsopFxn()");
 }
 
+Int PAF_ASOT_ioCompCreate(PAF_AST_IoOut *pIoOut, int numOut, IHeap_Handle iHeapHandle)
+{
+    int i, j, num_alloc;
+    lib_mem_rec_t   *mem_rec;
+    ioBuffHandle_t  ioBufHandle;
+    ioPhyHandle_t   ioPhyHandle;
+    Error_Block     eb;
+
+    for(i=0; i<numOut; i++)
+    {
+        // Create an I/O BUFF instance
+        // Obtain number of memory blocks required by I/O BUFF
+        num_alloc = ioBuffNumAlloc();
+
+        // Obtain requirements of each memory block
+        mem_rec   = (lib_mem_rec_t *)malloc(sizeof(lib_mem_rec_t)*num_alloc);
+        if(ioBuffAlloc(mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        /* Allocate memory and create I/O BUFF instance */
+        for(j=0; j<num_alloc; j++) {
+            mem_rec[j].base = Memory_calloc(iHeapHandle, mem_rec[j].size,
+                                            (1<<mem_rec[j].alignment), &eb);
+        }
+
+        if(ioBuffCreate(&ioBufHandle, mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        pIoOut[i].hIoBuff = ioBufHandle;
+
+        free(mem_rec);
+
+        // Create an I/O PHY instance
+        // Obtain number of memory blocks required by I/O PHY
+        num_alloc = ioPhyNumAlloc();
+
+        // Obtain requirements of each memory block
+        mem_rec   = (lib_mem_rec_t *)malloc(sizeof(lib_mem_rec_t)*num_alloc);
+        if(ioPhyAlloc(mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        /* Allocate memory and create I/O PHY instance */
+        for(j=0; j<num_alloc; j++) {
+            mem_rec[j].base = Memory_calloc(iHeapHandle, mem_rec[j].size,
+                                            (1<<mem_rec[j].alignment), &eb);
+        }
+
+        if(ioPhyCreate(&ioPhyHandle, mem_rec) != IOBUFF_NOERR) {
+            return __LINE__;
+        }
+
+        pIoOut[i].hIoPhy = ioPhyHandle;
+
+        free(mem_rec);
+
+    } // end of for loop
+
+    return 0;
+} // PAF_ASOT_ioCompCreate
+
 // -----------------------------------------------------------------------------
 // AST Initialization Function - Memory Allocation
 //
@@ -846,7 +913,7 @@ PAF_ASOT_initPhaseMalloc (
 {
     PAF_AST_Config *pAstCfg;
     Int as;                     /* Audio Stream Number (1, 2, etc.) */
-    Int zMS;
+    Int zMS, errLineNum;
     Error_Block    eb;
     //Int i;
 
@@ -914,6 +981,24 @@ PAF_ASOT_initPhaseMalloc (
             OUTPUTN * sizeof (*pAstCfg->xOut),
             HEAP_ID_INTERNAL, (IArg)pAstCfg->xOut);
 
+    /* Output I/O data structure memory */
+    if (!(pAsotCfg->pIoOut = Memory_calloc((IHeap_Handle)HEAP_INTERNAL, OUTPUTN * sizeof (*pAsotCfg->pIoOut), 4, &eb)))
+    {
+        TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS);
+        SW_BREAKPOINT;
+        return __LINE__;
+    }
+    TRACE_TERSE3("PAF_ASOT_initPhaseMalloc. (pAsotCfg->pIoOut) %d bytes from space %d at 0x%x.",
+                 OUTPUTN * sizeof (*pAsotCfg->pIoOut),
+                 HEAP_ID_INTERNAL, (IArg)pAsotCfg->pIoOut);
+
+    /* I/O components memory for output */
+    errLineNum = PAF_ASOT_ioCompCreate(pAsotCfg->pIoOut, OUTPUTN, (IHeap_Handle)HEAP_INTERNAL);
+    if(errLineNum)
+    {
+        SW_BREAKPOINT;
+        return errLineNum;
+    }
     TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: initialization phase - memory allocation complete.", as+zMS);
     return 0;
 } //PAF_ASOT_initPhaseMalloc
index c6c24eba29a379839c43d86bb3cdd803f8e3ff89..5cb7a14421e40cd94e1fcf6f15ab0d75b9770c31 100644 (file)
@@ -47,6 +47,8 @@ All rights reserved.
 #include "audioStreamProc_patchs.h"
 #include "audioStreamProc_config.h"
 #include "audioStreamProc_master.h"
+#include "ioPhy.h"
+#include "ioBuff.h"
 
 /* !!!!!!!!! Revisit !!!!!!!!!!!!!!
  * Purpose : Temporary ASOT FL sizes.
@@ -190,6 +192,25 @@ typedef struct PAF_ASOT_Patchs {
     const PAF_ASP_LinkInit * const (*i_encLinkInit);
 } PAF_ASOT_Patchs;
 
+typedef struct PAF_AST_OutIO {
+    ioPhyHandle_t        hIoPhy;     /* handle to I/O physical layer */
+    ioBuffHandle_t       hIoBuff;    /* handle to I/O buffer management */
+
+    void     *mcaspTxBuf1;
+    void     *mcaspTxBuf2;
+    uint32_t  mcaspTxSize1;
+    uint32_t  mcaspTxSize2;
+    int       mcaspTxtwoXfers;
+
+    int       numPrimeXfers;
+
+    uint32_t  mcaspXferErr;
+
+    // debugging counters
+    uint32_t num_xfers;
+
+} PAF_AST_IoOut;
+
 // Audio Stream Input Task (ASOT) configuration
 typedef struct PAF_ASOT_Config {
     Task_Handle taskHandle;             // ASOT handle
@@ -197,6 +218,7 @@ typedef struct PAF_ASOT_Config {
     Int8 cbDrainedFlag[DECODEN_MAX];    // CB drained flags
     PAF_ASPM_Config *pAspmCfg;          // ASIT/ASOT shared configuration
     PAF_AST_Config *pAstCfg;            // ASIT/ASOT/ASDT shared configuration
+    PAF_AST_IoOut  *pIoOut;
 } PAF_ASOT_Config;
 
 
diff --git a/pasdk/test_dsp/io/ioBuff.c b/pasdk/test_dsp/io/ioBuff.c
new file mode 100644 (file)
index 0000000..6fc6581
--- /dev/null
@@ -0,0 +1,375 @@
+
+#include "ioBuff.h"
+#include "ioBuff_loc.h"
+#include "libarch.h"
+#include <stdint.h>
+#include <string.h>
+
+/******************************************************************************
+* Implementation of I/O Buffer Management Component
+******************************************************************************/
+
+#define IOBUF_NUM_MEM_ALLOCS 1
+#define IOBUFF_INST_ALIGN   3 
+
+/*******************************************************************************
+* API function: ioBuffNumAlloc
+*    Returns the maximum number of memory allocation requests that ioBuffAlloc() 
+*    requires.
+*******************************************************************************/
+int ioBuffNumAlloc(void)
+{
+  return (IOBUF_NUM_MEM_ALLOCS);
+}
+
+/*******************************************************************************
+* API function: ioBuffAlloc
+*    Returns a table of memory records that describe the size, alignment, type 
+*    and memory space of all buffers required by this component. 
+*******************************************************************************/
+int ioBuffAlloc(lib_mem_rec_t *mem_tbl)
+{
+  mem_tbl[0].size = sizeof(ioBuffInst_t);
+  mem_tbl[0].alignment = IOBUFF_INST_ALIGN;
+  mem_tbl[0].type = LIB_PMEM_SLOW;
+  mem_tbl[0].base = NULL;
+
+  return (IOBUFF_NOERR);
+}
+
+/*******************************************************************************
+* API function: ioBuffCreate
+*    Create an I/O buffer management instance. 
+*******************************************************************************/
+int ioBuffCreate(ioBuffHandle_t *handle, const lib_mem_rec_t *mem_tbl) 
+{
+  ioBuffInst_t *inst;
+
+  if(  (mem_tbl[0].size < sizeof(ioBuffInst_t))
+     ||libChkAlign(mem_tbl[0].base, IOBUFF_INST_ALIGN) ) {
+    // to add: check memory type
+    return (IOBUFF_ERR_MEMORY);
+  }
+
+  inst = (ioBuffInst_t *)mem_tbl[0].base;
+  
+  *handle = (ioBuffHandle_t)inst;
+
+  return (IOBUFF_NOERR);  
+}
+
+/*******************************************************************************
+* API function: ioBuffInit
+*    Initializes the I/O buffer management instance. 
+*******************************************************************************/
+int ioBuffInit (ioBuffHandle_t handle, const ioBuffParams_t *params)
+{
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  if(params == NULL) {
+    return (IOBUFF_ERR_BAD_PARAMS);
+  }
+
+  if((params->base == NULL) || (params->nominalDelay > params->size)) {
+    return (IOBUFF_ERR_BAD_PARAMS);
+  }
+
+  /* initialize the instance */
+  inst->base  = params->base;  // I/O memory pool base address 
+  inst->size  = params->size;  // I/O memory pool size
+  inst->end   = (void *)((uint_least32_t)inst->base + inst->size);
+  inst->sync  = params->sync;           // synchronous read or synchronous write
+  inst->nom_delay = params->nominalDelay;   // nominal delay for synchronous read/write
+
+  inst->rw_wrap_around = 0;
+  inst->status = BUFF_STATUS_NORMAL;
+  inst->read_ptr  = inst->read_complete_ptr  = inst->base;
+  inst->write_ptr = inst->write_complete_ptr = (void *)((uint_least32_t)inst->base + inst->nom_delay);
+
+//  memset(inst->base, 0, inst->nom_delay);
+
+  return (IOBUFF_NOERR);  
+} /* ioBuffInit */
+
+/*******************************************************************************
+* API function: Return read pointer(s)
+*******************************************************************************/
+int ioBuffGetReadPtrs(ioBuffHandle_t handle, size_t mem_size, 
+                      void **ptr1, size_t *size1, void **ptr2, size_t *size2)
+{
+  uint_least32_t address_end_of_read;
+  void * new_read_ptr;
+  int ret_val;
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  if(inst->status != BUFF_STATUS_OVERFLOW) {
+    /* check if buffer underflows */
+    if(  (  (!inst->rw_wrap_around) 
+          &&(((uint_least32_t)inst->write_complete_ptr - 
+              (uint_least32_t)inst->read_ptr) < mem_size)
+         )
+       ||(  (inst->rw_wrap_around)
+          &&(((uint_least32_t)inst->write_complete_ptr + inst->size - 
+              (uint_least32_t)inst->read_ptr) < mem_size)
+         )
+      ) {
+      /* Buffer underflows */ 
+      inst->status = BUFF_STATUS_UNDERFLOW;
+  
+      if(inst->sync == IOBUff_READ_SYNC) {
+        /*If it's read-synchronized, don't return from here, but still return
+        read pointer(s) calculated below.  */
+        /* reset the delay between read and write_complete pointers */
+        uint_least32_t delay_adjust = inst->nom_delay;
+        if(delay_adjust < mem_size) {
+          delay_adjust = mem_size;
+        }
+        inst->read_ptr = (void *)((uint_least32_t)inst->write_complete_ptr - 
+                                                  delay_adjust);
+        if(inst->read_ptr < inst->base) {
+          inst->read_ptr = (void *)((uint_least32_t)inst->read_ptr + inst->size);
+          inst->rw_wrap_around = 1;   // set wrap around flag
+        }
+         
+        ret_val = IOBUFF_ERR_UNDERFLOW;
+      }
+      else {
+        /* Return here if it underflows but is not read-synchronized. */
+        *ptr1 = NULL; *size1 = 0;
+        *ptr2 = NULL; *size2 = 0;
+        return(IOBUFF_ERR_UNDERFLOW);
+      }
+    }
+    else {
+      inst->status = BUFF_STATUS_NORMAL;
+      ret_val = IOBUFF_NOERR;
+    }
+  } /* if(inst->status != BUFF_STATUS_OVERFLOW) */
+  else {
+    /* already in overflow and remain in overflow untill there is some distance 
+       between read pointer and write pointer */
+    ret_val = IOBUFF_ERR_OVERFLOW;    
+  } 
+
+  /* return 1 or 2 pointers depending buffer wraps around or not */
+  *ptr1 = inst->read_ptr;  /* starting address to read */
+
+  /* check if read pointer is going to wrap around during this read */
+  address_end_of_read = (uint_least32_t)inst->read_ptr + mem_size;
+  if(address_end_of_read <= (uint_least32_t)inst->end) {  
+    /* read pointer not going to wrap aound - return only 1 pointer */
+    *size1 = mem_size;
+    *ptr2  = NULL; *size2 = 0;
+    new_read_ptr = (void *)address_end_of_read;
+    if(address_end_of_read == (uint_least32_t)inst->end) {
+      new_read_ptr = inst->base;
+    }
+  }
+  else {  
+    /* read pointer going to wrap around - return 2 pointers */
+    *size1 = (size_t)inst->end - (size_t)inst->read_ptr;
+    *ptr2  = inst->base;
+    *size2 = mem_size - *size1;
+    new_read_ptr = (void *)((uint_least32_t)inst->base + *size2);   
+  }
+
+  /* update read pointer */
+  inst->read_ptr = new_read_ptr; 
+
+  return (ret_val);
+} /* ioBuffGetReadPtrs */
+
+
+/*******************************************************************************
+* API function: Rewind read pointer by a given amount.
+*******************************************************************************/
+int ioBuffRewindReadPtr(ioBuffHandle_t handle, size_t rewind_size)
+{
+  uint_least32_t address_rewind_read;
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  address_rewind_read = (uint_least32_t)inst->read_ptr - rewind_size;
+  if(address_rewind_read < (uint_least32_t)inst->base) {
+       address_rewind_read = (uint_least32_t)inst->end - ((uint_least32_t)inst->base-address_rewind_read );
+  }
+  inst->read_ptr = (void *)address_rewind_read;
+
+  return IOBUFF_NOERR;
+} /* ioBuffRewindReadPtr */
+
+/*******************************************************************************
+* API function: Return write pointer(s)
+*******************************************************************************/
+int ioBuffGetWritePtrs(ioBuffHandle_t handle, size_t mem_size, 
+                       void **ptr1, size_t *size1, void **ptr2, size_t *size2)
+{
+  int ret_val;
+  uint_least32_t address_end_of_write;
+  void * new_write_ptr;
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  /* check if buffer overflows or not */
+  if(inst->status != BUFF_STATUS_UNDERFLOW) {   // this condition may need to be removed!!!
+    if(  (  (!inst->rw_wrap_around) 
+          &&(((uint_least32_t)inst->read_complete_ptr + inst->size - 
+              (uint_least32_t)inst->write_ptr) < mem_size)
+         )
+       ||(  (inst->rw_wrap_around) 
+          &&(((uint_least32_t)inst->read_complete_ptr - 
+              (uint_least32_t)inst->write_ptr) < mem_size)
+         )
+      ) {
+      /* Buffer overflows */
+      inst->status = BUFF_STATUS_OVERFLOW;
+  
+      if(inst->sync == IOBUFF_WRITE_SYNC){
+        /* If it's write-synchronized, don't return from here. Still return the 
+           write pointer(s) calculated below. */
+        ret_val = IOBUFF_ERR_OVERFLOW;
+      }
+      else {
+        /* Return here if it overflows but is not write-synchronized. */
+        *ptr1 = NULL; *size1 = 0;
+        *ptr2 = NULL; *size2 = 0;
+        return(IOBUFF_ERR_OVERFLOW);
+      }
+    } 
+    else {
+      inst->status = BUFF_STATUS_NORMAL;
+      ret_val = IOBUFF_NOERR;
+    }
+  } 
+  else {
+    /* already in underflow and remain in underflow untill write pointer is 
+       ahead of read pointer */
+    ret_val = IOBUFF_ERR_UNDERFLOW;
+  }
+
+  /* return 1 or 2 pointers depending buffer wraps around or not */
+  *ptr1 = inst->write_ptr;  /* starting address to write */
+
+  /* check if write pointer is going to wrap around during this write */
+  address_end_of_write = (uint_least32_t)inst->write_ptr + mem_size;
+  if(address_end_of_write <= (uint_least32_t)inst->end) {  
+    /* write pointer not going to wrap aound, return only 1 pointer */
+    *size1 = mem_size;
+    *ptr2  = NULL; *size2 = 0;
+
+    new_write_ptr = (void *)address_end_of_write;
+    if(address_end_of_write == (uint_least32_t)inst->end) {
+      new_write_ptr = inst->base;
+    }
+  }
+  else {  
+    /* write pointer going to wrap around, return 2 pointers */
+    *size1 = (size_t)inst->end - (size_t)inst->write_ptr;
+    *ptr2  = inst->base;
+    *size2 = mem_size - *size1;
+    new_write_ptr = (void *)((uint_least32_t)inst->base + *size2);
+  }
+
+  /* update write pointer */
+  inst->write_ptr = new_write_ptr;
+
+  return (ret_val);
+} /* ioBuffGetWritePtrs */
+
+/*******************************************************************************
+* API function: Mark read completion
+*******************************************************************************/
+int ioBuffReadComplete(ioBuffHandle_t handle, void *read_begin, size_t read_size)
+{
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  inst->read_complete_ptr = (void *)((uint_least32_t)read_begin+read_size);
+  if(inst->read_complete_ptr >= inst->end) {
+    inst->read_complete_ptr = (void *) ((uint_least32_t)inst->read_complete_ptr 
+                                        - inst->size);
+    inst->rw_wrap_around ^= 1;   // toggle wrap around flag
+  }
+
+  return (IOBUFF_NOERR);
+}  /* ioBuffReadComplete */
+
+/*******************************************************************************
+* API function: Mark write completion
+*******************************************************************************/
+int ioBuffWriteComplete(ioBuffHandle_t handle, void *write_begin, size_t write_size)
+{
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  inst->write_complete_ptr = (void *)((uint_least32_t)write_begin+write_size);
+  if(inst->write_complete_ptr >= inst->end) {
+    inst->write_complete_ptr = (void *)((uint_least32_t)inst->write_complete_ptr 
+                                        - inst->size);
+    inst->rw_wrap_around ^= 1;   // toggle wrap around flag
+  }
+
+  return (IOBUFF_NOERR);
+}  /* ioBuffWriteComplete */
+
+
+int ioBuffGetInfo(ioBuffHandle_t handle, ioBuffInfo_t *info)
+{
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  info->base  = inst->base;
+  info->read  = inst->read_ptr;
+  info->write = inst->write_ptr;
+  info->size  = inst->size;
+
+  return (IOBUFF_NOERR);
+} /* ioBuffGetInfo */
+
+
+void * ioBuffWrapPointer(ioBuffHandle_t handle, void *pPtr)
+{
+  uint_least32_t ptr_temp;
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  ptr_temp = (uint_least32_t)pPtr;
+  if(ptr_temp >= (uint_least32_t)inst->end) {
+    ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
+  }
+
+  return ((void *)ptr_temp);
+} /* ioBuffWrapPointer */
+
+#if 0
+int ioBuffWrapPointer(ioBuffHandle_t handle, void **pPtr)
+{
+  uint_least32_t ptr_temp;
+  ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+  ptr_temp = (uint_least32_t)*pPtr;
+  if(ptr_temp >= (uint_least32_t)inst->end) {
+    ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
+  }
+
+  *pPtr = (void *)ptr_temp;
+
+  return (IOBUFF_NOERR);
+} /* ioBuffWrapPointer */
+#endif
+
+int ioBuffAdjustDelay(ioBuffHandle_t handle, size_t delay)
+{
+    size_t temp;
+    ioBuffInst_t *inst = (ioBuffInst_t *)handle;
+
+    if( (size_t)inst->write_complete_ptr >= ((size_t)inst->base+delay) ) {
+        inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->write_complete_ptr - delay);
+        inst->rw_wrap_around = 0;
+    }
+    else {
+        temp = delay - ((size_t)inst->write_complete_ptr - (size_t)inst->base);
+        inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->end - temp);
+        inst->rw_wrap_around = 1;
+    }
+
+    inst->nom_delay = delay;
+
+    return (IOBUFF_NOERR);
+} /* ioBuffAdjustDelay */
+
+/* Nothing past this point */
diff --git a/pasdk/test_dsp/io/ioBuff.h b/pasdk/test_dsp/io/ioBuff.h
new file mode 100644 (file)
index 0000000..78cd47c
--- /dev/null
@@ -0,0 +1,147 @@
+
+#ifndef _IOBUFF_H
+#define _IOBUFF_H
+
+#include <stdint.h>
+#include "libarch.h"
+/*
+ *  I/O buffer management API
+*/
+
+enum {
+  IOBUFF_NOERR         = 0,
+  IOBUFF_ERR_HANDLE,
+  IOBUFF_ERR_MEMORY,
+  IOBUFF_ERR_BAD_PARAMS,
+  IOBUFF_ERR_UNDERFLOW,
+  IOBUFF_ERR_OVERFLOW
+}; 
+
+enum {
+  IOBUff_NO_SYNC      = 0,
+  IOBUff_READ_SYNC,
+  IOBUFF_WRITE_SYNC,
+  IOBUFF_RW_SYNC
+};
+
+// I/O memory pool configuration parameters
+typedef struct ioBuffParams {
+  void          *base;        /* base address of I/O memory provided by the framework */
+  uint_fast32_t size;         /* size in MAU's (bytes) of I/O memory */
+  int_fast16_t  sync;         /* sync type: IOBUff_READ_SYNC, WRITE_SYNC, NO_SYNC, RW_SYNC */
+  uint_fast32_t nominalDelay; /* nominal delay as # of MAU's between write and read */
+} ioBuffParams_t; 
+
+typedef void * ioBuffHandle_t;
+
+typedef struct ioBuffInfo_s {
+  void *base;
+  void *read;
+  void *write;
+  uint_fast32_t size;
+} ioBuffInfo_t;
+
+/**
+ *  @brief ioBuffNumAlloc
+ *    Returns the maximum number of memory allocation requests that ioBuffAlloc() 
+ *    requires.
+ */
+int ioBuffNumAlloc(void);
+
+/**
+ *  @brief ioBuffAlloc
+ *    Returns a table of memory records that describe the size, alignment, type 
+ *    and memory space of all buffers required by this component. 
+ */
+int ioBuffAlloc(lib_mem_rec_t *mem_tbl);
+
+/**
+ *  @brief ioBuffCreate
+ *    Based on the provided memory blocks, this function creates an I/O BUFF
+ *    instance and returns a handle. This handle points to the memory block
+ *    that contains the instance.
+ */
+int ioBuffCreate(ioBuffHandle_t *handle, const lib_mem_rec_t *mem_tbl);
+
+/**
+ *  @brief ioBuffInit
+ *    Initializes the I/O buffer management instance. 
+ */
+int ioBuffInit (ioBuffHandle_t handle, const ioBuffParams_t *params);
+
+/**
+ *  @brief ioBuffGetReadPtrs
+ *    Provides pointers to read a given size of data from the I/O buffer. 
+ *      - If I/O buffer wrapps around, two pointers will be provided, each with 
+ *        a corresponding read size. 
+ *      - If I/O buffer does not wrapp around, one pointer and the corresponding 
+ *        size will be provided. The size will be equal to the input mem_size. 
+ *        The second pointer will be NULL and the corresponding size will be 
+ *        zero. 
+ *     
+ *  @param[in]   handle
+ *  @param[in]   mem_size       size of data to be read
+ *  @param[out]  rdptr1         read pointer 1
+ *  @param[out]  size1          read size corresponding to pointer 1
+ *  @param[out]  rdptr2         read pointer 2 
+ *  @param[out]  size2          read size corresponding to pointer 2
+ *
+ */
+int ioBuffGetReadPtrs(ioBuffHandle_t handle, size_t mem_size, 
+                    void **rdptr1, size_t *size1, 
+                    void **rdptr2, size_t *size2);
+
+/**
+ *  @brief ioBuffGetWritePtrs
+ *    Provides pointers to write a given size of data to the I/O buffer. 
+ *      - If I/O buffer wrapps around, two pointers will be provided, each with 
+ *        a corresponding write size. 
+ *      - If I/O buffer does not wrapp around, one pointer and the corresponding 
+ *        size will be provided. The size will be equal to the input mem_size. 
+ *        The second pointer will be NULL and the corresponding size will be 
+ *        zero. 
+ *     
+ *  @param[in]   handle
+ *  @param[in]   mem_size       size of data to be written to the I/O buffer
+ *  @param[out]  wrptr1         write pointer 1
+ *  @param[out]  size1          write size corresponding to pointer 1
+ *  @param[out]  wrptr2         write pointer 2 
+ *  @param[out]  size2          write size corresponding to pointer 2
+ *
+ */
+int ioBuffGetWritePtrs(ioBuffHandle_t handle, size_t mem_size, 
+                    void **wrptr1, size_t *size1, 
+                    void **wrptr2, size_t *size2);
+
+/**
+ *  @brief ioBuffReadComplete
+ *    Marks a portion of the I/O buffer as read complete so that the data in it
+ *    can be overwritten now.
+ *     
+ *  @param[in]  handle
+ *  @param[in]  start          start address of the read-completed portion 
+ *  @param[in]  size           size of the read-completed portion 
+ *
+ *  @remark   If two buffers, then size should be sum of two sizes.....
+ */
+int ioBuffReadComplete(ioBuffHandle_t handle, void *start, size_t size);
+
+/**
+ *  @brief ioBuffWriteComplete
+ *    Marks a portion of the I/O buffer as write complete so that the data in it
+ *    can be read now.
+ *     
+ *  @param[in]  handle
+ *  @param[in]  start          start address of the write-completed portion 
+ *  @param[in]  size           size of the write-completed portion 
+ *
+ */
+int ioBuffWriteComplete(ioBuffHandle_t handle, void *start, size_t size);
+
+int ioBuffGetInfo(ioBuffHandle_t handle, ioBuffInfo_t *info);
+
+void * ioBuffWrapPointer(ioBuffHandle_t handle, void * pPtr);
+
+int ioBuffAdjustDelay(ioBuffHandle_t handle, size_t delay);
+
+#endif
diff --git a/pasdk/test_dsp/io/ioBuff_loc.h b/pasdk/test_dsp/io/ioBuff_loc.h
new file mode 100644 (file)
index 0000000..ee5d670
--- /dev/null
@@ -0,0 +1,24 @@
+
+#include <stdint.h>
+
+#define BUFF_STATUS_NORMAL     0 
+#define BUFF_STATUS_UNDERFLOW  1
+#define BUFF_STATUS_OVERFLOW   2
+
+typedef struct ioBuffInst_s {
+
+  void *base;
+  void *end;
+  void *read_ptr;
+  void *read_complete_ptr;
+  void *write_ptr;
+  void *write_complete_ptr;
+
+  uint_least32_t size;
+  int_fast16_t   sync;   /* sync type: ioBUff_READ_SYNC, WRITE_SYNC, NO_SYNC, RW_SYNC */
+  uint_fast32_t  nom_delay;  /* nominal delay as # of MAU's between write and read */
+
+  uint_fast16_t  status;  /* overflow, underflow, normal */
+  uint_fast16_t  rw_wrap_around;  /* flag to indicate write pointer wraps around 
+                                     but read pointer has not yet */
+} ioBuffInst_t;
diff --git a/pasdk/test_dsp/io/ioConfig.h b/pasdk/test_dsp/io/ioConfig.h
new file mode 100644 (file)
index 0000000..d50cf0d
--- /dev/null
@@ -0,0 +1,83 @@
+
+#ifndef IO_CONFIG_H
+#define IO_CONFIG_H
+
+#define PASDK_SIO_DEV         // define this to use the legacy SIO/DEV based I/O driver
+
+//#define IO_LOOPBACK_TEST        // define this to run a loopback test bypassing PASDK processing
+
+#define INPUT_HDMI_4xI2S        // HDMI, 4 Rx serializers
+//#define INPUT_HDMI_STEREO       // HDMI, 1 Rx serializer
+//#define INPUT_SPDIF             // S/PDIF, 1 Rx serializer
+
+//#define INPUT_PCM_ONLY        // debugging, input fixed to PCM
+
+#ifdef INPUT_HDMI_4xI2S
+#define RX_MCASP_USE_MULT_SER
+#define TX_MCASP_USE_MULT_SER   // This is the normal operation. Undefine this for debugging and loopback
+//#define ASIP_ELEMENT_SIZE      2
+//#define ASIP_STRIDE            8    // 4 lane, stereo
+#endif
+
+#ifdef INPUT_HDMI_STEREO
+//#define ASIP_ELEMENT_SIZE      4
+//#define ASIP_STRIDE            2    // 1 lane, stereo
+#endif
+
+#ifdef INPUT_SPDIF
+//#define ASIP_ELEMENT_SIZE      4
+//#define ASIP_STRIDE            2    // 1 lane, stereo
+#endif
+
+// two options regarding I/O PHY transfer size and I/O DATA read size:
+//    1. fixed to 1024 words: simple for implementation and debugging, shorter delay,
+//            but more interrupts and more McASP LLD calls.
+//    2. adjusted to frame size after auto-detection: less interrupts and McASP LLD calls,
+//            but more complicated implementation and longer delay.
+#define ADJUST_XFER_SIZE_AFTER_AUTODET
+
+
+// Number of serializers configured for Rx McASP
+#ifdef RX_MCASP_USE_MULT_SER
+#define NUM_RX_SERIALIZER       4
+#else
+#define NUM_RX_SERIALIZER       1
+#endif
+
+// Number of serializers configured for Tx McASP
+#ifdef TX_MCASP_USE_MULT_SER
+#define NUM_TX_SERIALIZER       4
+#else
+#define NUM_TX_SERIALIZER       1
+#endif
+
+/* Number of submitted transfers in McASP LLD priming operation.
+ * Due to McASP LLD issue, there must be 3 or more transfer submits in priming.  */
+#define NUM_PRIME_XFERS         3   // 3 and above is good
+
+// Define McASP transfer element size: number of bytes in one word
+#define WORD_SIZE_BITSTREAM     2
+#define WORD_SIZE_PCM           4
+
+// Input frame length: number of words to be transfered in 1 transfer of McASP LLD Rx
+// These numbers are according to existing SIO/DEV based I/O.
+#ifdef INPUT_HDMI_4xI2S
+#define INPUT_FRAME_LENGTH      (256*NUM_RX_SERIALIZER)    // 128 stereo/lane
+#else
+//#define INPUT_FRAME_LENGTH      (128*NUM_RX_SERIALIZER)    // 64 stereo/lane
+#define INPUT_FRAME_LENGTH      (256*NUM_RX_SERIALIZER)    // 128 stereo/lane
+#endif
+
+// Input frame size: number of bytes to be transfered in 1 transfer of McASP LLD Rx
+#define INPUT_FRAME_SIZE_DEF    (INPUT_FRAME_LENGTH * WORD_SIZE_BITSTREAM)
+#define INPUT_FRAME_SIZE_PCM    (INPUT_FRAME_LENGTH * WORD_SIZE_PCM)
+
+// Output frame length: number of words to be transfered in 1 transfer of McASP LLD Tx
+#define OUTPUT_FRAME_LENGTH     (256*NUM_TX_SERIALIZER)    // 128 stereo/lane
+
+// Output frame size: number of bytes to be transfered in 1 transfer of McASP LLD Tx
+#define OUTPUT_FRAME_SIZE       (OUTPUT_FRAME_LENGTH * WORD_SIZE_PCM)
+
+
+
+#endif
diff --git a/pasdk/test_dsp/io/ioData.c b/pasdk/test_dsp/io/ioData.c
new file mode 100644 (file)
index 0000000..dd630c7
--- /dev/null
@@ -0,0 +1,877 @@
+
+
+#include <stdint.h>
+#include <limits.h> //INT_MAX
+
+#include "ioData.h"
+#include "iobuff.h"
+
+//#include "ioDataLoc.h"
+
+#include <ti/sysbios/hal/Cache.h>
+
+#define IODATA_NUM_MEM_ALLOCS   1
+#define IODATA_INST_ALIGN       3
+
+#define IODATA_NUM_BYTES_BITSTREAM  2
+#define IODATA_NUM_BYTES_PCMSAMPLE  4
+
+#define IODATA_ELEMENT_SIZE_DEF  IODATA_NUM_BYTES_BITSTREAM
+
+#define TRUE                  1
+#define FALSE                 0
+
+#define IODATA_SYNC_PC_MASK         0x1F
+#define IODATA_SYNC_SUBTYPE_MASK    0x700
+#define IODATA_SYNC_SUBTYPE_SHIFT   8
+#define IODATA_SYNC_SUBTYPE_DTSHD   0x11
+#define IODATA_SYNC_DDP             0x15
+#define IODATA_SYNC_THD             0x16
+
+#define IODATA_MIN_NUM_ZEROS_BEFORE_PA   2
+#define IODATA_PREAMBLE_MAX_LEN          8          // TBD
+#define IODATA_HEADER_LENGTH_IEC         4
+#define IODATA_HEADER_CHECK_LENGTH_IEC   2  // For IEC, only look at 2 words to check SYNC.
+
+#define IEC_PA       ((uint_least16_t) 0xF872)
+#define IEC_PB       ((uint_least16_t) 0x4E1F)
+#define DTS16_SYNC_A ((uint_least16_t) 0x7FFE)
+#define DTS16_SYNC_B ((uint_least16_t) 0x8001)
+#define DTS16_SYNC_C ((uint_least16_t) 0xFC00)
+#define DTS14_SYNC_A ((uint_least16_t) 0x1FFF)
+#define DTS14_SYNC_B ((uint_least16_t) 0xE800)
+#define DTS14_SYNC_C ((uint_least16_t) 0x07F0)
+
+#define  DTS_BURST_TYPE_I  0x008B
+#define  DTS_BURST_TYPE_II 0x018C
+#define  DTS_BURST_TYPE_III 0x028D
+#define  DTS_BURST_TYPE_IV  0x0491
+
+#define  DTS_BURST_TYPE_IV_CBR  0x02
+#define  DTS_BURST_TYPE_IV_LBR  0x03
+#define  DTS_BURST_TYPE_IV_HBR  0x04
+
+#define min(a, b)  (((a) < (b)) ? (a) : (b))
+#define max(a, b)  (((a) > (b)) ? (a) : (b))
+
+//IBMODE
+enum
+{
+    IBMODE_DEFAULT = 0,
+    IBMODE_NO_ZERORUNRESTART = 1,
+    IBMODE_NO_ZERORUN = 2
+};
+
+enum {
+       AUTODET_RESET = 0,
+       AUTODET_SYNC_SEARCH_INITIAL,
+       AUTODET_SYNC_SEARCH_PCM,
+       AUTODET_SYNC_CHECK_ONGOING
+};
+
+// scanState
+enum
+{
+    SCANNED_NONE,
+    SCANNED_IEC_PA,
+    SCANNED_IEC_PB,
+    SCANNED_IEC_PC,
+    SCANNED_IEC_PD,
+    SCANNED_DTS14_SYNC_A,
+    SCANNED_DTS14_SYNC_B,
+    SCANNED_DTS14_SYNC_C,
+    SCANNED_DTS14_SYNC_D,
+    SCANNED_DTS16_SYNC_A,
+    SCANNED_DTS16_SYNC_B,
+    SCANNED_DTS16_SYNC_C
+};
+
+typedef struct autoDet_s {
+  int_least32_t    frameLength;
+  int_least32_t    timeOutCntr;
+  uint_least32_t   zeroCount;
+  uint_least32_t   numElementsRcvd;
+  uint_least32_t   distToFrameEnd;
+
+  uint_least16_t   preambleRef[IODATA_PREAMBLE_MAX_LEN];
+  uint_least16_t   preambleBuf[IODATA_PREAMBLE_MAX_LEN];
+  int_fast32_t     preambleInd;
+  uint8_t          headerLength;
+  uint8_t          headerCheckLen;
+
+  uint_least16_t    scanState;
+  uint_least16_t    checkState;
+
+  int8_t           ibMode;
+  int8_t           timeOutStarted;
+  int8_t           preambleStartsPrevBuf;
+  int8_t           syncDetected;
+  int8_t           syncLost;
+  int8_t           completeFrameRcvd;
+  uint_least16_t   syncState;
+  uint_least16_t   bitStreamInfo;
+  uint_least16_t   *bitStreamSyncPtr;
+  uint_least16_t   *frameDataStartTemp;
+  uint_least16_t   *frameDataStartConfirm;
+} autoDet_t;
+
+typedef struct ioDataDebug_s {
+  uint_least32_t   numFramesRcvd;
+  uint_least32_t   numBuffUnderflow;
+  uint_least32_t   numSyncLost;
+
+} ioDataDebug_t;
+
+typedef struct ioDataInst_s {
+  autoDet_t        autoDet;
+  ioDataDebug_t    dbgStats;
+  uint_least16_t   autoDetState;
+  uint_least16_t   *IECframeLengths;
+  uint_least16_t   frameLengthPCM;
+  uint_least16_t   frameLengthDef;
+  uint_least32_t   frameLength;        // frame length: number of elements in a frame
+  uint_least32_t   numElementsRead;    // number of elements to read from input buffer
+  uint_least32_t   distToFrameEnd;
+  int8_t           elementSize;
+  ioBuffHandle_t   ioBuffHandle;
+  uint_least32_t   zeroRunTrigger;
+  uint_least32_t   zeroRunRestart;
+  int_least32_t    timeOutCntr;
+  uint_least32_t   unknownSourceTimeOut;
+
+  uint_least16_t   *frameDataStart;
+  size_t            frameDataSize;
+  uint8_t   deliverZeros;
+  uint8_t   ioBuffUnderFlow;
+  void *buff1;
+  void *buff2;
+  size_t size1;
+  size_t size2;
+
+} ioDataInst_t;
+
+
+// TODO: put this data structure somewhere, or use ioDataNumAlloc & ioDataAlloc to
+// dynamically allocate memory.
+//ioDataInst_t ioDataInst;
+
+void autoDetection(ioDataInst_t * pIoDataInst);
+void autoDetReset(ioDataInst_t * pIoDataInst);
+
+
+
+/*******************************************************************************
+* API function: ioDataNumAlloc
+*    Returns the maximum number of memory allocation requests that ioDataAlloc()
+*    requires.
+*******************************************************************************/
+int ioDataNumAlloc(void)
+{
+  return (IODATA_NUM_MEM_ALLOCS);
+} /* ioDataNumAlloc */
+
+/*******************************************************************************
+* API function: ioDataAlloc
+*    Returns a table of memory records that describe the size, alignment, type
+*    and memory space of all buffers required by I/O DATA component.
+*******************************************************************************/
+int ioDataAlloc(lib_mem_rec_t *mem_tbl)
+{
+  mem_tbl[0].size = sizeof(ioDataInst_t);
+  mem_tbl[0].alignment = IODATA_INST_ALIGN;
+  mem_tbl[0].type = LIB_PMEM_SLOW;
+  mem_tbl[0].base = NULL;
+
+  return (IODATA_NO_ERR);
+} /* ioDataAlloc */
+
+/*******************************************************************************
+* API function: ioDataCreate
+*    Create an I/O DATA instance.
+*******************************************************************************/
+int ioDataCreate(ioDataHandle_t *handle, const lib_mem_rec_t *mem_tbl)
+{
+  ioDataInst_t *inst;
+
+  if(  (mem_tbl[0].size < sizeof(ioDataInst_t))
+     ||libChkAlign(mem_tbl[0].base, IODATA_INST_ALIGN) ) {
+    // to add: check memory type
+    return (IODATA_ERR_MEMORY);
+  }
+
+  inst = (ioDataInst_t *)mem_tbl[0].base;
+
+  *handle = (ioDataHandle_t)inst;
+
+  return (IODATA_NO_ERR);
+} /* ioDataCreate */
+
+/*=============================================================================
+ * API function: this function initializes I/O data processing.
+ =============================================================================*/
+int ioDataInit(ioDataHandle_t handle, ioDataParam_t *cfgParams)
+{
+  ioDataInst_t *pIoDataInst = (ioDataInst_t *)handle;
+
+  if(cfgParams == NULL) {
+    return (IODATA_ERR_BAD_PARAMS);
+  }
+
+  pIoDataInst->ioBuffHandle    = cfgParams->ioBuffHandle;
+  pIoDataInst->IECframeLengths = cfgParams->frameLengthsIEC;
+  pIoDataInst->frameLengthPCM  = cfgParams->frameLengthPCM;
+  pIoDataInst->frameLengthDef  = cfgParams->frameLengthDef;
+  pIoDataInst->autoDet.ibMode  = cfgParams->ibMode;
+  pIoDataInst->zeroRunRestart  = cfgParams->zeroRunRestart;
+  pIoDataInst->zeroRunTrigger  = cfgParams->zeroRunTrigger;
+  pIoDataInst->unknownSourceTimeOut = cfgParams->unknownSourceTimeOut*2;
+  pIoDataInst->autoDetState         = AUTODET_SYNC_SEARCH_INITIAL;
+  pIoDataInst->dbgStats.numSyncLost = 0;
+  pIoDataInst->ioBuffUnderFlow      = FALSE;
+
+  autoDetReset(pIoDataInst);
+  
+  return IODATA_NO_ERR;
+} /* ioDataInit */
+
+
+/*=============================================================================
+ * API function: main function of I/O DATA component processing.
+ =============================================================================*/
+int ioDataProcess(ioDataHandle_t ioDataHandle)
+{
+  void *buff1, *buff2;
+  size_t size1, size2;
+  int status;
+  ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
+
+  // Get read pointers (or sub-buffers) of the input buffer
+  status = ioBuffGetReadPtrs(pIoDataInst->ioBuffHandle,
+                             pIoDataInst->numElementsRead*pIoDataInst->elementSize,
+                             &buff1, &size1, &buff2, &size2);
+  if(status == IOBUFF_ERR_UNDERFLOW) {
+         pIoDataInst->ioBuffUnderFlow = TRUE;
+         pIoDataInst->dbgStats.numBuffUnderflow += 1;
+
+      /* skip processing since there is no enough data to process */
+      return IODATA_ERR_IOBUF_UNDERFLOW;
+  }
+
+  // Store read pointers and sizes to instance for auto-detection to read
+  pIoDataInst->ioBuffUnderFlow = FALSE;
+  pIoDataInst->buff1 = buff1;
+  pIoDataInst->buff2 = buff2;
+  pIoDataInst->size1 = size1;
+  pIoDataInst->size2 = size2;
+
+  autoDetection(pIoDataInst);
+
+  return IODATA_NO_ERR;
+} /* ioDataProcess */
+
+
+/*=============================================================================
+ * API function - this function marks the sub-buffers provided by I/O BUFF as
+ * read complete. It makes API call to the associated I/O BUFF component to mark
+ * the data as reading completed.
+ =============================================================================*/
+int ioDataReadComplete(ioDataHandle_t ioDataHandle)
+{
+  ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
+
+  // If the associated I/O buffer underflows, i.e. no enough data to read, do not
+  // call I/O BUFF API to mark read complete.
+  if(pIoDataInst->ioBuffUnderFlow) {
+         return IODATA_ERR_IOBUF_UNDERFLOW;
+  }
+
+  ioBuffReadComplete(pIoDataInst->ioBuffHandle, pIoDataInst->buff1, pIoDataInst->size1);
+
+  if(pIoDataInst->buff2 != NULL) {
+    ioBuffReadComplete(pIoDataInst->ioBuffHandle, pIoDataInst->buff2, pIoDataInst->size2);
+  }
+
+  return IODATA_NO_ERR;
+} /* ioDataReadComplete */
+
+
+/*=============================================================================
+ * API function - this function allows framework to dynamically control I/O data
+ *                component or get information from it.
+ =============================================================================*/
+int ioDataControl(ioDataHandle_t ioDataHandle, ioDataCtl_t *ioDataCtl)
+{
+  ioBuffInfo_t ioBuffInfo;
+
+  ioDataInst_t *pIoDataInst = (ioDataInst_t *)ioDataHandle;
+
+  switch (ioDataCtl->code)
+  {
+
+    case IODATA_CTL_SET_ELEMENT_SIZE:
+       pIoDataInst->elementSize = ioDataCtl->param.frameInfo.elementSize;
+      break;
+
+    case IODATA_CTL_SET_FRAME_LENGTH:
+       pIoDataInst->frameLength = ioDataCtl->param.frameInfo.frameLength;
+      break;
+
+    case IODATA_CTL_GET_INPBUFFINFO:
+       ioBuffGetInfo(pIoDataInst->ioBuffHandle, &ioBuffInfo);
+       ioDataCtl->param.dataReadInfo.buffBase     = ioBuffInfo.base;
+       ioDataCtl->param.dataReadInfo.buffSize     = ioBuffInfo.size;
+       ioDataCtl->param.dataReadInfo.startAddress = pIoDataInst->frameDataStart;
+       ioDataCtl->param.dataReadInfo.frameSize    = pIoDataInst->frameDataSize;
+       break;
+
+    case IODATA_CTL_GET_AUTODET_STATUS:
+      ioDataCtl->param.autoDetStats.syncState     = pIoDataInst->autoDet.syncState;
+      ioDataCtl->param.autoDetStats.deliverZeros  = pIoDataInst->deliverZeros;
+      ioDataCtl->param.autoDetStats.bitStreamInfo = pIoDataInst->autoDet.bitStreamInfo;
+      break;
+/*
+    case IODATA_CTL_GET_STEAM_INFO:
+      break;
+*/
+    default:
+      break;
+  }
+
+  return IODATA_NO_ERR;
+} /* ioDataControl */
+
+//========== internal functions - to be moved to a different file ==========
+void autoDetSyncScan(ioDataInst_t * pIoDataInst);
+void autoDetSyncCheck(ioDataInst_t * pIoDataInst);
+void syncScan(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet);
+void syncCheck(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet);
+void syncCheckInit(ioDataInst_t * pIoDataInst);
+void syncScanPcmInit(ioDataInst_t * pIoDataInst);
+
+/*=============================================================================
+ * Main function of auto-detection of the I/O DATA component.
+ =============================================================================*/
+void autoDetection(ioDataInst_t * pIoDataInst)
+{
+  switch(pIoDataInst->autoDetState)
+  {    
+    case AUTODET_SYNC_SEARCH_INITIAL:
+      /* Search for SYNC the first time */
+      autoDetSyncScan(pIoDataInst);
+
+      if(pIoDataInst->autoDet.syncDetected) {
+        syncCheckInit(pIoDataInst);  // prepare for SYNC checking in subsequent frames
+
+        pIoDataInst->autoDet.frameDataStartConfirm = pIoDataInst->autoDet.frameDataStartTemp;
+        pIoDataInst->autoDet.syncState = IODATA_SYNC_ONE;      // found SYNC once and to be verified
+        pIoDataInst->autoDetState = AUTODET_SYNC_CHECK_ONGOING;
+      }      
+      /* Check time out counter if SYNC is not found:
+           - if autoDet.timeOutStarted == FALSE (no non-zero data has been received), look at pIoDataInst->timeOutCntr
+           - if autoDet.timeOutStarted == TRUE,  look at pIoDataInst->autoDet.timeOutCntr
+      */
+      else if(   ((!pIoDataInst->autoDet.timeOutStarted) && (pIoDataInst->timeOutCntr <= 0))
+                 || (pIoDataInst->autoDet.timeOutCntr <= 0) ) {
+        /* Time out, decide whether to reset or go to PCM */
+           if (  (pIoDataInst->autoDet.ibMode == IBMODE_DEFAULT) 
+            &&(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunRestart) ) {
+             /* Reset if zero-run is long enough */
+          autoDetReset(pIoDataInst);
+             pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
+           }
+           else {
+             // inform decoder where to read PCM data
+             pIoDataInst->frameDataStart = pIoDataInst->buff1;
+             pIoDataInst->frameDataSize  = pIoDataInst->size1;
+             if(pIoDataInst->buff2 != NULL) {
+               pIoDataInst->frameDataSize  += pIoDataInst->size2;
+             }
+
+             // Go to PCM scanning - to play out PCM and keep scanning for SYNC 
+             syncScanPcmInit(pIoDataInst);
+          pIoDataInst->autoDet.syncState = IODATA_SYNC_PCM;
+             pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_PCM;
+           }
+      }      
+      break;
+    
+    case AUTODET_SYNC_SEARCH_PCM:
+      /* Search for SYNC while PCM is played out */
+      autoDetSyncScan(pIoDataInst);
+      
+      /* Check if SYNC is detected or there is zero-run */
+      if(pIoDataInst->autoDet.syncDetected) {
+        autoDetReset(pIoDataInst);
+        pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
+      }
+      else {
+        // inform decoder where to read PCM data 
+        pIoDataInst->frameDataStart = pIoDataInst->buff1;    
+        pIoDataInst->frameDataSize  = pIoDataInst->frameLengthPCM*pIoDataInst->elementSize;
+
+        pIoDataInst->deliverZeros = FALSE;
+        
+        if(pIoDataInst->autoDet.ibMode == IBMODE_DEFAULT) {
+          if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunTrigger) {
+            pIoDataInst->deliverZeros = TRUE;
+          }
+
+          if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunRestart) {
+               /* Reset if zero-run is long enough */
+            autoDetReset(pIoDataInst);
+               pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;              
+          }
+        }
+        else if(pIoDataInst->autoDet.ibMode == IBMODE_NO_ZERORUNRESTART) {
+          if(pIoDataInst->autoDet.zeroCount >= pIoDataInst->zeroRunTrigger) {
+               pIoDataInst->deliverZeros = TRUE;              
+          }
+        }
+        else {
+          // ibMode = IBMODE_NO_ZERORUN. Stay in this state and do nothing
+        }          
+      }
+      
+      break;
+
+    case AUTODET_SYNC_CHECK_ONGOING:
+      autoDetSyncCheck(pIoDataInst);
+
+         /* Check if a full frame has been received and if so, check if SYNC is maintained */
+      if(pIoDataInst->autoDet.completeFrameRcvd) {
+               if(pIoDataInst->autoDet.syncDetected) {
+                 pIoDataInst->autoDet.syncState = IODATA_SYNC_BITSTREAM;
+         pIoDataInst->autoDet.completeFrameRcvd = FALSE;
+
+         // Inform decoder to read data from the beginning of current frame (after the preamble)
+         // Note: this address could be 1-word pass the end of input buffer and therefore needs
+         //       to be wrapped around by ioBuffWrapPointer().
+         pIoDataInst->frameDataStart = ioBuffWrapPointer(pIoDataInst->ioBuffHandle,
+                                                                 pIoDataInst->autoDet.frameDataStartConfirm);
+          pIoDataInst->frameDataSize  = pIoDataInst->autoDet.frameLength*pIoDataInst->elementSize;
+
+         // Store the beginning address of data in current frame (not including the preamble)
+         pIoDataInst->autoDet.frameDataStartConfirm = pIoDataInst->autoDet.frameDataStartTemp;
+         pIoDataInst->dbgStats.numFramesRcvd += 1;
+
+         // re-initialize for SYNC check
+                 syncCheckInit(pIoDataInst);
+               }
+               else {
+                 pIoDataInst->dbgStats.numSyncLost += 1;            // what else needs to be done???
+             autoDetReset(pIoDataInst);
+             pIoDataInst->autoDetState = AUTODET_SYNC_SEARCH_INITIAL;
+                 pIoDataInst->autoDet.syncState = IODATA_SYNC_NONE;
+               }
+         }
+      else {
+               ; //pIoDataInst->autoDet.syncState = IODATA_SYNC_CHECK;
+      }
+    break;
+    
+    default: break;
+  }
+
+} /* autoDetection */
+
+/*=============================================================================
+ * This function resets auto-detection.
+ =============================================================================*/
+void autoDetReset(ioDataInst_t * pIoDataInst)
+{
+       pIoDataInst->deliverZeros           = FALSE;
+       pIoDataInst->autoDet.zeroCount      = 0;
+       pIoDataInst->autoDet.syncState      = IODATA_SYNC_NONE;
+       pIoDataInst->autoDet.scanState      = SCANNED_NONE;
+       pIoDataInst->autoDet.timeOutStarted = FALSE;
+       pIoDataInst->autoDet.syncDetected   = FALSE;
+       pIoDataInst->autoDet.timeOutCntr    = pIoDataInst->unknownSourceTimeOut;
+       //pIoDataInst->autoDet.timeOutCntr    = pIoDataInst->unknownSourceTimeOut*20;
+       pIoDataInst->numElementsRead        = pIoDataInst->frameLengthDef;
+       pIoDataInst->elementSize            = IODATA_ELEMENT_SIZE_DEF;
+
+       pIoDataInst->timeOutCntr            = pIoDataInst->unknownSourceTimeOut;
+       //pIoDataInst->timeOutCntr            = pIoDataInst->unknownSourceTimeOut*20;
+       pIoDataInst->dbgStats.numFramesRcvd = 0;
+       pIoDataInst->dbgStats.numBuffUnderflow = 0;
+} /* autoDetReset */
+
+/*=============================================================================
+ * This function re-initializes auto-detection for scanning SYNC in PCM data
+ =============================================================================*/
+void syncScanPcmInit(ioDataInst_t * pIoDataInst)
+{
+       //pIoDataInst->deliverZeros           = FALSE;
+       //pIoDataInst->autoDet.zeroCount      = 0;
+       //pIoDataInst->autoDet.scanState      = SCANNED_NONE;
+       //pIoDataInst->autoDet.timeOutStarted = FALSE;
+       //pIoDataInst->autoDet.syncDetected   = FALSE;
+       //pIoDataInst->autoDet.timeOutCntr    = pIoDataInst->unknownSourceTimeOut*2;
+       //pIoDataInst->autoDet.timeOutCntr    = pIoDataInst->unknownSourceTimeOut*20;
+       pIoDataInst->numElementsRead        = pIoDataInst->frameLengthPCM;
+       //pIoDataInst->timeOutCntr            = pIoDataInst->unknownSourceTimeOut*2;
+       //pIoDataInst->timeOutCntr            = pIoDataInst->unknownSourceTimeOut*20;
+       pIoDataInst->elementSize            = IODATA_NUM_BYTES_PCMSAMPLE;
+} /* syncScanPcmInit */
+
+/*=============================================================================
+ * Initialization for checking sync in subsequent bitstream frames.
+ =============================================================================*/
+void syncCheckInit(ioDataInst_t * pIoDataInst)
+{
+       int i;
+       uint_least16_t pc = pIoDataInst->autoDet.bitStreamInfo & IODATA_SYNC_PC_MASK;
+
+       pIoDataInst->autoDet.frameLength    = pIoDataInst->IECframeLengths[pc];
+       pIoDataInst->autoDet.distToFrameEnd = pIoDataInst->autoDet.frameLength
+                                                     - pIoDataInst->autoDet.numElementsRcvd;
+
+//#ifdef ADJUST_XFER_SIZE_AFTER_AUTODET
+#if 1
+       // Adjust the read size such that next read will contain the preamble of next
+       // frame at the end of the read. For first frame after SYNC is detected, the
+       // read size will be smaller than frame size. For subsequent frames, the read
+       // size will be equal to the frame size.
+    pIoDataInst->numElementsRead = pIoDataInst->autoDet.distToFrameEnd
+                                      + pIoDataInst->autoDet.headerLength;
+#endif
+
+       pIoDataInst->autoDet.preambleStartsPrevBuf = FALSE;
+       pIoDataInst->autoDet.completeFrameRcvd = FALSE;
+       pIoDataInst->autoDet.syncDetected = FALSE;
+       pIoDataInst->autoDet.preambleInd = 0;
+
+       for(i=0; i<pIoDataInst->autoDet.headerLength; i++)
+       {
+               pIoDataInst->autoDet.preambleBuf[i] = 0x0;
+       }
+} /* syncCheckInit */
+
+
+/*=============================================================================
+ * This function scans for sync word (preamble) in the input buffer while
+ * checking for time out. It calls subroutine syncScan to scan the data.
+ *
+ * The read pointer(s) to the input buffer and the read sizes are provided by
+ * the I/O BUFF component and stored in auto-detection instance. The read
+ * pointers are also refered as sub-buffers.
+ *
+ * NOte: Since the input buffer may wrapp around, there may be two sub-buffers,
+ *       one at the end of the input buffer and the other at the beginning,
+ *       provided to auto-detection. In this case, syncScan subroutine will be
+ *       called twice.
+ =============================================================================*/
+void autoDetSyncScan(ioDataInst_t * pIoDataInst)
+{
+       /* scan first sub-buffer for sync */
+       if((pIoDataInst->buff1 != NULL) && (pIoDataInst->size1 != 0)) {
+               syncScan(pIoDataInst->buff1, pIoDataInst->size1, pIoDataInst->elementSize,
+                               &pIoDataInst->autoDet);
+               pIoDataInst->timeOutCntr -= pIoDataInst->size1/pIoDataInst->elementSize;
+       }
+
+       /* check if sync word is found in the first sub-buffer */
+       if(pIoDataInst->autoDet.syncDetected) {
+               /* skip scanning second sub-buffer if sync is detected */
+               if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
+                       /* update the number of received elements in current frame */
+                   pIoDataInst->autoDet.numElementsRcvd += pIoDataInst->size2;
+               }
+       }
+       else if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
+               /* scan second sub-buffer if there are two sub-buffers */
+               syncScan(pIoDataInst->buff2, pIoDataInst->size2, pIoDataInst->elementSize,
+                               &pIoDataInst->autoDet);
+               pIoDataInst->timeOutCntr -= pIoDataInst->size2/pIoDataInst->elementSize;
+       }
+} /* ioDataAutoDetSyncScan */
+
+/*=============================================================================
+ * This function scans for sync word (preamble) in the provided sub-buffer.
+ =============================================================================*/
+void syncScan(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet)
+{
+       uint_least16_t  *pbuf;
+    int i, stride, scanCount, zeroCount;
+    uint_least16_t scanState;
+    uint_least16_t *syncPtr;
+
+       pbuf = (uint_least16_t *)buff;
+
+       /* check element size */
+    if (elementSize == IODATA_NUM_BYTES_PCMSAMPLE) {
+       /* skip every other 16-bit number and only look at MSB of PCM samples */
+        stride = IODATA_NUM_BYTES_PCMSAMPLE / sizeof(uint_least16_t);
+        pbuf += 1;
+    }
+    else {
+        stride = 1;
+    }
+
+    /* get ready for scanning */
+    scanCount = 0;
+    zeroCount = pDet->zeroCount;
+    scanState = pDet->scanState;
+
+    /* check if part of the sync words (preamble) are found in previous call */
+    if(scanState != SCANNED_NONE) {
+       /* count this sub-buffer in the number of received elements in current frame */
+       pDet->numElementsRcvd += size/sizeof(uint_least16_t);
+    }
+
+    /* scan until out of available data or sync is found */
+    for (i=0; i < size/elementSize; i+=stride) {
+       uint_least16_t tail = pbuf[i];
+
+        if (scanState == SCANNED_NONE) {
+            if (tail == IEC_PA) {
+                /* make sure there are some zeros before PA. */
+                if (zeroCount >= IODATA_MIN_NUM_ZEROS_BEFORE_PA) {
+                    scanState = SCANNED_IEC_PA;
+                    syncPtr = &pbuf[i];  /* mark the position of PA */
+                }
+            }
+
+            if(scanState != SCANNED_NONE) {
+               /* Found first sync word. Save its address */
+               pDet->bitStreamSyncPtr = syncPtr;
+
+               /* number of elements in current frame that have been received
+                * in this sub-buffer, including the preamble (sync words). */
+                pDet->numElementsRcvd = size/sizeof(uint_least16_t) - i;
+                pDet->preambleRef[0]  = tail; /* save this word for sync check */
+            }
+
+            /* update zero count and prevent wrap around */
+            zeroCount = min (zeroCount+1,INT_MAX - 1);
+            if (tail != 0x0000) {
+                zeroCount = 0;
+            }
+
+            // don't start counting until we get the first non-zero
+            // sample while UNKNOWN. Note we don't have to worry
+            // about the other scanCount increments since these
+            // only occur after the first non-zero sample.
+            //
+            // so don't count unless one of the following is true:
+            //    . the last sample was non-zero
+            //    . we are already started counting (in this call)
+            //    . we started counting in an earlier scanForSync (timeout has changed)
+            //if (scanCount || (tail != 0x0000) || pDet->timeOutStarted) {
+            //    scanCount += 1;
+            //}
+
+            if (tail != 0x0000) {
+                scanCount += 1;
+                pDet->timeOutStarted = TRUE;
+            }
+            else if (scanCount || pDet->timeOutStarted) {
+                scanCount += 1;
+            }
+            else {
+               // don't increment scanCount
+            }
+
+            continue;
+        }
+
+        // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+
+        switch (scanState) {
+
+            case SCANNED_IEC_PA:
+                if (tail == IEC_PB) {
+                    scanState = SCANNED_IEC_PB;
+                    scanCount += 1;
+                    pDet->preambleRef[1]  = tail; /* save this word for sync check */
+                }
+                else {
+                    scanState = SCANNED_NONE;
+                }
+                break;
+
+            case SCANNED_IEC_PB:
+                // Update scanCount here since, at this point, we are confident that
+                // this is a proper IEC stream. Regardless if we ignore it our not.
+                // Therefore we want to properly signal that this data has been scanned.
+                scanCount += 1;
+
+                // check for IEC pause packets at this time and if required ignore them.
+                // By construction we are guaranteed to have tail=PC at this time.
+                if ((pDet->ibMode == IBMODE_NO_ZERORUNRESTART) ||
+                    (pDet->ibMode == IBMODE_NO_ZERORUN)) {
+                    if ( ((tail&0x1F) == 0) || ((tail&0x1F) == 3)) {
+                        scanState = SCANNED_NONE;
+                        break;
+                    }
+                }
+
+                // fall through to SCANNED_IEC_PC:
+                pDet->preambleRef[2] = tail;  /* save this word for sync check */
+               pDet->bitStreamInfo  = tail;
+                scanState = SCANNED_IEC_PC;
+                break;
+
+            case SCANNED_IEC_PC:
+                //pDevExt->headerSize = IEC_HEADER_SIZE;
+                pDet->preambleRef[3]  = tail; /* save this word for sync check */
+               pDet->headerLength    = IODATA_HEADER_LENGTH_IEC;
+               pDet->headerCheckLen  = IODATA_HEADER_CHECK_LENGTH_IEC;
+                scanState = SCANNED_IEC_PD;
+
+                break;
+
+            case SCANNED_IEC_PD:
+                // wait untill full header is received
+               pDet->syncDetected = TRUE;
+               pDet->frameDataStartTemp = &pbuf[i];
+
+                break;
+
+        } /* switch */
+
+        if(pDet->syncDetected) {
+               break; // break from for loop
+        }
+    } /* for */
+
+    pDet->zeroCount = zeroCount;
+    pDet->scanState = scanState;
+    if (pDet->timeOutCntr > scanCount) {
+       pDet->timeOutCntr -= scanCount;
+    }
+    else {
+       pDet->timeOutCntr = 0;
+    }
+
+} /* syncScan */
+
+
+/*=============================================================================
+ * This function checks for sync word (preamble) at the expected location in the
+ * input buffer. Similar to ioDataAutoDetSyncScan, it looks into two sub-buffers
+ * when the input buffer wraps around.
+ *
+ =============================================================================*/
+void autoDetSyncCheck(ioDataInst_t * pIoDataInst)
+{
+       // look into first sub-buffer for preamble
+       if((pIoDataInst->buff1 != NULL) && (pIoDataInst->size1 != 0)) {
+               syncCheck(pIoDataInst->buff1, pIoDataInst->size1, pIoDataInst->elementSize,
+                                 &pIoDataInst->autoDet);
+       }
+
+       // check if first sub-buffer contains the expected preamble
+       if(pIoDataInst->autoDet.syncDetected) {
+               // skip second sub-buffer if first sub-buffer contains the expected preamble */
+               if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
+                       // update the number of received elements in current frame
+                   pIoDataInst->autoDet.numElementsRcvd += pIoDataInst->size2;
+               }
+       }
+       else if((pIoDataInst->buff2 != NULL) && (pIoDataInst->size2 != 0)) {
+               // look into second sub-buffer if there are two sub-buffers
+               syncCheck(pIoDataInst->buff2, pIoDataInst->size2, pIoDataInst->elementSize,
+                                 &pIoDataInst->autoDet);
+       }
+} /* autoDetSyncCheck */
+
+
+/*=============================================================================
+ * This function scans checks for sync word (preamble) in the provided sub-buffer.
+ =============================================================================*/
+void syncCheck(void *buff, size_t size, int8_t elementSize, autoDet_t *pDet)
+{
+       uint_least16_t  *pbuf;
+    int i, diff, restOfPreamble;
+       uint_least32_t  numElements;
+
+       pbuf = (uint_least16_t  *)buff;
+       numElements = size / elementSize; // number of elements in provided sub-buffer
+
+       // Check if the preamble already starts from the sub-buffer in previous call
+       if(pDet->preambleStartsPrevBuf) {
+               // Calculate number of preamble words in this sub-buffer
+               restOfPreamble = pDet->headerLength - pDet->preambleInd;
+
+               // Save the preamble words for sync check
+               for(i=0; i<restOfPreamble; i++)
+               {
+                       pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
+               }
+
+               // Starts counting elements for next sync check
+       pDet->frameDataStartTemp  = &pbuf[i]; // starting address of data in next frame
+               pDet->numElementsRcvd += numElements; // number of received elements
+               pDet->preambleStartsPrevBuf = FALSE;  // reset flag
+       }
+       else {
+               // Preamble hasn't started from the sub-buffer in previous call.
+               // Check if this frame ends in this sub-buffer:
+               //   distToFrameEnd: distance from beginning of this sub-buffer to frame end
+               //   numElements:    number of elements in this sub-buffer
+               if(pDet->distToFrameEnd < numElements) {
+                       // Preamble of next frame is in this sub-buffer, either full or partial.
+                       // First distToFrameEnd elements in the sub-buffer are the end of current
+                       // frame. Preamble of next frame starts from pbuf[pDet->distToFrameEnd].
+                       if(pDet->distToFrameEnd <= (numElements-pDet->headerLength)) {
+                               // All the preamble words are in this sub-buffer
+                               for(i=pDet->distToFrameEnd; i<pDet->distToFrameEnd+pDet->headerLength; i++)
+                               {
+                                       // Save preamble words for sync check
+                                       pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
+                               }
+
+                               // Store the starting address of data in next frame.
+                               // Note: &pbuf[i] could be 1 word pass the input buffer end if
+                               //       the last word of preamble happens to be at the end of
+                               //       the input buffer. In this case, this address needs to
+                               //       be wrapped around to the beginning of input buffer.
+                       pDet->frameDataStartTemp  = &pbuf[i];
+                       }
+                       else {
+                               // Only partial preamble is in this sub-buffer.
+                               // The preamble spans across this sub-buffer and next.
+                               for(i=pDet->distToFrameEnd; i<numElements; i++)
+                               {
+                                       pDet->preambleBuf[pDet->preambleInd++] = pbuf[i];
+                               }
+                               pDet->preambleStartsPrevBuf = TRUE;
+                       }
+
+                       // Starts counting elements for next sync check
+                       pDet->numElementsRcvd = numElements - pDet->distToFrameEnd;
+               }
+               else {
+                       // Current frame doesn't end here.
+                       // Preamble of next frame is not in this sub-buffer
+                       pDet->distToFrameEnd -= numElements;
+               }
+       }
+
+       // Check if full preamble of next frame has been received
+       if(pDet->preambleInd == pDet->headerLength) {
+               pDet->completeFrameRcvd = TRUE;
+
+               // Check if the preamble matches the reference.
+               diff = 0;
+               for(i=0; i<pDet->headerCheckLen; i++)
+               {
+                       diff += pDet->preambleBuf[i] - pDet->preambleRef[i];
+               }
+
+               // SYNC is maintained if preamble matches reference
+               if(diff == 0) {
+                       pDet->syncDetected = TRUE;
+               }
+               else {
+                       pDet->syncDetected = FALSE;
+               }
+
+               // Reset index for next preamble check
+               //pDet->preambleInd = 0;
+       }
+} /* syncCheck */
+
+
+/* nothing past this point */
diff --git a/pasdk/test_dsp/io/ioData.h b/pasdk/test_dsp/io/ioData.h
new file mode 100644 (file)
index 0000000..388a164
--- /dev/null
@@ -0,0 +1,136 @@
+
+#ifndef IODATA_H
+#define IODATA_H
+
+#include <stdint.h>
+#include "ioBuff.h"
+
+// I/O DATA error code
+enum {
+    IODATA_NO_ERR,
+    IODATA_ERR_MEMORY,
+    IODATA_ERR_BAD_PARAMS,
+       IODATA_ERR_IOBUF_UNDERFLOW,
+       IODATA_ERR_IOBUF_OVERFLOW
+};
+
+// define a type for I/O DATA handle
+typedef void * ioDataHandle_t;
+
+// I/O DATA configuration parameters
+typedef struct ioDataParam_s{
+  ioBuffHandle_t    ioBuffHandle;           // handle to the associated I/O BUFF
+  uint_least16_t   *frameLengthsIEC;        // pointer to array of supported IEC frame lengths
+  uint_least16_t    frameLengthPCM;         // frame length for PCM input
+  uint_least16_t    frameLengthDef;         // default frame length for SYNC search
+  int_least32_t     unknownSourceTimeOut;   // time out value to declare unknown source
+  uint_least32_t    zeroRunTrigger;         // threshold to declare zero run
+  uint_least32_t    zeroRunRestart;         // threshold to restart auto-detection under zero run
+  int8_t            ibMode;                 // IB Mode
+} ioDataParam_t;
+
+// Information needed for decoders to read a bitstream frame
+typedef struct ioDataReadInfo_s {
+  void *buffBase;            // base address of the buffer holding the bitstream data
+  uint_least32_t buffSize;   // size of the buffer holding the bitstream data
+  void *startAddress;        // start address of next complete frame to read
+  uint_least32_t frameSize;  // size of the frame in bytes
+} ioDataReadInfo_t;
+
+// Control commands for ioDataControl
+enum {
+       IODATA_CTL_SET_ELEMENT_SIZE,
+       IODATA_CTL_SET_FRAME_LENGTH,
+       IODATA_CTL_GET_INPBUFFINFO,
+    IODATA_CTL_GET_AUTODET_STATUS,
+};
+
+// SYNC search/detection status
+enum
+{
+    IODATA_SYNC_NONE,
+    IODATA_SYNC_ONE,
+//     IODATA_SYNC_CHECK,
+    IODATA_SYNC_BITSTREAM,
+    IODATA_SYNC_PCM,
+    IODATA_SYNC_PCM_FORCED,
+    IODATA_SYNC_PCM_ZERORUN,
+    IODATA_SYNC_AUTO
+};
+
+// Frame information
+typedef struct ioDataFrameInfo_s {
+  uint_fast32_t frameLength;       // length in units of elements
+  int8_t        elementSize;       // size of elements in bytes
+} ioDataFrameInfo_t;
+
+// Auto-detection status
+typedef struct ioDataAutoDetStat_s {
+  uint_least16_t   syncState;      // SYNC state
+  uint_least16_t   bitStreamInfo;  // bit stream information - value of IEC_PC
+  uint8_t          deliverZeros;   // flag to indicate whether zeros should be sent to output
+} ioDataAutoDetStat_t;
+
+// I/O DATA control structure
+typedef struct ioDataCtl_s {
+  uint_fast16_t code;
+  union {
+       ioDataReadInfo_t    dataReadInfo;  // IODATA_CTL_GET_INPBUFFINFO
+       ioDataFrameInfo_t   frameInfo;     // IODATA_CTL_SET_ELEMENT_SIZE or IODATA_CTL_SET_FRAME_LENGTH
+       ioDataAutoDetStat_t autoDetStats;  // IODATA_CTL_GET_AUTODET_STATUS
+  } param;      
+} ioDataCtl_t;
+
+/**
+ *  @brief ioDataNumAlloc
+ *    Returns the maximum number of memory allocation requests that ioDataAlloc()
+ *    requires.
+ */
+int ioDataNumAlloc(void);
+
+/**
+ *  @brief ioDataAlloc
+ *    Returns a table of memory records that describe the size, alignment, type
+ *    and memory space of all buffers required by I/O DATA component.
+ */
+int ioDataAlloc(lib_mem_rec_t *mem_tbl);
+
+/**
+ *  @brief ioDataCreate
+ *    Based on the provided memory blocks, this function creates an I/O DATA
+ *    instance and returns a handle. This handle points to the memory block
+ *    that contains the instance.
+ */
+int ioDataCreate(ioDataHandle_t *handle, const lib_mem_rec_t *mem_tbl);
+
+/**
+ *  @brief ioDATAInit
+ *    Initializes the I/O DATA instance.
+ */
+int ioDataInit(ioDataHandle_t handle, ioDataParam_t *cfgParams);
+
+/**
+ *  @brief ioDataProcess
+ *    The main function of I/O DATA processing, i.e. auto-detection.
+ */
+int ioDataProcess(ioDataHandle_t handle);
+
+/**
+ *  @brief ioDataReadComplete
+ *    This function marks as read complete the data in the input buffer that has
+ *    been processed by ioDataProcess and the decoder. It should be called after
+ *    ioDataProcess() is called and after the decoder finishes reading current
+ *    frame in the input buffer.
+ */
+int ioDataReadComplete(ioDataHandle_t handle);
+
+
+/**
+ *  @brief ioDataControl
+ *    This function allows run-time control of I/O DATA components through control
+ *    command IODATA_CTL_XXX and control structure ioDataCtl_t.
+ */
+int ioDataControl(ioDataHandle_t handle, ioDataCtl_t *ctlParams);
+
+
+#endif
diff --git a/pasdk/test_dsp/io/ioPhy.c b/pasdk/test_dsp/io/ioPhy.c
new file mode 100644 (file)
index 0000000..6fd182a
--- /dev/null
@@ -0,0 +1,471 @@
+
+#include "ioPhy.h"
+#include "ioPhy_loc.h"
+#include "libarch.h"
+#include "mcasp_drv.h"
+
+#include <stdint.h>
+#include <xdc/runtime/System.h>    // for System_printf
+#include <ti/sysbios/hal/Cache.h>
+
+#define NUM_MCASP_PRIME_PACKETS 3   // should be provided by McASP driver
+
+/******************************************************************************
+* Implementation of I/O Physical Layer Component
+******************************************************************************/
+
+#define IOPHY_NUM_MEM_ALLOCS 1
+#define IOPHY_INST_ALIGN     3 
+
+//C:\ti\edma3_lld_2_12_01_24\packages\ti\sdo\edma3\drv\sample\src\platforms\sample_tci66ak2g02_cfg.c
+extern signed char*  getGlobalAddr(signed char* addr);  // to be replaced by lib_getGlobalAddr
+
+/*******************************************************************************
+* API function: ioPhyNumAlloc
+*    Returns the maximum number of memory allocation requests that ioPhyAlloc() 
+*    requires.
+*******************************************************************************/
+int ioPhyNumAlloc(void)
+{
+  return (IOPHY_NUM_MEM_ALLOCS);
+}
+
+/*******************************************************************************
+* API function: ioPhyAlloc
+*    Returns a table of memory records that describe the size, alignment, type 
+*    and memory space of all buffers required by I/O PHY component. 
+*******************************************************************************/
+int ioPhyAlloc(lib_mem_rec_t *mem_tbl)
+{
+  mem_tbl[0].size = sizeof(ioPhyInst_t);
+  mem_tbl[0].alignment = IOPHY_INST_ALIGN;
+  mem_tbl[0].type = LIB_PMEM_SLOW;
+  mem_tbl[0].base = NULL;
+
+  return (IOPHY_NOERR);
+}
+
+/******************************************************************************
+* API function: 
+*    I/O physical layer creation.  
+******************************************************************************/
+int ioPhyCreate(ioPhyHandle_t *handle, const lib_mem_rec_t *mem_tbl)
+{
+  ioPhyInst_t *io_phy_inst;
+
+  if(  (mem_tbl[0].size < sizeof(ioPhyInst_t))
+     ||libChkAlign(mem_tbl[0].base, IOPHY_INST_ALIGN) ) {
+    return (IOPHY_ERR_MEMORY);
+  }
+
+  io_phy_inst = (ioPhyInst_t *)mem_tbl[0].base;
+  
+  /* return I/O PHY instance */
+  *handle = (ioPhyHandle_t *)io_phy_inst;
+
+  return (IOPHY_NOERR);
+}
+
+/******************************************************************************
+* API function: 
+*    I/O physical layer initialization.  
+******************************************************************************/
+int ioPhyInit(ioPhyHandle_t handle, const ioPhyParams_t *params)
+{
+  ioPhyInst_t *io_phy_inst;
+  Mcasp_IOcmd_e mcasp_cmd;
+  int i;
+
+  io_phy_inst = (ioPhyInst_t *)handle;
+
+  if(params == NULL) {
+    return (IOPHY_ERR_BAD_PARAMS);
+  }
+  
+  /* attach I/O buffer manangement handle */
+  io_phy_inst->io_buff_handle  = params->ioBuffHandle;  
+  
+  /* set transfer frame size - interrupt generated when the frame is transfered */
+  io_phy_inst->xfer_frame_size = params->xferFrameSize;
+  
+  /* attach McASP driver channel handle  */
+  io_phy_inst->mcasp_chan_handle = params->mcaspChanHandle;
+
+  /* set the operation that I/O PHY will perform to I/O buffer - read or write */
+  io_phy_inst->ioBuffOp = params->ioBuffOp;
+
+  /* attach ioBuff functions based on buffer operation */
+  if(params->ioBuffOp == IOPHY_IOBUFFOP_READ) {
+    io_phy_inst->ioBuffMarkComplete = ioBuffReadComplete;
+    io_phy_inst->ioBuffGetPtrs = ioBuffGetReadPtrs;
+    mcasp_cmd = MCASP_WRITE;
+  } else {
+    io_phy_inst->ioBuffMarkComplete = ioBuffWriteComplete;
+    io_phy_inst->ioBuffGetPtrs = ioBuffGetWritePtrs;
+    mcasp_cmd = MCASP_READ;
+  }
+  for(i=0; i<IOPHY_NUM_XFER_RECORD; i++)
+  {
+       io_phy_inst->xfered_packets[i].cmd = mcasp_cmd;
+  }
+  io_phy_inst->mcasp_cmd = mcasp_cmd;
+
+  /* initialize status variables */
+  io_phy_inst->sync_cntr    = 0;  /* to keep track xfer submit and complete */
+  io_phy_inst->submit_ind   = 0;  /* index to submited  McASP packets       */
+  io_phy_inst->complete_ind = 0;  /* index to completed McASP packets       */
+
+  return (IOPHY_NOERR);
+} /* ioPhyInit */
+
+/******************************************************************************
+* I/O PHY internal function: 
+*    Calculate transfer size in bytes based on encoding frame size passed 
+*    through ioPhyControl.
+******************************************************************************/
+static size_t ioPhy_calc_xfer_size(ioPhyInst_t *io_phy_inst)
+{    
+  /* calc. xfer size based on io_phy_inst->frame_size */
+  
+  return (io_phy_inst->xfer_frame_size);
+}
+
+/******************************************************************************
+* API function: 
+*    Submit transfer to underlining driver.
+*
+*    - Called by audio processing task. 
+******************************************************************************/
+int ioPhyXferSubmit(ioPhyHandle_t handle)
+{ 
+  int submit_ind, err_code, ret_value;
+  void *buff1, *buff2;
+  size_t size1, size2, xfer_size;  
+  ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle;
+
+  /* Figure out the transfer size in bytes */
+  xfer_size = ioPhy_calc_xfer_size(io_phy_inst);  // internal function
+
+  ret_value = IOPHY_NOERR;
+
+  /* Get one or two buffers from I/O buffer management for write */
+  err_code = io_phy_inst->ioBuffGetPtrs(io_phy_inst->io_buff_handle, xfer_size, 
+                                        &buff1, &size1, &buff2, &size2);
+
+  /* Don't return from here even if ioBuff overflows or underflows, since McASP
+     needs to be running and generating interrupts all the time.  */
+  if(err_code == IOBUFF_ERR_UNDERFLOW) {
+    ret_value = IOPHY_ERR_BUFF_UNDERFLOW;
+  }
+  if(err_code == IOBUFF_ERR_OVERFLOW) {
+    ret_value = IOPHY_ERR_BUFF_OVERFLOW;
+  }
+  
+  /* ioBuff needs to provide buffer to read/write even if it underflows/overflows */
+  if(buff1 == NULL) {
+    return (IOPHY_ERR_BUFF_BADPTRS);
+  }
+
+  /* Submit 1 or 2 transfers depending on whether I/O buffer wraps around */
+  submit_ind = io_phy_inst->submit_ind; 
+
+  /* Compose McASP packet and save in the instance - McASP driver requires 
+     the packet to be in permanent memory so that it can provide the packet
+     to the callback function. */
+//  io_phy_inst->xfered_packets[submit_ind].cmd  = 0;
+  io_phy_inst->xfered_packets[submit_ind].addr = (void*)(getGlobalAddr(buff1));
+  io_phy_inst->xfered_packets[submit_ind].size = size1;
+  io_phy_inst->xfered_packets[submit_ind].status = 0;
+  io_phy_inst->xfer_rec[submit_ind].base = buff1;
+  io_phy_inst->xfer_rec[submit_ind].size = size1;
+
+  if(buff2 == NULL) {
+    /* There is no wrap around in I/O buffer - submit one transfer */
+    /* indicate that this is the final transfer of a frame */
+    io_phy_inst->xfered_packets[submit_ind].arg     = IOPHY_XFER_FINAL;
+    io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_FINAL;
+  } else {
+    /* There is wrap around in I/O buffer - submit two tranfers    */
+    /* indicate that this is the intermediate transfer of a frame */
+    io_phy_inst->xfered_packets[submit_ind].arg    = IOPHY_XFER_INTER;
+    io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_INTER;
+  }
+
+  /* make a transfer request */
+  if((err_code = mcaspSubmitChan(io_phy_inst->mcasp_chan_handle, 
+                                &io_phy_inst->xfered_packets[submit_ind])) != 1) {
+    //System_printf("mcaspSubmitChan failed with handle 0x%x and error code %d!\n", 
+    //              (unsigned int)io_phy_inst->mcasp_chan_handle, err_code);
+    return(IOPHY_ERR_MCASP_FAIL);  
+  }
+
+  /* update submit index */
+  submit_ind++;
+  if(submit_ind == IOPHY_NUM_XFER_RECORD) {
+    submit_ind = 0;
+  }
+  io_phy_inst->submit_ind = submit_ind;
+
+  /* make another transfer request if ioBuff wraps around */
+  if(buff2 != NULL) {
+    /* Compose McASP packets and save in the instance */
+    //io_phy_inst->xfered_packets[submit_ind].cmd  = 0;
+    io_phy_inst->xfered_packets[submit_ind].addr = (void*)(getGlobalAddr(buff2));
+    io_phy_inst->xfered_packets[submit_ind].size = size2;
+    io_phy_inst->xfered_packets[submit_ind].status = 0;
+    /* indicate that this is the final transfer of a frame */
+    io_phy_inst->xfered_packets[submit_ind].arg   = IOPHY_XFER_FINAL;
+
+    io_phy_inst->xfer_rec[submit_ind].base = buff2;
+    io_phy_inst->xfer_rec[submit_ind].size = size2;
+    io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_FINAL;
+
+    if((err_code = mcaspSubmitChan(io_phy_inst->mcasp_chan_handle, 
+                                  &io_phy_inst->xfered_packets[submit_ind])) != 1) {
+      //System_printf("mcaspSubmitChan failed with handle 0x%x and error code %d!\n", 
+      //              (unsigned int)io_phy_inst->mcasp_chan_handle, err_code);
+      return(IOPHY_ERR_MCASP_FAIL);  
+    }
+
+    submit_ind++;
+    if(submit_ind == IOPHY_NUM_XFER_RECORD) {
+      submit_ind = 0;
+    }
+    io_phy_inst->submit_ind = submit_ind;
+  }
+
+  return (ret_value);
+} /* ioPhyXferSubmit() */
+
+
+void swapData(void *buff, uint_least32_t size)
+{
+    int i;
+       int_least16_t L0, L1, L2, L3, R0, R1, R2, R3 = 0;
+       int_least16_t *p1, *p2;
+
+       int_least16_t *dataPtr = (int_least16_t *)buff;
+/*
+       for (i=0; i<size/2; i++)
+       {
+               if(dataPtr[i] == (int_least16_t)0xF872) {
+                       dataPtr[i] = 0x278F;
+               }
+       }
+*/
+       for (i=0; i<size/2; i+=8)
+       {
+                       p1 = &dataPtr[i];
+                       p2 = p1;
+
+                       L0 = *p1++;
+                       L1 = *p1++;
+                       L2 = *p1++;
+                       L3 = *p1++;
+                       R0 = *p1++;
+                       R1 = *p1++;
+                       R2 = *p1++;
+                       R3 = *p1++;
+
+                       *p2++ = L0;
+                       *p2++ = R0;
+                       *p2++ = L1;
+                       *p2++ = R1;
+                       *p2++ = L2;
+                       *p2++ = R2;
+                       *p2++ = L3;
+                       *p2++ = R3;
+       }
+
+       return;
+}
+
+/*======================================================================================
+ *  This function swaps HDMI input data in a given buffer
+ *====================================================================================*/
+void hdmiDataSwap(void * buff, uint_least32_t size)
+{
+    Cache_inv(buff, size, Cache_Type_ALL, 0);
+    Cache_wait();
+
+    swapData(buff, size);
+
+    Cache_wb (buff, size, Cache_Type_ALL, 0);
+    Cache_wait();
+} /* ioDataSwapBuffer */
+
+/******************************************************************************
+* API function:
+*    Marks I/O buffer read/write complete.
+*
+*    - Called by audio processing task.
+******************************************************************************/
+int ioPhyXferComplete(ioPhyHandle_t handle, int dataSwap)
+{
+  int complete_ind;
+  void *buff;
+  size_t size;
+
+  ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle;
+
+  /* Based on index to completed packets, find the base address and size of the 
+     just completed McASP packet and pass to ioBuff to mark read/write complete. */
+  complete_ind = io_phy_inst->complete_ind;
+  buff = io_phy_inst->xfer_rec[complete_ind].base;
+  size = io_phy_inst->xfer_rec[complete_ind].size;
+
+  if(dataSwap) {
+    hdmiDataSwap(buff, size);
+  }
+
+  io_phy_inst->ioBuffMarkComplete(io_phy_inst->io_buff_handle, buff, size);
+
+  /* Check if this is a single McASP transfer or batch transfer */
+  if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_INTER) {
+    /* This is a batch transfer, so also mark next packet as complete. */
+    complete_ind++;
+    if(complete_ind == IOPHY_NUM_XFER_RECORD) {
+      complete_ind = 0;
+    }
+
+    if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_FINAL) {
+         buff = io_phy_inst->xfer_rec[complete_ind].base;
+         size = io_phy_inst->xfer_rec[complete_ind].size;
+
+         if(dataSwap) {
+        hdmiDataSwap(buff, size);
+         }
+
+      io_phy_inst->ioBuffMarkComplete(io_phy_inst->io_buff_handle, buff, size);
+    } else {
+      // error!
+    }
+  } 
+
+  /* increment index to point to next completed packet */ 
+  io_phy_inst->complete_ind = complete_ind+1; 
+  if(io_phy_inst->complete_ind == IOPHY_NUM_XFER_RECORD) {
+    io_phy_inst->complete_ind = 0;
+  }
+
+  return (IOPHY_NOERR);
+} /* ioPhyXferComplete() */
+
+
+// TODO: add error check and recovery mechanism
+int ioPhyCheckXferStatus(ioPhyHandle_t handle, MCASP_Packet *mcasp_packet)
+{
+  int complete_ind, temp_ind;
+  ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle;
+
+  // complete_ind points to the packet to be marked as complete
+  complete_ind = io_phy_inst->complete_ind;
+  temp_ind = complete_ind + 1;
+  if(temp_ind == IOPHY_NUM_XFER_RECORD) {
+         temp_ind = 0;
+  }
+
+  // check if next completed packet is part of two-packet transfer or not:
+  //    - if two-packet transfer, it points to the first packet
+  //    - if one-packet transfer, it points to the only packet
+  if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_INTER) {
+       // this is a two-packet transfer and this function may be called after either the
+       // first or the second packet has been transfered.
+       if(   (mcasp_packet->arg  == IOPHY_XFER_INTER)  // first packet
+          && (mcasp_packet->addr == io_phy_inst->xfer_rec[complete_ind].base) ) {
+         // this is the first packet
+         return (IOPHY_XFER_INTER);
+       }
+       else if(   (mcasp_packet->arg  == IOPHY_XFER_FINAL)  // second packet
+                   && (mcasp_packet->addr == io_phy_inst->xfer_rec[temp_ind].base) ) {
+         // this is the second packet
+         return (IOPHY_XFER_FINAL);
+       }
+       else {
+               return (IOPHY_XFER_ERROR);
+       }
+  }
+  else {
+       // this is a one-packet transfer
+       if(  (mcasp_packet->arg  == IOPHY_XFER_FINAL)
+          &&(mcasp_packet->addr == io_phy_inst->xfer_rec[complete_ind].base) ) {
+         return (IOPHY_XFER_FINAL);
+       }
+       else {
+         return (IOPHY_XFER_ERROR);
+       }
+  }
+
+#if 0
+  if(mcasp_packet->addr != io_phy_inst->xfer_rec[io_phy_inst->complete_ind].base) {
+       return (IOPHY_XFER_ERROR);
+  }
+
+  if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
+    return (IOPHY_XFER_FINAL);  
+  }
+  else if (mcasp_packet->arg == IOPHY_XFER_INTER) {
+    return (IOPHY_XFER_INTER);  
+  }
+  else {
+       return (IOPHY_XFER_ERROR);
+  }
+#endif
+
+} /* ioPhyCheckXferStatus */
+
+
+/******************************************************************************
+* API function: run-time control of IO Configuration component
+******************************************************************************/
+int ioPhyControl(ioPhyHandle_t handle, ioPhyCtl_t *ctl)
+{
+  ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle;
+
+  switch(ctl->code) {
+    case IOPHY_CTL_FRAME_SIZE:
+    /* pass data frame size */
+    io_phy_inst->xfer_frame_size = ctl->params.xferFrameSize;
+    break;
+
+    case IOPHY_CTL_INPUT_CHANGE:
+      //ioPhyInit(handle, ctl->ioPhyRxParams);
+    break;
+
+    default:
+    break; 
+  }
+
+  return (IOPHY_NOERR);
+} /* ioPhyControl */
+
+// change this API to something like  ioPhyXferReSubmit(ioPhyHandle_t handle, int numXfer)
+int ioPhyXferErrRecover(ioPhyHandle_t handle)
+{
+  int submit_ind, i;
+  ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle;
+
+  /* resend the latest #NUM_MCASP_PRIME_PACKETS packets */
+  submit_ind = io_phy_inst->submit_ind - NUM_MCASP_PRIME_PACKETS;
+  //submit_ind = io_phy_inst->submit_ind - (NUM_MCASP_PRIME_PACKETS-1);
+  if(submit_ind < 0) {
+    submit_ind += IOPHY_NUM_XFER_RECORD;
+  }
+
+  for(i=0; i<NUM_MCASP_PRIME_PACKETS; i++)
+  {
+    if((mcaspSubmitChan(io_phy_inst->mcasp_chan_handle,
+                                    &io_phy_inst->xfered_packets[submit_ind])) != 1) {
+      return(IOPHY_ERR_MCASP_FAIL);
+    }
+
+    submit_ind++;
+    if(submit_ind == IOPHY_NUM_XFER_RECORD) {
+      submit_ind = 0;
+    }
+  }
+
+  io_phy_inst->submit_ind = submit_ind;
+
+  return (IOPHY_NOERR);
+} /* ioPhyXferErrRecover */
diff --git a/pasdk/test_dsp/io/ioPhy.h b/pasdk/test_dsp/io/ioPhy.h
new file mode 100644 (file)
index 0000000..8eee0ad
--- /dev/null
@@ -0,0 +1,107 @@
+
+
+#ifndef _IOPHY_H
+#define _IOPHY_H
+
+#include <stdint.h>
+#include "mcasp_drv.h"
+#include "libarch.h"
+#include "ioBuff.h"
+
+enum {
+  IOPHY_NOERR         = 0,
+  IOPHY_ERR_HANDLE,
+  IOPHY_ERR_MEMORY,
+  IOPHY_ERR_BAD_PARAMS,
+  IOPHY_ERR_MCASP_FAIL,
+  IOPHY_ERR_BUFF_UNDERFLOW,
+  IOPHY_ERR_BUFF_OVERFLOW,
+  IOPHY_ERR_BUFF_BADPTRS,
+  IOPHY_ERR_BATCH_XFER_FAIL
+}; 
+
+enum {
+  IOPHY_IOBUFFOP_READ   = 0,
+  IOPHY_IOBUFFOP_WRITE  = 1
+};
+
+typedef uint_fast16_t ioPhyBuffOp_t;
+
+enum {
+  IOPHY_XFER_INTER  = 0,
+  IOPHY_XFER_FINAL,
+  IOPHY_XFER_ERROR
+};
+
+typedef void * ioPhyHandle_t;
+
+typedef struct ioPhyParams {
+  void *         mcaspChanHandle;
+  uint_least32_t xferFrameSize;  // generate INT when this amount of data has been transfered
+                                 // can be changed at run time through control function
+  ioBuffHandle_t ioBuffHandle;
+  ioPhyBuffOp_t  ioBuffOp;       // READ or WRITE
+} ioPhyParams_t; 
+
+enum {
+  IOPHY_CTL_FRAME_SIZE    = 0,
+  IOPHY_CTL_INPUT_CHANGE,
+  IOPHY_CTL_INIT_DRIVER
+};
+
+typedef struct ioPhyCtl_s {
+  uint_fast16_t code;
+  union {
+    uint_least32_t xferFrameSize;
+    void *         mcaspChanHandle;
+  } params;
+} ioPhyCtl_t;
+
+int ioPhyNumAlloc(void);
+int ioPhyAlloc(lib_mem_rec_t *memTab);
+int ioPhyCreate(ioPhyHandle_t *handle, const lib_mem_rec_t *mem_tbl);
+int ioPhyInit(ioPhyHandle_t handle, const ioPhyParams_t *params);
+
+/**
+ *  @brief ioPhyXferCfg
+ *    Configures next transfer. 
+ *    Reconfigure the EDMA driver link channel (PaRAM set) that has just finished 
+ *    transfer and generated TCINT.
+ *
+ *    This function will call I/O buff API to get the write pointers.
+ *
+ *  @param[in]   handle
+ *
+ */
+int ioPhyXferSubmit(ioPhyHandle_t handle);
+
+/**
+ *  @brief ioPhyXferComplete
+ *    Marks complete the transfer which has just finished. This function will
+ *    call I/O buff API to mark certain portion of the I/O buffer as
+ *    write-completed. 
+ *
+ *  @param[in]   handle
+ *
+ */
+int ioPhyXferComplete(ioPhyHandle_t handle, int dataSwap);
+
+/**
+ *  @brief ioPhyControl
+ *    Changes I/O PHY parameters at run time.
+ *
+ *  @param[in]   handle
+ *  @param[in]   ctl
+ *
+ *  Configurable parameters:
+ *  - ctl->xfer_frame_size: transfer frame size in bytes. Transfer completion 
+ *                          INT is generated after this amount of data is 
+ *                          transfered.  
+ */
+int ioPhyControl(ioPhyHandle_t handle, ioPhyCtl_t *ctl);
+
+int ioPhyXferErrRecover(ioPhyHandle_t handle);
+
+int ioPhyCheckXferStatus(ioPhyHandle_t handle, MCASP_Packet *mcasp_packet);
+
+#endif
diff --git a/pasdk/test_dsp/io/ioPhy_loc.h b/pasdk/test_dsp/io/ioPhy_loc.h
new file mode 100644 (file)
index 0000000..469d8dd
--- /dev/null
@@ -0,0 +1,43 @@
+
+#ifndef IOPHY_LOC_H
+#define IOPHY_LOC_H
+
+#include <stdint.h>
+#include "ioBuff.h"
+#include "mcasp_drv.h"
+
+#define IOPHY_NUM_XFER_RECORD 8
+
+#define IOPHY_XFER_PACKET_INTER 0
+#define IOPHY_XFER_PACKET_FINAL 1
+
+
+typedef struct ioPhyXferRec_s {
+  void *base;
+  uint_least32_t size;
+  uint_fast16_t  packet_status;
+} ioPhyXferRec_t;
+
+typedef struct ioPhyInst_s {
+  ioPhyXferRec_t xfer_rec[IOPHY_NUM_XFER_RECORD];
+  MCASP_Packet   xfered_packets[IOPHY_NUM_XFER_RECORD];
+  ioBuffHandle_t io_buff_handle;
+  uint_least32_t xfer_frame_size;
+  Mcasp_IOcmd_e mcasp_cmd;
+
+  int_fast16_t  sync_cntr;
+  uint_fast16_t submit_ind;
+  uint_fast16_t complete_ind;
+
+  void *mcasp_chan_handle; 
+
+  ioPhyBuffOp_t  ioBuffOp;       // READ or WRITE
+  int (*ioBuffMarkComplete)(ioBuffHandle_t handle, void *start, size_t size);
+  int (*ioBuffGetPtrs)(ioBuffHandle_t handle, size_t mem_size, 
+                                void **rdptr1, size_t *size1, 
+                                void **rdptr2, size_t *size2);
+
+} ioPhyInst_t;
+
+
+#endif
diff --git a/pasdk/test_dsp/io/libarch.h b/pasdk/test_dsp/io/libarch.h
new file mode 100644 (file)
index 0000000..94a4242
--- /dev/null
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * Redistributions in binary form must reproduce the above copyright
+ *         notice, this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *   THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#ifndef _LIBARCH_MEMMGT_H
+#define _LIBARCH_MEMMGT_H
+
+#include <stdlib.h>
+
+/** @defgroup libarch_memmgt Memory Management API
+ *  @{
+ */
+/** @} */
+
+/** @addtogroup libarch_memmgt
+ *  @brief Error return codes of memory management functions.
+ *  @{
+ */
+/*@{*/
+#define LIB_MEMMGT_SUCCESS          (0)   /**< Success. No error.            */
+#define LIB_MEMMGT_ERROR            (-1)  /**< Failure.                      */ 
+/*@}*/
+/** @} */
+
+/** 
+  * @ingroup libarch_memmgt
+  * @brief Memory types in terms of speed and volatility
+  */
+enum {
+    LIB_SMEM_VFAST = 0, /**< Scratch memory, very fast       */
+    LIB_SMEM_FAST,      /**< Scratch memory, fast            */
+    LIB_SMEM_MED,       /**< Scratch memory, medium speed    */
+    LIB_SMEM_SLOW,      /**< Scratch memory, slow            */
+    LIB_PMEM_MED,       /**< Permanent memory, medium speed  */
+    LIB_PMEM_SLOW,      /**< Permanent memory, slow          */
+    LIB_MEMTYPE_N       /**< Total number of types           */
+};
+
+typedef unsigned int lib_mem_type_t;
+
+typedef struct {
+  size_t         size;      /**< heap size in number of bytes */
+  lib_mem_type_t type;
+  unsigned int   alignment;
+  void           *base;     /**< base address of the heap     */   
+} lib_mem_rec_t;
+
+#define libChkAlign(base, l2a)    \
+       (((uint_least32_t)(base)&((~0UL<<(l2a))))==0UL)
+
+
+#endif  /* _LIBARCH_MEMMGT_H */
+
+/* nothing past this point */
diff --git a/pasdk/test_dsp/io/test/audio_tsk.c b/pasdk/test_dsp/io/test/audio_tsk.c
new file mode 100644 (file)
index 0000000..01805dc
--- /dev/null
@@ -0,0 +1,990 @@
+
+//#include "analog_test.h"
+#include "frame_work.h"
+#include "ioBuff.h"
+#include "ioData.h"
+#include "ioPhy.h"
+#include <mcasp_drv.h>
+#include "mcasp_cfg.h"
+#include "ioConfig.h"
+
+//#define TEST_OVERFLOW_UNDERFLOW
+//#define TEST_OVERFLOW_OVERFLOW
+#define NUM_BUFS_USED  8
+
+#define INPUT_SWITCH_HANGOVER 8
+
+/* Frame index for Rx and Tx buffers */
+uint8_t rxFrameIndex = 0;
+uint8_t txFrameIndex = 0;
+uint32_t rxBufIndex = 0;
+uint32_t txBufIndex = 0;
+
+/* McASP Tx and Rx frame buffers */
+MCASP_Packet rxFrame[NUM_BUFS];
+MCASP_Packet txFrame[NUM_BUFS];
+
+/* McASP Tx and Rx frame buffer pointers */
+Ptr txBuf[NUM_BUFS];
+Ptr rxBuf[NUM_BUFS];
+Ptr procBuf;
+
+/* Flags for counting Rx and Tx interrupts */
+volatile uint32_t rxFlag = 0;
+volatile uint32_t txFlag = 0;
+
+int dataFrameIndex=0;
+int RxTSKcnt = 0, TxTSKcnt = 0;
+volatile int RxFlag=0, RxFlag1=0, RxFlag2=0, TxFlag=0, TxFlag1=0, TxFlag2=0;
+
+/* Semaphore handle for Tx and Rx */
+Semaphore_Handle semR;
+Semaphore_Handle semT;
+Semaphore_Params SemParams;
+
+uint32_t mcaspRxChanArg = 1;
+uint32_t mcaspTxChanArg = 2;
+int num_gbl_err = 0;
+int txCount = 0;
+int rxCount = 0;
+int resetCount = 0;
+
+extern Mcasp_ChanParams  mcaspRxChanParam;
+
+/* McASP channel handles */
+extern Ptr hMcaspTxChan;
+extern Ptr hMcaspRxChan;
+
+/* McASP device handles */
+extern Ptr hMcaspDevTx;
+extern Ptr hMcaspDevRx;
+
+extern uint32_t gblErrFlag;
+
+
+fwInst_t fwInst;
+extern Ptr databuf[NUM_BUFS];
+
+extern signed char*  getGlobalAddr(signed char* addr);
+
+void inputXferStart();
+void outputXferStart();
+
+int check_mcasp_rx_overrun(void);
+void mcasp_rx_restart(void);
+int check_mcasp_tx_underrun(void);
+void mcasp_tx_restart(void);
+void ioRecfgRxPhyForPcm(void);
+void ioRecfgRxPhyForBitStream();
+
+extern void ioCompsInitInput();
+extern void ioCompsInitOutput();
+
+
+#ifndef USE_IO_COMPONENTS
+/**
+ *  \brief   McASP callback function called up on the data transfer completion
+ *
+ *  \param  arg   [IN]  - Application specific callback argument
+ *  \param  ioBuf [IN]  - McASP IO buffer
+ *
+ *  \return    None
+ */
+void mcaspAppCallbackRx(void *arg, MCASP_Packet *ioBuf)
+{
+       /* Callback is triggered by Rx completion */
+
+               rxFlag++;
+
+               /* Post semaphore */
+               Semaphore_post(semR);
+}
+
+void mcaspAppCallbackTx(void *arg, MCASP_Packet *ioBuf)
+{
+       /* Callback is triggered by Tx completion */
+
+           txFlag++;
+
+               /* Post semaphore */
+               Semaphore_post(semT);
+}
+
+#else
+
+void *mcaspRxBuf1;
+void *mcaspRxBuf2;
+uint32_t mcaspRxSize1;
+uint32_t mcaspRxSize2;
+int mcaspRxtwoXfers = 0;
+
+void mcaspAppCallbackRx(void* arg, MCASP_Packet *mcasp_packet)
+{
+    RxFlag++;
+
+    /* post semaphore */
+       if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
+        RxFlag1++;
+
+        Semaphore_post(semR);
+    } else {
+        RxFlag2++;
+    }
+}
+
+void mcaspAppCallbackTx(void* arg, MCASP_Packet *mcasp_packet)
+{
+       TxFlag++;
+
+    /* post semaphore */
+       if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
+        TxFlag1++;
+
+        Semaphore_post(semT);
+    } else {
+        TxFlag2++;
+    }
+}
+#endif
+
+
+#ifdef IO_LOOPBACK_TEST
+
+#ifndef USE_IO_COMPONENTS
+
+/**
+ *  \brief   Task to echo the input data to output
+ *
+ *  Waits for the McASP data transfer completion and copies the
+ *  Rx data to Tx buffers
+ *
+ *  \return    Audk2g_EOK on Success or error code
+ */
+Void taskAsipFxn(
+    const PAF_ASIT_Params *pP,  //JX: asip_params_PAi defined in itopo/params.c
+    const PAF_ASIT_Patchs *pQ   //JX: asop_patchs_PAi defined in itopo/patchs.c
+)
+{
+    int32_t count;
+    Int     status;
+
+       inputXferStart();
+
+    /* Forever loop to continuously receive and transmit audio data */
+       count = 0;
+    while (1)
+    {
+       if(gblErrFlag)
+       {
+               break;
+               }
+
+        //Log_info0("Pending Rx semaphore");
+
+       /* Reclaim full buffer from the input stream */
+       Semaphore_pend(semR, BIOS_WAIT_FOREVER);
+
+        /* Copy the receive information to the transmit buffer */
+        Cache_inv(rxBuf[rxFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL, TRUE);
+        memcpy(procBuf, rxBuf[rxFrameIndex], INPUT_FRAME_SIZE);
+
+        /* Issue an empty buffer to the input stream                          */
+               rxFrame[rxFrameIndex].cmd    = MCASP_READ;
+               rxFrame[rxFrameIndex].addr   = (void*)(getGlobalAddr(rxBuf[rxFrameIndex]));
+               rxFrame[rxFrameIndex].size   = INPUT_FRAME_SIZE;
+               rxFrame[rxFrameIndex].arg    = (uint32_t) mcaspRxChanArg;
+               rxFrame[rxFrameIndex].status = 0;
+               rxFrame[rxFrameIndex].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+        status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[rxFrameIndex]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       Log_info0("mcaspSubmitChan for Rx Failed\n");
+               }
+
+        rxFrameIndex++;
+        if(rxFrameIndex==NUM_BUFS_USED) {
+               rxFrameIndex = 0;
+        }
+
+        // test McASP LLD reset
+        count += 1;
+        if(count == 1000) {
+            mcaspRxReset();
+            mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
+            mcaspRxCreate();
+            inputXferStart();
+
+            count = 0;
+            resetCount += 1;
+        }
+       }
+} /* taskAsipFxn */
+
+Void taskAsopFxn(
+    const PAF_ASOT_Params *pP,
+    const PAF_ASOT_Patchs *pQ
+)
+{
+    Int     status;
+
+       outputXferStart();
+    //Semaphore_Params_init(&params);
+
+    /* Forever loop to continuously receive and transmit audio data */
+    while (1)
+    {
+       if(gblErrFlag)
+       {
+               break;
+               }
+
+        //Log_info0("Pending Tx semaphore");
+
+        /* Reclaim full buffer from the input stream */
+       Semaphore_pend(semT, BIOS_WAIT_FOREVER);
+
+        memcpy(txBuf[txFrameIndex], procBuf, OUTPUT_FRAME_SIZE);
+           Cache_wbInv(txBuf[txFrameIndex], OUTPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
+
+        /* Issue full buffer to the output stream                             */
+        /* TX frame processing */
+               txFrame[txFrameIndex].cmd    = MCASP_WRITE;
+               txFrame[txFrameIndex].addr   = (void*)(getGlobalAddr(txBuf[txFrameIndex]));
+               txFrame[txFrameIndex].size   = OUTPUT_FRAME_SIZE;
+               txFrame[txFrameIndex].arg    = (uint32_t) mcaspTxChanArg;
+               txFrame[txFrameIndex].status = 0;
+               txFrame[txFrameIndex].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+               status = mcaspSubmitChan(hMcaspTxChan, &txFrame[txFrameIndex]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       Log_info0("mcaspSubmitChan for Tx Failed\n");
+               }
+               else {
+                       txCount++;
+               }
+
+        txFrameIndex++;
+        if(txFrameIndex==NUM_BUFS_USED) {
+               txFrameIndex = 0;
+        }
+
+       }
+
+    //testRet(0);
+}
+
+
+/* put input and output in the same task */
+Void taskAsipFxn_1tsk(
+    const PAF_ASIT_Params *pP,  //JX: asip_params_PAi defined in itopo/params.c
+    const PAF_ASIT_Patchs *pQ   //JX: asop_patchs_PAi defined in itopo/patchs.c
+)
+{
+    Int     status;
+
+//    mcaspRxCfgPCM();
+
+       inputXferStart();
+       outputXferStart();
+
+    /* Forever loop to continuously receive and transmit audio data */
+    while (1)
+    {
+       if(gblErrFlag)
+       {
+               break;
+               }
+
+       /* pending on both Rx and Tx semaphore */
+       Semaphore_pend(semR, BIOS_WAIT_FOREVER);
+       Semaphore_pend(semT, BIOS_WAIT_FOREVER);
+
+        /* Copy the receive information to the transmit buffer */
+        Cache_inv(rxBuf[rxFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL, TRUE);
+        memcpy(procBuf, rxBuf[rxFrameIndex], INPUT_FRAME_SIZE);
+
+        memcpy(txBuf[txFrameIndex], procBuf, INPUT_FRAME_SIZE);
+           Cache_wbInv(txBuf[txFrameIndex], OUTPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
+
+        /* Issue an empty buffer to the input stream                          */
+               rxFrame[rxFrameIndex].cmd    = MCASP_READ;
+               rxFrame[rxFrameIndex].addr   = (void*)(getGlobalAddr(rxBuf[rxFrameIndex]));
+               rxFrame[rxFrameIndex].size   = INPUT_FRAME_SIZE;
+               rxFrame[rxFrameIndex].arg    = (uint32_t) mcaspRxChanArg;
+               rxFrame[rxFrameIndex].status = 0;
+               rxFrame[rxFrameIndex].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+        status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[rxFrameIndex]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       Log_info0("mcaspSubmitChan for Rx Failed\n");
+               }
+
+        rxFrameIndex++;
+        if(rxFrameIndex==NUM_BUFS_USED) {
+               rxFrameIndex = 0;
+        }
+
+        /* Issue full buffer to the output stream                             */
+        /* TX frame processing */
+               txFrame[txFrameIndex].cmd    = MCASP_WRITE;
+               txFrame[txFrameIndex].addr   = (void*)(getGlobalAddr(txBuf[txFrameIndex]));
+               txFrame[txFrameIndex].size   = OUTPUT_FRAME_SIZE;
+               txFrame[txFrameIndex].arg    = (uint32_t) mcaspTxChanArg;
+               txFrame[txFrameIndex].status = 0;
+               txFrame[txFrameIndex].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+               status = mcaspSubmitChan(hMcaspTxChan, &txFrame[txFrameIndex]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       Log_info0("mcaspSubmitChan for Tx Failed\n");
+               }
+               else {
+                       txCount++;
+               }
+
+        txFrameIndex++;
+        if(txFrameIndex==NUM_BUFS_USED) {
+               txFrameIndex = 0;
+        }
+/*
+        if(txCount == 3000) {
+               mcaspRxReset();
+               mcaspRxCreate();
+               inputXferStart();
+
+               txCount = 0;
+               resetCount += 1;
+        }
+*/
+       }
+
+    //testRet(0);
+}
+
+Void taskAsopFxn_1tsk(
+    const PAF_ASOT_Params *pP,
+    const PAF_ASOT_Patchs *pQ
+)
+{
+
+}
+
+#else    // else of #ifndef USE_IO_COMPONENTS
+
+void audio_rx_proc()
+{
+    void *buff1, *buff2;
+    size_t size1, size2;
+
+    /* Get read pointers of input memory pool */
+    if (ioBuffGetReadPtrs(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE_PCM,
+                          &buff1, &size1, &buff2, &size2)
+        == IOBUFF_ERR_UNDERFLOW) {
+        fwInst.buf_status_in = FW_IOBUF_UNDERFLOW;
+        //System_printf ("Debug: input buff underflows!\n");
+
+        /* skip processing since there is no enough data to process */
+        return;
+    } else {
+        fwInst.buf_status_in = FW_IOBUF_NORMAL;
+    }
+
+    /* copy the input data to data buffer                */
+    Cache_inv(buff1, size1, Cache_Type_ALL, TRUE);
+    memcpy(databuf[0],buff1,size1);
+    ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff1, size1);
+
+    if(buff2 != NULL) {
+      Cache_inv(buff2, size2, Cache_Type_ALL, TRUE);
+      memcpy((void *)((size_t)databuf[0]+size1),buff2,size2);
+      ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff2, size2);
+    }
+
+    //Cache_wbInv(databuf[dataFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
+} /* audio_rx_proc */
+
+void audio_tx_proc()
+{
+    void *buff1, *buff2;
+    size_t size1, size2;
+    int status;
+/*
+    dataFrameIndex++;
+    if(dataFrameIndex==NUM_BUFS) {
+        dataFrameIndex = 0;
+    }
+*/
+    // Get write pointers of output memory pool
+    status = ioBuffGetWritePtrs(fwInst.ioOut.hIoBuff, OUTPUT_FRAME_SIZE,
+                                &buff1, &size1, &buff2, &size2);
+    if (status == IOBUFF_ERR_OVERFLOW) {
+        fwInst.buf_status_out = FW_IOBUF_OVERFLOW;
+        //System_printf ("Debug: output buff overflows in Tx proc!\n");
+
+        /* skip processing since output buffer overflows */
+        return;
+    } 
+    else if (status == IOBUFF_ERR_UNDERFLOW) {
+        /* already underflows and remain in underflow */
+        fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
+    } 
+    else {
+        fwInst.buf_status_out = FW_IOBUF_NORMAL;
+    }
+
+    /* copy the output data from data buffer to output memory pool            */
+    memcpy(buff1, databuf[0], size1);
+    Cache_wbInv(buff1, size1, Cache_Type_ALL,TRUE);
+
+    ioBuffWriteComplete(fwInst.ioOut.hIoBuff, buff1, size1);
+
+    if(buff2 != NULL) {
+      memcpy(buff2,(void *)((size_t)databuf[0]+size1),size2);
+      Cache_wbInv(buff2, size2, Cache_Type_ALL,TRUE);
+
+      ioBuffWriteComplete(fwInst.ioOut.hIoBuff, buff2, size2);
+    }
+}  /* audio_tx_proc */
+
+void rxDecodeProcess()
+{
+    ioDataCtl_t ioDataCtl;
+    void *buffBase;
+    void *dataStartAddress;
+    size_t buffSize, frameSize, size1, size2;
+
+    /* Get information for reading input data */
+    ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
+    ioDataControl(fwInst.ioInp.hIoData, &ioDataCtl);
+
+    buffBase = ioDataCtl.param.dataReadInfo.buffBase;
+    buffSize = ioDataCtl.param.dataReadInfo.buffSize;
+    dataStartAddress = ioDataCtl.param.dataReadInfo.startAddress;
+    frameSize        = ioDataCtl.param.dataReadInfo.frameSize;
+
+    /* Depending on source information, either decode bit stream or simply
+     * copy PCM data to output buffer.
+     */
+    if(fwInst.syncState == IODATA_SYNC_PCM) {
+        // Copy PCM data to output buffer
+        if(((size_t)dataStartAddress+frameSize) <= ((size_t)buffBase+buffSize)) {
+            // Input buffer doesn't wrap around
+            Cache_inv(dataStartAddress, frameSize, Cache_Type_ALL, TRUE);
+            memcpy(databuf[0], dataStartAddress, frameSize);
+        }
+        else {
+            // Input buffer wraps around
+            size1 = (size_t)buffBase + buffSize - (size_t)dataStartAddress;
+            size2 = frameSize - size1;
+            Cache_inv(dataStartAddress, size1, Cache_Type_ALL, TRUE);
+            memcpy(databuf[0], dataStartAddress, size1);
+
+            Cache_inv(buffBase, size2, Cache_Type_ALL, TRUE);
+            memcpy((void *)((size_t)databuf[0]+size1), buffBase, size2);
+        }
+    }
+    else if(fwInst.syncState == IODATA_SYNC_BITSTREAM) {
+        // Do nothing - there is no decoder
+    }
+} /* rxDecodeProcess */
+
+int numFrameReceived, numPcmFrameReceived, numSyncLost, numUnderflow;
+extern const MdUns iecFrameLength[23];
+
+#define SYNC_PC_MASK    0x001F
+
+Void taskAsipFxn(
+    const PAF_ASIT_Params *pP,  //JX: asip_params_PAi defined in itopo/params.c
+    const PAF_ASIT_Patchs *pQ   //JX: asop_patchs_PAi defined in itopo/patchs.c
+)
+{
+       int autoDetstatus;
+    ioDataCtl_t ioDataCtl;
+    ioPhyCtl_t  ioPhyCtl;
+
+    /* Initialize I/O components for input */
+    ioCompsInitInput();
+
+#ifdef INPUT_HDMI_4xI2S             // HDMI 4xI2S, bit stream or PCM
+#ifdef INPUT_PCM_ONLY
+    fwInst.ioInp.swapData = FALSE;  // initialized to receive PCM
+#else
+    fwInst.ioInp.swapData = TRUE;   // initialized to receive bit stream
+#endif
+#else
+    fwInst.ioInp.swapData = FALSE;  // initialized to receive PCM
+#endif
+
+    fwInst.syncState     = IODATA_SYNC_NONE;
+    fwInst.syncStatePrev = IODATA_SYNC_NONE;
+    fwInst.switchHangOver = 0;
+    fwInst.ioDelayAdjust  = FALSE;
+
+       /* Start McASP LLD  for input transfer */
+       inputXferStart();
+
+       numFrameReceived = 0;
+    numPcmFrameReceived = 0;
+       numSyncLost = 0;
+
+    /* Forever loop to continously receviec and transmit audio data           */
+    while (1)
+    {
+        if(gblErrFlag) {
+            num_gbl_err++;
+            break;
+        }
+
+        Semaphore_pend(semR, BIOS_WAIT_FOREVER);
+
+        RxTSKcnt++;
+
+        ioPhyXferComplete(fwInst.ioInp.hIoPhy, fwInst.ioInp.swapData);
+
+#ifndef INPUT_PCM_ONLY
+        if(fwInst.switchHangOver)
+        {
+            void *buff1, *buff2;
+            size_t size1, size2;
+
+            // Get read pointers (or sub-buffers) of the input buffer
+            if (ioBuffGetReadPtrs(fwInst.ioInp.hIoBuff, fwInst.phyXferSize,
+                                  &buff1, &size1, &buff2, &size2)
+                == IOBUFF_ERR_UNDERFLOW) {
+                printf("Input buffer underflows during switch hangover!\n");
+                exit(0);
+            }
+
+            ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff1, size1);
+
+            if(buff2 != NULL) {
+                ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff2, size2);
+            }
+
+            memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
+            fwInst.switchHangOver--;
+        }
+        else {
+            // Input format is unknown, perform auto-detection
+            autoDetstatus = ioDataProcess(fwInst.ioInp.hIoData);
+            if(autoDetstatus == IODATA_ERR_IOBUF_UNDERFLOW) {
+                // Input buffer underflows - no action is needed
+                //printf("Input buffer underflows.\n");
+                numUnderflow += 1;
+            }
+            else if(autoDetstatus != IODATA_NO_ERR) {
+                // print error log and return
+                printf("IODATA processing error!\n");
+                exit(0);
+            }
+            else {
+                // Check auto-detection status
+                ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
+                ioDataControl(fwInst.ioInp.hIoData, &ioDataCtl);
+
+                fwInst.syncState = ioDataCtl.param.autoDetStats.syncState;
+
+                if(fwInst.syncState == IODATA_SYNC_BITSTREAM) {
+                    if(fwInst.syncStatePrev != IODATA_SYNC_BITSTREAM) {
+                        // Change I/O PHY transfer size
+                        int frameSize;
+                        uint_least16_t pc = ioDataCtl.param.autoDetStats.bitStreamInfo & SYNC_PC_MASK; //0x001F
+                        frameSize = iecFrameLength[pc] * WORD_SIZE_BITSTREAM;
+
+                        ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
+                        ioPhyCtl.params.xferFrameSize = frameSize;
+                        ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
+                        fwInst.phyXferSize = ioPhyCtl.params.xferFrameSize;
+                    }
+
+                    numFrameReceived += 1;
+                }
+                else if(fwInst.syncState == IODATA_SYNC_PCM) {
+                    // reconfigure McASP LLD if necessary
+                    if(fwInst.syncStatePrev != IODATA_SYNC_PCM) {
+                        ioRecfgRxPhyForPcm();
+
+                        // Change I/O PHY transfer size
+                        ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
+                        ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_PCM;
+                        ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
+
+                        // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
+                        // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
+                        //ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE*2);
+                        fwInst.ioInp.swapData = FALSE;
+                        fwInst.phyXferSize = ioPhyCtl.params.xferFrameSize;
+
+                        fwInst.switchHangOver = INPUT_SWITCH_HANGOVER;
+                        fwInst.ioDelayAdjust  = TRUE;
+                    }
+
+                    numPcmFrameReceived += 1;
+                }
+                else if (fwInst.syncState == IODATA_SYNC_NONE) {
+
+                    if(fwInst.syncStatePrev != IODATA_SYNC_NONE) {
+                        numSyncLost += 1;
+                        numUnderflow = 0;
+                    }
+
+                    if(fwInst.syncStatePrev == IODATA_SYNC_PCM) {
+                        // reconfigure McASP LLD to 16-bit packed bits
+                        ioRecfgRxPhyForBitStream();
+
+                        // Change I/O PHY transfer size
+                        ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
+                        ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
+                        ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
+
+                        // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
+                        // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
+                        //ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE*2);
+
+                        fwInst.ioInp.swapData = TRUE;
+                        fwInst.phyXferSize  = ioPhyCtl.params.xferFrameSize;
+                        numPcmFrameReceived = 0;
+
+                        fwInst.switchHangOver = INPUT_SWITCH_HANGOVER;  // don't need hangover, since data is all 0's anyway
+                        fwInst.ioDelayAdjust  = TRUE;                   // no need to adjust delay since read size doesn't change during PCM
+                    }
+                    else if(fwInst.syncStatePrev == IODATA_SYNC_BITSTREAM) {
+                        numFrameReceived = 0;
+
+                        // Change I/O PHY transfer size
+                        ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
+                        ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
+                        ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
+                    }
+                    else {
+                        // SYNC has not been detected
+                        ;
+                    }
+                }
+
+                fwInst.syncStatePrev = ioDataCtl.param.autoDetStats.syncState;
+
+                // Receive processing: decoding bitstream or simply passing PCM to output
+                // To add proper processing for HDMI 4xlane interface: bitstream or PCM
+                /*if ((fwInst.syncState != IODATA_SYNC_NONE) && (fwInst.switchHangOver == 0)) {
+                    rxDecodeProcess();
+                }
+                else {
+                    if(fwInst.switchHangOver > 0) {
+                        fwInst.switchHangOver--;
+                    }
+                    memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
+                }*/
+
+                if(fwInst.syncState == IODATA_SYNC_NONE) {
+                    memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
+                }
+                else {
+                    if(fwInst.switchHangOver) {
+                        memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
+                        fwInst.switchHangOver--;
+                    }
+                    else {
+                        rxDecodeProcess();
+                    }
+                }
+
+                // Mark the input as read complete
+                if(fwInst.ioDelayAdjust) {
+                    // don't mark input buffer as read complete
+                    ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, fwInst.phyXferSize);
+                    fwInst.ioDelayAdjust = FALSE;
+                }
+                else {
+                    ioDataReadComplete(fwInst.ioInp.hIoData);
+                }
+            }
+        }
+#else
+        // Input is configured to PCM data
+        audio_rx_proc();
+
+        rxCount++;
+        if(rxCount == 2000) {
+            ioRecfgRxPhyForPcm();
+        }
+
+        if(rxCount == 4000) {
+            ioRecfgRxPhyForBitStream();
+            rxCount = 0;
+        }
+
+#if 0
+        // test McASP LLD reset
+        count += 1;
+        if(count == 1000) {
+            mcaspRxReset();
+            mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
+            mcaspRxCreate();
+            status = ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
+            if(status != IOPHY_NOERR) {
+                printf("ioPhyXferErrRecover fails with error code %d!\n.", status);
+                exit(0);
+            }
+
+            count = 0;
+            resetCount += 1;
+        }
+#endif
+#endif
+
+        if(check_mcasp_rx_overrun()) {
+            mcasp_rx_restart();
+            ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
+        }
+        else {
+            if(ioPhyXferSubmit(fwInst.ioInp.hIoPhy) == IOPHY_ERR_BUFF_OVERFLOW) {
+              fwInst.buf_status_in = FW_IOBUF_OVERFLOW;
+              printf("Input buffer overflows in Rx task!\n");
+              exit(0);
+            } else {
+              fwInst.buf_status_in = FW_IOBUF_NORMAL;
+            }
+        }
+    } /* while (1) */
+
+} /* taskAsipFxn */
+
+Void taskAsopFxn(const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ)
+{
+    /* Initialize I/O components for output */
+    ioCompsInitOutput();
+
+    /* Start McASP LLD for output transfer */
+       outputXferStart();
+
+       /* Forever loop to continously receviec and transmit audio data           */
+    //for (i32Count = 0; i32Count >= 0; i32Count++)
+    while (1)
+    {
+        if(gblErrFlag) {
+            num_gbl_err++;
+            break;
+        }
+
+        Semaphore_pend(semT, BIOS_WAIT_FOREVER);
+
+        TxTSKcnt++;
+
+        ioPhyXferComplete(fwInst.ioOut.hIoPhy, FALSE);
+
+#ifdef TEST_OVERFLOW_UNDERFLOW
+        if(TxTSKcnt == 200) {
+          while(fwInst.buf_status_out != FW_IOBUF_OVERFLOW) {
+            audio_tx_proc();  // create output buffer overflow situation
+          }
+        }
+
+        if(   (TxTSKcnt < 250) || (TxTSKcnt > 260) 
+           || (fwInst.buf_status_out == FW_IOBUF_UNDERFLOW)) {
+            audio_tx_proc();  // create output buffer underflow situation
+                              // between 250 and 260
+        }
+
+        if(fwInst.buf_status_out == FW_IOBUF_UNDERFLOW) {
+            audio_tx_proc();  // process one more frame during underflow
+        }
+
+        if(TxTSKcnt == 500) {
+            TxTSKcnt = 0;
+            TxFlag   = 0;
+            TxFlag1  = 0;
+            TxFlag2  = 0;
+        }
+#else
+        audio_tx_proc();  // process one more frame during underflow
+#endif
+
+        if(check_mcasp_tx_underrun()) {
+               mcasp_tx_restart();
+        }
+        else {
+            if(ioPhyXferSubmit(fwInst.ioOut.hIoPhy)==IOPHY_ERR_BUFF_UNDERFLOW) {
+              fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
+              //System_printf("Debug: output buffer underflows in Tx task!\n");
+            }
+            else {
+              fwInst.buf_status_out = FW_IOBUF_NORMAL;
+            }
+        }
+    } /* while (1) */
+} /* taskAsopFxn */
+
+#endif  // end of #ifndef USE_IO_COMPONENTS
+
+#endif  // end of #ifdef IO_LOOPBACK_TEST
+
+
+extern const uint_least16_t IECframeLength[23];
+
+void inputXferStart(void)
+{
+    Int32        count;
+
+#ifdef USE_IO_COMPONENTS
+    for(count = 0; count < NUM_PRIME_XFERS; count++)
+    {
+        ioPhyXferSubmit(fwInst.ioInp.hIoPhy);
+    }
+#else
+    int        status;
+
+    for(count = 0; count < NUM_PRIME_XFERS; count++)
+    {
+        /* Issue the first & second empty buffers to the input stream */
+       memset((uint8_t *)rxBuf[count], 0x0, INPUT_FRAME_SIZE);
+
+               /* RX frame processing */
+               rxFrame[count].cmd    = MCASP_READ;
+               rxFrame[count].addr   = (void*)(getGlobalAddr(rxBuf[count]));
+               rxFrame[count].size   = INPUT_FRAME_SIZE;
+               rxFrame[count].arg    = (uint32_t) mcaspRxChanArg;
+               rxFrame[count].status = 0;
+               rxFrame[count].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+               /* Submit McASP packet for Rx */
+               status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       IFPRINT(platform_write("mcaspSubmitChan for Rx Failed\n"));
+                       exit(0);
+               }
+    }
+
+//    rxFrameIndex = count;
+#endif
+} /* inputXferStart */
+
+void outputXferStart(void)
+{
+    Int32        count;
+
+       /* Create semaphores to wait for buffer reclaiming */
+//    semT = Semaphore_create(0, &SemParams, &eb);
+//    semT = Semaphore_create(0, NULL, NULL);
+
+#ifdef USE_IO_COMPONENTS
+    for(count = 0; count < NUM_PRIME_XFERS; count++)
+    {
+        if(ioPhyXferSubmit(fwInst.ioOut.hIoPhy)==IOPHY_ERR_BUFF_UNDERFLOW) {
+          fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
+          //System_printf("Debug, output buffer underflows in prime!\n");
+        } else {
+          fwInst.buf_status_out = FW_IOBUF_NORMAL;
+        }
+    }
+#else
+    int status;
+
+    for(count = 0; count < NUM_PRIME_XFERS; count++)
+    {
+       memset((uint8_t *)txBuf[count], 0x0, OUTPUT_FRAME_SIZE);
+
+               /* TX frame processing */
+               txFrame[count].cmd    = MCASP_WRITE;
+               txFrame[count].addr   = (void*)(getGlobalAddr(txBuf[count]));
+               txFrame[count].size   = OUTPUT_FRAME_SIZE;
+               txFrame[count].arg    = (uint32_t) mcaspTxChanArg;
+               txFrame[count].status = 0;
+               txFrame[count].misc   = 1;   /* reserved - used in callback to indicate asynch packet */
+
+               /* Submit McASP packet for Tx */
+               status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);
+               if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
+               {
+                       IFPRINT(platform_write("mcaspSubmitChan for Tx Failed\n"));
+                       exit(0);
+               }
+    }
+
+//     txFrameIndex = count;
+#endif
+} /* outputXferStart */
+
+int check_mcasp_rx_overrun(void)
+{
+    Mcasp_errCbStatus mcaspErrStat;
+
+    mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
+
+    return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
+}
+
+void mcasp_rx_restart(void)
+{
+       mcaspRxReset();
+    mcaspRxCreate();
+}
+
+int check_mcasp_tx_underrun(void)
+{
+    Mcasp_errCbStatus mcaspErrStat;
+
+    mcaspControlChan(hMcaspTxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
+
+    return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
+}
+
+void mcasp_tx_restart(void)
+{
+       mcaspTxReset();
+    mcaspTxCreate();
+       ioPhyXferErrRecover(fwInst.ioOut.hIoPhy);
+}
+
+void ioSemaphoreCreate(void)
+{
+    Semaphore_Params_init(&SemParams);
+
+    semR = Semaphore_create(0, &SemParams, NULL);
+    semT = Semaphore_create(0, &SemParams, NULL);
+}
+
+void ioRecfgRxPhyForBitStream()
+{
+    Int status = Audk2g_EOK;
+
+    if(mcaspRxChanParam.wordWidth != Mcasp_WordLength_16) {
+        //mcaspRxReset();
+
+        mcaspRxChanParam.wordWidth = Mcasp_WordLength_16;
+        status = mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_PARAMS_WORD_WIDTH, &mcaspRxChanParam);
+
+        //status = mcaspRxCreate();
+
+        if(status != Audk2g_EOK) {
+            printf("McASP LLD reconfiguration for bitstream fails!\n");
+            exit(0);
+        }
+
+        //ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
+    }
+} /* ioRecfgRxPhyForBitStream */
+
+void ioRecfgRxPhyForPcm(void)
+{
+    Int status = Audk2g_EOK;
+
+    if(mcaspRxChanParam.wordWidth != Mcasp_WordLength_32) {
+        //mcaspRxReset();
+
+        mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
+
+        status = mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_PARAMS_WORD_WIDTH, &mcaspRxChanParam);
+        //status = mcaspRxCreate();
+        if(status != Audk2g_EOK) {
+            printf("McASP LLD reconfiguration for PCM fails!\n");
+            exit(0);
+        }
+
+        //ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
+    }
+} /* ioRecfgRxPhyForPcm */
diff --git a/pasdk/test_dsp/io/test/frame_work.c b/pasdk/test_dsp/io/test/frame_work.c
new file mode 100644 (file)
index 0000000..9216d33
--- /dev/null
@@ -0,0 +1,207 @@
+
+#include <stdio.h>
+#include <xdc/runtime/Error.h>
+#include "../io/ioPhy.h"
+#include "../io/ioBuff.h"
+#include "frame_work.h"
+#include <ti/sysbios/io/IOM.h>  // for definition of Ptr 
+#include "audioStreamProc_common.h"
+#include "mcasp_cfg.h"
+#include "ioConfig.h"
+
+
+fwInst_t fwInst;
+
+/* Handle to heap object */
+//extern HeapMem_Handle heapHandle;
+//extern HeapMem_Handle HEAP_EXTERNAL;
+extern HeapMem_Handle heapMemDdr3;
+extern HeapMem_Handle heapMemL2Sram;
+
+/* McASP channel handles */
+extern Ptr hMcaspTxChan;
+extern Ptr hMcaspRxChan;
+
+Ptr databuf[NUM_BUFS];
+
+extern Int PAF_ASIT_ioCompCreate(PAF_AST_IoInp *pIoInp, int numInp, IHeap_Handle iHeapHandle);
+extern Int PAF_ASOT_ioCompCreate(PAF_AST_IoOut *pIoOut, int numOut, IHeap_Handle iHeapHandle);
+
+void ioCompsCreate()
+{
+    int errLineNum;
+    IHeap_Handle iheap;
+
+    iheap = HeapMem_Handle_to_xdc_runtime_IHeap(heapMemDdr3);
+
+    /* I/O components memory for input - only 1 input for standalone test */
+    errLineNum = PAF_ASIT_ioCompCreate(&fwInst.ioInp, 1, iheap);
+    if(errLineNum)
+    {
+        printf("Memory allocation fails for input I/O components!\n");
+        exit(0);
+    }
+
+    /* I/O components memory for output  - only 1 output for standalone test  */
+    errLineNum = PAF_ASOT_ioCompCreate(&fwInst.ioOut, 1, iheap);
+    if(errLineNum)
+    {
+        printf("Memory allocation fails for output I/O components!\n");
+        exit(0);
+    }
+}
+
+extern Ptr txBuf[NUM_BUFS];
+extern Ptr rxBuf[NUM_BUFS];
+extern Ptr procBuf;
+
+void ioBuffersCreate(void)
+{
+    Error_Block  eb;
+    uint32_t     count = 0;
+    IHeap_Handle iheap;
+    void *io_mempool_in;
+    void *io_mempool_out;
+
+    iheap = HeapMem_Handle_to_xdc_runtime_IHeap(heapMemDdr3);
+    Error_init(&eb);
+
+#ifdef USE_IO_COMPONENTS
+    /* Allocate memory for audio input memory pool                          */
+    io_mempool_in = Memory_calloc(iheap, INPUT_BUFF_SIZE, BUFALIGN, &eb);
+    if(NULL == io_mempool_in){
+      System_printf("\r\nMEM_calloc for io_mempool_in failed.\n");
+      exit(0);
+    }
+    fwInst.iomem_pool_input_base = io_mempool_in;
+    fwInst.iomem_pool_input_size = INPUT_BUFF_SIZE;
+
+    /* Allocate buffers for audio data processing                           */
+    for(count = 0; count < (NUM_BUFS); count ++)
+    {
+        databuf[count] = Memory_calloc(iheap, INPUT_FRAME_SIZE_PCM * 4,
+                                       BUFALIGN, &eb);
+        if(NULL == databuf[count]) {
+            System_printf("\r\nMEM_calloc failed.\n");
+            exit(0);
+        }
+    }
+
+    /* Allocate memory for audio output memory pool                          */
+    io_mempool_out = Memory_calloc(iheap, OUTPUT_BUFF_SIZE, BUFALIGN, &eb);
+    if(NULL == io_mempool_out){
+      System_printf("\r\nMEM_calloc for io_mempool_out failed.\n");
+      exit(0);
+    }
+    fwInst.iomem_pool_output_base = io_mempool_out;
+    fwInst.iomem_pool_output_size = OUTPUT_BUFF_SIZE;
+
+#else
+    /* Allocate buffers for the McASP data exchanges */
+    for(count = 0; count < NUM_BUFS; count++)
+    {
+        rxBuf[count] = Memory_calloc(iheap, INPUT_FRAME_SIZE_PCM,
+                                     BUFALIGN, &eb);
+        if(NULL == rxBuf[count])
+        {
+            IFPRINT(platform_write("\r\nMEM_calloc failed for Rx\n"));
+        }
+    }
+
+    /* Allocate buffers for the McASP data exchanges */
+    for(count = 0; count < NUM_BUFS; count++)
+    {
+        txBuf[count] = Memory_calloc(iheap, INPUT_FRAME_SIZE_PCM,
+                                     BUFALIGN, &eb);
+        if(NULL == txBuf[count])
+        {
+            IFPRINT(platform_write("\r\nMEM_calloc failed for Tx\n"));
+        }
+    }
+
+    procBuf = Memory_calloc(iheap, INPUT_FRAME_SIZE_PCM, BUFALIGN, &eb);
+#endif
+
+} /* ioBuffersCreate */
+
+void audioIoCreate(void)
+{
+#ifdef USE_IO_COMPONENTS
+    ioCompsCreate();
+#endif
+
+    ioBuffersCreate();
+}
+
+extern const MdUns iecFrameLength[23];
+
+void ioCompsInitInput()
+{
+    ioDataParam_t  ioDataCfg;
+    ioBuffParams_t ioBuffParams;
+    ioPhyParams_t  ioPhyParams;
+
+    ioBuffParams.base         = fwInst.iomem_pool_input_base;
+    ioBuffParams.size         = fwInst.iomem_pool_input_size;
+    ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
+    ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF*NUM_DELAY_BUFS_INPUT;
+    if(ioBuffInit(fwInst.ioInp.hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
+      printf("Input ioBuffInit error!\n");
+      exit(0);
+    }
+
+    ioPhyParams.ioBuffHandle    = fwInst.ioInp.hIoBuff;
+#ifdef INPUT_PCM_ONLY
+    ioPhyParams.xferFrameSize   = INPUT_FRAME_SIZE_PCM;
+#else
+    ioPhyParams.xferFrameSize   = INPUT_FRAME_SIZE_DEF;
+#endif
+    ioPhyParams.mcaspChanHandle = hMcaspRxChan;
+    ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_WRITE;
+    if(ioPhyInit(fwInst.ioInp.hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
+      printf("Input ioPhyInit error!\n");
+      exit(0);
+    }
+
+    ioDataCfg.ioBuffHandle         = fwInst.ioInp.hIoBuff;
+    ioDataCfg.unknownSourceTimeOut = 30720; //30720;
+    ioDataCfg.frameLengthsIEC      = (uint_least16_t *)&iecFrameLength[0];
+    ioDataCfg.frameLengthPCM       = INPUT_FRAME_SIZE_PCM / WORD_SIZE_PCM;
+    ioDataCfg.frameLengthDef       = INPUT_FRAME_SIZE_DEF / WORD_SIZE_BITSTREAM;
+    ioDataCfg.ibMode               = 0;
+    ioDataCfg.zeroRunRestart       = 300;
+    ioDataCfg.zeroRunTrigger       = 20;
+
+    if(ioDataInit(fwInst.ioInp.hIoData, &ioDataCfg) != IODATA_NO_ERR) {
+        printf("Input ioDataInit error!\n");
+        exit(0);
+    }
+
+} /* ioCompsInitInput */
+
+void ioCompsInitOutput()
+{
+    ioBuffParams_t ioBuffParams;
+    ioPhyParams_t  ioPhyParams;
+
+    ioBuffParams.base         = fwInst.iomem_pool_output_base;
+    ioBuffParams.size         = fwInst.iomem_pool_output_size;
+    ioBuffParams.sync         = IOBUff_READ_SYNC;
+    ioBuffParams.nominalDelay = OUTPUT_FRAME_SIZE*NUM_DELAY_BUFS_OUTPUT;
+    if(ioBuffInit(fwInst.ioOut.hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
+      printf("Output ioBuffInit error!\n");
+      exit(0);
+    }
+
+    ioPhyParams.ioBuffHandle    = fwInst.ioOut.hIoBuff;
+    ioPhyParams.xferFrameSize   = OUTPUT_FRAME_SIZE;
+    ioPhyParams.mcaspChanHandle = hMcaspTxChan;
+    ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
+    if(ioPhyInit(fwInst.ioOut.hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
+      printf("Output ioPhyInit error!\n");
+      exit(0);
+    }
+} /* ioCompsInitOutput */
+
+
+
diff --git a/pasdk/test_dsp/io/test/frame_work.h b/pasdk/test_dsp/io/test/frame_work.h
new file mode 100644 (file)
index 0000000..71b3174
--- /dev/null
@@ -0,0 +1,82 @@
+
+#ifndef FRAME_WORK_H
+#define FRAME_WORK_H
+
+#include "ioPhy.h"
+#include "ioBuff.h"
+#include "ioData.h"
+
+#include "mcasp_cfg.h"
+#include "audioStreamInpProc.h"
+#include "audioStreamOutProc.h"
+
+#define USE_IO_COMPONENTS           // define this to use I/O components: I/O BUFF and I/O PHY
+                                    // undefine for loopback test without using I/O components
+
+/** Num Bufs to be issued and reclaimed */
+#define NUM_BUFS                (8)    // Used for validation testing (not used for PASDK)
+
+#define BUFALIGN                (128) /* Alignment of buffer for use of L2 cache */
+
+/* Number of I/O buffers - used for validation testing (not used for PASDK). */
+//#define NUM_INPUT_BUFS             (30*3)  // large enough to hold 3 THD frames
+#define NUM_INPUT_BUFS             (30*4)  // large enough to hold 3 THD frames
+#define NUM_OUTPUT_BUFS            (12)
+
+/* Number of buffers constituting the nominal delay for I/O buffer management. */
+#define NUM_DELAY_BUFS_INPUT     1
+#define NUM_DELAY_BUFS_OUTPUT    3
+
+/* Size of total I/O buffer - used for validation testing (not used for PASDK). */
+#define INPUT_BUFF_SIZE         (1024*2)*NUM_INPUT_BUFS     // large enough to hold 3 THD frames
+#define OUTPUT_BUFF_SIZE        (OUTPUT_FRAME_SIZE * NUM_OUTPUT_BUFS)
+
+/* Operation status of I/O buffer management. */
+enum {
+  FW_IOBUF_NORMAL = 0,
+  FW_IOBUF_UNDERFLOW,
+  FW_IOBUF_OVERFLOW
+};
+
+#if 0
+typedef struct fw_inst_s {
+  void *       mcasp_chan_handle_input;
+  void *       mcasp_chan_handle_output;
+  ioPhyHandle_t  iophy_handle_input;
+  ioPhyHandle_t  iophy_handle_output;
+  ioBuffHandle_t iobuf_handle_input;
+  ioBuffHandle_t iobuf_handle_output;
+  ioDataHandle_t iodata_handle;
+  void *       iomem_pool_input_base;
+  size_t       iomem_pool_input_size;
+  void *       iomem_pool_output_base;
+  size_t       iomem_pool_output_size;
+
+  uint_fast16_t  buf_status_in;
+  uint_fast16_t  buf_status_out;
+} fw_inst_t;
+
+extern void io_create(void *mcasp_chan_handle_rx, void *mcasp_chan_handle_tx);
+#endif
+
+typedef struct fwInst_s {
+    PAF_AST_IoInp  ioInp;
+    PAF_AST_IoOut  ioOut;
+    void *       iomem_pool_input_base;
+    size_t       iomem_pool_input_size;
+    void *       iomem_pool_output_base;
+    size_t       iomem_pool_output_size;
+    size_t       phyXferSize;
+
+    void *       hMcaspRxChan;
+
+    int_fast32_t   switchHangOver;
+    uint_fast16_t  buf_status_in;
+    uint_fast16_t  buf_status_out;
+    uint_least16_t syncState;
+    uint_least16_t syncStatePrev;
+    uint_fast16_t  ioDelayAdjust;
+
+}fwInst_t;
+
+#endif
index 980da950d9b8a900637d251deeb758b525ea19a6..ce7183a7e3eb8d184d1127fe30d9d820493b6ae1 100644 (file)
@@ -220,7 +220,7 @@ const SmUns iecPafSource[23] =
 };
 
 // IEC framelengths (in 16bit words)
-static const MdUns iecFrameLength[23] =
+const MdUns iecFrameLength[23] =
 {
     0,
     1536*2,