diff -r b1801bf4365c -r caae3ad2d03b etherlab/etherlab.py --- a/etherlab/etherlab.py Sat Oct 13 22:48:05 2012 +0200 +++ b/etherlab/etherlab.py Wed Oct 17 19:12:08 2012 +0200 @@ -795,6 +795,15 @@ (" EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + "%(real_var)s);") % entry_infos) +def ExclusionSortFunction(x, y): + if x["matching"] == y["matching"]: + if x["assigned"] and not y["assigned"]: + return -1 + elif not x["assigned"] and y["assigned"]: + return 1 + return cmp(x["count"], y["count"]) + return -cmp(x["matching"], y["matching"]) + class _EthercatCFileGenerator: def __init__(self, controler): @@ -947,96 +956,133 @@ sync_managers.append(sync_manager_infos) pdos_index = [] - excluded_pdos = [] - for only_mandatory in [True, False]: - for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] + - [(pdo, "Outputs") for pdo in device.getRxPdo()]): + exclusive_pdos = {} + selected_pdos = [] + for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] + + [(pdo, "Outputs") for pdo in device.getRxPdo()]): + + pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) + pdos_index.append(pdo_index) + + excluded_list = pdo.getExclude() + if len(excluded_list) > 0: + exclusion_list = [pdo_index] + for excluded in excluded_list: + exclusion_list.append(ExtractHexDecValue(excluded.getcontent())) + exclusion_list.sort() + + exclusion_scope = exclusive_pdos.setdefault(tuple(exclusion_list), []) + entries = pdo.getEntry() - - pdo_needed = pdo.getMandatory() - if pdo_needed is None: - pdo_needed = False - if only_mandatory != pdo_needed: - continue - - pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) - pdos_index.append(pdo_index) - if pdo_index in excluded_pdos: - continue - - entries_infos = [] + pdo_mapping_match = { + "index": pdo_index, + "matching": 0, + "count": len(entries), + "assigned": pdo.getSm() is not None + } + exclusion_scope.append(pdo_mapping_match) for entry in entries: index = ExtractHexDecValue(entry.getIndex().getcontent()) subindex = ExtractHexDecValue(entry.getSubIndex()) - entry_infos = { - "index": index, - "subindex": subindex, - "name": ExtractName(entry.getName()), - "bitlen": entry.getBitLen(), - } - entry_infos.update(type_infos) - entries_infos.append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) - - entry_declaration = slave_variables.get((index, subindex), None) - if entry_declaration is not None and not entry_declaration["mapped"]: - pdo_needed = True - - entry_infos.update(dict(zip(["var_type", "dir", "var_name"], entry_declaration["infos"]))) - entry_declaration["mapped"] = True - - entry_type = entry.getDataType().getcontent() - if entry_infos["var_type"] != entry_type: - message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"] - if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != - self.Controler.GetSizeOfType(entry_type)): - raise ValueError, message - else: - self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n") - - if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or - entry_infos["dir"] == "Q" and pdo_type != "Outputs"): - raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] - - ConfigureVariable(entry_infos, str_completion) - - elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None: - data_type = entry.getDataType().getcontent() - entry_infos["dir"] = "Q" - entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8) - entry_infos["data_type"] = DATATYPECONVERSION.get(data_type) - entry_infos["var_type"] = data_type - entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos - - ConfigureVariable(entry_infos, str_completion) - - str_completion["slaves_output_pdos_default_values_extraction"] += \ - SLAVE_OUTPUT_PDO_DEFAULT_VALUE % entry_infos - - if pdo_needed: - for excluded in pdo.getExclude(): - excluded_index = ExtractHexDecValue(excluded.getcontent()) - if excluded_index not in excluded_pdos: - excluded_pdos.append(excluded_index) - - sm = pdo.getSm() - if sm is None: - for sm_idx, sync_manager in enumerate(sync_managers): - if sync_manager["name"] == pdo_type: - sm = sm_idx - if sm is None: - raise ValueError, _("No sync manager available for %s pdo!") % pdo_type - - sync_managers[sm]["pdos_number"] += 1 - sync_managers[sm]["pdos"].append( - {"slave": slave_idx, - "index": pdo_index, - "name": ExtractName(pdo.getName()), - "type": pdo_type, - "entries": entries_infos, - "entries_number": len(entries_infos), - "fixed": pdo.getFixed() == True}) + if slave_variables.get((index, subindex), None) is not None: + pdo_mapping_match["matching"] += 1 + + elif pdo.getMandatory(): + selected_pdos.append(pdo_index) + excluded_pdos = [] + for exclusion_scope in exclusive_pdos.itervalues(): + exclusion_scope.sort(ExclusionSortFunction) + start_excluding_index = 0 + if exclusion_scope[0]["matching"] > 0: + selected_pdos.append(exclusion_scope[0]["index"]) + start_excluding_index = 1 + excluded_pdos.extend([pdo["index"] for pdo in exclusion_scope[start_excluding_index:] if PdoAssign or not pdo["assigned"]]) + + for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] + + [(pdo, "Outputs") for pdo in device.getRxPdo()]): + entries = pdo.getEntry() + + pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) + if pdo_index in excluded_pdos: + continue + + pdo_needed = pdo_index in selected_pdos + + entries_infos = [] + + for entry in entries: + index = ExtractHexDecValue(entry.getIndex().getcontent()) + subindex = ExtractHexDecValue(entry.getSubIndex()) + entry_infos = { + "index": index, + "subindex": subindex, + "name": ExtractName(entry.getName()), + "bitlen": entry.getBitLen(), + } + entry_infos.update(type_infos) + entries_infos.append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) + + entry_declaration = slave_variables.get((index, subindex), None) + if entry_declaration is not None and not entry_declaration["mapped"]: + pdo_needed = True + + entry_infos.update(dict(zip(["var_type", "dir", "var_name"], entry_declaration["infos"]))) + entry_declaration["mapped"] = True + + entry_type = entry.getDataType().getcontent() + if entry_infos["var_type"] != entry_type: + message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"] + if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != + self.Controler.GetSizeOfType(entry_type)): + raise ValueError, message + else: + self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n") + + if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or + entry_infos["dir"] == "Q" and pdo_type != "Outputs"): + raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] + + ConfigureVariable(entry_infos, str_completion) + + elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None: + data_type = entry.getDataType().getcontent() + entry_infos["dir"] = "Q" + entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8) + entry_infos["data_type"] = DATATYPECONVERSION.get(data_type) + entry_infos["var_type"] = data_type + entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos + + ConfigureVariable(entry_infos, str_completion) + + str_completion["slaves_output_pdos_default_values_extraction"] += \ + SLAVE_OUTPUT_PDO_DEFAULT_VALUE % entry_infos + + if pdo_needed: + for excluded in pdo.getExclude(): + excluded_index = ExtractHexDecValue(excluded.getcontent()) + if excluded_index not in excluded_pdos: + excluded_pdos.append(excluded_index) + + sm = pdo.getSm() + if sm is None: + for sm_idx, sync_manager in enumerate(sync_managers): + if sync_manager["name"] == pdo_type: + sm = sm_idx + if sm is None: + raise ValueError, _("No sync manager available for %s pdo!") % pdo_type + + sync_managers[sm]["pdos_number"] += 1 + sync_managers[sm]["pdos"].append( + {"slave": slave_idx, + "index": pdo_index, + "name": ExtractName(pdo.getName()), + "type": pdo_type, + "entries": entries_infos, + "entries_number": len(entries_infos), + "fixed": pdo.getFixed() == True}) + if PdoConfig and PdoAssign: dynamic_pdos = {} dynamic_pdos_number = 0