﻿%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Device definition for IMSE ExM28
%
% Settings module:
%       Parity: None
%       Baud:   38400
%       Mode:   RTU
%       
% Factory default 
%       Address: 1
% 
% Author: Daniel Carlson, ABELKO AB Luleå
%
% History:  2014-03-28 Initial version
%           2015-11-26 Converted to fit WMPro
%           2016-03-23 RWORD not allowed as comparison in answers
%           2016-04-08 Group script for UI added
%
DEVICETYPE ExM28_DI_DO NAMED "ExM28_DI_DO" TYPEID 21471 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Communication timeout
    ComTimeout: "ComTimeout";
       
    % Trip voltage
    DI_TripVoltage: "DI Trip voltage";
    
    % Digital output
    DO1: "DO1";      
    DO2: "DO2";      
    DO3: "DO3";      
    DO4: "DO4";      
    DO5: "DO5";      
    DO6: "DO6";
      
  PUBLIC
    % Digital input
    DI1  :"DI1";      
    DI2  :"DI2";      
    DI3  :"DI3";      
    DI4  :"DI4";      
    DI5  :"DI5";      
    DI6  :"DI6";      
    DI7  :"DI7";      
    DI8  :"DI8";
    
    % Short circuit
    DI_ShortCirc: "DI Short Circuit";
    
    % DO Override
    DO1_Overridden : "DO1 Man. overr.";      
    DO2_Overridden : "DO2 Man. overr.";      
    DO3_Overridden : "DO3 Man. overr.";      
    DO4_Overridden : "DO4 Man. overr.";   
    DO5_Overridden : "DO5 Man. overr.";      
    DO6_Overridden : "DO6 Man. overr.";    
    
  PRIVATE
    Tmp;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
  
  TELEGRAM SetComTimeout NAMED "SetCommunicationTimeout" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(6);       % Modbus command "6" write single register
      DATA[2]  := RWORD(101);    % Start register
      DATA[4]  <- RWORD(DATA := ComTimeout;); 
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(6);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(101);
  
    TIMEOUT 300
  END;
  
  TELEGRAM SetDO1_6 NAMED "SetDO1-6" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(102);    % Start register
      DATA[4]  := RWORD(6);      % Number of registers to write
      DATA[6]  := BYTE(12);      % Numer of bytes of data, two for each DO
      DATA[7]  <- RWORD(DATA := DO1;);
      DATA[9]  <- RWORD(DATA := DO2;);
      DATA[11] <- RWORD(DATA := DO3;);
      DATA[13] <- RWORD(DATA := DO4;);
      DATA[15] <- RWORD(DATA := DO5;);
      DATA[17] <- RWORD(DATA := DO6;);
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(102);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(6);

    TIMEOUT 300
  END;
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for settting values in the unit
  TELEGRAM SetDISettings NAMED "SetDISettings" IS
    QUESTION
      DATA[0] := BYTE(Addr);     % Modbus unit address
      DATA[1] := BYTE(6);        % Modbus command "16" write multiple registers
      DATA[2] := RWORD(100);     % Start register
      DATA[4] <- RWORD(DATA := DI_TripVoltage;);
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(6);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(100);
  
    TIMEOUT 300
  END;
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit
  
  TELEGRAM GetDIStatus NAMED "GetDIStatus" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(49);     % Start register
      DATA[4]  := RWORD(1);      % Number of registers to read
            
    ANSWER SIZE 7
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(2);      % Numer of bytes of data
      DATA[3]  -> RWORD(DI_ShortCirc := DATA;); 
          
    TIMEOUT 300
  END;
  
  TELEGRAM GetDI1_8 NAMED "DI1-8" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(1);      % Start register
      DATA[4]  := RWORD(8);      % Number of registers to read
            
    ANSWER SIZE 21
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(16);      % Numer of bytes of data, two for each DI
      DATA[3]  -> RWORD(DI1 := DATA;); 
      DATA[5]  -> RWORD(DI2 := DATA;); 
      DATA[7]  -> RWORD(DI3 := DATA;);
      DATA[9]  -> RWORD(DI4 := DATA;);
      DATA[11] -> RWORD(DI5 := DATA;);
      DATA[13] -> RWORD(DI6 := DATA;);
      DATA[15] -> RWORD(DI7 := DATA;);
      DATA[17] -> RWORD(DI8 := DATA;);
      
    TIMEOUT 300
  END;
      
  TELEGRAM GetDOManualOverrideStatus NAMED "DOManualOverrideStatus" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(50);     % Start register
      DATA[4]  := RWORD(6);      % Number of registers to read
            
    ANSWER SIZE 17
      DATA[0]  =   BYTE(Addr);    % Modbus unit address
      DATA[1]  =   BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =   BYTE(12);      % Numer of bytes of data
      DATA[3]  ->  RWORD(DO1_Overridden := DATA;);
      DATA[5]  ->  RWORD(DO2_Overridden := DATA;);
      DATA[7]  ->  RWORD(DO3_Overridden := DATA;);
      DATA[9]  ->  RWORD(DO4_Overridden := DATA;);
      DATA[11] ->  RWORD(DO5_Overridden := DATA;);
      DATA[13] ->  RWORD(DO6_Overridden := DATA;);
      
    TIMEOUT 300
  END;  
