Jon Thysell

Father. Engineer. Retro games. Ukuleles. Nerd.

Tag: hardware

SegaController v1.3.0 now available

I’ve released an updated version of the SegaController Arduino library. If you don’t know, SegaController enables your Arduino sketches to read Sega Genesis (Mega Drive) and now Master System (Mark III) controllers.

What’s new in v1.3.0?

  • Now supports Sega Master System (Mark III) controllers
  • Optimized code to reduce compiled binary size
  • Reduced read latency
  • Fixed issue with errant button reads when inserting/removing controller
  • Temporarily disables interrupts while reading to prevent misreads
  • Added DB9 pinout diagram to readme and examples

So if you’re interested in reading Sega controllers in your Arduino projects, check out  SegaController Arduino library on GitHub.

I’ve also updated How To Read Sega Controllers with information on reading Master System (Mark III) controllers.

Enjoy and happy hacking!

/jon

Introducing the AtariController Arduino library

After releasing my Arduino library to read Sega Controllers, I decided it might be fun to create a suite of such libraries for reading other retro controllers.

So today I’m introducing my new AtariController Arduino library on GitHub. This initial release only supports the classic Atari 2600 joystick, but I hope to add other controllers in the future.

The code is provided as a proper Arduino library, making it easy for Arduino enthusiasts to use in their own sketches. As with SegaController, I also include two examples, one which reports the button states via the serial port (good for testing) and one which sends Keyboard key presses (good for driving other software).

And of course, I’ve created some documentation of my own in the AtariController wiki at How To Read Atari Controllers.

Enjoy and happy hacking!

/jon

Introducing the SegaController Arduino library

A couple years ago I tried my hand at building an interface for reading Sega Genesis / Mega Drive controllers with an Arduino. I documented my first attempt with Reading Sega Genesis controllers with Arduino, and my updated version with Sega Genesis controllers and Arduino revisited.

That was three years ago, and I’ve gotten a lot of feedback about those projects. While they worked well enough for me, many people had problems getting my code to work. My research had led me to an implementation that relied heavily on having correct timing delays, and others found they had to constantly tweak those timings.

Of course, as any decent programmer will tell you, if your code relies on a bunch of seemingly random sleeps to work properly, you’re probably doing it wrong. And it turns out I was.

I recently found the Six Button Controller page on SegaRetro, where I gleaned some new vital pieces of information:

  1. The controller must be cycled through 8 different states.
  2. Reading the controller involves knowing the current state.
  3. If the state isn’t changed for 1.5 ms, the controller resets.

Using this information, I decided to take another crack at my Arduino code. And with a little bit of work (not all of the information on the SegaRetro page was accurate) I created a much more deterministic, stable, delay-free program. Taking it a step further, I refactored the code into a proper Arduino library, both to learn how to do that, and to make it much easier for Arduino enthusiasts to use in their own sketches.

So if you’re interested in reading Sega controllers in your Arduino projects, check out my new SegaController Arduino library on GitHub. Replacing the original sketches are two new examples, one which reports the button states via the serial port (good for testing) and one which sends Keyboard key presses (good for driving other software).

Also, since my research into how the controllers worked led me to mixed results (no one’s documentation had it 100% right) I’ve created some documentation on my own in the SegaController wiki at How To Read Sega Controllers.

Enjoy and happy hacking!

/jon

Consolidating the Sega Genesis, Sega CD, and Sega 32x power supplies

As I’ve mentioned before, the Sega Genesis was my first and favorite childhood gaming console, and though over the years I’ve come to rely on emulators, re-releases and clone systems to get my Sega nostalgia, I recently decided to set up some original hardware.

Whether you’re new to the system, or a long-time fan, the holy trinity is to get a Sega Genesis along with its two biggest add-ons, the Sega CD and the Sega 32X. Now, one of the major annoyances is that each has its own wall-wart power supply, which are a pain to use: they’re hard to get situated on power strips due to their size and they generate a lot of heat, even with nothing turned on.

I thought there had to be a way to have a single consolidated power supply that supports all three systems at once. And after a little research, I found two solutions:

  1. The Sega Trio, which is a commercial power supply made specifically to solve this problem at the reasonable cost of $28.99. Only problem seems to be the very limited availability.
  2. Follow what others have done (see this forum post), and build my own custom harness on top of a generic power supply.

So I decided to build my own, and document the build along the way.

