/*
 * Original Sketch from DFRobot.com
 * Modified by Alex Wulff (www.AlexWulff.com)
 * on 7/25/19
 */

#include "Lib_I2C.h"
#include "DFRobot_AS3935_I2C.h"

#define AS3935_CAPACITANCE  96
// Indoor/outdoor mode selection
#define AS3935_INDOORS      0
#define AS3935_OUTDOORS     1
#define AS3935_MODE         AS3935_INDOORS
// Enable/disable disturber detection
#define AS3935_DIST_DIS     0
#define AS3935_DIST_EN      1
#define AS3935_DIST         AS3935_DIST_EN
// I2C address
#define AS3935_I2C_ADDR     AS3935_ADD3

#define IRQ_PIN             0
#define BUZZ                11
#define LIGHT               13

void AS3935_ISR();
DFRobot_AS3935_I2C  lightning0((uint8_t)IRQ_PIN, (uint8_t)AS3935_I2C_ADDR);

// Needs to be voltatile because this variable is accessed in an ISR
volatile int8_t AS3935_ISR_Trig = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("Lightning Sensor Start");

  I2c.begin();
  I2c.pullup(true);
  I2c.setSpeed(1);
  delay(2);

  lightning0.defInit();
  lightning0.manualCal(AS3935_CAPACITANCE, AS3935_MODE, AS3935_DIST);
  attachInterrupt(digitalPinToInterrupt(IRQ_PIN), AS3935_ISR, RISING);

  pinMode(BUZZ, OUTPUT);
  pinMode(LIGHT, OUTPUT);
}

void loop()
{
  // blink light while waiting for lightning
  while (AS3935_ISR_Trig == 0) {
    digitalWrite(13, HIGH); 
    delay(200); 
    digitalWrite(13, LOW); 
    delay(200);
  }
  
  delay(5);

  // Reset interrupt flag variable
  AS3935_ISR_Trig = 0;
  
  // Get interrupt source
  uint8_t int_src = lightning0.getInterruptSrc();

  // lightning nearby
  if (int_src == 1) {
    uint8_t lightning_dist_km = lightning0.getLightningDistKm();

    if (lightning_dist_km == 1) {
      Serial.println("Lightning overhead!");
    }
    
    else if ((lightning_dist_km >= 5) && (lightning_dist_km <= 40)) {
      Serial.println("Lightning occurs!");
      Serial.print("Distance: ");
      Serial.print(lightning_dist_km);
      Serial.println(" km");
    }
    
    else if (lightning_dist_km == 0x3F){
      Serial.println("Out of range.");
    }

    // Get lightning energy intensity
    uint32_t lightning_energy_val = lightning0.getStrikeEnergyRaw();
    Serial.print("Intensity: ");
    Serial.print(lightning_energy_val);
    Serial.println("");

    // round to nearest tens place
    float distf = (float)lightning_dist_km;
    int dist_tens = (int)roundf(distf / 10);
    
    // buzz to get attention
    for (int i = 0; i < 20; i++) {
      digitalWrite(BUZZ, HIGH);
      delay(25);
      digitalWrite(BUZZ, LOW);
      delay(25);
    }

    if (lightning_dist_km <= 5) {dist_tens = 1;}

    // buzz to indicate distance
    for (int i = 0; i < dist_tens; i++) {
      digitalWrite(BUZZ, HIGH);
      delay(1000);
      digitalWrite(BUZZ, LOW);
      delay(1000);
    }
  }

  // interference detected
  else if (int_src == 2)
  {
    for (int i = 0; i < 3; i++) {
      digitalWrite(LIGHT, HIGH);
      delay(200);
      digitalWrite(LIGHT, LOW);
      delay(200);
    }
    
    Serial.println("interference detected");
  }

  // too much noise
  else if (int_src == 3)
  {
    for (int i = 0; i < 5; i++) {
      digitalWrite(LIGHT, HIGH);
      delay(100);
      digitalWrite(LIGHT, LOW);
      delay(100);
    }
    Serial.println("Noise level too high!");
  }

}

//ISR function just sets the flag to 1
void AS3935_ISR()
{
  AS3935_ISR_Trig = 1;
}