END;

DEVICETYPE ExM28_Freq_Count NAMED "ExM28_Freq_Count" TYPEID 21472 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Flank Settings
    DI1_FlankSettings: "DI1 Pulse edge";      
    DI2_FlankSettings: "DI2 Pulse edge";      
    DI3_FlankSettings: "DI3 Pulse edge";      
    DI4_FlankSettings: "DI4 Pulse edge";    
    DI5_FlankSettings: "DI5 Pulse edge";      
    DI6_FlankSettings: "DI6 Pulse edge";      
    DI7_FlankSettings: "DI7 Pulse edge";      
    DI8_FlankSettings: "DI8 Pulse edge";
          
  PUBLIC
    % Frequency
    DI1_Freq   :"DI1 Frequency";      
    DI2_Freq   :"DI2 Frequency";      
    DI3_Freq   :"DI3 Frequency";      
    DI4_Freq   :"DI4 Frequency";      
    DI5_Freq   :"DI5 Frequency";      
    DI6_Freq   :"DI6 Frequency";      
    DI7_Freq   :"DI7 Frequency";      
    DI8_Freq   :"DI8 Frequency";
      
    % Counter
    DI1_Counter  :"DI1 Counter";      
    DI2_Counter  :"DI2 Counter";      
    DI3_Counter  :"DI3 Counter";      
    DI4_Counter  :"DI4 Counter";      
    DI5_Counter  :"DI5 Counter";      
    DI6_Counter  :"DI6 Counter";      
    DI7_Counter  :"DI7 Counter";      
    DI8_Counter  :"DI8 Counter";
        
  PRIVATE
    Tmp;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for settting values in the unit
  
  TELEGRAM SetFlankSettings NAMED "SetFlankSettings" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(92);     % Start register
      DATA[4]  := RWORD(8);      % Number of registers to write
      DATA[6]  := BYTE(16);      % Numer of bytes of data, two for each register
      DATA[7]  <- RWORD(DATA := DI1_FlankSettings * 4;);
      DATA[9]  <- RWORD(DATA := DI2_FlankSettings * 4;);
      DATA[11] <- RWORD(DATA := DI3_FlankSettings * 4;);
      DATA[13] <- RWORD(DATA := DI4_FlankSettings * 4;);
      DATA[15] <- RWORD(DATA := DI5_FlankSettings * 4;);
      DATA[17] <- RWORD(DATA := DI6_FlankSettings * 4;);
      DATA[19] <- RWORD(DATA := DI7_FlankSettings * 4;);
      DATA[21] <- RWORD(DATA := DI8_FlankSettings * 4;);
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(92);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(8);
  
    TIMEOUT 300
  END;
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit

  TELEGRAM GetDI1_8Freq_Cnt NAMED "DI1-8Freq_Cnt" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(9);      % Start register
      DATA[4]  := RWORD(32);     % Number of registers to read
            
    ANSWER SIZE 69
      DATA[0]   =  BYTE(Addr);    % Modbus unit address
      DATA[1]   =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]   =  BYTE(64);      % Numer of bytes of data, two for each DI
      DATA[3]   ->  RWORD(Tmp      :=  DATA;);
      DATA[5]   ->  RWORD(DI1_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[7]   ->  RWORD(Tmp      :=  DATA;);
      DATA[9]   ->  RWORD(DI2_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[11]  ->  RWORD(Tmp      :=  DATA;);
      DATA[13]  ->  RWORD(DI3_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[15]  ->  RWORD(Tmp      :=  DATA;);
      DATA[17]  ->  RWORD(DI4_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[19]  ->  RWORD(Tmp      :=  DATA;);
      DATA[21]  ->  RWORD(DI5_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[23]  ->  RWORD(Tmp      :=  DATA;);
      DATA[25]  ->  RWORD(DI6_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[27]  ->  RWORD(Tmp      :=  DATA;);
      DATA[29]  ->  RWORD(DI7_Freq := (DATA + Tmp*65536) / 1000;);
      DATA[31]  ->  RWORD(Tmp      :=  DATA;);
      DATA[33]  ->  RWORD(DI8_Freq := (DATA + Tmp*65536) / 1000;);
      
      DATA[35]  ->  RWORD(Tmp         := DATA;);
      DATA[37]  ->  RWORD(DI1_Counter := DATA + Tmp*65536;);
      DATA[39]  ->  RWORD(Tmp         := DATA;);
      DATA[41]  ->  RWORD(DI2_Counter := DATA + Tmp*65536;);
      DATA[43]  ->  RWORD(Tmp         := DATA;);
      DATA[45]  ->  RWORD(DI3_Counter := DATA + Tmp*65536;);
      DATA[47]  ->  RWORD(Tmp         := DATA;);
      DATA[49]  ->  RWORD(DI4_Counter := DATA + Tmp*65536;);
      DATA[51]  ->  RWORD(Tmp         := DATA;);
      DATA[53]  ->  RWORD(DI5_Counter := DATA + Tmp*65536;);
      DATA[55]  ->  RWORD(Tmp         := DATA;);
      DATA[57]  ->  RWORD(DI6_Counter := DATA + Tmp*65536;);
      DATA[59]  ->  RWORD(Tmp         := DATA;);
      DATA[61]  ->  RWORD(DI7_Counter := DATA + Tmp*65536;);
      DATA[63]  ->  RWORD(Tmp         := DATA;);
      DATA[65]  ->  RWORD(DI8_Counter := DATA + Tmp*65536;);
            
    TIMEOUT 300
  END;
END;

DEVICETYPE ExM28_AO NAMED "ExM28_AO" TYPEID 21473 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Communication timeout
    % ComTimeout: "ComTimeout"; Note! Use DI_DO-script to set this parameter

    % Analog output
    AO1: "AO1";      
    AO2: "AO2";      
    AO3: "AO3";      
    AO4: "AO4";      
    AO5: "AO5";      
    AO6: "AO6";
      
  PUBLIC
    % AO Override
    AO1_Overridden : "AO1 Man. overr.";      
    AO2_Overridden : "AO2 Man. overr.";      
    AO3_Overridden : "AO3 Man. overr.";      
    AO4_Overridden : "AO4 Man. overr.";      
    AO5_Overridden : "AO5 Man. overr.";      
    AO6_Overridden : "AO6 Man. overr.";      
    
  PRIVATE
    Tmp;
    Tmp2;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
      
  TELEGRAM SetAO1_6 NAMED "SetAO1-6" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(116);    % Start register
      DATA[4]  := RWORD(12);     % Number of registers to write
      DATA[6]  := BYTE(24);      % Numer of bytes of data, two for each AO
      DATA[7]  := RWORD(0);
      DATA[9]  <- RWORD(DATA :=  AO1 * 1000;);
      DATA[11] := RWORD(0);
      DATA[13] <- RWORD(DATA :=  AO2 * 1000;);
      DATA[15] := RWORD(0);
      DATA[17] <- RWORD(DATA :=  AO3 * 1000;);
      DATA[19] := RWORD(0);
      DATA[21] <- RWORD(DATA :=  AO4 * 1000;);
      DATA[23] := RWORD(0);
      DATA[25] <- RWORD(DATA :=  AO5 * 1000;);
      DATA[27] := RWORD(0);
      DATA[29] <- RWORD(DATA :=  AO6 * 1000;);
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(116);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(12);

    TIMEOUT 300
  END;
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit
  
  TELEGRAM GetAO1_6Status NAMED "GetAO1-6Status" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(80);     % Start register
      DATA[4]  := RWORD(12);     % Number of registers to read
            
    ANSWER SIZE 29
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(24);      % Numer of bytes of data
      DATA[3]  -> RWORD(Tmp :=  DATA;);
      DATA[5]  -> RWORD(IF DATA < 32768 THEN AO1_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO1_Overridden := -1; ENDIF;);
      DATA[7]  -> RWORD(Tmp :=  DATA;);
      DATA[9]  -> RWORD(IF DATA < 32768 THEN AO2_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO2_Overridden := -1; ENDIF;);
      DATA[11] -> RWORD(Tmp :=  DATA;);
      DATA[13] -> RWORD(IF DATA < 32768 THEN AO3_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO3_Overridden := -1; ENDIF;);
      DATA[15] -> RWORD(Tmp :=  DATA;);
      DATA[17] -> RWORD(IF DATA < 32768 THEN AO4_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO4_Overridden := -1; ENDIF;);
      DATA[19] -> RWORD(Tmp :=  DATA;);
      DATA[21] -> RWORD(IF DATA < 32768 THEN AO5_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO5_Overridden := -1; ENDIF;);
      DATA[23] -> RWORD(Tmp :=  DATA;);
      DATA[25] -> RWORD(IF DATA < 32768 THEN AO6_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO6_Overridden := -1; ENDIF;);
      
    TIMEOUT 300
  END;
END;

DEVICETYPE ExM28_UI NAMED "ExM28_UI" TYPEID 21470 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Universal input type
    UI1_Type: "UI1 Type";      
    UI2_Type: "UI2 Type";      
    UI3_Type: "UI3 Type";      
    UI4_Type: "UI4 Type";      
    UI5_Type: "UI5 Type";      
    UI6_Type: "UI6 Type";      
    UI7_Type: "UI7 Type";      
    UI8_Type: "UI8 Type";
    
    % Resistor Range
    %UI1_Range: "UI1_Range ";
    %UI2_Range: "UI2_Range ";
    %UI3_Range: "UI3_Range ";
    %UI4_Range: "UI4_Range ";
    %UI5_Range: "UI5_Range ";
    %UI6_Range: "UI6_Range ";
    %UI7_Range: "UI7_Range ";
    %UI8_Range: "UI8_Range ";
      
  PUBLIC
    % Universal input value
    UI1 : "UI1";      
    UI2 : "UI2";      
    UI3 : "UI3";      
    UI4 : "UI4";      
    UI5 : "UI5";      
    UI6 : "UI6";      
    UI7 : "UI7";      
    UI8 : "UI8";
   
    % Universal input status
    UI1_Status : "UI1 Status";      
    UI2_Status : "UI2 Status";      
    UI3_Status : "UI3 Status";      
    UI4_Status : "UI4 Status";      
    UI5_Status : "UI5 Status";      
    UI6_Status : "UI6 Status";      
    UI7_Status : "UI7 Status";      
    UI8_Status : "UI8 Status";
          
  PRIVATE
    Tmp;
    UI1_Raw;
    UI2_Raw;
    UI3_Raw;
    UI4_Raw;
    UI5_Raw;
    UI6_Raw;
    UI7_Raw;
    UI8_Raw;
    
    % Used by group script
    Input;
    Raw;
    Type;
    Value;
    R2;
    R3;
    R5;
    R7;
    LNR;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
    
  TELEGRAM SetUISettings NAMED "SetUISettings" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(108);    % Start register
      DATA[4]  := RWORD(8);      % Number of registers to write
      DATA[6]  := BYTE(16);      % Numer of bytes of data, two for each DO
      DATA[7]  <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI1_Type * 64; ENDIF;);
      DATA[9]  <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI2_Type * 64; ENDIF;);
      DATA[11] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI3_Type * 64; ENDIF;);
      DATA[13] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI4_Type * 64; ENDIF;);
      DATA[15] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI5_Type * 64; ENDIF;);
      DATA[17] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI6_Type * 64; ENDIF;);
      DATA[19] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI7_Type * 64; ENDIF;);
      DATA[21] <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI8_Type * 64; ENDIF;);
          
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(108);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(8);

    TIMEOUT 300
  END;
      
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit
    
  TELEGRAM GetUI1_8 NAMED "GetUI1-8" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(56);     % Start register
      DATA[4]  := RWORD(16);     % Number of registers to read
            
    ANSWER SIZE 37
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(32);      % Numer of bytes of data
      
      DATA[3]  -> RWORD(Tmp     :=  DATA;);
      DATA[5]  -> RWORD(UI1_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[7]  -> RWORD(Tmp     :=  DATA;);
      DATA[9]  -> RWORD(UI2_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[11] -> RWORD(Tmp     :=  DATA;);
      DATA[13] -> RWORD(UI3_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[15] -> RWORD(Tmp     :=  DATA;);
      DATA[17] -> RWORD(UI4_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[19] -> RWORD(Tmp     :=  DATA;);
      DATA[21] -> RWORD(UI5_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[23] -> RWORD(Tmp     :=  DATA;);
      DATA[25] -> RWORD(UI6_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[27] -> RWORD(Tmp     :=  DATA;);
      DATA[29] -> RWORD(UI7_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[31] -> RWORD(Tmp     :=  DATA;);
      DATA[33] -> RWORD(UI8_Raw := (DATA + Tmp*65536) / 1000;);
      
    TIMEOUT 300
  END;
  
  TELEGRAM GetUI1_8Status NAMED "GetUI1-8Status" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(72);     % Start register
      DATA[4]  := RWORD(8);      % Number of registers to read
            
    ANSWER SIZE 21
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(16);      % Numer of bytes of data
      DATA[3]  -> RWORD(UI1_Status := DATA;);
      DATA[5]  -> RWORD(UI2_Status := DATA;);
      DATA[7]  -> RWORD(UI3_Status := DATA;);
      DATA[9]  -> RWORD(UI4_Status := DATA;);
      DATA[11] -> RWORD(UI5_Status := DATA;);
      DATA[13] -> RWORD(UI6_Status := DATA;);
      DATA[15] -> RWORD(UI7_Status := DATA;);
      DATA[17] -> RWORD(UI8_Status := DATA;);
      
    TIMEOUT 300
  END;
END; 


% Group script used to calulate vaues for universal inputs
GROUP All_UI OF MAX 4 DEVICE TYPEID 21470 SELECT ALL
  ITERATOR CalcValue
  ALIAS
  BEGIN
    IF Input = 1 THEN
      Type  := UI2_Type;
      Raw   := UI2_Raw;
    ELSIF Input = 2 THEN
      Type  := UI3_Type;
      Raw   := UI3_Raw;
    ELSIF Input = 3 THEN
      Type  := UI4_Type;
      Raw   := UI4_Raw;
    ELSIF Input = 4 THEN
      Type  := UI5_Type;
      Raw   := UI5_Raw;
    ELSIF Input = 5 THEN
      Type  := UI6_Type;
      Raw   := UI6_Raw;
    ELSIF Input = 6 THEN
      Type  := UI7_Type;
      Raw   := UI7_Raw;
    ELSIF Input = 7 THEN
      Type  := UI8_Type;
      Raw   := UI8_Raw;
    ELSE	
      Type  := UI1_Type;
      Raw   := UI1_Raw;
      Input := 0;
    ENDIF;
    
    IF Type <= 3 THEN % Raw resistance, Voltage, Current or DI
      Value := Raw;
    
    ELSIF Type = 4 THEN %Pt100 EN 50 751 alpha 0.00385
      Value := 3383.809524 - 0.08658008660 * (1758480889 - 2310000 * Raw)^0.5;
    ELSIF Type = 5 THEN %Pt100 alpha 0.00375
      Value := 3164.451827 - 8305.647840 * (0.169241 - 0.000240800 * Raw)^0.5;
    ELSIF Type = 6 THEN %Pt100 alpha 0.00392
      Value := 3392.940594 - 8527.911855 * (0.1817473668 - 0.00023452400 * Raw)^0.5;
    ELSIF Type = 7 THEN %Pt1000 EN 50 751 alpha 0.00385
      Value := 3383.809524 - 865.8008660 * (17.58480889 - 0.00231 * Raw)^0.5;
    ELSIF Type = 8 THEN %Pt1000 alpha 0.00375
      Value := 3164.451827 - 830.5647840 * (16.9241 - 0.002408 * Raw)^0.5;
    ELSIF Type = 9 THEN %Pt1000 alpha 0.00392
      Value := 3392.940594 - 852.7911855 * (18.17473668 - 0.00234524 * Raw)^0.5;
    ELSIF	Type = 10 THEN %Ni1000 DIN
      R5:= Raw*Raw*Raw*Raw*Raw;
      R7:= R5*Raw*Raw;
      Value := (-412.6) + (140.41 * (1 + (0.00764 * Raw))^0.5) - (0.0000000000000000625 * R5) - (0.00000000000000000000000125 * R7);
    ELSIF	Type = 11 THEN %Ni1000 LG
      R2:= Raw*Raw;
      R3:= R2*Raw;
      Value := (-300.0187) + (Raw * 0.3888) - (R2 * 0.00010355) + (R3 * 0.000000014749);
    ELSIF	Type = 12 THEN %QAC31/32 old
      R2:= Raw*Raw;
      R3:= R2*Raw;
      IF Raw <= 622.27 THEN
        Value :=  1840.822526461981 - (8.81283638032425 * Raw) + (0.01481833026842 * R2) - (0.000008693645718129028 * R3);
      ELSIF Raw <= 655.74 THEN
        Value :=  18284.57180623524 - (87.53497076730491 * Raw) + (0.14047361791540 * R2) - (0.00007556728104760220 * R3);
      ELSE
        Value :=  447598.5593294129 - (2034.707401563966 * Raw) + (3.08435262703205 * R2) - (0.00155918519608 * R3);      
      ENDIF;  
    ELSIF	Type = 13 THEN %NTC575 (QAC3132)
      R2:= Raw*Raw;
      R3:= R2*Raw;
      IF Raw <= 616.7 THEN
        Value :=  1984.368236149433 - (9.45847603610924 * Raw) + (0.01577267911992 * R2) - (0.000009153756833227248 * R3);
      ELSIF Raw <= 675.5 THEN
        Value :=  13500.31890121417 - (64.89024643188350 * Raw) + (0.10472492893027 * R2) - (0.00005674169841769381 * R3);
      ELSE
        Value :=  -8135.044676629710 + (25.40018648262130 * Raw) - (0.01986043031034 * R2);      
      ENDIF;  
    ELSIF	Type = 14 THEN %FWT1G
      Value := (-264.6311531847244) + (Raw * 0.13733939226662) - (Raw * Raw * 0.000008300189626466234);
    ELSIF	Type = 15 THEN %FOT35
      LNR:= LN(Raw);
      Value := 245.7686957352614 - (Raw * 0.0002180214076186565) + (Raw * Raw * 0.000000001160703041443256) + (0.07334532481221 * LNR * LNR * LNR) - (34.06632737942485 * LNR);
    ELSIF	Type = 16 THEN %TAC ECU
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.00114944558407 + (0.0002941176088004037 * LNR) - (0.0000000000002525998855897292 * LNR* LNR* LNR)));

    ELSIF	Type = 17 THEN %Satchwell DOT
      R2 := Raw*Raw;
      R3 := R2*Raw;
      IF Raw >= 7661 THEN
        Value :=  508885.1065949351 - (19.71706149035526 * Raw) + (0.001301247481832191 * R2) - (0.00000003594831664363352 * R3) - (3738912.809188366 / LN(Raw));
      ELSIF Raw >= 1193 THEN
        Value :=  (-128.4611061637296) - (0.007002012490937275 * Raw) + (0.0000006986512762901833 * R2) - (0.00000000006639391744752032 * R3) + (1529.490359465714 / LN(Raw));
      ELSE
        Value :=  (-339.6118638033802) + (0.09063945312481900 * Raw) - (0.00006415896542404209 * R2) + (0.00000001784096838726073 * R3) + (2639.015168861766 / LN(Raw));
      ENDIF;  
    ELSIF	Type = 18 THEN %Satchwell DW1204 DWS1202
      R2 := Raw*Raw;
      R3 := R2*Raw;
      IF Raw >= 2236 THEN
        Value :=  39382.90132075548 - (6.021252248143583 * Raw) + (0.0013733544102798 * R2) - (0.0000001313622917888568 * R3) - (241223.6906016618 / LN(Raw));
      ELSIF Raw >= 974 THEN
        Value :=  (-888.2657030489725) + (0.1056691176426888 * Raw) - (0.00002987131417113171 * R2) + (0.000000002522599122874649 * R3) + (6271.371860366971 / LN(Raw));
      ELSE
        Value :=  (-9517.677682528738) + (4.164299211339042 * Raw) - (0.002604874308355931 * R2) + (0.0000006794599871065049 * R3) + (50956.91507092444 / LN(Raw));
      ENDIF;  
    ELSIF	Type = 19 THEN %Satchwell DO2202
      R2 := Raw*Raw;
      R3 := R2*Raw;
      Value :=  (-1021.199118881201) + (0.04569968689660045 * Raw) + (0.00002069764420667956 * R2) - (0.00000000981645089002807 * R3) + (6869.504979681983 / LN(Raw));
    ELSIF	Type = 20 THEN %IVT
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001311184263438729 + (0.0002338997792885658 * LNR) + (0.0000001077046283506101 * LNR * LNR * LNR)));
    ELSIF	Type = 21 THEN %NIBE
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001387800349275742 + (0.0002400761437010071 * LNR) + (0.00000008613539226217632 * LNR * LNR * LNR)));
    ELSIF	Type = 22 THEN %KTY 10/7
      R2 := Raw*Raw;
      R3 := R2*Raw;
      Value :=  311.5439406854249 + (0.04844211701143084 * Raw) - (0.000002908837846165819 * R2) + (0.0000000001362467604839759 * R3) - (2848.566087438425 / LN(Raw));
    ELSIF	Type = 23 THEN %Bodendammen
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001466426327478712 + (0.0002385193263772018 * LNR) + (0.0000001006014722395608 * LNR * LNR * LNR)));
    ELSIF	Type = 24 THEN %T7043 Honywell
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001705367599798446 + (0.0002527653342936799 * LNR) + (0.0000000005227580950721076 * LNR * LNR * LNR)));

    ELSE
      Value := Raw;
    ENDIF;  

    IF Input = 1 THEN
      UI2 := Value;
    ELSIF Input = 2 THEN
      UI3 := Value;
    ELSIF Input = 3 THEN
      UI4 := Value;
    ELSIF Input = 4 THEN
      UI5 := Value;
    ELSIF Input = 5 THEN
      UI6 := Value;
    ELSIF Input = 6 THEN
      UI7 := Value;
    ELSIF Input = 7 THEN
      UI8 := Value;
    ELSE	
      UI1 := Value;
    ENDIF;
    Input := Input +1;
  END;
END;  	


%Calls All_UI.CalcValue to calculate Universal input values
ROUTINE UpdateUI
BEGIN
  %One call for each input	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;		
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
END;	
