hiya everyone.
Hoping someone has travelled this road before and has my solution.
Suppose a byte of data I’m punching out of a pico (gen1).
I’m rocking micro-python and I’ve written a simple for loop.
from machine import Pin
pins : Tuple = tuple([Pin(w) for w in range(6-14)])
my_byte : int = 0b01000101
for pin in pins:
pin.value(output & 0b1)
output = output >> 1
This works, but notice that, while I’m looping through, I’m actually changing the byte being output. For. example, if I were to change the value from 0b01000101 to 0b11111111 the output would look like:
iter1 : 0b0100 0101
iter2 : 0b0100 0111
iter3 : 0b0100 1111
iter4 : 0b0100 1111
iter5 : 0b0101 1111
etc
Noisy data = bad. 
What I’d like to do is buffer the output while I’m quietly priming the next byte 
I own a few of these 74ls125 Tri State buffer IC and they would do the job. I don’t really want to do this because I’d have to run 5v and sprinkle 3.3v voltage regulators around the circuit. Plus I’d be hand wiring 8 bits around everywhere which is a snore-fest. 
Is there a native micro python solution?
I’m praying for something like:
def modify_pins(value : int):
# TODO
machine.Pin.freeze_all(True) #buffer pins
modify_pins(0b01000101) #mod pins
machine.Pin.freeze_all(False) #pins toggle output now
Thanks in advance
pix 
2 Likes
This looks like a case for the PIO. In one machine cycle the OUT instruction will write sequential bits from the buffer into a contiguous range of pins. See 3.5.6.
RP2040 Datasheet: A microcontroller by Raspberry Pi.
4 Likes
Hi Jeff.
That was quite a rabbit hole.
I’ve done my reading and PIO looks like the right thing for my application. 
I had an attempt… 
and it compiles… 
but it doesn’t do anything. 
Can anyone see what I might be missing here?
Maybe I need a watch dog to keep the PIO processor alive?
#Part of a class that handles IO
def __init__(self, pins : List[int]):
#self.pins : Tuple[Pins] = tuple([Pin(p, Pin.OUT) for p in pins])
self.sm = rp2.StateMachine(0, self.update_DAC_in, freq=200000, set_base=Pin(6))
self.sm.active(1)
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW, fifo_join=rp2.PIO.JOIN_TX)
def update_DAC_in():
label("loop")
pull(block) # Read in the next byte
mov(x, osr) # update the x register
out(pins, x) # punch x register onto all pins instantaneously
jmp("loop")
def pio_do_something(data : int):
# assume data is a 10 bit int
self.sm.put(data);
2 Likes
There’s another rabbit hole right alongside this one - DMA. They join up somewhere well underground.
I don’t have much experience with this, but it seems to me that after initializing the buffer you should be loading the OSR, not the x register, and then
out(pins, 8) # put OSR to GPIO[PINCTRL_OUT_BASE] thru GPIO[PINCTRL_OUT_BASE + 8]
I have time tomorrow and I will see if I can get this working. I can’t find an example. I would have thought that a PC Parallel Port would be the ideal example of the power of the PIO.
2 Likes
Ah! I got it. 
It’s all in the decorator. 
pio_config = {
"out_init": [rp2.PIO.OUT_HIGH] * 10,
"out_shiftdir": rp2.PIO.SHIFT_RIGHT,
"autopull": True,
"pull_thresh": 10
}
def __init__(self, pins : List[int]):
self.pins : Tuple[Pins] = tuple([Pin(p, Pin.OUT) for p in pins])
self.sm = rp2.StateMachine(0, self.punch_out, freq=16384, out_base=Pin(6))
self.sm.active(1)
@rp2.asm_pio(**pio_config)
def punch_out():
out(pins, 10) # punch x register onto all pins instantaneously
def mod_statemachine(val):
self.sm.put(val)
Check it out.
The difference is day and night.
before
after
Thanks @Jeff105671 for pointing me towards PIO.
Happy new year all 
Pix 
3 Likes
Nice! Thanks for letting us know that you got it sorted. Can you provide some context for this so as to make it more useful as an example (or are you intending to publish the project?).
3 Likes
I’m just playing around with this DAC. 
it takes a 10bit number and throws it out as an analogue DC voltage.
I’ve got some interesting beginner friendly syntactic sugar going but I’m not entirely sure the Pico is fast enough to handle it yet… should be.
I might publish this as a project if I think it might be rewarding and fun for others.
It’s not a secret or anything. 
I don’t mean to be coy with context.
I try to keep my questions online as generalized as I dare so that it can be useful to more people.
1 Like