Page 1 of 1

Reading multiple ports in one select

Posted: Fri Jun 22, 2018 12:05 am
by RitchRock
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;
                .....
     }
}

Re: Reading multiple ports in one select

Posted: Fri Jun 22, 2018 12:10 am
by RitchRock
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.

Re: Reading multiple ports in one select

Posted: Fri Jun 22, 2018 2:55 am
by mon2
Can I call par{} outside of main?
Yes,

http://www.xcore.com/viewtopic.php?t=3407

Re: Reading multiple ports in one select

Posted: Fri Jun 22, 2018 3:56 am
by RitchRock
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?

Re: Reading multiple ports in one select

Posted: Fri Jun 22, 2018 9:22 am
by robertxmos
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

Re: Reading multiple ports in one select

Posted: Fri Jun 22, 2018 7:24 pm
by RitchRock
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.

Re: Reading multiple ports in one select

Posted: Mon Jul 02, 2018 1:06 pm
by robertxmos
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