//justin downs  johnhenryshammer.com

//code developed with Daniel Soltis and Rob Faludi
//Code that packages a API serial series 2 packet
//packageData function is NOT NEEDED for the xbee communication 
// it is used for passing info as ASCII chars, just comment out.
 
//sendData function takes an array of BYTES and sends them to the specified 
//address
 
 
//char a[6]; // extra if not using malloc 
int dataSize =0;// for passing data array
 
long mydata;
long destination[]={0x0013A200,0x400A2391}; //Des highbyte, Des lowByte
#define led 7
 
 
//function defs
byte* packageData(byte _start,byte _stop,long _data);
byte* packageDataChar(char _start,char _stop,long _data);
long dePackageData(byte* _data, byte _start, byte _stop);                      //default local address to zero
boolean sendData(byte* data,int _dataLength, long* _destination,char _tagByte,int _localAdress=0xFFFE);
long ArrayLookChars(byte* _array);
long test = 0;
void tests(char* data,int _length);
 
 
 
void setup() {
  Serial.begin(9600);
  //  pinMode(led,OUTPUT);
 
}
 
 
void loop() {
 
  //SerialLookChars();
  
  sendData(packageDataChar('a','b', test),dataSize, destination,'T');
  test+=1000;
 //int dataLength = (sizeof(DATAss) / sizeof(DATAss[0]));
 // sendData(DATAss,11, destination,'T');
  //tests(DATAss,dataLength); 
 // Serial.println("test"+ test);
 //Serial.println(ArrayLookChars(packageDataChar('a','b', test)));//test 
 // Serial.println(dePackageData(packageData(0x41,0x7F, test), 0x41,0x7F));//test
  //sendData(packageData(0x41,0x7F, test),dataSize, destination,'T');
  //dataLength = (sizeof(_data));// / sizeof(_data[0]));
  delay(100);
 
}
 
 
void tests(char* data,int _length){
  Serial.print("start");
  for(int i=0; i<_length;i++){
   
    Serial.print(data[i]);
   
  }
  
  
}
 
// function that puts together a data packet and transmits it, using 64-bit addressing
//USES TAGBYTE TO SIGNAL START OF PACKET (not needed for transmission comment out if desired)
boolean sendData(byte* data, int _dataLength,long* _destination, char _tagByte,int _localAdress) {
  int dataLength = _dataLength;
  //strlen dosen't work with num conversion because of null use only with letter strings
  // dataLength =(strlen(data)); // length of data when using CHAR ARRAYS ONLY
  static byte frameID = 0xA1;
  frameID++; // add one to the frame ID each time, okay to overflow
  if (frameID == 0) frameID = 1; //skip zero because this disables status response packets
  byte checksum = 0xFF; // checksums are the hex FF minus the total of all bytes
  // calculate length of the packet
  // API identifier + frameId + 8bytes 64-bit addr 
  // + 2 bytes 16-bit addr + broadcast radius
  // + options + ***TAGBYTE***
  int length = (dataLength + 14 + 1);  // last one is tagByte
  // send the packet
  Serial.print(0x7E, BYTE); // send start delimiter
  Serial.print(0x0, BYTE);  // send length MSB (always zero because packets can't be more than 100 bytes)
  Serial.print(length, BYTE); // send length LSB
  Serial.print(0x10, BYTE); // send API command identifier
  checksum = checksum - 0x10;  // minus from checksum FF
  Serial.print(frameID, BYTE); // send frame ID (set to 0 if noresponse is required)
  checksum = checksum - frameID;
 
  // set  the 64 bit factory address long high byte then low
  for(int i=0;i < 2; i++){ // address never bigger than 2
    for (int j = 4; j > 0; j--) {
      byte destinationByte = _destination[i] >> 8 * (j-1); // shift over one byte at a time, MSB first 4 for long
      Serial.print(destinationByte, BYTE);  // send destination address
      checksum = checksum - destinationByte;
    }
  }
 
 
   // break up local address and send it
  byte localLow = _localAdress;
  byte localHigh = _localAdress >> 8;
  //send 16-bit address as unkown FUNCTION 
  Serial.print(localHigh,BYTE);   //send unknown for 16-bit address FF
  checksum = checksum-localHigh;
  Serial.print(localLow,BYTE);   //send unknown for 16-bit address  FE
  checksum = checksum - localLow;
  Serial.print(0x0,BYTE); //send broadcast radius
  checksum = checksum - 0x0;
  Serial.print(0x0,BYTE); //send option byte about multicasting
  checksum = checksum - 0x0;
  //////******start data *****\\\\\\\\\\
  // send TAGBYTE as first byte in data
  Serial.print(_tagByte,BYTE); // marker byte
  checksum = checksum - _tagByte;
  //send all data in array
  byte thisbyte;
  for (int i = 0; i < dataLength ; i++){
     thisbyte = data[i]; 
    Serial.print(thisbyte,BYTE);
    checksum = checksum - thisbyte;
  }
   
 
  Serial.print(checksum,BYTE); //  send checksum
  free(data); //comment out if not using PACKAGEDATA
 
 
  return true;
 
}
 
 
//*** code for packaging data not needed ***
 
// PACKAGES DATA into a char array with start and stop tag, can be used with int, long, byte, char
byte* packageData(byte _start,byte _stop,long _data){
  // get array, be sure to use with free() in SENDDATA function to get rid of allocated memory
  dataSize =int((sizeof(_start)*2)+sizeof(_data));
  byte* a = (byte*) malloc(dataSize);// get memory, be sure to call free in sendData or it blows real quick 
  if(a == NULL) {
    Serial.println("brain damaged");
  }
  // data + two start stop bytes
  a[0]= _start; // set start 
  for(int i =1; i<(sizeof(_data)+1); i++){// for whatever data in this case a long
    a[i] =_data >> 8 *(4-i);    
  }
  a[5] =_stop;  // set stop CORUPTS VALUE ONCE A CYCLE
    return a;
}
 
 
 
 
// PACKAGES DATA into a char array with start and stop tag, can be used with int, long, byte, char
byte* packageDataChar(char _start,char _stop,long _data){
   char dataNum[sizeof(_data)*8+1]; //get array the size of data
   ltoa (_data,dataNum,10); // convert long use itoa to chars 0-9
  // Serial.println(int(strlen(dataNum)));
   dataSize =((sizeof(_start)*2) + (strlen(dataNum))); // global not really needed how many in arry '1','0','9' ect
  // get array, be sure to use with free() in SENDDATA function to get rid of allocated memory
  byte* a = (byte*) malloc(strlen(dataNum));// get memory, be sure to call free in sendData or it blows real quick 
  if(a == NULL) {
    Serial.println("brain damaged");
  }
   
  // data + two start stop bytes
  a[0]= byte(_start); // set start
 int i = 0; 
  while (dataNum[i] != '\0'){ // put number chars in data arry return
    a[i+1] = byte(dataNum[i]);
      i++;  
  }
   a[i+1] = byte(_stop);  // set stop 
    return a;
}