Problem with default case in select {}

Technical questions regarding the XTC tools and programming with XMOS.
abk
Junior Member
Posts: 5
Joined: Mon Jul 04, 2011 9:43 am

Problem with default case in select {}

Post by abk »

Hi everyone!

I'm trying to count the bursts I read from a pin and the number of cycles between those bursts.
Without a default case I can count the pulses of a burst but if I add a default case that increases a variable my program doesn't recognize the pulses anymore. I don't understand why :cry: The channel end still works though..

The code below is the thread containing the select statement.

Code: Select all

void receiver(chanend c){
	unsigned dataIn = 0;
	int channelData = 0;
	unsigned pulseCounter = 0;
	unsigned counter = 0;

	while(1){
		select {
			/* Pin for bursts */
			case inP when pinsneq(dataIn) :> dataIn:
				pulseCounter++;
				break;
			/* Channel end for frequent reset */
			case c :> channelData:
				if (channelData == 0){
					printf("ctr: %u; plsCtr: %u\n",counter,pulseCounter);
					counter = 0;
					pulseCounter = 0;
				}
				break;
			default:
				counter++;
				break;
		}
		//counter++;
	}
}
The output generated

with default:
ctr: 7142857; plsCtr: 0
ctr: 7088387; plsCtr: 0
ctr: 7109786; plsCtr: 0

without default:
ctr: 0; plsCtr: 744
ctr: 0; plsCtr: 672
ctr: 0; plsCtr: 672

counter outside switch:
ctr: 744; plsCtr: 744
ctr: 669; plsCtr: 668
ctr: 673; plsCtr: 672

What is the reason for that behavior?
You do not have the required permissions to view the files attached to this post.


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

Post by richard »

Is dataIn declared as an unbuffered port (i.e. port dataIn)?

A default is case implemented by enabling events and then disabling events immediately afterwards. If any cases are ready it will cause an event when events are enabled, otherwise execution will fall-through into the code for the default case.

An unbuffered port will only event when it samples data from the pins meets the condition. By default the pins are only sampled on the rising edges the port clock. If no rising edge occours between events being enabled for the select and then disabled again then the case with the port will not fire.
abk
Junior Member
Posts: 5
Joined: Mon Jul 04, 2011 9:43 am

Post by abk »

Richard, thank you for the quick and helpful reply!!
Buffering the port fixed the problem. I think I'll read the chapter about port buffering again :)
rhind
Junior Member
Posts: 6
Joined: Fri Jun 17, 2011 9:31 am

Post by rhind »

richard wrote:A default is case implemented by enabling events and then disabling events immediately afterwards. If any cases are ready it will cause an event when events are enabled, otherwise execution will fall-through into the code for the default case.

An unbuffered port will only event when it samples data from the pins meets the condition. By default the pins are only sampled on the rising edges the port clock. If no rising edge occours between events being enabled for the select and then disabled again then the case with the port will not fire.
If you don't have a 'default' in a select, and you are waiting on 2 unbuffered ports, and one of them fires an interrupt and while you'll handling that (in the case statement), the other port fires, does this mean you'll miss the second port firing because you're handling the first one? Or is this only an issue if you have a 'default' case?

If it is an issue, then this sounds like ports should always be declared as buffered so you don't miss any edges, doesn't it?

Thanks

Russell
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

You'll get the event from that second port as soon as you enable events again, i.e.,
as soon as the first event is handled and you enter the select statement again.

If it fires twice before you get there, you get only one event; if both ports have an
event ready, you "randomly" get one of the two.
rhind
Junior Member
Posts: 6
Joined: Fri Jun 17, 2011 9:31 am

Post by rhind »

segher wrote:You'll get the event from that second port as soon as you enable events again, i.e.,
as soon as the first event is handled and you enter the select statement again.

If it fires twice before you get there, you get only one event; if both ports have an
event ready, you "randomly" get one of the two.
Thanks. Why does having a 'default' case cause you to miss if the pin is unbuffered then? From the sounds of this, once you've re-enabled the events after re-enterting the select you'd see the event on pin.