The Investigation

The first step was to collect all of the relevant power requirements for each system (thanks to this page for a lot of it). For my own setup, I have a model 2 Genesis, model 2 Sega CD, and a 32X. Here’s what the original power supplies look like:

System Voltage Amperage Plug Type Polarity
Sega Genesis Model 2 10V 0.85A 1.7mm Pos. center
Sega CD Model 2 9V 1.2A 2.1mm Neg. center
Sega 32X 10V 0.85A 1.7mm Pos. center

Now the next step is to find a suitable generic power supply. It is important to note that none of these systems actually needs exactly 9 or 10 volts to operate. In fact, the rating on the label is more like the “average voltage” that adapters of that model produce. So a particular one of these power adapters may actually produce anywhere from 8 to 12V.

This is all fine because the first thing each system does is step down that input power to the steady 5 volts that the chips inside are designed to use.

Since it’s very easy to source 9V power supplies, I’ll go with 9V for my generic.

As for the amperage, I need to add up the ratings of each power supply to get a minimum safe value. Amperage ratings show the maximum amperage that the power supplies can safely provide, not the actual amount the systems will necessarily draw. To be safe, OEM manufacturers typically provide power supplies that can offer slightly more amps than they expect their product to draw at full intensity.

So in the original setup, 2.9A is probably safely above the maximum current I’d expect the three systems to draw at once. Round that up to 3A, and now I’m looking for a 9V, minimum 3A power supply, preferably one that isn’t a wall-wart.

The next consideration is how to get one power supply to have three plugs. So I’m going to need to make or buy some kind of harness to split or daisy-chain three separate plugs. As for the plugs themselves, I have couple of things to consider.

Generic power supplies typically come standard with barrel plugs with a 2.1mm diameter center hole with positive polarity. The Genesis Model 2 and 32X both use the more common positive polarity center. Unfortunately, they use the less common EIAJ-03 barrel plugs with a smaller 1.7mm diameter center hole. The Sega CD Model 2 uses the common 2.1mm center hole, but the less common negative polarity center.

So in both cases I’m going to need some adapters.

At this point I have a spectrum of options. On one end is to buy all raw parts and try to solder up a completely custom harness. More extreme, I could even build my own power supply from scratch. On the other end of the spectrum is to try and get away with buying off-the-shelf cables and adapters.

Building from scratch is fine if you have the time, skills and tools. To save money you’ll need to buy parts in bulk, which is great if you’re going to build a bunch, or might use the parts in other projects.

Anyone can buy off-the-shelf parts and just plug them all together. No special skills required. But you will pay a premium.

For this project, I thought it would be interesting to source off-the-shelf parts, just to prove that I could make it work with no soldering required. Yes it probably wouldn’t look as slick, but anyone could replicate it. Also I was feeling lazy. I can always play cable doctor later and transform the off-the-shelf parts into a slicker, more permanent solution.

Bill of Materials

Item Product Quantity Unit Price
9V 3A DC Power Supply Output 9V 3A AC/DC Power Supply Cord Charger IEC320 C8 Socket Adapter 1 $14.37
AC Power Cord SF Cable, 6ft 18 AWG 2-Slot Non-Polarized Power Cord (IEC320 C7 to NEMA 1-15P) 1 5.75
3-Way DC Power Cable Splitter 1:3 DC Power Splitter Cable Cord 1 Female to 3 Male 5.5×2.1mm Port Pigtals 12V 1 3.99
2.1mm to 1.7mm DC Power Adapter Cable 4.8mm x 1.7mm Male Plug to 5.5mm x 2.1mm female socket DC Power Adapter cable 2 3.59
2.1mm Power Jack Polarity Changer MODE 2.1MM JACK-PLUG POLARITY CHANGER BLACK 68-102-0 1 3.80
Subtotal $35.09
Shipping 4.49
Total $39.58

First off, I’ll say that I didn’t spend a ton of time sourcing the parts. Just a couple days casually browsing Amazon and Ebay. If I found something that looked like it’d work, I bought it. For $40, this is definitely not the cheapest way to do this, but it’s not much worse than buying three new power supplies at $9.99 each.

The nicest thing was finding out that the CCTV security camera market supports an industry of nice DC power cable splitters in a variety of configurations, which was the part I assumed I’d have to make myself.

The Build

