#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/i2c.h"
// DEFINICIÓN DE PINES
#define LCD_ADDR 0x27
#define PIN_SDA_LCD 4
#define PIN_SCL_LCD 5
#define PIN_BUZZER 14
#define PIN_POTENC 26
const uint8_t PINES_FILAS[] = {6, 7, 8, 9};
const uint8_t PINES_COLS[] = {10, 11, 12, 13};
// VARIABLES DEL SISTEMA
typedef struct {
int freq_actual;
int vol_actual;
char entrada_txt[8];
uint8_t pos_txt;
} DatosSistema;
DatosSistema app = {0, 50, "", 0};
char tecla_previa = 0;
// TECLADO
const char TECLADO[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
// FUNCIONES LCD (mantener igual)
void i2c_enviar_byte(uint8_t val) {
i2c_write_blocking(i2c0, LCD_ADDR, &val, 1, false);
}
void lcd_pulso(uint8_t val) {
sleep_us(10);
i2c_enviar_byte(val | 0x04);
sleep_us(50);
i2c_enviar_byte(val & ~0x04);
sleep_us(50);
}
void lcd_enviar(uint8_t val, int modo) {
uint8_t alto = modo | (val & 0xF0) | 0x08;
uint8_t bajo = modo | ((val << 4) & 0xF0) | 0x08;
i2c_enviar_byte(alto); lcd_pulso(alto);
i2c_enviar_byte(bajo); lcd_pulso(bajo);
}
void lcd_limpiar() {
lcd_enviar(0x01, 0);
sleep_ms(3);
}
void lcd_xy(int x, int y) {
lcd_enviar((x == 0 ? 0x80 : 0xC0) + y, 0);
}
void lcd_print(const char *s) {
while (*s) lcd_enviar(*s++, 1);
}
void lcd_inicializar() {
sleep_ms(100);
lcd_enviar(0x03, 0); sleep_ms(5);
lcd_enviar(0x03, 0); sleep_ms(5);
lcd_enviar(0x03, 0); sleep_us(150);
lcd_enviar(0x02, 0);
lcd_enviar(0x28, 0);
lcd_enviar(0x0C, 0);
lcd_enviar(0x06, 0);
lcd_limpiar();
i2c_enviar_byte(0x08);
}
// TECLADO
char escanear_matriz() {
for (int r = 0; r < 4; r++) {
gpio_put(PINES_FILAS[r], 1);
sleep_us(10);
for (int c = 0; c < 4; c++) {
if (gpio_get(PINES_COLS[c])) {
char k = TECLADO[r][c];
gpio_put(PINES_FILAS[r], 0);
return k;
}
}
gpio_put(PINES_FILAS[r], 0);
}
return 0;
}
void configurar_tono_wokwi() {
static uint32_t last_time = 0;
uint32_t current_time = to_ms_since_boot(get_absolute_time());
if (app.freq_actual <= 0 || app.vol_actual <= 0) {
gpio_put(PIN_BUZZER, 0);
return;
}
int freq_limitada = app.freq_actual;
if (freq_limitada > 5000) freq_limitada = 5000;
if (freq_limitada < 20) freq_limitada = 20;
int periodo = 1000 / freq_limitada;
if (periodo < 1) periodo = 1;
if (current_time - last_time > periodo) {
gpio_xor_mask(1u << PIN_BUZZER);
last_time = current_time;
}
}
int leer_potenciometro() {
adc_select_input(0);
uint16_t val = adc_read();
return (val * 100) / 4095;
}
// MAIN
int main() {
stdio_init_all();
// I2C para LCD
i2c_init(i2c0, 100000);
gpio_set_function(PIN_SDA_LCD, GPIO_FUNC_I2C);
gpio_set_function(PIN_SCL_LCD, GPIO_FUNC_I2C);
gpio_pull_up(PIN_SDA_LCD);
gpio_pull_up(PIN_SCL_LCD);
// Inicializar LCD
lcd_inicializar();
// Configurar pines del teclado
for (int i = 0; i < 4; i++) {
gpio_init(PINES_FILAS[i]);
gpio_set_dir(PINES_FILAS[i], GPIO_OUT);
gpio_put(PINES_FILAS[i], 0);
gpio_init(PINES_COLS[i]);
gpio_set_dir(PINES_COLS[i], GPIO_IN);
gpio_pull_down(PINES_COLS[i]);
}
gpio_init(PIN_BUZZER);
gpio_set_dir(PIN_BUZZER, GPIO_OUT);
gpio_put(PIN_BUZZER, 0);
adc_init();
adc_gpio_init(PIN_POTENC);
lcd_xy(0, 0); lcd_print("Sistema Audio");
lcd_xy(1, 0); lcd_print("Iniciando...");
sleep_ms(1000);
lcd_limpiar();
char buf[17];
uint32_t last_update = 0;
while (true) {
// Leer teclado
char tecla = escanear_matriz();
if (tecla && tecla != tecla_previa) {
if (tecla >= '0' && tecla <= '9') {
if (app.pos_txt < 5) {
app.entrada_txt[app.pos_txt++] = tecla;
app.entrada_txt[app.pos_txt] = 0;
// Feedback
gpio_put(PIN_BUZZER, 1);
sleep_ms(30);
gpio_put(PIN_BUZZER, 0);
}
} else if (tecla == '#') {
app.freq_actual = atoi(app.entrada_txt);
app.pos_txt = 0;
// Feedback
for(int i = 0; i < 2; i++) {
gpio_put(PIN_BUZZER, 1);
sleep_ms(80);
gpio_put(PIN_BUZZER, 0);
sleep_ms(80);
}
} else if (tecla == '*') {
app.freq_actual = 0;
app.pos_txt = 0;
memset(app.entrada_txt, 0, sizeof(app.entrada_txt));
gpio_put(PIN_BUZZER, 1);
sleep_ms(200);
gpio_put(PIN_BUZZER, 0);
}
}
tecla_previa = tecla;
// Actualizar cada 100ms
uint32_t current_time = to_ms_since_boot(get_absolute_time());
if (current_time - last_update > 100) {
last_update = current_time;
// Leer volumen
app.vol_actual = leer_potenciometro();
// Controlar audio
configurar_tono_wokwi();
// Actualizar LCD
lcd_xy(0, 0);
if (app.pos_txt > 0) {
snprintf(buf, 16, "Freq: %-5s Hz", app.entrada_txt);
} else {
snprintf(buf, 16, "Freq: %-5d Hz", app.freq_actual);
}
lcd_print(buf);
lcd_xy(1, 0);
// Calcular el volumen mostrado
int vol_mostrado = app.vol_actual;
if (vol_mostrado > 90) vol_mostrado = 90;
snprintf(buf, 16, "Vol: %3d%% %s",
vol_mostrado,
app.freq_actual > 0 ? "[ON] " : "[OFF]");
lcd_print(buf);
}
sleep_ms(10);
}
}