Introduction: Sega MegaPi
My interest in this started from reading a magazine where they shoved a raspberry PI into a ZX Spectrum and an original Sega Megadrive. I started looking around and was further inspired by this:
I built something similar using Chameleon PI.
So given this success I started scouring around for broken 80's computers and game consoles. The game consoles are surprisingly rugged and the first few I bought I was able to fix so I onsold them! However I finally found one that had a case that was in very good condition but with a board that I could not get going. So this project was born!
There are many people doing similar things and initially I just wanted to stick a PI into the case and plug in some USB controllers. People in the past have done just that and have cut holes in the case for various reasons and pulled out the DB9 connectors and put in female USB connectors.
However as I sat there looking at the case I started thinking could I do this a bit better. The case already has an opening on the bottom which is high enough to expose the four USB and ethernet ports if I mounted it just right. What about the original controllers could I interface those to the Pi somehow? I looked around the net and as far as I could tell people have done various parts of what I wanted to do but not the whole thing together. So maybe this will be a new take on this idea!
My goal is to have a Megadrive that from the outside looks unchanged from the original as far as possible (the only difference you can see is the power connector and the HDMI connector. When working it should work exactly as it did when new, the power LED will work and both controllers (including six button versions) will work seamlessly. Those controllers though will also work well with Retropie and the emulators. As a bonus you will be able to plug in a cartridge for aesthetic value (it wont actually work though!).
Step 1: What I Used
Components:
- Broken Sega Megadrive 2
- Raspberry Pi 2
Arduino Pro Micro
- Male Female HDMI Cable
- 90 Degree Male to Female USB
- Female to Female Jumper Cables
- Heat Shrink Tubing
- Various Colour Hook Up Wire
- Panel Mount DC Socket
- Micro USB to USB Cable
- 19mm Cable Tie Mounts
- 2x Micro Momentary Push Switches
- 2x 10k Ohm Resistors
- 2x 1k Ohm Resistors
- 4mm perspex cut up as spacers
Tools:
- Screwdriver
- Soldering Iron
- Dremel (or equivalent!)
- Wire cutters
- Drill
Step 2: Installing the PI
The first part is easy. Open up the case and pull everything out so you are left with a plastic shell.
I then located the PI in the case with the front lip of the Ethernet and HDMI connectors resting on the flat section of the case beside the expansion opening. I used some perpex I had to make spacers and glued them down before drilling holes and securing the Pi with screws.
Once that was in I reinstalled the cartridge slot (which was hard as to get off the board!) using the original spacers so it will be close to the original height (minus the thickness of the motherboard).
Next I installed the panel socket which fit neatly into place.
Lastly for this phase I plugged in the HDMI cable. This was a snug fit given where I placed the PI and necessitated some close shaving of the section of motherboard which I retained for the DB9 connectors. On the female end of the connector I shaved 1-2mm off all the way around so it has a little step which will fit through the side of the case. Using a small file I gently cut the existing round hole out to make it rectangular and slipped the connector through so that it is flush with the outside of the case. I glued a small block of plastic under the connector for support and then used silicon to hold it in place. Not a perfect job but I can live with it since it is around the back.
Step 3: DB9 Connectors
Initially I thought I would desolder the DB9 connectors from the board but then that is hard and how to mount them? So what I did was cut back the board as you can see such that I could still screw it back onto the case. Before I did that though I attached a series of wires to all the DB9 pins and brought them out in two bundles putting a bit of heat shrink tubing over each to keep them nicely together. I used the same colour for corresponding pins of each connector which sped up the process of attaching them all to the Arduino.
If you look closely at the right hand side you can see the HDMI cable is a tight fit. I had to remove a screw and cut back some of the board to get that all to work. It could not be any tighter but in the end came together perfectly.
Also I preserved the LED and ran power from a 5V GPIO pin and GND to the LED and the surface mounted resistor that is right beside it. Result is a power LED which works exactly like the original!
All eighteen wires then need to be soldered neatly to the Arduino Pro Micro. I used a cable tie mount to hold it in its final place.
Step 4: Arduino Sketch
Upfront this is all the work of Jon Thysell. I have used his sketch for the Leonardo except I am using a Pro Micro.
This just worked out of the box without any problems. It is awesome! However I have tried it with the six button controllers you can buy on eBay at the moment and it does not work in six button mode. There is obviously some timing issue there. If you aren't fussed about the six buttons or you have different controllers to the cheap ones currently on offer then no problems (those eBay controllers are cheap - short cord, light weight, crappy button feel!)
Software wise though it does seem to work great. Just load up the sketch and solder on the wires according to what is described in the sketch starting on line 43 although I modified it slightly as there is different pin numbering with the Micro:
// Controller DB9 Pin to Button Flag Mappings // First column is the controller index, second column // is the Arduino pin that the controller's DB9 pin is // attached to input inputMap[] = { { 0, 2, UP, UP, Z }, // P0 DB9 Pin 1 { 0, 3, DOWN, DOWN, Y }, // P0 DB9 Pin 2 { 0, 4, ON, LEFT, X }, // P0 DB9 Pin 3 { 0, 5, ON, RIGHT, MODE }, // P0 DB9 Pin 4 { 0, 6, A, B, 0 }, // P0 DB9 Pin 6 { 0, 7, START, C, 0 }, // P0 DB9 Pin 9 { 1, A3, UP, UP, Z }, // P1 DB9 Pin 1 { 1, A2, DOWN, DOWN, Y }, // P1 DB9 Pin 2 { 1, A1, ON, LEFT, X }, // P1 DB9 Pin 3 { 1, A0, ON, RIGHT, MODE }, // P1 DB9 Pin 4 { 1, 15, A, B, 0 }, // P1 DB9 Pin 6 { 1, 14, START, C, 0 } // P1 DB9 Pin 9 };
You also need to solder the remaining wires as follows:
- P0 and P1 DB9 Pin 5 to VCC
- P0 DB9 Pin 7 to Arduino Pin 8
- P1 DB9 Pin 7 to Arduino Pin 9 (See lines 31 and 32 of the sketch)
- P0 and P1 DB9 Pin 8 to GND
Details about the DB9 pin configuration is here.
Once you have this done then the Arduino appears as a keyboard and for each button press a particular keystroke is sent. The sketch supports 3 and 6 button controllers and does this automatically. It is probably better to use a 6 button controller as it then allows those extra buttons to be used when you are playing other emulators. The only button which is effectively missing is SELECT. However, I have used the RESET button to provide this functionality by adding the following code to the sketch:
void readExtraButtons()
{ buttonState1 = digitalRead(buttonPin1); buttonState2 = digitalRead(buttonPin2); if (buttonState1 == LOW && buttonState1 != oldButtonState1) { Keyboard.print('w'); // Could use this as a SELECT key delayMicroseconds(1000); } oldButtonState1 = buttonState1; if (buttonState2 == LOW && buttonState2 != oldButtonState2) { // Cycle through six button modes if (sixButtonMode[0] == false && sixButtonMode[1] == false) sixButtonMode[0] = true; else if (sixButtonMode[0] == true && sixButtonMode[1] == false) { sixButtonMode[0] = false; sixButtonMode[1] = true; } else if (sixButtonMode[0] == false && sixButtonMode[1] == true) sixButtonMode[0] = true; else { sixButtonMode[0] = false; sixButtonMode[1] = false; } Keyboard.print(sixButtonMode[0]); Keyboard.println(sixButtonMode[1]); } oldButtonState2 = buttonState2; }
The long press cycles through six button mode which I added to try and help with the problems I was having trying to get the cheap eBay controller to work. You could omit that or use the long press to send a different key stroke. This function is called from loop()
I did have some issues trying to figure out how to interface correctly with the emulator. Retropie itself needed very little tinkering to get it all up and running. The best guide for setting it up I found here. The issue I had though was that guide assumes you have USB controllers that appear to the PI as a Joystick/Joypad/Gamepad. In my case the controllers actually appear as a keyboard and there is very little information about setting up a keyboard to work with the game emulators. When I say very little I mean i couldn't find anything!
In the end I nutted it out by noticing that there was an example retroarch.cfg file which has a section titled KEYBOARD INPUT. By using that as a template and then referring to the button setup diagrams on the Retropie setup wiki I came up with the following initial lines for my own retroarch.cfg file:
# For the Megadrive controller using keyboard outputs we need to know that the megadrive mapping # is odd. See <a href="https://github.com/petrockblog/RetroPie-Setup/wik..." rel="nofollow"> <a rel="nofollow"> <a rel="nofollow"> <a rel="nofollow"> https://github.com/petrockblog/RetroPie-Setup/wik...>>>> # Controller A - Retroarch Y # Controller B - Retroarch B # Controller C - Retroarch A # Controller X - Retroarch Left Button # Controller Y - Retroarch X # Controller Z - Retroarch Right Button # Controller Start - Retroarch Start input_player1_a = c input_player1_b = x input_player1_y = z input_player1_x = s input_player1_l = a input_player1_r = d input_player1_start = enter input_player1_select = w input_player1_up = up input_player1_down = down input_player1_left = left input_player1_right = right input_enable_hotkey = enter input_exit_emulator = down input_player2_a = n input_player2_b = b input_player2_y = v input_player2_x = g input_player2_l = f input_player2_r = h input_player2_start = t input_player2_up = i input_player2_down = k input_player2_left = j input_player2_right = l
It is possible, with this config file, to set up simultaneous button presses to do particular things. The most important is to setup a sequence to quit the game and go back to the emulator. In my case I press START and DOWN together (See the lines input_enable_hotkey and input_exit_emulator). This is key, as without setting that you would need a keyboard plugged in. Now once everything is setup the Megadrive can sit there looking like it did back in the 80s and be completely controlled by the Gamepad.
Step 5: Shutdown and Reset Buttons
I wanted to have the original case buttons work as well. Initially I though about a physical power button but then decided on making it a software shutdown command instead so that the corrupt SD card problem is minimised. (In fact I originally cut the board so that the original push button was still there and I was going to use that!)
Firstly the hardware. You can get little momentary push buttons with a plastic shaft around the place. The ones I used I have had for ages. The advantage of the plastic shaft is that you can cut it off to the length you need. For the power switch the original square hole is just the right size for the thread of the button. I screwed it in to the point where is was just touching the original button. Some silicon sealed it in place. For the reset button I cut the shaft of the original Sega reset button back slightly. Then I drilled out the hole in the shaft that the button sits in slightly so that my button would screw into it. This held it sturdy so I left it at that.
For the wiring I went through a bunch of iterations to get it right. There are plenty of guides on how to wire up one button but not so many about multiple buttons. Finally I found this and and this and this:
From all of that I wired up the two push buttons as shown in the diagram at the top. Also of interest I split the "GPIO" wire to go to both the Arduino pins 16 and 10 as well as the Raspberry PI pins. This is so I can use the buttons to be a keyboard press via the Arduino or do something directly on the Raspberry Pi (eg. send a shutdown command)
For the software I used the sketch from here. Just note the diagram on that page is for the 26 pin header. A good diagram for the 40 pin header I found here. A nice thing about this sketch is you effectively have four buttons, short press and long press for both the power and reset buttons.
You can see the addition to the Arduino sketch in STEP 4. For the Raspberry Pi the Python code I used is:
import RPi.GPIO as GPIO import time import uinput import os GPIO.setmode(GPIO.BCM) GPIO.setup(23,GPIO.IN) GPIO.setup(24,GPIO.IN) buttonPower_previous = 1 buttonPower_current = 1 powerTimer= 0 flag_powerPressed = 0 buttonReset_previous = 1 buttonReset_current = 1 resetTimer= 0 flag_resetPressed = 0 while True: buttonPower_current = GPIO.input(23); flag_powerPressed = buttonPower_previous + buttonPower_current buttonReset_current = GPIO.input(24); flag_resetPressed = buttonReset_previous + buttonPower_current if (not(flag_powerPressed)): powerTimer += 1 else: powerTimer = 0 if (not(flag_resetPressed)): resetTimer += 1 else: resetTimer = 0 events = { uinput.KEY_ESC, uinput.KEY_M } device = uinput.Device(events) if (buttonPower_current and (not buttonPower_previous)): device.emit(uinput.KEY_ESC, 1) device.emit(uinput.KEY_ESC, 0) if ((not flag_powerPressed) and powerTimer >= 20): os.system("sudo shutdown -h now") break; if (buttonReset_current and (not buttonReset_previous)): device.emit(uinput.KEY_M, 1) device.emit(uinput.KEY_M, 0) if ((not flag_resetPressed) and resetTimer >= 20): os.system("sudo shutdown -r now") break; buttonPower_previous = buttonPower_current buttonReset_previous - buttonReset_current time.sleep(0.03)
You will have to install the uinput module most likely if you want key presses to work. At this point I have it in the code but I am not using it as I found those presses were not being detected by the emulators. Hence why I have the dual config of using the arduino to do those. I have left the capability though in case I think of something in the future.
Also you will likely have to install the GPIO module as described here.
Step 6: The Finished Product
So I think that describes everything you need to know! As I said it works perfectly except when using the cheap six button controllers. If someone can solve that problem let me know! If I get time I will have a further look at it.
Once the case is all together one of the USB ports is tight if not inaccessible but that leaves two others for additional controllers if you only have three button ones and you want to play Nintendo games (for example). The USB ports allow easy access to upload more ROMs without having to plug in a network cable. The network cable can be attached easily you just need a small screwdriver to lift the latch to get it out again.
Hope you like my very first instructable!