//In JAVA justin downs  johnhenryshammer.com



// Code that will parse a XBEE API Series2 receive packet started from Rob Faludis/Dan Shiftman API series 1 lib
 
// It is broken into functions for Debugging and for easier use with a microcontroller time out
// for program flow. It is not needed for raw parsing and
//runs faster without funcs. Just decomment.
 
//** There is also code for transmitting serial as ASCII you don't have to use those
//funcs for the XBEE, just disregard and don't use the dePackageData func.
 
 
 
//set up and run stuff
import processing.serial.*;
Serial port;  // Create object from Serial class
 
 
int num[] = new int[3];
int points[]= new int[WIDTH];
int beats=0;
//char[] dataIn = new char[20];
 byte id = 10;
 
 
void setup() 
{
  println(Serial.list());
 
  
  frameRate(30);
  // Open the port that the board is connected to and use the same speed (9600 bps)
  port = new Serial(this,Serial.list()[2], 9600);
}
void draw()
{
 
  getData();
}
 
 
/* Function that receives API2 data which was sent using 16-bit addressing
   broken into functions for microcontroler timeout blocks. not needed on pc 
   runs slower.
*/
 
 
void getData() {
  //println("a");
  int timeout=100;
  int packetLength = 0;
  packetLength = checkHeader(timeout); // START BYTE AND PACKET LENGTH
  // println(packetLength);
  if (packetLength > 0 ) { // if we have a packet continue
    int apiIdentifier = getIdentifier(timeout); // GET ID
 
    char adress[] = getLongAdress(timeout);//GET LONG ADRESS
     /*char addrByte=0;
     while( port.available() < 8); // stop for bits
     char adress[]= new char[8];// array for address
     for (int i = 0; i<8; i++){
     addrByte =char( port.read());
     adress[i]=addrByte;
     // print(hex(addrByte));
     }
     */
 
    int localAdress =getLocaladdress(timeout);// GET LOCAL ADDRESS
    /*  while (port.available() < 2); // wait for at least two bytes to be available
     int localAd = port.read(); // read the most significant length byte
     int localAd2 = port.read(); // read the least significant length byte
     int localAdress = (localAd << 8) + localAd2; // put the two bytes together
     */
 
    char options = getOptions(timeout);//GET OPTION 
    /* while (port.available() < 1);
     char options = char(port.read()); // get the options 1 packet ack returned 2 brodcast
     */
   
    char[] dataIn = getInfo(packetLength,timeout);//GET INFO   
    /*
     //info packet
     char[] dataIn = new char[30];
     while (port.available() < (packetLength - 12));
     // println("packetLength22  "+packetLength);
     for (int i= 0; i < (packetLength - 12); i++) { // take out other info in packet + checksu
     println("packetLength  "+ packetLength);
      dataIn[i] = char(port.read()); // get a byte of data
     // println(hex(dataIn[i]));
     }
   */
    char checksum = getCheckSum(timeout); //GET CHECKSUM
    /*
    while (port.available() < 1);
     char checksum = char(port.read());
     */
 
 
    //printall 
    println("packetLength  "+packetLength);
    println("sent long address");
    for (int i = 0; i<8; i++){
      print(hex(adress[i]));
    }
    println();
    println ("local adress  "+hex(localAdress));
    println("options  "+hex(options));    
    println("info");
    for (int i= 0; i < (packetLength - 12); i++) { // take out other info in packet + checksum
      println(hex(dataIn[i]));
    }
     println("checksum  "+hex(checksum));
     
     
     
    // For ASCCII ***OPTIONAL
    println("data   " + ArrayLookChars(dataIn));
   
   
   //for non ASSCII parse **OPTIONAL
   /* char stop=char(127); // hex 7F
    println("data   " + dePackageData(dataIn,'A',stop));// calls below function
    */
  }
 
}
 
 
 
