Port to Channel com.

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Port to Channel com.

Post by lilltroll »

Can the data from a syncronised serial port directly be sent to a channel?

In the code below, the sdin data are synced with bclk, but the data is sent to another thread for signal processing. So for the moment I'm using TEMP to transport the port data to the channel.
Can the TEMP-step be avoided ?

(The 4 rows of 0xCCCC... creates a squarewave with 32 periods.)

Code: Select all

sync(p_bclk);
...

Code: Select all

	 	             p_bclk 	<: 0xCCCCCCCC; 
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_sdin  :> TEMP_R;
	 	        	c_ADC_R <: TEMP_R;


Probably not the most confused programmer anymore on the XCORE forum.
User avatar
paul
XCore Addict
Posts: 169
Joined: Fri Jan 08, 2010 12:13 am
Contact:

Post by paul »

1) Not quite sure what you are implying by the use of the sync function - from the documentation:
void sync (void port p)

Waits until a port has completed any pending outputs.
So this just blocks to ensure you don't override any pending output on a port.

2) The temporary variable stage cannot be avoided - there is no direct interface from ports to channels
Paul

On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

I had timing problems with the channel com at high sampling freqs. as 192 kHz. I was simply starved out of time, but I solved it after a lot of trial and error.

What is the "special" with the use of outuint() and inuint() {from xs1.h }
instead of chan | streaming chan as described in the XC manual ?
It seems to take less time somehow !?

//confused

The main loop look like this

Code: Select all

 int main(){
	 chan c_DAC_L,c_DAC_R,c_ADC_L,c_ADC_R; //Used channels
	 
	 par{
		 I2S_slave(c_DAC_L,c_DAC_R,c_ADC_L,c_ADC_R);
		 ProcessAudio_L(c_DAC_L,c_ADC_L);
		 ProcessAudio_R(c_DAC_R,c_ADC_R);
	 }
	return 0;
		
 }

ProcessAudio look like this:

Code: Select all

void ProcessAudio_R(chanend c_DAC_R,chanend c_ADC_R)
  {
 	 unsigned int DATA=0;
 	 int k;
 	 while(1)
 	 {
 		 outuint(c_DAC_R,DATA);  // DAC data must always be ready on time
 		//********** START DSP CODE **************** 
 		 k=0;
		 while(k<600) //Stupid loop to emulate signal proc. load
		 {
			 k++;
		 }
		 //********** END DSP CODE ****************
		 DATA=inuint(c_ADC_R);		 
 	 }
  }

And the main while loop in the I2C function look like this

Code: Select all

while(1){
//****************** LEFT CHANNEL AUDIO DATA ******************
	 	   	   p_sdin :> TEMP_ADC_L; 		/* Input left Audio-data to TEMP */
	 	   	   outuint(c_ADC_L,TEMP_ADC_L); /* Send TEMP to channel ADC_L */
	 	   	   TEMP_DAC_L=inuint(c_DAC_L);  /* Store DAC_L channel to TEMP */
	 	       p_sdout <: TEMP_DAC_L;		/* Output left Audio-data from TEMP */
	 	    
	 	       p_lrclk <: 0x80000000;		//Change to Right channel	
	 	    		 	    
//************************************************
// Clock bclk 32 periods	    	
//************************************************
	 	    	#if (FREQ==0 || FREQ==2)	//44.1 or 96 kHz
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
				#endif
				#if (FREQ==1)				//48 kHz
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0; 
				#endif	
	 			#if (FREQ==4||FREQ==5)	//88.2 or 192 kHz
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
				#endif
//****************** RIGHT CHANNEL AUDIO DATA ******************
	 	        	p_sdin :> TEMP_ADC_R; 		/* Input right Audio-data to TEMP */
	 	        	outuint(c_ADC_R,TEMP_ADC_R);
	 	        	TEMP_DAC_R=inuint(c_DAC_R);
	 	        	p_sdout <: TEMP_DAC_R;
      	
	 	       	 	p_lrclk <: 0x7FFFFFFF; //Change to Left channel
//************************************************				
// Clock bclk 32 periods 	    	
//************************************************
	 	        	#if (FREQ==0 || FREQ==2)	//44.1 or 96 kHz
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
				#endif
				#if (FREQ==1)					//48 kHz
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0; 
				#endif	
 				#if (FREQ==4||FREQ==5)			//88.2 or 192 kHz
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
				#endif
/*******************************************************/ 	        		 	        
	 	        #ifdef decimate     	 
					#if(FREQ==4)				// Do 3 extra
	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;

	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	
	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	
	 	        	#endif
	 	        #endif   	        
	 				 	        	
	 		}
 }
