Wireless Joypad

I’ve been working these days on a 2.4Ghz wireless controller for our beloved Sega Genesis / MegaDrive. I’d like to share with everyone this guide on how to actually make one.

16

It’s not an easy mod, I’m assuming you have soldering and modding experience. Here’s a list of items I used for the mod:

 

Let the fun begin:

Controller side schematic (transmitter)

1

We have to fit all the components inside the original controller. Here’s what I did

1. Remove the SMD LEDs on the charging board and replace them with the Red and Green 3mm leds.

2. Drill holes for the leds, USB port, switch and UART connector (optional)  in the plastic shell. Place them like this:

1

3. Place the nRF24L01+ tranceiver at the bottom left and hot glue everything in place:

3

5. Solder wires to the tranceiver and the yellow LED:

4

6. On the original PCB you’ll have to cut all traces to the main chip. After that you’ll have to solder a wire to each trace that’s going to a button. Like this:

67. Hotglue the Arduino Pro Mini on top of the original chip and solder all wires according the schematic. You’ll have to join the Pro Mini GND to  ground (GND) point somewhere on the original PCB, as it’s common for all buttons.

7

8. Finally you’ll have to connect all wires according the schematic. Leave them as short as possible, closing the controller is real pain. Add the small battery wherever it fits.

8

9. Test the UART connector and load the Arduino sketch below to the Pro Mini. You can try to close the controller case. Make sure all wires are free and not pushed between the plastic rings that support the main board.

15

14

Arduino code for the controller:

/* 
 1 - GND
 2 - VCC 3.3V !!! NOT 5V
 3 - CE to Arduino pin 7
 4 - CSN to Arduino pin 8
 5 - SCK to Arduino pin 13
 6 - MOSI to Arduino pin 11
 7 - MISO to Arduino pin 12
 8 - UNUSED
 */

#include <SPI.h>
#include "RF24.h"

#define CE_PIN 7 // The pins to be used for CE and SN
#define CSN_PIN 8

// Define buttons
#define A 2
#define B 3
#define C 4
#define X 5
#define Y 6
#define Z 9
#define B_UP 10
#define B_DOWN A0
#define B_LEFT A1
#define B_RIGHT A2
#define START A3
#define MODE A4

/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus (usually) pins 7 & 8 (Can be changed) */
RF24 radio(CE_PIN, CSN_PIN);

byte addresses[][6] = {"1Node"};

/* 
 0-A
 1-B 
 2-C
 3-X
 4-Y
 5-Z
 6-UP
 7-DOWN
 8-LEFT
 9-RIGHT
 10-START
 11-MODE
 */

word Joypad, Joypad_old;

bool hasHardware = 1; // 1 - real hardware, 0 - test

void setup()
{
 //Serial.begin(115200);
 
 pinMode(A, INPUT_PULLUP);
 pinMode(B, INPUT_PULLUP);
 pinMode(C, INPUT_PULLUP);
 pinMode(X, INPUT_PULLUP);
 pinMode(Y, INPUT_PULLUP);
 pinMode(Z, INPUT_PULLUP);
 pinMode(B_UP, INPUT_PULLUP);
 pinMode(B_DOWN, INPUT_PULLUP); 
 pinMode(B_LEFT, INPUT_PULLUP);
 pinMode(B_RIGHT, INPUT_PULLUP);
 pinMode(START, INPUT_PULLUP);
 pinMode(MODE, INPUT_PULLUP);

 radio.begin(); // Initialize the nRF24L01 Radio
 radio.setChannel(108); // Above most WiFi frequencies
 radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range
 
 radio.setPALevel(RF24_PA_MAX);

 // Open a writing pipe
 radio.openWritingPipe(addresses[0]);

 delay(1000);
}

void loop() 
{

 if (hasHardware)
 {
 Joypad = (digitalRead(MODE) << 11) | (digitalRead(START) << 10) | (digitalRead(B_RIGHT) << 9) | (digitalRead(B_LEFT) << 8) |
 (digitalRead(B_DOWN) << 7) | (digitalRead(B_UP) << 6) | (digitalRead(Z) << 5) | (digitalRead(Y) << 4) |
 (digitalRead(X) << 3) | (digitalRead(C) << 2) | (digitalRead(B) << 1) | digitalRead(A);
 }
 else
 {
 Joypad = random(0,100);
 //Joypad = (1 << 4) | (0 << 3) | (1 << 2) | (1 << 1) | 1;
 //delay(200);
 }

 if (Joypad != Joypad_old){
 
 //Serial.println(F("-- ")); 
 //Serial.println(F(" MSRLDUZYXCBA"));
 
 radio.write( &Joypad, sizeof(word)); 
 
 // Serial.println(Joypad,BIN);
 
 }

 Joypad_old = Joypad; 
 
}

 

Now let’s move to the receiver side.

Receiver schematic

receiver

 

1. Take the PCB from the scrap controller and look how the traces are running. We will use the active part (the chip) to communicate with the console and control it with our Arduino Nano. Cut it from all sides so the board stays small, but you still have access to all traces for all buttons. Solder wires to all button traces and to GND, and also to +5V (you’ll have to find it on the PCB, it’s coming from pin 5 on the connector). This is how we’re going to power the Arduino Nano.

