#include "pico/stdlib.h"
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
// Definir pines de segmento para el display de 7 segmentos (a - g)
const uint segmentPins[] = {2, 3, 4, 5, 6, 7, 8};
// Definir pines de selección de dígitos (para cada dígito)
const uint digitPins[] = {10, 11, 12, 13};
// Definir pines de botones (para las funciones de reinicio y reversa)
const uint resetPin = 14;
const uint reversePin = 15;
// Codificación para los dígitos 0-9 en un display de 7 segmentos de cátodo común
const bool segmentEncoding[10][7] = {
{0, 0, 0, 0, 0, 0, 1}, // Mostrar 0
{1, 0, 0, 1, 1, 1, 1}, // Mostrar 1
{0, 0, 1, 0, 0, 1, 0}, // Mostrar 2
{0, 0, 0, 0, 1, 1, 0}, // Mostrar 3
{1, 0, 0, 1, 1, 0, 0}, // Mostrar 4
{0, 1, 0, 0, 1, 0, 0}, // Mostrar 5
{0, 1, 0, 0, 0, 0, 0}, // Mostrar 6
{0, 0, 0, 1, 1, 1, 1}, // Mostrar 7
{0, 0, 0, 0, 0, 0, 0}, // Mostrar 8
{0, 0, 0, 0, 1, 0, 0} // Mostrar 9
};
int counter = 0; // Inicializar el contador
bool isReversing = false; // Conteo inverso
uint64_t lastUpdateTime = 0;
const uint64_t updateInterval = 1; // \ \1 ms para actualizaciones de pantalla
// Punteros de función para los callbacks de los botones
void (*onReset)(void);
void (*onReverse)(void);
// Reinicia el valor del contador
void resetCounter() {
counter = 0;
}
// Alterna entre contar hacia arriba y hacia abajo
void switchReverse() {
isReversing = !isReversing;
}
// Activa un dígito específico en el display
void activateDigit(int number, int position) {
// Apagar todos los dígitos primero
for (int i = 0; i < 4; i++) {
gpio_put(digitPins[i], 0);
}
// Configurar los segmentos para el número especificado
for (int i = 0; i < 7; i++) {
gpio_put(segmentPins[i], segmentEncoding[number][i]);
}
// Encender el dígito seleccionado
gpio_put(digitPins[position], 1);
}
// Muestra el número completo de 4 dígitos en el display
void showNumber(int value) {
for (int i = 0; i < 4; i++) {
int currentDigit = (value / (int)pow(10, 3 - i)) % 10; // Extraer cada dígito
activateDigit(currentDigit, i); // Mostrar el dígito actual
sleep_ms(5); // Breve retraso para una visualización suave
}
}
// Establece la función de callback para el botón de reinicio
void setResetFunction(void (*callback)(void)) {
onReset = callback;
}
// Establece la función de callback para el botón de reversa
void setReverseFunction(void (*callback)(void)) {
onReverse = callback;
}
int main() {
// Inicializar pines GPIO para los segmentos
for (int i = 0; i < 7; i++) {
gpio_init(segmentPins[i]);
gpio_set_dir(segmentPins[i], GPIO_OUT);
}
// Inicializar pines GPIO para la selección de dígitos
for (int i = 0; i < 4; i++) {
gpio_init(digitPins[i]);
gpio_set_dir(digitPins[i], GPIO_OUT);
}
// Configurar botones con resistencias de pull-up
gpio_init(resetPin);
gpio_set_dir(resetPin, GPIO_IN);
gpio_pull_up(resetPin);
gpio_init(reversePin);
gpio_set_dir(reversePin, GPIO_IN);
gpio_pull_up(reversePin);
// Asignar funciones de callback
setResetFunction(resetCounter);
setReverseFunction(switchReverse);
// Bucle principal
while (true) {
// Mostrar el valor actual
showNumber(counter);
// Manejar la pulsación del botón de reinicio
if (!gpio_get(resetPin) && onReset != NULL) {
onReset();
}
// Manejar la pulsación del botón de reversa
if (!gpio_get(reversePin) && onReverse != NULL) {
onReverse();
}
// Gestionar el tiempo para el conteo
uint64_t currentTime = time_us_64() / 1000;
if (currentTime - lastUpdateTime >= updateInterval) {
lastUpdateTime = currentTime;
if (isReversing) {
counter--; // Decrementar en modo inverso
if (counter < 0) {
counter = 9999; // Volver a 9999
}
} else {
counter++; // Incrementar en modo normal
if (counter >= 10000) {
counter = 0; // Volver a 0
}
}
}
}
return 0;
}