User avatar
paul
XCore Addict
Posts: 169
Joined: Fri Jan 08, 2010 12:13 am
Contact:

Post by paul »

inuint and outuint functions are just a legacy of how streaming channels used to be used.There shouldn't be any difference in speed between them and the recommended <: and :> for streaming channels.

I find it a little odd that the code you use works at all as using inuint/outuint requires you to initialise the streaming channels by calling some specific functions.

In your current code if you replace the inuint/outuint functions with the normal <: and :> you will see a drop in performance as you are packetising the data over the channel as they aren't using streaming channels. This takes more instructions as control tokens have to be issued and received to open the channel over the switch and then close it once it is finished sending the 'packet'.
Paul

On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

Then I will try to change back to streaming chan and :> instead to make it more simple to read.
Probably not the most confused programmer anymore on the XCORE forum.
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

Well, I have time to count to 170 in the dummy loop @ 192kHz without glitches so it does seems to work fine with streaming channel, but i'm still confused regarding the channels.

I first wrote the channels like this, starting with the input, ending with the output - but it doesn't work

Code: Select all

void ProcessAudio_L(streaming chanend c_DAC_L,streaming chanend c_ADC_L)
  {
 	 unsigned int DATA=0;
 	 int k;
 	 while(1)
 	 {
 		 c_ADC_L :> DATA;
 		 //********** START DSP CODE **************** 
 		 k=0;
		 while(k<170) //Stupid loop to emulate signal proc. load
		 {
			 k++;
		 }
		 //********** END DSP CODE ****************
		 c_DAC_L <: bitrev(DATA);  // DAC data must always be ready on time		 
 	 }
  }
But it works the otherway around. Is it timing, prefilling or tokens or what ?? (in the upper case)

