--- 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():