Sega adapters refactoring.
This commit is contained in:
parent
1015f20cd3
commit
0ee8aef8f0
|
@ -146,5 +146,10 @@ void Gamepad_::send()
|
||||||
|
|
||||||
uint8_t Gamepad_::getShortName(char *name)
|
uint8_t Gamepad_::getShortName(char *name)
|
||||||
{
|
{
|
||||||
|
if(!next)
|
||||||
|
{
|
||||||
|
strcpy(name, gp_serial);
|
||||||
|
return strlen(name);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "HID.h"
|
#include "HID.h"
|
||||||
|
|
||||||
|
extern const char* gp_serial;
|
||||||
|
|
||||||
// The numbers after colon are bit fields, meaning how many bits the field uses.
|
// The numbers after colon are bit fields, meaning how many bits the field uses.
|
||||||
// Remove those if there are problems
|
// Remove those if there are problems
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
|
|
||||||
SegaController32U4::SegaController32U4(void)
|
SegaController32U4::SegaController32U4(void)
|
||||||
{
|
{
|
||||||
// Setup select pin as output high (6, PD7)
|
// Setup select pin as output high (7, PE6)
|
||||||
DDRD |= B10000000; // output
|
DDR_SELECT |= MASK_SELECT; // output
|
||||||
PORTD |= B10000000; // high
|
PORT_SELECT |= MASK_SELECT; // high
|
||||||
|
|
||||||
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
|
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
|
||||||
DDRF &= ~B11110000; // input
|
DDRF &= ~B11110000; // input
|
||||||
|
@ -67,7 +67,7 @@ word SegaController32U4::getStateMD()
|
||||||
|
|
||||||
// Set the select pin low/high
|
// Set the select pin low/high
|
||||||
_pinSelect = !_pinSelect;
|
_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
|
// Short delay to stabilise outputs in controller
|
||||||
delayMicroseconds(SC_CYCLE_DELAY);
|
delayMicroseconds(SC_CYCLE_DELAY);
|
||||||
|
|
|
@ -28,6 +28,18 @@
|
||||||
#ifndef SegaController32U4_h
|
#ifndef SegaController32U4_h
|
||||||
#define 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
|
enum
|
||||||
{
|
{
|
||||||
SC_CTL_ON = 1, // The controller is connected (not used)
|
SC_CTL_ON = 1, // The controller is connected (not used)
|
||||||
|
@ -43,8 +55,10 @@ enum
|
||||||
SC_BTN_Z = 1024,
|
SC_BTN_Z = 1024,
|
||||||
SC_BTN_START = 2048,
|
SC_BTN_START = 2048,
|
||||||
SC_BTN_MODE = 4096,
|
SC_BTN_MODE = 4096,
|
||||||
SC_BTN_1 = 64, // Master System compatibility
|
SC_BIT_UP = 1,
|
||||||
SC_BTN_2 = 128, // Master System compatibility
|
SC_BIT_DOWN = 2,
|
||||||
|
SC_BIT_LEFT = 3,
|
||||||
|
SC_BIT_RIGHT = 4,
|
||||||
DB9_PIN1_BIT = 7,
|
DB9_PIN1_BIT = 7,
|
||||||
DB9_PIN2_BIT = 6,
|
DB9_PIN2_BIT = 6,
|
||||||
DB9_PIN3_BIT = 5,
|
DB9_PIN3_BIT = 5,
|
||||||
|
@ -53,8 +67,6 @@ enum
|
||||||
DB9_PIN9_BIT = 1
|
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
|
const byte SC_CYCLE_DELAY = 10; // Delay (µs) between setting the select pin and reading the button pins
|
||||||
|
|
||||||
class SegaController32U4 {
|
class SegaController32U4 {
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
#include "SegaController32U4.h"
|
#include "SegaController32U4.h"
|
||||||
#include "Gamepad.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):
|
// Controller DB9 pins (looking face-on to the end of the plug):
|
||||||
//
|
//
|
||||||
// 5 4 3 2 1
|
// 5 4 3 2 1
|
||||||
|
@ -38,7 +42,7 @@
|
||||||
// 3 A2 PF5
|
// 3 A2 PF5
|
||||||
// 4 A3 PF4
|
// 4 A3 PF4
|
||||||
// 6 14 PB3
|
// 6 14 PB3
|
||||||
// 7 6 PD7
|
// 7 7 PE6 (Used to be 6 PD7)
|
||||||
// 9 15 PB1
|
// 9 15 PB1
|
||||||
|
|
||||||
SegaController32U4 controller;
|
SegaController32U4 controller;
|
||||||
|
@ -67,8 +71,8 @@ void sendState()
|
||||||
if (currentState != lastState)
|
if (currentState != lastState)
|
||||||
{
|
{
|
||||||
Gamepad._GamepadReport.buttons = currentState >> 5;
|
Gamepad._GamepadReport.buttons = currentState >> 5;
|
||||||
Gamepad._GamepadReport.Y = ((currentState & B00000100) >> 2) - ((currentState & B00000010) >> 1);
|
Gamepad._GamepadReport.Y = ((currentState & SC_BTN_DOWN) >> SC_BIT_DOWN) - ((currentState & SC_BTN_UP) >> SC_BIT_UP);
|
||||||
Gamepad._GamepadReport.X = ((currentState & B00010000) >> 4) - ((currentState & B00001000) >> 3);
|
Gamepad._GamepadReport.X = ((currentState & SC_BTN_RIGHT) >> SC_BIT_RIGHT) - ((currentState & SC_BTN_LEFT) >> SC_BIT_LEFT);
|
||||||
Gamepad.send();
|
Gamepad.send();
|
||||||
lastState = currentState;
|
lastState = currentState;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
|
@ -24,8 +24,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Gamepad.h"
|
#include "Gamepad.h"
|
||||||
|
|
||||||
static const uint8_t _hidReportDescriptor[] PROGMEM = {
|
static const uint8_t _hidReportDescriptor[] PROGMEM = {
|
||||||
|
@ -146,5 +144,10 @@ void Gamepad_::send()
|
||||||
|
|
||||||
uint8_t Gamepad_::getShortName(char *name)
|
uint8_t Gamepad_::getShortName(char *name)
|
||||||
{
|
{
|
||||||
|
if(!next)
|
||||||
|
{
|
||||||
|
strcpy(name, gp_serial);
|
||||||
|
return strlen(name);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "HID.h"
|
#include "HID.h"
|
||||||
|
|
||||||
|
extern const char* gp_serial;
|
||||||
|
|
||||||
// The numbers after colon are bit fields, meaning how many bits the field uses.
|
// The numbers after colon are bit fields, meaning how many bits the field uses.
|
||||||
// Remove those if there are problems
|
// Remove those if there are problems
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -33,39 +33,29 @@
|
||||||
|
|
||||||
SegaControllers32U4::SegaControllers32U4(void)
|
SegaControllers32U4::SegaControllers32U4(void)
|
||||||
{
|
{
|
||||||
// Setup select pin as output high (6, PD7)
|
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
|
||||||
DDRD |= B10000000; // output
|
DDRF &= ~B11110000; // input
|
||||||
PORTD |= B10000000; // high
|
PORTF |= B11110000; // high to enable internal pull-up
|
||||||
// Setup select pin as output high (5, PC6)
|
DDRB &= ~B00001010; // input
|
||||||
DDRC |= B01000000; // output
|
PORTB |= B00001010; // high to enable internal pull-up
|
||||||
PORTC |= B01000000; // high
|
// Setup input pins (TXO,RXI,2,3,4,6 or PD3,PD2,PD1,PD0,PD4,PE6)
|
||||||
|
DDRD &= ~B10011111; // input
|
||||||
// Setup input pins (A0,A1,A2,A3,14,15 or PF7,PF6,PF5,PF4,PB3,PB1)
|
PORTD |= B10011111; // high to enable internal pull-up
|
||||||
DDRF &= ~B11110000; // input
|
|
||||||
PORTF |= B11110000; // high to enable internal pull-up
|
for(byte i=0; i<=1; i++)
|
||||||
DDRB &= ~B00001010; // input
|
{
|
||||||
PORTB |= B00001010; // high to enable internal pull-up
|
*_ddrSelect[i] |= _maskSelect[i]; // Select pins as output
|
||||||
// Setup input pins (TXO,RXI,2,3,4,6 or PD3,PD2,PD1,PD0,PD4,PE6)
|
*_portSelect[i] |= _maskSelect[i]; // Select pins high
|
||||||
DDRD &= ~B00011111; // input
|
_inputReg[i] = 0;
|
||||||
PORTD |= B00011111; // high to enable internal pull-up
|
_currentState[i] = 0;
|
||||||
DDRE &= ~B01000000; // input
|
_connected[i] = 0;
|
||||||
PORTE |= B01000000; // high to enable internal pull-up
|
_sixButtonMode[i] = false;
|
||||||
|
_ignoreCycles[i] = 0;
|
||||||
_inputReg1 = 0;
|
_pinSelect[i] = true;
|
||||||
_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
word SegaControllers32U4::getStateMD1()
|
word SegaControllers32U4::getStateMD(byte gp)
|
||||||
{
|
{
|
||||||
// "Normal" Six button controller reading routine, done a bit differently in this project
|
// "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
|
// Cycle TH out TR in TL in D3 in D2 in D1 in D0 in
|
||||||
|
@ -79,163 +69,81 @@ word SegaControllers32U4::getStateMD1()
|
||||||
// 7 HI --- --- --- --- --- ---
|
// 7 HI --- --- --- --- --- ---
|
||||||
|
|
||||||
// Set the select pin low/high
|
// Set the select pin low/high
|
||||||
_pinSelect[0] = !_pinSelect[0];
|
_pinSelect[gp] = !_pinSelect[gp];
|
||||||
(!_pinSelect[0]) ? PORTD &= ~B10000000 : PORTD |= B10000000; // Set LOW on even cycle, HIGH on uneven cycle
|
(!_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
|
// Short delay to stabilise outputs in controller
|
||||||
delayMicroseconds(SC_CYCLE_DELAY);
|
delayMicroseconds(SC_CYCLE_DELAY);
|
||||||
|
|
||||||
// Read input register(s)
|
// Read input register(s)
|
||||||
_inputReg1 = PINF;
|
_inputReg[0] = *_pinInputs[gp][0];
|
||||||
_inputReg2 = PINB;
|
_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
|
// Check if six button mode is active
|
||||||
if(_sixButtonMode[0])
|
if(_sixButtonMode[gp])
|
||||||
{
|
{
|
||||||
// Read input pins for X, Y, Z, Mode
|
// 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(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_Z : _currentState[gp] &= ~SC_BTN_Z;
|
||||||
(bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) ? _currentState[0] |= SC_BTN_Y : _currentState[0] &= ~SC_BTN_Y;
|
(bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_Y : _currentState[gp] &= ~SC_BTN_Y;
|
||||||
(bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) ? _currentState[0] |= SC_BTN_X : _currentState[0] &= ~SC_BTN_X;
|
(bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_X : _currentState[gp] &= ~SC_BTN_X;
|
||||||
(bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) ? _currentState[0] |= SC_BTN_MODE : _currentState[0] &= ~SC_BTN_MODE;
|
(bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_MODE : _currentState[gp] &= ~SC_BTN_MODE;
|
||||||
_sixButtonMode[0] = false;
|
_sixButtonMode[gp] = false;
|
||||||
_ignoreCycles[0] = 2; // Ignore the two next cycles (cycles 6 and 7 in table above)
|
_ignoreCycles[gp] = 2; // Ignore the two next cycles (cycles 6 and 7 in table above)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read input pins for Up, Down, Left, Right, B, C
|
// 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(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_UP : _currentState[gp] &= ~SC_BTN_UP;
|
||||||
(bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) ? _currentState[0] |= SC_BTN_DOWN : _currentState[0] &= ~SC_BTN_DOWN;
|
(bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_DOWN : _currentState[gp] &= ~SC_BTN_DOWN;
|
||||||
(bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) ? _currentState[0] |= SC_BTN_LEFT : _currentState[0] &= ~SC_BTN_LEFT;
|
(bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_LEFT : _currentState[gp] &= ~SC_BTN_LEFT;
|
||||||
(bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) ? _currentState[0] |= SC_BTN_RIGHT : _currentState[0] &= ~SC_BTN_RIGHT;
|
(bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_RIGHT : _currentState[gp] &= ~SC_BTN_RIGHT;
|
||||||
(bitRead(_inputReg2, DB9_PIN6_BIT1) == LOW) ? _currentState[0] |= SC_BTN_B : _currentState[0] &= ~SC_BTN_B;
|
(bitRead(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_B : _currentState[gp] &= ~SC_BTN_B;
|
||||||
(bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) ? _currentState[0] |= SC_BTN_C : _currentState[0] &= ~SC_BTN_C;
|
(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
|
else // No Mega Drive controller is connected, use SMS/Atari mode
|
||||||
{
|
{
|
||||||
// Clear current state
|
// Clear current state
|
||||||
_currentState[0] = 0;
|
_currentState[gp] = 0;
|
||||||
|
|
||||||
// Read input pins for Up, Down, Left, Right, Fire1, Fire2
|
// Read input pins for Up, Down, Left, Right, Fire1, Fire2
|
||||||
if (bitRead(_inputReg1, DB9_PIN1_BIT1) == LOW) { _currentState[0] |= SC_BTN_UP; }
|
if (bitRead(*_pinInputs[gp][SC_PIN1_BIT], _bitInputs[gp][SC_PIN1_BIT]) == LOW) { _currentState[gp] |= SC_BTN_UP; }
|
||||||
if (bitRead(_inputReg1, DB9_PIN2_BIT1) == LOW) { _currentState[0] |= SC_BTN_DOWN; }
|
if (bitRead(*_pinInputs[gp][SC_PIN2_BIT], _bitInputs[gp][SC_PIN2_BIT]) == LOW) { _currentState[gp] |= SC_BTN_DOWN; }
|
||||||
if (bitRead(_inputReg1, DB9_PIN3_BIT1) == LOW) { _currentState[0] |= SC_BTN_LEFT; }
|
if (bitRead(*_pinInputs[gp][SC_PIN3_BIT], _bitInputs[gp][SC_PIN3_BIT]) == LOW) { _currentState[gp] |= SC_BTN_LEFT; }
|
||||||
if (bitRead(_inputReg1, DB9_PIN4_BIT1) == LOW) { _currentState[0] |= SC_BTN_RIGHT; }
|
if (bitRead(*_pinInputs[gp][SC_PIN4_BIT], _bitInputs[gp][SC_PIN4_BIT]) == LOW) { _currentState[gp] |= SC_BTN_RIGHT; }
|
||||||
if (bitRead(_inputReg2, DB9_PIN6_BIT1) == LOW) { _currentState[0] |= SC_BTN_A; }
|
if (bitRead(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) { _currentState[gp] |= SC_BTN_A; }
|
||||||
if (bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) { _currentState[0] |= SC_BTN_B; }
|
if (bitRead(*_pinInputs[gp][SC_PIN9_BIT], _bitInputs[gp][SC_PIN9_BIT]) == LOW) { _currentState[gp] |= SC_BTN_B; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Select pin is LOW
|
else // Select pin is LOW
|
||||||
{
|
{
|
||||||
// Check if a controller is connected
|
// 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
|
// 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
|
// 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(*_pinInputs[gp][SC_PIN6_BIT], _bitInputs[gp][SC_PIN6_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_A : _currentState[gp] &= ~SC_BTN_A;
|
||||||
(bitRead(_inputReg2, DB9_PIN9_BIT1) == LOW) ? _currentState[0] |= SC_BTN_START : _currentState[0] &= ~SC_BTN_START;
|
(bitRead(*_pinInputs[gp][SC_PIN9_BIT], _bitInputs[gp][SC_PIN9_BIT]) == LOW) ? _currentState[gp] |= SC_BTN_START : _currentState[gp] &= ~SC_BTN_START;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ignoreCycles[0]--;
|
_ignoreCycles[gp]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _currentState[0];
|
return _currentState[gp];
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,21 +30,29 @@
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SC_CTL_ON = 1, // The controller is connected (not used)
|
SC_CTL_ON = 1, // The controller is connected (not used)
|
||||||
SC_BTN_UP = 2,
|
SC_BTN_UP = 2,
|
||||||
SC_BTN_DOWN = 4,
|
SC_BTN_DOWN = 4,
|
||||||
SC_BTN_LEFT = 8,
|
SC_BTN_LEFT = 8,
|
||||||
SC_BTN_RIGHT = 16,
|
SC_BTN_RIGHT = 16,
|
||||||
SC_BTN_A = 32,
|
SC_BTN_A = 32,
|
||||||
SC_BTN_B = 64,
|
SC_BTN_B = 64,
|
||||||
SC_BTN_C = 128,
|
SC_BTN_C = 128,
|
||||||
SC_BTN_X = 256,
|
SC_BTN_X = 256,
|
||||||
SC_BTN_Y = 512,
|
SC_BTN_Y = 512,
|
||||||
SC_BTN_Z = 1024,
|
SC_BTN_Z = 1024,
|
||||||
SC_BTN_START = 2048,
|
SC_BTN_START = 2048,
|
||||||
SC_BTN_MODE = 4096,
|
SC_BTN_MODE = 4096,
|
||||||
SC_BTN_1 = 64, // Master System compatibility
|
SC_BIT_UP = 1,
|
||||||
SC_BTN_2 = 128, // Master System compatibility
|
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_PIN1_BIT1 = 7,
|
||||||
DB9_PIN2_BIT1 = 6,
|
DB9_PIN2_BIT1 = 6,
|
||||||
DB9_PIN3_BIT1 = 5,
|
DB9_PIN3_BIT1 = 5,
|
||||||
|
@ -59,20 +67,20 @@ enum
|
||||||
DB9_PIN9_BIT2 = 6
|
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
|
const byte SC_CYCLE_DELAY = 10; // Delay (µs) between setting the select pin and reading the button pins
|
||||||
|
|
||||||
class SegaControllers32U4 {
|
class SegaControllers32U4 {
|
||||||
public:
|
public:
|
||||||
SegaControllers32U4(void);
|
SegaControllers32U4(void);
|
||||||
|
|
||||||
word getStateMD1();
|
word getStateMD(byte);
|
||||||
word getStateMD2();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
word _currentState[2];
|
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];
|
boolean _pinSelect[2];
|
||||||
|
|
||||||
byte _ignoreCycles[2];
|
byte _ignoreCycles[2];
|
||||||
|
@ -80,10 +88,9 @@ class SegaControllers32U4 {
|
||||||
boolean _connected[2];
|
boolean _connected[2];
|
||||||
boolean _sixButtonMode[2];
|
boolean _sixButtonMode[2];
|
||||||
|
|
||||||
byte _inputReg1;
|
byte volatile * const _pinInputs[2][7] = { {&PINF,&PINF,&PINF,&PINF,&PINB,&PINB}, {&PIND,&PIND,&PIND,&PIND,&PIND,&PIND} };
|
||||||
byte _inputReg2;
|
byte _bitInputs[2][7] = { {7,6,5,4,3,1}, {3,2,1,0,4,7} };
|
||||||
byte _inputReg3;
|
byte _inputReg[2];
|
||||||
byte _inputReg4;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
#include "SegaControllers32U4.h"
|
#include "SegaControllers32U4.h"
|
||||||
#include "Gamepad.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):
|
// Controller DB9 pins (looking face-on to the end of the plug):
|
||||||
//
|
//
|
||||||
// 5 4 3 2 1
|
// 5 4 3 2 1
|
||||||
|
@ -38,7 +42,7 @@
|
||||||
// 3 A2 PF5
|
// 3 A2 PF5
|
||||||
// 4 A3 PF4
|
// 4 A3 PF4
|
||||||
// 6 14 PB3
|
// 6 14 PB3
|
||||||
// 7 6 PD7
|
// 7 7 PE6
|
||||||
// 9 15 PB1
|
// 9 15 PB1
|
||||||
|
|
||||||
// 1 TXO PD3
|
// 1 TXO PD3
|
||||||
|
@ -47,7 +51,7 @@
|
||||||
// 4 3 PD0
|
// 4 3 PD0
|
||||||
// 6 4 PD4
|
// 6 4 PD4
|
||||||
// 7 5 PC6
|
// 7 5 PC6
|
||||||
// 9 7 PE6
|
// 9 6 PD7
|
||||||
|
|
||||||
SegaControllers32U4 controllers;
|
SegaControllers32U4 controllers;
|
||||||
|
|
||||||
|
@ -61,16 +65,16 @@ word lastState[2] = {1,1};
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Gamepad[0].reset();
|
for(byte gp=0; gp<=1; gp++)
|
||||||
Gamepad[1].reset();
|
Gamepad[gp].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
currentState[0] = controllers.getStateMD1();
|
for(byte gp=0; gp<=1; gp++) {
|
||||||
sendState(0);
|
currentState[gp] = controllers.getStateMD(gp);
|
||||||
currentState[1] = controllers.getStateMD2();
|
sendState(gp);
|
||||||
sendState(1);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendState(byte gp)
|
void sendState(byte gp)
|
||||||
|
@ -79,8 +83,8 @@ void sendState(byte gp)
|
||||||
if (currentState[gp] != lastState[gp])
|
if (currentState[gp] != lastState[gp])
|
||||||
{
|
{
|
||||||
Gamepad[gp]._GamepadReport.buttons = currentState[gp] >> 5;
|
Gamepad[gp]._GamepadReport.buttons = currentState[gp] >> 5;
|
||||||
Gamepad[gp]._GamepadReport.Y = ((currentState[gp] & B00000100) >> 2) - ((currentState[gp] & B00000010) >> 1);
|
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] & B00010000) >> 4) - ((currentState[gp] & B00001000) >> 3);
|
Gamepad[gp]._GamepadReport.X = ((currentState[gp] & SC_BTN_RIGHT) >> SC_BIT_RIGHT) - ((currentState[gp] & SC_BTN_LEFT) >> SC_BIT_LEFT);
|
||||||
Gamepad[gp].send();
|
Gamepad[gp].send();
|
||||||
lastState[gp] = currentState[gp];
|
lastState[gp] = currentState[gp];
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 316 KiB |
Loading…
Reference in New Issue