Problems with clock and partial serial output.

Technical questions regarding the XTC tools and programming with XMOS.
Ganux
Active Member
Posts: 35
Joined: Tue Mar 08, 2011 12:58 pm

Problems with clock and partial serial output.

Post by Ganux »

Hello,

I am writing a serial interface for a MAX6974 LED-driver.
But, I am getting some problems for getting it running.
It should be clocked at 32 Mhz, so if I use:

configure_clock_rate(led_clk,128,4);

I'm getting the following error:
xrun: Program received signal ET_ECALL, Application exception.
0x0001031c in configure_clock_rate.coersed..f.7b0.7d.28ui.2cui.2cui.29 ()

Though, if I clock it at 10 Mhz it doesn't complain about the clock, but i get the following error:

xrun: Program received signal ET_ILLEGAL_RESOURCE, Resource not valid.
0x0001023e in send_header (command=<value optimized out>, p_led_data=66560, p_led_load=<value optimized out>, led_clk=<value optimized out>) at ../src/main.xc:132

I'll add the entire code below, but line 132 is:

partout(p_led_data, command_load_config, 6);

Code: Select all

#include <xs1.h>
#include <platform.h>

#include <print.h>

#define INDIVIDUAL_PWM 0
#define LOAD_CALDAC 1
#define GLOBAL_PDM 2
#define LOAD_CONFIG 3
#define DRIVERS 1		// aantal drivers dat gebruikt wordt

on stdcore[0]: clock led_clk	= XS1_CLKBLK_2;
out port p_led_clk 				= PORT_LED_OUT_CLK;
out buffered port:8 p_led_data 	= PORT_LED_OUT_R0;
out port p_led_load 			= PORT_LED_OUT_R1;

int initDriver(out buffered port:8 p_led_data, out port p_led_load, clock led_clk);
int send_header(int command, out buffered port:8 p_led_data, out port p_led_load, clock led_clk);



int main(){
	configure_clock_rate(led_clk,100,10);
	configure_port_clock_output(p_led_clk,led_clk);
	configure_out_port(p_led_data, led_clk,0);
	configure_out_port(p_led_load, led_clk,1);
	start_clock(led_clk);

	initDriver(p_led_data, p_led_load, led_clk);

	return 0;
}


int initDriver(out buffered port:8 p_led_data, out port p_led_load, clock led_clk){
	int config = 1;
	int caldac = 149;	// 149 steps is 20mA
	int global_pdm = 32;	// 32 frames on = 50%
	int R,G,B = 0;



	/*	config	*/
	send_header(LOAD_CONFIG, p_led_data, p_led_load, led_clk);
	for(int i=0; i<DRIVERS; i++){		//voor elke driver...
		for(int j=0; j<3; j++){			//3x sturen (zie datasheet)
			p_led_data <: config;
		}
	}

	/*	CALDAC	*/
	send_header(LOAD_CALDAC, p_led_data, p_led_load, led_clk);
	for(int i=0; i<DRIVERS; i++){		//voor elke driver...
		for(int j=0; j<3; j++){			//3x sturen (zie datasheet)
			p_led_data <: caldac;
		}
	}

	/*	Global PDM	*/
	send_header(GLOBAL_PDM, p_led_data, p_led_load, led_clk);
	for(int i=0; i<DRIVERS; i++){		//voor elke driver...
		for(int j=0; j<3; j++){			//3x sturen (zie datasheet)
			p_led_data <: global_pdm;
		}
	}

	/*	Individual PWM	*/
	send_header(INDIVIDUAL_PWM, p_led_data, p_led_load, led_clk);
	for(int i=0; i<DRIVERS; i++){
		for(int j=0; j<15;j++){				// 15x 0 sturen voor Blauw
			partout(p_led_data, 0, 4);
			p_led_data <: B;
		}
		B = 128;						// 1x Blauw aan 50%
		partout(p_led_data, 0, 4);
		p_led_data <: B;

		for(int k=0; k<16;k++){				// 16x O sturen voor Groen
			partout(p_led_data, 0, 4);
			p_led_data <: G;
		}

		for(int j=0; j<14;j++){				// 14x 0 sturen voor Rood
			partout(p_led_data, 0, 4);
			p_led_data <: R;
		}
		R = 128;						// 1x Rood aan 50%
		partout(p_led_data, 0, 4);
		p_led_data <: R;

		R = 0;							// laatste rode led 0
		partout(p_led_data, 0, 4);
		p_led_data <: R;

	}

	return 0;
}

