//Arduino code for controlling a MicroMag3 magnetometer through SPI
//by Daniel Soltis


#define SCLK 7 //the clock to pulse
#define MISO 6 //master in, slave out
#define MOSI 5 //master out, slave in
#define SSNOT 4 //when low, the device is enabled
#define DRDY 3 //this is low after a reset, high when data is ready
#define RESET 2 //this needs to be toggled low-high-low before each measurement

long x = 0;
long y = 0;
long z = 0;

void setup(){
  Serial.begin(9600);

  pinMode(SSNOT, OUTPUT);
  pinMode(RESET, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(DRDY, INPUT);
  pinMode(SCLK, OUTPUT);

  //i could just ground this line, but this at least marks it as
  //something that one could change if needed
  digitalWrite(SSNOT, LOW);
}

void loop(){
  if (Serial.available()){
    //this reads the x, y, and z axes sequentially
    readaxis(0);
    readaxis(1);
    readaxis(2);
    //at the end of the cycle, send a return to indicate that the cycle is over
    Serial.print(13,BYTE);
  }
}

void send_bit(int _high){

  //this sends the bit on the rising edge of the clock

  digitalWrite(MOSI, _high);
  delay(2);
  digitalWrite(SCLK, HIGH);
  delay(2);
  digitalWrite(SCLK, LOW);
  delay(2);
}

int receive_bit(){

  //this receives the data on the falling edge of the clock

  digitalWrite(SCLK, HIGH);
  delay(2);
  int bit = digitalRead(MISO); 
  delay(2);
  digitalWrite(SCLK, LOW);
  delay(2);
  return bit;
}

int readaxis(int _axis){
  //this function sends eight bits, waits until the data is ready
  //and receives 16 bits

    //pulse the reset
  digitalWrite(RESET, LOW);
  delay(2);
  digitalWrite(RESET, HIGH);
  delay(2);
  digitalWrite(RESET, LOW);
  delay(2);

  //send the command byte

  //this sends data that we are not in debug mode
  //and sets the amount of time to read the magnetic sensors (the ASIC period)
  //as /2048 
  send_bit(LOW);
  send_bit(HIGH);
  send_bit(HIGH);
  send_bit(LOW);
  send_bit(LOW);
  send_bit(LOW);

  //the last two bits select the axis
  if (_axis == 0){ //x axis
    send_bit(LOW);
    send_bit(HIGH);
  }
  else if (_axis == 1){ //y axis
    send_bit(HIGH);
    send_bit(LOW);
  }
  else{ //z axis
    send_bit(HIGH);
    send_bit(HIGH);
  }

  //wait until the drdy line is high
  while (digitalRead(DRDY) == LOW){
    //wait
    //Serial.println("waiting"); 
  }
  //Serial.println("data!");

  long runningtotal = 0;

  //receive the results and tally them up as they come in 

  //the leftmost bit signs the number as positive or negative
  long sign = receive_bit();

  //the remaining bits need to be translated from individual bits into an integer
  for (int i = 14; i >= 0; i = i - 1){
    long thisbit = receive_bit();
    thisbit = thisbit << i;
    runningtotal = runningtotal | thisbit;
  }

  if (sign == 1){
    runningtotal = runningtotal - 32768; 
  }

  //this sends the data over the serial line, as a string separated by commas
  if (_axis == 0){
    x = runningtotal;
    Serial.print(x,DEC);
    Serial.print(44, BYTE);
  }
  else if (_axis == 1){
    y = runningtotal;
    Serial.print(y,DEC);
    Serial.print(44, BYTE);
  }
  else{
    z = runningtotal; 
    Serial.print(z,DEC);
    Serial.print(44, BYTE);
  }
}