pio_encode_mov(pio_pindirs, pio_x) gives wrong value
When calling:
pio_encode_mov(pio_pindirs, pio_x);
it returns 0xA081, while according to datasheet the correct value would be 0xA061
I think this is a left-over bug from RP2040 which doesn't support pindirs as mov destination.
I did a bit of digging, and it looks like you're right.
I compiled these tables of encoding bit-patterns from the PIO chapters of the RP2040 and RP2350 datasheets: (with bold highlighting where RP2350 differs from RP2040)
| Chip | Instruction | Src or Dest | 00 | 01 | 10 | 11 |
|---|---|---|---|---|---|---|
| RP2040 | WAIT |
Source | GPIO | PIN | IRQ | Reserved |
| RP2350 | WAIT |
Source | GPIO | PIN | IRQ | JMPPIN |
| Chip | Instruction | Src or Dest | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
|---|---|---|---|---|---|---|---|---|---|---|
| RP2040 | IN |
Source | PINS | X | Y | NULL | Reserved | Reserved | ISR | OSR |
| RP2040 | OUT |
Destination | PINS | X | Y | NULL | PINDIRS | PC | ISR | EXEC |
| RP2040 | MOV |
Destination | PINS | X | Y | Reserved | EXEC | PC | ISR | OSR |
| RP2040 | MOV |
Source | PINS | X | Y | NULL | Reserved | STATUS | ISR | OSR |
| RP2040 | SET |
Destination | PINS | X | Y | Reserved | PINDIRS | Reserved | Reserved | Reserved |
| RP2350 | IN |
Source | PINS | X | Y | NULL | Reserved | Reserved | ISR | OSR |
| RP2350 | OUT |
Destination | PINS | X | Y | NULL | PINDIRS | PC | ISR | EXEC |
| RP2350 | MOV |
Destination | PINS | X | Y | PINDIRS | EXEC | PC | ISR | OSR |
| RP2350 | MOV |
Source | PINS | X | Y | NULL | Reserved | STATUS | ISR | OSR |
| RP2350 | SET |
Destination | PINS | X | Y | Reserved | PINDIRS | Reserved | Reserved | Reserved |
pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) just does
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
pio_src_dest is defined as:
enum pio_src_dest {
pio_pins = 0u,
pio_x = 1u,
pio_y = 2u,
pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
pio_isr = 6u | _PIO_INVALID_SET_DEST,
pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
};
which explains why pio_encode_mov(pio_pindirs, pio_x); is encoding pio_pindirs as binary 100 instead of the binary 011 that the MOV instruction in RP2350's PIO expects.
So perhaps pio_src_dest needs to be tweaked to add:
#if PICO_PIO_VERSION > 0
pio_pindirs_mov = 3u _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
#endif
and then your example-code would need to do pio_encode_mov(pio_pindirs_mov, pio_x); instead of pio_encode_mov(pio_pindirs, pio_x);.