//BUTTON BOX //USE w ProMicro //Tested in WIN10 + Assetto Corsa //AMSTUDIO //20.8.17 // code taken from https://github.com/AM-STUDIO/32-FUNCTION-BUTTON-BOX/blob/master/ARDUINO_BUTTON_BOXV2.ino //include 2 libraries to manage grid layout and une gamepad features #include #include //define values #define ENABLE_PULLUPS #define NUMROTARIES 4 #define NUMBUTTONS 24 //grid size 5 x 5 #define NUMROWS 5 #define NUMCOLS 5 //this is the matching between the grid and the button number that will be triggered //for instance , if I physically press the button plug in the grid at the column 1 , row 2 // the program will send the gamepad signal that the button 5 have been pressed byte buttons[NUMROWS][NUMCOLS] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}, {15,16,17,18,19}, {20,21,22,23}, }; //define a custom structure to manage easily the rotary encoder struct rotariesdef { byte pin1; // the Arduino pin connected to the A side of the rotary encoder byte pin2; // the Arduino pin connected to the B side of the rotary encoder int ccwchar; //ccw => counter clockwise this is the character/ the button of the gamepad that will be pressed when user turn the rotary counter clockwise int cwchar;//cw => clockwise this is the character/ the button of the gamepad that will be pressed when user turn the rotary clockwise volatile unsigned char state; => state to know if the user turn clockwise or counter clockwise }; //as define earlier, there is 4 rotaries encoders //so it defines the structure rotariesdef for each rotary // for instance: // the first rotry is connected to pin 0 and 1 of the arduino // if the user turn counter clockwise , the button 24 will be pressed // if the user turn clockwise , the button 25 will be pressed rotariesdef rotaries[NUMROTARIES] { {0,1,24,25,0}, {2,3,26,27,0}, {4,5,28,29,0}, {6,7,30,31,0}, }; //define some value to be used to know if the rotary is turned and what direction (ccw or cw) // and depending if there is HALF_STEP or not it will use one set of data or the other #define DIR_CCW 0x10 #define DIR_CW 0x20 #define R_START 0x0 #ifdef HALF_STEP #define R_CCW_BEGIN 0x1 #define R_CW_BEGIN 0x2 #define R_START_M 0x3 #define R_CW_BEGIN_M 0x4 #define R_CCW_BEGIN_M 0x5 const unsigned char ttable[6][4] = { // R_START (00) {R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN {R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START}, // R_CW_BEGIN {R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START}, // R_START_M (11) {R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START}, // R_CW_BEGIN_M {R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW}, // R_CCW_BEGIN_M {R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW}, }; #else #define R_CW_FINAL 0x1 #define R_CW_BEGIN 0x2 #define R_CW_NEXT 0x3 #define R_CCW_BEGIN 0x4 #define R_CCW_FINAL 0x5 #define R_CCW_NEXT 0x6 const unsigned char ttable[7][4] = { // R_START {R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CW_FINAL {R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_BEGIN {R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_NEXT {R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CCW_BEGIN {R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_FINAL {R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW}, // R_CCW_NEXT {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, }; #endif //define the arduino pin used for the grid byte rowPins[NUMROWS] = {21,20,19,18,15}; byte colPins[NUMCOLS] = {14,16,10,9,8}; //manage easily the keypad based on the define grid Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 32, 0, false, false, false, false, false, false, false, false, false, false, false); void setup() { Joystick.begin(); rotary_init();} void loop() { CheckAllEncoders(); CheckAllButtons(); } //equivalent of the ButtonCheck(int inputNb, int gamepadButtonNb) of my version // but it is managed the same way for every button void CheckAllButtons(void) { if (buttbx.getKeys()) { for (int i=0; i