segajoypadpinout

2. Find a suitable plastic box for the receiver.

  • Replace the power LED of the Arduino Nano with the Red 3mm LED.
  • Drill holes for the USB port of the Nano, position it in the box and secure it with hot glue.
  • Drill holes for the Red and Green LEDs. Connect the Green LED according the schematic, just add 200ohm resistor to the anode.
  • Position the nRF24L01+ inside the box, hotglue it and solder wires from it to the Nano according the schematic above.
  • Connect the wires from the button board to the Arduino Nano.
  • Cut the original DB9 cable and solder it as it was originally in the controller.

Final device should look like this:

11

12

13

3. Now load the following code in the Arduino Nano over the USB:

/* 
 1 - GND
 2 - VCC 3.3V !!! NOT 5V
 3 - CE to Arduino pin 7
 4 - CSN to Arduino pin 8
 5 - SCK to Arduino pin 13
 6 - MOSI to Arduino pin 11
 7 - MISO to Arduino pin 12
 8 - UNUSED
*/
#include <SPI.h> // Comes with Arduino IDE
#include "RF24.h" // Download and Install
#include "digitalWriteFast.h" //Download and Install

#define CE_PIN 7 // The pins to be used for CE and SN
#define CSN_PIN 8

#define B_UP 2 
#define B_DOWN 3 
#define B_LEFT 4 
#define B_RIGHT 5 
#define A 6 
#define B 9 
#define C 10
#define X A0 
#define Y A1 
#define Z A2
#define START A3
#define MODE A4
#define STATUS_LED A5

RF24 radio(CE_PIN, CSN_PIN);

byte addresses[][6] = {"1Node"};

word Joypad; //Declare the word

void setup() 
{
 pinMode(B_UP, OUTPUT);
 pinMode(B_DOWN, OUTPUT);
 pinMode(B_LEFT, OUTPUT);
 pinMode(B_RIGHT, OUTPUT);
 pinMode(A, OUTPUT);
 pinMode(B, OUTPUT);
 pinMode(C, OUTPUT);
 pinMode(X, OUTPUT);
 pinMode(Y, OUTPUT);
 pinMode(Z, OUTPUT);
 pinMode(START, OUTPUT);
 pinMode(MODE, OUTPUT);
 pinMode(STATUS_LED, OUTPUT);
 
 //Serial.begin(115200);
 delay(500);
 radio.begin(); // Initialize the nRF24L01 Radio
 radio.setChannel(108); // 2.508 Ghz - Above most Wifi Channels
  
 radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range
 radio.setPALevel(RF24_PA_MAX);

 radio.openReadingPipe(1, addresses[0]);
 radio.startListening();

delay(1000);
}


void loop()
{

 if ( radio.available()) // Check for incoming data from transmitter
 {
 while (radio.available()) // While there is data ready
 {
 radio.read( &Joypad, sizeof(Joypad) ); // Get the data payload (You must have defined that already!)
 }

 // Serial.print(F("Received "));
 // Serial.println(Joypad, BIN);
 } 

 /* Joypad bit description
 0-A
 1-B 
 2-C
 3-X
 4-Y
 5-Z
 6-UP
 7-DOWN
 8-LEFT
 9-RIGHT
 10-START
 11-MODE
 */

 digitalWriteFast(B_UP, bitRead(Joypad, 6));
 digitalWriteFast(B_DOWN, bitRead(Joypad, 7));
 digitalWriteFast(B_LEFT, bitRead(Joypad, 8));
 digitalWriteFast(B_RIGHT, bitRead(Joypad, 9));
 digitalWriteFast(A, bitRead(Joypad, 0));
 digitalWriteFast(B, bitRead(Joypad, 1));
 digitalWriteFast(C, bitRead(Joypad, 2));
 digitalWriteFast(X, bitRead(Joypad, 3));
 digitalWriteFast(Y, bitRead(Joypad, 4));
 digitalWriteFast(Z, bitRead(Joypad, 5));
 digitalWriteFast(START, bitRead(Joypad, 10));
 digitalWriteFast(MODE, bitRead(Joypad, 11));

 if (!bitRead(Joypad, 0) | !bitRead(Joypad, 1) | !bitRead(Joypad, 2) | !bitRead(Joypad, 3) | 
 !bitRead(Joypad, 4) | !bitRead(Joypad, 5) | !bitRead(Joypad, 6) | !bitRead(Joypad, 7) | 
 !bitRead(Joypad, 8) | !bitRead(Joypad, 9) | !bitRead(Joypad, 10) | !bitRead(Joypad, 11)) {
 digitalWriteFast(STATUS_LED,HIGH);
 } else digitalWriteFast(STATUS_LED,LOW);
}

Red LED is just showing Arduino Nano has power. The green LED is a diagnostic one.
It will show whenever any button is pressed on the controller.
If everything is fine you should have a fully compatible 6 button 2.4Ghz wireless controller.

I tested it, there is virtually no lag, at least no human can notice 20ms delay 🙂 . I gave it to a friend of mine who is exceptional player on UMK3 and he said it’s great! So I’m counting on his word 🙂

Enjoy and leave a comment if you have any questions!!

Advertisements