/*
* LED Firefly by http://dwhacks.blogspot.ca/ using attiny 13a @4.8MHz
* /translated / Updated Thomas HOCEDEZ http://www.asthrolab.fr
* inspired by http://www.seanet.com/~karllunt/fireflyLED.html
* using core13 for Arduino http://sourceforge.net/projects/ard-core13/
*/

#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int sense = 3;        // Pin de la LED comme capteur de lumière
int LED = 3;            // Pin de la LED comme emmeteur
int val = 0;     // variable de stockage du capteur
int light = 60;        // Limite de luminosité en deça de laquelle la led clignotte NB : a tester pour chaque type de led/environnement !
int val2 = 0;    // Valeur boucle du nombre de fois à clignotter

volatile boolean f_wdt = 1;

void setup(){
  setup_watchdog(9); // initialisation du watchdog à 9 (+/- 8 secondes)
}

void loop(){
  if (f_wdt==1) {  // On attend que le watchdog soit déclenché (le flag passe à 1)
    f_wdt=0;       // remis eà 0 du flag
    pinMode(sense, INPUT); // on défini la pin de sortie comme entrée
    delay(150); // on attend un peu (tension résiduelle possible)
    val = analogRead(sense);      // on lit le capteur (la led, donc)
    delay(50); // On attend encore un peu ...
    if (val >= light) { //On compare la valeur du capteur à la limite définie.
      digitalWrite(LED, LOW); // S'il fait jour, on laisse éteint...
    } else {
       blink_run(); //S'il fait noir, on déclenche la luciole
    }
    pinMode(LED,INPUT); // On remet la pin en entrée... (économie d'énergie!)
    system_sleep();
    pinMode(LED,OUTPUT); // on repasse la led en sortie (... à vérifier sans).
  }
}

void blink_run(){
  pinMode(LED, OUTPUT);
  val2 = 0;
  while(val2 < 30){             // On va faire 30 fois la boucle
      digitalWrite(LED, HIGH);        //on allume la LED
      delay(2);                     // un petit peu de délai...
      digitalWrite(LED, LOW);         //on éteint la LED
      delay(80);                     // On réattend
      val2++;                         //On boucle
  }

}

// Mettre le système en sommeil profond 
// Réveiller une fois le watchdog terminé
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // On éteind les ADC

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // On choisi le mode de Sommeil
  sleep_enable();

  sleep_mode();                        // Le système s'endort ici !

  sleep_disable();                     // On désactive le sommeil (mais pas réveillé pour autant)
  sbi(ADCSRA,ADEN);                    // on réactive l'ADC
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
// boucle de définition d'un watchdog chez Atmega :
void setup_watchdog(int ii) {
  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;
  MCUSR &= ~(1<<WDRF);
  // On commence la boucle de timer :
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // On défini la valeur du Watchdog
  WDTCR = bb;
  WDTCR |= _BV(WDTIE);
}

// Interrupt du watchdog : se déclenche en cas de timeout :
ISR(WDT_vect) {
  f_wdt=1;  // on passe le flag à 1
}