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.

Left/Right Channel Separation using EDMA

Hello,

I am trying to separate the left and right channels using the EDMA, but the values in the buffers seem to remain the same all the time. I am sending 2 sine waves with different frequencies on each channel. I am trying to do the separation in real time. In the ping buffer is one channel saved and in the pong buffer the second one. Below are the two files with my code. I would be very grateful if someone could help me.

Thanks in advance,

Laura 

skeleton.h

#include "header.h"

void main(void)
{
	CSL_init();  /* init CSL */
	

	/* Konfiguration des AIC23 �ber McBSP0 */
	Config_DSK6713_AIC23();
	
	/* Konfiguration des McBSP1 - Datenschnittstelle */
	hMcbsp = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
    MCBSP_config(hMcbsp, &datainterface_config);
    
    config_EDMA();

    /* interrupts immer zuletzt */
    config_interrupts();

    MCBSP_start(hMcbsp, MCBSP_RCV_START | MCBSP_XMIT_START, 0xffffffff);
    MCBSP_write(hMcbsp, 0x0); /* einmal schie�en */
} /* und fertig */


void config_EDMA(void)
{
	/* Konfiguration der EDMA zum Lesen*/
	hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);  // EDMA Kanal f�r das Event REVT1
	hEdmaRcvPing = EDMA_allocTable(-1);                     // Reload-Parametersatz Ping
	hEdmaRcvPong = EDMA_allocTable(-1);                     // Reload-Parametersatz Pong


	configEDMARcv.src = MCBSP_getRcvAddr(hMcbsp);          //  Quell-Adresse zum Lesen

	// receive ping (default)
	tccRcvPing = EDMA_intAlloc(-1);                        // n�chsten freien Transfer-Complete-Code
	configEDMARcv.opt |= EDMA_FMK(OPT,TCC,tccRcvPing);     // dann der Grundkonfiguration des EDMA Empfangskanals zuweisen
	configEDMARcv.dst = (short)Buffer_in_ping;			   // Ziel Adresse

	/* ersten Transfer und Reload-Ping mit Config Ping konfigurieren */
	EDMA_config(hEdmaRcv, &configEDMARcv);
	EDMA_config(hEdmaRcvPing, &configEDMARcv);

	//receive pong
	tccRcvPong = EDMA_intAlloc(-1);                        // n�chsten freien Transfer-Complete-Code
	configEDMARcv.opt |= EDMA_FMK(OPT,TCC,tccRcvPong);     // dann der Grundkonfiguration des EDMA Empfangskanals zuweisen
	configEDMARcv.dst =(short)Buffer_in_pong;

	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
	EDMA_config(hEdmaRcvPong, &configEDMARcv);
	
	/* Transfers verlinken ping -> pong -> ping */
	EDMA_link(hEdmaRcv,hEdmaRcvPong);
	EDMA_link(hEdmaRcvPong,hEdmaRcvPing);
	EDMA_link(hEdmaRcvPing,hEdmaRcvPong);

	/* Konfiguration der EDMA zum Schreiben*/
	hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET);  // EDMA Kanal f�r das Event XEVT1
	hEdmaXmtPing = EDMA_allocTable(-1);                     // Reload-Parametersatz Ping
	hEdmaXmtPong = EDMA_allocTable(-1);                     // Reload-Parametersatz Pong

	configEDMAXmt.dst = MCBSP_getXmtAddr(hMcbsp);		//Ziel Adresse zum Schreiben


	//transmit ping (default)
	configEDMAXmt.src =(short)Buffer_out_ping;		//  Quell-Adresse zum Schreiben
	tccXmtPing = EDMA_intAlloc(-1);							// n�chsten freien Transfer-Complete-Code
	configEDMAXmt.opt |= EDMA_FMK(OPT,TCC,tccXmtPing);

	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
	EDMA_config(hEdmaXmt, &configEDMAXmt);
	EDMA_config(hEdmaXmtPing, &configEDMAXmt);

	//transmit pong
	configEDMAXmt.src =(short)Buffer_out_pong;		//  Quell-Adresse zum Schreiben
	tccXmtPong = EDMA_intAlloc(-1);							// n�chsten freien Transfer-Complete-Code
	configEDMAXmt.opt |=EDMA_FMK(OPT,TCC,tccXmtPong);

	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
	EDMA_config(hEdmaXmtPong, &configEDMAXmt);

	/* Transfers verlinken ping -> pong -> ping */
	EDMA_link(hEdmaXmt,hEdmaXmtPong);
	EDMA_link(hEdmaXmtPong,hEdmaXmtPing);
	EDMA_link(hEdmaXmtPing,hEdmaXmtPong);

	/* EDMA TCC-Interrupts freigeben */
	// receive ping
	EDMA_intClear(tccRcvPing);
	EDMA_intEnable(tccRcvPing);
	// receive pong
	EDMA_intClear(tccRcvPong);
	EDMA_intEnable(tccRcvPong);
	// transmit ping
	EDMA_intClear(tccXmtPing);
	EDMA_intEnable(tccXmtPing);
	// transmit ping
	EDMA_intClear(tccXmtPong);
	EDMA_intEnable(tccXmtPong);
	/* EDMA starten, wen alles? */
	EDMA_enableChannel(hEdmaRcv);
	EDMA_enableChannel(hEdmaXmt);
}

