Electronic – How to interface a Raspberry PI GPIO to an open collector circuit to send / receive data

digital-communicationsgpioopen-collectorraspberry pi

I have a GPIO from a Raspberry PI connected to a Nintendo 64 system like so:

n64-gpio connection

From what I've gathered and observed, the data line on the N64 system is an open-collector output. The line is tied high when data is not being transmitted and pulled low to transmit.

The PI supports pull up/down configurations for the GPIO pins, but I don't see anything about an open-collector configuration.

With my current setup, I am able to read data from the N64 with the PI. However, I'm completely stuck on how to pull the data line low in a non-destructive manner using the GPIO pin, and also read from the same pin.

Is this something I can accomplish without additional hardware? Or do I need to add something like a transistor that I can switch with the PI to connect the data line to ground? If I do that, how will I read data?

As you can see, I know just enough to thoroughly confuse myself, but not enough to solve the problem.

Thanks for your help!

Best Answer

Assuming the Raspberry Pi is just a consumer of data its GPIO would be configured as an input, and whether or not you enable a pull-up resistor would depend on if that's built into the controller or not. I can't think of a reason why the Raspberry Pi would ever actively drive the data line. I would guess you need to enable the pull-up on the Raspberry Pi, because otherwise what's the point of having an open collector interface on the controller. You might need to use an external pull-up resistor if the internal pull-up is too weak; the tutorial I reference below suggests 2.2k Ohms, whereas the internal pull-ups on the Pi are likely > 30k.

I wonder whether you're actually going to be able to get sufficiently frequent / deterministic sampling of the signal on the Raspberry Pi by polling the GPIO though, in order to decode the (presumably) serial data coming from the controller. I'm not familiar with the N64 controller protocol, so it's hard to say.

I found this reference on the internet, which might be helpful to you:

To understand how to interface with an N64 controller, one must first understand the protocol that a genuine N64 uses to interface with the controller. All data is transmitted on a single, half-duplex wire (the signal wire plugged into pin 25 above). When this wire is idle, it is high (hence the pull-up resistor). If a falling edge is detected, it means that bits are being transmitted. Bits are transmitted in 4μs intervals. For a 0, the wire is low for 3μs and high for 1μs. For a 1, the wire is low for 1μs and high for 3μs. In order to read a bit, you must simply wait for a falling edge, and then read the wire 2μs after the falling edge. If the wire is high, the value is a 1, if it is low, the value is a 0. All transmissions end with a 1 bit that is not followed by a falling edge, called the signal bit.

Looks like a serial Pulse Width Modulation encoding. I'm skeptical that one can decode this with a Raspberry Pi easily. It would, on the other hand, be trivial to decode with a microcontroller, e.g. using pin change interrupts and/or hardware timers / input capture interrupts.

Update

Seeing as it is a bi-directional bus, you should indeed never set the GPIO to an output-HIGH. When you want the output to be HIGH, you just st it to an input with pull-up enabled (or no pull-up maybe). When you want to output LOW, set the GPIO to an output low. Again though, I doubt you can get the timing right with a Pi given the O/S in the way.