5 import wx |
5 import wx |
6 |
6 |
7 from xmlclass import * |
7 from xmlclass import * |
8 from plugger import PlugTemplate |
8 from plugger import PlugTemplate |
9 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
9 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
10 from ConfigEditor import ConfigEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE |
10 from ConfigEditor import ConfigEditor, DS402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE |
11 |
11 |
12 #-------------------------------------------------- |
12 #-------------------------------------------------- |
13 # Ethercat DS402 Node |
13 # Ethercat DS402 Node |
14 #-------------------------------------------------- |
14 #-------------------------------------------------- |
15 |
15 |
16 NODE_VARIABLES = [ |
16 NODE_VARIABLES = [ |
17 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
17 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
|
18 ("TargetPosition", 0x607a, 0x00, "DINT", "Q"), |
18 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
19 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
19 ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"), |
20 ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"), |
|
21 ("ActualPosition", 0x6064, 0x00, "DINT", "I"), |
20 ("ErrorCode", 0x603f, 0x00, "UINT", "I"), |
22 ("ErrorCode", 0x603f, 0x00, "UINT", "I"), |
21 ] |
23 ] |
22 |
24 |
23 class _EthercatDS402SlavePlug: |
25 class _EthercatDS402SlavePlug: |
24 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
26 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
67 "product_code": GenerateHexDecValue(product_code, 16), |
76 "product_code": GenerateHexDecValue(product_code, 16), |
68 "revision_number": GenerateHexDecValue(revision_number, 16)} |
77 "revision_number": GenerateHexDecValue(revision_number, 16)} |
69 |
78 |
70 return None |
79 return None |
71 |
80 |
|
81 def GetSlaveInfos(self): |
|
82 slave_typeinfos = self.GetSlaveTypeInfos() |
|
83 if slave_typeinfos is not None: |
|
84 device = self.PlugParent.GetModuleInfos(slave_typeinfos) |
|
85 if device is not None: |
|
86 infos = slave_typeinfos.copy() |
|
87 entries = device.GetEntriesList() |
|
88 entries_list = entries.items() |
|
89 entries_list.sort() |
|
90 infos.update({"physics": device.getPhysics(), |
|
91 "sync_managers": device.GetSyncManagers(), |
|
92 "entries": [entry[1] for entry in entries_list]}) |
|
93 return infos |
|
94 return None |
|
95 |
72 def GetVariableLocationTree(self): |
96 def GetVariableLocationTree(self): |
73 slave_infos = self.GetSlaveInfos() |
97 slave_typeinfos = self.GetSlaveTypeInfos() |
74 vars = [] |
98 vars = [] |
75 if slave_infos is not None: |
99 if slave_typeinfos is not None: |
76 vars = self.PlugParent.GetDeviceLocationTree(self.GetCurrentLocation(), slave_infos) |
100 vars = self.PlugParent.GetDeviceLocationTree(self.GetCurrentLocation(), slave_typeinfos) |
77 |
101 |
78 return {"name": self.BaseParams.getName(), |
102 return {"name": self.BaseParams.getName(), |
79 "type": LOCATION_PLUGIN, |
103 "type": LOCATION_PLUGIN, |
80 "location": self.GetFullIEC_Channel(), |
104 "location": self.GetFullIEC_Channel(), |
81 "children": vars} |
105 "children": vars} |
|
106 |
|
107 PluginMethods = [ |
|
108 {"bitmap" : os.path.join("images", "EditCfile"), |
|
109 "name" : _("Edit Node"), |
|
110 "tooltip" : _("Edit Node"), |
|
111 "method" : "_OpenView"}, |
|
112 ] |
|
113 |
82 |
114 |
83 def PlugGenerate_C(self, buildpath, locations): |
115 def PlugGenerate_C(self, buildpath, locations): |
84 """ |
116 """ |
85 Generate C code |
117 Generate C code |
86 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
118 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
97 |
129 |
98 location_str = "_".join(map(lambda x:str(x), current_location)) |
130 location_str = "_".join(map(lambda x:str(x), current_location)) |
99 |
131 |
100 slave_pos = current_location[-2:] |
132 slave_pos = current_location[-2:] |
101 |
133 |
102 slave_infos = self.GetSlaveInfos() |
134 slave_typeinfos = self.GetSlaveTypeInfos() |
103 device = None |
135 device = None |
104 if slave_infos is not None: |
136 if slave_typeinfos is not None: |
105 device = self.PlugParent.GetModuleInfos(slave_infos) |
137 device = self.PlugParent.GetModuleInfos(slave_typeinfos) |
106 |
138 |
107 if device is None: |
139 if device is None: |
108 raise (ValueError, |
140 raise (ValueError, |
109 _("No information found for DS402 node \"%s\" at location %s!") % ( |
141 _("No information found for DS402 node \"%s\" at location %s!") % ( |
110 slave_infos["device_type"], ".".join(current_location))) |
142 slave_typeinfos["device_type"], ".".join(current_location))) |
111 |
143 |
112 slave_idx = self.PlugParent.FileGenerator.DeclareSlave(slave_pos, slave_infos) |
144 self.PlugParent.FileGenerator.DeclareSlave(slave_pos, slave_typeinfos) |
113 |
145 |
114 plc_ds402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_ds402node.c") |
146 plc_ds402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_ds402node.c") |
115 plc_ds402node_file = open(plc_ds402node_filepath, 'r') |
147 plc_ds402node_file = open(plc_ds402node_filepath, 'r') |
116 plc_ds402node_code = plc_ds402node_file.read() |
148 plc_ds402node_code = plc_ds402node_file.read() |
117 plc_ds402node_file.close() |
149 plc_ds402node_file.close() |
118 |
150 |
|
151 from plugins.motion import Headers |
|
152 |
119 str_completion = { |
153 str_completion = { |
120 "location": location_str, |
154 "location": location_str, |
121 "MCL_includes": "", |
155 "MCL_headers": Headers, |
122 "located_variables_declaration": [], |
156 "extern_located_variables_declaration": [], |
123 "entry_variables": [], |
157 "entry_variables": [], |
124 "extern_pdo_entry_configuration": [], |
158 "init_entry_variables": [], |
125 "retrieve_variables": [], |
|
126 "publish_variables": [], |
|
127 } |
159 } |
128 |
160 |
129 variables = {} |
|
130 for variable in NODE_VARIABLES: |
161 for variable in NODE_VARIABLES: |
131 var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable)) |
162 var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable)) |
132 var_infos["location"] = location_str |
163 var_infos["location"] = location_str |
133 var_infos["slave"] = slave_idx |
|
134 var_infos["var_size"] = self.PlugParent.GetSizeOfType(var_infos["var_type"]) |
164 var_infos["var_size"] = self.PlugParent.GetSizeOfType(var_infos["var_type"]) |
135 var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos |
165 var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos |
136 var_infos["real_var"] = "__DS402Node_%(location)s.%(name)s" % var_infos |
|
137 var_infos.update(slave_infos) |
|
138 |
166 |
139 variables[(var_infos["index"], var_infos["subindex"])] = var_infos["name"] |
167 str_completion["extern_located_variables_declaration"].append( |
140 |
168 "IEC_%(var_type)s *%(var_name)s;" % var_infos) |
141 str_completion["entry_variables"].append(" IEC_%(var_type)s %(name)s;" % var_infos) |
169 str_completion["entry_variables"].append( |
142 |
170 " IEC_%(var_type)s *%(name)s;" % var_infos) |
143 ConfigureVariable(var_infos, str_completion) |
171 str_completion["init_entry_variables"].append( |
144 |
172 " __DS402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos) |
145 str_completion["extern_pdo_entry_configuration"].append( |
|
146 "extern unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % var_infos) |
|
147 |
|
148 if var_infos["var_type"] == "BOOL": |
|
149 str_completion["extern_pdo_entry_configuration"].append( |
|
150 "extern unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % var_infos) |
|
151 |
173 |
152 self.PlugParent.FileGenerator.DeclareVariable( |
174 self.PlugParent.FileGenerator.DeclareVariable( |
153 slave_pos, var_infos["index"], var_infos["subindex"], |
175 slave_pos, var_infos["index"], var_infos["subindex"], |
154 var_infos["var_type"], var_infos["dir"], var_infos["var_name"], False) |
176 var_infos["var_type"], var_infos["dir"], var_infos["var_name"]) |
155 |
177 |
156 for element in ["located_variables_declaration", |
178 for element in ["extern_located_variables_declaration", |
157 "entry_variables", |
179 "entry_variables", |
158 "extern_pdo_entry_configuration", |
180 "init_entry_variables"]: |
159 "retrieve_variables", |
|
160 "publish_variables"]: |
|
161 str_completion[element] = "\n".join(str_completion[element]) |
181 str_completion[element] = "\n".join(str_completion[element]) |
162 |
182 |
163 Gen_DS402Nodefile_path = os.path.join(buildpath, "ds402node_%s.c"%location_str) |
183 Gen_DS402Nodefile_path = os.path.join(buildpath, "ds402node_%s.c"%location_str) |
164 ds402nodefile = open(Gen_DS402Nodefile_path, 'w') |
184 ds402nodefile = open(Gen_DS402Nodefile_path, 'w') |
165 ds402nodefile.write(plc_ds402node_code % str_completion) |
185 ds402nodefile.write(plc_ds402node_code % str_completion) |
166 ds402nodefile.close() |
186 ds402nodefile.close() |
167 |
|
168 for location in locations: |
|
169 loc = location["LOC"][len(current_location):] |
|
170 if variables.get(loc, None) is None: |
|
171 self.PlugParent.FileGenerator.DeclareVariable( |
|
172 slave_pos, loc[0], loc[1], location["IEC_TYPE"], location["DIR"], location["NAME"]) |
|
173 |
187 |
174 return [(Gen_DS402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True |
188 return [(Gen_DS402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True |
175 |
189 |
176 |
190 |
177 |
191 |
596 def ConfigureVariable(entry_infos, str_completion): |
610 def ConfigureVariable(entry_infos, str_completion): |
597 entry_infos["data_type"] = DATATYPECONVERSION.get(entry_infos["var_type"], None) |
611 entry_infos["data_type"] = DATATYPECONVERSION.get(entry_infos["var_type"], None) |
598 if entry_infos["data_type"] is None: |
612 if entry_infos["data_type"] is None: |
599 raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"] |
613 raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"] |
600 |
614 |
601 if not entry_infos.has_key("real_var"): |
615 entry_infos["real_var"] = "beremiz" + entry_infos["var_name"] |
602 entry_infos["real_var"] = "beremiz" + entry_infos["var_name"] |
616 str_completion["located_variables_declaration"].extend( |
603 str_completion["located_variables_declaration"].append( |
617 ["IEC_%(var_type)s %(real_var)s;" % entry_infos, |
604 "IEC_%(var_type)s %(real_var)s;" % entry_infos) |
618 "IEC_%(var_type)s *%(var_name)s = &%(real_var)s;" % entry_infos]) |
605 str_completion["located_variables_declaration"].append( |
619 |
606 "IEC_%(var_type)s *%(var_name)s = &%(real_var)s;" % entry_infos) |
620 str_completion["used_pdo_entry_offset_variables_declaration"].append( |
|
621 "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos) |
607 |
622 |
608 if entry_infos["data_type"] == "BIT": |
623 if entry_infos["data_type"] == "BIT": |
|
624 str_completion["used_pdo_entry_offset_variables_declaration"].append( |
|
625 "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos) |
|
626 |
|
627 str_completion["used_pdo_entry_configuration"].append( |
|
628 (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + |
|
629 "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + |
|
630 "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos) |
|
631 |
609 if entry_infos["dir"] == "I": |
632 if entry_infos["dir"] == "I": |
610 str_completion["retrieve_variables"].append( |
633 str_completion["retrieve_variables"].append( |
611 (" %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
634 (" %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
612 "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos) |
635 "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos) |
613 elif entry_infos["dir"] == "Q": |
636 elif entry_infos["dir"] == "Q": |
614 str_completion["publish_variables"].append( |
637 str_completion["publish_variables"].append( |
615 (" EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
638 (" EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
616 "slave%(slave)d_%(index).4x_%(subindex).2x_bit, %(real_var)s);") % entry_infos) |
639 "slave%(slave)d_%(index).4x_%(subindex).2x_bit, %(real_var)s);") % entry_infos) |
617 |
640 |
618 else: |
641 else: |
|
642 str_completion["used_pdo_entry_configuration"].append( |
|
643 (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + |
|
644 "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos) |
|
645 |
619 if entry_infos["dir"] == "I": |
646 if entry_infos["dir"] == "I": |
620 str_completion["retrieve_variables"].append( |
647 str_completion["retrieve_variables"].append( |
621 (" %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + |
648 (" %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + |
622 "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos) |
649 "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos) |
623 elif entry_infos["dir"] == "Q": |
650 elif entry_infos["dir"] == "Q": |
624 str_completion["publish_variables"].append( |
651 str_completion["publish_variables"].append( |
625 (" EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
652 (" EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + |
626 "%(real_var)s);") % entry_infos) |
653 "%(real_var)s);") % entry_infos) |
627 |
654 |
628 def ConfigurePDO(entry_infos, str_completion): |
|
629 str_completion["used_pdo_entry_offset_variables_declaration"].append( |
|
630 "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos) |
|
631 |
|
632 if entry_infos["var_type"] == "BOOL": |
|
633 str_completion["used_pdo_entry_offset_variables_declaration"].append( |
|
634 "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos) |
|
635 |
|
636 str_completion["used_pdo_entry_configuration"].append( |
|
637 (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + |
|
638 "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + |
|
639 "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos) |
|
640 |
|
641 else: |
|
642 |
|
643 str_completion["used_pdo_entry_configuration"].append( |
|
644 (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + |
|
645 "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos) |
|
646 |
|
647 class _EthercatCFileGenerator: |
655 class _EthercatCFileGenerator: |
648 |
656 |
649 def __init__(self, controler): |
657 def __init__(self, controler): |
650 self.Controler = controler |
658 self.Controler = controler |
651 |
659 |
658 def DeclareSlave(self, slave_identifier, slave): |
666 def DeclareSlave(self, slave_identifier, slave): |
659 self.Slaves.append((slave_identifier, slave)) |
667 self.Slaves.append((slave_identifier, slave)) |
660 self.Slaves.sort() |
668 self.Slaves.sort() |
661 return self.Slaves.index((slave_identifier, slave)) |
669 return self.Slaves.index((slave_identifier, slave)) |
662 |
670 |
663 def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name, configure=True): |
671 def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name): |
664 slave_variables = self.UsedVariables.setdefault(slave_identifier, {}) |
672 slave_variables = self.UsedVariables.setdefault(slave_identifier, {}) |
665 |
673 |
666 entry_infos = slave_variables.get((index, subindex), None) |
674 entry_infos = slave_variables.get((index, subindex), None) |
667 if entry_infos is None: |
675 if entry_infos is None: |
668 slave_variables[(index, subindex)] = { |
676 slave_variables[(index, subindex)] = { |
669 "infos": (iec_type, dir, name), |
677 "infos": (iec_type, dir, name), |
670 "configure": configure, |
|
671 "mapped": False} |
678 "mapped": False} |
672 elif entry_infos["infos"] != (iec_type, dir, name): |
679 elif entry_infos["infos"] != (iec_type, dir, name): |
673 raise ValueError, _("Definition conflict for location \"%s\"") % name |
680 raise ValueError, _("Definition conflict for location \"%s\"") % name |
674 |
681 |
675 def GenerateCFile(self, filepath, location_str, etherlab_node_infos): |
682 def GenerateCFile(self, filepath, location_str, etherlab_node_infos): |