////////////////////////////////////////////////////////////////////////////////////////////////////
//ANDRUINO LIBRARY
//A.Scavuzzo
//www.andruino.it
//PINS
////////////////////////////////////////////////////////////////////////////////////////////////////

void setupDig(DigitalPin& pin, boolean mode, boolean init_state, boolean inv_state);
void setupDig(DigitalPin& pin, boolean mode, boolean init_state);
void setupPWM(DigitalPin& pin, byte mode, byte state);
void writeDig(DigitalPin& pin, boolean state);
void writePWM(DigitalPin& pin, byte state);
DigitalPin& read(DigitalPin& pin);
boolean changed(DigitalPin& pin);
void write(DigitalPin& pin, boolean state);
void toggle(DigitalPin& pin);
void pulse(DigitalPin& pin, int wait);
void flashLed(DigitalPin& pin, byte times, int wait) ;
void setAnalog(AnalogPin& pin, boolean mode);
void setupAnalog(AnalogPin& pin);
AnalogPin& readAnalog(AnalogPin& pin);
void writeAnalog(AnalogPin& pin);


///////////////////
//Used to initialize all vectors to avoid ecc errors
///////////////////

void pins_Variable_ResetValue() {

  for (int i = 0; i < sizeof(base_variable_used); i++) {
    Arduino_User_var[i].value = 0;
  }
}



void pins_InitSensorArray() {



  memset(Arduino_User_var, 0, sizeof(Arduino_User_var));
  memset(ArduinoAnalog, 0, sizeof(ArduinoAnalog));
  memset(ArduinoIO, 0, sizeof(ArduinoIO));


  for (int i = 0; i < sizeof(base_variable_used); i++) {
    Arduino_User_var[i].pin = base_variable_used[i];
    Arduino_User_var[i].Limit.max_events = 5;             //frequency of PUSH notifications when the limit is reached
  }
  for (int i = 0; i < sizeof(base_analog_pins_used); i++) {
    ArduinoAnalog[i].pin = base_analog_pins_used[i];					//used to index each pin
    ArduinoAnalog[i].Limit.max_events = 5;              //max_events number (push and setting)
  }


  //init all the DIGITAL specified on base_digital_pins_used as OUTPUTS
  for (int i = 0; i < sizeof(base_digital_pins_used); i++) {

    ArduinoIO[i].pin = base_digital_pins_used[i];					          //used to index each pin
    ArduinoIO[i].used = 1;     //SI PUO ELIMINARE!!!!!
    ArduinoIO[i].mode = base_digital_pins_mode_used[i];
    ArduinoIO[i].state = 0;
    ArduinoIO[i].inv = base_digital_pins_inv_used[i];
    ArduinoIO[i].pulse = 0;
    pinMode(ArduinoIO[i].pin, ArduinoIO[i].mode);
    writeDig(ArduinoIO[i], ArduinoIO[i].state);
    //    Serial.print("Inxed:");Serial.print(i);Serial.print(" - pin[");Serial.print(base_digital_pins_used[i]);Serial.print("], mode:");Serial.print(ArduinoIO[i].mode);Serial.println();
    ArduinoIO[i].Limit.max_events = 5;              //max_events number (push and setting)
  }

#if NRF24L_ENABLE == 1

  memset(SystemNRF24LPins, 0, sizeof(SystemNRF24LPins));
  for (byte index_nrf = 0; index_nrf < NRF24LMaxModules; index_nrf++) {
    SystemNRF24LPins[index_nrf].RNF24LAddr = 0;
    for (int i = 0; i < NRF24LMaxAnalogPin; i++)   {
      SystemNRF24LPins[index_nrf].AnaPin[i].Limit.max_events = 5;             //frequency of PUSH notifications when the limit is reached
    }
    for (int i = 0; i < NRF24LMaxDigitalPin; i++)   {
      SystemNRF24LPins[index_nrf].DigPin[i].Limit.max_events = 5;             //frequency of PUSH notifications when the limit is reached
    }
    for (int i = 0; i < NRF24LMaxVariable; i++)   {
      SystemNRF24LPins[index_nrf].VarPin[i].Limit.max_events = 5;             //frequency of PUSH notifications when the limit is reached
    }
  }
#endif
}




////////////////////////////////////////////
//DIGITALS
////////////////////////////////////////////

