 // -------------------------
 //        Settings
 // -------------------------
-const bool debug = true;       //true = write to serial monitor, false = bypass
-const int serialOutLoops = 000; //Number of loops that should execute before a serial write
+const bool debug = false;       //true = write to serial monitor, false = bypass
+const int serialOutLoops = 300; //Number of loops that should execute before a serial write
 //Ignition Settings
 const int dwell = 2500;         //Ignition coil charging dwell in microseconds (2.5ms = 2500us)
-const long periodMax = 2000000; //Maximum period between ignitions, in microseconds (min frequency)
+const long periodMax = 1000000; //Maximum period between ignitions, in microseconds (min frequency)
 const long periodMin = 5000;    //Minimum period between ignitions, in microseconds (max frequency)
 const int periodCorrection = 0; //Variance to period due to loop code execution time (milliseconds)
-const float linearity = 2.5;    //1.0 = linear, 0.5 = more resolution in the high end, 2.0 = more resolution in the low end (exponential)
+const float linearity = 3.0;    //1.0 = linear, 0.5 = more resolution in the high end, 2.0 = more resolution in the low end (exponential)
 const bool triggerHigh = true;  //true = HIGH to fire, false = LOW to fire
 //Multifire Settings
-const bool multiFire = false;    //true = fire [firingCount] times per period, false = fire once per period
+const bool multiFire = true;    //true = fire [firingCount] times per period, false = fire once per period
 const int multiCount = 3;       //Numeber of sparks to fire per event
 const int multiDelay = 2000;    //Delay between multifires in microseconds (2ms = 2000us)
 //Tachometer Settings

void fireCoil()
{
  chargeCoil();
  delayMicroseconds(dwell);
  dischargeCoil();
}


  }
}

// -------------------------
//          Methods
// -------------------------
bool isActive() 
{
  return digitalRead(ACTIVATION_PIN) == activeState;
}

long getPeriod()
{
  int frequency = analogRead(FREQUENCY_PIN);
  
  float percentage = frequency / 1023.0;
  
  if (debug && loopsSinceSerialWrite >= serialOutLoops)
  {
    Serial.print("Frequency: ");
    Serial.print(frequency);
    Serial.print("(");
    Serial.print(percentage * 100);
    Serial.print("%), ");
  }
  
  return periodMin + (periodMax - periodMin) * pow(percentage, linearity) + periodCorrection;
}

unsigned int getRPM()
{
  noInterrupts();
  unsigned long current = tachCurrent;
  unsigned long previous = tachPrevious;
  interrupts();
  
  if (isStale())
  {
    tachDuration0 = 0;
    tachDuration1 = 0;
    tachDuration2 = 0;
    return 0;
  }
  
  unsigned long duration;
  if (current >= previous)
  {
    duration = current - previous + tachTrim;
  }
  else
  {
    //Handle Rollover
    duration = 0xFFFFFFFFu - previous + current + tachTrim;
  }
  
  //Shift the values
  tachDuration2 = tachDuration1;
  tachDuration1 = tachDuration0;
  tachDuration0 = duration;
  
  if (false && debug && loopsSinceSerialWrite >= serialOutLoops)
  {
    Serial.print("t0: ");
    Serial.print(tachDuration0);
    Serial.print(", t1: ");
    Serial.print(tachDuration1);
    Serial.print(", t2: ");
    Serial.print(tachDuration2);
    Serial.print(", ");
  }
  
  if (tachDuration0 <= 0 || tachDuration1 <= 0 || tachDuration2 <= 0)
    return 0;
  
  //Calculate Weighted Average duration
  unsigned long average = (3*tachDuration0 + 2*tachDuration1 + 1*tachDuration2)/6;
  
  //Convert to RPM
  return 60.0 * 1000000 / average;
}

bool isStale()
{
  return (micros() - tachCurrent) > tachStale;
}

void enableCoil()
{
  //Enable Coil Firing
  ignitionMode = DWELL;
}

void disableCoil()
{
  //Disable Coil Firing
  ignitionMode = OFF;
}

void chargeCoil()
{
  digitalWrite(EXTERNAL_LED_PIN, HIGH);
  digitalWrite(INTERNAL_LED_PIN, HIGH);
  
  if (triggerHigh)
    digitalWrite(IGNITION_PIN, HIGH);
  else
    digitalWrite(IGNITION_PIN, LOW);
}

void dischargeCoil()
{
  if (triggerHigh)
    digitalWrite(IGNITION_PIN, LOW);
  else
    digitalWrite(IGNITION_PIN, HIGH);
    
  digitalWrite(EXTERNAL_LED_PIN, LOW);
  digitalWrite(INTERNAL_LED_PIN, LOW);
}

void fireMultiple()
{
  fireCoil();
  for(int i = 1; i < multiCount; i++)
  {
    delayAtLeast(multiDelay);
    fireCoil();
  }
}
