Android Bluetooth joystick

Here it is

#define VERSION     "\n\nAndroTest V1.41 - @kas2014\ndemo for V4.X  (6 button version)"

// V1.41 minor modifications
// V1.4  improved communication errors handling
// V1.3  renamed for publishing, posted on 09/05/2014
// V1.2  Text display   ** not backward compatible **
// V1.1  Integer display
// V1.0  6 buttons + 4 data char implemented

// Demo setup:
// Button #1 controls pin13 LED
// Button #2 starts DEBUG
// Button #3 displays demo message
// Button #4 toggle datafield display rate
// Button #5 configured as "push" button (momentary)

// Arduino pin#2 to TX BlueTooth module
// Arduino pin#3 to RX BlueTooth module
// make sure your BT board is set @57600 bps
// better remove SoftSerial for PWM based projects

// For Mega 2560:
// remove   #include "SoftwareSerial.h", SoftwareSerial mySerial(2,3);
// search/replace  mySerial  >> Serial1
// pin#18 to RX bluetooth module, pin#19 to TX bluetooth module

#include "SoftwareSerial.h"

#define    STX          0x01
#define    ETX          0x00
#define    ledPin       13
#define    SLOW         1000                           // Datafields refresh rate (ms)
#define    FAST         250                            // Datafields refresh rate (ms)

SoftwareSerial mySerial(2,3);                           // BlueTooth module: pin#2=TX pin#3=RX
int i=0;
byte cmd[6] = {0, 0, 0, 0, 0, 0};                       // bytes received
byte buttonStatus = 0;                                  // first Byte sent to Android device
long previousMillis = 0;                                // will store last time Buttons status was updated
boolean setButtonFeedback = false;                      // momentary buttons feedback to Android device
long sendInterval = SLOW;                               // interval between Buttons status transmission (milliseconds)
String displayStatus = "xxxx";                          // message to Android device

void setup()  {
  Serial.begin(57600);
  mySerial.begin(57600);                                // 57600 = max value for softserial
  pinMode(ledPin, OUTPUT);     
  Serial.println(VERSION);
  while(mySerial.available())  mySerial.read();         // empty RX buffer    //  <<mod XXXXXXXX 
}

void loop() {
  if(mySerial.available())  {                            // data received from smartphone
    delay(2);                                                              //  <<mod XXXXXXXX
    cmd[0] =  mySerial.read();  
    if(cmd[0] == STX)  {
      i=1;      
      while(mySerial.available())  {
        delay(1);                                                          //  <<mod XXXXXXXX
        cmd[i] = mySerial.read();
        if(cmd[i]>127 || i>5)                               break;   // Communication error << XXX Mod
        if((cmd[i]==ETX) && ((i==2 && cmd[1]>2) || i==5))   break;   // Button or Joystick data
        i++;
      }
      if     (i==2 && cmd[1]>48 && cmd[1]<68)     getButtonState(cmd[1]);                         // 3 Bytes
      else if(i==5 && cmd[1]<3  && cmd[3]<3 )     getJoystickState(cmd);                          // 6 Bytes
    }
  }
  sendBlueToothData();                                                       //  <<mod XXXXXXXX
//    delay(5);                                                              //  <<mod XXXXXXXX
// your code here
}

void sendBlueToothData()  {
  static long previousMillis = 0;                             
  long currentMillis = millis();
  if(setButtonFeedback == true)  {                      // allow momentary button visual effect
    previousMillis = currentMillis + 250;   
    setButtonFeedback = false;
  }
  if(currentMillis - previousMillis > sendInterval) {   // send data to smartphone
    previousMillis = currentMillis; 

// Data frame transmitted back from Arduino to Android device:
// < 0X02   Buttons state   0X01   DataField#1   0x04   DataField#2   0x05   DataField#3    0x03 >  
// < 0X02       01011       0X01      120.00     0x04      -4500      0x05   Motor enabled  0x03 >    // example

    mySerial.print((char)0x2);                                                 // Start of Transmission
    mySerial.print(getButtonStatusString());      mySerial.print((char)0x1);   // buttons status feedback
    mySerial.print(GetDataField_1_int());         mySerial.print((char)0x4);   // datafield #1
    mySerial.print(GetDataField_2_float());       mySerial.print((char)0x5);   // datafield #2
    mySerial.print(displayStatus);                                             // datafield #3
    mySerial.print((char)0x3);                                                 // End of Transmission
  }  
}

