Reading multiple ports in one select Topic is solved

Sub forums for various specialist XMOS applications. e.g. USB audio, motor control and robotics.
RitchRock
Experienced Member
Posts: 95
Joined: Tue Jan 17, 2017 9:25 pm

Reading multiple ports in one select

Postby RitchRock » Fri Jun 22, 2018 12:05 am

I have a user-interface task that needs to read from two 4-bit ports. I'm hoping to keep this to one task if at all possible. I have an encoder on one port and buttons on the other. I've been using a method similar to this, as it is best debounce method I've found. I have no problem if I'm just using one port with either the encoder or buttons port. The problem is if I duplicate this for two ports. The project builds fine, but hangs when I run it.

Is it possible to have multiple cases in a single select{} that query two different ports with pinsneq like:

Code: Select all


            ....
while(1){
     select{
           case p_buttons_A when pinsneq(button_val_A) :> button_val_A:
                t1 :> press_time_A;
                debounce_A = 1;
                break;
                ....

           case p_buttons_B when pinsneq(button_val_B) :> button_val_B:
                t2 :> press_time_B;
                debounce_B = 1;
                break;
                .....
     }
}
View Solution
RitchRock
Experienced Member
Posts: 95
Joined: Tue Jan 17, 2017 9:25 pm

Postby RitchRock » Fri Jun 22, 2018 12:10 am

Can I call par{} outside of main? If so, perhaps I could have two small combinable tasks, one for each port that does the above as the userinterface task.
User avatar
mon2
XCore Legend
Posts: 1133
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Postby mon2 » Fri Jun 22, 2018 2:55 am

Can I call par{} outside of main?


Yes,

viewtopic.php?t=3407
RitchRock
Experienced Member
Posts: 95
Joined: Tue Jan 17, 2017 9:25 pm

Postby RitchRock » Fri Jun 22, 2018 3:56 am

I tried the par and have the same result. Probably because combining these two tasks is really the same as having them one after another in a while loop. My original question still stands - is it possible to query multiple ports like this in a single select?
robertxmos
XCore Addict
Posts: 164
Joined: Fri Oct 23, 2015 10:23 am

Postby robertxmos » Fri Jun 22, 2018 9:22 am

yes.
The events are triggered in each port's hardware.
The port's hardware stores the address of the 'case' statement code that needs to be run.
If both ports trigger at the same time, the core will run one case statement followed by the other - it is not using interrupts but rather picking up queued events that need to be run.

When using combined, the compiler munges your blocks of code back into a single block (as in your example) - its a handy way to organise your code.

Could you define what you mean by 'hang'?

robert
RitchRock
Experienced Member
Posts: 95
Joined: Tue Jan 17, 2017 9:25 pm

Postby RitchRock » Fri Jun 22, 2018 7:24 pm

Thanks - I got it working. It's good to know the port's hardware stores the address of the case statement code.

My problem was not using the two port query's, but rather using two statements like this to count samples:

Code: Select all

...
//If debounce has started, take several samples. Register button changed if n consequitive the same
case (debounce > 0) => t when timerafter(press_time + (DEBOUNCE_PERIOD / DEBOUNCE_SAMPLES)) :> void:
...


I just have one of these cases now and it works as expected.
robertxmos
XCore Addict
Posts: 164
Joined: Fri Oct 23, 2015 10:23 am

Postby robertxmos » Mon Jul 02, 2018 1:06 pm

RitchRock wrote:Thanks - I got it working. It's good to know the port's hardware stores the address of the case statement code.


... ususaly, yes.
Timers (non explicitly hardware) are different.
The compiler will emit code that compares the current time with each requested signed-absolute time (assuming current time as zero) and pick the lowest (e.g. already in the past) and only initialise that one (using a hardware timer set aside for that logical core).
Hence, by default, each core is allocated one hardware timer, and XC timers use this in their physical usage - see the assembler output.
This makes sense, as only one event can occur at a time and hence there is no point in setting up a load of hardware timers. It also means that timers will event in order!
The remaining hardware timers are available for assembler or `[[hardware]]' usage and will give you a faster set up and less compiled code... but not faster response - measure assembler output for details.

robert

Who is online

Users browsing this forum: sgtpepper335 and 10 guests