void config_interrupts(void)
{
	IRQ_globalDisable();				//Disable all Interrupts for init of serial data port
	IRQ_map(IRQ_EVT_EDMAINT, 8);
	IRQ_clear(IRQ_EVT_EDMAINT);
	IRQ_enable(IRQ_EVT_EDMAINT);
	IRQ_globalEnable();

}

void EDMA_interrupt_service(void)
{
	static volatile int rcvPingDone=0;
	static volatile int rcvPongDone=0;
	static volatile int xmtPingDone=0;
	static volatile int xmtPongDone=0;
	
	if(EDMA_intTest(tccRcvPing)) {
		EDMA_intClear(tccRcvPing); /* ohne clear geht es NICHT */
		rcvPingDone=1;
	}
	else if(EDMA_intTest(tccRcvPong)) {
		EDMA_intClear(tccRcvPong);
		rcvPongDone=1;
	}
	
	if(EDMA_intTest(tccXmtPing)) {
		EDMA_intClear(tccXmtPing);
		xmtPingDone=1;
	}
	else if(EDMA_intTest(tccXmtPong)) {
		EDMA_intClear(tccXmtPong);
		xmtPongDone=1;
	}	
	
	if(rcvPingDone && xmtPingDone) {
		rcvPingDone=0;
		xmtPingDone=0;
		// SW-Interrupt mit Verarbeitung
		SWI_post(&swi_ping);
	}
	else if(rcvPongDone && xmtPongDone) {
		rcvPongDone=0;
		xmtPongDone=0;
		// SW-Interrupt mit Verarbeitung
		SWI_post(&swi_pong);
	}
}

void process_ping_SWI(void)
{
	int i;
	for(i=0; i<BUFFER_LEN; i++)
		*(Buffer_out_ping+i) = *(Buffer_in_ping+i);

}

