#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/clocks.h"

//Configuração dos pinos dos LED's para o semáforo.
const uint GREEN_LED_PIN_FOR_CARS = 28;   // LED verde no GPIO 28
const uint YELLOW_LED_PIN  = 27; // LED Amarelo no GPIO 27
const uint RED_LED_PIN = 26;  // LED Vermelho no GPIO 26

//Configuração do pino do LED para pedestres.
const uint GREEN_LED_PIN_FOR_PEDESTRIANS = 22; // LED no GPIO 22

// Configuração do pino para o buzzer
const uint BUZZER_PIN = 21; // Buzzer no GPIO 21
const int BUZZER_FREQUENCY = 2000;

// Configuração do pino para o botão
const uint BUTTON_PIN = 20;  // Button no GPIO 20

// Variáveis para controlar o estado do botão
bool button_pressed = false;
bool previous_button_state = false;

// Variável responsável por verificar se já ocorreu o pressionar do botão, permitindo que assim que acabar a interação com o pedestre, seja acionado o led verde para carros, para que após um longo tempo de espera, os carros possam atravessar.
bool verification = false;

void pwm_init_buzzer(uint pin) {
    // Configurar o pino como saída de PWM
    gpio_set_function(pin, GPIO_FUNC_PWM);

    // Obter o slice do PWM associado ao pino
    uint slice_num = pwm_gpio_to_slice_num(pin);

    // Configurar o PWM com frequência desejada
    pwm_config config = pwm_get_default_config();
    pwm_config_set_clkdiv(&config, clock_get_hz(clk_sys) / (BUZZER_FREQUENCY * 4096)); // Divisor de clock
    pwm_init(slice_num, &config, true);

    // Iniciar o PWM no nível baixo
    pwm_set_gpio_level(pin, 0);
}

// Definição de uma função para emitir um beep com duração especificada
void beep(uint pin, uint duration_ms) {
    // Obter o slice do PWM associado ao pino
    uint slice_num = pwm_gpio_to_slice_num(pin);

    // Configurar o duty cycle para 50% (ativo)
    pwm_set_gpio_level(pin, 1024);

    // Temporização
    sleep_ms(duration_ms);

    // Desativar o sinal PWM (duty cycle 0)
    pwm_set_gpio_level(pin, 0);

    // Pausa entre os beeps
    sleep_ms(500); // Pausa de 500ms
}


bool button(int time) {
  for (int i = 0; i < time; i++) {
    bool current_button_state = gpio_get(BUTTON_PIN);

    printf("%d", gpio_get(BUTTON_PIN));

    // Verifica se o valor indentificado no botão é o mesmo da variavel "previous_button_state".
    if (current_button_state != previous_button_state) {
      printf("%d", current_button_state);
      verification = true;
      return true;
    }
    previous_button_state = current_button_state; // Atualiza o valor da variável
    sleep_ms(50);
  }
  return false;
}


// Lógica para quando o botão é precionado.
void pedestres_interacao() {
  // Muda o estado da variavel para o estado atual do botão (0 ou 1)
  if(button_pressed) {
    if(gpio_get(RED_LED_PIN)) {
      gpio_put(YELLOW_LED_PIN, 0);
      gpio_put(GREEN_LED_PIN_FOR_PEDESTRIANS, 1);
      for (int i = 0; i < 15; i++) {
        beep(BUZZER_PIN, 500); // Bipe de 500ms
      }
      gpio_put(GREEN_LED_PIN_FOR_PEDESTRIANS, 0);
      gpio_put(BUZZER_PIN, 0);
      button_pressed = false;
    } else {
      gpio_put(GREEN_LED_PIN_FOR_CARS, 0);
      gpio_put(YELLOW_LED_PIN, 1);
      sleep_ms(5000);
      gpio_put(YELLOW_LED_PIN, 0);
      gpio_put(RED_LED_PIN, 1);
      gpio_put(GREEN_LED_PIN_FOR_PEDESTRIANS, 1);
      for (int i = 0; i < 15; i++) {
        beep(BUZZER_PIN, 500); // Bipe de 500ms
      }
      gpio_put(RED_LED_PIN, 0);
      gpio_put(GREEN_LED_PIN_FOR_PEDESTRIANS, 0);
      button_pressed = false;
      return 0;
    }
  }
}


// Lógica do semáforo.
void semaforo_carros(){
  // Loop relacionado a forma como o semaforo vai agir.
  while (true) {
    gpio_put(RED_LED_PIN, 0);
    gpio_put(GREEN_LED_PIN_FOR_CARS, 1);
    button_pressed = button(160);
    pedestres_interacao();
    
    if (verification != true) {
      gpio_put(GREEN_LED_PIN_FOR_CARS, 0);
      gpio_put(YELLOW_LED_PIN, 1);
      button_pressed = button(40);
      pedestres_interacao();
    }

    if (verification != true) {
      gpio_put(YELLOW_LED_PIN, 0);
      gpio_put(RED_LED_PIN, 1);
      button_pressed = button(200);
      pedestres_interacao();
    }
    verification = false;
  }
}


//Essa é a função principal do projeto. É por ela que o código inicia.
int main() {
  // Inicializar o sistema de saída padrão
  stdio_init_all();

  gpio_init(GREEN_LED_PIN_FOR_CARS); // Inicializando o pino verde
  gpio_init(YELLOW_LED_PIN); // Inicializando o pino amarelo
  gpio_init(RED_LED_PIN); // Inicializando o pino vermelho
  gpio_set_dir(GREEN_LED_PIN_FOR_CARS, GPIO_OUT); // Definindo direção para "saida"
  gpio_set_dir(YELLOW_LED_PIN, GPIO_OUT); // Definindo direção para "saida"
  gpio_set_dir(RED_LED_PIN, GPIO_OUT); // Definindo direção para "saida"

  gpio_init(GREEN_LED_PIN_FOR_PEDESTRIANS); // Inicializando o pino
  gpio_set_dir(GREEN_LED_PIN_FOR_PEDESTRIANS, GPIO_OUT); // Definindo direção para "saida"

  // Inicializar o PWM no pino do buzzer
  pwm_init_buzzer(BUZZER_PIN);

  gpio_init(BUTTON_PIN);
  gpio_set_dir(BUTTON_PIN, GPIO_IN); // Configura o botão como entrada
  
  semaforo_carros();

  return 0;
}
$abcdeabcde151015202530fghijfghij