Once I had the parts, it was a simply a matter of connecting everything. If it’s not straight-forward for you, it goes like this:

  1. Connect AC cord to the power supply.
  2. Connect the 3-way splitter to the power supply.
  3. Connect each of the two 2.1mm to 1.7mm adapter cables to a cable coming out of the 3-way splitter (one each for the Genesis and 32X).
  4. Connect the 2.1mm polarity changer to the remaining cable coming out of the 3-way splitter (for the Sega CD).

The end result should look something like this:

Since the plugs have different sizes, it shouldn’t be too hard to figure out which plug connects to each system. For the sake of simplicity, I put a bit of colored tape on each: red for Genesis, blue for CD, yellow for 32X, corresponding with the primary colors of the game boxes for each system.

The power supply works like a charm. I’m free from the three-wart tyranny!

Have questions or comments? Sound off below.

/jon

Sega Genesis controllers and Arduino revisited

NOTICE: This research and implementation in this post is not 100% correct. Please check out my SegaController Arduino library for better code and How To Read Sega Controllers for details on how it works.

Version 1.0

A couple of months ago I detailed the process by which I used an Arduino Uno to read the button presses of a pair of Sega Genesis controllers. It was my first bit of micro-controller programming, and it has exposed me to a whole new world of possibilities for hardware hacking. So it is with some certain future projects in mind that I’ve revisited and updated that initial code.

Version 1.1

Other than some minor code cleanup, the only major feature-add to the core of the sketch is to support reading the “Mode” button on six-button controllers (thanks to a comment from soe for that). The other change, now that I’ve acquired an Arduino Leonardo, is to create a fork of the sketch which reports the button presses as keyboard key presses via the ATmega32u4 chip’s ability appear as a USB keyboard.

Anyway, here’s the updated code (for reporting over the Serial connection):

/*
 * Sega Controller Reader
 * Author: Jon Thysell <thysell@gmail.com>
 * Version: 1.1
 * Date: 9/29/2014
 *
 * Reads buttons presses from Sega Genesis 3/6 button controllers
 * and reports their state via the Serial connection. Handles hot
 * swapping of controllers and auto-switches between 3 and 6 button
 * polling patterns.
 *
 */

const int PLAYERS = 2;

// Controller Button Flags
const int ON = 1;
const int UP = 2;
const int DOWN = 4;
const int LEFT = 8;
const int RIGHT = 16;
const int START = 32;
const int A = 64;
const int B = 128;
const int C = 256;
const int X = 512;
const int Y = 1024;
const int Z = 2048;
const int MODE = 4096;

// Controller DB9 Pin 7 Mappings
const int SELECT[] = { 8, 9 };

typedef struct
{
  int player;
  int pin;
  int lowFlag;
  int highFlag;
  int pulse3Flag;
} input;

// 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, remaing columns are the button flags
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,  A0, UP,    UP,     Z    }, // P1 DB9 Pin 1
  { 1,  A1, DOWN,  DOWN,   Y    }, // P1 DB9 Pin 2
  { 1,  A2, ON,    LEFT,   X    }, // P1 DB9 Pin 3
  { 1,  A3, ON,    RIGHT,  MODE }, // P1 DB9 Pin 4
  { 1,  A4, A,     B,      0    }, // P1 DB9 Pin 6
  { 1,  A5, START, C,      0    }  // P1 DB9 Pin 9
};

// Controller State
int currentState[] = { 0, 0 };
int lastState[] = { -1, -1 };

// Default to three-button mode until six-button connects
boolean sixButtonMode[] = { false, false };

void setup()
{
  // Setup input pins
  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    pinMode(inputMap[i].pin, INPUT);
    digitalWrite(inputMap[i].pin, HIGH);
  }

  // Setup select pins
  for (int i = 0; i < PLAYERS; i++)
  {
    pinMode(SELECT[i], OUTPUT);
    digitalWrite(SELECT[i], HIGH);
  }

  Serial.begin(9600);
}

void loop()
{
  readButtons();
  sendStates();
}

void readButtons()
{
  for (int i = 0; i < PLAYERS; i++)
  {
    resetState(i);
    if (sixButtonMode[i])
    {
      read6buttons(i);
    }
    else
    {
      read3buttons(i);
    }
  }
}

void resetState(int player)
{
  currentState[player] = 0;
}

