/*
  @file main.c
  @author Eduardo Dueñas
  @brief Exemplo de contador de eventos
  @version 1.0
  @date 06/04/2021

  última modificação: 05/05/2021

  Veja o artigo publicado no link abaixo:
  https://www.embarcados.com.br/franzininho-diy-contador-de-pulsos-externos/
*/

#include <avr/io.h>

#define F_CPU 16500000L                // Frequência de CLK

#define setBit(valor, bit)             (valor |= (1 << bit))
#define clearBit(valor, bit)           (valor &= ~(1 << bit))
#define toogleBit(valor, bit)          (valor ^= (1 << bit))
#define testBit(valor, bit)            (valor & (1 << bit))

// Debounce da chave táctil para desconsiderarmos ruído e bouncing do botão
char debounce(int pino) {
  unsigned int i;
  for (i = 0; i < 20000; i++) {        // Testa o pino várias vezes para evitar leituras erradas
    if (!(testBit(PINB, pino))) {      // Testa se o pino deixou de ser 1
      return 0;                        // Se sim, retorna falso
    }
  }
  return 1;                            // Retorna verdadeiro
}

int main(void) {
  // Configuração de PORTB
  clearBit(DDRB, PB0);                 // Configura PB0 como entrada
  setBit(DDRB, PB1);                   // Configura PB1 como saida
  setBit(DDRB, PB2);                   // Configura PB2 como saida
  setBit(DDRB, PB3);                   // Configura PB3 como saida
  setBit(DDRB, PB4);                   // Configura PB4 como saida

  PORTB &= 0xE1;                       // Manda 0 para PB[4:1]

  unsigned char count = 0;

  for (;;) {                           // Loop infinito

    if (testBit(PINB, PB0)) {          // Testa se PB0 é 1
      if (debounce(PB0)) {             // Verifica se realmente foi um aperto de botão
        count++;                       // Se sim, incrementa o contador
        while (testBit(PINB, PB0)) {}  // Espera o botão parar de ser pressionado
      }
    }

    count = count % 0x10;                    // Limpa o overflow do contador
    PORTB = ((PORTB & 0xE1) | (count << 1)); // Manda o contador para PB[4:1]
  }
}