/*************************************************** 
  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815
  
  These drivers use I2C to communicate, 2 pins are required to  
  interface.

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);

// Depending on your servo make, the pulse width min and max may vary, you 
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define WIGGLE_CENTER 125 // value at which the wiggler motor is centered
#define SERVOMIN  WIGGLE_CENTER-75 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  WIGGLE_CENTER+75 // This is the 'maximum' pulse length count (out of 4096)
#define USMIN  900 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX  2500 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
#define CONT_STABLE 1355 // value at which the continuous rotation servo is not moving -- will vary per motor
#define PLOP_UPRIGHT 1650 // value at which the plopper motor/trough is right side up -- will vary per motor/position


const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
int sensorValue = 0;
int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value

void setup() {
  pinMode(analogInPin, INPUT);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Hot Dog!");
  pwm.writeMicroseconds(12, CONT_STABLE);
  pwm.setPWM(13, 0, WIGGLE_CENTER);
  pwm.setPWM(14, 0, PLOP_UPRIGHT);
  
  Serial.println("Calibrating...");
  // calibrate during the first five seconds
  while (millis() < 5000) {
    sensorValue = analogRead(analogInPin);
  Serial.print("calibration sensor = ");
  Serial.println(sensorValue);
    // record the maximum sensor value
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
      Serial.println("Setting new sensorMax");
    }

    // record the minimum sensor value
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
      Serial.println("Setting new sensorMin");
    }
  }
  Serial.println("... Finished calibrating.");

  pwm.begin();
  /*
   * In theory the internal oscillator (clock) is 25MHz but it really isn't
   * that precise. You can 'calibrate' this by tweaking this number until
   * you get the PWM update frequency you're expecting!
   * The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
   * is used for calculating things like writeMicroseconds()
   * Analog servos run at ~50 Hz updates, It is importaint to use an
   * oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
   * 1) Attach the oscilloscope to one of the PWM signal pins and ground on
   *    the I2C PCA9685 chip you are setting the value for.
   * 2) Adjust setOscillatorFrequency() until the PWM update frequency is the
   *    expected value (50Hz for most ESCs)
   * Setting the value here is specific to each individual I2C PCA9685 chip and
   * affects the calculations for the PWM update frequency. 
   * Failure to correctly set the int.osc value will cause unexpected PWM results
   */
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  delay(10);
}

// You can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. It's not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;
  
  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= SERVO_FREQ;   // Analog servos run at ~60 Hz updates
  Serial.print(pulselength); Serial.println(" us per period"); 
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit"); 
  pulse *= 1000000;  // convert input seconds to us
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
// read the analog in value:
  sensorValue = analogRead(analogInPin);
  // apply the calibration to the sensor reading
  //sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 1023);
  // in case the sensor value is outside the range seen during calibration
  //sensorValue = constrain(sensorValue, 0, 1023);
   Serial.print("sensor = ");
  Serial.println(sensorValue);

  //read the pushbutton value into a variable
  int greenbuttonVal = digitalRead(4);
  int redbuttonVal = digitalRead(3);
  Serial.println(greenbuttonVal);
  Serial.println(redbuttonVal);

  // Keep in mind the pull-up means the pushbutton's logic is inverted. It goes
  // HIGH when it's open, and LOW when it's pressed.
  if (greenbuttonVal == HIGH && redbuttonVal == HIGH) {
     if (sensorValue > (.90*sensorMax)) {
      pwm.writeMicroseconds(12, CONT_STABLE);
      pwm.setPWM(13, 0, WIGGLE_CENTER);
      delay(20);
  } else if (sensorValue <= (.90*sensorMax)){ //squeeze mustard
      applyMustard();
      //delay(200);
      dumpOnions();
  }
  } else if (greenbuttonVal == LOW){ //reel it in
  pwm.writeMicroseconds(12, CONT_STABLE+15);
  }else if (redbuttonVal == LOW){ //reel it out
  pwm.writeMicroseconds(12, CONT_STABLE-15);
  }
}

void applyMustard(){
  Serial.println("applying mustard");
pwm.writeMicroseconds(12, CONT_STABLE+15);
delay(500);
for (int i=0; i<9; i++){
      for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
        pwm.setPWM(13, 0, pulselen);
      }

  //delay(500);
      for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
        pwm.setPWM(13, 0, pulselen);
      }
}
pwm.setPWM(13, 0, WIGGLE_CENTER);
pwm.writeMicroseconds(12, CONT_STABLE-15);
delay(500);
 pwm.writeMicroseconds(12, CONT_STABLE);
  
}

void dumpOnions(){
  Serial.println("applying onions");
   for (uint16_t pulselen = PLOP_UPRIGHT; pulselen > 0; pulselen--) {
      pwm.setPWM(14, 0, pulselen);
    }
    delay(7000);
    
    for (uint16_t pulselen = 0; pulselen < PLOP_UPRIGHT; pulselen++) {
      pwm.setPWM(14, 0, pulselen);
     }

  
    
}