//DIG PIN SETUP
void setupDig(DigitalPin & pin, boolean mode = false, boolean init_state = false, boolean inv_state = false)
{
  pin.used = true;                   //is the pin used (0=not used, 1=used)
  pin.mode = mode;                   //used to know if the pin is: INPUT=0, OUTPUT=1, PWM=2
  pin.state = init_state;            //used  to store the read pin
  pin.inv = inv_state;               //used  to store the inverted state of pin
  pin.pulse = false;                 //used to remember if the pin has been pulsed (to transmit the feedback to Andruino)



  //mode=2 == PWM
  if (pin.mode == PWM)
    pinMode(pin.pin, OUTPUT);        //configure the pin
  else
    pinMode(pin.pin, pin.mode);        //configure the pin

  //PIN INV 7.3 Aug 2016
  if (pin.inv)
    digitalWrite( pin.pin, !pin.state);
  else
    digitalWrite( pin.pin, pin.state);

}


//DIG PIN SETUP without inv_state (false)
void setupDig(DigitalPin& pin, boolean mode = false, boolean init_state = false)
{
  setupDig(pin, mode, init_state, false);
}

//DIG PIN SETUP PWM
void setupPWM(DigitalPin& pin, byte mode, byte state)
{
  pin.used = true;
  pin.mode = mode;
  pin.state = state;


  pinMode( pin.pin, OUTPUT);
  analogWrite( pin.pin, pin.state);

}
//DIG PIN WRITE
void writeDig(DigitalPin& pin, boolean state) //the port has to be configured as output before with setupDig
{
  byte old_value;
  pin.state = state;

  old_value = digitalRead(pin.pin);

#if DEBUG_SERIAL_GPIO == 1
  Serial.print("Pin #:"); Serial.print(pin.pin); Serial.print(", Pin-state:"); Serial.print(old_value); Serial.print(", App-state:"); Serial.print(pin.state);; Serial.print(", inv:"); Serial.println(pin.inv);
#endif

  //don't modify the pin if the new value is the same
  if ((old_value == pin.state && pin.inv == false) || (old_value == !pin.state && pin.inv == true))
    return;


  //PIN INV 7.3 Aug 2016
  if (pin.inv)
    digitalWrite( pin.pin, !pin.state);
  else
    digitalWrite( pin.pin, pin.state);

#if DEBUG_SERIAL_GPIO == 1
  Serial.print("WriteDig exec - PIN:"); Serial.print(pin.pin); Serial.print(", state: ");
  if (pin.inv)
    Serial.println(!pin.state);
  else
    Serial.println(pin.state);
#endif

  store_digital_out_eeprom = true;



}
//DIG PIN WRITE PWM
void writePWM(DigitalPin& pin, byte state)   //the port has to be configured as output before with setupPWM
{
  pin.state = state;
  analogWrite( pin.pin, pin.state);
  //store_digital_out_eeprom=true;

}


//DIG PIN READ
DigitalPin& read(DigitalPin& pin)
{
  //PIN INV 7.3 Aug 2016 (pin.state is linked to the AppState)
  if (pin.inv)
    pin.state = !digitalRead( pin.pin );
  else
    pin.state = digitalRead( pin.pin );

  return pin;
}


//Toggle pin
void toggle(DigitalPin& pin) {
  writeDig(pin, !pin.state);
}

//Pulse pin
void pulse(DigitalPin& pin, int wait) {

  toggle(pin);
  delay(wait);
  toggle(pin);
  //#if DEBUG_SERIAL == 1
  //            Serial.print(F("Pulse on PIN: "));Serial.println(pin.pin);
  //#endif
  pin.pulse = true;

}

void flashLed(DigitalPin& pin, byte times, int wait) {

  for (byte i = 0; i < times; i++) {
    writeDig(pin, 1);
    delay(wait);
    writeDig(pin, 0);

    if (i + 1 < times) {
      delay(wait);
    }
  }
  //don't store dta on flash
  store_digital_out_eeprom = false;

}

////////////////////////////////////////////
//ANALOGS
////////////////////////////////////////////

void setupAnalog(AnalogPin& pin)
{
  pin.used = true;
}

/*void writeAnalog(AnalogPin& pin)
  {
  analogWrite(pin.pin,pin.value);
  }
*/
