NathanY3G / rp2040-pio-emulator

RP2040 emulator for the testing and debugging of PIO programs
Apache License 2.0
43 stars 7 forks source link

Defining input and sideset GPIO pins? #143

Closed redlegjed closed 8 months ago

redlegjed commented 8 months ago

Hi I'm trying to simulate a PIO program that has two GPIO inputs and sets 3 sideset GPIO pins. I'm a bit confused about how to setup these GPIOs.

How do I specify the direction of the two input GPIOs?

I see the emulate() function has an input for sideset pins, but I can't see how to extract the state of these pins at every iteration. The State class does not have any sideset attribute, only pin values.

Any help would be appreciated. Thanks

NathanY3G commented 8 months ago

Hi @redlegjed :wave:

Good question and I will try my best to help.

  1. I believe that the simplest approach is to use set pindirs at the start of your PIO program! This approach ensures that your PIO program behaves as you expect when you come to run it on actual silicon irrespective of whether you are using C/C++, MicroPython or CircuitPython. Below is an example PIO program which configures GPIO pins 0 and 1 as inputs and GPIO pins 2-4 as outputs.
.program example

.side_set 3
    set pindirs, 0b011100 side 0  ; Configure GPIO 0 and 1 as inputs and GPIO 2-4 as outputs
.wrap_target
    nop side 1
    nop side 2
    nop side 4
.wrap

You could then configure the emulator using:

emulate(assembled_program, side_set_count=3, side_set_base=2, wrap_target=1, stop_when=clock_cycles_reached(4))]
  1. Ultimately the side-set maps to actual GPIO pins, therefore, to obtain the output value you would read the pin_values field of each State instance. However, you might wish to mask and shift this value if you are only interested in these outputs.

If you would like me to expand on any of the above or provide a complete example then please just ask :slightly_smiling_face:

redlegjed commented 8 months ago

OK I think I see. The sideset values get "added" into State.pin_values as higher bits. So I can extract the sideset only pins using something like this:

pin_values = 0b11010                                            # example value
side_set_pins = pin_values >> side_set_base
bin(side_set_pins)                                              # Display bit fields 

'0b110'

Then, as you say, I can mask and shift to get the individual bit fields.

Thank you, very helpful.

NathanY3G commented 8 months ago

You've got it :+1:

According to the datasheet the side-side has the highest precedence. Therefore, the following instruction actually causes GPIO 0 to go high instead of low! (when side-set base is 0)

set pins, 0 side 1