{
    S7_Author := "ABH";
    S7_BlockComment := "MLC_4ii";
    S7_BlockNumber := "2005";
    S7_BlockTitle := "MLC_3pw";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION "FC2005_ZC_SD" : Void
    VAR_INPUT
        { S7_MLC := "MLC_36J" }
        Pulso1seg : Bool;
        { S7_MLC := "MLC_hm" }
        Simulacion : Bool;
        { S7_MLC := "MLC_4ik" }
        Arranque : Bool;
        { S7_MLC := "MLC_4ps" }
        Ack : Bool;
        { S7_MLC := "MLC_3d4" }
        SeguridadesOK : Bool;
        { S7_MLC := "MLC_4tF" }
        UsuarioActual : String;
        { S7_MLC := "MLC_4ph" }
        FechaHoraActual : DTL;
    END_VAR
    VAR_TEMP
        for_i : Int;
        t_N_MAX : Int;
        t_Activar : Bool;
        t_ActivarConRetardo : Bool;
    END_VAR
    VAR CONSTANT
        TIPO_ACCESO_INDIRECTO : SInt := 0;
        TIPO_ACCESO_PLC : SInt := 1;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        ###### (C)Copyright ZeusControl 2020 - 2026
        
        ---
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        > **Restricciones:** Ninguna.
        
        ---
        ### Descripción Funcional
        
        Funcion para la gestion de dispositivo de tipo Salida Digital.
        
        En ella se realizan las siguientes acciones:
        
        - Se gestiona el multiplexado de los dispositivos para su uso en sistemas HMI/SCADA.
        - Se gestiona el estado del dispositivo
        - Se gestiona la orden de activacion y activacion retardada    
        - Se gestiona la trazabilidad de las manualizaciones del dispositivo
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | - |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 00.00.01 | 26.04.2022 | (HCR)   | Primera version. Cambio en la organizacion del UDT. Se organiza en estructuras en base al tipo de funcion que realizan los datos. |
        | 00.00.02 | 27.04.2022 | (ABH)   | Se añaden auxiliares de estado anterior del modo manual y automatico para poder registrar las trazas. |
        | 00.00.03 | 08.11.2022 | (ABH)   | Se añade trazabilidad manualizaciones |
        | 00.00.03 | 08.11.2022 | (HCR)   | Se añade trazabilidad de activación manual |
        | 00.00.04 | 20.02.2024 | (ABH)   | Se añade gestion multiplexado para Scada (no indexado) |
        | 00.00.05 | 08.01.2025 | (ABH)   | Se añade entrada de primer arranque del PLC para resetear indices de multiplexado Se añade movimiento de ED[0] a multiplexado en caso de que el indice sea 0.  |
        | 00.00.07 | 24.01.2025 | (ABH)   | Se modifica la logica del multiplexado, la asignacion de oldindex se cambia de sitio ya que de vez en cuando (dependiendo de cuando el HMI realiza la comunicacion asincrona con el PLC) no detectaba el cambio y se machacaban valores. |
        | 00.00.08 | 26.03.2025 | (ABH)   | Se añade variable grupo de alarma para separar los nuevos avisos por cuadro. |
        | 00.00.09 | 24.04.2025 | (HCR)   | Se añade gestion de idioma |
        | 00.00.10 | 11.09.2025 | (ABH)   | Se eliminan las constantes de idioma dentro del FC. Se utilizan constantes globales para facilitar su traduccion. |
        | 00.00.11 | 17.12.2025 | (ABH)   | Se eliminan los idiomas. Se utiliza codigos para trazabilidad. Se elimina entrada "Idioma". Se elimina nombre de UDT. Se añade indexHMI para lista de texto en sistemas de supervision. |
        | 00.00.12 | 14.05.2026 | (ABH)   | Se modifica UDT para añadir tipo de lectura. |
        | 01.00.00 | 18.05.2026 | (ABH)   | Se añade variable `Config_TipoAcceso` para uso de direccionamiento indirecto o uso directo en PLC. |
        | 01.01.00 | 08.07.2026 | (ABH)   | Se extrae el multiplexado a FC independiente. Se corrigen logicas de activacion y se añade variable "Estado_Salida". |
        *)
        END_REGION DESCRIPCION
        
        
        REGION LOGICA_DEL_DISPOSITIVO
            
            // =============================================================================
            // Resetear todas las alarmas para que se vuelvan a generar
            FOR #for_i := 0 TO "N_MAX_DISP_AGRUP" DO
                "DB2005_SD".Agrup[#for_i].AlgunaAlarma := FALSE;
                "DB2005_SD".Agrup[#for_i].AlgunaEnManual := FALSE;
            END_FOR;
            
            //  Numero maximo de dispositivos para limitar en HMI/Scada
            "DB2005_SD".NumDispositivos := "N_MAX_DISP_SD";
            
            REGION COMPROBACION_N_MAX
                
                //  Si no hay dispositivos declarados, salimos del bloque inmediatamente
                IF "N_MAX_DISP_SD" <= 0 THEN
                    RETURN;
                END_IF;
                
                //  Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
                #t_N_MAX := "N_MAX_DISP_SD";
                
            END_REGION COMPROBACION_N_MAX
            
            FOR #for_i := 1 TO #t_N_MAX DO
                
                
                // =============================================================================
                // DISPOSITIVO HABILITADO
                // =============================================================================
                IF "DB2005_SD".SD[#for_i].Config_Habilitar THEN
                    
                    REGION LIMITE_GRUPO_ALARMA
                        
                        IF "DB2005_SD".SD[#for_i].Config_GrupoAlarma < 0 THEN
                            "DB2005_SD".SD[#for_i].Config_GrupoAlarma := 0;
                        END_IF;
                        IF "DB2005_SD".SD[#for_i].Config_GrupoAlarma > "N_MAX_DISP_AGRUP" THEN
                            "DB2005_SD".SD[#for_i].Config_GrupoAlarma := "N_MAX_DISP_AGRUP";
                        END_IF;
                        
                    END_REGION LIMITE_GRUPO_ALARMA
                    
                    
                    REGION MODOS_DE_TRABAJO
                        
                        // =============================================================================
                        //  MODO MANUAL
                        IF "DB2005_SD".SD[#for_i].Estado_AutoMan THEN
                            "DB2005_SD".Agrup["DB2005_SD".SD[#for_i].Config_GrupoAlarma].AlgunaEnManual := TRUE;
                            IF "DB2005_SD".SD[#for_i].Orden_ActivarManual AND #SeguridadesOK AND "DB2005_SD".SD[#for_i].Estado_SeguridadOk THEN // En caso de enclavar válvula en manual AND NOT "DB2005_SD".SD[#for_i].Estado_Enclavado  
                                #t_Activar := TRUE;
                            ELSE
                                #t_Activar := FALSE;
                                "DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
                            END_IF;
                        ELSE
                            "DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
                        END_IF;
                        
                        // =============================================================================
                        //  MODO AUTO
                        IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan THEN
                            IF "DB2005_SD".SD[#for_i].Orden_ActivarAuto AND #SeguridadesOK AND "DB2005_SD".SD[#for_i].Estado_SeguridadOk AND NOT "DB2005_SD".SD[#for_i].Estado_Enclavado THEN
                                #t_Activar := TRUE;
                            ELSE
                                #t_Activar := FALSE;
                            END_IF;
                            "DB2005_SD".SD[#for_i].Orden_ActivarManual := "DB2005_SD".SD[#for_i].Estado_Activado;
                        END_IF;
                        //  Reset orden auto
                        "DB2005_SD".SD[#for_i].Orden_ActivarAuto := FALSE;
                        
                    END_REGION MODOS_DE_TRABAJO
                    
                    
                    REGION ESTADO_DEL_DISPOSITIVO
                        
                        // =============================================================================
                        //  SALIDA SIMULADA
                        IF #Simulacion THEN
                            
                            IF #t_Activar THEN
                                "DB2005_SD".SD[#for_i].Estado_Activado := TRUE;
                            ELSE
                                "DB2005_SD".SD[#for_i].Estado_Activado := FALSE;
                            END_IF;
                        END_IF;
                        
                        
                        IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT #Simulacion THEN
                            
                            // =============================================================================
                            //  RETARDO A LA ACTIVACIÓN AUTOMÁTICO
                            IF #t_Activar AND "DB2005_SD".SD[#for_i].Config_HabilitarRetardoAct THEN
                                
                                IF #Pulso1seg AND "DB2005_SD".SD[#for_i].Tiempos_TiempoAct < "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoAct THEN
                                    "DB2005_SD".SD[#for_i].Tiempos_TiempoAct += 1;
                                END_IF;
                                
                                IF "DB2005_SD".SD[#for_i].Tiempos_TiempoAct >= "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoAct THEN
                                    #t_ActivarConRetardo := TRUE;
                                ELSE
                                    #t_ActivarConRetardo := FALSE;
                                END_IF;
                                
                            ELSIF #t_Activar THEN
                                #t_ActivarConRetardo := TRUE;
                            ELSE
                                "DB2005_SD".SD[#for_i].Tiempos_TiempoAct := 0;
                            END_IF;
                            
                            // =============================================================================
                            //  RETARDO A LA DESACTIVACIÓN AUTOMÁTICO
                            IF NOT #t_Activar AND "DB2005_SD".SD[#for_i].Config_HabilitarRetardoDes THEN
                                
                                IF #Pulso1seg AND "DB2005_SD".SD[#for_i].Tiempos_TiempoDes < "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoDes THEN
                                    "DB2005_SD".SD[#for_i].Tiempos_TiempoDes += 1;
                                END_IF;
                                
                                IF "DB2005_SD".SD[#for_i].Tiempos_TiempoDes >= "DB2005_SD".SD[#for_i].Tiempos_SetPointTiempoDes THEN
                                    #t_ActivarConRetardo := FALSE;
                                ELSE
                                    #t_ActivarConRetardo := TRUE;
                                END_IF;
                                
                            ELSIF NOT #t_Activar THEN
                                #t_ActivarConRetardo := FALSE;
                            ELSE
                                "DB2005_SD".SD[#for_i].Tiempos_TiempoDes := 0;
                            END_IF;
                            
                        ELSE
                            
                            #t_ActivarConRetardo := #t_Activar;
                            
                        END_IF;
                        
                        //  Estado activado
                        "DB2005_SD".SD[#for_i].Estado_Activado := #t_ActivarConRetardo;
                        
                    END_REGION ESTADO_DEL_DISPOSITIVO
                    
                    
                    REGION ESCRITURA_SALIDA
                        
                        // =============================================================================
                        //  INVERSION DE LA SALIDA
                        IF "DB2005_SD".SD[#for_i].Config_HabilitarInvertir THEN
                            #t_ActivarConRetardo := NOT #t_ActivarConRetardo;
                        END_IF;
                        
                        
                        CASE "DB2005_SD".SD[#for_i].Config_TipoAcceso OF
                                
                            #TIPO_ACCESO_INDIRECTO:
                                // =============================================================================
                                //  ESCRITURA VALORES DE LA TARJETA
                                IF "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte >= 0 THEN
                                    IF #t_ActivarConRetardo THEN
                                        
                                        "DB2005_SD".SD[#for_i].Estado_Salida := TRUE;
                                        POKE_BOOL(area := 16#82,
                                                  dbNumber := 0,
                                                  byteOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte,
                                                  bitOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaBit,
                                                  value := TRUE);
                                    ELSE
                                        "DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
                                        POKE_BOOL(area := 16#82,
                                                  dbNumber := 0,
                                                  byteOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte,
                                                  bitOffset := "DB2005_SD".SD[#for_i].Config_DireccionSalidaBit,
                                                  value := FALSE);
                                    END_IF;
                                END_IF;
                                
                            #TIPO_ACCESO_PLC:
                                IF #t_ActivarConRetardo THEN
                                    "DB2005_SD".SD[#for_i].Estado_Salida := TRUE;
                                ELSE
                                    "DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
                                END_IF;
                                
                        END_CASE;
                        
                    END_REGION ESCRITURA_SALIDA
                    
                    
                    // =============================================================================
                    //  RESET ORDEN ACTIVAR EN AUTO
                    "DB2005_SD".SD[#for_i].Orden_ActivarAuto := FALSE;
                    
                    
                    REGION TRAZABILIDAD_MANUALIZACION
                        
                        IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT "DB2005_SD".SD[#for_i].Aux_oldAutoMan THEN
                            "FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
                                                    Registrar := 1,
                                                    Categoria := "TRZ_CAT_12_DISP_SD",
                                                    User := #UsuarioActual,
                                                    CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
                                                    CodInt_2 := #for_i,
                                                    CodInt_3 := "TRZ_SYS_DISP_ACC_MAN",
                                                    CodInt_4 := 0,
                                                    CodInt_5 := 0,
                                                    CodReal_1 := 0.0,
                                                    CodReal_2 := 0.0);
                        END_IF;
                        
                        IF NOT "DB2005_SD".SD[#for_i].Estado_AutoMan AND "DB2005_SD".SD[#for_i].Aux_oldAutoMan THEN
                            "FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
                                                    Registrar := 1,
                                                    Categoria := "TRZ_CAT_12_DISP_SD",
                                                    User := #UsuarioActual,
                                                    CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
                                                    CodInt_2 := #for_i,
                                                    CodInt_3 := "TRZ_SYS_DISP_ACC_AUTO",
                                                    CodInt_4 := 0,
                                                    CodInt_5 := 0,
                                                    CodReal_1 := 0.0,
                                                    CodReal_2 := 0.0);
                        END_IF;
                        
                        IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND "DB2005_SD".SD[#for_i].Estado_Activado AND NOT "DB2005_SD".SD[#for_i].Aux_oldActivado THEN
                            "FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
                                                    Registrar := 1,
                                                    Categoria := "TRZ_CAT_12_DISP_SD",
                                                    User := #UsuarioActual,
                                                    CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
                                                    CodInt_2 := #for_i,
                                                    CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_ON",
                                                    CodInt_4 := 0,
                                                    CodInt_5 := 0,
                                                    CodReal_1 := 0.0,
                                                    CodReal_2 := 0.0);
                        END_IF;
                        
                        IF "DB2005_SD".SD[#for_i].Estado_AutoMan AND NOT "DB2005_SD".SD[#for_i].Estado_Activado AND "DB2005_SD".SD[#for_i].Aux_oldActivado THEN
                            "FC8_ZC_TRZ_REGISTRO"(FechaHora := #FechaHoraActual,
                                                    Registrar := 1,
                                                    Categoria := "TRZ_CAT_12_DISP_SD",
                                                    User := #UsuarioActual,
                                                    CodInt_1 := "TRZ_SYS_DISP_TIPO_SD",
                                                    CodInt_2 := #for_i,
                                                    CodInt_3 := "TRZ_SYS_DISP_ACC_MAN_OFF",
                                                    CodInt_4 := 0,
                                                    CodInt_5 := 0,
                                                    CodReal_1 := 0.0,
                                                    CodReal_2 := 0.0);
                        END_IF;
                        
                        
                        
                    END_REGION
                    
                    
                    // =============================================================================
                    // Estado anterior manual/automatico
                    "DB2005_SD".SD[#for_i].Aux_oldAutoMan := "DB2005_SD".SD[#for_i].Estado_AutoMan;
                    "DB2005_SD".SD[#for_i].Aux_oldActivado := "DB2005_SD".SD[#for_i].Estado_Activado;
                    
                ELSE
                    
                    // =============================================================================
                    // DISPOSITIVO DESHABILITADO
                    // =============================================================================
                    "DB2005_SD".SD[#for_i].Estado_Activado := FALSE;
                    "DB2005_SD".SD[#for_i].Estado_AutoMan := FALSE;
                    "DB2005_SD".SD[#for_i].Estado_Enclavado := FALSE;
                    "DB2005_SD".SD[#for_i].Estado_Salida := FALSE;
                    "DB2005_SD".SD[#for_i].Tiempos_TiempoAct := 0;
                    "DB2005_SD".SD[#for_i].Tiempos_TiempoDes := 0;
                    "DB2005_SD".SD[#for_i].Orden_ActivarManual := FALSE;
                    
                END_IF;
                
                
                REGION GESTION_HMI
                    
                    // =============================================================================
                    //  GESTION BITS PARA VISUALIZACION
                    //  Bit     0   Habilitacion
                    //  Bit     1   ManualAutomatico
                    //  Bit     2   Enclavado
                    //  Bit     3   Activado 1
                    //  Bit     4   Activado 2
                    //  Bit     5   Reserva
                    //  Bit     6   Reserva
                    //  Bit     7   Reserva
                    //  Bit     8   Alarma General
                    //  Bit     9   Alarma 1
                    //  Bit     10  Alarma 2
                    //  Bit     11  Alarma 3
                    //  Bit     12  Alarma 4
                    //  Bit     13  Alarma Mantenimiento
                    //  Bit     14  Reserva
                    //  Bit     15  Reserva
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X0 := "DB2005_SD".SD[#for_i].Config_Habilitar;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X1 := "DB2005_SD".SD[#for_i].Estado_AutoMan;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X2 := "DB2005_SD".SD[#for_i].Estado_Enclavado;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X3 := "DB2005_SD".SD[#for_i].Estado_Activado;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X4 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X5 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X6 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X7 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X8 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X9 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X10 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X11 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X12 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X13 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X14 := FALSE;
                    "DB2005_SD".SD[#for_i].Hmi_Estado.%X15 := FALSE;
                    
                END_REGION
                
                
            END_FOR;
            
        END_REGION
        
    END_NETWORK
END_FUNCTION
