#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/clocks.h"

// Definição de pinos (GPIOs)
#define LED_VERDE_CARRO 0
#define LED_AMARELO_CARRO 1
#define LED_VERMELHO_CARRO 2
#define LED_VERDE_PEDESTRE 3
#define BUZZER 4
#define BOTAO 5

// Estado do semáforo
enum EstadoSemaforo {VERDE, AMARELO, VERMELHO};
enum EstadoSemaforo estado_atual = VERDE;

// Função para configurar o PWM no buzzer
void pwm_init_buzzer(uint pin) {
    // Configura 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) / (1000 * 4096)); // Frequência de 1000 Hz
    pwm_init(slice_num, &config, true);

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

// 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, 2048);  // Duty cycle de 50%

    // 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(100); // Pausa de 100ms
}

// Função de delay com verificação do botão
void esperar_com_botao(int segundos) {
    for (int i = 0; i < segundos * 10; i++) {
        if (gpio_get(BOTAO) == 0) {  // Se o botão for pressionado
            atravessar_pedestre();   // Interrompe ciclo e faz travessia
            return;                  // Volta ao loop principal
        }
        sleep_ms(100);
    }
}

// Função que controla o ciclo normal do semáforo
void ciclo_normal() {
    switch (estado_atual) {
        case VERDE:
            gpio_put(LED_VERDE_CARRO, 1);
            esperar_com_botao(8);  // Verde por 8 segundos
            gpio_put(LED_VERDE_CARRO, 0);
            estado_atual = AMARELO;
            // Não usa break para seguir diretamente ao próximo estado

        case AMARELO:
            gpio_put(LED_AMARELO_CARRO, 1);
            esperar_com_botao(5);  // Amarelo por 5 segundos
            gpio_put(LED_AMARELO_CARRO, 0);
            estado_atual = VERMELHO;
            
        case VERMELHO:
            gpio_put(LED_VERMELHO_CARRO, 1);
            esperar_com_botao(10);  // Vermelho por 10 segundos
            gpio_put(LED_VERMELHO_CARRO, 0);
            estado_atual = VERDE;
            break;
    }
}

// Função para travessia de pedestre quando o botão é pressionado
void atravessar_pedestre() {
    // Desliga todos os LEDs de carro
    gpio_put(LED_VERDE_CARRO, 0);
    gpio_put(LED_AMARELO_CARRO, 0);
    gpio_put(LED_VERMELHO_CARRO, 0);

    // Acende o LED amarelo do carro por 5 segundos
    gpio_put(LED_AMARELO_CARRO, 1);
    sleep_ms(5000);
    gpio_put(LED_AMARELO_CARRO, 0);

    // Acende o vermelho do carro e verde do pedestre
    gpio_put(LED_VERMELHO_CARRO, 1);
    gpio_put(LED_VERDE_PEDESTRE, 1);

    // Emite o som do buzzer
    beep(BUZZER, 500); // Emite o som por 500ms

    // Mantém o estado por 15 segundos com o buzzer ativo
    for (int i = 0; i < 30; i++) {  // Buzzer intermitente (ciclo de 250 ms)
        beep(BUZZER, 250);  // Emite o som do buzzer por 250ms
        sleep_ms(250);  // Pausa de 250ms
    }

    // Desliga tudo após 15 segundos
    gpio_put(LED_VERDE_PEDESTRE, 0);
    gpio_put(LED_VERMELHO_CARRO, 0);
}

int main() {
    stdio_init_all();

    // Inicialização dos pinos
    gpio_init(LED_VERDE_CARRO);
    gpio_init(LED_AMARELO_CARRO);
    gpio_init(LED_VERMELHO_CARRO);
    gpio_init(LED_VERDE_PEDESTRE);
    gpio_init(BUZZER);
    gpio_init(BOTAO);

    gpio_set_dir(LED_VERDE_CARRO, GPIO_OUT);
    gpio_set_dir(LED_AMARELO_CARRO, GPIO_OUT);
    gpio_set_dir(LED_VERMELHO_CARRO, GPIO_OUT);
    gpio_set_dir(LED_VERDE_PEDESTRE, GPIO_OUT);
    gpio_set_dir(BUZZER, GPIO_OUT);
    gpio_set_dir(BOTAO, GPIO_IN);

    gpio_pull_up(BOTAO);  // Ativa pull-up interno no botão

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

    // Loop infinito
    while (1) {
        ciclo_normal();  // Executa ciclo normal do semáforo
    }
}
$abcdeabcde151015202530fghijfghij