There is a lot of NES/SNES controler adapter projects availabe online, and I even have built myself one ( #Digi:[S]NES ).
The code is very straightforward:
- Pulse the latch line
- Read a bit
- Pulse the clock
- Repeat step 2 until you have read 12 bits
The same code can be used for NES and SNES, with one minor inconvenience that the buttons A and B are not on the same position in either controller, meaning that the buttons assigned to B and Y will be activated when a NES controller is plugged.
The code that I have has been proven on several NES controllers that I have but none of them were original controllers.
According to the schematics of the NES controllers that I have found online that shouldn't happen (quite right) because the NES controller is based on a 4021 shift register chip which have the SHIFT IN pin connected to GND (that was done by Nintendo to provide means to detect the presence of the controller).
But the Knockoffs that I have always present a HIGH after the last button read (RIGHT)
Ok, that is a good effect of using knockoffs but I want this firmware to be ready to use original controllers, and I wish also to have A and B mapped to the same (PC) buttons, no matter if a NES or an SNES controller is attached. For accomplishing that I need to differentiate the SNES controller from the NES controller (and from the Knockoffs).
The solution came from the analysis of the SNES controller schematic. It uses two 4021s in series and also have the serial input of the last shift register connected to the GND and the last bits (which are unused) are pulled up to VCC. Tha means that after the 12 button bits I should have 4 bits HIGH and after that any bit read will be LOW.
So considering the complete waveform, we can read 17 bits from the controller then analyze the last 5 bits received:
- if last 5 bits are 01111 then we have a SNES controller
- if last 5 bits are 00000 then we have a NES controller
- anything different we have a knockoff controller and it will be treated as a NES controller
The code is implemented slightly different because I use a 16 bit variable for the shifted bits and after all bits are shifted in I test the 17th bit, and test for 8 bits in LOW for the NES controller.
// read 16 bits from the controller
dataIn = 0;
for (i = 0; i < 16; i++) {
dataIn >>= 1;
if (digitalRead(dataPin)==0) dataIn |= (1<<15) ; // shift in one bit
Pulse_clock();
}
if (digitalRead(dataPin)) { // 17th bit should be a zero if an original controller is attached
controllerType = NONE;
} else {
if ( (dataIn & 0xf000) == 0x0000)
controllerType = SNES;
else if ( (dataIn & 0xff00) == 0xff00)
controllerType = NES;
else
controllerType = NONE;
}
Luckly the knockof SNES controller that I have worked as expected. As the SNES uses the last bits to identify some different types of controllers like the mouse, I thinkg that the knockoff manufacurers took care in following the behaviour or the original controller.
Here's a waveform for the SNES controller.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.