{
    S7_Author := "ABH";
    S7_BlockComment := "MLC_4dQ";
    S7_BlockNumber := "2927";
    S7_BlockTitle := "MLC_3Pj";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION "FC2927_ZC_FF_SEC_INDV" : Void
    VAR_INPUT
        { S7_MLC := "MLC_W4" }
        Pulso1Seg : Bool;
    END_VAR
    VAR_IN_OUT
        FF_SEC : _.UDT_ZC_DISP_FF_SEC;
    END_VAR
    VAR_TEMP
        for_i : Int;
        t_SumaFlip : Int;
    END_VAR
    VAR CONSTANT
        REPOSO : SInt := 0;
        FLOP : SInt := 10;
        FLIP : SInt := 20;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        ###### (C)Copyright ZeusControl 2023 - 2025
        
        ---
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        > **Restricciones:** Ninguna.
        
        ---
        ### Descripción Funcional
        
        Función encargada de gestionar un dispositivo flip flop secuencial.
        
        Las tareas que realiza son las siguientes:
        
        - Gestionar la activacion y calculos de tiempo de cambio entre ordenes Flip y Flop.
        - Adicionalmente, se gestiona tambien la posibilidad de pausar el contaje del tiempo, para evitar su reinicializacion en caso de pausa.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | `UDT_ZC_DISP_FF_SEC` |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 00.00.01 | 02.10.2023 | (ABH)   | Primera version. |
        | 00.00.02 | 28.11.2023 | (ABH)   | Se añade condicion de activacion del Flip Flop a que algun SP sea mayor que 0. |
        | 01.00.00 | 15.10.2025 | (ABH)   | Se añade orden pausa para dejar de contar. Refactorizacion de logica de gestion de flips. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION GESTION_DISPOSITIVO
            
            // ==========================================================================================================
            REGION COMPROBACIONES_INICIALES
                
                //  Suma de seguridad por FOR (Determinista)
                #t_SumaFlip := 0;
                FOR #for_i := 1 TO 10 DO
                    #t_SumaFlip += #FF_SEC.Config_SetPointTiempoFlip[#for_i];
                END_FOR;
                
                // Si no hay orden o los tiempos globales son 0, reseteamos valores y salimos de la funcion
                IF NOT #FF_SEC.Orden_Activar OR (#t_SumaFlip <= 0 AND #FF_SEC.Config_SetPointTiempoFlop <= 0) THEN
                    #FF_SEC.Estado_SalidaFlop := FALSE;
                    FOR #for_i := 1 TO 10 DO
                        #FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
                    END_FOR;
                    
                    #FF_SEC.Aux_Tiempo := 0;
                    #FF_SEC.Estado_Etapa := #REPOSO;
                    #FF_SEC.Aux_FlipActual := 0;
                    #FF_SEC.Aux_Inicializacion := FALSE;
                    RETURN;
                END_IF;
                
            END_REGION COMPROBACIONES_INICIALES
            
            
            // ==========================================================================================================
            REGION INICIALIZACION
                
                //  Arranque inicial forzado a Flop si no hay estado activo
                IF NOT #FF_SEC.Aux_Inicializacion THEN
                    #FF_SEC.Estado_Etapa := #FLOP;
                    #FF_SEC.Aux_FlipActual := 0;
                    #FF_SEC.Aux_Inicializacion := TRUE;
                END_IF;
                
            END_REGION INICIALIZACION
                
                
                // ==========================================================================================================
                REGION LOGICA_DE_ESTADOS        
                    
                    CASE #FF_SEC.Estado_Etapa OF
                            
                        #FLOP:
                            //  Salidas
                            #FF_SEC.Estado_SalidaFlop := TRUE;
                            FOR #for_i := 1 TO 10 DO
                                #FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
                            END_FOR;
                            
                            //  Conteo de tiempo
                            IF #Pulso1Seg AND NOT #FF_SEC.Orden_Pausa THEN
                                #FF_SEC.Aux_Tiempo += 1;
                            END_IF;
                            
                            //  Transición
                            IF #FF_SEC.Aux_Tiempo >= #FF_SEC.Config_SetPointTiempoFlop THEN
                                #FF_SEC.Aux_Tiempo := 0;
                                #FF_SEC.Aux_FlipActual := 11; // Fallback por defecto
                                
                                //  Buscar primer Flip válido
                                FOR #for_i := 1 TO 10 DO
                                    IF #FF_SEC.Config_SetPointTiempoFlip[#for_i] > 0 THEN
                                        #FF_SEC.Aux_FlipActual := #for_i;
                                        EXIT; // Corta el FOR en el primer acierto
                                    END_IF;
                                END_FOR;
                                
                                //  Transición si encontró algo válido
                                IF #FF_SEC.Aux_FlipActual <= 10 THEN
                                    #FF_SEC.Estado_Etapa := #FLIP;
                                END_IF;
                            END_IF;
                            
                        #FLIP:
                            //  Salidas
                            #FF_SEC.Estado_SalidaFlop := FALSE;
                            FOR #for_i := 1 TO 10 DO
                                IF #for_i = #FF_SEC.Aux_FlipActual THEN
                                    #FF_SEC.Estado_SalidaFlip[#for_i] := TRUE;
                                ELSE
                                    #FF_SEC.Estado_SalidaFlip[#for_i] := FALSE;
                                END_IF;
                            END_FOR;
                            
                            //  Conteo de tiempo
                            IF #Pulso1Seg AND NOT #FF_SEC.Orden_Pausa THEN
                                #FF_SEC.Aux_Tiempo += 1;
                            END_IF;
                            
                            ///  Transición
                            IF #FF_SEC.Aux_Tiempo >= #FF_SEC.Config_SetPointTiempoFlip[#FF_SEC.Aux_FlipActual] THEN
                                #FF_SEC.Aux_Tiempo := 0;
                                #FF_SEC.Aux_FlipActual += 1; // Apunta al siguiente
                                
                                // Búsqueda del siguiente Flip válido
                                FOR #for_i := #FF_SEC.Aux_FlipActual TO 10 DO
                                    IF #FF_SEC.Config_SetPointTiempoFlip[#for_i] > 0 THEN
                                        #FF_SEC.Aux_FlipActual := #for_i;
                                        EXIT;
                                    END_IF;
                                    // Si llega al final sin encontrar nada
                                    IF #for_i = 10 THEN
                                        #FF_SEC.Aux_FlipActual := 11;
                                    END_IF;
                                END_FOR;
                                
                                // Si rebasó el límite, vuelve al Flop
                                IF #FF_SEC.Aux_FlipActual > 10 THEN
                                    #FF_SEC.Estado_Etapa := #FLOP;
                                END_IF;
                            END_IF;
                            
                        ELSE
                            #FF_SEC.Estado_Etapa := #REPOSO;
                    END_CASE;
                    
                END_REGION LOGICA_DE_ESTADOS 
                
        END_REGION GESTION_DISPOSITIVO
          
    END_NETWORK
END_FUNCTION