void read3buttons(int player)
{
  // Set SELECT LOW and read lowFlag
  digitalWrite(SELECT[player], LOW);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].lowFlag;
    }
  }

  // Set SELECT HIGH and read highFlag
  digitalWrite(SELECT[player], HIGH);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].highFlag;
    }
  }

  // When a six-button first connects, it'll spam UP and DOWN,
  // which signals the game to switch to 6-button polling
  if (currentState[player] == (ON | UP | DOWN))
  {
    sixButtonMode[player] = true;
  }
  // When a controller disconnects, revert to three-button polling
  else if ((currentState[player] & ON) == 0)
  {
    sixButtonMode[player] = false;
  }

  delayMicroseconds(20);
}

void read6buttons(int player)
{
  // Poll for three-button states twice
  read3buttons(player);
  read3buttons(player);

  // After two three-button polls, pulse the SELECT line
  // so the six-button reports the higher button states
  digitalWrite(SELECT[player], LOW);
  delayMicroseconds(20);
  digitalWrite(SELECT[player], HIGH);

  for(int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].pulse3Flag;
    }
  }

  delayMicroseconds(1000);
}

void sendStates()
{
  // Only report controller states if at least one has changed
  boolean hasChanged = false;

  for (int i = 0; i < PLAYERS; i++)
  {
    if (currentState[i] != lastState[i])
    {
      hasChanged = true;
    }
  }

  if (hasChanged)
  {
    for (int i = 0; i < PLAYERS; i++)
    {
      Serial.print((currentState[i] & ON) == ON ? "+" : "-");
      Serial.print((currentState[i] & UP) == UP ? "U" : "0");
      Serial.print((currentState[i] & DOWN) == DOWN ? "D" : "0");
      Serial.print((currentState[i] & LEFT) == LEFT ? "L" : "0");
      Serial.print((currentState[i] & RIGHT) == RIGHT ? "R" : "0");
      Serial.print((currentState[i] & START) == START ? "S" : "0");
      Serial.print((currentState[i] & A) == A ? "A" : "0");
      Serial.print((currentState[i] & B) == B ? "B" : "0");
      Serial.print((currentState[i] & C) == C ? "C" : "0");
      Serial.print((currentState[i] & X) == X ? "X" : "0");
      Serial.print((currentState[i] & Y) == Y ? "Y" : "0");
      Serial.print((currentState[i] & Z) == Z ? "Z" : "0");
      Serial.print((currentState[i] & MODE) == MODE ? "M" : "0");

      Serial.print((i == 0) ? "," : "\n");
      lastState[i] = currentState[i];
    }
  }
}

As with the previous version, all you have to do is upload the sketch and connect the controller’s DB9 pins to the Arduino following the mapping in inputMap in the code.

Now, if you have an Arduino Leonardo (or compatible board), and want the controller button presses to map to keyboard keys instead, you can upload the following sketch:

/*
 * Sega Controller Reader (Keyboard)
 * Author: Jon Thysell <thysell@gmail.com>
 * Version: 1.1
 * Date: 9/29/2014
 *
 * Reads buttons presses from Sega Genesis 3/6 button controllers
 * and reports their state via keyboard button presses. Handles hot
 * swapping of controllers and auto-switches between 3 and 6 button
 * polling patterns.
 *
 */

const int PLAYERS = 2;

// Controller Button Flags
const int ON = 1;
const int UP = 2;
const int DOWN = 4;
const int LEFT = 8;
const int RIGHT = 16;
const int START = 32;
const int A = 64;
const int B = 128;
const int C = 256;
const int X = 512;
const int Y = 1024;
const int Z = 2048;
const int MODE = 4096;

// Controller DB9 Pin 7 Mappings
const int SELECT[] = { 8, 9 };

typedef struct
{
  int player;
  int pin;
  int lowFlag;
  int highFlag;
  int pulse3Flag;
} input;

// 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,  A0, UP,    UP,     Z    }, // P1 DB9 Pin 1
  { 1,  A1, DOWN,  DOWN,   Y    }, // P1 DB9 Pin 2
  { 1,  A2, ON,    LEFT,   X    }, // P1 DB9 Pin 3
  { 1,  A3, ON,    RIGHT,  MODE }, // P1 DB9 Pin 4
  { 1,  A4, A,     B,      0    }, // P1 DB9 Pin 6
  { 1,  A5, START, C,      0    }  // P1 DB9 Pin 9
};

typedef struct
{
  int player;
  int flag;
  char key;
} output;

