Browse Source

Sega adapters refactoring.

pull/5/head
MickGyver 2 years ago
parent
commit
0ee8aef8f0
12 changed files with 141 additions and 194 deletions
  1. +5
    -0
      SegaControllerUSB/Gamepad.cpp
  2. +2
    -0
      SegaControllerUSB/Gamepad.h
  3. +4
    -4
      SegaControllerUSB/SegaController32U4.cpp
  4. +16
    -4
      SegaControllerUSB/SegaController32U4.h
  5. +7
    -3
      SegaControllerUSB/SegaControllerUSB.ino
  6. BIN
      SegaControllerUSB/images/sega-usb-adapter-wiring.png
  7. +5
    -2
      SegaTwoControllersUSB/Gamepad.cpp
  8. +2
    -0
      SegaTwoControllersUSB/Gamepad.h
  9. +56
    -148
      SegaTwoControllersUSB/SegaControllers32U4.cpp
  10. +30
    -23
      SegaTwoControllersUSB/SegaControllers32U4.h
  11. +14
    -10
      SegaTwoControllersUSB/SegaTwoControllersUSB.ino
  12. BIN
      SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png

+ 5
- 0
SegaControllerUSB/Gamepad.cpp View File

@ -146,5 +146,10 @@ void Gamepad_::send()
uint8_t Gamepad_::getShortName(char *name)
{
if(!next)
{
strcpy(name, gp_serial);
return strlen(name);
}
return 0;
}

+ 2
- 0
SegaControllerUSB/Gamepad.h View File

