1
\$\begingroup\$

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!

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

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 set it as 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.

\$\endgroup\$
2
  • \$\begingroup\$ Every time the N64 controller data needs to be read, the console sends out a 9-bit polling request \$\endgroup\$
    – Passerby
    Commented Jul 14, 2017 at 0:50
  • \$\begingroup\$ Thanks for the very thorough response! I am able to read data from the N64 using a Linux kernel module I wrote without an issue (aside from hanging the system during the read). I used your tip about setting the GPIO to input to "write" the high value, and setting the GPIO output to zero to write low, and that works at very low transmission rates. I measured the line with a multimeter to confirm. However, when I try to write at the rate I need to, the Raspberry PI hangs and I need to power cycle the device... so it looks like a PIC or two is in my future. This will help me going forward though. \$\endgroup\$ Commented Jul 14, 2017 at 1:42
1
\$\begingroup\$

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.

Only switch the GPIO between input/high-z, and output low. Never switch it to output high. That's how a open collector works.

\$\endgroup\$
3
  • \$\begingroup\$ You're suggesting this is a bi-directional interface? I can't imagine the "computer" driving the data line to signal information to the controller. \$\endgroup\$
    – vicatcu
    Commented Jul 14, 2017 at 0:34
  • \$\begingroup\$ @vicatcu yes. Controllers in The last three decades are not simple devices. hackaday.com/2012/10/16/… \$\endgroup\$
    – Passerby
    Commented Jul 14, 2017 at 0:46
  • \$\begingroup\$ Got it "the console sends out a 9-bit polling request. The controller responds in turn with a 32-bit sequence informing the console of the status of all the buttons and joysticks" at any rate, I think most of what I wrote in my answer is sound. \$\endgroup\$
    – vicatcu
    Commented Jul 14, 2017 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.