// Controller Button Flag to Keyboard Mappings
// First column is the controller index, second column
// is the button flag, third is keyboard key
output outputMap[] = {
  { 0, UP,    KEY_UP_ARROW },
  { 0, DOWN,  KEY_DOWN_ARROW },
  { 0, LEFT,  KEY_LEFT_ARROW },
  { 0, RIGHT, KEY_RIGHT_ARROW },
  { 0, START, KEY_RETURN },
  { 0, A,     'z' },
  { 0, B,     'x' },
  { 0, C,     'c' },
  { 0, X,     'a' },
  { 0, Y,     's' },
  { 0, Z,     'd' },
  { 0, MODE,  'q' },
  { 1, UP,    'i' },
  { 1, DOWN,  'k' },
  { 1, LEFT,  'j' },
  { 1, RIGHT, 'l' },
  { 1, START, 't' },
  { 1, A,     'v' },
  { 1, B,     'b' },
  { 1, C,     'n' },
  { 1, X,     'f' },
  { 1, Y,     'g' },
  { 1, Z,     'h' },
  { 1, MODE,  'r' }
};

// Controller State
int currentState[] = { 0, 0 };
int lastState[] = { -1, -1 };

// Default to three-button mode until six-button connects
boolean sixButtonMode[] = { false, false };

void setup()
{
  // Setup input pins
  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    pinMode(inputMap[i].pin, INPUT);
    digitalWrite(inputMap[i].pin, HIGH);
  }

  // Setup select pins
  for (int i = 0; i < PLAYERS; i++)
  {
    pinMode(SELECT[i], OUTPUT);
    digitalWrite(SELECT[i], HIGH);
  }

  Keyboard.begin();
}

void loop()
{
  readButtons();
  sendStates();
}

void readButtons()
{
  for (int i = 0; i < PLAYERS; i++)
  {
    resetState(i);
    if (sixButtonMode[i])
    {
      read6buttons(i);
    }
    else
    {
      read3buttons(i);
    }
  }
}

void resetState(int player)
{
  currentState[player] = 0;
}

void read3buttons(int player)
{
  // Set SELECT LOW and read lowFlag
  digitalWrite(SELECT[player], LOW);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].lowFlag;
    }
  }

  // Set SELECT HIGH and read highFlag
  digitalWrite(SELECT[player], HIGH);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].highFlag;
    }
  }

  // When a six-button first connects, it'll spam UP and DOWN,
  // which signals the game to switch to 6-button polling
  if (currentState[player] == (ON | UP | DOWN))
  {
    sixButtonMode[player] = true;
  }
  // When a controller disconnects, revert to three-button polling
  else if ((currentState[player] & ON) == 0)
  {
    sixButtonMode[player] = false;
  }

  delayMicroseconds(20);
}

void read6buttons(int player)
{
  // Poll for three-button states twice
  read3buttons(player);
  read3buttons(player);

  // After two three-button polls, pulse the SELECT line
  // so the six-button reports the higher button states
  digitalWrite(SELECT[player], LOW);
  delayMicroseconds(20);
  digitalWrite(SELECT[player], HIGH);

  for(int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].pulse3Flag;
    }
  }

  delayMicroseconds(1000);
}

void sendStates()
{
  for (int i = 0; i < sizeof(outputMap) / sizeof(output); i++)
  {
    int last = (lastState[outputMap[i].player] & outputMap[i].flag);
    int current = (currentState[outputMap[i].player] & outputMap[i].flag);

    if (last != current)
    {
      if (current == outputMap[i].flag)
      {
        Keyboard.press(outputMap[i].key);
      }
      else
      {
        Keyboard.release(outputMap[i].key);
      }
    }
  }

  for (int i = 0; i < PLAYERS; i++)
  {
    lastState[i] = currentState[i];
  }
}

If you want to change the button to key mapping, simply update outputMap in the code. You can use any key on the keyboard, including special keys and modifiers.

I hope this is a worthy updated to the sketch – it was a great delight to test it by playing emulated games on my laptop with real Genesis controllers. It worked wonderfully, and I can’t wait to get this integrated into a bigger project.

So happy hacking and stay tuned for more!

/jon

Update 26-JUN-2017: The source is now available on GitHub here.

Update 28-JUN-2017: I’ve announced a newer, stable, reusable version at Introducing the SegaController Arduino library.