diff --git a/SegaControllerUSB/Gamepad.cpp b/SegaControllerUSB/Gamepad.cpp index eddab2b..8eef31d 100644 --- a/SegaControllerUSB/Gamepad.cpp +++ b/SegaControllerUSB/Gamepad.cpp @@ -146,5 +146,10 @@ void Gamepad_::send() uint8_t Gamepad_::getShortName(char *name) { + if(!next) + { + strcpy(name, gp_serial); + return strlen(name); + } return 0; } diff --git a/SegaControllerUSB/Gamepad.h b/SegaControllerUSB/Gamepad.h index a39ebdc..d2bd4c0 100644 --- a/SegaControllerUSB/Gamepad.h +++ b/SegaControllerUSB/Gamepad.h @@ -29,6 +29,8 @@ #include #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 { diff --git a/SegaControllerUSB/SegaController32U4.cpp b/SegaControllerUSB/SegaController32U4.cpp index 754fc4e..1937869 100644 --- a/SegaControllerUSB/SegaController32U4.cpp +++ b/SegaControllerUSB/SegaController32U4.cpp @@ -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); diff --git a/SegaControllerUSB/SegaController32U4.h b/SegaControllerUSB/SegaController32U4.h index 3954b39..e02684f 100644 --- a/SegaControllerUSB/SegaController32U4.h +++ b/SegaControllerUSB/SegaController32U4.h @@ -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 { diff --git a/SegaControllerUSB/SegaControllerUSB.ino b/SegaControllerUSB/SegaControllerUSB.ino index d318d5e..d2081e4 100644 --- a/SegaControllerUSB/SegaControllerUSB.ino +++ b/SegaControllerUSB/SegaControllerUSB.ino @@ -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; } diff --git a/SegaControllerUSB/images/sega-usb-adapter-wiring.png b/SegaControllerUSB/images/sega-usb-adapter-wiring.png index ee21349..deb1dd5 100644 Binary files a/SegaControllerUSB/images/sega-usb-adapter-wiring.png and b/SegaControllerUSB/images/sega-usb-adapter-wiring.png differ diff --git a/SegaTwoControllersUSB/Gamepad.cpp b/SegaTwoControllersUSB/Gamepad.cpp index eddab2b..879fe2f 100644 --- a/SegaTwoControllersUSB/Gamepad.cpp +++ b/SegaTwoControllersUSB/Gamepad.cpp @@ -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; } diff --git a/SegaTwoControllersUSB/Gamepad.h b/SegaTwoControllersUSB/Gamepad.h index a39ebdc..d2bd4c0 100644 --- a/SegaTwoControllersUSB/Gamepad.h +++ b/SegaTwoControllersUSB/Gamepad.h @@ -29,6 +29,8 @@ #include #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 { diff --git a/SegaTwoControllersUSB/SegaControllers32U4.cpp b/SegaTwoControllersUSB/SegaControllers32U4.cpp index 958f0b5..1c26e21 100644 --- a/SegaTwoControllersUSB/SegaControllers32U4.cpp +++ b/SegaTwoControllersUSB/SegaControllers32U4.cpp @@ -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 + _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) - _inputReg1 = PINF; - _inputReg2 = PINB; + _inputReg[0] = *_pinInputs[gp][0]; + _inputReg[1] = *_pinInputs[gp][1]; - if(_ignoreCycles[0] <= 0) + if(_ignoreCycles[gp] <= 0) { - if(_pinSelect[0]) // Select pin is HIGH + if(_pinSelect[gp]) // Select pin is HIGH { - if(_connected[0]) + if(_connected[gp]) { // Check if six button mode is active - if(_sixButtonMode[0]) + if(_sixButtonMode[gp]) { // 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) + (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(_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; + (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[0] = 0; + _currentState[gp] = 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; } + 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[0] = (bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW && bitRead(_inputReg1, DB9_PIN4_BIT1) == 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[0] = (bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW && bitRead(_inputReg1, DB9_PIN2_BIT1) == 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[0]) + if(_connected[gp]) { - if(!_sixButtonMode[0]) + if(!_sixButtonMode[gp]) { - (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; + (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[0]--; + _ignoreCycles[gp]--; } - 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 - - // Short delay to stabilise outputs in controller - delayMicroseconds(SC_CYCLE_DELAY); - - // Read input register(s) - _inputReg3 = PIND; - _inputReg4 = PINE; - - if(_ignoreCycles[1] <= 0) - { - if(_pinSelect[1]) // Select pin is HIGH - { - if(_connected[1]) - { - // Check if six button mode is active - if(_sixButtonMode[1]) - { - // 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) - } - 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; - } - } - else // No Mega Drive controller is connected, use SMS/Atari mode - { - // Clear current state - _currentState[1] = 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; } - } - } - 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); - - // Check for six button mode - _sixButtonMode[1] = (bitRead(_inputReg3, DB9_PIN1_BIT2) == LOW && bitRead(_inputReg3, DB9_PIN2_BIT2) == LOW); - - // Read input pins for A and Start - if(_connected[1]) - { - if(!_sixButtonMode[1]) - { - (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; - } - } - } - } - else - { - _ignoreCycles[1]--; - } - - return _currentState[1]; + return _currentState[gp]; } diff --git a/SegaTwoControllersUSB/SegaControllers32U4.h b/SegaTwoControllersUSB/SegaControllers32U4.h index f585303..a26bf58 100644 --- a/SegaTwoControllersUSB/SegaControllers32U4.h +++ b/SegaTwoControllersUSB/SegaControllers32U4.h @@ -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 diff --git a/SegaTwoControllersUSB/SegaTwoControllersUSB.ino b/SegaTwoControllersUSB/SegaTwoControllersUSB.ino index d1e7775..51f4e9c 100644 --- a/SegaTwoControllersUSB/SegaTwoControllersUSB.ino +++ b/SegaTwoControllersUSB/SegaTwoControllersUSB.ino @@ -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]; } diff --git a/SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png b/SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png index e0a0331..39c36d6 100644 Binary files a/SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png and b/SegaTwoControllersUSB/images/sega-usb-2x-adapter-wiring.png differ