Hacker News new | past | comments | ask | show | jobs | submit login

Looking at the described protocol it seems the SNES controller uses a simple 16-bit parallel-in-serial-out shift register - and a quick Google confirmed that.

This means the timing is almost certainly quite loose, and there's a pretty decent chance you might even be able to poll it as the 1kHz "needed" for "serious" gaming. And it'd be pretty trivial to offload the readout to the MCU's SPI peripheral.




It's extremely loose! Using a custom PCB to connect the controller over RJ45 to a custom Pi hat I wrote some code to simply display the button presses on screen, to test the functionality of the controller (we are modifying hundreds). I had to play around a lot with the timings to match up the response of the program with the speed of my finger pushing a button, else the program would return "you pushed B" a dozen times on a single push.

I do wonder how much original SNES devs had to consider similar scenarios.


The physical switches may actually bounce, so you might need some debounce logic, if it wasn't the shift register glitching out. It's pretty common for buttons to need this, often seen in keyboard firmware as well for similar reasons, the physical mechanism actually will oscillate a bit between states.


The way the NES and SNES work is that once per frame you read from the memory address mapped to the shift register to get all the bits out, one at a time. For certain inputs you only care if it's pressed now. Others you compare to previous state to see if it changed.

Bounce could, theoretically, cause an input to be read as a non-input if it just bounced at exactly the wrong time, but it won't cause multiple inputs, as it's only polled every 1/60th of a second.


Yes, it sounds like SNES implements debounce by just scanning slowly, but if you want to feed USB reports at maximum (or above maximum) specification, you will want to check the state more frequently, and you'll need an alternate mitigation for switch bounce.


Were you checking to see if the button state changed between reads? Or were you reading a 1 as "down" regardless of whether the previous read was "up"?


I converted a DOS-era joystick like this, and the shift registers inside were stable at higher speeds, I don't remember needing to care about the timing much. I may have just run the clock in a for-loop during the polling loop.


Thanks for teaching me about SPI, I might have a play around and see if I can get that working.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: