Skip to content
anthonygj-buttonbox.ino 10.1 KiB
Newer Older
// include the joystick and keyboard library
#include <Joystick.h>
#include <Keyboard.h>

// Create the Joystick object
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
                   JOYSTICK_TYPE_JOYSTICK, 32, 0,
                   true, true, false, false, false, false,
                   false, false, false, false, false);
//declare the pin number for each button, switch, encoder...
//declare understandable var to recognise button in the code,
const int SwitchButton1 = 2;
const int SwitchButton2 = 3;
const int SwitchButton3 = 53;
const int SwitchButton4 = 51;
const int SwitchButton5 = 50;

const int NCButton = 7;

const int Button1 = 8;
const int Button2 = 9;
const int Button3 = 10;
const int Button4 = 11;
const int Button5 = 12;
const int Button6 = 13;
const int Button7 = 14;
const int Button8 = 15;
const int Button9 = 16;
const int Button10 = 17;

const int threeWay1A = 18;
const int threeWay1B = 19;
const int threeWay2A = 20;
const int threeWay2B = 21;
const int threeWay3A = 24;
const int threeWay3B = 25;

const int rotaryEncoder1A = 31;
const int rotaryEncoder1B = 32;
const int rotaryEncoder1Button = 26;

const int rotaryEncoder2A = 33;
const int rotaryEncoder2B = 34;
const int rotaryEncoder2Button = 27;

const int rotaryEncoder3A = 35;
const int rotaryEncoder3B = 36;
const int rotaryEncoder3Button = 28;
const int rotaryEncoder4A = 37;
const int rotaryEncoder4B = 38;
const int rotaryEncoder4Button = 29;

const int rotaryEncoder5A = 39;
const int rotaryEncoder5B = 40;
const int rotaryEncoder5Button = 30;

const int joystickX = A0;
const int joystickY = A1;
const int joystickButton = 49;


char ctrlKey = KEY_LEFT_CTRL;

//array to store the last status of the button
//TODO: improve the "32" and only declare the required ammount
int lastButtonStatus[32];

//variable needed for the rotary encoders
int counter[5];
bool aState[5] ;
bool aLastState[5] ;
long unsigned aTime[5] ;

//funtion that will be run only once to init the arduino
void setup() {
  //initialise the pin mode of the buttons, switches, rotary encoders
  pinMode(SwitchButton1, INPUT);
  pinMode(SwitchButton2, INPUT);
  pinMode(SwitchButton3, INPUT);
  pinMode(SwitchButton4, INPUT);
  pinMode(SwitchButton5, INPUT);

  pinMode(NCButton, INPUT_PULLUP);

  pinMode(Button1, INPUT_PULLUP);
  pinMode(Button2, INPUT_PULLUP);
  pinMode(Button3, INPUT_PULLUP);
  pinMode(Button4, INPUT_PULLUP);
  pinMode(Button5, INPUT_PULLUP);
  pinMode(Button6, INPUT_PULLUP);
  pinMode(Button7, INPUT_PULLUP);
  pinMode(Button8, INPUT_PULLUP);
  pinMode(Button9, INPUT_PULLUP);
  pinMode(Button10, INPUT_PULLUP);


  pinMode(threeWay1A, INPUT);
  pinMode(threeWay1B, INPUT);
  pinMode(threeWay2A, INPUT);
  pinMode(threeWay2B, INPUT);
  pinMode(threeWay3A, INPUT);
  pinMode(threeWay3B, INPUT);

  pinMode(rotaryEncoder1A, INPUT_PULLUP);
  pinMode(rotaryEncoder1B, INPUT_PULLUP);
  pinMode(rotaryEncoder1Button, INPUT_PULLUP);
  aLastState[0] = digitalRead(rotaryEncoder1A);
  aTime[0] = millis();
  counter[0] = 0;

  pinMode(rotaryEncoder2A, INPUT_PULLUP);
  pinMode(rotaryEncoder2B, INPUT_PULLUP);
  pinMode(rotaryEncoder2Button, INPUT_PULLUP);
  aLastState[1] = digitalRead(rotaryEncoder2A);
  aTime[1] = millis();
  counter[1] = 0;

  pinMode(rotaryEncoder3A, INPUT_PULLUP);
  pinMode(rotaryEncoder3B, INPUT_PULLUP);
  pinMode(rotaryEncoder3Button, INPUT_PULLUP);
  aLastState[2] = digitalRead(rotaryEncoder3A);
  aTime[2] = millis();
  counter[2] = 0;

  pinMode(rotaryEncoder4A, INPUT_PULLUP);
  pinMode(rotaryEncoder4B, INPUT_PULLUP);
  pinMode(rotaryEncoder4Button, INPUT_PULLUP);
  aLastState[3] = digitalRead(rotaryEncoder4A);
  aTime[3] = millis();
  counter[3] = 0;

  pinMode(rotaryEncoder5A, INPUT_PULLUP);
  pinMode(rotaryEncoder5B, INPUT_PULLUP);
  pinMode(rotaryEncoder5Button, INPUT_PULLUP);
  aLastState[5] = digitalRead(rotaryEncoder5A);
  aTime[5] = millis();
  counter[5] = 0;

  pinMode(joystickX, INPUT_PULLUP);
  pinMode(joystickY, INPUT_PULLUP);
  pinMode(joystickButton, INPUT_PULLUP);

  for (int i = 0 ; i < 31 ; i++)
  {
    lastButtonStatus[i] = HIGH;
  }

  Joystick.begin();

}

//function that will be executed again and again and again...
void loop() {

  //call the function for each type of input
  switchCheck(SwitchButton1, 'a');
  switchCheck(SwitchButton2, 'z');
  switchCheck(SwitchButton3, 'e');
  switchCheck(SwitchButton4, 'r');
  switchCheck(SwitchButton5, 't');

  ButtonCheckNC(NCButton, 'y');

  ButtonCheck(Button1, 'u');
  ButtonCheck(Button2, 'i');
  ButtonCheck(Button3, 'o');
  ButtonCheck(Button4, 'p');
  ButtonCheck(Button5, 'q');
  ButtonCheck(Button6, 's');
  ButtonCheck(Button7, 'd');
  ButtonCheck(Button8, 'f');
  ButtonCheck(Button9, 'g');
  ButtonCheck(Button10, 'h');


  ButtonCheck(threeWay1A, 'j');
  ButtonCheck(threeWay1B, 'k');
  ButtonCheck(threeWay2A, 'l');
  ButtonCheck(threeWay2B, 'm');
  ButtonCheck(threeWay3A, 'w');
  ButtonCheck(threeWay3B, 'x');

  ButtonCheck(rotaryEncoder1Button, 'c');
  ButtonCheck(rotaryEncoder2Button, 'v');
  ButtonCheck(rotaryEncoder3Button, 'b');
  ButtonCheck(rotaryEncoder4Button, 'n');
  ButtonCheck(rotaryEncoder5Button, ',');

  rotaryEncoderChar(rotaryEncoder1A, rotaryEncoder1B , '1' , '2');
  rotaryEncoderChar(rotaryEncoder2A, rotaryEncoder2B , '3' , '4');
  rotaryEncoderChar(rotaryEncoder3A, rotaryEncoder3B , '5' , '6');
  rotaryEncoderChar(rotaryEncoder4A, rotaryEncoder4B , '7' , '8');
  rotaryEncoderChar(rotaryEncoder5A, rotaryEncoder5B , '9' , '-');

  ButtonCheck(joystickButton, '*');
  /*
    analogJoyAxisCheck(joystickX , joystickY);
  */
}

//this function manage the analog joystick
//the parameters are
// joyX => the pin number of the X axis of the analog joystick
// joyY => the pin number of the Y axis of the analog joystick
void analogJoyAxisCheck(int joyX , int joyY) {
  //initialise variable that will be needed
  int xMap, yMap, xValue, yValue;

  //initialise the range on 16bit
  Joystick.setXAxisRange(-32765, 32766);
  Joystick.setYAxisRange(-32765, 32766);

  //read the input value of the analog joystick x and y axis
  xValue = analogRead(joyX);
  yValue = analogRead(joyY);

  // after playing with the joystick and sending
  // value in the serial bus Serial.println(xValue); and Serial.println(yValue);
  // it appears that center of joystick is x:517 and y:531
  // max/top y: 1023 min/bottom y :0
  // max/right x: 1023 min/left x :0

  //we map the scale to transform value from 0 to 1023 into something from -32765 to 32766
  xMap = map(xValue, 0, 1023, -32765, 32766);
  yMap = map(yValue, 0, 1023, -32765, 32766);

  //once we have the matching coordinates, we can send it to the gamepad
  Joystick.setXAxis(xMap);
  Joystick.setYAxis(yMap);
}


//external function to manage switch
//it takes 2 parameters
//inputNb => the pin number on which the switch is plug
//gamepadButtonNb => the button number of the gamepad
void switchCheck(int inputNb, char gamepadButtonNb) {
  //read the digital input of the switch
  int ButtonVal = digitalRead(inputNb);

  //if the status is not the same as last time
  //it means that the user switches "off" or "on"
  if (ButtonVal != lastButtonStatus[inputNb]) {
    //don't forget to update the last status
    lastButtonStatus[inputNb] = ButtonVal;

    Keyboard.press(gamepadButtonNb);
    delay(300);
    //  Keyboard.release(ctrlKey);
    Keyboard.release(gamepadButtonNb);


  }

}


// function that check the button state
// the parameters are
// inputNB => the pin nb of the button
// gamepadButtonNb => which gamepad number will be pressed when rotary button is pressed
void ButtonCheck(int inputNb, char gamepadButtonNb) {

  int ButtonVal = digitalRead(inputNb);

  if (ButtonVal != lastButtonStatus[inputNb]) {
    if (ButtonVal == LOW) {
      Keyboard.press(gamepadButtonNb);
    }
    else {
      Keyboard.release(gamepadButtonNb);
    }
    lastButtonStatus[inputNb] = ButtonVal;
  }
}

//TODO: factorise with the regular ButtonCheck function
// basically the same function but the if else test is inverted due to the
// naturaly closed status
void ButtonCheckNC(int inputNb, char gamepadButtonNb) {

  int ButtonVal = digitalRead(inputNb);

  if (ButtonVal != lastButtonStatus[inputNb]) {
    if (ButtonVal == HIGH) {
      Keyboard.press(gamepadButtonNb);
    }
    else {
      Keyboard.release(gamepadButtonNb);
    }
    lastButtonStatus[inputNb] = ButtonVal;
  }
}

//this function manage the rotary encoders
//the parameters are
// inputA => the pin number of the A side of the rotary
// inputB => the pin number of the B side of the rotary
// gamepadButtonUpNb => which gamepad number will be pressed when rotary going up
// gamepadButtonDownNb => which gamepad number will be pressed when rotary going down
void rotaryEncoderChar(int inputA, int inputB , char gamepadButtonUpNb , char gamepadButtonDownNb) {

  aState[inputA] = digitalRead(inputA);// Reads the "current" state of the outputA

  // If the previous and the current state of the outputA are different, that means a Pulse has occured

  if ( aState[inputA] != aLastState[inputA] ) {
    //check time to avoid inconsistency
    if ( abs(millis() - aTime[inputA]) > 100 ) {
      // If the outputB state is different to the aLastState (itself different from aState), that means the encoder is rotating counter clockwise
      if (digitalRead(inputB) != aLastState[inputA]) {
        counter[inputA]--;

        //since I don't want to hold the press
        // I just "press" the button, wait 300ms and release the button
        //Keyboard.press(ctrlKey);
        Keyboard.press(gamepadButtonDownNb);
        delay(100);
        //Keyboard.release(ctrlKey);
        Keyboard.release(gamepadButtonDownNb);

        // Serial.print("bouton -");
      }
      else { // else, it means that the outputB state is the same as aLastState that means the encoder is rotating clockwise
        //since I don't want to hold the press
        // I just "press" the button, wait 300ms and release the button
        //Keyboard.press(ctrlKey);
        Keyboard.press(gamepadButtonUpNb);
        delay(100);
        //Keyboard.release(ctrlKey);
        Keyboard.release(gamepadButtonUpNb);

        counter[inputA]++;
      }
      // save the time for next check
      aTime[inputA] = millis();
    }
    // save the current state (that will be the next "last" state)
    aLastState[inputA] = aState[inputA] ;


  }

}