//Add the SPI library so we can communicate with the ADXL345 sensor
#include <SPI.h>
#include <SoftwareSerial.h>

#define MESSAGE_BYTE_SIZE  2

void send_path_change_msg();

SoftwareSerial Bluetooth(5, 6); 
//Assign the Chip Select signal to pin 10.
int CS=10;

//This is a list of some of the registers available on the ADXL345.
//To learn more about these and the rest of the registers on the ADXL345, read the datasheet!
char POWER_CTL = 0x2D;	//Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32;	//X-Axis Data 0
char DATAX1 = 0x33;	//X-Axis Data 1
char DATAY0 = 0x34;	//Y-Axis Data 0
char DATAY1 = 0x35;	//Y-Axis Data 1
char DATAZ0 = 0x36;	//Z-Axis Data 0
char DATAZ1 = 0x37;	//Z-Axis Data 1
 unsigned long count;

uint8_t auto_mode_change_message[2];
uint8_t wait_mode_change_message[2];
uint8_t path_change_msg[2];

int current_path;

const int SEND_WAITING = 0;
const int SEND_AUTO = 1;
int currentState;
unsigned long path_change_timeout;

void auto_send_mode_change_message()
{
  Bluetooth.write(auto_mode_change_message, MESSAGE_BYTE_SIZE);
}

void wait_send_mode_change_message()
{
  Bluetooth.write(wait_mode_change_message, MESSAGE_BYTE_SIZE);
}

//This buffer will hold values read from the ADXL345 registers.
char values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
float x,y,z;
float xg,yg,zg;
float mag;

unsigned long last_millis;
void setup(){ 
  count = 0;
  // Start serial for sending via bluetooth
  Serial.begin(9600);
  // fill out the mode change message for auto. mode
  auto_mode_change_message[0] = 0x12;
  auto_mode_change_message[1] = 0x03;
  // mode change message for waiting mode
  wait_mode_change_message[0]= 0x12;
  wait_mode_change_message[1] = 0x01;
  // path change msg
  current_path = 0;
  path_change_msg[0] = 0x42;
  path_change_msg[1] = current_path;
  
  currentState = SEND_AUTO;
  
 
  
  //Initiate an SPI communication instance.
  SPI.begin();
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);
  Bluetooth.begin(9600);
  
  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS, HIGH);
  
  //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
  writeRegister(DATA_FORMAT, 0x01);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(POWER_CTL, 0x08);  //Measurement mode  
}

void loop(){
  //Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
  //The results of the read operation will get stored to the values[] buffer.
  readRegister(DATAX0, 6, values);

  //The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
  //The X value is stored in values[0] and values[1].
  x = ((int)values[1]<<8)|(int)values[0];
  //The Y value is stored in values[2] and values[3].
  y = ((int)values[3]<<8)|(int)values[2];
  //The Z value is stored in values[4] and values[5].
  z = ((int)values[5]<<8)|(int)values[4];
  x=abs(x);
  y=abs(y);
  z=abs(z);
   xg = x * 0.0078;
  yg = y * 0.0078;
  zg = z * 0.0078;
  //xg=abs(xg);
  //yg=abs(yg);
  //zg=abs(zg);
  
  //xg=pow(xg,2);
  //yg=pow(yg,2);
  //zg=pow(zg,2);
  //mag=zg + yg+ zg;
  //mag=sqrt(mag);
  //Print the results to the terminal.
//  Serial.print(xg, DEC);
//  Serial.print(", ");
//  Serial.print(yg, DEC);
//  Serial.print(", ");
//  Serial.println(zg, DEC); 
  
 if (currentState == SEND_AUTO)
 {
  // Serial.println("Auto Mode");
   if ( (xg >= 0.6 || yg >= 0.6) && zg >= 0.8){
     auto_send_mode_change_message();
     currentState = SEND_WAITING;
     path_change_timeout = millis();
   }
 }
 else if (currentState == SEND_WAITING)
 {
   //Serial.println("Waiting mode");
   if ( (xg < 0.6 || yg < 0.6) && zg > 0.8){
     unsigned long current_millis = millis();
     if (current_millis - last_millis > 5000)
     {
       wait_send_mode_change_message();
       currentState = SEND_AUTO;
       last_millis = millis();
     }
   }
   else
   {
     // change paths every 10 seconds
     if (millis() - path_change_timeout > 10000)
     {
       current_path++;
       if (current_path > 3) current_path = 0;
       
       path_change_msg[1] = current_path;
       
       send_path_change_msg();
       path_change_timeout = millis();
     }
     last_millis = millis();
   }

 }
 
}

void read_bt_message()
{
  char buff[2];
  for (int i = 0; i < 2; i++)
  {
    buff[i] = Bluetooth.read();
  }
  
  // Assume we got ack message
  
}

void send_path_change_msg()
{
  Bluetooth.write(path_change_msg, MESSAGE_BYTE_SIZE);
}

//This function will write a value to a register on the ADXL345.
//Parameters:
//  char registerAddress - The register to write a value to
//  char value - The value to be written to the specified register.
void writeRegister(char registerAddress, char value){
  //Set Chip Select pin low to signal the beginning of an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the register address over SPI.
  SPI.transfer(registerAddress);
  //Transfer the desired register value over SPI.
  SPI.transfer(value);
  //Set the Chip Select pin high to signal the end of an SPI packet.
  digitalWrite(CS, HIGH);
}

//This function will read a certain number of registers starting from a specified address and store their values in a buffer.
//Parameters:
//  char registerAddress - The register addresse to start the read sequence from.
//  int numBytes - The number of registers that should be read.
//  char * values - A pointer to a buffer where the results of the operation should be stored.
void readRegister(char registerAddress, int numBytes, char * values){
  //Since we're performing a read operation, the most significant bit of the register address should be set.
  char address = 0x80 | registerAddress;
  //If we're doing a multi-byte read, bit 6 needs to be set as well.
  if(numBytes > 1)address = address | 0x40;
  
  //Set the Chip select pin low to start an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the starting register address that needs to be read.
  SPI.transfer(address);
  //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<numBytes; i++){
    values[i] = SPI.transfer(0x00);
  }
  //Set the Chips Select pin high to end the SPI packet.
  digitalWrite(CS, HIGH);
}