///Start XBee parse funcs 
 
 
 
 
int checkHeader(int timeout) { // timeout is in milliseconds set this to break from waiting for byte
  long startTime = millis();
  int Length = 0;
  int inByte = 0;
  
  // during the timeout period, if we haven't gotten the start byte yet...
  while (((millis() - startTime) < timeout) && (inByte != 0x7E)) {
    if (port.available() > 0) { // if a byte is waiting in the buffer
      inByte = port.read(); // read a byte from the buffer 
    }
  }
 
  // look at byte
  if (inByte == 0x7E) { // if we got the API start byte
    while (port.available() < 2); // wait for at least two bytes to be available
    int lengthMSB = port.read(); // read the most significant length byte
    int lengthLSB = port.read(); // read the least significant length byte
    Length = (lengthMSB << 8) + lengthLSB; // put the two bytes together
  }
 
 
  return Length;
}
 
 
    
    char getCheckSum(int _timeOut){
 char checksum ='Z';
 long startTime = millis();
    while (port.available() < 1 && ((millis() - startTime) <  _timeOut)); // wait for at least two bytes to be available
    if (port.available() > 0) { // if a byte is waiting in the buffer
    checksum = char(port.read());
    return checksum; // returns null if timed out
   }
   println("checksum");
    return '0'; // returns null if timed out
 }
 
 
// function that checks to see if the API Identifier matches a requested value
char getIdentifier(int _timeOut) {
  long startTime = millis();
 char apiIdentifier = 'Z'; // set apiIdentifier to an impossible value
  while (port.available() < 1 && (millis() - startTime) <  _timeOut) ; // wait for a byte or timeout
  if (port.available() > 0) { // if a byte is waiting in the buffer
    apiIdentifier = char(port.read());
    return apiIdentifier; // returns null if timed out
  }
   println("Identifier");
    return 'N'; // returns null if timed out
 
}
 
int getLocaladdress(int _timeOut){
 int localAdress =0;
 long startTime = millis();
    while (port.available() < 2 && ((millis() - startTime) <  _timeOut)); // wait for at least two bytes to be available
    if (port.available() > 0) { // if a byte is waiting in the buffer
    int localAd = port.read(); // read the most significant length byte
    int localAd2 = port.read(); // read the least significant length byte
    localAdress = (localAd << 8) + localAd2; // put the two bytes together
     return localAdress; // returns null if timed out
  }
   println("location");
    return '0'; // returns null if timed out
 }
 
 
char[] getLongAdress(int _timeOut){
  
  long startTime = millis();
   char addrByte = 'Z';
  while( port.available() < 8 && ((millis() - startTime) < _timeOut)); // stop for bits 
     char address[]= new char[8];// array for address
  if (port.available() > 0) { // if a byte is waiting in the buffer
       for (int i = 0; i<8; i++){
       addrByte =char( port.read());
       address[i]=addrByte;
       }
      return address; //returns null if timed out
  }
      println("Adresslong");
        return null;
}
 
 
char[] getInfo(int _packetLength, int _timeOut){
  
  long startTime = millis();
  char addrByte = 'Z';
  while (port.available() < (_packetLength - 12) && millis() - startTime < _timeOut); // stop for bits 
     char[] dataIn = new char[100]; // do malloc here
  if (port.available() > 0) { // if a byte is waiting in the buffer
      for (int i= 0; i < (_packetLength - 12); i++) { // take out other info in packet + checksu
        dataIn[i] = char(port.read()); // get a byte of data
       //  println("packetLength  "+ _packetLength);
        println("getinfo "+hex(dataIn[i]));
       }
      return dataIn; //returns null if timed out
  }
    println("info packet");
        return null;
}
 
 
 
 
 char getOptions(int _timeOut){
 char options ='Z';
 long startTime = millis();
    while (port.available() < 1 && ((millis() - startTime) <  _timeOut)); // wait for at least two bytes to be available
    if (port.available() > 0) { // if a byte is waiting in the buffer
     options = char(port.read()); // get the options 1 packet ack returned 2 brodcast
     return options; // returns null if timed out
  }
  println("Options");
    return '0'; // returns null if timed out
 }
 
 
 
 
