Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5196

General • Re: Help with PIO fundamentals to drive matrix-based displays.

$
0
0
I've been printing lots of debugging information while trying to figure this out and can't make heads or tails of it. I'm only a few weeks into Pico programming so I don't have a deep grasp of the internals yet.

I had a very long reply written out with lots of debugging that showed the DMA states being very messed up and not matching what I was seeing output by the hardware. Then it finally hit me!

@arg001 you were right all along. It's the abstraction that bit me. I was assuming that "dma = rp2.DMA()" would give me DMA channel 0. It does. Sometimes. Other times it's 2, or some other channel. Seems to be random and changes a LOT based on if I power down or not.

This certainly explains why I've been having such troubles!

I changed CH0_READ_ADDR to CH0_READ_ADDR+(dma1.channel*0x40) and suddenly it all works perfectly.

Thanks a lot for your help everyone. For anyone else reading this, here is the working code to stream data to a PIO in a loop without needing to fill the buffers manually.

Code:

from machine import Pin, mem32from rp2 import PIO, StateMachine, asm_pio, DMAimport timefrom uctypes import addressof, bytes_atfrom array import array# This will set up two DMA channels that will send a repeating stream of data# to a PIO's FIFO.# Thanks to @arg001 and @fdufnews for helping make sense of all of this!DATA_PIN = const(7)   # Pins going to the hardware device CLOCK_PIN = const(0)  # Just using an 8-bit shift register for this test.@asm_pio(out_shiftdir=rp2.PIO.SHIFT_RIGHT, out_init=(PIO.OUT_LOW,) * 6, sideset_init=(PIO.OUT_LOW))def strobe_hp_display():    # Get 8 bits to send to display, send them out the CLOCK pin    pull()   # Get a 32 bit word from the FIFO into the OSR register    set(x,7) # Set the loop index to 7 for a toal of 8 loops    label('loopx')    out(pins, 1) [0]   # Shift a bit off the OSR and set the pin to that value    nop().side(1) [0]  # Toggle the clock HI then LOW    nop().side(0) [0]    jmp(x_dec, 'loopx')    pull()      # Get the delay value from FIFO    mov(x,osr)      label('waitx')    jmp(x_dec, 'waitx') [7] # Loop until 0        wrapDMA_BASE = 0x50000000PIO0_BASE = 0x50200000 TXF0 = 0x010DREQ_PIO0_TX0 = 0CHAN_ABORT = DMA_BASE + 0x444CH0_AL3_TRANS_COUNT = DMA_BASE + 0x038 CH0_AL3_READ_ADDR_TRIG = DMA_BASE + 0x03cCH0_AL3_READ_ADDR = DMA_BASE + 0x028CH0_TRANS_COUNT = DMA_BASE + 0x008CH0_READ_ADDR = DMA_BASE + 0x000# Force stop any previously running DMA channels.# Not needed if cold bootingmem32[CHAN_ABORT] = 2047# Create our data to feed to the PIO.# Just a simple series from 0 to 255 with a delay big enough to make the sequence visible.a = array('i',(0 for i in range(0,256*2)))for i in range(len(a)/2):    a[i*2] = i & 0xff     # Bits to shift out through DATA_PIN    a[i*2+1] = 1000       # How many loops to wait before sending the next groupsm_hp = StateMachine(0, strobe_hp_display, freq=800000, out_base=Pin(DATA_PIN), sideset_base=Pin(CLOCK_PIN))sm_hp.active(1)dma1 = rp2.DMA()    ch1 = dma1.channel # This does NOT always start at 0 so you must use this value.dma1.active(False)dma2 = rp2.DMA()dma2.active(False) # Just a precaution to init any values that might not be clearedch2 = dma2.channel# This is where DMA2 will copy data from.# When restarting DMA1 this number will get written to it's READ_ADDRc = array('i',(addressof(a),0,0,0))print("Init", ch1,ch2,c[0])# DREQ_PIO0_TX0 makes sure we stop transfers when PIO 0's TX0 FIFO is full.# We read from the arra "a" and write to PIO 0's TX0 FIFO at PIO0_BASE+TXF0# When it finishes the transfer it triggers DMA2 with chain_to=ch2ctl = dma1.pack_ctrl(size=2, inc_read=True, inc_write=False, treq_sel=DREQ_PIO0_TX0, chain_to=ch2)dma1.config(read=a, write=PIO0_BASE+TXF0, count=len(a), ctrl=ctl, trigger=False)# DMA2 waits to be triggered, then reads the memory in c[0] and sends it to# the READ_ADDR_TRIG of DMA1. Note the (ch*0x40) to make sure it goes to the right channel.# We do not chain.  @arg001 says do one or the other.ct2 = dma2.pack_ctrl(size=2, inc_read=False, inc_write=False)dma2.config(read=c, write=CH0_AL3_READ_ADDR_TRIG+(ch1*0x40), count=1, ctrl=ct2, trigger=False)# Start sending bits to the shift register.dma1.active(True)while True: # Just print some debugging to show buffer size and location.    print(dma1.count, mem32[CH0_READ_ADDR+(ch1*0x40)], dma1.active())    time.sleep(0.5)    # If you want you can now just change the values in a[] and they will get    # shifted out automaticly. No need to restart the DMA or PIO.    #for i in range(255):    #    a[i*2] = (a[i*2] + 13) & 0xff

Statistics: Posted by iansmith6 — Fri Apr 12, 2024 9:06 pm



Viewing all articles
Browse latest Browse all 5196

Trending Articles