diff -r 346a43f179a5 -r 049f2e7090a2 plcopen/structures.py --- a/plcopen/structures.py Thu Aug 23 09:26:02 2007 +0200 +++ b/plcopen/structures.py Thu Aug 23 09:39:18 2007 +0200 @@ -27,6 +27,40 @@ LANGUAGES = ["IL","ST","FBD","LD","SFC"] +def generate_block(generator, block, body, link): + name = block.getInstanceName() + type = block.getTypeName() + block_infos = GetBlockType(type) + if block_infos["type"] == "function" and link: + generator.GeneratePouProgram(type) + vars = [] + for variable in block.inputVariables.getVariable(): + connections = variable.connectionPointIn.getConnections() + if connections and len(connections) == 1: + value = generator.ComputeFBDExpression(body, connections[0]) + vars.append(generator.ExtractModifier(variable, value)) + variable = block.outputVariables.getVariable()[0] + return generator.ExtractModifier(variable, "%s(%s)"%(type, ", ".join(vars))) + elif block_infos["type"] == "functionBlock": + if not generator.ComputedBlocks.get(name, False): + vars = [] + for variable in block.inputVariables.getVariable(): + connections = variable.connectionPointIn.getConnections() + if connections and len(connections) == 1: + parameter = variable.getFormalParameter() + value = generator.ComputeFBDExpression(body, connections[0]) + vars.append("%s := %s"%(parameter, generator.ExtractModifier(variable, value))) + generator.Program += " %s(%s);\n"%(name, ", ".join(vars)) + generator.ComputedBlocks[name] = True + if link: + connectionPoint = link.getPosition()[-1] + else: + connectionPoint = None + for variable in block.outputVariables.getVariable(): + blockPointx, blockPointy = variable.connectionPointOut.getRelPosition() + if not connectionPoint or block.getX() + blockPointx == connectionPoint.getX() and block.getY() + blockPointy == connectionPoint.getY(): + return generator.ExtractModifier(variable, "%s.%s"%(name, variable.getFormalParameter())) + raise ValueError, "No output variable found" #------------------------------------------------------------------------------- # Function Block Types definitions @@ -42,6 +76,7 @@ - "inputs" : List of the block inputs - "outputs" : List of the block outputs - "comment" : Comment that will be displayed in the block popup + - "generate" : Method that generator will call for generating ST block code Inputs and outputs are a tuple of characteristics that are in order: - The name - The data type @@ -52,110 +87,104 @@ [{"name" : "SR", "type" : "functionBlock", "extensible" : False, "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], "outputs" : [("Q1","BOOL","none")], - "comment" : "SR bistable\nThe SR bistable is a latch where the Set dominates."}, + "comment" : "SR bistable\nThe SR bistable is a latch where the Set dominates.", + "generate" : generate_block}, {"name" : "RS", "type" : "functionBlock", "extensible" : False, "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], "outputs" : [("Q1","BOOL","none")], - "comment" : "RS bistable\nThe RS bistable is a latch where the Reset dominates."}, + "comment" : "RS bistable\nThe RS bistable is a latch where the Reset dominates.", + "generate" : generate_block}, {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], "outputs" : [("BUSY","BOOL","none")], - "comment" : "Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."}, + "comment" : "Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources.", + "generate" : generate_block}, {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, "inputs" : [("CLK","BOOL","none")], "outputs" : [("Q","BOOL","none")], - "comment" : "Rising edge detector\nThe output produces a single pulse when a rising edge is detected."}, + "comment" : "Rising edge detector\nThe output produces a single pulse when a rising edge is detected.", + "generate" : generate_block}, {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, "inputs" : [("CLK","BOOL","none")], "outputs" : [("Q","BOOL","none")], - "comment" : "Falling edge detector\nThe output produces a single pulse when a falling edge is detected."}, + "comment" : "Falling edge detector\nThe output produces a single pulse when a falling edge is detected.", + "generate" : generate_block}, {"name" : "CTU", "type" : "functionBlock", "extensible" : False, "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], "outputs" : [("Q","BOOL","none"),("CV","INT","none")], - "comment" : "Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."}, + "comment" : "Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value.", + "generate" : generate_block}, {"name" : "CTD", "type" : "functionBlock", "extensible" : False, "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], "outputs" : [("Q","BOOL","none"),("CV","INT","none")], - "comment" : "Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."}, + "comment" : "Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value.", + "generate" : generate_block}, {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")], - "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 ans down on the other."}, + "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 ans down on the other.", + "generate" : generate_block}, {"name" : "TP", "type" : "functionBlock", "extensible" : False, "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], - "comment" : "Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."}, + "comment" : "Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration.", + "generate" : generate_block}, {"name" : "TOF", "type" : "functionBlock", "extensible" : False, "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], - "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."}, + "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.", + "generate" : generate_block}, {"name" : "TON", "type" : "functionBlock", "extensible" : False, "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], - "comment" : "Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."}, + "comment" : "Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false.", + "generate" : generate_block}, {"name" : "RTC", "type" : "functionBlock", "extensible" : False, "inputs" : [("EN","BOOL","none"),("PDT","DATE_AND_TIME","none")], "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")], - "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."}, + "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.", + "generate" : generate_block}, {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")], - "comment" : "Integral\nThe integral function block integrates the value of input XIN over time."}, + "comment" : "Integral\nThe integral function block integrates the value of input XIN over time.", + "generate" : generate_block}, {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], "outputs" : [("XOUT","REAL","none")], - "comment" : "Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."}, + "comment" : "Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN.", + "generate" : generate_block}, {"name" : "PID", "type" : "functionBlock", "extensible" : False, "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")], "outputs" : [("XOUT","REAL","none")], - "comment" : "PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."}, + "comment" : "PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control.", + "generate" : generate_block}, {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none"),("HOLDBACK","BOOL","none"),("ERROR","REAL","none"),("PV","REAL","none")], "outputs" : [("RAMP","BOOL","none"),("XOUT","REAL","none")], - "comment" : "Ramp\nThe RAMP function block is modelled on example given in the standard but with the addition of a 'Holdback' feature."}, + "comment" : "Ramp\nThe RAMP function block is modelled on example given in the standard but with the addition of a 'Holdback' feature.", + "generate" : generate_block}, {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], "outputs" : [("Q","BOOL","none")], - "comment" : "Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."}, + "comment" : "Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2.", + "generate" : generate_block}, {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, "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")], "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")], - "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."} + "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.", + "generate" : generate_block} ]}, - {"name" : "SVGUI function blocks", "list": - [{"name" : "Container", "type" : "functionBlock", "extensible" : False, - "inputs" : [("X","FLOAT","none"),("SetX","BOOL","none"),("Y","FLOAT","none"),("SetY","BOOL","none"),("Angle","FLOAT","none"),("SetAngle","BOOL","none")], - "outputs" : [("X","FLOAT","none"),("X Changed","BOOL","none"),("Y","FLOAT","none"),("Y Changed","BOOL","none"),("Angle","FLOAT","none"),("Angle Changed","BOOL","none")], - "comment" : "SVGUI Container"}, - {"name" : "Button", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Toggle","BOOL","none")], - "outputs" : [("Visible","BOOL","none"),("State","BOOL","none")], - "comment" : "SVGUI Button"}, - {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Text","STRING","none"),("Set Text","BOOL","none")], - "outputs" : [("Text","STRING","none"),("Text Changed","BOOL","none")], - "comment" : "SVGUI Text Control"}, - {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Position","UINT","none"),("Set Position","BOOL","none")], - "outputs" : [("Position","UINT","none"),("Position Changed","BOOL","none")], - "comment" : "SVGUI ScrollBar"}, - {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Selected","UINT","none"),("Set Selected","BOOL","none")], - "outputs" : [("Selected","UINT","none"),("Selected Changed","BOOL","none")], - "comment" : "SVGUI Notebook"}, - {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Angle","FLOAT","none"),("Set Angle","BOOL","none")], - "outputs" : [("Angle","FLOAT","none"),("Angle changed","BOOL","none")], - "comment" : "SVGUI Rotating Control"}, - ]} ] + +PluginTypes = [] """ Function that returns the block definition associated to the block type given """ def GetBlockType(type, inputs = None): - for category in BlockTypes: + for category in BlockTypes + PluginTypes: for blocktype in category["list"]: if inputs: block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) @@ -166,6 +195,12 @@ return blocktype return None +""" +Function that add a new plugin to the plugin list +""" + +def AddPlugin(blocklist): + PluginTypes.append(blocklist) #------------------------------------------------------------------------------- # Data Types definitions @@ -455,6 +490,7 @@ Function_decl_list = [] if Current_section: Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ]) + Function_decl["generate"] = generate_block baseinputnumber = int(Function_decl.get("baseinputnumber",1)) Function_decl["baseinputnumber"] = baseinputnumber for param, value in Function_decl.iteritems():