// Gian Luca Ramírez - 1096600
// LAB 04 - Sistemas digitales y Microprocesadores
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/irq.h"
#include "hardware/adc.h"
#include "pico/cyw43_arch.h"
#define FIRST_GPIO 0
#define BUTTON_GPIO (FIRST_GPIO + 11)
#define DISPLAY1 0xF080
#define DP 22 // Punto decimal del display
#define ADC_PERIOD (200) // Periodo de muestreo del ADC (100ms)
int bits[10] = {
0x3f, // 0
0x06, // 1
0x5b, // 2
0x4f, // 3
0x66, // 4
0x6d, // 5
0x7d, // 6
0x07, // 7
0x7f, // 8
0x67 // 9
};
// Variables globales
int num = 15; // Valor actual de voltaje/corriente
int delay_sleep = 0; // Control de espera
int adc_inc = 0; // Incremento del ADC
int waiter = 0; // Control de rebote del botón
int ciclar = DISPLAY1; // Inicio del display
int display = 0; // Valor mostrado en el display
int dec_point = 0; // Control del punto decimal
int modo = 0; // Modo de medición: corriente(0) o voltaje(1)
// Función de callback para incrementar
bool incrementar_callback() {
if (adc_inc > 0) adc_inc--;
if (waiter != 0) waiter--;
if (delay_sleep >= 0) delay_sleep--;
}
// Función de callback para botones
void general_callback(uint gpio, uint32_t event_mask) {
if (gpio == 12 && waiter == 0) {
gpio_acknowledge_irq(12, GPIO_IRQ_EDGE_FALL);
modo = (modo == 1) ? 0 : 1;
}
waiter = 250;
}
int main() {
// Inicialización de puertos
stdio_init_all();
gpio_init_mask(0x4fff);
gpio_set_dir_out_masked(0x77f);
gpio_init(DP); // Inicializar el punto decimal
gpio_set_dir(DP, GPIO_OUT);
// Invertir los GPIO de los segmentos
for (int gpio = FIRST_GPIO; gpio < FIRST_GPIO + 7; gpio++) {
gpio_set_outover(gpio, GPIO_OVERRIDE_INVERT);
}
gpio_set_outover(DP, GPIO_OVERRIDE_INVERT);
gpio_set_dir_in_masked(0x7800);
gpio_pull_up(12);
// Inicialización del ADC
adc_init();
adc_gpio_init(26); // GPIO 26 como ADC 0
adc_gpio_init(27); adc_select_input(1); // GPIO 27 como ADC 1
// Inicialización del temporizador
struct repeating_timer timer;
add_repeating_timer_ms(1, incrementar_callback, NULL, &timer);
// Configuración de interrupción del botón
gpio_set_irq_enabled_with_callback(12, GPIO_IRQ_EDGE_FALL, true, &general_callback);
// Bucle principal
while (true) {
// Lectura del ADC
if (adc_inc == 0) {
const float conversion_factor = 3.3f / (1 << 12);
adc_inc = ADC_PERIOD;
adc_select_input(modo);
if (modo == 1) {
num = adc_read() * conversion_factor * 100;
} else if (modo == 0) {
num = adc_read() * conversion_factor * 100;
}
}
// Ciclar display
if (ciclar > DISPLAY1 << 2) {
ciclar = DISPLAY1;
} else {
ciclar = ciclar << 1;
}
// Número a mostrar en el display
if (ciclar == DISPLAY1 << 3) {
display = num % 10;
} else if (ciclar == DISPLAY1 << 2) {
display = (num % 100 - num % 10) / 10;
} else if (ciclar == DISPLAY1 << 1) {
display = (num % 1000 - num % 100) / 100;
} else if (ciclar == DISPLAY1) {
display = (num - num % 1000) / 1000;
}
display = bits[display];
// Control del punto decimal
if (ciclar == DISPLAY1 << 1) dec_point = 1 << DP; else dec_point = 0;
gpio_set_mask(ciclar + display + dec_point);
// Espera y limpieza del display
sleep_ms(4);
gpio_clr_mask(ciclar + display + dec_point);
gpio_clr_mask(0xFFFFF);
}
while (true) {}
}