/* LDR_Pin é o pino onde está ligado o LDR; assumimos um prescaler (divisor do clock) igual a 40;
  Devem ser feitas 2000 leituras do LDR dentro da frequência de contagem (1MHz); e
  dividindo a frequência de contagem pela quantidade de leituras (2000) dá o valor que deve ser
  inicializado o contador do timer (500)
*/
#define LDR_Pin 2
#define LED 32
#define clock 40000000
#define prescaler 40
#define freq_contagem clock/prescaler
#define leituras 2000
#define quanto_contar freq_contagem/leituras

hw_timer_t *timer = NULL; // ponteiro para uma variável do tipo hw_timer_t

volatile bool interrupted = false;
bool stateLED = true;

/* Ao definir a ISR como IRAM_ATTR, indicamos que o trecho de código ficará na seção de
   instruções da RAM e não na Flash, ganhando velocidade na execução
*/
void IRAM_ATTR onTimer() {
  interrupted = true;
}

void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite(LED, stateLED);
  Serial.begin(115200);
  Serial.println(freq_contagem);
  Serial.println(quanto_contar);

  /* timerBegin(param1, param2, param3)
    param1: número do timer que queremos usar (de 0 a 3, pois temos 4 timers de hardware)
    param2: valor do prescaler
    param3: flag indicando se o contador deve contar para cima (true) ou para baixo (false)
  */
  timer = timerBegin(0, prescaler, true);

  /* o terceiro parametro de timerAttachInterrupt(), true, indica que queremos que a interrupção
    seja do tipo borda (o que significa que ela deve ser acionada em uma borda de subida (rising) ou
    de descida (falling)
  */
  
  timerAttachInterrupt(timer, &onTimer, true);

  /* A função timerAlarmWrite especifica que um ALARME deve ser acionado toda vez que a contagem do
    temporizador atingir quanto_contar.
    O terceiro argumento desta função, true, indica que o temporizador deve ser recarregado automaticamente.
    Isso significa que após gerar um alarme uma vez, ele deve recarregar automaticamente e começar a contar
    novamente de 0 a quanto_contar
  */
  timerAlarmWrite(timer, quanto_contar, true);
  timerAlarmEnable(timer);
}

void loop() {
  if (interrupted) { // Se interrupted for true, significa que o alarme foi acionado
    Serial.print("LDR: ");
    Serial.println(analogRead(LDR_Pin));
    Serial.println("Leitura de stateLED ANTES da inversão: ");
    Serial.println(stateLED);
    stateLED = !stateLED;
    Serial.println("Leitura de stateLED APÓS da inversão: ");
    Serial.println(stateLED);
    digitalWrite(LED, stateLED);
    delay(500);
    interrupted = false;
  }
}