pico-examples icon indicating copy to clipboard operation
pico-examples copied to clipboard

Pins incorrectly mapped in PIO+SPI w/CS sample?

Open issa-tseng opened this issue 2 years ago • 0 comments

i'm wondering if maybe the pins were differently mapped a little before launch when the samples were written, and maybe something got changed around? the sample code at the bottom seems to confidently assume that the CS pin should follow the SCK pin, where in the pinout we seem to have them the other way around.

in my own code i've modified the sample to reverse these pins and i'm successfully writing out the values i mean to, so i'm inclined to think i'm not wrong.

i'm happy to supply a patch for the sample along the lines of what i wrote, but i just wanted to confirm i'm not totally confused, and ask if there is some particular preferred way to resolve this, especially wrt the particular way the pins/pindirs and their masks are composed together, a lot of 1u/2u/3u mixing there for reasons that aren't always clear to me.

also, in my own code, i added the line sm_config_set_sideset(&c, 2, false, false); because i'm not sure if the 2 pin sideset is somehow automatically applied due to the .side_set 2 annotation, but from what i can tell in the documentation it's not.

in my case i was just doing transmit, no receive, so i ripped some things out but here's my working code:

; CPHA=0: data is captured on the leading edge of each SCK pulse (including
; the first pulse), and transitions on the trailing edge

.program dac_spi
.side_set 2

.wrap_target
bitloop:
    out pins, 1        side 0x0 [1]
    jmp x-- bitloop    side 0x2 [1]

    out pins, 1        side 0x0
    mov x, y           side 0x0     ; Reload bit counter from Y
    jmp !osre bitloop  side 0x2 [1] ; Fall-through if TXF empties

    nop                side 0x0 [1] ; CSn back porch
public entry_point:                 ; Must set X,Y to n-2 before starting!
    pull ifempty       side 0x1 [1] ; Block with CSn high (minimum 2 cycles)
.wrap                               ; Note ifempty to avoid time-of-check race

% c-sdk {
#include "hardware/gpio.h"
static inline void dac_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol,
        uint pin_cs, uint pin_sck, uint pin_mosi) {
    assert(cpha == 0);
    assert((pin_sck - pin_cs) == 1);

    pio_sm_config c = dac_spi_program_get_default_config(prog_offs);
    sm_config_set_out_pins(&c, pin_mosi, 1);
    sm_config_set_out_shift(&c, false, true, n_bits);
    sm_config_set_sideset(&c, 2, false, false);
    sm_config_set_sideset_pins(&c, pin_cs);
    sm_config_set_clkdiv(&c, clkdiv);

    pio_sm_set_pins_with_mask(pio, sm, (1u << pin_cs), (3u << pin_cs) | (1u << pin_mosi));
    pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_cs) | (1u << pin_mosi), (3u << pin_cs) | (1u << pin_mosi));
    pio_gpio_init(pio, pin_mosi);
    pio_gpio_init(pio, pin_sck);
    pio_gpio_init(pio, pin_cs);
    gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);

    uint entry_point = prog_offs + dac_spi_offset_entry_point;
    pio_sm_init(pio, sm, entry_point, &c);
    pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
    pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
    pio_sm_set_enabled(pio, sm, true);
}
%}

issa-tseng avatar Oct 05 '22 00:10 issa-tseng