{
    S7_BlockNumber := "3";
    S7_EditorMode := "SCL";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "0.1"
}
FUNCTION_BLOCK "FB3_ZC_CHECKSUM"
    VAR_INPUT
        Comprobar : Bool;
        Copiar : Bool;
    END_VAR
    VAR_OUTPUT
        CheckSumOK : Bool;
    END_VAR
    VAR
        {
            S7_Access := "ReadOnly := External";
            S7_Setpoint := "False";
            S7_Visibility := "Hidden := External"
        }
        s_GetCheckSum : GetChecksum;
    END_VAR
    VAR RETAIN
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_EstadoCheckSum : Array[0..7] of Byte;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_CheckSumFabrica : Array[0..7] of Byte;
    END_VAR
    VAR
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_Comprobar : Bool;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_OldComprobar : Bool;
    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         |
        
        ---
        ### Descripción Funcional
        El bloque `FB3_CHECKSUM` implementa la lectura del checksum del programa actual del PLC y su comparación con el checksum de fábrica, permitiendo detectar modificaciones no autorizadas en el proyecto.
        
        Funcionalidades principales:
        - Detección de flanco ascendente en la entrada `#Comprobar` para ejecutar la comprobación bajo demanda (modo "pulso"), mediante la variable interna `#s_OldComprobar`.
        - Lectura del checksum del bloque `Scope:=1` (objeto PLC) con `Range:=0` y `Subrange:=0` (rango completo), invocando la función de sistema `GetChecksum` a través del FB `GetChecksum` y depositando el resultado en `#s_EstadoCheckSum`.
        - Captura del checksum de fábrica: cuando se activa la entrada `#Copiar`, se copia el checksum actual al valor de referencia `#s_CheckSumFabrica`, operación que se realiza una sola vez durante la puesta en marcha para fijar la línea base.
        - Comparación continua entre el checksum actual y el de fábrica, exponiendo el resultado en la salida `#CheckSumOK` (TRUE cuando coinciden).
        
        > **Restricciones:** Ninguna.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | `GetChecksum` |
        | DB   | - |
        | UDT  | - |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 28.09.2020 | (ABH)   | Primera versión. |
        | 01.00.01 | 02.07.2026 | (ABH)   | Cambio a SCL. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION ORDEN_COMPROBACION
            
            //  Comprobacion mediante un pulso
            #s_Comprobar := #Comprobar AND NOT #s_OldComprobar;
            
            //  Estado anterior
            #s_OldComprobar := #Comprobar;
            
        END_REGION ORDEN_COMPROBACION
        
        
        //  ==========================================================================================================
        REGION LECTURA_CHECKSUM
            
            //  Comprobacion mediante un pulso
            #s_GetCheckSum(Scope:=1,
                          Range:=0,
                          Subrange:=0,
                          Checksum:=#s_EstadoCheckSum);
           
           //   Copia de checksum a valor de fabrica
           IF #Copiar THEN
               #s_CheckSumFabrica := #s_EstadoCheckSum;
           END_IF;
            
        END_REGION LECTURA_CHECKSUM
        
        
        //  ==========================================================================================================
        REGION SALIDAS
            
            //  Checksum OK
            #CheckSumOK := #s_EstadoCheckSum = #s_CheckSumFabrica;
            
        END_REGION SALIDAS
        
    END_NETWORK
END_FUNCTION_BLOCK
