plcopen/structures.py
changeset 1310 3d7fa2257b24
parent 1298 f034fb2b1aab
child 1313 85c167bfff93
equal deleted inserted replaced
1309:85ce56758900 1310:3d7fa2257b24
    32                      "D" : ["DINT", "UDINT", "REAL", "DWORD"],
    32                      "D" : ["DINT", "UDINT", "REAL", "DWORD"],
    33                      "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} 
    33                      "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} 
    34 
    34 
    35 _ = lambda x:x
    35 _ = lambda x:x
    36 
    36 
    37 # Helper for emulate join on element list
       
    38 def JoinList(separator, mylist):
       
    39     if len(mylist) > 0 :
       
    40         return reduce(lambda x, y: x + separator + y, mylist)
       
    41     else :
       
    42         return mylist
       
    43 
       
    44 def generate_block(generator, block, block_infos, body, link, order=False, to_inout=False):
       
    45     body_type = body.getcontent().getLocalTag()
       
    46     name = block.getinstanceName()
       
    47     type = block.gettypeName()
       
    48     executionOrderId = block.getexecutionOrderId()
       
    49     input_variables = block.inputVariables.getvariable()
       
    50     output_variables = block.outputVariables.getvariable()
       
    51     inout_variables = {}
       
    52     for input_variable in input_variables:
       
    53         for output_variable in output_variables:
       
    54             if input_variable.getformalParameter() == output_variable.getformalParameter():
       
    55                 inout_variables[input_variable.getformalParameter()] = ""
       
    56     input_names = [input[0] for input in block_infos["inputs"]]
       
    57     output_names = [output[0] for output in block_infos["outputs"]]
       
    58     if block_infos["type"] == "function":
       
    59         if not generator.ComputedBlocks.get(block, False) and not order:
       
    60             generator.ComputedBlocks[block] = True
       
    61             connected_vars = []
       
    62             if not block_infos["extensible"]:
       
    63                 input_connected = dict([("EN", None)] + 
       
    64                                        [(input_name, None) for input_name in input_names])
       
    65                 for variable in input_variables:
       
    66                     parameter = variable.getformalParameter()
       
    67                     if input_connected.has_key(parameter):
       
    68                         input_connected[parameter] = variable
       
    69                 if input_connected["EN"] is None:
       
    70                     input_connected.pop("EN")
       
    71                     input_parameters = input_names
       
    72                 else:
       
    73                     input_parameters = ["EN"] + input_names
       
    74             else:
       
    75                 input_connected = dict([(variable.getformalParameter(), variable)
       
    76                                         for variable in input_variables])
       
    77                 input_parameters = [variable.getformalParameter()
       
    78                                     for variable in input_variables]
       
    79             one_input_connected = False
       
    80             all_input_connected = True
       
    81             for i, parameter in enumerate(input_parameters):
       
    82                 variable = input_connected.get(parameter)
       
    83                 if variable is not None:
       
    84                     input_info = (generator.TagName, "block", block.getlocalId(), "input", i)
       
    85                     connections = variable.connectionPointIn.getconnections()
       
    86                     if connections is not None:
       
    87                         if parameter != "EN":
       
    88                             one_input_connected = True
       
    89                         if inout_variables.has_key(parameter):
       
    90                             expression = generator.ComputeExpression(body, connections, executionOrderId > 0, True)
       
    91                             if expression is not None:
       
    92                                 inout_variables[parameter] = value
       
    93                         else:
       
    94                             expression = generator.ComputeExpression(body, connections, executionOrderId > 0)
       
    95                         if expression is not None:
       
    96                             connected_vars.append(([(parameter, input_info), (" := ", ())],
       
    97                                                    generator.ExtractModifier(variable, expression, input_info)))
       
    98                     else:
       
    99                         all_input_connected = False
       
   100                 else:
       
   101                     all_input_connected = False
       
   102             if len(output_variables) > 1 or not all_input_connected:
       
   103                 vars = [name + value for name, value in connected_vars]
       
   104             else:
       
   105                 vars = [value for name, value in connected_vars]
       
   106             if one_input_connected:
       
   107                 for i, variable in enumerate(output_variables):
       
   108                     parameter = variable.getformalParameter()
       
   109                     if not inout_variables.has_key(parameter) and parameter in output_names + ["", "ENO"]:
       
   110                         if variable.getformalParameter() == "":
       
   111                             variable_name = "%s%d"%(type, block.getlocalId())
       
   112                         else:
       
   113                             variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter)
       
   114                         if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]:
       
   115                             generator.Interface.append(("VAR", None, False, []))
       
   116                         if variable.connectionPointOut in generator.ConnectionTypes:
       
   117                             generator.Interface[-1][3].append((generator.ConnectionTypes[variable.connectionPointOut], variable_name, None, None))
       
   118                         else:
       
   119                             generator.Interface[-1][3].append(("ANY", variable_name, None, None))
       
   120                         if len(output_variables) > 1 and parameter not in ["", "OUT"]:
       
   121                             vars.append([(parameter, (generator.TagName, "block", block.getlocalId(), "output", i)), 
       
   122                                          (" => %s"%variable_name, ())])
       
   123                         else:
       
   124                             output_info = (generator.TagName, "block", block.getlocalId(), "output", i)
       
   125                             output_name = variable_name
       
   126                 generator.Program += [(generator.CurrentIndent, ()),
       
   127                                       (output_name, output_info),
       
   128                                       (" := ", ()),
       
   129                                       (type, (generator.TagName, "block", block.getlocalId(), "type")),
       
   130                                       ("(", ())]
       
   131                 generator.Program += JoinList([(", ", ())], vars)
       
   132                 generator.Program += [(");\n", ())]
       
   133             else:
       
   134                 generator.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, generator.TagName.split("::")[-1]))
       
   135     elif block_infos["type"] == "functionBlock":
       
   136         if not generator.ComputedBlocks.get(block, False) and not order:
       
   137             generator.ComputedBlocks[block] = True
       
   138             vars = []
       
   139             offset_idx = 0
       
   140             for variable in input_variables:
       
   141                 parameter = variable.getformalParameter()
       
   142                 if parameter in input_names or parameter == "EN":
       
   143                     if parameter == "EN":
       
   144                         input_idx = 0
       
   145                         offset_idx = 1
       
   146                     else:
       
   147                         input_idx = offset_idx + input_names.index(parameter)
       
   148                     input_info = (generator.TagName, "block", block.getlocalId(), "input", input_idx)
       
   149                     connections = variable.connectionPointIn.getconnections()
       
   150                     if connections is not None:
       
   151                         expression = generator.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter))
       
   152                         if expression is not None:
       
   153                             vars.append([(parameter, input_info),
       
   154                                          (" := ", ())] + generator.ExtractModifier(variable, expression, input_info))
       
   155             generator.Program += [(generator.CurrentIndent, ()), 
       
   156                                   (name, (generator.TagName, "block", block.getlocalId(), "name")),
       
   157                                   ("(", ())]
       
   158             generator.Program += JoinList([(", ", ())], vars)
       
   159             generator.Program += [(");\n", ())]
       
   160     
       
   161     if link is not None:
       
   162         connectionPoint = link.getposition()[-1]
       
   163         output_parameter = link.getformalParameter()
       
   164     else:
       
   165         connectionPoint = None
       
   166         output_parameter = None
       
   167     
       
   168     output_variable = None
       
   169     output_idx = 0
       
   170     if output_parameter is not None:
       
   171         if output_parameter in output_names or output_parameter == "ENO":
       
   172             for variable in output_variables:
       
   173                 if variable.getformalParameter() == output_parameter:
       
   174                     output_variable = variable
       
   175                     if output_parameter != "ENO":
       
   176                         output_idx = output_names.index(output_parameter)
       
   177     else:
       
   178         for i, variable in enumerate(output_variables):
       
   179             blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
       
   180             if (connectionPoint is None or 
       
   181                 block.getx() + blockPointx == connectionPoint.getx() and 
       
   182                 block.gety() + blockPointy == connectionPoint.gety()):
       
   183                 output_variable = variable
       
   184                 output_parameter = variable.getformalParameter()
       
   185                 output_idx = i
       
   186     
       
   187     if output_variable is not None:
       
   188         if block_infos["type"] == "function":
       
   189             output_info = (generator.TagName, "block", block.getlocalId(), "output", output_idx)
       
   190             if inout_variables.has_key(output_parameter):
       
   191                 output_value = inout_variables[output_parameter]
       
   192             else:
       
   193                 if output_parameter == "":
       
   194                     output_name = "%s%d"%(type, block.getlocalId())
       
   195                 else:
       
   196                     output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter)
       
   197                 output_value = [(output_name, output_info)]
       
   198             return generator.ExtractModifier(output_variable, output_value, output_info)
       
   199         
       
   200         if block_infos["type"] == "functionBlock":
       
   201             output_info = (generator.TagName, "block", block.getlocalId(), "output", output_idx)
       
   202             output_name = generator.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info)
       
   203             if to_inout:
       
   204                 variable_name = "%s_%s"%(name, output_parameter)
       
   205                 if not generator.IsAlreadyDefined(variable_name):
       
   206                     if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]:
       
   207                         generator.Interface.append(("VAR", None, False, []))
       
   208                     if variable.connectionPointOut in generator.ConnectionTypes:
       
   209                         generator.Interface[-1][3].append(
       
   210                             (generator.ConnectionTypes[output_variable.connectionPointOut], variable_name, None, None))
       
   211                     else:
       
   212                         generator.Interface[-1][3].append(("ANY", variable_name, None, None))
       
   213                     generator.Program += [(generator.CurrentIndent, ()),
       
   214                                           ("%s := "%variable_name, ())]
       
   215                     generator.Program += output_name
       
   216                     generator.Program += [(";\n", ())]
       
   217                 return [(variable_name, ())]
       
   218             return output_name 
       
   219     if link is not None:
       
   220         if output_parameter is None:
       
   221             output_parameter = ""
       
   222         if name:
       
   223             blockname = "%s(%s)" % (name, type)
       
   224         else:
       
   225             blockname = type
       
   226         raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken")  % \
       
   227                           (output_parameter, blockname, generator.Name)
       
   228 
       
   229 def initialise_block(type, name, block = None):
       
   230     return [(type, name, None, None)]
       
   231 
       
   232 #-------------------------------------------------------------------------------
    37 #-------------------------------------------------------------------------------
   233 #                        Function Block Types definitions
    38 #                        Function Block Types definitions
   234 #-------------------------------------------------------------------------------
    39 #-------------------------------------------------------------------------------
   235 
    40 
   236 
    41 
   252 
    57 
   253 StdBlckLst = [{"name" : _("Standard function blocks"), "list":
    58 StdBlckLst = [{"name" : _("Standard function blocks"), "list":
   254                [{"name" : "SR", "type" : "functionBlock", "extensible" : False, 
    59                [{"name" : "SR", "type" : "functionBlock", "extensible" : False, 
   255                     "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], 
    60                     "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], 
   256                     "outputs" : [("Q1","BOOL","none")],
    61                     "outputs" : [("Q1","BOOL","none")],
   257                     "comment" : _("SR bistable\nThe SR bistable is a latch where the Set dominates."),
    62                     "comment" : _("SR bistable\nThe SR bistable is a latch where the Set dominates.")},
   258                     "generate" : generate_block, "initialise" : initialise_block},
       
   259                 {"name" : "RS", "type" : "functionBlock", "extensible" : False, 
    63                 {"name" : "RS", "type" : "functionBlock", "extensible" : False, 
   260                     "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], 
    64                     "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], 
   261                     "outputs" : [("Q1","BOOL","none")],
    65                     "outputs" : [("Q1","BOOL","none")],
   262                     "comment" : _("RS bistable\nThe RS bistable is a latch where the Reset dominates."),
    66                     "comment" : _("RS bistable\nThe RS bistable is a latch where the Reset dominates.")},
   263                     "generate" : generate_block, "initialise" : initialise_block},
       
   264                 {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, 
    67                 {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, 
   265                     "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], 
    68                     "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], 
   266                     "outputs" : [("BUSY","BOOL","none")],
    69                     "outputs" : [("BUSY","BOOL","none")],
   267                     "comment" : _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."),
    70                     "comment" : _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources.")},
   268                     "generate" : generate_block, "initialise" : initialise_block},
       
   269                 {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, 
    71                 {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, 
   270                     "inputs" : [("CLK","BOOL","none")], 
    72                     "inputs" : [("CLK","BOOL","none")], 
   271                     "outputs" : [("Q","BOOL","none")],
    73                     "outputs" : [("Q","BOOL","none")],
   272                     "comment" : _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected."),
    74                     "comment" : _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected.")},
   273                     "generate" : generate_block, "initialise" : initialise_block},
       
   274                 {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, 
    75                 {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, 
   275                     "inputs" : [("CLK","BOOL","none")], 
    76                     "inputs" : [("CLK","BOOL","none")], 
   276                     "outputs" : [("Q","BOOL","none")],
    77                     "outputs" : [("Q","BOOL","none")],
   277                     "comment" : _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected."),
    78                     "comment" : _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected.")},
   278                     "generate" : generate_block, "initialise" : initialise_block},
       
   279                 {"name" : "CTU", "type" : "functionBlock", "extensible" : False, 
    79                 {"name" : "CTU", "type" : "functionBlock", "extensible" : False, 
   280                     "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], 
    80                     "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], 
   281                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
    81                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
   282                     "comment" : _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."),
    82                     "comment" : _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value.")},
   283                     "generate" : generate_block, "initialise" : initialise_block},
       
   284                 {"name" : "CTD", "type" : "functionBlock", "extensible" : False, 
    83                 {"name" : "CTD", "type" : "functionBlock", "extensible" : False, 
   285                     "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], 
    84                     "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], 
   286                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
    85                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
   287                     "comment" : _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."),
    86                     "comment" : _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value.")},
   288                     "generate" : generate_block, "initialise" : initialise_block},
       
   289                 {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, 
    87                 {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, 
   290                     "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], 
    88                     "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], 
   291                     "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")],
    89                     "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")],
   292                     "comment" : _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other."),
    90                     "comment" : _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other.")},
   293                     "generate" : generate_block, "initialise" : initialise_block},
       
   294                 {"name" : "TP", "type" : "functionBlock", "extensible" : False, 
    91                 {"name" : "TP", "type" : "functionBlock", "extensible" : False, 
   295                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
    92                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
   296                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
    93                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
   297                     "comment" : _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."),
    94                     "comment" : _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration.")},
   298                     "generate" : generate_block, "initialise" : initialise_block},
       
   299                 {"name" : "TON", "type" : "functionBlock", "extensible" : False, 
    95                 {"name" : "TON", "type" : "functionBlock", "extensible" : False, 
   300                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
    96                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
   301                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
    97                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
   302                     "comment" : _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true."),
    98                     "comment" : _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true.")},
   303                     "generate" : generate_block, "initialise" : initialise_block},
       
   304                 {"name" : "TOF", "type" : "functionBlock", "extensible" : False, 
    99                 {"name" : "TOF", "type" : "functionBlock", "extensible" : False, 
   305                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
   100                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
   306                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
   101                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
   307                     "comment" : _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."),
   102                     "comment" : _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false.")},
   308                     "generate" : generate_block, "initialise" : initialise_block},
       
   309                 ]},
   103                 ]},
   310               {"name" : _("Additional function blocks"), "list":
   104               {"name" : _("Additional function blocks"), "list":
   311                [{"name" : "RTC", "type" : "functionBlock", "extensible" : False, 
   105                [{"name" : "RTC", "type" : "functionBlock", "extensible" : False, 
   312                     "inputs" : [("IN","BOOL","none"),("PDT","DATE_AND_TIME","none")], 
   106                     "inputs" : [("IN","BOOL","none"),("PDT","DATE_AND_TIME","none")], 
   313                     "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")],
   107                     "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")],
   314                     "comment" : _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on."),
   108                     "comment" : _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on.")},
   315                     "generate" : generate_block, "initialise" : initialise_block},
       
   316                 {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, 
   109                 {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, 
   317                     "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], 
   110                     "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], 
   318                     "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")],
   111                     "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")],
   319                     "comment" : _("Integral\nThe integral function block integrates the value of input XIN over time."),
   112                     "comment" : _("Integral\nThe integral function block integrates the value of input XIN over time.")},
   320                     "generate" : generate_block, "initialise" : initialise_block},
       
   321                 {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, 
   113                 {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, 
   322                     "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], 
   114                     "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], 
   323                     "outputs" : [("XOUT","REAL","none")],
   115                     "outputs" : [("XOUT","REAL","none")],
   324                     "comment" : _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."),
   116                     "comment" : _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN.")},
   325                     "generate" : generate_block, "initialise" : initialise_block},
       
   326                 {"name" : "PID", "type" : "functionBlock", "extensible" : False, 
   117                 {"name" : "PID", "type" : "functionBlock", "extensible" : False, 
   327                     "inputs" : [("AUTO","BOOL","none"),("PV","REAL","none"),("SP","REAL","none"),("X0","REAL","none"),("KP","REAL","none"),("TR","REAL","none"),("TD","REAL","none"),("CYCLE","TIME","none")], 
   118                     "inputs" : [("AUTO","BOOL","none"),("PV","REAL","none"),("SP","REAL","none"),("X0","REAL","none"),("KP","REAL","none"),("TR","REAL","none"),("TD","REAL","none"),("CYCLE","TIME","none")], 
   328                     "outputs" : [("XOUT","REAL","none")],
   119                     "outputs" : [("XOUT","REAL","none")],
   329                     "comment" : _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."),
   120                     "comment" : _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control.")},
   330                     "generate" : generate_block, "initialise" : initialise_block},
       
   331                 {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, 
   121                 {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, 
   332                     "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none")], 
   122                     "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none")], 
   333                     "outputs" : [("BUSY","BOOL","none"),("XOUT","REAL","none")],
   123                     "outputs" : [("BUSY","BOOL","none"),("XOUT","REAL","none")],
   334                     "comment" : _("Ramp\nThe RAMP function block is modelled on example given in the standard."),
   124                     "comment" : _("Ramp\nThe RAMP function block is modelled on example given in the standard.")},
   335                     "generate" : generate_block, "initialise" : initialise_block},
       
   336                 {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, 
   125                 {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, 
   337                     "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], 
   126                     "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], 
   338                     "outputs" : [("Q","BOOL","none")],
   127                     "outputs" : [("Q","BOOL","none")],
   339                     "comment" : _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."),
   128                     "comment" : _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2.")},
   340                     "generate" : generate_block, "initialise" : initialise_block},
       
   341 ##                {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, 
   129 ##                {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, 
   342 ##                    "inputs" : [("PV1","REAL","none"),("PV2","REAL","none"),("RATIO","REAL","none"),("TIMON","TIME","none"),("TIMOFF","TIME","none"),("TOLERANCE","BOOL","none"),("RESET","BOOL","none"),("CYCLE","TIME","none")], 
   130 ##                    "inputs" : [("PV1","REAL","none"),("PV2","REAL","none"),("RATIO","REAL","none"),("TIMON","TIME","none"),("TIMOFF","TIME","none"),("TOLERANCE","BOOL","none"),("RESET","BOOL","none"),("CYCLE","TIME","none")], 
   343 ##                    "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")],
   131 ##                    "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")],
   344 ##                    "comment" : _("Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2."),
   132 ##                    "comment" : _("Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2.")}
   345 ##                    "generate" : generate_block, "initialise" : initialise_block}
       
   346                 ]},
   133                 ]},
   347              ]
   134              ]
   348 
   135 
   349 
   136 
   350 #-------------------------------------------------------------------------------
   137 #-------------------------------------------------------------------------------
   599                 Current_section = {"name" : section_name, "list" : []}
   386                 Current_section = {"name" : section_name, "list" : []}
   600                 Standard_Functions_Decl.append(Current_section)
   387                 Standard_Functions_Decl.append(Current_section)
   601                 Function_decl_list = []
   388                 Function_decl_list = []
   602             if Current_section:
   389             if Current_section:
   603                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
   390                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
   604                 Function_decl["generate"] = generate_block
       
   605                 Function_decl["initialise"] = lambda x,y:[]
       
   606                 baseinputnumber = int(Function_decl.get("baseinputnumber",1))
   391                 baseinputnumber = int(Function_decl.get("baseinputnumber",1))
   607                 Function_decl["baseinputnumber"] = baseinputnumber
   392                 Function_decl["baseinputnumber"] = baseinputnumber
   608                 for param, value in Function_decl.iteritems():
   393                 for param, value in Function_decl.iteritems():
   609                     if param in translate:
   394                     if param in translate:
   610                         Function_decl[param] = translate[param](value)
   395                         Function_decl[param] = translate[param](value)