About PIO(Programmed I/O) programming in Pico of raspberry pie, three articles have been written earlier:
There are only 9 assembly statements in PIO, but it can combine many powerful functions. In order to study the effect of out instruction, I used 6 LED lights and connected GP16~GP21 pins respectively.
In the Raspberry Pi Pico C/C++ SDK, the OUT instruction is described in detail, as shown in the following figure:
Delay / side set shares five binary bits, which is the same as other instructions.
Destination can be:
- PINS
- X
- Y
- NULL (black hole)
- PINDIRS (not introduced temporarily)
- PC(Programm Counter)
- ISR
- EXEC (not introduced for the time being)
The value range of Bit count is 1 to 32, accounting for 5 binary bits. 32 is internally encoded as 0b00000.
The OUT instruction means to remove the data of Bit count bits from the OSR register and write these bits into the Destination.
For example: out(pins, 6)
This means that six binary bits are taken from the OSR and written to pins. If out_ If the starting pin of base is GP16, the six binary bits will be written into GP16~GP21 respectively. 1 is the high potential and 0 is the low potential. Because the OSR is a 32-bit register, there are 26 bits of data left in the OSR. You can use the out instruction to continue fetching.
The direction of the shift is determined by out_shiftdir specifies that it is moved out from the left (high order) by default. If it is SHIFT_RIGHT means to move out from the right. I drew a schematic diagram:
Now you can write the program:
import machine import utime import rp2 @rp2.asm_pio(out_init=(rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW), out_shiftdir=rp2.PIO.SHIFT_RIGHT) def pio_out(): wrap_target() pull() out(pins, 6) wrap() sm = rp2.StateMachine(0, pio_out, out_base=machine.Pin(16)) sm.active(1) cmd = 0b011010 # Decimal: 23 while True: sm.put(cmd) cmd = int(input("Enter an integer:")) utime.sleep(0.01)
The state machine executes pull(), where there is no noblock parameter. The state machine has been waiting for the data in the FIFO queue. When sm.put (0b010110), the data in the FIFO is immediately taken out and put into the OSR. The data here is 32-bit binary. out(pins, 6) sets the potential of GP16~GP21, so as to set the potential of 6 pins at the same time.
Now you can enter an integer (no more than 63) in the program, and its binary can be represented by the light and dark of the LED light.
You can also use PIO to Seven segment nixie tube Although it is a little overqualified to set the potential of the pin, it is still helpful to study pioasm.
The code of 9 to 0 displayed in the countdown is as follows:
import machine import utime import rp2 @rp2.asm_pio(out_init=(rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW), out_shiftdir=rp2.PIO.SHIFT_RIGHT) def pio_out(): wrap_target() pull() out(pins, 7) wrap() sm = rp2.StateMachine(0, pio_out, out_base=machine.Pin(14)) sm.active(1) # Segment selection from 0 to 9 mask_digits = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f] for code in reversed(mask_digits): sm.put(~code) utime.sleep(1) sm.put(~0x0) #Total extinction
The starting pin here is GP14. There is no LED connected to the decimal point. My seven segment nixie tube has a common anode, so high potential 1 does not light up and low potential 0 does not light up.
Each time pull() is a little troublesome, you can set autopull to automatically fetch data from OSR when encountering the out() instruction. The parameter used together is pull_thresh, specifically take out several binary bits at a time. I guess thresh is the abbreviation of threshhold.
@rp2.asm_pio(out_init=(rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW), autopull=True, pull_thresh=7, out_shiftdir=rp2.PIO.SHIFT_RIGHT) def pio_out(): out(pins, 7)
To summarize:
1) sm.put() puts a 32-bit integer into FIFO
2) pull() when there is data in FIFO, take it out and put it in OSR
3) pull(noblock) is not blocked. If there is no data in FIFO, continue to execute
4) out(pins, 6) removes the 6-bit binary number from the OSR, and the shift direction is changed from out_shiftdir is defined, and the starting pin is defined by out_base definition, there are 26 bits of binary data left