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

General • Best way to set pindirs for 16 GPIOs for a multiplexed 16-bit data bus?

$
0
0
Hi guys,

I am writing this forum post to get some perspective, as I am waiting for my PCB that will allow me to attach an Intellivision to a logic analyzer.

I'm in the middle of writing PIO state machine code to both receive and send data on a General Instrument CP-1610 data bus. This is a 16-bit CPU from the 1975 time frame that was used in the Mattel Intellivision.

I am running the RP2040 clock at 250MHz.

It implements a multiplexed 16 bit data bus, pushing data and addresses over the same bus, differentiated by a 3-bit bus state (intended to be implemented using an 3 to 8 decoder by the system designer).

There is exactly one bus state, DTB, that allows for something NOT the CPU to place a 16-bit value onto the bus.

I assume that for every other state, the bus pins are set to input (everything is set to input at cold start), and I have one PIO program that samples the bus, thusly:

Code:

.wrap_target    wait 1 pin 16        ; Wait for BDIR == 1 (CPU driving bus)    nop [31]             ; 279.3ns valid delay    nop [31]             ; at 250MHz.    nop [5]    in pins, PINS_TO_SAMPLE          ; Read pins    in null, 13    push block    wait 0 pin 16        ; Wait for BDIR == 0 (CPU released bus).wrap
It's set up with the following:

Code:

    uint offset_rx = pio_add_program(pio, &cp1600_bus_rx_program);    //    // --- RX SM (read from CP-1600) ---    pio_sm_config c_rx = cp1600_bus_rx_program_get_default_config(offset_rx);    sm_config_set_in_pins(&c_rx, PIN_DATA_BASE);    sm_config_set_clkdiv(&c_rx, CLOCK_DIVIDER);  // Full speed    sm_config_set_in_shift(&c_rx, true, false, PINS_TO_SAMPLE);    pio_sm_init(pio, sm_rx, offset_rx, &c_rx);    pio_sm_set_enabled(pio, sm_rx, true);
And I have one TX PIO program

Code:

// Transmits 16 bits onto DB0–15 during DTB// Expects two entries in queue, first pindirs, then pins..program cp1600_bus_tx.wrap_target    wait 0 pin 16        ; BDIR == 0    wait 1 pin 17        ; BC2 == 1    wait 1 pin 18        ; BC1 == 1 => DTB    out pindirs, 16      ; Set pindirs    out pins, 16         ; Output data onto DB0–15    nop [31]    nop [31]    nop [5]    mov osr, null        ; clear osr    out pindirs, 16      ; and set all pins to input.wrap
and it is set up thusly:

Code:

    uint offset_tx = pio_add_program(pio, &cp1600_bus_tx_program);    // --- TX SM (write to CP-1600) ---    pio_sm_config c_tx = cp1600_bus_tx_program_get_default_config(offset_tx);    sm_config_set_out_pins(&c_tx, PIN_DATA_BASE, 16);    sm_config_set_clkdiv(&c_tx, CLOCK_DIVIDER);    sm_config_set_out_shift(&c_tx, false, true, 16);  // Auto-pull 16 bits    pio_sm_init(pio, sm_tx, offset_tx, &c_tx);    pio_sm_set_enabled(pio, sm_tx, true);}
when called, the TX queue writes two entries to the queue, first being pindirs for gpio 0-15, the second being the data to assert.

Code:

// Writing to TX FIFO (to respond to DTB phase)bool __time_critical_func(write_cp1600)(PIO pio, uint sm_tx, uint16_t data) {    if (!pio_sm_is_tx_fifo_full(pio, sm_tx))      {pio_sm_put(pio, sm_tx, 0xFFFF); // pindirs to output.pio_sm_put(pio, sm_tx, data);return true;      }    return false;}
---

Does this approach make sense of using the OSR to hold the pindirs to get around the limit of being able to only do 5 bits in a set instruction (or 8 with an additional side?)

If not, what should I try instead?

-Thom

Statistics: Posted by tschak909 — Thu Aug 07, 2025 11:40 pm



Viewing all articles
Browse latest Browse all 9189

Trending Articles