FUNCTION "FC2815_ZC_M_MUX" : Void
TITLE = FC2815_ZC_M_MUX
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Funcion de gestion multiplexado dispositivo Motor
   VAR_INPUT 
      Arranque : Bool;   // Primer arranque
      SeguridadesOk : Bool;   // Seguridades OK
   END_VAR

   VAR_TEMP 
      for_mux : Int;
      t_Index : Int;
      t_oldIndex : Int;
      t_N_MAX : Int;
      t_CambioDesdeHMI : Bool;
      t_CambioDesdeMux : Bool;
   END_VAR


BEGIN
	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:** Ninguna.
	
	- - -
	### Descripción Funcional
	El bloque implementa la gestión de multiplexado estático para el dispositivo motor, exponiendo la matriz de equipos de la planta a los sistemas de supervisión SCADA Clásicos (WinCC Professional) sin necesidad de acceso indexado nativo.
	
	Funcionalidades principales de la arquitectura:
	- En el primer arranque del PLC (`#Arranque`), inicializa a `0` los índices (`Index` y `oldIndex`) de todos los canales de multiplexado.
	- Validación de los límites del índice de cada multiplexado frente a la constante `N_MAX_DISP_M`.
	- Detección de cambio de índice (`Index <> oldIndex`) para cargar la estructura completa del equipo seleccionado (`DB2015_M.M[X]`) en la interfaz del multiplexor.
	- Transferencia continua de datos de Solo Lectura (estados, valores actuales, alarmas) desde el PLC hacia el SCADA.
	- Transferencia bidireccional segura de datos de Escritura (consignas, configuraciones y modos) evaluando máscaras de cambios (`CambioDesdeHMI` vs `CambioDesdeMux`) para evitar sobrescrituras accidentales.
	- Gestión de comandos (Resets, pulsadores) con auto-reseteo para evitar el efecto rebote.
	- Caso especial de índice `0`: carga la estructura `M[0]` (reservada y vacía) para limpiar la pantalla del SCADA.
	
	> ** Restricciones: ** Exclusivo para SCADAs sin soporte de indexación directa.
	
	- - -
	### Dependencias Requeridas
	| Tipo | Elementos |
	|------|-----------|
	| FC   | - |
	| FB   | - |
	| DB   | `DB2015_M` |
	| UDT  | `ZC_DISP_M`, `ZC_DISP_MUX_M` | 
	---
	### Historial de Cambios
	| Versión  | Fecha      | Técnico | Cambios |
	|----------|------------|---------|---------|
	| 01.00.00 | 10.07.2026 | (ABH)   | Primera versión extraído a FC independiente. Refactorizacion de multiplexado para su uso solo en WinCC Professional.|
	*)
	END_REGION DESCRIPCION
	
	
	REGION COMPROBACION_N_MAX
	    
	    //  Si no hay Scada declarados, salimos del bloque inmediatamente
	    IF "N_MAX_SCADA" <= 0 THEN
	        RETURN;
	    END_IF;
	    
	    //  Traspaso de N_MAX a variable temporal para evitar fallos de compilacion
	    #t_N_MAX := "N_MAX_SCADA";
	    
	END_REGION COMPROBACION_N_MAX
	
	
	REGION MULTIPLEXADO
	    
	    //  ===========================================================================================================
	    //  Al arranque del PLC, ponemos a 0 todos los indices de los multiplexados
	    IF #Arranque THEN
	        FOR #for_mux := 1 TO #t_N_MAX DO
	            "DB2015_M".Mux.Scada[#for_mux].Index :=
	            "DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
	        END_FOR;
	    END_IF;
	    
	    //  ===========================================================================================================
	    //  Gestion de multiplexado
	    FOR #for_mux := 1 TO #t_N_MAX DO
	        
	        //  ===============================================================================================================
	        //  Antes de iniciar la logica del multiplexado, revisamos los limites
	        REGION LIMITES
	            
	            //  ===========================================================================================================
	            //  Limites
	            IF "DB2015_M".Mux.Scada[#for_mux].Index < 0 THEN
	                "DB2015_M".Mux.Scada[#for_mux].Index := 0;
	            END_IF;
	            IF "DB2015_M".Mux.Scada[#for_mux].Index > "N_MAX_DISP_M" THEN
	                "DB2015_M".Mux.Scada[#for_mux].Index := "N_MAX_DISP_M";
	            END_IF;
	            
	        END_REGION LIMITES
	        
	        
	        REGION INDICES
	            
	            //  Pasamos el indice a variable temporal para evisar cambios no deseados
	            #t_Index := "DB2015_M".Mux.Scada[#for_mux].Index;
	            #t_oldIndex := "DB2015_M".Mux.Scada[#for_mux].oldIndex;
	            
	        END_REGION INDICES
	        
	        
	        IF "DB2015_M".Mux.Scada[#for_mux].Habilitar THEN
	            
	            //  ===========================================================================================================
	            //  Gestionamos solo los tipos 
	            IF #t_Index > 0 THEN
	                
	                REGION CARGA_INICIAL
	                    
	                    //  ===========================================================================================================
	                    //  Al detectar un cambio en el indice del dispositivo, cargamos los valores del dispositivo que tenga el indice.
	                    IF #t_Index <> #t_oldIndex THEN
	                        
	                        //  Traspaso de dispositivos al multiplexado
	                        "DB2015_M".Mux.Scada[#for_mux].M := "DB2015_M".M[#t_Index];
	                        "DB2015_M".Mux.Scada[#for_mux].oldM := "DB2015_M".M[#t_Index];
	                        
	                        //  ===========================================================================================================
	                        //  Valor anterior del indice
	                        "DB2015_M".Mux.Scada[#for_mux].oldIndex := #t_Index;
	                        
	                    END_IF;
	                    
	                END_REGION CARGA_INICIAL
	                
	                
	                REGION DATOS_LECTURA
	                    
	                    //  ===========================================================================================================
	                    //  Movimiento de datos gestionados en FC
	                    "DB2015_M".Mux.Scada[#for_mux].M.Hmi_Estado := "DB2015_M".M[#t_Index].Hmi_Estado;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_SeguridadOk := "DB2015_M".M[#t_Index].Estado_SeguridadOk;
	                    IF NOT "DB2015_M".M[#t_Index].Estado_AutoMan THEN
	                        "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
	                    ELSE
	                        IF NOT #SeguridadesOk OR NOT "DB2015_M".Mux.Scada[#for_mux].M.Estado_SeguridadOk OR "DB2015_M".M[#t_Index].Alarmas_Termico THEN
	                            "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual :=
	                            "DB2015_M".M[#t_Index].Orden_ActivarManual := FALSE;
	                        END_IF;
	                    END_IF;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_Activado := "DB2015_M".M[#t_Index].Estado_Activado;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_Enclavado := "DB2015_M".M[#t_Index].Estado_Enclavado;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_Salida := "DB2015_M".M[#t_Index].Estado_Salida;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_EntradaTermico := "DB2015_M".M[#t_Index].Estado_EntradaTermico;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Estado_EntradaConfMarcha := "DB2015_M".M[#t_Index].Estado_EntradaConfMarcha;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Alarmas_ConfirmacionMarcha := "DB2015_M".M[#t_Index].Alarmas_ConfirmacionMarcha;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Alarmas_General := "DB2015_M".M[#t_Index].Alarmas_General;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Alarmas_Mantenimiento := "DB2015_M".M[#t_Index].Alarmas_Mantenimiento;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Alarmas_Termico := "DB2015_M".M[#t_Index].Alarmas_Termico;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarAuto := "DB2015_M".M[#t_Index].Orden_ActivarAuto;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_Alarma := "DB2015_M".M[#t_Index].Tiempos_Alarma;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_Mantenimiento := "DB2015_M".M[#t_Index].Tiempos_Mantenimiento;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Aux_oldActivado := "DB2015_M".M[#t_Index].Aux_oldActivado;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Aux_oldAlarma := "DB2015_M".M[#t_Index].Aux_oldAlarma;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Aux_oldAutoMan := "DB2015_M".M[#t_Index].Aux_oldAutoMan;
	                    "DB2015_M".Mux.Scada[#for_mux].M.Config_GrupoAlarma := "DB2015_M".M[#t_Index].Config_GrupoAlarma;
	                    
	                END_REGION DATOS_LECTURA
	                
	                
	                REGION DATOS_ESCRITURA
	                    
	                    REGION GESTION_CAMBIOS_DINAMICOS
	                        
	                        //  ===========================================================================================================
	                        //  Estado Auto/Manual
	                        IF "DB2015_M".M[#t_Index].Estado_AutoMan <> "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan THEN
	                            //  Cambio desde HMI
	                            "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
	                        ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan <> "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan THEN
	                            //  Cambio desde Multiplexado
	                            "DB2015_M".M[#t_Index].Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
	                        END_IF;
	                        
	                        //  ===========================================================================================================
	                        //  Orden Activar Manual
	                        IF "DB2015_M".M[#t_Index].Orden_ActivarManual <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual THEN
	                            //  Cambio desde HMI
	                            "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
	                        ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual THEN
	                            //  Cambio desde Multiplexado
	                            "DB2015_M".M[#t_Index].Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
	                        END_IF;
	                        
	                        //  ===========================================================================================================
	                        //  Orden Reset horas
	                        IF "DB2015_M".M[#t_Index].Orden_ResetHoras <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras THEN
	                            //  Cambio desde HMI
	                            "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras := "DB2015_M".M[#t_Index].Orden_ResetHoras;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras := "DB2015_M".M[#t_Index].Orden_ResetHoras;
	                        ELSIF "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras <> "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras THEN
	                            //  Cambio desde Multiplexado
	                            "DB2015_M".M[#t_Index].Orden_ResetHoras := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ResetHoras := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Orden_ResetHoras := FALSE;
	                        END_IF;
	                        
	                    END_REGION GESTION_CAMBIOS_DINAMICOS
	                    
	                    
	                    REGION GESTION_CAMBIOS_CONFIG
	                        
	                        //  Marca auxiliar para indicar que el cambio es desde HMI
	                        //  Comparamos el dispositivo original con el dispositivo real, para detectar cambios desde PLC o desde HMI
	                        #t_CambioDesdeHMI :=
	                        ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit <> "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte <> "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit <> "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte <> "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit <> "DB2015_M".M[#t_Index].Config_DireccionSalidaBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte <> "DB2015_M".M[#t_Index].Config_DireccionSalidaByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar <> "DB2015_M".M[#t_Index].Config_Habilitar)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha <> "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico <> "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento <> "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha <> "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico <> "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso <> "DB2015_M".M[#t_Index].Config_TipoAcceso)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma <> "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento <> "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento);
	                        
	                        //  Marca auxiliar para indicar que el cambio es desde MUX SCADA
	                        //  Comparamos el dispositivo original con el multiplexado, para detectar cambios desde multiplexado
	                        #t_CambioDesdeMux :=
	                        ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso <> "DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma <> "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma)
	                        OR ("DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento <> "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento);
	                        
	                    END_REGION GESTION_CAMBIOS_CONFIG
	                    
	                    
	                    REGION TRASPASO_DATOS
	                        
	                        IF #t_CambioDesdeHMI THEN
	                            
	                            //  Al detectar un cambio desde el HMI, cargamos sus valores de nuevo al multiplexado
	                            "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
	                            
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit := "DB2015_M".M[#t_Index].Config_DireccionSalidaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte := "DB2015_M".M[#t_Index].Config_DireccionSalidaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar := "DB2015_M".M[#t_Index].Config_Habilitar;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico := "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento := "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico := "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso := "DB2015_M".M[#t_Index].Config_TipoAcceso;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma := "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma;
	                            "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento := "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento;
	                            
	                            //  Actualizamos el estado original para configuraciones
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".M[#t_Index].Estado_AutoMan;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".M[#t_Index].Orden_ActivarManual;
	                            
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte := "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte := "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit := "DB2015_M".M[#t_Index].Config_DireccionSalidaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte := "DB2015_M".M[#t_Index].Config_DireccionSalidaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar := "DB2015_M".M[#t_Index].Config_Habilitar;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico := "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento := "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha := "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico := "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso := "DB2015_M".M[#t_Index].Config_TipoAcceso;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma := "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento := "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento;
	                            
	                        ELSIF #t_CambioDesdeMux THEN
	                            
	                            //  Al detectar un cambio desde el MUX, cargamos sus valores al dispositivo
	                            "DB2015_M".M[#t_Index].Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
	                            "DB2015_M".M[#t_Index].Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
	                            
	                            "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit;
	                            "DB2015_M".M[#t_Index].Config_DireccionRetConfMarchaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte;
	                            "DB2015_M".M[#t_Index].Config_DireccionRetTermicoBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit;
	                            "DB2015_M".M[#t_Index].Config_DireccionRetTermicoByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte;
	                            "DB2015_M".M[#t_Index].Config_DireccionSalidaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit;
	                            "DB2015_M".M[#t_Index].Config_DireccionSalidaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte;
	                            "DB2015_M".M[#t_Index].Config_Habilitar := "DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar;
	                            "DB2015_M".M[#t_Index].Config_HabilitarInvertirConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha;
	                            "DB2015_M".M[#t_Index].Config_HabilitarInvertirTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico;
	                            "DB2015_M".M[#t_Index].Config_HabilitarMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento;
	                            "DB2015_M".M[#t_Index].Config_HabilitarRetornoConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha;
	                            "DB2015_M".M[#t_Index].Config_HabilitarRetornoTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico;
	                            "DB2015_M".M[#t_Index].Config_TipoAcceso := "DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso;
	                            "DB2015_M".M[#t_Index].Tiempos_SetPointTiempoAlarma := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma;
	                            "DB2015_M".M[#t_Index].Tiempos_SetPointMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento;
	                            
	                            //  Actualizamos el estado original para configuraciones
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Estado_AutoMan := "DB2015_M".Mux.Scada[#for_mux].M.Estado_AutoMan;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Orden_ActivarManual := "DB2015_M".Mux.Scada[#for_mux].M.Orden_ActivarManual;
	                            
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetConfMarchaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetConfMarchaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionRetTermicoByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionRetTermicoByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaBit := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaBit;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_DireccionSalidaByte := "DB2015_M".Mux.Scada[#for_mux].M.Config_DireccionSalidaByte;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_Habilitar := "DB2015_M".Mux.Scada[#for_mux].M.Config_Habilitar;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarInvertirTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarInvertirTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarMantenimiento;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoConfMarcha := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoConfMarcha;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_HabilitarRetornoTermico := "DB2015_M".Mux.Scada[#for_mux].M.Config_HabilitarRetornoTermico;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Config_TipoAcceso := "DB2015_M".Mux.Scada[#for_mux].M.Config_TipoAcceso;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointTiempoAlarma := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointTiempoAlarma;
	                            "DB2015_M".Mux.Scada[#for_mux].oldM.Tiempos_SetPointMantenimiento := "DB2015_M".Mux.Scada[#for_mux].M.Tiempos_SetPointMantenimiento;
	                            
	                        END_IF;
	                        
	                    END_REGION TRASPASO_DATOS
	                    
	                END_REGION DATOS_ESCRITURA
	                
	            ELSE
	                
	                //  ===========================================================================================================
	                //  En caso de que el indice sea 0, movemos el valor de la M[0] que no se usa para escribir el index.
	                "DB2015_M".Mux.Scada[#for_mux].M := "DB2015_M".M[0];
	                "DB2015_M".Mux.Scada[#for_mux].oldM := "DB2015_M".M[0];
	                
	                //  Actualizacion de estado anterior
	                "DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
	                
	            END_IF;
	            
	        ELSE
	            
	            //  Multiplexado no habilitado
	            "DB2015_M".Mux.Scada[#for_mux].Index :=
	            "DB2015_M".Mux.Scada[#for_mux].oldIndex := 0;
	            
	        END_IF;
	        
	    END_FOR;
	    
	END_REGION MULTIPLEXADO
	
END_FUNCTION