String getButtonStatusString()  {
  String bStatus = "";
  for(int i=0; i<6; i++)  {
    if(buttonStatus & (B100000 >>i))      bStatus += "1";
    else                                  bStatus += "0";
  }
  return bStatus;
}

int GetDataField_1_int()  {            // Data dummy values sent to Android device for demo purpose
  static int i= -30;                   // Replace with your own code
  i ++;
  if(i >0)    i = -3000;
  return i;  
}

float GetDataField_2_float()  {       // Data dummy values sent to Android device for demo purpose
  static float i=50;                  // Replace with your own code
  i-=.5;
  if(i <-50)    i = 50;
  return i;  
}

void getJoystickState(byte data[6])    {                             //  <<mod XXXXXXXX   nasty bug, was byte data[5]
  int joyX = (data[1]<<7) + data[2];
  int joyY = (data[3]<<7) + data[4];
  joyX = joyX - 200;                                            // Offset to avoid
  joyY = joyY - 200;                                            // transmitting negative numbers
  if(joyX<-100 || joyX>100 || joyY<-100 || joyY>100)    return; // commmunication error
  
  Serial.print("Joystick position:  ");
  Serial.print(joyX); Serial.print(", "); Serial.println(joyY);
    
// Your code here ...
}

void getButtonState(int bStatus)  {
  switch (bStatus) {
// -----------------  BUTTON #1  -----------------------
    case '1':
      buttonStatus |= B000001;        // ON
      Serial.println("\n** Button_1: ON **");    // your code here...
      displayStatus = "LED <ON>";
      Serial.println(displayStatus);
      digitalWrite(ledPin, HIGH);
      break;
    case '2':
      buttonStatus &= B111110;        // OFF
      Serial.println("\n** Button_1: OFF **");    // your code here...
      displayStatus = "LED <OFF>";
      Serial.println(displayStatus);
      digitalWrite(ledPin, LOW);
      break;
// -----------------  BUTTON #2  -----------------------
    case '3':
      buttonStatus |= B000010;        // ON
      Serial.println("\n** Button_2: ON **");    // your code here...
      break;
    case '4':
      buttonStatus &= B111101;        // OFF
      Serial.println("\n** Button_2: OFF **");    // your code here...
      break;
// -----------------  BUTTON #3  -----------------------
    case '5':
      buttonStatus |= B000100;        // ON
     // setButtonFeedback = true;            moved to button #5 (for push buttons)
      Serial.println("\n** Button_3: ON **");    // your code here...
      displayStatus = "Motor #1 enabled"; // Demo text message
      Serial.println(displayStatus);
      break;
    case '6':
      buttonStatus &= B111011;      // OFF
      Serial.println("\n** Button_3: OFF **");    // your code here...
      displayStatus = "Motor #1 stopped";
      Serial.println(displayStatus);
      break;
// -----------------  BUTTON #4  -----------------------
    case '7':
      buttonStatus |= B001000;       // ON
      Serial.println("\n** Button_4: ON **");    // your code here...
      displayStatus = "Datafield update <FAST>";
      Serial.println(displayStatus);
      sendInterval = FAST;
      break;
    case '8':
      buttonStatus &= B110111;    // OFF
      Serial.println("\n** Button_4: OFF **");    // your code here...
      displayStatus = "Datafield update <SLOW>";
      Serial.println(displayStatus);
      sendInterval = SLOW;
     break;
// -----------------  BUTTON #5  -----------------------
    case '9':           // configured as momentary button
//      buttonStatus |= B010000;        // ON
      setButtonFeedback = true;                     // moved from button #3
      Serial.println("\n** Button_5: + pushed + **"); // your code here...
      displayStatus = "Button_5: ++ pushed ++";
      break;
//   case 'A':
//     buttonStatus &= B101111;        // OFF
//     break;
// -----------------  BUTTON #6  -----------------------
    case 'B':
      buttonStatus |= B100000;        // ON
      Serial.println("\n** Button_6: ON **");    // your code here...
       displayStatus = "Button #6 ON"; // Demo text message
     break;
    case 'C':
      buttonStatus &= B011111;        // OFF
      Serial.println("\n** Button_6: OFF **");    // your code here...
      displayStatus = "Button #6 OFF";
      break;
// -----------------------------------------------------
  }
}

EDIT: moved setButtonFeedback from button #3 to button #5 (push button)
Added 1ms delay after while(mySerial.available())
Renamed to AndroTest V1.41 see Reply #225