mcgurk / Arduino-USB-HID-RetroJoystickAdapter

Arduino joystick/gamepad/other USB-adapter
131 stars 35 forks source link

Genesis 6 button #3

Closed luizoti closed 3 years ago

luizoti commented 6 years ago

I followed the passes and got to ride, but the x, y, z and MODE buttons do not work, is there any option that needs to be activated in order for them to work?

epixthunder commented 6 years ago

I'm having the same issue. Any ideas?

luizoti commented 6 years ago

Man, I'm pretty sure I used this code.

As I already had the solder ready, I just changed the code on the pins of each button, but you can just follow the pinning of the code that should work.

When compiling the code the IDE should give error, because it lacks two lines at the beginning of the code, I do not remember what the lines are, if I find out post here later.

Original site: [](https://jonthysell.com/2014/09/29/sega-genesis-controllers-and-arduino-revisited/

If you decide to change the code pinning, change these lines below.

// 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 };

/*
 * 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];
  }
}
webodan commented 5 years ago

Hello,

I have the same problem with my new AFUNTA sega genesis controllers that I got from amazon. Only A,B,C, Start and dpad work; X Y Z do not ,and my controller doesn't have a MODE button. How can I make it work in 6 button mode? I tried changing the uint8_t J1BTN6 = 0; to 1 in the source code, but that wired the up, down, left and right dpad directions to buttons 5 to 8 instead of wiring them to the x y and z buttons.

Thanks in advance.

luizoti commented 5 years ago

I really have no idea, I do not know these controls, but if they use the same arduino model it's probably possible.

truglodite commented 4 years ago

That code posted above isn't even from this repo?!: https://github.com/jonthysell/SegaController

Please post any issues related to jonthysell's code in the proper place (his repo), and keep the discussions here on the topic of mcgurk's code.

Anyhow, I've personally tested the code from this repo and it works perfectly with 6 button controllers. This issue should be closed.

HeReBuS commented 3 years ago

Hi, I have the original sega pads for both cable and wireless, but I don't know how to make the mode, x, y, and z buttons work. I think something is wrong and I don't know what. I would really appreciate if someone can help me.