//*** OPTIONAL **** Serial Packaging functions (optional not needed for xbee)
 
 
long dePackageData(char[] _data , char _start, char _stop) {    //can return a char int long or array
  long data=0;      // CHANGE HERE 
  // println(_data[0]);
  // println(_data[1]);
  if(_data[1] == _start){
    int i = 2; 
    while(_data[i] != _stop){ // variable will read till whenever you say stop
      data = data << 8; // data equals data shifted for place
      data += _data[i]; // add new eights place
      i++; // inc i to get new place
      // println(i);
    }
  }
 
  return data;
} 
 
//use with serialinput
long SerialLookChars() {
char ASCIIString[] = new char[100]; // in string
char inByte='c'; 
long number = 0; // return number
int stringPos = 0; // keeps track of places in number
if ('a' == port.read()){ // for id parsing of serial
while(inByte !='b'){
inByte = char(port.read());
// save ASCII numeric characters in string:
if ((inByte >= '0') && (inByte <= '9')){
// Serial.println( inByte);
ASCIIString [stringPos] = inByte;
stringPos++;
// Serial.println( stringPos);
}
}
}
port.clear(); // flush junk
number = SerialToInt( ASCIIString,stringPos ); /// convert captured string to an int
 
stringPos = 0; //reset count num 
//if (number !=0)Serial.println(number);//DEBUG
return number;
}
 
 
// use with parsed array array
long ArrayLookChars(char[] _array) {
char ASCIIString[] = new char[100]; // in string
char inByte ='z';
long number = 0; // return number
int stringPos = 0; // keeps track of places in number
int i = 2;
if ('a' == _array[1] ){ // for id parsing of serial
while(_array[i] != 'b'){ /// FIRST ONE IS T FOR TAG byte
inByte =_array[i];
i++;
if (i > 90) break; ///FOR PROCESSING, second run of program always fucks buffer
// save ASCII numeric characters in string:
if ((inByte >= '0') && (inByte <= '9')){
ASCIIString [stringPos] = inByte;
stringPos++;
 
}
}
}
println( "array"+ASCIIString[0] +ASCIIString[1]+ASCIIString[2]+ASCIIString[3]+ASCIIString[4]);
number = SerialToInt( ASCIIString,stringPos ); /// convert captured string to an int
stringPos = 0; //reset count num 
//if (number !=0)Serial.println(number);//DEBUG
return number;
}
 
 
/*****************
the important parts of the function conversions 
are to have a inverting for loop go 
from last in array to first and call the plusBaseTen()function
each time.
*******************/
 
// hits up the number by base ten powered
long timesBaseTen(int _move){ // the
long place = 1; //base 10
int n = 0;
if( _move < 1){ return 1;}//ones place no change
else{
for( n= 0; n<_move; n++){ place = place*10;}
}return place;
} 
 
 
 
// converts a ten digit ASCII to int
long SerialToInt(char[] _input, int _arrayLength){
long number=0;
long total=0;
int arrayLook=0;
int i = 0;
int arrayLength =_arrayLength-1; // need one less than actual length 0 is 1
// call invert string for proper string power order
for(i =arrayLength; i >= 0;i--){ 
// Serial.println(i);
// Serial.println(_input[i]); 
// picks out ASCII numbers for error check
if ((_input[i] >= '0') && (_input[i]<= '9')){
println ("INPUT"+ _input[i]);
     // processing does not seem to understand Integer class it is stupid, should have done it in eclipse
 switch( _input[i]){
 case '0' : number =0;
 break; 
 case '1' : number =1;
 break; 
 case '2' : number =2;
 break; 
 case '3' : number =3;
 break; 
 case '4' : number =4;
 break; 
 case '5' : number =5;
 break; 
 case '6' : number =6;
 break; 
 case '7' : number =7;
 break; 
 case '8' : number =8;
 break; 
 case '9' : number =9;
 break;   
   
 }
 
 
println ("NUMBER"+ number);
number = (number * (timesBaseTen(arrayLook))); // puts number in its place
arrayLook++;
total = number+total;
}
}
return total; 
}