void process_pong_SWI(void)
{
	int i;
	for(i=0; i<BUFFER_LEN; i++)
		*(Buffer_out_pong+i) = *(Buffer_in_pong+i);
}

  • I'm sorry, I forgot to specify that I use C6713.
  • Laura,

    My recommendation is for you to go to TI.com and search for "c6713 workshop" (no quotes). The archived workshop has 'integration' in the title. It should have some good discussion about the EDMA and indexing, which is what you need for doing this.

    You will need to have left_ping and left_pong and right_ping and right_pong buffers. Putting left into the ping buffer and right into the pong buffer will not leave you any time to do processing once they two buffers are filled. Giving you a lot of time for processing is the reason to use ping and pong buffers.

    When you have been through the workshop, if you modify your project and still have problems, please let us know how it is working. You may also find examples or descriptions in the EDMA User Guide for the C6713, or look for some application notes that will help.

    Regards,
    RandyP
  • Hi,

    I would also reecommend you to go through the lab doc as below which involves programming the TMS320C6713 DSP Starter Kit (DSK) module:

    http://ecee.colorado.edu/~fmeyer/class/ecen4532/lab6.pdf

    The above lab would include sample c codes, examples, lab assignments etc. and hope, it will help you. The below are the test projects available on the above link:

    http://processors.wiki.ti.com/index.php/File:C6713_audio_minimal.zip

    https://ecee.colorado.edu/~fmeyer/class/ecen4532/startup.zip

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.

    -------------------------------------------------------------------------------------------------------

  • Hello,

    thank you for your suggestions. I have modified the program accordingly and the separation seems to work fine on the receiver side. I have plotted all eight buffers, ping and pong, in and out, for the left and right. In the left channel I have a sine of one frequency and in the right channel I have the other sine wave with another frequency. The problem is on the transmitter side. The 2 sine waves are damaged, They don't sound like they should. Below you can see the modified files.

    I also have another question related to Frame Index. I have configured it to be as big as my buffer size. What happens after the Frame Index becomes 0? Is it somehow reloaded? 

    4188.skeleton.h.

    Thank you very much,

    Laura

    #include "header.h"
    
    void main(void)
    {
    	CSL_init();  /* init CSL */
    	
    
    	/* Konfiguration des AIC23 �ber McBSP0 */
    	Config_DSK6713_AIC23();
    	
    	/* Konfiguration des McBSP1 - Datenschnittstelle */
    	hMcbsp = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
        MCBSP_config(hMcbsp, &datainterface_config);
        
        config_EDMA();
    
        /* interrupts immer zuletzt */
        config_interrupts();
    
        MCBSP_start(hMcbsp, MCBSP_RCV_START | MCBSP_XMIT_START, 0xffffffff);
        MCBSP_write(hMcbsp, 0x0); /* einmal schie�en */
    } /* und fertig */
    
    
    void config_EDMA(void)
    {
    	/* Konfiguration der EDMA zum Lesen*/
    	hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);  // EDMA Kanal f�r das Event REVT1
    	hEdmaRcvPing = EDMA_allocTable(-1);                     // Reload-Parametersatz Ping
    	hEdmaRcvPong = EDMA_allocTable(-1);                     // Reload-Parametersatz Pong
    
    
    	configEDMARcv.src = MCBSP_getRcvAddr(hMcbsp);          //  Quell-Adresse zum Lesen
    
    	// receive ping (default)
    	tccRcvPing = EDMA_intAlloc(-1);                        // n�chsten freien Transfer-Complete-Code
    	configEDMARcv.opt |= EDMA_FMK(OPT,TCC,tccRcvPing);     // dann der Grundkonfiguration des EDMA Empfangskanals zuweisen
    	configEDMARcv.dst = (short)Buffer_in_pingLEFT;			   // Ziel Adresse
    
    	/* ersten Transfer und Reload-Ping mit Config Ping konfigurieren */
    	EDMA_config(hEdmaRcv, &configEDMARcv);
    	EDMA_config(hEdmaRcvPing, &configEDMARcv);
    
    	//receive pong
    	tccRcvPong = EDMA_intAlloc(-1);                        // n�chsten freien Transfer-Complete-Code
    	configEDMARcv.opt |= EDMA_FMK(OPT,TCC,tccRcvPong);     // dann der Grundkonfiguration des EDMA Empfangskanals zuweisen
    	configEDMARcv.dst =(short)Buffer_in_pongLEFT;
    
    	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
    	EDMA_config(hEdmaRcvPong, &configEDMARcv);
    	
    	/* Transfers verlinken ping -> pong -> ping */
    	EDMA_link(hEdmaRcv,hEdmaRcvPong);
    	EDMA_link(hEdmaRcvPong,hEdmaRcvPing);
    	EDMA_link(hEdmaRcvPing,hEdmaRcvPong);
    
    	/* Konfiguration der EDMA zum Schreiben*/
    	hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET);  // EDMA Kanal f�r das Event XEVT1
    	hEdmaXmtPing = EDMA_allocTable(-1);                     // Reload-Parametersatz Ping
    	hEdmaXmtPong = EDMA_allocTable(-1);                     // Reload-Parametersatz Pong
    
    	configEDMAXmt.dst = MCBSP_getXmtAddr(hMcbsp);		//Ziel Adresse zum Schreiben
    
    
    	//transmit ping (default)
    	configEDMAXmt.src =(short)Buffer_out_pingLEFT;		//  Quell-Adresse zum Schreiben
    	tccXmtPing = EDMA_intAlloc(-1);							// n�chsten freien Transfer-Complete-Code
    	configEDMAXmt.opt |= EDMA_FMK(OPT,TCC,tccXmtPing);
    
    	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
    	EDMA_config(hEdmaXmt, &configEDMAXmt);
    	EDMA_config(hEdmaXmtPing, &configEDMAXmt);
    
    	//transmit pong
    	configEDMAXmt.src =(short)Buffer_out_pongLEFT;		//  Quell-Adresse zum Schreiben
    	tccXmtPong = EDMA_intAlloc(-1);							// n�chsten freien Transfer-Complete-Code
    	configEDMAXmt.opt |=EDMA_FMK(OPT,TCC,tccXmtPong);
    
    	/* ersten Transfer und Reload-Ping mit ConfigPing konfigurieren */
    	EDMA_config(hEdmaXmtPong, &configEDMAXmt);
    
    	/* Transfers verlinken ping -> pong -> ping */
    	EDMA_link(hEdmaXmt,hEdmaXmtPong);
    	EDMA_link(hEdmaXmtPong,hEdmaXmtPing);
    	EDMA_link(hEdmaXmtPing,hEdmaXmtPong);
    
    	/* EDMA TCC-Interrupts freigeben */
    	// receive ping
    	EDMA_intClear(tccRcvPing);
    	EDMA_intEnable(tccRcvPing);
    	// receive pong
    	EDMA_intClear(tccRcvPong);
    	EDMA_intEnable(tccRcvPong);
    	// transmit ping
    	EDMA_intClear(tccXmtPing);
    	EDMA_intEnable(tccXmtPing);
    	// transmit ping
    	EDMA_intClear(tccXmtPong);
    	EDMA_intEnable(tccXmtPong);
    	/* EDMA starten, wen alles? */
    	EDMA_enableChannel(hEdmaRcv);
    	EDMA_enableChannel(hEdmaXmt);
    }
    
    void config_interrupts(void)
    {
    	IRQ_globalDisable();				//Disable all Interrupts for init of serial data port
    	IRQ_map(IRQ_EVT_EDMAINT, 8);
    	IRQ_clear(IRQ_EVT_EDMAINT);
    	IRQ_enable(IRQ_EVT_EDMAINT);
    	IRQ_globalEnable();
    
    }
    
    void EDMA_interrupt_service(void)
    {
    	static volatile int rcvPingDone=0;
    	static volatile int rcvPongDone=0;
    	static volatile int xmtPingDone=0;
    	static volatile int xmtPongDone=0;
    	
    	if(EDMA_intTest(tccRcvPing)) {
    		EDMA_intClear(tccRcvPing); /* ohne clear geht es NICHT */
    		rcvPingDone=1;
    	}
    	else if(EDMA_intTest(tccRcvPong)) {
    		EDMA_intClear(tccRcvPong);
    		rcvPongDone=1;
    	}
    	
    	if(EDMA_intTest(tccXmtPing)) {
    		EDMA_intClear(tccXmtPing);
    		xmtPingDone=1;
    	}
    	else if(EDMA_intTest(tccXmtPong)) {
    		EDMA_intClear(tccXmtPong);
    		xmtPongDone=1;
    	}	
    	
    	if(rcvPingDone && xmtPingDone) {
    		rcvPingDone=0;
    		xmtPingDone=0;
    		// SW-Interrupt mit Verarbeitung
    		SWI_post(&swi_ping);
    	}
    	else if(rcvPongDone && xmtPongDone) {
    		rcvPongDone=0;
    		xmtPongDone=0;
    		// SW-Interrupt mit Verarbeitung
    		SWI_post(&swi_pong);
    	}
    }
    
    void process_ping_SWI(void)
    {
    	int i;
    	for(i=0; i<BUFFER_LEN; i++)
    		{ *(Buffer_out_pingLEFT+i) = *(Buffer_in_pingLEFT+i);
    		  *(Buffer_out_pingRIGHT+i) = *(Buffer_in_pingRIGHT+i);
    		}
    
    }
    
    void process_pong_SWI(void)
    {
    	int i;
    	for(i=0; i<BUFFER_LEN; i++)
    		{ *(Buffer_out_pongLEFT+i) = *(Buffer_in_pongLEFT+i);
    		  *(Buffer_out_pongRIGHT+i) = *(Buffer_in_pongRIGHT+i);
    		}
    }
    
    
     

  • Oh sorry, I mean Frame Count, not Frame Index.
  • Laura,

    It depends on how you have programmed it and what type of transfers you are doing. The EDMA User Guide is the best document for me when I am trying to understand how this works. But some prefer the training student guide provided as part of the workshop.

    Regards,
    RandyP