Edge triggering?

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Sorry for the delay in replying, I've been on vacation.
JohnR wrote:

Code: Select all

		if(peek(start)==0) // only wait for start with input low
		{
			start when pinseq(1) :> void; // @ tStart;
            tmr :> tStart;
	        test <: 1;

			stop  when pinseq(1) :> void; // @ tStop;
	        tmr :> tStop;
	        test <: 0;
	        tmr :> t;
	        delay = delay + (tStop - tStart);

It is almost as if the system was not processing the second pulse until the first pulse had been processed??
In the code sequence above the code does simply execute sequentially. So the second pulse will not be processed until after the first one has been processed. This is a problem because it takes longer to execute the instructions between the inputs than the difference in time between the edges.

One way around this is to setup two threads both performing a timestamped input on one of the two ports that we want to time. When the second thread detects the edge, it can report the time down a channel to the first thread which can then compute the delay between the two.


JohnR
Experienced Member
Posts: 93
Joined: Fri Dec 11, 2009 1:39 pm

Post by JohnR »

Hi,

Thanks so much for responding - I hope you enjoyed your holiday. That's a neat idea to use two threads.
One way around this is to setup two threads both performing a timestamped input on one of the two ports that we want to time. When the second thread detects the edge, it can report the time down a channel to the first thread which can then compute the delay between the two.
But in the L1 with only one core, won't the code to read the two inputs be itself multiplexed between the cores? Or is the timestamp generated only by the hardware associated with the pad circuitry?

I have modified my .xn file to generate a higher clock frequency thus
<Node Id="0" Type="XS1-L1A-TQ128" Oscillator="20MHz" SystemFrequency="400MHz" ReferenceFrequency="200MHz">
I read in one of the XMOS pdfs that the reference clock associated with the ports is always 100Mhz. Am I right in assuming that if the .xn file calls for a higher reference frequency, this applies to the port clocks or are they permanently set to 100Mhz?

Thanks again in advance for your help

John
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

JohnR wrote:But in the L1 with only one core, won't the code to read the two inputs be itself multiplexed between the cores? Or is the timestamp generated only by the hardware associated with the pad circuitry?
The timestamping is performed by the hardware associated with the port circuitry. You need to have two threads to make sure that both ports are setup to look for the condition and store the timestamp. When the threads are setup like this the time it takes to read the timestamps is irrelevant.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

JohnR wrote:I have modified my .xn file to generate a higher clock frequency thus

Code: Select all

    <Node Id="0" Type="XS1-L1A-TQ128" Oscillator="20MHz" SystemFrequency="400MHz" ReferenceFrequency="200MHz">
I read in one of the XMOS pdfs that the reference clock associated with the ports is always 100Mhz. Am I right in assuming that if the .xn file calls for a higher reference frequency, this applies to the port clocks or are they permanently set to 100Mhz?
Wherever possible applications should use a 100MHz reference clock. Maintaining this fixed reference clock allows code to be shared all making this assumption. Precompiled code that is shared will not be able to work with ref frequencies other than 100MHz.

That said, some applications such as yours can benefit from changing the ref freq. A change in the ref freq changes the timer ref clock and clock block ref clock (used to drive the ports). You should be able to change the ref freq to 400MHz in your application using the xn file.
JohnR
Experienced Member
Posts: 93
Joined: Fri Dec 11, 2009 1:39 pm

Post by JohnR »

Hi,
The timestamping is performed by the hardware associated with the port circuitry. You need to have two threads to make sure that both ports are setup to look for the condition and store the timestamp. When the threads are setup like this the time it takes to read the timestamps is irrelevant.
Thanks for the replies. I must be extremely dense but I still cannot see why two threads are needed. If the two separate port hardware blocks read the time stamps, why can't the one thread access the two time values via the getts call.

Maybe what I should be doing is to peek for the second pulse, not the first, knowing at the later time, that the first pulse had in fact occurred and that the timestamp should be available in its port.

Thanks again for your help.

John.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Both ports need to be setup to detect the condition and record the timestamp. The code below will setup the condition for the 'start' port then pause until the condition occurs, then read the timestamp. Only then will it setup the condition on the 'stop' port. If the two edges are close together then the stop condition will have occurred by the time the condition is setup because it takes a finite amount of time to execute the instructions to do so.

Code: Select all

start when pinseq(1) :> void @ tStart;
stop  when pinseq(1) :> void @ tStop;
However if these lines of code are executed on separate threads they are both setup before either condition occurs. The conditions can be met very close in duration to eachother without having to consider how long it takes to execute the instructions.
JohnR
Experienced Member
Posts: 93
Joined: Fri Dec 11, 2009 1:39 pm

Post by JohnR »

Both ports need to be setup to detect the condition and record the timestamp. The code below will setup the condition for the 'start' port then pause until the condition occurs, then read the timestamp. Only then will it setup the condition on the 'stop' port. If the two edges are close together then the stop condition will have occurred by the time the condition is setup because it takes a finite amount of time to execute the instructions to do so.
Yes, I have just found this out the long way by implementing my version. I used more registers ot try and save on the number of load instructions and found that there was no improvement. Using the one thread does exactly as you say, one port has to be set up and read and only then can the second port be set up and read.

Would I be better off using interrupts rather then events. I got an example by Ross (http://www.xmoslinkers.org/forum/viewto ... ?f=6&t=370) working using timers as the interrupt source but have had no success in using a port as the interrupt.

In xs1b_kernel.h there are a number of interrupt related defines, eg XS1_SR_IEBLE(x) but I cannot find any documentation as to how they are used.

Any help on this would be appreciated.

John
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Hi John,

I'm not clear now where you're having the problem. Have you tried the 2 thread solution using timestamping and passing the times between the threads using a channel? This seems to be to be the simplest way to achieve what I think you are trying to achieve. Are you having problems with implementing that solution? Or are you having problems with an alternative solution?
JohnR
Experienced Member
Posts: 93
Joined: Fri Dec 11, 2009 1:39 pm

Post by JohnR »

Hi Woody,
I'm not clear now where you're having the problem. Have you tried the 2 thread solution using timestamping and passing the times between the threads using a channel? This seems to be to be the simplest way to achieve what I think you are trying to achieve. Are you having problems with implementing that solution? Or are you having problems with an alternative solution?
Thanks for your patience. I am now in the process of implementing a multithreaded approach as you suggested. I think I will use three threads - two as the time delay measurement units feeding a third thread that would integrate the results over a few milliseconds and display them on a LCD. My current single thread solution also integrates/displays the data but is limited to time delays greater than about 60 nsecs. I will report back when I have the new system running.
In xs1b_kernel.h there are a number of interrupt related defines, eg XS1_SR_IEBLE(x) but I cannot find any documentation as to how they are used.
I would still be interested in finding some more documentation on the use of interrupt in XMOS and their settings.

John
JohnR
Experienced Member
Posts: 93
Joined: Fri Dec 11, 2009 1:39 pm

Post by JohnR »

Hi Woody,

The three thread approach works beautifully! Two threads handle the start/stop pulses and the third thread accumulates the data over a few hundred milliseconds before displaying the results on a LCD display.

The minimum delay now that I can measure is around 15 ns and that is probably set by my delay generator which is an XC1 running at 100Mhz.

I still need clean up the code - I need to handle the case when there is no second pulse - as well as to tidy up the LCD display code. Then maybe I will post it in the projects section.

Thanks so much for your help. I am still interested in XMOS interrupt code and parameters for other projects so if you could point me in the right direction I would be most grateful.

John
Post Reply