653 current_location = self.GetCurrentLocation() |
641 current_location = self.GetCurrentLocation() |
654 |
642 |
655 slaves = self.GetSlaves() |
643 slaves = self.GetSlaves() |
656 for slave_pos in slaves: |
644 for slave_pos in slaves: |
657 slave = self.GetSlave(slave_pos) |
645 slave = self.GetSlave(slave_pos) |
658 slave_node = self.GetChildByIECLocation([slave_pos]) |
|
659 if slave_node.CTNParams is not None: |
|
660 slave_infos = slave_node.CTNParams[1] |
|
661 else: |
|
662 slave_infos = None |
|
663 if slave is not None: |
646 if slave is not None: |
664 self.FileGenerator.DeclareSlave(slave_pos, slave.getInfo().getAutoIncAddr(), slave.getType(), slave_infos) |
647 self.FileGenerator.DeclareSlave(slave_pos, slave.getInfo().getAutoIncAddr(), slave.getType()) |
665 |
648 |
666 for location in locations: |
649 for location in locations: |
667 loc = location["LOC"][len(current_location):] |
650 loc = location["LOC"][len(current_location):] |
668 slave_pos = loc[0] |
651 slave_pos = loc[0] |
669 if slave_pos in slaves and len(loc) == 3: |
652 if slave_pos in slaves and len(loc) == 3: |
819 self.Slaves = [] |
802 self.Slaves = [] |
820 self.UsedVariables = {} |
803 self.UsedVariables = {} |
821 |
804 |
822 def __del__(self): |
805 def __del__(self): |
823 self.Controler = None |
806 self.Controler = None |
824 |
807 |
825 def DeclareSlave(self, slave_index, slave_alias, slave, slave_infos): |
808 def DeclareSlave(self, slave_index, slave_alias, slave): |
826 self.Slaves.append((slave_index, slave_alias, slave, slave_infos)) |
809 self.Slaves.append((slave_index, slave_alias, slave)) |
827 |
810 |
828 def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name): |
811 def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name): |
829 slave_variables = self.UsedVariables.setdefault(slave_index, {}) |
812 slave_variables = self.UsedVariables.setdefault(slave_index, {}) |
830 |
813 |
831 entry_infos = slave_variables.get((index, subindex), None) |
814 entry_infos = slave_variables.get((index, subindex), None) |
836 elif entry_infos["infos"] != (iec_type, dir, name): |
819 elif entry_infos["infos"] != (iec_type, dir, name): |
837 raise ValueError, _("Definition conflict for location \"%s\"") % name |
820 raise ValueError, _("Definition conflict for location \"%s\"") % name |
838 |
821 |
839 def GenerateCFile(self, filepath, location_str, etherlab_node_infos): |
822 def GenerateCFile(self, filepath, location_str, etherlab_node_infos): |
840 |
823 |
|
824 # Extract etherlab master code template |
841 plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c") |
825 plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c") |
842 plc_etherlab_file = open(plc_etherlab_filepath, 'r') |
826 plc_etherlab_file = open(plc_etherlab_filepath, 'r') |
843 plc_etherlab_code = plc_etherlab_file.read() |
827 plc_etherlab_code = plc_etherlab_file.read() |
844 plc_etherlab_file.close() |
828 plc_etherlab_file.close() |
845 |
829 |
|
830 # Initialize strings for formatting master code template |
846 str_completion = { |
831 str_completion = { |
847 "location": location_str, |
832 "location": location_str, |
848 "configure_pdos": int(etherlab_node_infos.getConfigurePDOs()), |
|
849 "master_number": etherlab_node_infos.getMasterNumber(), |
833 "master_number": etherlab_node_infos.getMasterNumber(), |
850 "located_variables_declaration": [], |
834 "located_variables_declaration": [], |
851 "used_pdo_entry_offset_variables_declaration": [], |
835 "used_pdo_entry_offset_variables_declaration": [], |
852 "used_pdo_entry_configuration": [], |
836 "used_pdo_entry_configuration": [], |
853 "pdos_configuration_declaration": "", |
837 "pdos_configuration_declaration": "", |
857 "slaves_initialization": "", |
841 "slaves_initialization": "", |
858 "retrieve_variables": [], |
842 "retrieve_variables": [], |
859 "publish_variables": [], |
843 "publish_variables": [], |
860 } |
844 } |
861 |
845 |
|
846 # Initialize variable storing variable mapping state |
862 for slave_entries in self.UsedVariables.itervalues(): |
847 for slave_entries in self.UsedVariables.itervalues(): |
863 for entry_infos in slave_entries.itervalues(): |
848 for entry_infos in slave_entries.itervalues(): |
864 entry_infos["mapped"] = False |
849 entry_infos["mapped"] = False |
865 |
850 |
|
851 # Sort slaves by position (IEC_Channel) |
866 self.Slaves.sort() |
852 self.Slaves.sort() |
|
853 # Initialize dictionary storing alias auto-increment position values |
867 alias = {} |
854 alias = {} |
868 for (slave_idx, slave_alias, type_infos, slave_infos) in self.Slaves: |
855 |
|
856 # Generating code for each slave |
|
857 for (slave_idx, slave_alias, type_infos) in self.Slaves: |
|
858 |
|
859 # Defining slave alias and auto-increment position |
869 if alias.get(slave_alias) is not None: |
860 if alias.get(slave_alias) is not None: |
870 alias[slave_alias] += 1 |
861 alias[slave_alias] += 1 |
871 else: |
862 else: |
872 alias[slave_alias] = 0 |
863 alias[slave_alias] = 0 |
873 slave_pos = (slave_alias, alias[slave_alias]) |
864 slave_pos = (slave_alias, alias[slave_alias]) |
874 |
865 |
|
866 # Extract slave device informations |
875 device = self.Controler.GetModuleInfos(type_infos) |
867 device = self.Controler.GetModuleInfos(type_infos) |
876 if device is not None: |
868 if device is not None: |
877 |
869 |
|
870 # Extract slaves variables to be mapped |
878 slave_variables = self.UsedVariables.get(slave_idx, {}) |
871 slave_variables = self.UsedVariables.get(slave_idx, {}) |
|
872 |
|
873 # Extract slave device object dictionary entries |
879 device_entries = device.GetEntriesList() |
874 device_entries = device.GetEntriesList() |
880 |
875 |
881 if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0: |
876 # Adding code for declaring slave in master code template strings |
|
877 for element in ["vendor", "product_code", "revision_number"]: |
|
878 type_infos[element] = ExtractHexDecValue(type_infos[element]) |
|
879 type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos))) |
|
880 |
|
881 # Extract slave device CoE informations |
|
882 device_coe = device.getCoE() |
|
883 if device_coe is not None: |
882 |
884 |
883 for element in ["vendor", "product_code", "revision_number"]: |
885 # If device support CanOpen over Ethernet, adding code for calling |
884 type_infos[element] = ExtractHexDecValue(type_infos[element]) |
886 # init commands when initializing slave in master code template strings |
885 type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos))) |
887 for initCmd in device_coe.getInitCmd(): |
886 |
|
887 str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos |
|
888 str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos |
|
889 |
|
890 for initCmd in device.getInitCmd(): |
|
891 index = ExtractHexDecValue(initCmd.getIndex()) |
888 index = ExtractHexDecValue(initCmd.getIndex()) |
892 subindex = ExtractHexDecValue(initCmd.getSubIndex()) |
889 subindex = ExtractHexDecValue(initCmd.getSubIndex()) |
893 entry = device_entries.get((index, subindex), None) |
890 entry = device_entries.get((index, subindex), None) |
894 if entry is not None: |
891 if entry is not None: |
895 data_size = entry["BitSize"] / 8 |
892 data_size = entry["BitSize"] / 8 |
901 "data": data_str, |
898 "data": data_str, |
902 "data_size": data_size |
899 "data_size": data_size |
903 } |
900 } |
904 init_cmd_infos.update(type_infos) |
901 init_cmd_infos.update(type_infos) |
905 str_completion["slaves_initialization"] += SLAVE_INITIALIZATION_TEMPLATE % init_cmd_infos |
902 str_completion["slaves_initialization"] += SLAVE_INITIALIZATION_TEMPLATE % init_cmd_infos |
906 |
903 |
|
904 # Extract slave device PDO configuration capabilities |
|
905 PdoAssign = device_coe.getPdoAssign() |
|
906 PdoConfig = device_coe.getPdoConfig() |
|
907 else: |
|
908 PdoAssign = PdoConfig = False |
|
909 |
|
910 # Test if slave has a configuration or need one |
|
911 if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0 and PdoConfig and PdoAssign: |
|
912 |
|
913 str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos |
|
914 str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos |
|
915 |
|
916 # Initializing |
907 pdos_infos = { |
917 pdos_infos = { |
908 "pdos_entries_infos": [], |
918 "pdos_entries_infos": [], |
909 "pdos_infos": [], |
919 "pdos_infos": [], |
910 "pdos_sync_infos": [], |
920 "pdos_sync_infos": [], |
911 } |
921 } |
987 entry_infos["dir"] == "Q" and pdo_type != "Outputs"): |
997 entry_infos["dir"] == "Q" and pdo_type != "Outputs"): |
988 raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] |
998 raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] |
989 |
999 |
990 ConfigureVariable(entry_infos, str_completion) |
1000 ConfigureVariable(entry_infos, str_completion) |
991 |
1001 |
992 elif pdo_type == "Outputs" and entry.getDataType() is not None: |
1002 elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None: |
993 entry_infos["dir"] = "Q" |
1003 entry_infos["dir"] = "Q" |
994 entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8) |
1004 entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8) |
995 entry_infos["var_type"] = entry.getDataType().getcontent() |
1005 entry_infos["var_type"] = entry.getDataType().getcontent() |
996 entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos |
1006 entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos |
997 |
1007 |
1022 "type": pdo_type, |
1032 "type": pdo_type, |
1023 "entries": entries_infos, |
1033 "entries": entries_infos, |
1024 "entries_number": len(entries_infos), |
1034 "entries_number": len(entries_infos), |
1025 "fixed": pdo.getFixed() == True}) |
1035 "fixed": pdo.getFixed() == True}) |
1026 |
1036 |
1027 if slave_infos is None or slave_infos.getDynamicPDOs(): |
1037 if PdoConfig and PdoAssign: |
1028 dynamic_pdos = {} |
1038 dynamic_pdos = {} |
1029 dynamic_pdos_number = 0 |
1039 dynamic_pdos_number = 0 |
1030 for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), |
1040 for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), |
1031 ("Outputs", 0x1a00, 0x1C00)]: |
1041 ("Outputs", 0x1a00, 0x1C00)]: |
1032 for sync_manager in sync_managers: |
1042 for sync_manager in sync_managers: |
1102 pdo["entries"].append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) |
1112 pdo["entries"].append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) |
1103 pdo["entries_number"] += 1 |
1113 pdo["entries_number"] += 1 |
1104 |
1114 |
1105 if pdo["entries_number"] == 255: |
1115 if pdo["entries_number"] == 255: |
1106 dynamic_pdos[pdo_type]["pdos"].pop(0) |
1116 dynamic_pdos[pdo_type]["pdos"].pop(0) |
1107 |
1117 |
1108 pdo_offset = 0 |
1118 pdo_offset = 0 |
1109 entry_offset = 0 |
1119 entry_offset = 0 |
1110 for sync_manager_infos in sync_managers: |
1120 for sync_manager_infos in sync_managers: |
1111 |
1121 |
1112 for pdo_infos in sync_manager_infos["pdos"]: |
1122 for pdo_infos in sync_manager_infos["pdos"]: |
1113 pdo_infos["offset"] = entry_offset |
1123 pdo_infos["offset"] = entry_offset |
1114 pdo_entries = pdo_infos["entries"] |
1124 pdo_entries = pdo_infos["entries"] |
1115 pdos_infos["pdos_infos"].append( |
1125 pdos_infos["pdos_infos"].append( |
1116 (" {0x%(index).4x, %(entries_number)d, " + |
1126 (" {0x%(index).4x, %(entries_number)d, " + |
1128 |
1138 |
1129 for element in ["pdos_entries_infos", "pdos_infos", "pdos_sync_infos"]: |
1139 for element in ["pdos_entries_infos", "pdos_infos", "pdos_sync_infos"]: |
1130 pdos_infos[element] = "\n".join(pdos_infos[element]) |
1140 pdos_infos[element] = "\n".join(pdos_infos[element]) |
1131 |
1141 |
1132 str_completion["pdos_configuration_declaration"] += SLAVE_PDOS_CONFIGURATION_DECLARATION % pdos_infos |
1142 str_completion["pdos_configuration_declaration"] += SLAVE_PDOS_CONFIGURATION_DECLARATION % pdos_infos |
1133 |
1143 |
|
1144 for (index, subindex), entry_declaration in slave_variables.iteritems(): |
|
1145 if not entry_declaration["mapped"]: |
|
1146 message = _("Entry index 0x%4.4x, subindex 0x%2.2x not mapped for device %s") % \ |
|
1147 (index, subindex, type_infos["device_type"]) |
|
1148 self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n") |
|
1149 |
1134 for element in ["used_pdo_entry_offset_variables_declaration", |
1150 for element in ["used_pdo_entry_offset_variables_declaration", |
1135 "used_pdo_entry_configuration", |
1151 "used_pdo_entry_configuration", |
1136 "located_variables_declaration", |
1152 "located_variables_declaration", |
1137 "retrieve_variables", |
1153 "retrieve_variables", |
1138 "publish_variables"]: |
1154 "publish_variables"]: |
1214 if content is not None and content["name"] == "SubItem": |
1230 if content is not None and content["name"] == "SubItem": |
1215 self.DataTypes[datatype.getName()] = datatype |
1231 self.DataTypes[datatype.getName()] = datatype |
1216 |
1232 |
1217 setattr(cls, "ExtractDataTypes", ExtractDataTypes) |
1233 setattr(cls, "ExtractDataTypes", ExtractDataTypes) |
1218 |
1234 |
1219 def getInitCmd(self): |
1235 def getCoE(self): |
1220 mailbox = self.getMailbox() |
1236 mailbox = self.getMailbox() |
1221 if mailbox is None: |
1237 if mailbox is not None: |
1222 return [] |
1238 return mailbox.getCoE() |
1223 |
1239 return None |
1224 coe = mailbox.getCoE() |
1240 setattr(cls, "getCoE", getCoE) |
1225 if coe is None: |
|
1226 return [] |
|
1227 |
|
1228 return coe.getInitCmd() |
|
1229 setattr(cls, "getInitCmd", getInitCmd) |
|
1230 |
1241 |
1231 def GetEntriesList(self): |
1242 def GetEntriesList(self): |
1232 if self.DataTypes is None: |
1243 if self.DataTypes is None: |
1233 self.ExtractDataTypes() |
1244 self.ExtractDataTypes() |
1234 |
1245 |