This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ECU stop working after 30-60 sec

Hi there,

CCS5.5

C5515EVM

VoLib_2_1_0_1 CPU3

I am trying to get ECU worked but it always stop cancelling echo after 30 - 60 second. For testing purposes I am using ECU demo tracks(Sin and Rin) which come from PC to the board. Frames are synchronized and there is no delay between them. 

Within 30-60 sec it is working well, even better than I expected but after that time Sout is just a copy of Sin.

My code:

#define SIU_MAX_FRAME_LENGTH DMA_BUFFER_SIZE // 10ms maximum frame duration */
#define SIU_MAX_ECU_FILTER_LENGTH 1024 			   // 128ms tail search filter
#define SIU_MAX_ECU_FLTSEG 3 					   // Maximum of 3 individual filter segments
#define SIU_MAX_ECU_FLTSEG_LENGTH 256 			   // 32ms total BG filter coefficients
#define SIU_MAX_SYSTEM_DELAY 120 				   // 15ms maximum system delay between Rout/Sin
#define ecu_FG_FLTSEG 1
#define ecu_BG_FLTSEG 2
#define ecu_BG_E_BUF 3
#define ecu_RECEIVE_IN 4
#define ecu_EXPAND_DL_BUF 5
#define ecu_BG_UPDATE_BUF 6
#define ecu_SEARCH_FILTER_BUF 14
ecuContext_t ecuContext = {
	(vfnptr) my_exception,  //NULL,
    NULL, /* Debug streaming function pointer */
    NULL,
    NULL, /* Search filter swapping function */
    NULL, //ecu_send_out, /* Send out function pointer */
    NULL, //piuReceiveIn, /* Receive out function pointer */
    SIU_MAX_FRAME_LENGTH, /* Maximum number of samples per frame */
    SIU_MAX_ECU_FILTER_LENGTH, /* Maximum filter length in taps */
    SIU_MAX_ECU_FLTSEG_LENGTH, /* Maximum filter segment buffer length in taps */
    SIU_MAX_ECU_FLTSEG,  /* Maximum allowed active filter segments */
    SIU_MAX_SYSTEM_DELAY, 
    0L, /* Bitfield representing those portions of the delay line already expanded. */
    NULL, /* Pointer to base of the scratch delay line */
    NULL, /* TDM aligned pointer within scratch delay line */
    NULL, /* TDM aligned pointer within packed delay line */
};

typedef struct {
    Fract ecu_buf_1[512];
    Fract ecu_buf_2[512];
    linSample ecu_buf_3[80];
    linSample ecu_buf_4[2048];
    linSample ecu_buf_5[4096];
    Fract ecu_buf_6[2048];
    Fract ecu_buf_14[2048];
} ecu_buf_t;

void ecu_set_buffer(const ecomemBuffer_t *bufs, ecomemBuffer_t *ecuBufs, tint ecuNbufs, int inst_num)
{
    int i;

    for (i = 0; i < ecuNbufs; i++)
    {
        ecuBufs[i] = bufs[i];
        if (i == ecu_FG_FLTSEG)
        {
        	/* FG Filter */
            ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_1[0]);
            ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_1);
        }
        else if (i == ecu_BG_FLTSEG)
        {
        	/* BG Filter */
            ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_2[0]);
            ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_2);
        }
        else if (i == ecu_BG_E_BUF)
        {
        	/* BG Error Buffer IRAM */
            ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_3[0]);
            ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_3);
        }

        else if (i == ecu_RECEIVE_IN)
        {
        	/* ECU's recv-in buffer is aligned! */
            ecuBufs[i].volat = FALSE;
            ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_4[0]);
            ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_4);
        }
        else if (i == ecu_EXPAND_DL_BUF)
        {
        	/* ECU's recv-in buffer is aligned! */
            ecuBufs[i].volat = TRUE;
            ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_5[0]);
            ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_5);
        }
        else if (i == ecu_BG_UPDATE_BUF)
        {
        	/* BG Work Buffer IRAM */
            if (ecuBufs[i].size > 0)
            {
                ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_6[0]);
                ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_6);
            }
            else
            {
            	/* Float version may not use this buffer */
                ecuBufs[i].base = NULL;
                ecuBufs[i].size = 0;
            }
        }
        else if (i == ecu_SEARCH_FILTER_BUF)
        	{
        		/* Search filter buffer IRAM */
        		ecuBufs[i].volat = FALSE;
        		ecuBufs[i].base = &(ecu_buf[inst_num].ecu_buf_14[0]);
        		ecuBufs[i].size = sizeof(ecu_buf[inst_num].ecu_buf_14);
        	}
        	else
        	{
        		if (ecuBufs[i].size > 0)
        		{
        			ecuBufs[i].volat = FALSE;
        			ecuBufs[i].base = (mhmAlloc(vheap, bufs[i].size));
        		}
        		else
        		{
        			/* no buffer allocated if size zero or less */
        			ecuBufs[i].base = NULL;
                	ecuBufs[i].size = 0;
        		}
        	}

    }
}

