#include <16F628A.h>
// Configuración de fusibles para cristal externo de 4MHz u oscilador interno
#fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, MCLR
#use delay(clock=4000000)
// ---- ASIGNACIÓN DE PINES (12 LEDs) ----
#define LED1 PIN_B0
#define LED2 PIN_B1
#define LED3 PIN_B2
#define LED4 PIN_B3
#define LED5 PIN_B4
#define LED6 PIN_B5
#define LED7 PIN_B6
#define LED7_BIT 6
#define LED8 PIN_B7
#define LED9 PIN_A0
#define LED10 PIN_A1
#define LED11 PIN_A2
#define LED12 PIN_A3
// ---- CONTROL Y ENTRADA ----
#define BOTON_MODO PIN_A5 // Pin RA5 configurado como entrada para el pulsador
#define ANALOG_IN PIN_A4 // Pin RA4 (Entrada del Comparador 1)
// Variables globales para la animación del vúmetro
int1 modo_barra = 1; // 1 = Modo Barra (LM3914), 0 = Modo Punto
int8 pico_actual = 0; // Guarda el LED más alto alcanzado
int16 retencion_timer = 0; // Contador de tiempo para sostener el pico
// Función para actualizar los 12 LEDs según el nivel y el modo seleccionado
void actualizar_vumetro(int8 nivel) {
// Actualizar el pico más alto (Peak Hold)
if (nivel >= pico_actual && nivel > 0) {
pico_actual = nivel;
retencion_timer = 30;
} else {
if (retencion_timer > 0) {
retencion_timer--;
} else {
if (pico_actual > 0) pico_actual--;
}
}
// Renderizado físico en los pines
if (modo_barra) {
// --- MODO BARRA ---
output_bit(LED1, (nivel >= 1));
output_bit(LED2, (nivel >= 2));
output_bit(LED3, (nivel >= 3));
output_bit(LED4, (nivel >= 4));
output_bit(LED5, (nivel >= 5));
output_bit(LED6, (nivel >= 6));
output_bit(LED7, (nivel >= 7));
output_bit(LED8, (nivel >= 8));
output_bit(LED9, (nivel >= 9));
output_bit(LED10, (nivel >= 10));
output_bit(LED11, (nivel >= 11));
output_bit(LED12, (nivel >= 12));
} else {
// --- MODO PUNTO --- (Enciende el nivel actual o el punto de pico retenido)
output_bit(LED1, (nivel == 1 || pico_actual == 1));
output_bit(LED2, (nivel == 2 || pico_actual == 2));
output_bit(LED3, (nivel == 3 || pico_actual == 3));
output_bit(LED4, (nivel == 4 || pico_actual == 4));
output_bit(LED5, (nivel == 5 || pico_actual == 5));
output_bit(LED6, (nivel == 6 || pico_actual == 6));
output_bit(LED7, (nivel == 7 || pico_actual == 7));
output_bit(LED8, (nivel == 8 || pico_actual == 8));
output_bit(LED9, (nivel == 9 || pico_actual == 9));
output_bit(LED10, (nivel == 10 || pico_actual == 10));
output_bit(LED11, (nivel == 11 || pico_actual == 11));
output_bit(LED12, (nivel == 12 || pico_actual == 12));
}
}
void main() {
int8 i = 0;
int8 lectura_vref = 0;
// TRIS: Puertos B como salidas completas. Puerto A salidas excepto RA4 y RA5.
set_tris_b(0x00);
set_tris_a(0x30); // 00110000 b (Pines RA4 y RA5 como entradas)
// Configuración del comparador: RA4 es comparado con la referencia interna VREF
setup_comparators(A4_VR_A4_VR);
while(TRUE) {
lectura_vref = 0;
for(i = 1; i <= 15; i++) {
setup_vref(VREF_LOW | i);
delay_us(15);
if(C1OUT) {
lectura_vref = i;
}
}
int8 nivel_leds = (lectura_vref * 12) / 15;
actualizar_vumetro(nivel_leds);
if(!input(BOTON_MODO)) {
delay_ms(20);
if(!input(BOTON_MODO)) {
modo_barra = !modo_barra;
while(!input(BOTON_MODO));
}
}
delay_ms(10);
}
}