#include "LowPower.h"
#include <PinChangeInt.h>
#include <RFM69.h>
#include <SPI.h>

// Attemtping to see if it works with RFM69 chip
// This is more complex example of using hardware interrupt. Button is connected to both INT pin and some other pin.
// When INT is initiated it polls other pin to see if button state changed. This is useful when you have more tha one button
// but only one hardware interrupt pin. All buttons connect to both interrupt pin and other pins.
// Uses hardware interrupt pin (INT1 a.k.a. D3) to monitor when button press
// Also debounces input
#define BUTTON1_PIN 4
#define BUTTON2_PIN A0
#define DEBOUNCE_TIME 20 // Debounce time in ms
#define AWAKE_TIME 5000 // Time to stay away before sleeping
byte myLED=9;

#define NODEID      99
#define NETWORKID   100
#define GATEWAYID   1
#define FREQUENCY   RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY         "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define ACK_TIME    30  // # of ms to wait for an ack
RFM69 radio;

byte buttonPIN[2]={BUTTON1_PIN,BUTTON2_PIN};//array of pin definitions
boolean isButtonPressed=false; // This var modified by ISR function
static unsigned long last_interrupt_time = 0; // Keeps track of time for debouncing
boolean currentState[2]={HIGH,HIGH}; // Keeps state of buttons
boolean lastState[2]={HIGH,HIGH};
boolean debouncedState[2] = {HIGH,HIGH};
unsigned long timeOfLastButtonEvent[2] = {0,0};//store the last time the button state changed
int activeButton=0;

void setup() {
  Serial.begin(115200);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.encrypt(KEY);
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  pinMode(BUTTON1_PIN,INPUT_PULLUP); // Enables internal 20K pullup
  pinMode(BUTTON2_PIN,INPUT_PULLUP); // Enables internal 20K pullup
  pinMode(myLED,OUTPUT);      // set LED_PIN as an output so we can use LED to monitor
  PCintPort::attachInterrupt(BUTTON1_PIN, button_ISR,FALLING); // attach a PinChange Interrupt to our pin on the rising edge
  PCintPort::attachInterrupt(BUTTON2_PIN, button_ISR,FALLING); // attach a PinChange Interrupt to our pin on the rising edge
}

void loop() {
   buttonProc(activeButton);
   sleepNow();
 
}

void sleepNow(void)
{
 if (millis()-last_interrupt_time > AWAKE_TIME) {
   digitalWrite(myLED ,LOW);   // turn LED off to indicate sleep
   delay (50);  
   Serial.println ("Sleeping");
   last_interrupt_time=millis();
   delay (100);
   LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); 
 }
    
   
}

// Process buttons logic
void buttonProc(byte butNum) {
  currentState[butNum]=digitalRead (buttonPIN[butNum]);
    unsigned long currentTime = millis();
    if (currentState[butNum] != lastState[butNum]){
      timeOfLastButtonEvent[butNum] = currentTime;
    }
    if (currentTime - timeOfLastButtonEvent[butNum] > DEBOUNCE_TIME){//if enough time has passed
      if (currentState[butNum] != debouncedState[butNum]){//if the current state is still different than our last stored debounced state
        debouncedState[butNum] = currentState[butNum];//update the debounced state
        //trigger an event
        if (debouncedState[butNum] == LOW) {
          Serial.print("Button "); Serial.print (butNum); Serial.println (" pressed");
          sendData();
         isButtonPressed=false; 
         digitalWrite (myLED, HIGH);
         last_interrupt_time=millis();
        }
       // } else {
        //  Serial.println("released");
        //}
      }
    }
    lastState[butNum] = currentState[butNum];
}

// Interrupt without debounce
void button_ISR() {
  // isButtonPressed=true;
  if (digitalRead(buttonPIN[0])==LOW )activeButton=0;
  if (digitalRead(buttonPIN[1])==LOW )activeButton=1;
   last_interrupt_time=millis();
  // Serial.println ("Awake");
}

// Recieves transmission and parse it
void recieveData() {
  if (radio.receiveDone())
  {
      Serial.print("Data recieved");
      for (byte i = 0; i < radio.DATALEN; i++) 
        Serial.print((char)radio.DATA[i]); // Print out characters received
      if (radio.ACKRequested())
      {
        radio.sendACK();
        Serial.print(" - ACK sent");
      }
   
  }
 // radio.sleep();
}

void sendData() {
  char buffer[17];
  Serial.print ("Sending: ");
  snprintf(buffer, sizeof(buffer),"Button %d pressed",activeButton); 
  Serial.println (buffer);
  if (radio.sendWithRetry(GATEWAYID, buffer, sizeof(buffer))) Serial.println ("Transmission OK");
  else  Serial.println ("Transmission ERROR");
}
