/*  Servo_PN_ATtiny.ino
 *  --------------------------------------------------------------------------------
 *  Servomoteur avec un ATtiny pour barrieres PN
 *  http://www.locoduino.org/spip.php?article194
 *  Fabrique sur la sortie ServoPin un signal de servomoteur avec une 
 *  impulsion réglable de pulseMin à pulseMax (soit 1 à 2 ms) et
 *  avec une période de 15000 µS (soit 15 ms) qui est fixe.
 *  1,0 ms ==> servo a -90°
 *  1,5 ms ==> servo centré
 *  2,0 ms ==> servo a +90°
 *  En fait, depend du modele de servo
 *  --------------------------------------------------------------------------------
 *  ILS non déclenché ==> barrieres fixes (ouvertes ou fermées)
 *  ILS déclenché ==> provoque mouvement des barrieres
 *  --------------------------------------------------------------------------------
 *  Introduit le clignotement des feux rouges de PN sur sortie ledPin
 */

// constantes :
const int bpPin = 4;               // ILS
const int ServoPin =  3;           // Servo 
const int ledPin = 0;              // LED de feux rouges 
const int nbre_cligno_avant = 3;   // clignotement des DEL avant fermeture barrières
const int duree_cligno = 500;      // demi période de clignotement des LED en ms
const long period = 15000;         // période (en microsecondes; comprise entre 10 et 20 ms)
const long pulseMin = 1000;        // logiquement >= 1000
const long pulseMax = 2000;        // logiquement <= 2000
// Ces deux valeurs permettent un débattement de 90° du servo S3001 Futaba

// variables :
unsigned long debut_boucle = 0;     // mémorise le début du signal Servo
unsigned long duree_signal = 2000;  // signal limité en durée pour éviter frétillement
unsigned long previousMicros = 0;   // mémorise l instant du front montant
unsigned long previousMillis = 0;   // mémorise changement d état de la LED
unsigned long currentMicros;
unsigned long currentMillis;
long pulse = 1000;                  // Impulsion en microsecondes du signal, de pulseMin à pulseMax

void setup() {
  pinMode(bpPin, INPUT_PULLUP);
  pinMode(ServoPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  debut_boucle = millis();
  while(digitalRead(bpPin)==HIGH){
    // ILS non déclenché
    pulse = pulseMin;
    
    currentMicros = micros();
    if(currentMicros - previousMicros >= pulse) {
      digitalWrite(ServoPin, LOW);
    }
  
    if (currentMicros - previousMicros >= (period - pulse)) {
      digitalWrite(ServoPin, HIGH);
      previousMicros = currentMicros;
    }
    if(millis() - debut_boucle >= duree_signal){
      break; // on arrête le signal après 2 secondes
    }
  }
  while(digitalRead(bpPin)==HIGH) {
    // attendre
  }
  
  // Ici, ILS déclenché : clignotement des LED
  for(int i = 1; i <= nbre_cligno_avant; i++) {
    digitalWrite(ledPin, HIGH);
    delay(duree_cligno);
    digitalWrite(ledPin, LOW);
    delay(duree_cligno);
  }
  debut_boucle = millis();
  while(digitalRead(bpPin) == HIGH) {
    currentMillis = millis();
      pulse = pulseMax;

    currentMicros = micros();
    if(currentMicros - previousMicros >= pulse) {
      digitalWrite(ServoPin, LOW);
    }
  
    if (currentMicros - previousMicros >= (period - pulse)) {
      digitalWrite(ServoPin, HIGH);
      previousMicros = currentMicros;
    }

    // Clignotement des LED rouges
    if (currentMillis - previousMillis >= duree_cligno) {
      digitalWrite(ledPin, !digitalRead(ledPin));
      previousMillis = currentMillis;
    }
    if(millis() - debut_boucle >= duree_signal) {
      break; // on arrête le signal après 2 secondes
    }
  }
  
  while(digitalRead(bpPin)==HIGH) {
    // les LED continuent à clignoter
    currentMillis = millis();
    if(currentMillis - previousMillis >= duree_cligno) {
      digitalWrite(ledPin, !digitalRead(ledPin));
      previousMillis = currentMillis;
    }    
  }
  // Déclenchement ILS
  delay(500); // anti-rebond
  digitalWrite(ledPin, LOW); // Extinction des LED rouges
  // ouverture des barrières se fera en début de fonction loop
  }  
ATTINY8520PU