{
    S7_Author := "ABH";
    S7_BlockNumber := "17";
    S7_BlockTitle := "MLC_yr";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION "FC17_ZC_GEST_ALM" : Void
    VAR_INPUT
        { S7_MLC := "MLC_3FJ" }
        Pulso1Seg : Bool;
        { S7_MLC := "MLC_3Ra" }
        Ack : Bool;
        { S7_MLC := "MLC_3bC" }
        AutoAck : Bool;
    END_VAR
    VAR_IN_OUT
        { S7_MLC := "MLC_4tY" }
        ALM : Array[*] of _.UDT_ZC_ALARMA;
        { S7_MLC := "MLC_4ej" }
        AlarmasHMI : Array[*] of Word;
        { S7_MLC := "MLC_42S" }
        NuevaAlarma : Bool;
        { S7_MLC := "MLC_36G" }
        AlgunaAlarma : Bool;
    END_VAR
    VAR_TEMP
        { S7_MLC := "MLC_3pd" }
        for_i : DInt;
        { S7_MLC := "MLC_4S8" }
        t_IndiceSuperiorAlarmas : DInt;
        { S7_MLC := "MLC_53S" }
        t_IndiceInferiorAlarmas : DInt;
        { S7_MLC := "MLC_3NY" }
        t_IndiceSuperiorHmi : DInt;
        { S7_MLC := "MLC_52h" }
        t_IndiceInferiorHmi : DInt;
        t_IndiceAlarma : Int;
        t_ValorAlarma : Bool;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        ###### (C)Copyright ZeusControl 2026 - 2026
        
        ---
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        > **Restricciones:** DB Optimizado.
        
        ---
        ### Descripción Funcional
        
        Función principal para la gestión de alarmas. 
        
        Su objetivo principal es gestionar y temporizar la activacion de las alarmas.
        
        El bloque opera de la siguiente manera:
        
            1. Calcula dinámicamente los límites superior e inferior del array de entrada.
            2. Comprueba la logica de activacion de las alarmas.
            3. Gestiona la conversion de alarmas para HMI.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | `UDT_ZC_ALARMA` |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 21.07.2026 | (ABH)   | Primera version. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION CALCULO_LIMITES_ARRAY
            
            //  Calculo de los limites del array
            #t_IndiceInferiorAlarmas := LOWER_BOUND(ARR := #ALM, DIM := 1);
            #t_IndiceSuperiorAlarmas := UPPER_BOUND(ARR := #ALM, DIM := 1);
            #t_IndiceInferiorHmi := LOWER_BOUND(ARR := #AlarmasHMI, DIM := 1);
            #t_IndiceSuperiorHmi := UPPER_BOUND(ARR := #AlarmasHMI, DIM := 1);
            
        END_REGION CALCULO_LIMITES_ARRAY
        
        
        //  ==========================================================================================================
        REGION GESTION_ALARMAS    
            
            //  Reinicializacion de variables
            #AlgunaAlarma := FALSE;
            
            // Gestion de activacion alarmas
            FOR #for_i := #t_IndiceInferiorAlarmas TO #t_IndiceSuperiorAlarmas DO
                
                #t_ValorAlarma := FALSE;
                
                // Invertir valor en caso de habilitado
                IF #ALM[#for_i].HabilitarInvertir THEN
                    #t_ValorAlarma := NOT #ALM[#for_i].In;
                ELSE
                    #t_ValorAlarma := #ALM[#for_i].In;
                END_IF;
                
                //  Reinicializacion de la salida
                IF #AutoAck THEN
                    
                    #ALM[#for_i].Out := FALSE;
                    
                ELSE
                    
                    IF (#ALM[#for_i].Out AND #Ack)
                        OR
                        #AutoAck
                    THEN
                        #ALM[#for_i].Out := FALSE;
                    END_IF;
                    
                END_IF;
                
                #ALM[#for_i].OutInstantanea := FALSE;
                
                //  Retardo de la activacion de la alarma
                IF #t_ValorAlarma AND #ALM[#for_i].Habilitar THEN
                    
                    IF #ALM[#for_i].TiempoRetardo <> 0 THEN
                        
                        IF #ALM[#for_i].auxTiempoAlarma >= #ALM[#for_i].TiempoRetardo THEN
                            #ALM[#for_i].OutInstantanea := TRUE;
                        ELSE
                            
                            IF #Pulso1Seg THEN
                                #ALM[#for_i].auxTiempoAlarma += 1;
                            END_IF;
                            
                        END_IF;
                        
                    ELSE
                        
                        #ALM[#for_i].OutInstantanea := TRUE;
                    END_IF;
                    
                ELSE
                    #ALM[#for_i].auxTiempoAlarma := 0;
                END_IF;
                
                IF #ALM[#for_i].OutInstantanea THEN
                    #ALM[#for_i].Out := TRUE;
                END_IF;
                
                //  Aalguna alarma
                IF #ALM[#for_i].Out THEN
                    #AlgunaAlarma := TRUE;
                END_IF;
                
                //  Deteccion de nueva alarma
                IF #ALM[#for_i].Out AND NOT #ALM[#for_i].oldAlarma AND #ALM[#for_i].HabilitarSonora THEN
                    #NuevaAlarma := TRUE;
                END_IF;
                
                //  Estado anterior de las alarmas
                #ALM[#for_i].oldAlarma := #ALM[#for_i].Out;
                
            END_FOR;
            
            
        END_REGION GESTION_ALARMAS
        
        
        //  ==========================================================================================================
        REGION GESTION_ALARMAS_HMI
            
            //  Copia de valores de las alarmas a WORD para Scada/HMI
            #t_IndiceAlarma := 1;
            FOR #for_i := #t_IndiceInferiorHmi TO #t_IndiceSuperiorHmi DO
                #AlarmasHMI[#for_i].%X0 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X1 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X2 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X3 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X4 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X5 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X6 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X7 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X8 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X9 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X10 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X11 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X12 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X13 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X14 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
                #AlarmasHMI[#for_i].%X15 := #ALM[#t_IndiceAlarma].Out;
                #t_IndiceAlarma += 1;
            END_FOR;
            
        END_REGION GESTION_ALARMAS_HMI
        
        
        //  ==========================================================================================================
        REGION ACUSE_NUEVA_ALARMA
            
                //  Acuse de nuevas alarmas
                IF #Ack THEN
                    #NuevaAlarma := FALSE;
                END_IF;
            
        END_REGION ACUSE_NUEVA_ALARMA
        
    END_NETWORK
END_FUNCTION