int send_header(int command, out buffered port:8 p_led_data, out port p_led_load, clock led_clk){
	int sync = 232;		//(11101000)
	int counter = 0;
	int command_ind_pwm = 0;		//000000
	int command_load_caldac = 21;	//010101
	int command_global_pdm = 42;	//101010
	int command_load_config = 63;	//111111


	/*	SYNC	*/
	p_led_load <: 0;	//ready for SYNC
	p_led_data <: sync;
	p_led_load <: 1;	//stop SYNC

	/*	COMMAND */
	switch(command){
		case 0:
			partout(p_led_data, command_ind_pwm, 6);		// command individuele PWM
			break;
		case 1:
			partout(p_led_data, command_load_caldac, 6);	// command voor CALDAC's
			break;
		case 2:
			partout(p_led_data, command_global_pdm, 6);		// command voor global intensity PWM's
			break;
		case 3:
			partout(p_led_data, command_load_config, 6);	// command voor Load Config
			break;
		default:
			break;
	}

	/*	COUNTER */
	p_led_data <: counter;
	partout(p_led_data, counter, 2);
	return 0;
}
I really hope anyone can help me with this!!

Greets,

Ganux_


richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

Ganux wrote:Hello,

I am writing a serial interface for a MAX6974 LED-driver.
But, I am getting some problems for getting it running.
It should be clocked at 32 Mhz, so if I use:

configure_clock_rate(led_clk,128,4);

I'm getting the following error:
xrun: Program received signal ET_ECALL, Application exception.
0x0001031c in configure_clock_rate.coersed..f.7b0.7d.28ui.2cui.2cui.29 ()
The configure_clock_rate() function traps if the specified rate can't be achieved. The possible rates are in the form (ref / 2n) where ref is the reference clock and n is a number between 1 and 255.
Ganux wrote:Though, if I clock it at 10 Mhz it doesn't complain about the clock, but i get the following error:

xrun: Program received signal ET_ILLEGAL_RESOURCE, Resource not valid.
0x0001023e in send_header (command=<value optimized out>, p_led_data=66560, p_led_load=<value optimized out>, led_clk=<value optimized out>) at ../src/main.xc:132

I'll add the entire code below, but line 132 is:

partout(p_led_data, command_load_config, 6);
partout traps if the width specified is not a multiple of the port width. In this case the port is a 4 bit port (0x10400) but the width you've specified is 6.
Ganux
Active Member
Posts: 35
Joined: Tue Mar 08, 2011 12:58 pm

Post by Ganux »

Hi,

Thx for you response!
I don't really get the thing about the clock..
so what numbers should I use for a clock closest to 32 Mhz, but not higher then it..

I am using an XC-3 board, and the port is a 1-bit (checked it in the XN file:XS1_PORT_1F).
Then I serialized it to 8bit. But I can't send the 6 bit..

Ganux
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

Ganux wrote:Hi,

Thx for you response!
I don't really get the thing about the clock..
so what numbers should I use for a clock closest to 32 Mhz, but not higher then it..
You can use the function configure_clock_rate_at_most() to get the closest supported clock rate that doesn't exceed your target frequency. With a 100MHz reference block this will give you a 25MHz clock rate (100 / (2 * 2)).

If this rate isn't close enough you have two options. You could try and change the reference clock frequency so its is an even multiple of the rate you need. See the following docs:

XS1-G Clock Frequency Control
XS1-L Clock Frequency Control

Alternatively you could provide the clock rate as an external signal on one of the one bit ports of the XCore. You can then configure a clock block to use this port as the clock source. This requires you add something to your board to generate the correct frequency.
I am using an XC-3 board, and the port is a 1-bit (checked it in the XN file:XS1_PORT_1F).
Then I serialized it to 8bit. But I can't send the 6 bit..
My mistake. I think I can now see what the problem is. The second argument of partout should be the transfer width and the third should be the value to output. It appears you have these two swapped which would explain the trap.
Ganux
Active Member
Posts: 35
Joined: Tue Mar 08, 2011 12:58 pm

Post by Ganux »

Hi.

Seems to work this way.
Now i just have another little problem..
I checked my data using a scope,
and I saw that the least significant bits are transmitted first.
I need it the other way around: the MSB sent first...

Is there an easy way to change this, or do I have to write a fuction to invert my data?

Greetings,

Ganux
User avatar
Bianco
XCore Expert
Posts: 754
Joined: Thu Dec 10, 2009 6:56 pm

Post by Bianco »

Ganux wrote:Hi.

Seems to work this way.
Now i just have another little problem..
I checked my data using a scope,
and I saw that the least significant bits are transmitted first.
I need it the other way around: the MSB sent first...

Is there an easy way to change this, or do I have to write a fuction to invert my data?

Greetings,

Ganux
Check the bitrev() and byterev() functions.

I think you need to #include <xclib.h> to be able to use it.