Code: Select all

 void I2S_slave(streaming chanend c_DAC_L,streaming chanend c_DAC_R,streaming chanend c_ADC_L,streaming chanend c_ADC_R){
	 unsigned int TEMP_ADC_R=0,TEMP_ADC_L=0,TEMP_DAC_R=0,TEMP_DAC_L=0;
	 configure_audio_ports(FREQ); 
	 p_control <: control_reg; 
	 	 
	
	 t :> time;
	 time += 100000;  // hold in reset for 1ms
	 t when timerafter(time) :> int _;
	 if ((FREQ == 0) || (FREQ == 5) || (FREQ == 6))
	    	control_reg=control_reg^0b010; // Choose 11.286 MHz clock
	 else
	    	control_reg=control_reg^0b110;// Choose 24.5 MHz clock
	 	    
	 p_control <: control_reg; // Release CODEC from reset	    		

	 /* Prefill the buffered ports. */ 
	 p_sdout <: 0;  
	 p_lrclk <: 0x7FFFFFFF; //Change to Left channel
	 p_bclk <: 0xAAAAAAAA;
	 p_bclk <: 0xAAAAAAAA;

	 	    
	 	    while(1){
//****************** LEFT CHANNEL AUDIO DATA ******************
	 	    	c_DAC_L:>TEMP_DAC_L;  		/* Store DAC_L channel to TEMP */
	 	    	p_sdout <: TEMP_DAC_L;		/* Output left Audio-data from TEMP */
	 	        p_sdin :> TEMP_ADC_L; 		/* Input left Audio-data to TEMP */
	 	   	    c_ADC_L<:bitrev(TEMP_ADC_L); /* Send TEMP to channel ADC_L */
	 	   	   
	 	        p_lrclk <: 0x80000000;		//Change to Right channel	
	 	    		 	    
//************************************************
// Clock bclk 32 periods	    	
//************************************************
	 	    	#if (FREQ==0 || FREQ==2)	//44.1 or 96 kHz
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
				#endif
				#if (FREQ==1)				//48 kHz
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0; 
				#endif	
	 			#if (FREQ==4||FREQ==5)	//88.2 or 192 kHz
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
				#endif
//****************** RIGHT CHANNEL AUDIO DATA ******************
	 	        	c_DAC_R :> TEMP_DAC_R;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_sdin :> TEMP_ADC_R;	/* Input right Audio-data to TEMP */
	 	        	c_ADC_R <: bitrev(TEMP_ADC_R);
	 	        		 	        	
	 	        	
	 	       	 	p_lrclk <: 0x7FFFFFFF; //Change to Left channel
//************************************************				
// Clock bclk 32 periods 	    	
//************************************************
	 	        	#if (FREQ==0 || FREQ==2)	//44.1 or 96 kHz
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
	 	        	p_bclk 	<: 0xCCCCCCCC;
				#endif
				#if (FREQ==1)					//48 kHz
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0;   
	 	        	p_bclk <: 0xF0F0F0F0; 
				#endif	
 				#if (FREQ==4||FREQ==5)			//88.2 or 192 kHz
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
				#endif
/*******************************************************/ 	        		 	        
	 	        #ifdef decimate     	 
					#if(FREQ==4)				// Do 3 extra
	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;

	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	
	 	           	p_sdout	<: TEMP_DAC_L;
	 	        	p_lrclk <: 0x80000000; 		//Change to Right channel
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_sdout <: TEMP_DAC_R;
	 	        	p_lrclk <: 0x7FFFFFFF;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	p_bclk <: 0xAAAAAAAA;
	 	        	
	 	        	#endif
	 	        #endif   	        
	 				 	        	
	 		}
 }
 
 void ProcessAudio_R(streaming chanend c_DAC_R,streaming chanend c_ADC_R)
 {
	 int h = 0, l = 0;
	 int X0=0,X1=0,X2=0;   // a global (in data pointer)
	 int Y0,Y1=0,Y2=0;
	 while(1)
	 {
		 c_DAC_R <: bitrev(Y0);
		 //********** START DSP CODE **************** 
		 //Directf form II IIR-filter
		 {h, l} = macs(B0, X0, 0, 0);
		 {h, l} = macs(B1, X1, h, l);
		 {h, l} = macs(B2, X2, h, l);
		 {h, l} = macs(A1, Y1, h, l);
		 {h, l} = macs(A2, Y2, h, l);
		 		 
		 Y0=h<<1;
		 X2=X1;
		 X1=X0;
         Y2=Y1;
         Y1=Y0;
         //********** END DSP CODE ****************
         c_ADC_R :> X0;
   	 }
 }
 
 void ProcessAudio_L(streaming chanend c_DAC_L,streaming chanend c_ADC_L)
  {
 	 unsigned int DATA=0;
 	 int k;
 	 while(1)
 	 {
 		 c_DAC_L <: bitrev(DATA);  // DAC data must always be ready on time
 		//********** START DSP CODE **************** 
 		 k=0;
		 while(k<170) //Stupid loop to emulate signal proc. load
		 {
			 k++;
		 }
		 //********** END DSP CODE ****************
		 c_ADC_L :> DATA;		 
 	 }
  }

 
 int main(){
	 streaming chan c_DAC_L,c_DAC_R,c_ADC_L,c_ADC_R; //Used channels
	 
	 par{
		 I2S_slave(c_DAC_L,c_DAC_R,c_ADC_L,c_ADC_R);
		 ProcessAudio_L(c_DAC_L,c_ADC_L);
		 ProcessAudio_R(c_DAC_R,c_ADC_R);
	 }
	return 0;
		
 }
Probably not the most confused programmer anymore on the XCORE forum.
Post Reply