@ -29,6 +29,8 @@
#include <Arduino.h>
#include "HID.h"
extern const char* gp_serial;
// The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems
typedef struct {


+ 4
- 4
SegaControllerUSB/SegaController32U4.cpp View File

@ -33,9 +33,9 @@
SegaController32U4::SegaController32U4(void)
{
// Setup select pin as output high (6, PD7)
DDRD |= B10000000; // output
PORTD |= B10000000; // high
// Setup select pin as output high (7, PE6)
DDR_SELECT |= MASK_SELECT; // output
PORT_SELECT |= MASK_SELECT; // high
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
DDRF &= ~B11110000; // input
@ -67,7 +67,7 @@ word SegaController32U4::getStateMD()
// Set the select pin low/high
_pinSelect = !_pinSelect;
(!_pinSelect) ? PORTD &= ~B10000000 : PORTD |= B10000000; // Set LOW on even cycle, HIGH on uneven cycle
(!_pinSelect) ? PORT_SELECT &= ~MASK_SELECT : PORT_SELECT |= MASK_SELECT; // Set LOW on even cycle, HIGH on uneven cycle
// Short delay to stabilise outputs in controller
delayMicroseconds(SC_CYCLE_DELAY);


+ 16
- 4
SegaControllerUSB/SegaController32U4.h View File

@ -28,6 +28,18 @@
#ifndef SegaController32U4_h
#define SegaController32U4_h
//#define USE_OLD_WIRING // Uncomment this line to use the old wiring with DB9 pin 6 to Arduino pin 7
#ifdef USE_OLD_WIRING
#define DDR_SELECT DDRD
#define PORT_SELECT PORTD
#define MASK_SELECT B10000000
#else
#define DDR_SELECT DDRE
#define PORT_SELECT PORTE
#define MASK_SELECT B01000000
#endif
enum
{
SC_CTL_ON = 1, // The controller is connected (not used)
@ -43,8 +55,10 @@ enum
SC_BTN_Z = 1024,
SC_BTN_START = 2048,
SC_BTN_MODE = 4096,
SC_BTN_1 = 64, // Master System compatibility
SC_BTN_2 = 128, // Master System compatibility
SC_BIT_UP = 1,
SC_BIT_DOWN = 2,
SC_BIT_LEFT = 3,
SC_BIT_RIGHT = 4,
DB9_PIN1_BIT = 7,
DB9_PIN2_BIT = 6,
DB9_PIN3_BIT = 5,
@ -53,8 +67,6 @@ enum
DB9_PIN9_BIT = 1
};
const byte SC_INPUT_PINS = 6;
const byte SC_CYCLE_DELAY = 10; // Delay (µs) between setting the select pin and reading the button pins
class SegaController32U4 {


+ 7
- 3
SegaControllerUSB/SegaControllerUSB.ino View File

@ -24,6 +24,10 @@
#include "SegaController32U4.h"
#include "Gamepad.h"
// ATT: 20 chars max (including NULL at the end) according to Arduino source code.
// Additionally serial number is used to differentiate arduino projects to have different button maps!
const char *gp_serial = "Sega/C= to USB";
// Controller DB9 pins (looking face-on to the end of the plug):
//
// 5 4 3 2 1
@ -38,7 +42,7 @@
// 3 A2 PF5
// 4 A3 PF4
// 6 14 PB3
// 7 6 PD7
// 7 7 PE6 (Used to be 6 PD7)
// 9 15 PB1
SegaController32U4 controller;
@ -67,8 +71,8 @@ void sendState()
if (currentState != lastState)
{
Gamepad._GamepadReport.buttons = currentState >> 5;
Gamepad._GamepadReport.Y = ((currentState & B00000100) >> 2) - ((currentState & B00000010) >> 1);
Gamepad._GamepadReport.X = ((currentState & B00010000) >> 4) - ((currentState & B00001000) >> 3);
Gamepad._GamepadReport.Y = ((currentState & SC_BTN_DOWN) >> SC_BIT_DOWN) - ((currentState & SC_BTN_UP) >> SC_BIT_UP);
Gamepad._GamepadReport.X = ((currentState & SC_BTN_RIGHT) >> SC_BIT_RIGHT) - ((currentState & SC_BTN_LEFT) >> SC_BIT_LEFT);
Gamepad.send();
lastState = currentState;
}


BIN
SegaControllerUSB/images/sega-usb-adapter-wiring.png View File

Before After
Width: 700  |  Height: 544  |  Size: 300 KiB Width: 700  |  Height: 544  |  Size: 300 KiB

+ 5
- 2
SegaTwoControllersUSB/Gamepad.cpp View File

@ -24,8 +24,6 @@
*
*/
#pragma once
#include "Gamepad.h"
static const uint8_t _hidReportDescriptor[] PROGMEM = {
@ -146,5 +144,10 @@ void Gamepad_::send()
uint8_t Gamepad_::getShortName(char *name)
{
if(!next)
{
strcpy(name, gp_serial);
return strlen(name);
}
return 0;
}

+ 2
- 0
SegaTwoControllersUSB/Gamepad.h View File

@ -29,6 +29,8 @@
#include <Arduino.h>
#include "HID.h"
extern const char* gp_serial;
// The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems
typedef struct {


+ 56
- 148
SegaTwoControllersUSB/SegaControllers32U4.cpp View File

@ -33,39 +33,29 @@
SegaControllers32U4::SegaControllers32U4(void)
{
// Setup select pin as output high (6, PD7)
DDRD |= B10000000; // output
PORTD |= B10000000; // high
// Setup select pin as output high (5, PC6)
DDRC |= B01000000; // output
PORTC |= B01000000; // high
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
DDRF &= ~B11110000; // input
PORTF |= B11110000; // high to enable internal pull-up
DDRB &= ~B00001010; // input
PORTB |= B00001010; // high to enable internal pull-up
// Setup input pins (TXO,RXI,2,3,4,6 or PD3,PD2,PD1,PD0,PD4,PE6)
DDRD &= ~B00011111; // input
PORTD |= B00011111; // high to enable internal pull-up
DDRE &= ~B01000000; // input
PORTE |= B01000000; // high to enable internal pull-up
_inputReg1 = 0;
_inputReg2 = 0;
_inputReg3 = 0;
_inputReg4 = 0;
for(byte i=0; i<=1; i++)
{
_currentState[i] = 0;
_connected[i] = 0;
_sixButtonMode[i] = false;
_ignoreCycles[i] = 0;
_pinSelect[i] = true;
}
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
DDRF &= ~B11110000; // input
PORTF |= B11110000; // high to enable internal pull-up
DDRB &= ~B00001010; // input
PORTB |= B00001010; // high to enable internal pull-up
// Setup input pins (TXO,RXI,2,3,4,6 or PD3,PD2,PD1,PD0,PD4,PE6)
DDRD &= ~B10011111; // input
PORTD |= B10011111; // high to enable internal pull-up
for(byte i=0; i<=1; i++)
{
*_ddrSelect[i] |= _maskSelect[i]; // Select pins as output
*_portSelect[i] |= _maskSelect[i]; // Select pins high
_inputReg[i] = 0;
_currentState[i] = 0;
_connected[i] = 0;
_sixButtonMode[i] = false;
_ignoreCycles[i] = 0;
_pinSelect[i] = true;
}
}
word SegaControllers32U4::getStateMD1()
word SegaControllers32U4::getStateMD(byte gp)
{
// "Normal" Six button controller reading routine, done a bit differently in this project
// Cycle TH out TR in TL in D3 in D2 in D1 in D0 in
@ -79,163 +69,81 @@ word SegaControllers32U4::getStateMD1()
// 7 HI --- --- --- --- --- ---
// Set the select pin low/high
_pinSelect[0] = !_pinSelect[0];
(!_pinSelect[0]) ? PORTD &= ~B10000000 : PORTD |= B10000000; // Set LOW on even cycle, HIGH on uneven cycle
// Short delay to stabilise outputs in controller
delayMicroseconds(SC_CYCLE_DELAY);
// Read input register(s)
_inputReg1 = PINF;
_inputReg2 = PINB;
if(_ignoreCycles[0] <= 0)
{
if(_pinSelect[0]) // Select pin is HIGH
{
if(_connected[0])
{
// Check if six button mode is active
if(_sixButtonMode[0])
{
// Read input pins for X, Y, Z, Mode
(bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW) ? _currentState[0] |= SC_BTN_Z : _currentState[0] &= ~SC_BTN_Z;
(bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) ? _currentState[0] |= SC_BTN_Y : _currentState[0] &= ~SC_BTN_Y;
(bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) ? _currentState[0] |= SC_BTN_X : _currentState[0] &= ~SC_BTN_X;
(bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) ? _currentState[0] |= SC_BTN_MODE : _currentState[0] &= ~SC_BTN_MODE;
_sixButtonMode[0] = false;
_ignoreCycles[0] = 2; // Ignore the two next cycles (cycles 6 and 7 in table above)
}
else
{
// Read input pins for Up, Down, Left, Right, B, C
(bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW) ? _currentState[0] |= SC_BTN_UP : _currentState[0] &= ~SC_BTN_UP;
(bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) ? _currentState[0] |= SC_BTN_DOWN : _currentState[0] &= ~SC_BTN_DOWN;
(bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) ? _currentState[0] |= SC_BTN_LEFT : _currentState[0] &= ~SC_BTN_LEFT;
(bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) ? _currentState[0] |= SC_BTN_RIGHT : _currentState[0] &= ~SC_BTN_RIGHT;
(bitRead(_inputReg2, DB9_PIN6_BIT1) == LOW) ? _currentState[0] |= SC_BTN_B : _currentState[0] &= ~SC_BTN_B;
(bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) ? _currentState[0] |= SC_BTN_C : _currentState[0] &= ~SC_BTN_C;
}
}
else // No Mega Drive controller is connected, use SMS/Atari mode
{
// Clear current state
_currentState[0] = 0;
// Read input pins for Up, Down, Left, Right, Fire1, Fire2
if (bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW) { _currentState[0] |= SC_BTN_UP; }
if (bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) { _currentState[0] |= SC_BTN_DOWN; }
if (bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) { _currentState[0] |= SC_BTN_LEFT; }
if (bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) { _currentState[0] |= SC_BTN_RIGHT; }
if (bitRead(_inputReg2, DB9_PIN6_BIT1) == LOW) { _currentState[0] |= SC_BTN_A; }
if (bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) { _currentState[0] |= SC_BTN_B; }
}
}
else // Select pin is LOW
{
// Check if a controller is connected
_connected[0] = (bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW && bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW);
// Check for six button mode
_sixButtonMode[0] = (bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW && bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW);
// Read input pins for A and Start
if(_connected[0])
{
if(!_sixButtonMode[0])
{
(bitRead(_inputReg2, DB9_PIN6_BIT1) == LOW) ? _currentState[0] |= SC_BTN_A : _currentState[0] &= ~SC_BTN_A;
(bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) ? _currentState[0] |= SC_BTN_START : _currentState[0] &= ~SC_BTN_START;
}
}
}
}
else
{
_ignoreCycles[0]--;
}
return _currentState[0];
}
word SegaControllers32U4::getStateMD2()
{
// Set the select pin low/high
_pinSelect[1] = !_pinSelect[1];
(!_pinSelect[1]) ? PORTC &= ~B01000000 : PORTC |= B01000000; // Set LOW on even cycle, HIGH on uneven cycle
_pinSelect[gp] = !_pinSelect[gp];
(!_pinSelect[gp]) ? *_portSelect[gp] &= ~_maskSelect[gp] : *_portSelect[gp] |= _maskSelect[gp]; // Set LOW on even cycle, HIGH on uneven cycle
// Short delay to stabilise outputs in controller
delayMicroseconds(SC_CYCLE_DELAY);
// Read input register(s)
_inputReg3 = PIND;
_inputReg4 = PINE;
_inputReg[0] = *_pinInputs[gp][0];
_inputReg[1] = *_pinInputs[gp][1];
if(_ignoreCycles[1] <= 0)
if(_ignoreCycles[gp] <= 0)
{
if(_pinSelect[1]) // Select pin is HIGH
if(_pinSelect[gp]) // Select pin is HIGH
{
if(_connected[1])
if(_connected[gp])
{
// Check if six button mode is active
if(_sixButtonMode[1])
if(_sixButtonMode[gp])
{
// Read input pins for X, Y, Z, Mode
(bitRead(_inputReg3, DB9_PIN1_BIT2) == LOW) ? _currentState[1] |= SC_BTN_Z : _currentState[1] &= ~SC_BTN_Z;
(bitRead(_inputReg3, DB9_PIN2_BIT2) == LOW) ? _currentState[1] |= SC_BTN_Y : _currentState[1] &= ~SC_BTN_Y;
(bitRead(_inputReg3, DB9_PIN3_BIT2) == LOW) ? _currentState[1] |= SC_BTN_X : _currentState[1] &= ~SC_BTN_X;
(bitRead(_inputReg3, DB9_PIN4_BIT2) == LOW) ? _currentState[1] |= SC_BTN_MODE : _currentState[1] &= ~SC_BTN_MODE;
_sixButtonMode[1] = false;
_ignoreCycles[1] = 2; // Ignore the two next cycles (cycles 6 and 7 in table above)
(bitRead(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_Z : _currentState[gp] &= ~SC_BTN_Z;
(bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_Y : _currentState[gp] &= ~SC_BTN_Y;
(bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_X : _currentState[gp] &= ~SC_BTN_X;
(bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_MODE : _currentState[gp] &= ~SC_BTN_MODE;
_sixButtonMode[gp] = false;
_ignoreCycles[gp] = 2; // Ignore the two next cycles (cycles 6 and 7 in table above)
}
else
{
// Read input pins for Up, Down, Left, Right, B, C
(bitRead(_inputReg3, DB9_PIN1_BIT2) == LOW) ? _currentState[1] |= SC_BTN_UP : _currentState[1] &= ~SC_BTN_UP;
(bitRead(_inputReg3, DB9_PIN2_BIT2) == LOW) ? _currentState[1] |= SC_BTN_DOWN : _currentState[1] &= ~SC_BTN_DOWN;
(bitRead(_inputReg3, DB9_PIN3_BIT2) == LOW) ? _currentState[1] |= SC_BTN_LEFT : _currentState[1] &= ~SC_BTN_LEFT;
(bitRead(_inputReg3, DB9_PIN4_BIT2) == LOW) ? _currentState[1] |= SC_BTN_RIGHT : _currentState[1] &= ~SC_BTN_RIGHT;
(bitRead(_inputReg3, DB9_PIN6_BIT2) == LOW) ? _currentState[1] |= SC_BTN_B : _currentState[1] &= ~SC_BTN_B;
(bitRead(_inputReg4, DB9_PIN9_BIT2) == LOW) ? _currentState[1] |= SC_BTN_C : _currentState[1] &= ~SC_BTN_C;
(bitRead(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_UP : _currentState[gp] &= ~SC_BTN_UP;
(bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_DOWN : _currentState[gp] &= ~SC_BTN_DOWN;
(bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_LEFT : _currentState[gp] &= ~SC_BTN_LEFT;
(bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_RIGHT : _currentState[gp] &= ~SC_BTN_RIGHT;
(bitRead(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_B : _currentState[gp] &= ~SC_BTN_B;
(bitRead(*_pinInputs[gp][SC_PIN9_BIT], _bitInputs[gp][SC_PIN9_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_C : _currentState[gp] &= ~SC_BTN_C;
}
}
else // No Mega Drive controller is connected, use SMS/Atari mode
{
// Clear current state
_currentState[1] = 0;
_currentState[gp] = 0;
// Read input pins for Up, Down, Left, Right, Fire1, Fire2
if (bitRead(_inputReg3, DB9_PIN1_BIT2) == LOW) { _currentState[1] |= SC_BTN_UP; }
if (bitRead(_inputReg3, DB9_PIN2_BIT2) == LOW) { _currentState[1] |= SC_BTN_DOWN; }
if (bitRead(_inputReg3, DB9_PIN3_BIT2) == LOW) { _currentState[1] |= SC_BTN_LEFT; }
if (bitRead(_inputReg3, DB9_PIN4_BIT2) == LOW) { _currentState[1] |= SC_BTN_RIGHT; }
if (bitRead(_inputReg3, DB9_PIN6_BIT2) == LOW) { _currentState[1] |= SC_BTN_A; }
if (bitRead(_inputReg4, DB9_PIN9_BIT2) == LOW) { _currentState[1] |= SC_BTN_B; }
if (bitRead(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) { _currentState[gp] |= SC_BTN_UP; }
if (bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) { _currentState[gp] |= SC_BTN_DOWN; }
if (bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) { _currentState[gp] |= SC_BTN_LEFT; }
if (bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) { _currentState[gp] |= SC_BTN_RIGHT; }
if (bitRead(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) { _currentState[gp] |= SC_BTN_A; }
if (bitRead(*_pinInputs[gp][SC_PIN9_BIT], _bitInputs[gp][SC_PIN9_BIT]) == LOW) { _currentState[gp] |= SC_BTN_B; }
}
}
else // Select pin is LOW
{
// Check if a controller is connected
_connected[1] = (bitRead(_inputReg3, DB9_PIN3_BIT2) == LOW && bitRead(_inputReg3, DB9_PIN4_BIT2) == LOW);
_connected[gp] = (bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW && bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW);
// Check for six button mode
_sixButtonMode[1] = (bitRead(_inputReg3, DB9_PIN1_BIT2) == LOW && bitRead(_inputReg3, DB9_PIN2_BIT2) == LOW);
_sixButtonMode[gp] = (bitRead(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW && bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW);
// Read input pins for A and Start
if(_connected[1])
if(_connected[gp])
{
if(!_sixButtonMode[1])
if(!_sixButtonMode[gp])
{
(bitRead(_inputReg3, DB9_PIN6_BIT2) == LOW) ? _currentState[1] |= SC_BTN_A : _currentState[1] &= ~SC_BTN_A;
(bitRead(_inputReg4, DB9_PIN9_BIT2) == LOW) ? _currentState[1] |= SC_BTN_START : _currentState[1] &= ~SC_BTN_START;
(bitRead(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_A : _currentState[gp] &= ~SC_BTN_A;
(bitRead(*_pinInputs[gp][SC_PIN9_BIT], _bitInputs[gp][SC_PIN9_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_START : _currentState[gp] &= ~SC_BTN_START;
}
}
}
}
else
{
_ignoreCycles[1]--;
_ignoreCycles[gp]--;
}
return _currentState[1];
return _currentState[gp];
}

+ 30
- 23
SegaTwoControllersUSB/SegaControllers32U4.h View File

@ -30,21 +30,29 @@
enum
{
SC_CTL_ON = 1, // The controller is connected (not used)
SC_BTN_UP = 2,
SC_BTN_DOWN = 4,
SC_BTN_LEFT = 8,
SC_BTN_RIGHT = 16,
SC_BTN_A = 32,
SC_BTN_B = 64,
SC_BTN_C = 128,
SC_BTN_X = 256,
SC_BTN_Y = 512,
SC_BTN_Z = 1024,
SC_BTN_START = 2048,
SC_BTN_MODE = 4096,
SC_BTN_1 = 64, // Master System compatibility
SC_BTN_2 = 128, // Master System compatibility
SC_CTL_ON = 1, // The controller is connected (not used)
SC_BTN_UP = 2,
SC_BTN_DOWN = 4,
SC_BTN_LEFT = 8,
SC_BTN_RIGHT = 16,
SC_BTN_A = 32,
SC_BTN_B = 64,
SC_BTN_C = 128,
SC_BTN_X = 256,
SC_BTN_Y = 512,
SC_BTN_Z = 1024,
SC_BTN_START = 2048,
SC_BTN_MODE = 4096,
SC_BIT_UP = 1,
SC_BIT_DOWN = 2,
SC_BIT_LEFT = 3,
SC_BIT_RIGHT = 4,
SC_PIN1_BIT = 0,
SC_PIN2_BIT = 1,
SC_PIN3_BIT = 2,
SC_PIN4_BIT = 3,
SC_PIN6_BIT = 4,
SC_PIN9_BIT = 5,
DB9_PIN1_BIT1 = 7,
DB9_PIN2_BIT1 = 6,
DB9_PIN3_BIT1 = 5,
@ -59,20 +67,20 @@ enum
DB9_PIN9_BIT2 = 6
};
const byte SC_INPUT_PINS = 6;
const byte SC_CYCLE_DELAY = 10; // Delay (µs) between setting the select pin and reading the button pins
class SegaControllers32U4 {
public:
SegaControllers32U4(void);
word getStateMD1();
word getStateMD2();
word getStateMD(byte);
private:
word _currentState[2];
byte volatile * const _ddrSelect[2] = { &DDRE, &DDRC };
byte volatile * const _portSelect[2] = { &PORTE, &PORTC };
const byte _maskSelect[2] = {B01000000, B01000000};
boolean _pinSelect[2];
byte _ignoreCycles[2];
@ -80,10 +88,9 @@ class SegaControllers32U4 {
boolean _connected[2];
boolean _sixButtonMode[2];
byte _inputReg1;
byte _inputReg2;
byte _inputReg3;
byte _inputReg4;
byte volatile * const _pinInputs[2][7] = { {&PINF,&PINF,&PINF,&PINF,&PINB,&PINB}, {&PIND,&PIND,&PIND,&PIND,&PIND,&PIND} };
byte _bitInputs[2][7] = { {7,6,5,4,3,1}, {3,2,1,0,4,7} };
byte _inputReg[2];
};
#endif

+ 14
- 10
SegaTwoControllersUSB/SegaTwoControllersUSB.ino View File

@ -24,6 +24,10 @@
#include "SegaControllers32U4.h"
#include "Gamepad.h"
// ATT: 20 chars max (including NULL at the end) according to Arduino source code.
// Additionally serial number is used to differentiate arduino projects to have different button maps!
const char *gp_serial = "Sega/C= to USB";
// Controller DB9 pins (looking face-on to the end of the plug):
//
// 5 4 3 2 1
@ -38,7 +42,7 @@
// 3 A2 PF5
// 4 A3 PF4
// 6 14 PB3
// 7 6 PD7
// 7 7 PE6
// 9 15 PB1
// 1 TXO PD3
@ -47,7 +51,7 @@
// 4 3 PD0
// 6 4 PD4
// 7 5 PC6
// 9 7 PE6
// 9 6 PD7
SegaControllers32U4 controllers;
@ -61,16 +65,16 @@ word lastState[2] = {1,1};
void setup()
{
Gamepad[0].reset();
Gamepad[1].reset();
for(byte gp=0; gp<=1; gp++)
Gamepad[gp].reset();
}
void loop()
{
currentState[0] = controllers.getStateMD1();
sendState(0);
currentState[1] = controllers.getStateMD2();
sendState(1);
for(byte gp=0; gp<=1; gp++) {
currentState[gp] = controllers.getStateMD(gp);
sendState(gp);
}
}
void sendState(byte gp)
@ -79,8 +83,8 @@ void sendState(byte gp)
if (currentState[gp] != lastState[gp])
{
Gamepad[gp]._GamepadReport.buttons = currentState[gp] >> 5;
Gamepad[gp]._GamepadReport.Y = ((currentState[gp] & B00000100) >> 2) - ((currentState[gp] & B00000010) >> 1);
Gamepad[gp]._GamepadReport.X = ((currentState[gp] & B00010000) >> 4) - ((currentState[gp] & B00001000) >> 3);
Gamepad[gp]._GamepadReport.Y = ((currentState[gp] & SC_BTN_DOWN) >> SC_BIT_DOWN) - ((currentState[gp] & SC_BTN_UP) >> SC_BIT_UP);
Gamepad[gp]._GamepadReport.X = ((currentState[gp] & SC_BTN_RIGHT) >> SC_BIT_RIGHT) - ((currentState[gp] & SC_BTN_LEFT) >> SC_BIT_LEFT);
Gamepad[gp].send();
lastState[gp] = currentState[gp];
}


BIN
SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png View File

Before After
Width: 700  |  Height: 544  |  Size: 317 KiB Width: 700  |  Height: 544  |  Size: 316 KiB

Loading…
Cancel
Save