Arduino Lets You Play Atari 2600 and ZX Spectrum Using a NES Controller
by danjovic in Circuits > Arduino
20469 Views, 25 Favorites, 0 Comments
Arduino Lets You Play Atari 2600 and ZX Spectrum Using a NES Controller
![NESATARI.jpg](/proxy/?url=https://content.instructables.com/F8J/6Q9K/H1JU52H2/F8J6Q9KH1JU52H2.jpg&filename=NESATARI.jpg)
This instructable shows you how to use NES controller in Atari 2600 or ZX Spectrum (with Kempston Interface) with the aid of an Arduino.
Background Talk
![Controle Gemini - Auto fire.jpg](/proxy/?url=https://content.instructables.com/FL1/4MEK/H1JU527A/FL14MEKH1JU527A.jpg&filename=Controle Gemini - Auto fire.jpg)
I have recently acquired a couple of Atari 2600s and a bunch of joysticks. Both consoles were working but all of the 5 joysticks were damaged beyond repair. Indeed, it is very easy to find It is easy to find an old Atari 2600 console working but it's hard to find an original joystick in useful condition.
On the other hand, I had a spare NES 'generic' controller bought in a flea market that was working perfectly.
I thought about using a microcontroller to convert the serialized signals in NES joystick to parallel signals required by Atari 2600, but then I wondered that if instead of a custom microcontroller board I could use an Arduino. So other people without many skills in electronics could assemble their own adaptors with easy.
On the other hand, I had a spare NES 'generic' controller bought in a flea market that was working perfectly.
I thought about using a microcontroller to convert the serialized signals in NES joystick to parallel signals required by Atari 2600, but then I wondered that if instead of a custom microcontroller board I could use an Arduino. So other people without many skills in electronics could assemble their own adaptors with easy.
The 'big' Circuit
![Diagrama.jpg](/proxy/?url=https://content.instructables.com/F65/IIXA/H1LWPOA6/F65IIXAH1LWPOA6.jpg&filename=Diagrama.jpg)
![Arduino Severino.jpg](/proxy/?url=https://content.instructables.com/F5D/N9LH/H1KHA4LC/F5DN9LHH1KHA4LC.jpg&filename=Arduino Severino.jpg)
The circuit uses only the Arduino and a couple of connectors. The code is very small, so any Arduino board will do. But either way here follows the list.
Bill of Materials:
- 1 Arduino (any version will do)
- 2 DB-9 Male connectors. One for the NES 'generic' Controller and another to the test dongle
- 1 DB-9 Female connector, to plug into the Atari.
- 5 Leds for the test dongle
- 5 resistors 330 Ohms 1/4 Watt for the test dongle
- A buch of wires
Of course is it possible to reuse the old Atari Joystick cable instead of the DB9 female plus wires.
It is also possible to cut the NES controller cable and connect directly to the Arduino, but you should identify the wires in the cable.
Bill of Materials:
- 1 Arduino (any version will do)
- 2 DB-9 Male connectors. One for the NES 'generic' Controller and another to the test dongle
- 1 DB-9 Female connector, to plug into the Atari.
- 5 Leds for the test dongle
- 5 resistors 330 Ohms 1/4 Watt for the test dongle
- A buch of wires
Of course is it possible to reuse the old Atari Joystick cable instead of the DB9 female plus wires.
It is also possible to cut the NES controller cable and connect directly to the Arduino, but you should identify the wires in the cable.
Programming the Arduino and Doing Some Tests
![dongle.jpg](/proxy/?url=https://content.instructables.com/F13/1QS9/H1JUGZPZ/F131QS9H1JUGZPZ.jpg&filename=dongle.jpg)
![Testador de Joystick.jpg](/proxy/?url=https://content.instructables.com/F3F/M3N6/H1JUIPHP/F3FM3N6H1JUIPHP.jpg&filename=Testador de Joystick.jpg)
Compile and upload the code below to the Arduino. It was developed using IDE version 0.22. Before connecting the circuito to the ATARI use use a Dongle to verify the correct behavior of the circuit. The leds in the dongle shall be activated according with the buttons in the NES controller. Both action buttons are mapped to the same (and sole) Atari button. For the test with the dongle it is necessary to power the Arduino board.
//
// Play on ATARI 2600 with NES Controller By Danjovic, 2012
// Compiled on Arduino 0.22
//
/*
ATARI 2600 Joystick
Activates sequentially the following directions from an Atari 2600 Joystick
UP, DOWN, LEFT, RIGHT, TRIGGER
CONNECTIONS ON ATARI JOYSTICK
Function DB-9 Arduino AVR
UP 1 Pin 2 (PD2)
DOWN 2 Pin 3 (PD3)
LEFT 3 Pin 4 (PD4)
RIGHT 4 Pin 5 (PD5)
+5VCC 5 +5V +Vcc
TRIGGER 6 Pin 6 (PD6)
GND 9 GND GND
*/
/*
NES Controller
Contains a CMOS Shift Register (CD4021). Data change on raise border of Clock
button sequence as below.
latch ___---_______________________
Clock _______-__-__-__-__-__-__-__
Data xxxA B SL ST UP DW LF RG
The NES controller is powered by the Arduino.
Function DB-9 Arduino AVR
DATA 2 Pin 8 (PB0)
LATCH 3 Pin 9 (PB1)
CLOCK 4 Pin 10 (PB2)
+5VCC 7 Pin 11 (PB3)
GND 8 Pin 12 (PB4)
*/
// adapt to your hardware config
#define POWER_VIA_PORT_B3_B4 1 // use port pins B3 and B4 as power supply
#undef int
#include <stdio.h>
/* Atari Joystick port connections */
int Up_Pin = 2;
int Down_Pin = 3;
int Left_Pin = 4;
int Right_Pin = 5;
int Trigger_Pin = 6;
/* NES Controller connections */
int Data_Pin = 8;
int Latch_Pin = 9;
int Clock_Pin = 10;
int PWR5V_Pin = 11; // power
int PWRGND_Pin = 12;
void setup ()
{
/* Initialize Pins connected to Atari 2600. */
//Pins are set as inputs to emulate open collector outputs
pinMode(Up_Pin, INPUT);
pinMode(Down_Pin, INPUT);
pinMode(Left_Pin, INPUT);
pinMode(Right_Pin, INPUT);
pinMode(Trigger_Pin, INPUT);
// Initialize Latch outputs as zero, thus to activate a pin the direction
// shall be changed to Output
digitalWrite(Up_Pin, LOW);
digitalWrite(Down_Pin, LOW);
digitalWrite(Left_Pin, LOW);
digitalWrite(Right_Pin, LOW);
digitalWrite(Trigger_Pin, LOW);
/* Initialize Pins connected to NES controller. */
// Pin set as Inputs/Outputs as required
pinMode(Data_Pin, INPUT);
pinMode(Latch_Pin, OUTPUT);
pinMode(Clock_Pin, OUTPUT);
// Initialize NES controller signals
digitalWrite(Data_Pin, HIGH); // enable pullup resitor
digitalWrite(Latch_Pin, LOW);
digitalWrite(Clock_Pin, LOW);
// Check wether to power the NES joystick or not
#ifdef POWER_VIA_PORT_B3_B4 // power supply for NES controller via port B3 and B4
PORTB &=~ _BV(PORTB4); // Ground
PORTB |= _BV(PORTB3); // Vcc
DDRB |= _BV(PORTB3) | _BV(PORTB4); // make outputs
delay(100); // wait for things to stabilize
#endif
}
// Perform a clock cycle on NES controller Clock line
void do_clock (void){
digitalWrite(Clock_Pin, HIGH); // Raise clock pin
delayMicroseconds(10); // pauses for 10 microseconds
digitalWrite(Clock_Pin, LOW); // sets the pin off
delayMicroseconds(50); // pauses for another 10 microseconds
}
/*
Here is our main loop. It issues a latch pulse then starts to reat the state of the buttons.
The Atari joystick port pins are set according with the state of the bits read from shift
register inside the NES controller.
*/
void loop ()
{
digitalWrite(Latch_Pin, HIGH); // Raise the latch signal
delayMicroseconds(30); // hold it for 30 microseconds
digitalWrite(Latch_Pin, LOW); // Return latch signal to low level
delayMicroseconds(10); // hold it for more 10 microseconds
// Process Button A (remember: A zero means button pressed)
if (digitalRead(Data_Pin))
{
pinMode(Trigger_Pin, INPUT); // Unassert pin (zero means button pressed)
}
else
{
pinMode(Trigger_Pin, OUTPUT); // Assert pin
}
do_clock(); // A clock pulse is generated at the end of each bit
// Process Button B // Both NES button generates a trigger to Atari
if (digitalRead(Data_Pin))
{
pinMode(Trigger_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Trigger_Pin, OUTPUT); // Assert pin
}
do_clock();
// Skip Select Button
do_clock();
// Skip Start Button
do_clock();
// UP direction
if (digitalRead(Data_Pin))
{
pinMode(Up_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Up_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process DOWN direction
if (digitalRead(Data_Pin))
{
pinMode(Down_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Down_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process LEFT direction
if (digitalRead(Data_Pin))
{
pinMode(Left_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Left_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process RIGHT direction
if (digitalRead(Data_Pin))
{
pinMode(Right_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Right_Pin, OUTPUT); // Assert pin
}
do_clock(); // Kinda useless, but kept to mantain the pattern
// After read all buttons, wait 10 milisseconds before next reading
delay(10);
}
//
// Play on ATARI 2600 with NES Controller By Danjovic, 2012
// Compiled on Arduino 0.22
//
/*
ATARI 2600 Joystick
Activates sequentially the following directions from an Atari 2600 Joystick
UP, DOWN, LEFT, RIGHT, TRIGGER
CONNECTIONS ON ATARI JOYSTICK
Function DB-9 Arduino AVR
UP 1 Pin 2 (PD2)
DOWN 2 Pin 3 (PD3)
LEFT 3 Pin 4 (PD4)
RIGHT 4 Pin 5 (PD5)
+5VCC 5 +5V +Vcc
TRIGGER 6 Pin 6 (PD6)
GND 9 GND GND
*/
/*
NES Controller
Contains a CMOS Shift Register (CD4021). Data change on raise border of Clock
button sequence as below.
latch ___---_______________________
Clock _______-__-__-__-__-__-__-__
Data xxxA B SL ST UP DW LF RG
The NES controller is powered by the Arduino.
Function DB-9 Arduino AVR
DATA 2 Pin 8 (PB0)
LATCH 3 Pin 9 (PB1)
CLOCK 4 Pin 10 (PB2)
+5VCC 7 Pin 11 (PB3)
GND 8 Pin 12 (PB4)
*/
// adapt to your hardware config
#define POWER_VIA_PORT_B3_B4 1 // use port pins B3 and B4 as power supply
#undef int
#include <stdio.h>
/* Atari Joystick port connections */
int Up_Pin = 2;
int Down_Pin = 3;
int Left_Pin = 4;
int Right_Pin = 5;
int Trigger_Pin = 6;
/* NES Controller connections */
int Data_Pin = 8;
int Latch_Pin = 9;
int Clock_Pin = 10;
int PWR5V_Pin = 11; // power
int PWRGND_Pin = 12;
void setup ()
{
/* Initialize Pins connected to Atari 2600. */
//Pins are set as inputs to emulate open collector outputs
pinMode(Up_Pin, INPUT);
pinMode(Down_Pin, INPUT);
pinMode(Left_Pin, INPUT);
pinMode(Right_Pin, INPUT);
pinMode(Trigger_Pin, INPUT);
// Initialize Latch outputs as zero, thus to activate a pin the direction
// shall be changed to Output
digitalWrite(Up_Pin, LOW);
digitalWrite(Down_Pin, LOW);
digitalWrite(Left_Pin, LOW);
digitalWrite(Right_Pin, LOW);
digitalWrite(Trigger_Pin, LOW);
/* Initialize Pins connected to NES controller. */
// Pin set as Inputs/Outputs as required
pinMode(Data_Pin, INPUT);
pinMode(Latch_Pin, OUTPUT);
pinMode(Clock_Pin, OUTPUT);
// Initialize NES controller signals
digitalWrite(Data_Pin, HIGH); // enable pullup resitor
digitalWrite(Latch_Pin, LOW);
digitalWrite(Clock_Pin, LOW);
// Check wether to power the NES joystick or not
#ifdef POWER_VIA_PORT_B3_B4 // power supply for NES controller via port B3 and B4
PORTB &=~ _BV(PORTB4); // Ground
PORTB |= _BV(PORTB3); // Vcc
DDRB |= _BV(PORTB3) | _BV(PORTB4); // make outputs
delay(100); // wait for things to stabilize
#endif
}
// Perform a clock cycle on NES controller Clock line
void do_clock (void){
digitalWrite(Clock_Pin, HIGH); // Raise clock pin
delayMicroseconds(10); // pauses for 10 microseconds
digitalWrite(Clock_Pin, LOW); // sets the pin off
delayMicroseconds(50); // pauses for another 10 microseconds
}
/*
Here is our main loop. It issues a latch pulse then starts to reat the state of the buttons.
The Atari joystick port pins are set according with the state of the bits read from shift
register inside the NES controller.
*/
void loop ()
{
digitalWrite(Latch_Pin, HIGH); // Raise the latch signal
delayMicroseconds(30); // hold it for 30 microseconds
digitalWrite(Latch_Pin, LOW); // Return latch signal to low level
delayMicroseconds(10); // hold it for more 10 microseconds
// Process Button A (remember: A zero means button pressed)
if (digitalRead(Data_Pin))
{
pinMode(Trigger_Pin, INPUT); // Unassert pin (zero means button pressed)
}
else
{
pinMode(Trigger_Pin, OUTPUT); // Assert pin
}
do_clock(); // A clock pulse is generated at the end of each bit
// Process Button B // Both NES button generates a trigger to Atari
if (digitalRead(Data_Pin))
{
pinMode(Trigger_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Trigger_Pin, OUTPUT); // Assert pin
}
do_clock();
// Skip Select Button
do_clock();
// Skip Start Button
do_clock();
// UP direction
if (digitalRead(Data_Pin))
{
pinMode(Up_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Up_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process DOWN direction
if (digitalRead(Data_Pin))
{
pinMode(Down_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Down_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process LEFT direction
if (digitalRead(Data_Pin))
{
pinMode(Left_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Left_Pin, OUTPUT); // Assert pin
}
do_clock();
// Process RIGHT direction
if (digitalRead(Data_Pin))
{
pinMode(Right_Pin, INPUT); // Unassert pin
}
else
{
pinMode(Right_Pin, OUTPUT); // Assert pin
}
do_clock(); // Kinda useless, but kept to mantain the pattern
// After read all buttons, wait 10 milisseconds before next reading
delay(10);
}
Playing!
![NES2ATARI 005_.jpg](/proxy/?url=https://content.instructables.com/FQP/CUM9/H1LWPO4P/FQPCUM9H1LWPO4P.jpg&filename=NES2ATARI 005_.jpg)
![NES2ATARI 002_.jpg](/proxy/?url=https://content.instructables.com/FWO/QXO0/H1LWPO46/FWOQXO0H1LWPO46.jpg&filename=NES2ATARI 002_.jpg)
![NES2ATARI 003_.jpg](/proxy/?url=https://content.instructables.com/FH0/BC16/H1O5DFLD/FH0BC16H1O5DFLD.jpg&filename=NES2ATARI 003_.jpg)
Now that the circuit working was tested with the dongle you can connect it to the Atari. The Arduino board will then be powered by the joystick connector (therefore does not require external power).
Enjoy your console with the new controller.
Enjoy your console with the new controller.