int tst_ecu_new(int chan) {
    tint stat, ecuNbufs;
    const ecomemBuffer_t *bufs;

    tst_ecu_inst[chan].ecu_Inst = NULL;

    stat = ecuGetSizes(&ecuNbufs, &bufs, (void *) NULL);
    if (stat != ecu_NOERR) {
        return stat;
    }

    if((tst_ecu_inst[chan].ecu_buffers = (ecomemBuffer_t*) calloc(ecuNbufs,    sizeof(ecomemBuffer_t))) == NULL)
    {
    	printf("no memory\n");
    }

    vheap = mhmCreate(siu_voice_heap, SIU_VOICE_HEAP_SIZE, 0);

    ecu_set_buffer(bufs, tst_ecu_inst[chan].ecu_buffers, ecuNbufs, chan);

    tst_ecu_inst[chan].ecuCfgNew.ID = siuMakeID (SIU_MID_ECU, chan);

    stat = ecuNew(&(tst_ecu_inst[chan].ecu_Inst), ecuNbufs, tst_ecu_inst[chan].ecu_buffers, &(tst_ecu_inst[chan].ecuCfgNew));
    if (stat != ecu_NOERR) {
        ecu_init_result = stat;
//        return stat;
    	printf("ecuNew fail\n");
    }
    return 0;
}

int tst_ecu_open(int chan) {
    ecuConfigParam_t cfgParam;
    tst_ecu_inst[chan].ecuCfg.cfgParam = &cfgParam;

    tst_ecu_inst[chan].ecuCfg.samples_per_frame = 10 * 8; /* 10ms default frame duration */
    tst_ecu_inst[chan].ecuCfg.pcm_zero = (0x55D5);// A-law zero: 0x55D5, U-law zero: 0xFFFF
    tst_ecu_inst[chan].ecuCfg.pcm_expand_tbl = &muaTblAlaw[0];//NULL
    cfgParam.filter_length = SIU_MAX_ECU_FILTER_LENGTH; /* 128ms default ECU tail */
    cfgParam.config_bitfield = ecu_ENABLE_ECHO_CANCELLER |  
    						   ecu_ENABLE_UPDATE 		 |
    						   ecu_ENABLE_NLP 			 |
    						   ecu_ENABLE_AUTO_UPDATE    |
    						   ecu_ENABLE_SEARCH 		 |
    						   ecu_ENABLE_CNG_ADAPT 	 |
    						   ecu_ENABLE_OPNLP_DETECT   |
                                                   ecu_CLEAR_FG              |
                                                   ecu_CLEAR_BG              |
                                                   ecu_CLEAR_SEARCH;



    cfgParam.config_bitfield1 = 0;
    cfgParam.noise_level = 0; /* Use default (-70) if fixed */
    cfgParam.nlp_aggress = 0; /* balance performance */
    cfgParam.cn_config = 0; /* pink noise */


    ecuOpen(tst_ecu_inst[chan].ecu_Inst, &(tst_ecu_inst[chan].ecuCfg));
}

 

/* Compress A-law delay line samples */
muaTblAlawCmpr (DMA_BUFFER_SIZE, rinLinearPING_prt, rinCompr_prt);

/* Pack samples for delay line compression */
for (i=0; i<DMA_BUFFER_SIZE; i++) {
rinBuffer[i] = rinCompr[i] & 0xFF;
}

ecuSendIn(tst_ecu_inst[0].ecu_Inst, sinBufferPING_prt, rinBuffer_prt, soutBufferPING_prt);

Thank you.

  • I made it worked but it needs to be explained. Actually I put ecuControl function after ecuSendIn being called. The crucial thing is clearing any buffer or all (BG, FG or SEARCH). 

    void tst_ecu_control(int chan)
    {
    	tst_ecu_inst[chan].ecuCtl.ctl_code      = ecu_CTL_MASK;
    	tst_ecu_inst[chan].ecuCtl.u.ctl_mask[0] = ecu_ENABLE_ECHO_CANCELLER |   /* ENABLE ECU, ENABLE NLP, ENABLE UPDATE */
    	                                 	 	 ecu_ENABLE_UPDATE         |
    	                                 	 	 ecu_ENABLE_NLP            |
    	                                 	 	 ecu_ENABLE_AUTO_UPDATE    |
    	                                 	 	 ecu_ENABLE_SEARCH         |
    	                                 	 	 ecu_ENABLE_CNG_ADAPT      |
    	                                 	 	 ecu_ENABLE_OPNLP_DETECT   |
    //	                                         ecu_CLEAR_FG    ;//          |
    //	                                         ecu_CLEAR_BG;//              |
    	                                         ecu_CLEAR_SEARCH;
    
    
        ecuControl (tst_ecu_inst[chan].ecu_Inst, &(tst_ecu_inst[chan].ecuCtl));
    }

    But why it does not work without clearing buffers? I thought it is ECU responsibility to update buffers.

    Thanks

     

  • Hi Stan,

    Are you using TI-RTOS? If yes, please let us know the version. If this is a non TI-RTOS application, can you please post your question in the C5000 forum for faster response?

    Thanks,

    Vikram

  • Hi Vikram,

    I am DSP/BIOS user. All questions related to VoLIB were posted in DSP/BIOS(TI-RTOS) forum before. Moreover it was suggested by TI engineer to post them here.
    http://e2e.ti.com/support/embedded/tirtos/f/355/t/184439

    Sorry if I posted it in a wrong place. Please let me know and I will get it in the C5000 forum.
  • Hi Stan,


    On this forum, we support questions regarding the TI-RTOS (or DSP/BIOS) and related products. The VoLib is developed and supported by a different team in TI. So I suggest that you post your question in the device specific forum for a response on the VoLib questions.


    Thanks,

    Vikram

  • Thanks, I will do that.