├── Fritzing └── Classic Controller to USB Adapter.fzz ├── LICENSE ├── README.md ├── libraries └── ClassicController │ ├── ClassicController.h │ └── ClassicController.cpp └── ClassicJoystickAdaptor └── ClassicJoystickAdaptor.ino /Fritzing/Classic Controller to USB Adapter.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MHeironimus/ClassicJoystickAdaptor/HEAD/Fritzing/Classic Controller to USB Adapter.fzz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Matthew Heironimus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ultimate Classic Game Console Joystick USB Adaptor (ClassicJoystickAdaptor) 2 | #### Version 1.0.0 3 | Software for the Arduino Leonardo and Arduino Micro that allow these devices to become USB adaptors for classic game console joysticks (e.g. Atari 2600, ColecoVision, and Coleco ADAM game controllers). 4 | ## Arduino IDE Version 1.6.5 and earlier 5 | For Arduino IDE Version 1.6.5 or earlier, please use the Arduino-1.6.5 branch. I do not plan on making future enhancements to this branch, but I have left it available for reference and people who are still using the Arduino IDE verstion 1.6.5 or earlier. 6 | ## Arduino IDE Version 1.6.6 or later 7 | For Arduino IDE Version 1.6.6 or later, please use the main branch. This is the branch that will see future updates. 8 | ## Dependencies 9 | ### Arduino Joystick Library 10 | This Arduino sketch file depends on Version 1.0 of the [Arduino Joystick Library](http://mheironimus.blogspot.com/2015/11/arduino-joystick-library.html) which can be found on GitHub at [MHeironimus/ArduinoJoystickLibrary](https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-1.0). 11 | ### Classic Controller Library 12 | It also depends on the Classic Controller Library, which can be found in this GitHub repository at /source/libraries/ClassicController. 13 | ## Hardware - Building Your Own Adapter 14 | Please see the [Ultimate Classic Game Console Joystick to USB Adapter](http://mheironimus.blogspot.com/2015/12/ultimate-classic-game-console-joystick.html) blog posting or the [Ultimate Classic Game Console Joystick to USB Adapter](http://www.instructables.com/id/Ultimate-Classic-Game-Console-Joystick-to-USB-Adap/) Instructable for details on how to build your own Ultimate Classic Game Console Joystick USB Adaptor. 15 | 16 | 17 | -------------------------------------------------------------------------------- /libraries/ClassicController/ClassicController.h: -------------------------------------------------------------------------------- 1 | /* 2 | ClassicController.h - Library for reading a classic controller 3 | (e.g. ColecoVision, Coleco ADAM, Atari, etc.) and emulating a keyboard, 4 | USB joystict, etc. 5 | Created by Matthew Heironimus, 04/27/2015. 6 | */ 7 | #ifndef ClassicController_h 8 | #define ClassicController_h 9 | 10 | #include 11 | #include 12 | 13 | // Define special keyboard keys not defined in Keyboard library. 14 | #define KEY_NUMPAD_DIVIDE 0xDC 15 | #define KEY_NUMPAD_MULTIPLY 0xDD 16 | #define KEY_NUMPAD_MINUS 0xDE 17 | #define KEY_NUMPAD_PLUS 0xDF 18 | #define KEY_NUMPAD_ENTER 0xE0 19 | #define KEY_NUMPAD_1 0xE1 20 | #define KEY_NUMPAD_2 0xE2 21 | #define KEY_NUMPAD_3 0xE3 22 | #define KEY_NUMPAD_4 0xE4 23 | #define KEY_NUMPAD_5 0xE5 24 | #define KEY_NUMPAD_6 0xE6 25 | #define KEY_NUMPAD_7 0xE7 26 | #define KEY_NUMPAD_8 0xE8 27 | #define KEY_NUMPAD_9 0xE9 28 | #define KEY_NUMPAD_0 0xEA 29 | #define KEY_NUMPAD_DEL 0xEB 30 | 31 | // Constants 32 | const int NOT_USED = -1; 33 | 34 | class ClassicController 35 | { 36 | private: 37 | // Controller Pins 38 | int _firePin; 39 | int _upPin; 40 | int _downPin; 41 | int _leftPin; 42 | int _rightPin; 43 | int _keypadModePin; 44 | int _directionModePin; 45 | int _bit0Pin; 46 | int _bit1Pin; 47 | int _bit2Pin; 48 | int _bit3Pin; 49 | int _spinnerAPin; 50 | int _spinnerBPin; 51 | 52 | // Pin Read Value Counters 53 | unsigned int _leftFireCount; 54 | unsigned int _rightFireCount; 55 | unsigned int _upCount; 56 | unsigned int _downCount; 57 | unsigned int _leftCount; 58 | unsigned int _rightCount; 59 | unsigned int _bit0Count; 60 | unsigned int _bit1Count; 61 | unsigned int _bit2Count; 62 | unsigned int _bit3Count; 63 | 64 | // Pin Values 65 | bool _leftFire; 66 | bool _rightFire; 67 | bool _up; 68 | bool _down; 69 | bool _left; 70 | bool _right; 71 | bool _bit0; 72 | bool _bit1; 73 | bool _bit2; 74 | bool _bit3; 75 | 76 | // Special Values 77 | int _keypadCode; 78 | char _keypadValue; 79 | bool _purpleFire; 80 | bool _blueFire; 81 | 82 | // Previous Pin Values 83 | bool _lastLeftFire; 84 | bool _lastRightFire; 85 | bool _lastUp; 86 | bool _lastDown; 87 | bool _lastLeft; 88 | bool _lastRight; 89 | bool _lastBit0; 90 | bool _lastBit1; 91 | bool _lastBit2; 92 | bool _lastBit3; 93 | 94 | // Previous Special Values 95 | int _lastKeypadCode; 96 | char _lastKeypadValue; 97 | bool _lastPurpleFire; 98 | bool _lastBlueFire; 99 | 100 | // Joystick Button Mappings 101 | int _leftFireButton; 102 | int _rightFireButton; 103 | int _purpleFireButton; 104 | int _blueFireButton; 105 | 106 | // Joystick Button Keyboard Mappings 107 | char _leftFireKey; 108 | char _rightFireKey; 109 | char _purpleFireKey; 110 | char _blueFireKey; 111 | 112 | // Direction Keyboard Mappings 113 | char _upKey; 114 | char _downKey; 115 | char _leftKey; 116 | char _rightKey; 117 | 118 | // Keypad Button Mappings 119 | int _keypadButtons[16] = { 120 | NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, 121 | NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED 122 | }; 123 | 124 | // Keypad Keyboard Mappings 125 | char _keypadKeys[16] = { 126 | 0, 0, 0, 0, 0, 0, 0, 0, 127 | 0, 0, 0, 0, 0, 0, 0, 0 128 | }; 129 | 130 | int _joystickIndex; 131 | unsigned int _readCount; 132 | 133 | // Mode Variables 134 | bool _directionJoystickMode; 135 | bool _fireJoystickMode; 136 | bool _extraFireJoystickMode; 137 | bool _keypadJoystickMode; 138 | 139 | // Private: Constants 140 | const int _cModeDelayMicroseconds = 50; 141 | const unsigned int _cPinLowThreashold = 5; 142 | const char _cKeypadCodeTable[16] = { 143 | 0, '6', '1', '3', '9', '0', '*', 0, 144 | '2', '#', '7', 0, '5', '4', '8', 0 }; 145 | 146 | // Private: Methods 147 | void determineAllPinValues(); 148 | void determineSpecialValues(); 149 | bool setDirectionJoystickState(); 150 | void sendDirectionKeyboardStateToHost(); 151 | bool setFireJoystickState(); 152 | void sendFireKeyboardStateToHost(); 153 | bool setExtraFireJoystickState(); 154 | void sendExtraFireKeyboardStateToHost(); 155 | bool setKeypadJoystickState(); 156 | void sendKeypadKeyboardStateToHost(); 157 | void sendLineStateToHost(bool lastState, bool currentState, char keyUsedForLine); 158 | 159 | inline unsigned int readControllerPin(int pin) { return (digitalRead(pin) == LOW); } 160 | inline bool determinePinValue(unsigned int pinLowCount) { return (pinLowCount >= _cPinLowThreashold); } 161 | 162 | public: 163 | ClassicController( 164 | int joystickIndex, 165 | int pin1Up, 166 | int pin2Down, 167 | int pin3Left, 168 | int pin4Right, 169 | int pin5KeypadMode, 170 | int pin6FireButton, 171 | int pin7SpinnerA, 172 | int pin8DirectionMode, 173 | int pin9SpinnerB); 174 | 175 | void startReadController(); 176 | void readControllerKeypad(); 177 | void readControllerDirection(); 178 | void writeToHost(); 179 | 180 | // The classic controller's direction values are emulated using the USB Joystick. 181 | void setDirectionJoystickMode(); 182 | 183 | // The classic controller's direction values are emulated using the specified keyboard keys. 184 | void setDirectionKeyboardMode(char upKey = KEY_UP_ARROW, char downKey = KEY_DOWN_ARROW, char leftKey = KEY_LEFT_ARROW, char rightKey = KEY_RIGHT_ARROW); 185 | 186 | void setFireJoystickMode(int leftFireButton = 0, int rightfireButton = 1); 187 | void setFireKeyboardMode(char leftFireKey = KEY_LEFT_ALT, char rightFireKey = KEY_LEFT_CTRL); 188 | void setExtraFireJoystickMode(int purpleFireButton = 2, int blueFireButton = 3); 189 | void setExtraFireKeyboardMode(char purpleFireKey = KEY_NUMPAD_MINUS, char blueFireKey = KEY_NUMPAD_PLUS); 190 | void setKeypadJoystickMode(int oneButton = 4, int twoButton = 5, int threeButton = 6, 191 | int fourButton = 7, int fiveButton = 8, int sixButton = 9, 192 | int sevenButton = 10, int eightButton = 11, int nineButton = 12, 193 | int asteriskButton = 13, int zeroButton = 14, int poundButton = 15); 194 | void setKeypadKeyboardMode(char oneKey = KEY_NUMPAD_1, char twoKey = KEY_NUMPAD_2, char threeKey = KEY_NUMPAD_3, 195 | char fourKey = KEY_NUMPAD_4, char fiveKey = KEY_NUMPAD_5, char sixKey = KEY_NUMPAD_6, 196 | char sevenKey = KEY_NUMPAD_7, char eightKey = KEY_NUMPAD_8, char nineKey = KEY_NUMPAD_9, 197 | char asteriskKey = KEY_NUMPAD_DEL, char zeroKey = KEY_NUMPAD_0, char poundKey = KEY_NUMPAD_ENTER); 198 | 199 | inline bool getUp() { return _lastUp; } 200 | inline bool getDown() { return _lastDown; } 201 | inline bool getLeft() { return _lastLeft; } 202 | inline bool getRight() { return _lastRight; } 203 | inline bool getLeftFire() { return _lastLeftFire; } 204 | inline bool getRightFire() { return _lastRightFire; } 205 | inline bool getPurpleFire() { return _lastPurpleFire; } 206 | inline bool getBlueFire() { return _lastBlueFire; } 207 | inline char getKeypad() { return _cKeypadCodeTable[_lastKeypadCode]; } 208 | }; 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /ClassicJoystickAdaptor/ClassicJoystickAdaptor.ino: -------------------------------------------------------------------------------- 1 | // Ultimate Classic Game Console Joystick USB Adaptor 2 | // Supports ColecoVision / ADAM Joysticks and Atari 2600 Joysticks. 3 | // For the Arduino Leonardo or Arduino Micro 4 | // 2015-05-23 5 | //---------------------------------------------------------------------------------- 6 | 7 | #include 8 | 9 | #define JOYSTICK_COUNT 3 10 | 11 | // Emulator Modes 12 | const int gcModeAdamEm = 0; 13 | const int gcModeMame = 1; 14 | const int gcModeJoystickOnly = 2; 15 | const int gcModeMax = 2; 16 | int gCurrentMode; 17 | 18 | // Emulator Mode Toggle Pin 19 | const int gcModePin = 9; 20 | 21 | // Joystick Pins 22 | const int gcFirePin = 6; 23 | const int gcUpPin = 2; 24 | const int gcDownPin = 3; 25 | const int gcLeftPin = 4; 26 | const int gcRightPin = 5; 27 | const int gcSpinnerAPin = 7; 28 | const int gcSpinnerBPin = 8; 29 | const int gcModeAPin[JOYSTICK_COUNT] = { A0, A2, A4 }; 30 | const int gcModeBPin[JOYSTICK_COUNT] = { A1, A3, A5 }; 31 | 32 | // Monitor Pins 33 | const int gcFireMonitorPin = 13; 34 | const int gcJoystickOnlyModePin = 12; 35 | const int gcMameModePin = 11; 36 | const int gcAdamEmModePin = 10; 37 | 38 | // Configure Classic Controller 39 | ClassicController gController[JOYSTICK_COUNT] = { 40 | ClassicController(0, 41 | gcUpPin, 42 | gcDownPin, 43 | gcLeftPin, 44 | gcRightPin, 45 | gcModeAPin[0], 46 | gcFirePin, 47 | gcSpinnerAPin, 48 | gcModeBPin[0], 49 | gcSpinnerBPin), 50 | ClassicController(1, 51 | gcUpPin, 52 | gcDownPin, 53 | gcLeftPin, 54 | gcRightPin, 55 | gcModeAPin[1], 56 | gcFirePin, 57 | gcSpinnerAPin, 58 | gcModeBPin[1], 59 | gcSpinnerBPin), 60 | ClassicController(2, 61 | gcUpPin, 62 | gcDownPin, 63 | gcLeftPin, 64 | gcRightPin, 65 | gcModeAPin[2], 66 | gcFirePin, 67 | gcSpinnerAPin, 68 | gcModeBPin[2], 69 | gcSpinnerBPin) 70 | }; 71 | 72 | // Frame Variables 73 | const int gcFrameLength = 10; 74 | unsigned long gNextFrameStart = 0; 75 | unsigned int gLoopsPerFrame = 0; 76 | 77 | // Shows the status of the joystick. 78 | void ShowJoystickStatus() 79 | { 80 | 81 | // Debug Information 82 | //Serial.print("Loops per Frame: "); 83 | //Serial.print(gLoopsPerFrame); 84 | //Serial.println(); 85 | //Serial.print("Keypad #3: "); 86 | //Serial.println(gController[2].getKeypad()); 87 | 88 | digitalWrite(gcFireMonitorPin, gController[0].getLeftFire()); 89 | } 90 | 91 | void DisplayEmulatorMode(int modeToDisplay) 92 | { 93 | gCurrentMode = modeToDisplay; 94 | digitalWrite(gcJoystickOnlyModePin, (modeToDisplay == gcModeJoystickOnly)); 95 | digitalWrite(gcAdamEmModePin, (modeToDisplay == gcModeAdamEm)); 96 | digitalWrite(gcMameModePin, (modeToDisplay == gcModeMame)); 97 | } 98 | 99 | void SetupJoystickOnlyMode() 100 | { 101 | for (int index = 0; index < JOYSTICK_COUNT; index++) 102 | { 103 | gController[index].setDirectionJoystickMode(); 104 | gController[index].setFireJoystickMode(); 105 | gController[index].setExtraFireJoystickMode(); 106 | gController[index].setKeypadJoystickMode(); 107 | } 108 | DisplayEmulatorMode(gcModeJoystickOnly); 109 | } 110 | 111 | void SetupAdamEmMode() 112 | { 113 | // Joystick 1 Uses Joystick 114 | gController[0].setDirectionJoystickMode(); 115 | gController[0].setFireJoystickMode(); 116 | gController[0].setExtraFireKeyboardMode(); 117 | gController[0].setKeypadKeyboardMode(); 118 | 119 | // Joystick 2 Uses Keyboard 120 | gController[1].setDirectionKeyboardMode(); 121 | gController[1].setFireKeyboardMode(); 122 | gController[1].setExtraFireKeyboardMode(KEY_LEFT_SHIFT, 'z'); 123 | gController[1].setKeypadKeyboardMode('1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '0', '='); 124 | 125 | // Joystick 3 Not Used 126 | gController[2].setDirectionJoystickMode(); 127 | gController[2].setFireJoystickMode(); 128 | gController[2].setExtraFireJoystickMode(); 129 | gController[2].setKeypadJoystickMode(); 130 | 131 | DisplayEmulatorMode(gcModeAdamEm); 132 | } 133 | 134 | void SetupMameMode() 135 | { 136 | // Joystick 1 (* = Pause, # = Quit) 137 | gController[0].setDirectionJoystickMode(); 138 | gController[0].setFireJoystickMode(); 139 | gController[0].setExtraFireJoystickMode(); 140 | gController[0].setKeypadKeyboardMode('1', '2', '3', '4', '5', '6', '7', '8', '9', 'P', '0', KEY_ESC); 141 | 142 | // Joystick 2 (* = Screen Capture, # = Mame Menu) 143 | gController[1].setDirectionJoystickMode(); 144 | gController[1].setFireJoystickMode(); 145 | gController[1].setExtraFireJoystickMode(); 146 | gController[1].setKeypadKeyboardMode('1', '2', '3', '4', '5', '6', '7', '8', '9', KEY_F12, '0', KEY_TAB); 147 | 148 | // Joystick 3 (* = Volume Control, # = Game Reset) 149 | gController[2].setDirectionJoystickMode(); 150 | gController[2].setFireJoystickMode(); 151 | gController[2].setExtraFireJoystickMode(); 152 | gController[2].setKeypadKeyboardMode('1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'); 153 | 154 | DisplayEmulatorMode(gcModeMame); 155 | } 156 | 157 | void ReadController(int joystickIndex) 158 | { 159 | const int cLineDelay = 50; 160 | 161 | // Put Joystick in Direction Mode 162 | digitalWrite(gcModeAPin[joystickIndex], HIGH); 163 | digitalWrite(gcModeBPin[joystickIndex], LOW); 164 | delayMicroseconds(cLineDelay); 165 | gController[joystickIndex].readControllerDirection(); 166 | 167 | // Put Joystick in Keypad Mode 168 | digitalWrite(gcModeAPin[joystickIndex], LOW); 169 | digitalWrite(gcModeBPin[joystickIndex], HIGH); 170 | delayMicroseconds(cLineDelay); 171 | gController[joystickIndex].readControllerKeypad(); 172 | 173 | // Turn off Joystick 174 | digitalWrite(gcModeAPin[joystickIndex], HIGH); 175 | } 176 | 177 | void CheckForModeChange() 178 | { 179 | // Change Mode Button is not down, so just return. 180 | if (digitalRead(gcModePin)) return; 181 | 182 | digitalWrite(gcJoystickOnlyModePin, LOW); 183 | digitalWrite(gcAdamEmModePin, LOW); 184 | digitalWrite(gcMameModePin, LOW); 185 | 186 | do 187 | { 188 | delay(100); 189 | } while (!digitalRead(gcModePin)); 190 | 191 | // Reset Output 192 | Keyboard.releaseAll(); 193 | 194 | // Go to next mode 195 | gCurrentMode++; 196 | if (gCurrentMode > gcModeMax) 197 | { 198 | gCurrentMode = 0; 199 | } 200 | 201 | switch (gCurrentMode) 202 | { 203 | case gcModeAdamEm: 204 | SetupAdamEmMode(); 205 | break; 206 | case gcModeJoystickOnly: 207 | SetupJoystickOnlyMode(); 208 | break; 209 | case gcModeMame: 210 | SetupMameMode(); 211 | break; 212 | } 213 | } 214 | 215 | void setup() { 216 | // Setup Serial Monitor 217 | //Serial.begin(19200); 218 | 219 | // Setup Keyboard 220 | Keyboard.begin(); 221 | 222 | // Setup Joystick Pins 223 | pinMode(gcFirePin, INPUT_PULLUP); 224 | pinMode(gcUpPin, INPUT_PULLUP); 225 | pinMode(gcDownPin, INPUT_PULLUP); 226 | pinMode(gcLeftPin, INPUT_PULLUP); 227 | pinMode(gcRightPin, INPUT_PULLUP); 228 | pinMode(gcSpinnerAPin, INPUT_PULLUP); 229 | pinMode(gcSpinnerBPin, INPUT_PULLUP); 230 | 231 | for (int index = 0; index < JOYSTICK_COUNT; index++) 232 | { 233 | pinMode(gcModeAPin[index], OUTPUT); 234 | pinMode(gcModeBPin[index], OUTPUT); 235 | } 236 | 237 | // Setup Mode Pin 238 | pinMode(gcModePin, INPUT_PULLUP); 239 | 240 | // Setup Output Monitor Pins 241 | pinMode(gcFireMonitorPin, OUTPUT); 242 | pinMode(gcAdamEmModePin, OUTPUT); 243 | pinMode(gcMameModePin, OUTPUT); 244 | pinMode(gcJoystickOnlyModePin, OUTPUT); 245 | 246 | // Default Mode 247 | SetupJoystickOnlyMode(); 248 | //SetupAdamEmMode(); 249 | //SetupMameMode(); 250 | } 251 | 252 | void loop() { 253 | unsigned long currentTime = millis(); 254 | 255 | if (currentTime >= gNextFrameStart) 256 | { 257 | // Send Values to Host 258 | for (int index = 0; index < JOYSTICK_COUNT; index++) 259 | { 260 | gController[index].writeToHost(); 261 | } 262 | 263 | // Send Values to Monitor 264 | ShowJoystickStatus(); 265 | 266 | // Check to see if user has requested mode change 267 | CheckForModeChange(); 268 | 269 | // Reset Frame Variables 270 | for (int index = 0; index < JOYSTICK_COUNT; index++) 271 | { 272 | gController[index].startReadController(); 273 | } 274 | gLoopsPerFrame = 0; 275 | 276 | // Time to start next frame 277 | gNextFrameStart = currentTime + gcFrameLength; 278 | } 279 | else 280 | { 281 | // Check and store the value of the classic controller. 282 | for (int index = 0; index < JOYSTICK_COUNT; index++) 283 | { 284 | ReadController(index); 285 | } 286 | gLoopsPerFrame++; 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /libraries/ClassicController/ClassicController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ClassicController.h - Library for reading a classic controller 3 | (e.g. ColecoVision, Coleco ADAM, Atari, etc.) and emulating a keyboard, 4 | USB joystict, etc. 5 | Created by Matthew Heironimus, 04/25/2015. 6 | */ 7 | 8 | #include "ClassicController.h" 9 | 10 | ClassicController::ClassicController( 11 | int joystickIndex, 12 | int pin1Up, 13 | int pin2Down, 14 | int pin3Left, 15 | int pin4Right, 16 | int pin5KeypadMode, 17 | int pin6FireButton, 18 | int pin7SpinnerA, 19 | int pin8DirectionMode, 20 | int pin9SpinnerB) 21 | { 22 | // Setup Pins 23 | _firePin = pin6FireButton; 24 | _upPin = pin1Up; 25 | _downPin = pin2Down; 26 | _leftPin = pin3Left; 27 | _rightPin = pin4Right; 28 | _keypadModePin = pin5KeypadMode; 29 | _directionModePin = pin8DirectionMode; 30 | _bit0Pin = pin1Up; 31 | _bit1Pin = pin4Right; 32 | _bit2Pin = pin2Down; 33 | _bit3Pin = pin3Left; 34 | _spinnerAPin = pin7SpinnerA; 35 | _spinnerBPin = pin9SpinnerB; 36 | 37 | // Initalize USB Joystick 38 | _joystickIndex = joystickIndex; 39 | Joystick[_joystickIndex].begin(false); 40 | 41 | // Reset the Previous and Current State 42 | startReadController(); 43 | startReadController(); 44 | 45 | // Set default Modes 46 | setDirectionJoystickMode(); 47 | setFireJoystickMode(); 48 | setExtraFireJoystickMode(); 49 | setKeypadJoystickMode(); 50 | } 51 | 52 | void ClassicController::startReadController() 53 | { 54 | // Copy Current State to Last State 55 | _lastLeftFire = _leftFire; 56 | _lastRightFire = _rightFire; 57 | _lastUp = _up; 58 | _lastDown = _down; 59 | _lastLeft = _left; 60 | _lastRight = _right; 61 | _lastPurpleFire = _purpleFire; 62 | _lastBlueFire = _blueFire; 63 | _lastKeypadValue = _keypadValue; 64 | _lastKeypadCode = _keypadCode; 65 | 66 | // Reset Frame Loop Counter 67 | _readCount = 0; 68 | 69 | // Reset Pin Read Value Counters 70 | _leftFireCount = 0; 71 | _rightFireCount = 0; 72 | _upCount = 0; 73 | _downCount = 0; 74 | _leftCount = 0; 75 | _rightCount = 0; 76 | _bit0Count = 0; 77 | _bit1Count = 0; 78 | _bit2Count = 0; 79 | _bit3Count = 0; 80 | 81 | // Reset Current State 82 | _leftFire = 0; 83 | _rightFire = 0; 84 | _up = 0; 85 | _down = 0; 86 | _left = 0; 87 | _right = 0; 88 | _keypadValue = 0; 89 | _keypadCode = 0; 90 | _purpleFire = 0; 91 | _blueFire = 0; 92 | _bit0 = 0; 93 | _bit1 = 0; 94 | _bit2 = 0; 95 | _bit3 = 0; 96 | } 97 | 98 | void ClassicController::readControllerDirection() 99 | { 100 | _leftFireCount += readControllerPin(_firePin); 101 | _upCount += readControllerPin(_upPin); 102 | _downCount += readControllerPin(_downPin); 103 | _leftCount += readControllerPin(_leftPin); 104 | _rightCount += readControllerPin(_rightPin); 105 | } 106 | 107 | void ClassicController::readControllerKeypad() 108 | { 109 | _readCount++; 110 | _rightFireCount += readControllerPin(_firePin); 111 | _bit0Count += readControllerPin(_bit0Pin); 112 | _bit1Count += readControllerPin(_bit1Pin); 113 | _bit2Count += readControllerPin(_bit2Pin); 114 | _bit3Count += readControllerPin(_bit3Pin); 115 | } 116 | 117 | void ClassicController::writeToHost() 118 | { 119 | bool joystickUpdateNeeded = false; 120 | 121 | determineAllPinValues(); 122 | determineSpecialValues(); 123 | 124 | // Send Joystick State To Host 125 | if (_directionJoystickMode) 126 | { 127 | joystickUpdateNeeded |= setDirectionJoystickState(); 128 | } 129 | else 130 | { 131 | sendDirectionKeyboardStateToHost(); 132 | } 133 | 134 | if (_fireJoystickMode) 135 | { 136 | joystickUpdateNeeded |= setFireJoystickState(); 137 | } 138 | else 139 | { 140 | sendFireKeyboardStateToHost(); 141 | } 142 | 143 | if (_extraFireJoystickMode) 144 | { 145 | joystickUpdateNeeded |= setExtraFireJoystickState(); 146 | } 147 | else 148 | { 149 | sendExtraFireKeyboardStateToHost(); 150 | } 151 | 152 | if (_keypadJoystickMode) 153 | { 154 | joystickUpdateNeeded |= setKeypadJoystickState(); 155 | } 156 | else 157 | { 158 | sendKeypadKeyboardStateToHost(); 159 | } 160 | 161 | if (joystickUpdateNeeded) 162 | { 163 | Joystick[_joystickIndex].sendState(); 164 | } 165 | } 166 | 167 | void ClassicController::determineAllPinValues() 168 | { 169 | _leftFire = determinePinValue(_leftFireCount); 170 | _rightFire = determinePinValue(_rightFireCount); 171 | 172 | _up = determinePinValue(_upCount); 173 | _down = determinePinValue(_downCount); 174 | _left = determinePinValue(_leftCount); 175 | _right = determinePinValue(_rightCount); 176 | 177 | _bit0 = determinePinValue(_bit0Count); 178 | _bit1 = determinePinValue(_bit1Count); 179 | _bit2 = determinePinValue(_bit2Count); 180 | _bit3 = determinePinValue(_bit3Count); 181 | } 182 | 183 | void ClassicController::determineSpecialValues() 184 | { 185 | _keypadCode = (_bit3 << 3) + (_bit2 << 2) + (_bit1 << 1) + _bit0; 186 | 187 | // Check for SuperAction Controller Buttons. 188 | if (_keypadCode == 7) 189 | { 190 | _purpleFire = 1; 191 | } 192 | if (_keypadCode == 11) 193 | { 194 | _blueFire = 1; 195 | } 196 | } 197 | 198 | void ClassicController::sendKeypadKeyboardStateToHost() 199 | { 200 | _keypadValue = _keypadKeys[_keypadCode]; 201 | 202 | if ((_lastKeypadValue != 0) && (_lastKeypadValue != _keypadValue)) 203 | { 204 | Keyboard.release(_lastKeypadValue); 205 | } 206 | if ((_keypadValue != 0) && (_lastKeypadValue != _keypadValue)) 207 | { 208 | Keyboard.press(_keypadValue); 209 | } 210 | } 211 | 212 | bool ClassicController::setDirectionJoystickState() 213 | { 214 | const byte UP = -127; 215 | const byte DOWN = 127; 216 | const byte LEFT = -127; 217 | const byte RIGHT = 127; 218 | 219 | // Check to see if state needs to be updated 220 | if ((_up == _lastUp) 221 | && (_down == _lastDown) 222 | && (_left == _lastLeft) 223 | && (_right == _lastRight)) 224 | { 225 | return false; 226 | } 227 | 228 | if (_up) 229 | { 230 | Joystick[_joystickIndex].setYAxis(UP); 231 | } 232 | else if (_down) 233 | { 234 | Joystick[_joystickIndex].setYAxis(DOWN); 235 | } 236 | else 237 | { 238 | Joystick[_joystickIndex].setYAxis(0); 239 | } 240 | 241 | if (_left) 242 | { 243 | Joystick[_joystickIndex].setXAxis(LEFT); 244 | } 245 | else if (_right) 246 | { 247 | Joystick[_joystickIndex].setXAxis(RIGHT); 248 | } 249 | else 250 | { 251 | Joystick[_joystickIndex].setXAxis(0); 252 | } 253 | 254 | return true; 255 | } 256 | 257 | void ClassicController::sendDirectionKeyboardStateToHost() 258 | { 259 | sendLineStateToHost(_lastUp, _up, _upKey); 260 | sendLineStateToHost(_lastDown, _down, _downKey); 261 | sendLineStateToHost(_lastLeft, _left, _leftKey); 262 | sendLineStateToHost(_lastRight, _right, _rightKey); 263 | } 264 | 265 | bool ClassicController::setFireJoystickState() 266 | { 267 | // Check to see if state needs to be updated 268 | if ((_leftFire == _lastLeftFire) 269 | && (_rightFire == _lastRightFire)) 270 | { 271 | return false; 272 | } 273 | 274 | Joystick[_joystickIndex].setButton(_leftFireButton, _leftFire); 275 | Joystick[_joystickIndex].setButton(_rightFireButton, _rightFire); 276 | 277 | return true; 278 | } 279 | 280 | void ClassicController::sendFireKeyboardStateToHost() 281 | { 282 | sendLineStateToHost(_lastLeftFire, _leftFire, _leftFireKey); 283 | sendLineStateToHost(_lastRightFire, _rightFire, _rightFireKey); 284 | } 285 | 286 | bool ClassicController::setExtraFireJoystickState() 287 | { 288 | // Check to see if state needs to be updated 289 | if ((_purpleFire == _lastPurpleFire) 290 | && (_blueFire == _lastBlueFire)) 291 | { 292 | return false; 293 | } 294 | 295 | Joystick[_joystickIndex].setButton(_purpleFireButton, _purpleFire); 296 | Joystick[_joystickIndex].setButton(_blueFireButton, _blueFire); 297 | 298 | return true; 299 | } 300 | 301 | void ClassicController::sendExtraFireKeyboardStateToHost() 302 | { 303 | sendLineStateToHost(_lastPurpleFire, _purpleFire, _purpleFireKey); 304 | sendLineStateToHost(_lastBlueFire, _blueFire, _blueFireKey); 305 | } 306 | 307 | bool ClassicController::setKeypadJoystickState() 308 | { 309 | // Check to see if state needs to be updated 310 | if (_keypadCode == _lastKeypadCode) 311 | { 312 | return false; 313 | } 314 | 315 | int lastButtonPressed = _keypadButtons[_lastKeypadCode]; 316 | 317 | if (lastButtonPressed != NOT_USED) 318 | { 319 | Joystick[_joystickIndex].setButton(lastButtonPressed, LOW); 320 | } 321 | 322 | int currentButtonPressed = _keypadButtons[_keypadCode]; 323 | if (currentButtonPressed != NOT_USED) 324 | { 325 | Joystick[_joystickIndex].setButton(currentButtonPressed, HIGH); 326 | } 327 | 328 | return true; 329 | } 330 | 331 | void ClassicController::setDirectionJoystickMode() 332 | { 333 | _directionJoystickMode = true; 334 | } 335 | 336 | void ClassicController::setDirectionKeyboardMode(char upKey, char downKey, char leftKey, char rightKey) 337 | { 338 | _directionJoystickMode = false; 339 | _upKey = upKey; 340 | _downKey = downKey; 341 | _leftKey = leftKey; 342 | _rightKey = rightKey; 343 | } 344 | 345 | void ClassicController::setFireJoystickMode(int leftFireButton, int rightFireButton) 346 | { 347 | _fireJoystickMode = true; 348 | _leftFireButton = leftFireButton; 349 | _rightFireButton = rightFireButton; 350 | } 351 | 352 | void ClassicController::setExtraFireJoystickMode(int purpleFireButton, int blueFireButton) 353 | { 354 | _extraFireJoystickMode = true; 355 | _purpleFireButton = purpleFireButton; 356 | _blueFireButton = blueFireButton; 357 | } 358 | 359 | void ClassicController::setFireKeyboardMode(char leftFireKey, char rightFireKey) 360 | { 361 | _fireJoystickMode = false; 362 | _leftFireKey = leftFireKey; 363 | _rightFireKey = rightFireKey; 364 | } 365 | 366 | void ClassicController::setExtraFireKeyboardMode(char purpleFireKey, char blueFireKey) 367 | { 368 | _extraFireJoystickMode = false; 369 | _purpleFireKey = purpleFireKey; 370 | _blueFireKey = blueFireKey; 371 | } 372 | 373 | void ClassicController::setKeypadJoystickMode(int oneButton, int twoButton, int threeButton, 374 | int fourButton, int fiveButton, int sixButton, 375 | int sevenButton, int eightButton, int nineButton, 376 | int asteriskButton, int zeroButton, int poundButton) 377 | { 378 | _keypadJoystickMode = true; 379 | 380 | _keypadButtons[1] = sixButton; 381 | _keypadButtons[2] = oneButton; 382 | _keypadButtons[3] = threeButton; 383 | _keypadButtons[4] = nineButton; 384 | _keypadButtons[5] = zeroButton; 385 | _keypadButtons[6] = asteriskButton; 386 | _keypadButtons[8] = twoButton; 387 | _keypadButtons[9] = poundButton; 388 | _keypadButtons[10] = sevenButton; 389 | _keypadButtons[12] = fiveButton; 390 | _keypadButtons[13] = fourButton; 391 | _keypadButtons[14] = eightButton; 392 | } 393 | 394 | void ClassicController::setKeypadKeyboardMode(char oneKey, char twoKey, char threeKey, 395 | char fourKey, char fiveKey, char sixKey, 396 | char sevenKey, char eightKey, char nineKey, 397 | char asteriskKey, char zeroKey, char poundKey) 398 | { 399 | _keypadJoystickMode = false; 400 | 401 | _keypadKeys[1] = sixKey; 402 | _keypadKeys[2] = oneKey; 403 | _keypadKeys[3] = threeKey; 404 | _keypadKeys[4] = nineKey; 405 | _keypadKeys[5] = zeroKey; 406 | _keypadKeys[6] = asteriskKey; 407 | _keypadKeys[8] = twoKey; 408 | _keypadKeys[9] = poundKey; 409 | _keypadKeys[10] = sevenKey; 410 | _keypadKeys[12] = fiveKey; 411 | _keypadKeys[13] = fourKey; 412 | _keypadKeys[14] = eightKey; 413 | } 414 | 415 | void ClassicController::sendLineStateToHost(bool lastState, bool currentState, char keyUsedForLine) 416 | { 417 | if ((lastState == true) && (currentState == false)) 418 | { 419 | Keyboard.release(keyUsedForLine); 420 | } 421 | if ((lastState == false) && (currentState == true)) 422 | { 423 | Keyboard.press(keyUsedForLine); 424 | } 425 | } 426 | --------------------------------------------------------------------------------