#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "hardware/adc.h"
#include "hardware/timer.h"
#define PWM_GPIO_BUZZER 21
#define CLOCK_DIV 2.0f
#define FREQ_GRAVE 500
#define FREQ_MEDIA 1000
#define FREQ_AGUDA 2000
#define JOY_X_ADC_CHANNEL 0 // GPIO26
#define JOY_Y_ADC_CHANNEL 1 // GPIO27
#define INTERVALO_MS 100
#define MARGEM_CENTRO 500
#define LED_PWM_GPIO 13
#define LED_PWM_WRAP 255
volatile uint16_t freq_atual = FREQ_MEDIA;
volatile int contador = 0;
volatile bool tocando = false;
// Calcula wrap baseado na frequência do buzzer
uint16_t calcula_wrap_buzzer(uint16_t freq) {
return (uint16_t)(125000000 / (freq * CLOCK_DIV));
}
void atualizar_pwm_buzzer(uint slice, uint16_t nova_freq) {
pwm_config cfg = pwm_get_default_config();
pwm_config_set_clkdiv(&cfg, CLOCK_DIV);
pwm_config_set_wrap(&cfg, calcula_wrap_buzzer(nova_freq));
pwm_init(slice, &cfg, true);
if (tocando) {
pwm_set_gpio_level(PWM_GPIO_BUZZER, calcula_wrap_buzzer(nova_freq) / 2);
} else {
pwm_set_gpio_level(PWM_GPIO_BUZZER, 0);
}
}
void pwm_wrap_handler() {
uint slice = pwm_gpio_to_slice_num(PWM_GPIO_BUZZER);
pwm_clear_irq(slice);
contador++;
if (contador == 0) return;
if (contador >= freq_atual) {
contador = 0;
tocando = true;
pwm_set_gpio_level(PWM_GPIO_BUZZER, calcula_wrap_buzzer(freq_atual) / 2);
printf("🔊 BEEP! Freq: %d Hz\n", freq_atual);
}
if (tocando && contador == 100) {
pwm_set_gpio_level(PWM_GPIO_BUZZER, 0);
tocando = false;
}
}
// Callback periódico para ler joystick e ajustar frequência + LED
bool leitura_joystick_callback(struct repeating_timer *t) {
adc_select_input(JOY_X_ADC_CHANNEL);
uint16_t x = adc_read();
adc_select_input(JOY_Y_ADC_CHANNEL);
uint16_t y = adc_read();
bool centro_x = (x > (2048 - MARGEM_CENTRO)) && (x < (2048 + MARGEM_CENTRO));
bool centro_y = (y > (2048 - MARGEM_CENTRO)) && (y < (2048 + MARGEM_CENTRO));
uint slice_led = pwm_gpio_to_slice_num(LED_PWM_GPIO);
if (centro_x && centro_y) {
freq_atual = FREQ_GRAVE;
pwm_set_gpio_level(LED_PWM_GPIO, 64); // LED fraco (~25%)
} else {
freq_atual = FREQ_AGUDA;
pwm_set_gpio_level(LED_PWM_GPIO, 255); // LED forte (100%)
}
return true;
}
int main() {
stdio_init_all();
sleep_ms(2000);
printf("🎮 Joystick + Beep + LED PWM (GPIO13)\n");
// ---- Configura PWM do Buzzer ----
gpio_set_function(PWM_GPIO_BUZZER, GPIO_FUNC_PWM);
uint slice_buzzer = pwm_gpio_to_slice_num(PWM_GPIO_BUZZER);
pwm_config cfg_buzzer = pwm_get_default_config();
pwm_config_set_clkdiv(&cfg_buzzer, CLOCK_DIV);
pwm_config_set_wrap(&cfg_buzzer, calcula_wrap_buzzer(freq_atual));
pwm_init(slice_buzzer, &cfg_buzzer, true);
pwm_set_gpio_level(PWM_GPIO_BUZZER, 0);
pwm_clear_irq(slice_buzzer);
pwm_set_irq_enabled(slice_buzzer, true);
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap_handler);
irq_set_enabled(PWM_IRQ_WRAP, true);
// ---- Configura PWM do LED (GPIO13) ----
gpio_set_function(LED_PWM_GPIO, GPIO_FUNC_PWM);
uint slice_led = pwm_gpio_to_slice_num(LED_PWM_GPIO);
pwm_config cfg_led = pwm_get_default_config();
pwm_config_set_clkdiv(&cfg_led, 4.0f); // Pode ser mais lento
pwm_config_set_wrap(&cfg_led, LED_PWM_WRAP);
pwm_init(slice_led, &cfg_led, true);
pwm_set_gpio_level(LED_PWM_GPIO, 0);
// ---- ADC Joystick (X = GPIO26, Y = GPIO27) ----
adc_init();
adc_gpio_init(26);
adc_gpio_init(27);
struct repeating_timer timer;
add_repeating_timer_ms(INTERVALO_MS, leitura_joystick_callback, NULL, &timer);
while (true) {
tight_loop_contents();
}
return 0;
}