/*
 * ITES - MICROCONTROLADORES II
 * by Alejo S. Giles
 * 
 * - BlinkAsimetrico
 * - EfectoBarraLILO (6 LEDS)
 * - Boton para incrementar (avanzar en el efecto)
 * - Boton para decrementar (retrocecder en el efecto)
 * - Antirrebote para los botones
 * - Puerto Serie
 * -- Comando para incrementar (+)
 * -- Comando para decrementar (-)
 * -- Comando para reiniciar el efecto (0)
 */

#define PIN_LED1 2
#define PIN_LED2 3
#define PIN_LED3 4
#define PIN_LED4 5
#define PIN_LED5 6
#define PIN_LED6  7
#define CANT_LEDS 6
const int PIN_LEDS[]={PIN_LED1,PIN_LED2,PIN_LED3,PIN_LED4,PIN_LED5,PIN_LED6};

#define CONFIG_SALIDA(x) pinMode(x,OUTPUT)
#define AJUSTAR_LED(x,y) digitalWrite(PIN_LEDS[x],y)

//BLINK
#define PIN_BLINK         13
#define CONFIG_BLINK      pinMode(PIN_BLINK, OUTPUT)
#define ENCENDER_BLINK    digitalWrite(PIN_BLINK, 1)
#define APAGAR_BLINK      digitalWrite(PIN_BLINK, 0)
#define AJUSTAR_BLINK(x)  digitalWrite(PIN_BLINK, x)
#define MS_BLINK_ON 50
#define MS_BLINK_OFF 2000

//BOTONES
#define MS_ANTIREBOTE             100
#define PIN_BTN_INC               8
#define CONFIG_BTN_INC            pinMode(PIN_BTN_INC, INPUT)
#define BTN_INCREMENTA_PRESIONADO digitalRead(PIN_BTN_INC)

#define PIN_BTN_DEC               9
#define CONFIG_BTN_DEC            pinMode(PIN_BTN_DEC, INPUT)
#define BTN_DECREMENTA_PRESIONADO digitalRead(PIN_BTN_DEC)

#define MS_ANTIRREBOTE 100

char accion=0;

void setup()
  {
  Serial.begin(9600);
  Serial.print("EfectoBarraLILOControlado");
  CONFIG_BTN_INC;
  CONFIG_BTN_DEC;
  CONFIG_BLINK;
  
  //LEDS DEL EFECTO
  for(int i=0; i<CANT_LEDS; i++)  CONFIG_SALIDA(PIN_LEDS[i]);
  }

void loop()
  {
  BlinkAsimetrico();
  CtrlBotones();
  RecepcionSerie();

  EfectoBarraLILO();  //Debe actuar de acuerdo a la variable accion
  if(accion) accion=0;
  }

void RecepcionSerie(void)
  {
  if(!Serial.available()) return;
  
  switch(Serial.read())
    {
    case '-': accion=-1;  break;
    case '+': accion=1;   break;
    }
  }

void CtrlBotones(void)  
  {
  static unsigned long millis_ini=0;
  static char btn_incrementa_presionado_ant=0;
  static char btn_decrementa_presionado_ant=0;

  if(millis_ini>0) 
      {
      if(millis() - millis_ini < MS_ANTIREBOTE) return;
      millis_ini=0;
      }
  
  if(BTN_INCREMENTA_PRESIONADO != btn_incrementa_presionado_ant)
    {
    btn_incrementa_presionado_ant=BTN_INCREMENTA_PRESIONADO;
    if(BTN_INCREMENTA_PRESIONADO) 
      {
      millis_ini= millis(); //Preparar para esperar MS_ANTIREBOTE
      accion=1;
      }
    }

  if(BTN_DECREMENTA_PRESIONADO != btn_decrementa_presionado_ant)
    {
    btn_decrementa_presionado_ant=BTN_DECREMENTA_PRESIONADO;
    if(BTN_DECREMENTA_PRESIONADO) 
      {
      millis_ini= millis(); //Preparar para esperar MS_ANTIREBOTE
      accion=-1;
      }
    }
  }

void EfectoBarraLILO(void) //1=avanzar / 0=no hacer nada / -1=retroceder
  {
  static unsigned int paso=2*CANT_LEDS-1;

  if(accion==0)  return;
 
  if(accion>0)
    {
    paso++;
    if(paso>=2*CANT_LEDS) paso=0;
    }

  if(paso<CANT_LEDS)  AJUSTAR_LED(paso, accion>0);
  else                AJUSTAR_LED(paso-CANT_LEDS, !(accion>0));

  if(accion<0)
    {
    if(paso>0) paso--;
    else paso=2*CANT_LEDS-1;
    }
  }

void BlinkAsimetrico(void)
  {
  static unsigned long millis_ant=0;
  static bool estado=0;
  static unsigned int espera=0;

  if(millis() - millis_ant < espera) return;
  millis_ant=millis();

  estado=!estado;
  AJUSTAR_BLINK(estado);

  espera= estado ? MS_BLINK_ON : MS_BLINK_OFF;  //Ajustar el tiempo de espera
  }