├── README.md ├── maimaiKeyboard └── maimaiKeyboard.ino └── maimaiJoystick └── maimaiJoystick.ino /README.md: -------------------------------------------------------------------------------- 1 | ## Maimai buttons 2 | 3 | This is a firmware to use Maimai arcade buttons. 4 | 5 | Maimai buttons are photointerrupters instead of the usual microswitches, with a normally closed logic. 6 | 7 | ## Wiring/pinout 8 | 9 | Each button has 3 wires, black red and orange 10 | 11 | - Daisychain all black wires to Arduino GND 12 | 13 | - Daisychain all red wires to Arduino 3.3V or 5V 14 | 15 | - Wire buttons 1 to 8 orange wires to Arduino gpio 2 to 9 16 | 17 | - (optional) wire an additional regular microswitch on gpio 10 and GND 18 | 19 | ## Behavior 20 | 21 | - maimaiKeyboard maps buttons 1 to 8 to qwedcxza keys (ie. clockwise starting from top left), button 9 to 's' 22 | 23 | - maimaiJoystick maps them to joystick button 1 to 9 -------------------------------------------------------------------------------- /maimaiKeyboard/maimaiKeyboard.ino: -------------------------------------------------------------------------------- 1 | #define BOUNCE_WITH_PROMPT_DETECTION 2 | #include 3 | #include 4 | #define BUTTON_COUNT 8 5 | #define EXTRA_BUTTON_COUNT 1 6 | #define TOTAL_BUTTON_COUNT BUTTON_COUNT+EXTRA_BUTTON_COUNT 7 | #define BOUNCE_INTERVAL 5 8 | 9 | int buttonPin[] = {2,3,4,5,6,7,8,9,10}; 10 | char buttonKey[] = {'q','w','e','d','c','x','z','a','s'}; 11 | Bounce buttonBounce[TOTAL_BUTTON_COUNT]; 12 | bool buttonState[TOTAL_BUTTON_COUNT]; 13 | bool previousState[TOTAL_BUTTON_COUNT]; 14 | 15 | void setup() { 16 | 17 | for (int i = 0; i < BUTTON_COUNT; i++){ 18 | buttonBounce[i] = Bounce(); 19 | buttonBounce[i].attach(buttonPin[i], INPUT_PULLUP); 20 | buttonBounce[i].interval(BOUNCE_INTERVAL); 21 | buttonState[i] = false; 22 | previousState[i] = true; 23 | } 24 | 25 | for (int i = BUTTON_COUNT; i < TOTAL_BUTTON_COUNT; i++){ 26 | buttonBounce[i] = Bounce(); 27 | buttonBounce[i].attach(buttonPin[i], INPUT_PULLUP); 28 | buttonBounce[i].interval(BOUNCE_INTERVAL); 29 | buttonState[i] = false; 30 | previousState[i] = false; 31 | } 32 | Keyboard.begin(); 33 | } 34 | 35 | void loop() { 36 | 37 | for (int i = 0; i < BUTTON_COUNT; i++){ 38 | buttonBounce[i].update(); 39 | buttonState[i] = (buttonBounce[i].read() == HIGH); 40 | if (buttonState[i] && !previousState[i]) { 41 | Keyboard.press(buttonKey[i]); 42 | } else if (!buttonState[i] && previousState[i]) { 43 | Keyboard.release(buttonKey[i]); 44 | } 45 | previousState[i] = buttonState[i]; 46 | } 47 | for (int i = BUTTON_COUNT; i < TOTAL_BUTTON_COUNT; i++){ 48 | buttonBounce[i].update(); 49 | buttonState[i] = (buttonBounce[i].read() == LOW); 50 | 51 | if (buttonState[i] && !previousState[i]) { 52 | Keyboard.press(buttonKey[i]); 53 | } else if (!buttonState[i] && previousState[i]) { 54 | Keyboard.release(buttonKey[i]); 55 | } 56 | previousState[i] = buttonState[i]; 57 | } 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /maimaiJoystick/maimaiJoystick.ino: -------------------------------------------------------------------------------- 1 | #define BOUNCE_WITH_PROMPT_DETECTION 2 | #include 3 | #include 4 | #define BUTTON_COUNT 8 5 | #define EXTRA_BUTTON_COUNT 1 6 | #define TOTAL_BUTTON_COUNT BUTTON_COUNT+EXTRA_BUTTON_COUNT 7 | #define BOUNCE_INTERVAL 5 8 | 9 | Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 10 | TOTAL_BUTTON_COUNT, 0, // Button Count, Hat Switch Count 11 | false, false, false, // X and Y, but no Z Axis 12 | false, false, false, // No Rx, Ry, or Rz 13 | false, false, // No rudder or throttle 14 | false, false, false); // No accelerator, brake, or steering 15 | 16 | int buttonPin[] = {2,3,4,5,6,7,8,9,10}; 17 | Bounce buttonBounce[TOTAL_BUTTON_COUNT]; 18 | bool buttonState[TOTAL_BUTTON_COUNT]; 19 | bool previousState[TOTAL_BUTTON_COUNT]; 20 | 21 | void setup() { 22 | 23 | for (int i = 0; i < BUTTON_COUNT; i++){ 24 | buttonBounce[i] = Bounce(); 25 | buttonBounce[i].attach(buttonPin[i], INPUT_PULLUP); 26 | buttonBounce[i].interval(BOUNCE_INTERVAL); 27 | buttonState[i] = false; 28 | previousState[i] = true; 29 | } 30 | for (int i = BUTTON_COUNT; i < TOTAL_BUTTON_COUNT; i++){ 31 | buttonBounce[i] = Bounce(); 32 | buttonBounce[i].attach(buttonPin[i], INPUT_PULLUP); 33 | buttonBounce[i].interval(BOUNCE_INTERVAL); 34 | buttonState[i] = false; 35 | previousState[i] = false; 36 | } 37 | Joystick.begin(); 38 | 39 | } 40 | 41 | void loop() { 42 | 43 | for (int i = 0; i < BUTTON_COUNT; i++){ 44 | buttonBounce[i].update(); 45 | buttonState[i] = (buttonBounce[i].read() == HIGH); 46 | if (buttonState[i] && !previousState[i]) { 47 | Joystick.setButton(i, buttonState[i]); 48 | } else if (!buttonState[i] && previousState[i]) { 49 | Joystick.setButton(i, buttonState[i]); 50 | } 51 | previousState[i] = buttonState[i]; 52 | } 53 | 54 | for (int i = BUTTON_COUNT; i < TOTAL_BUTTON_COUNT; i++){ 55 | buttonBounce[i].update(); 56 | buttonState[i] = (buttonBounce[i].read() == LOW); 57 | 58 | if (buttonState[i] && !previousState[i]) { 59 | Joystick.setButton(i, buttonState[i]); 60 | } else if (!buttonState[i] && previousState[i]) { 61 | Joystick.setButton(i, buttonState[i]); 62 | } 63 | previousState[i] = buttonState[i]; 64 | } 65 | 66 | } 67 | 68 | 69 | --------------------------------------------------------------------------------