DÍA 005 DE 365

Fase 1: Fundamentos de C y Lógica de Software

📖 Teoría Explícita: El Comando `switch` y Enumeradores

1. La Tabla de Saltos (Jump Table) vs. Secuencia

Cuando usas una docena de else if, el procesador (ej. STM32) evalúa la condición #1, luego la #2, luego la #3, y así sucesivamente. El tiempo de ejecución varía dependiendo de qué estado esté activo. En el control de hardware crítico, queremos que los tiempos sean constantes (Determinismo).

El compilador GCC traduce el switch en una Jump Table (Tabla de Saltos). En lugar de evaluar secuencialmente, el procesador usa el valor de la variable como un "índice" para saltar directamente a la línea de código exacta en memoria. Toma el mismo tiempo procesar el estado 1 que el estado 50.

2. El Poder del `enum` (Enumeradores)

Ayer declaramos estados con números "mágicos" (`#define ESTADO_REPOSO 0`). La desventaja es que el compilador los ve como simples enteros, y no puede avisarte si accidentalmente asignas un valor inválido (como 99). Un enum crea un nuevo tipo de dato. Agrupa estados lógicos bajo nombres legibles y ayuda al compilador a validar que no te salgas del guion.

3. El Rol de `break` y `default`

MÁQUINA DE ESTADOS FINITOS (FSM) CON SWITCH ESTADO_INICIO ESTADO_REPOSO ESTADO_DESPACHO ESTADO_FALLO case default: Autodiagnóstico OK Botón Start Corte Volumétrico Interlock Falló

⚙️ Ejercicios Prácticos: Implementando la Máquina de Estados

Ejercicio 1: Remplazaremos las macros `#define` por un enumerador limpio. Luego, convertiremos la maraña de `if/else` del Día 4 en un bloque `switch` ordenado y expansible.


#include <stdint.h>
#include <stdbool.h>

// 1. Declaración del Tipo de Dato (Enumerador)
typedef enum {
    ESTADO_INICIO,
    ESTADO_REPOSO,
    ESTADO_DESPACHO,
    ESTADO_FALLO_CRITICO
} EstadoDespachador_t;

// La variable global ahora es fuertemente tipada
EstadoDespachador_t maquina_estado = ESTADO_INICIO;

// Funciones ficticias de hardware (ya analizadas en días anteriores)
extern bool verificar_permisivos_despacho(void);
extern void Safe_Shutdown(void);
extern void Abrir_Valvulas(void);
extern void run_post_diagnostics(void); // Power-On Self Test

/**
 * @brief Cerebro lógico de la FSM (Finite State Machine).
 */
void actualizar_fsm_despachador(void) {
    
    // El Switch evalúa el estado actual. Al compilar en ARM, esto
    // se optimiza a una Tabla de Saltos (Jump Table).
    switch (maquina_estado) {
        
        case ESTADO_INICIO:
            // Rutina de arranque: Autodiagnóstico de sensores
            run_post_diagnostics();
            
            // Si el hardware responde bien, pasamos a reposo
            if (verificar_permisivos_despacho()) {
                maquina_estado = ESTADO_REPOSO;
            } else {
                maquina_estado = ESTADO_FALLO_CRITICO;
            }
            break; // ¡Crucial para evitar Fall-Through!

        case ESTADO_REPOSO:
            if (!verificar_permisivos_despacho()) {
                maquina_estado = ESTADO_FALLO_CRITICO;
            } else {
                // Lógica de monitoreo del botón de Start
                // if (boton_start_presionado()) { maquina_estado = ESTADO_DESPACHO; }
            }
            break;

        case ESTADO_DESPACHO:
            // Interlock dinámico: Si el despachador está abierto, la presión sube
            // Si perdemos un permisivo (ej. fuga), abortamos inmediatamente.
            if (!verificar_permisivos_despacho()) {
                Safe_Shutdown();
                maquina_estado = ESTADO_FALLO_CRITICO;
            } else {
                Abrir_Valvulas();
                // Lógica volumétrica (Corte por litros)
                // if (volumen_alcanzado()) { 
                //     Safe_Shutdown(); 
                //     maquina_estado = ESTADO_REPOSO; 
                // }
            }
            break;

        case ESTADO_FALLO_CRITICO:
            // Estado Latching (Enclavado). No hay salida automática.
            Safe_Shutdown();
            break;

        default:
            // Atrapamoscas contra corrupción de RAM.
            // Si 'maquina_estado' lee un valor como 0xFF, cae aquí.
            Safe_Shutdown();
            maquina_estado = ESTADO_FALLO_CRITICO;
            break;
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Hito Logrado: Refactorización hacia una FSM (Finite State Machine).

Al implementar el `switch` y los `enum`, has elevado la calidad de tu código de "prototipo" a "grado industrial". Si mañana necesitas agregar un estado intermedio (como ESTADO_AUTENTICACION_RFID), solo agregas una palabra al enumerador y un case al bloque, sin alterar ni romper la lógica de los demás estados. Esta estructura modular es el requisito principal para cuando incorporemos un Sistema Operativo en Tiempo Real (RTOS) más adelante en tu formación.

📝 Resumen del Día

❓ Cuestionario de Autoevaluación

1. ¿Qué ocurriría si eliminas accidentalmente el break; al final del case ESTADO_INICIO:?
Respuesta: Ocurriría un Fall-Through. El procesador ejecutaría la rutina de inicio, e inmediatamente (sin evaluar el estado) continuaría leyendo y ejecutando las líneas del case ESTADO_REPOSO:. Esto causaría un comportamiento impredecible, violando el diseño determinista de la Máquina de Estados Finitos.