etherlab/etherlab.py
changeset 2029 7c848efa21c6
parent 2026 65ecbfe9a6f9
child 2030 7147f20c23e3
equal deleted inserted replaced
2028:5132c497918c 2029:7c848efa21c6
    13     "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"}
    13     "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"}
    14 
    14 
    15 DATATYPECONVERSION = {"BOOL" : "BIT", "SINT" : "S8", "INT" : "S16", "DINT" : "S32", "LINT" : "S64",
    15 DATATYPECONVERSION = {"BOOL" : "BIT", "SINT" : "S8", "INT" : "S16", "DINT" : "S32", "LINT" : "S64",
    16     "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", 
    16     "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", 
    17     "BYTE" : "U8", "WORD" : "U16", "DWORD" : "U32", "LWORD" : "U64"}
    17     "BYTE" : "U8", "WORD" : "U16", "DWORD" : "U32", "LWORD" : "U64"}
       
    18 
       
    19 VARCLASSCONVERSION = {"ro": LOCATION_VAR_INPUT, "wo": LOCATION_VAR_OUTPUT, "rw": LOCATION_VAR_MEMORY}
    18 
    20 
    19 #--------------------------------------------------
    21 #--------------------------------------------------
    20 #                 Ethercat MASTER
    22 #                 Ethercat MASTER
    21 #--------------------------------------------------
    23 #--------------------------------------------------
    22 
    24 
    28     except:
    30     except:
    29         pass
    31         pass
    30     try:
    32     try:
    31         return int(value.replace("#", "0"), 16)
    33         return int(value.replace("#", "0"), 16)
    32     except:
    34     except:
    33         raise "Invalid value for HexDecValue \"%s\"" % value
    35         raise ValueError, "Invalid value for HexDecValue \"%s\"" % value
    34 
    36 
    35 def GenerateHexDecValue(value, base=10):
    37 def GenerateHexDecValue(value, base=10):
    36     if base == 10:
    38     if base == 10:
    37         return str(value)
    39         return str(value)
    38     elif base == 16:
    40     elif base == 16:
    39         return "#x%.8x" % value
    41         return "#x%.8x" % value
    40     else:
    42     else:
    41         raise "Not supported base"
    43         raise ValueError, "Not supported base"
    42 
    44 
    43 cls = EtherCATConfigClasses.get("Config_Slave", None)
    45 cls = EtherCATConfigClasses.get("Config_Slave", None)
    44 if cls:
    46 if cls:
    45     
    47     
    46     def getType(self):
    48     def getType(self):
   184         if slave is not None:
   186         if slave is not None:
   185             type_infos = slave.getType()
   187             type_infos = slave.getType()
   186             device = self.GetModuleInfos(type_infos)
   188             device = self.GetModuleInfos(type_infos)
   187             if device is not None:
   189             if device is not None:
   188                 infos = type_infos.copy()
   190                 infos = type_infos.copy()
       
   191                 entries = device.GetEntriesList()
       
   192                 entries_list = entries.items()
       
   193                 entries_list.sort()
   189                 infos.update({"physics": device.getPhysics(),
   194                 infos.update({"physics": device.getPhysics(),
   190                               "variables": []})
   195                               "sync_managers": device.GetSyncManagers(),
   191                 for TxPdo in device.getTxPdo():
   196                               "entries": [entry[1] for entry in entries_list]})
   192                     ExtractPdoInfos(TxPdo, "Transmit", infos)
       
   193                 for RxPdo in device.getRxPdo():
       
   194                     ExtractPdoInfos(RxPdo, "Receive", infos)
       
   195                 return infos
   197                 return infos
   196         return None
   198         return None
   197     
   199     
   198     def GetModuleInfos(self, type_infos):
   200     def GetModuleInfos(self, type_infos):
   199         return self.PlugParent.GetModuleInfos(type_infos)
   201         return self.PlugParent.GetModuleInfos(type_infos)
   224                         if sync_manager_direction:
   226                         if sync_manager_direction:
   225                             sync_managers.append(LOCATION_VAR_OUTPUT)
   227                             sync_managers.append(LOCATION_VAR_OUTPUT)
   226                         else:
   228                         else:
   227                             sync_managers.append(LOCATION_VAR_INPUT)
   229                             sync_managers.append(LOCATION_VAR_INPUT)
   228                     
   230                     
   229                     for pdo in device.getTxPdo() + device.getRxPdo():
   231                     entries = device.GetEntriesList().items()
   230                         var_class = sync_managers[pdo.getSm()]
   232                     entries.sort()
   231                         
   233                     for (index, subindex), entry in entries:
   232                         for entry in pdo.getEntry():
   234                         var_size = self.GetSizeOfType(entry["Type"])
   233                             index = ExtractHexDecValue(entry.getIndex().getcontent())
   235                         if var_size is not None:
   234                             subindex = ExtractHexDecValue(entry.getSubIndex())
   236                             var_class = VARCLASSCONVERSION.get(entry["Access"], LOCATION_VAR_MEMORY)
   235                             var_type = entry.getDataType().getcontent()
       
   236                             var_size = self.GetSizeOfType(var_type)
       
   237                             if var_class == LOCATION_VAR_INPUT:
   237                             if var_class == LOCATION_VAR_INPUT:
   238                                 var_dir = "%I"
   238                                 var_dir = "%I"
   239                             else:
   239                             else:
   240                                 var_dir = "%Q"    
   240                                 var_dir = "%Q"    
   241                             
   241                             
   242                             pdo_name = ExtractName(pdo.getName())
   242                             vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]),
   243                             entry_name = ExtractName(entry.getName())
       
   244                             vars.append({"name": "%s - %s" % (pdo_name, entry_name),
       
   245                                          "type": var_class,
   243                                          "type": var_class,
   246                                          "size": var_size,
   244                                          "size": var_size,
   247                                          "IEC_type": var_type,
   245                                          "IEC_type": entry["Type"],
   248                                          "var_name": "%s_%s" % (type_infos["device_type"], "_".join(pdo_name.split())),
   246                                          "var_name": "%s_%4.4x_%2.2x" % (type_infos["device_type"], index, subindex),
   249                                          "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + 
   247                                          "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + 
   250                                                                                                     slave_pos + 
   248                                                                                                     slave_pos + 
   251                                                                                                     (index, subindex)))),
   249                                                                                                     (index, subindex)))),
   252                                          "description": "",
   250                                          "description": "",
   253                                          "children": []})
   251                                          "children": []})
   381         fprintf(stderr, "Failed to configure PDOs for slave %(device_type)s at alias %(alias)d and position %(position)d.\\n");
   379         fprintf(stderr, "Failed to configure PDOs for slave %(device_type)s at alias %(alias)d and position %(position)d.\\n");
   382         return -1;
   380         return -1;
   383     }
   381     }
   384 """
   382 """
   385 
   383 
       
   384 def ConfigureVariable(entry_infos, str_completion):
       
   385     data_type = DATATYPECONVERSION.get(entry_infos["var_type"], None)
       
   386     if data_type is None:
       
   387         raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"]
       
   388                                 
       
   389     str_completion["located_variables_declaration"].extend(
       
   390         ["IEC_%(var_type)s beremiz%(var_name)s;" % entry_infos,
       
   391          "IEC_%(var_type)s *%(var_name)s = &beremiz%(var_name)s;" % entry_infos])
       
   392     
       
   393     if data_type == "BIT":
       
   394         str_completion["used_pdo_entry_offset_variables_declaration"].extend(
       
   395             ["static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos,
       
   396              "static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos])
       
   397         
       
   398         str_completion["used_pdo_entry_configuration"].append(
       
   399              ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + 
       
   400               "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   401               "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos)
       
   402         
       
   403         if entry_infos["dir"] == "I":
       
   404             str_completion["retrieve_variables"].append(
       
   405               ("    beremiz%(name)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   406                "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos)
       
   407         elif entry_infos["dir"] == "Q":
       
   408             str_completion["publish_variables"].append(
       
   409               ("    EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   410                "slave%(slave)d_%(index).4x_%(subindex).2x_bit, beremiz%(var_name)s);") % entry_infos)
       
   411     
       
   412     else:
       
   413         entry_infos["data_type"] = data_type
       
   414         
       
   415         str_completion["used_pdo_entry_offset_variables_declaration"].append(
       
   416             "static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos)
       
   417         
       
   418         str_completion["used_pdo_entry_configuration"].append(
       
   419             ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + 
       
   420              "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos)
       
   421         
       
   422         if entry_infos["dir"] == "I":
       
   423             str_completion["retrieve_variables"].append(
       
   424                 ("    beremiz%(var_name)s = EC_READ_BIT(domain1_pd + " + 
       
   425                  "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos)
       
   426         elif entry_infos["dir"] == "Q":
       
   427             str_completion["publish_variables"].append(
       
   428                 ("    EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   429                  "beremiz%(var_name)s);") % entry_infos)
       
   430         
       
   431 
   386 class _EthercatCFileGenerator:
   432 class _EthercatCFileGenerator:
   387     
   433     
   388     def __init__(self, controler, filepath):
   434     def __init__(self, controler, filepath):
   389         self.Controler = controler
   435         self.Controler = controler
   390         self.FilePath = filepath
   436         self.FilePath = filepath
   397     def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name):
   443     def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name):
   398         slave_variables = self.UsedVariables.setdefault(slave_identifier, {})
   444         slave_variables = self.UsedVariables.setdefault(slave_identifier, {})
   399         
   445         
   400         entry_infos = slave_variables.get((index, subindex), None)
   446         entry_infos = slave_variables.get((index, subindex), None)
   401         if entry_infos is None:
   447         if entry_infos is None:
   402             slave_variables[(index, subindex)] = (iec_type, dir, name)
   448             slave_variables[(index, subindex)] = {
   403         elif entry_infos != (iec_type, dir, name):
   449                 "infos": (iec_type, dir, name),
       
   450                 "mapped": False}
       
   451         elif entry_infos["infos"] != (iec_type, dir, name):
   404             raise ValueError, _("Definition conflict for location \"%s\"") % name 
   452             raise ValueError, _("Definition conflict for location \"%s\"") % name 
   405     
   453         
   406     def GenerateCFile(self):
   454     def GenerateCFile(self):
   407         
   455         
   408         current_location = self.Controler.GetCurrentLocation()
   456         current_location = self.Controler.GetCurrentLocation()
   409         # define a unique name for the generated C file
   457         # define a unique name for the generated C file
   410         location_str = "_".join(map(lambda x:str(x), current_location))
   458         location_str = "_".join(map(lambda x:str(x), current_location))
   426             "slaves_configuration": "",
   474             "slaves_configuration": "",
   427             "retrieve_variables": [],
   475             "retrieve_variables": [],
   428             "publish_variables": [],
   476             "publish_variables": [],
   429         }
   477         }
   430         
   478         
       
   479         for slave_entries in self.UsedVariables.itervalues():
       
   480             for entry_infos in slave_entries.itervalues():
       
   481                 entry_infos["mapped"] = False
       
   482         
   431         for slave_idx, slave_pos in enumerate(self.Controler.GetSlaves()):
   483         for slave_idx, slave_pos in enumerate(self.Controler.GetSlaves()):
   432             
   484             
   433             slave = self.Controler.GetSlave(slave_pos)
   485             slave = self.Controler.GetSlave(slave_pos)
   434             if slave is not None:
   486             if slave is not None:
   435                 type_infos = slave.getType()
   487                 type_infos = slave.getType()
   436                 
   488                 
   437                 device = self.Controler.GetModuleInfos(type_infos)
   489                 device = self.Controler.GetModuleInfos(type_infos)
   438                 if device is not None:
   490                 if device is not None:
       
   491                     slave_variables = self.UsedVariables.get(slave_pos, {})
       
   492                     device_entries = device.GetEntriesList()
   439                     
   493                     
   440                     pdos = device.getTxPdo() + device.getRxPdo()
   494                     if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0:
   441                     if len(pdos) > 0:
       
   442                         slave_variables = self.UsedVariables.get(slave_pos, {})
       
   443                         
   495                         
   444                         for element in ["vendor", "product_code", "revision_number"]:
   496                         for element in ["vendor", "product_code", "revision_number"]:
   445                             type_infos[element] = ExtractHexDecValue(type_infos[element])
   497                             type_infos[element] = ExtractHexDecValue(type_infos[element])
   446                         type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos)))
   498                         type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos)))
   447                     
   499                     
   457                         
   509                         
   458                         sync_managers = []
   510                         sync_managers = []
   459                         for sync_manager_idx, sync_manager in enumerate(device.getSm()):
   511                         for sync_manager_idx, sync_manager in enumerate(device.getSm()):
   460                             sync_manager_infos = {
   512                             sync_manager_infos = {
   461                                 "index": sync_manager_idx, 
   513                                 "index": sync_manager_idx, 
       
   514                                 "name": sync_manager.getcontent(),
   462                                 "slave": slave_idx,
   515                                 "slave": slave_idx,
       
   516                                 "pdos": [], 
   463                                 "pdos_number": 0,
   517                                 "pdos_number": 0,
   464                             }
   518                             }
   465                             
   519                             
   466                             sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte())
   520                             sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte())
   467                             sync_manager_direction = sync_manager_control_byte & 0x0c
   521                             sync_manager_direction = sync_manager_control_byte & 0x0c
   475                             else:
   529                             else:
   476                                 sync_manager_infos["watchdog"] = "EC_WD_DISABLE"
   530                                 sync_manager_infos["watchdog"] = "EC_WD_DISABLE"
   477                             
   531                             
   478                             sync_managers.append(sync_manager_infos)
   532                             sync_managers.append(sync_manager_infos)
   479                         
   533                         
   480                         entry_offset = 0
   534                         pdos_index = []
   481                         for pdo in pdos:
   535                         for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] +
       
   536                                               [(pdo, "Outputs") for pdo in device.getRxPdo()]):
   482                             entries = pdo.getEntry()
   537                             entries = pdo.getEntry()
   483                             
   538                             
   484                             pdo_needed = pdo.getMandatory()
   539                             pdo_needed = pdo.getMandatory()
       
   540                             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
       
   541                             pdos_index.append(pdo_index)
   485                             entries_infos = []
   542                             entries_infos = []
   486                             
   543                             
   487                             for entry in entries:
   544                             for entry in entries:
   488                                 index = ExtractHexDecValue(entry.getIndex().getcontent())
   545                                 index = ExtractHexDecValue(entry.getIndex().getcontent())
   489                                 subindex = ExtractHexDecValue(entry.getSubIndex())
   546                                 subindex = ExtractHexDecValue(entry.getSubIndex())
   497                                 entries_infos.append("    {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
   554                                 entries_infos.append("    {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
   498                                 
   555                                 
   499                                 entry_declaration = slave_variables.get((index, subindex), None)
   556                                 entry_declaration = slave_variables.get((index, subindex), None)
   500                                 if entry_declaration is not None:
   557                                 if entry_declaration is not None:
   501                                     pdo_needed = True
   558                                     pdo_needed = True
   502                                     entry_infos.update(dict(zip(["var_type", "dir", "var_name"], entry_declaration)))
   559                                     
       
   560                                     entry_infos.update(dict(zip(["var_type", "dir", "var_name"], entry_declaration["infos"])))
       
   561                                     entry_declaration["mapped"] = True
   503                                     
   562                                     
   504                                     if entry_infos["var_type"] != entry.getDataType().getcontent():
   563                                     if entry_infos["var_type"] != entry.getDataType().getcontent():
   505                                         raise ValueError, _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
   564                                         raise ValueError, _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
   506                                     
   565                                     
   507                                     data_type = DATATYPECONVERSION.get(entry_infos["var_type"], None)
   566                                     if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or 
   508                                     if data_type is None:
   567                                         entry_infos["dir"] == "Q" and pdo_type != "Outputs"):
   509                                         raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"]
       
   510                                     
       
   511                                     if (entry_infos["dir"] == "I" and sync_managers[pdo.getSm()]["sync_manager_type"] != "EC_DIR_INPUT" or 
       
   512                                         entry_infos["dir"] == "Q" and sync_managers[pdo.getSm()]["sync_manager_type"] != "EC_DIR_OUTPUT"):
       
   513                                         raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
   568                                         raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
   514                                     
   569                                     
   515                                     str_completion["located_variables_declaration"].extend(
   570                                     ConfigureVariable(entry_infos, str_completion)
   516                                         ["IEC_%(var_type)s beremiz%(var_name)s;" % entry_infos,
       
   517                                          "IEC_%(var_type)s *%(var_name)s = &beremiz%(var_name)s;" % entry_infos])
       
   518                                     
       
   519                                     if data_type == "BIT":
       
   520                                         str_completion["used_pdo_entry_offset_variables_declaration"].extend(
       
   521                                             ["static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos,
       
   522                                              "static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos])
       
   523                                         
       
   524                                         str_completion["used_pdo_entry_configuration"].append(
       
   525                                              ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + 
       
   526                                               "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   527                                               "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos)
       
   528                                         
       
   529                                         if entry_infos["dir"] == "I":
       
   530                                             str_completion["retrieve_variables"].append(
       
   531                                               ("    beremiz%(name)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   532                                                "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos)
       
   533                                         elif entry_infos["dir"] == "Q":
       
   534                                             str_completion["publish_variables"].append(
       
   535                                               ("    EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   536                                                "slave%(slave)d_%(index).4x_%(subindex).2x_bit, beremiz%(var_name)s);") % entry_infos)
       
   537                                     
       
   538                                     else:
       
   539                                         entry_infos["data_type"] = data_type
       
   540                                         
       
   541                                         str_completion["used_pdo_entry_offset_variables_declaration"].append(
       
   542                                             "static unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos)
       
   543                                         
       
   544                                         str_completion["used_pdo_entry_configuration"].append(
       
   545                                             ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + 
       
   546                                              "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos)
       
   547                                         
       
   548                                         if entry_infos["dir"] == "I":
       
   549                                             str_completion["retrieve_variables"].append(
       
   550                                                 ("    beremiz%(name)s = EC_READ_BIT(domain1_pd + " + 
       
   551                                                  "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos)
       
   552                                         elif entry_infos["dir"] == "Q":
       
   553                                             str_completion["publish_variables"].append(
       
   554                                                 ("    EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   555                                                  "beremiz%(var_name)s);") % entry_infos)
       
   556                             
   571                             
   557                             if pdo_needed:
   572                             if pdo_needed:
   558                                 sync_managers[pdo.getSm()]["pdos_number"] += 1
   573                                 sm = pdo.getSm()
   559                                 pdo_infos = {
   574                                 if sm is None:
   560                                     "slave": slave_idx,
   575                                     for sm_idx, sync_manager in enumerate(sync_managers):
   561                                     "index": ExtractHexDecValue(pdo.getIndex().getcontent()),
   576                                         if sync_manager["Name"] == pdo_type:
   562                                     "name": ExtractName(pdo.getName()),
   577                                             sm = sm_idx
   563                                     "offset": entry_offset,
   578                                 if sm is None:
   564                                     "entries_number": len(entries)
   579                                     raise ValueError, _("No sync manager available for %s pdo!") % pdo_type
       
   580                                     
       
   581                                 sync_managers[sm]["pdos_number"] += 1
       
   582                                 sync_managers[sm]["pdos"].append(
       
   583                                     {"slave": slave_idx,
       
   584                                      "index": pdo_index,
       
   585                                      "name": ExtractName(pdo.getName()),
       
   586                                      "type": pdo_type, 
       
   587                                      "entries": entries_infos,
       
   588                                      "entries_number": len(entries_infos),
       
   589                                      "fixed": pdo.getFixed() == True})
       
   590                         
       
   591                         dynamic_pdos = {}
       
   592                         dynamic_pdos_number = 0
       
   593                         for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), 
       
   594                                                                ("Outputs", 0x1a00, 0x1C00)]:
       
   595                             for sync_manager in sync_managers:
       
   596                                 if sync_manager["name"] == category:
       
   597                                     category_infos = dynamic_pdos.setdefault(category, {})
       
   598                                     category_infos["sync_manager"] = sync_manager
       
   599                                     category_infos["pdos"] = [pdo for pdo in category_infos["sync_manager"]["pdos"] 
       
   600                                                               if not pdo["fixed"] and pdo["type"] == category]
       
   601                                     category_infos["current_index"] = min_index
       
   602                                     category_infos["max_index"] = max_index
       
   603                                     break
       
   604                         
       
   605                         for (index, subindex), entry_declaration in slave_variables.iteritems():
       
   606                             
       
   607                             if not entry_declaration["mapped"]:
       
   608                                 entry = device_entries.get((index, subindex), None)
       
   609                                 if entry is None:
       
   610                                     raise ValueError, _("Unknown entry index 0x%4.4x, subindex 0x%2.2x for device %s") % \
       
   611                                                      (index, subindex, type_infos["device_type"])
       
   612                                 
       
   613                                 entry_infos = {
       
   614                                     "index": index,
       
   615                                     "subindex": subindex,
       
   616                                     "name": entry["Name"],
       
   617                                     "bitlen": entry["BitSize"],
   565                                 }
   618                                 }
       
   619                                 entry_infos.update(type_infos)
       
   620                                 
       
   621                                 entry_infos.update(dict(zip(["var_type", "dir", "var_name"], entry_declaration["infos"])))
       
   622                                 entry_declaration["mapped"] = True
       
   623                                 
       
   624                                 if entry_infos["var_type"] != entry["Type"]:
       
   625                                     raise ValueError, _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
       
   626                                 
       
   627                                 if entry_infos["dir"] == "I" and entry["Access"] in ["ro", "rw"]:
       
   628                                     pdo_type = "Inputs"
       
   629                                 elif entry_infos["dir"] == "Q" and entry["Access"] in ["wo", "rw"]:
       
   630                                     pdo_type = "Outputs"
       
   631                                 else:
       
   632                                     raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
       
   633                                 
       
   634                                 if not dynamic_pdos.has_key(pdo_type):
       
   635                                     raise ValueError, _("No Sync manager defined for %s!") % pdo_type
       
   636                                 
       
   637                                 ConfigureVariable(entry_infos, str_completion)
       
   638                                 
       
   639                                 if len(dynamic_pdos[pdo_type]["pdos"]) > 0:
       
   640                                     pdo = dynamic_pdos[pdo_type]["pdos"][0]
       
   641                                 else:
       
   642                                     while dynamic_pdos[pdo_type]["current_index"] in pdos_index:
       
   643                                         dynamic_pdos[pdo_type]["current_index"] += 1
       
   644                                     if dynamic_pdos[pdo_type]["current_index"] >= dynamic_pdos[pdo_type]["max_index"]:
       
   645                                         raise ValueError, _("No more free PDO index available for %s!") % pdo_type
       
   646                                     pdos_index.append(dynamic_pdos[pdo_type]["current_index"])
       
   647                                     
       
   648                                     dynamic_pdos_number += 1
       
   649                                     pdo = {"slave": slave_idx,
       
   650                                            "index": dynamic_pdos[pdo_type]["current_index"],
       
   651                                            "name": "Dynamic PDO %d" % dynamic_pdos_number,
       
   652                                            "type": pdo_type, 
       
   653                                            "entries": [],
       
   654                                            "entries_number": 0,
       
   655                                            "fixed": False}
       
   656                                     dynamic_pdos[pdo_type]["sync_manager"]["pdos_number"] += 1
       
   657                                     dynamic_pdos[pdo_type]["sync_manager"]["pdos"].append(pdo)
       
   658                                     dynamic_pdos[pdo_type]["pdos"].append(pdo)
       
   659                                 
       
   660                                 pdo["entries"].append("    {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
       
   661                                 pdo["entries_number"] += 1
       
   662                                 
       
   663                                 if pdo["entries_number"] == 255:
       
   664                                     dynamic_pdos[pdo_type]["pdos"].pop(0)
       
   665                                 
       
   666                         pdo_offset = 0
       
   667                         entry_offset = 0
       
   668                         for sync_manager_infos in sync_managers:
       
   669                             
       
   670                             for pdo_infos in sync_manager_infos["pdos"]:
       
   671                                 pdo_infos["offset"] = entry_offset
       
   672                                 pdo_entries = pdo_infos["entries"]
   566                                 pdos_infos["pdos_infos"].append(
   673                                 pdos_infos["pdos_infos"].append(
   567                                     ("    {0x%(index).4x, %(entries_number)d, " + 
   674                                     ("    {0x%(index).4x, %(entries_number)d, " + 
   568                                      "slave_%(slave)d_pdo_entries + %(offset)d}, /* %(name)s */") % pdo_infos)
   675                                      "slave_%(slave)d_pdo_entries + %(offset)d}, /* %(name)s */") % pdo_infos)
   569                                 entry_offset += len(entries)
   676                                 entry_offset += len(pdo_entries)
   570                                 pdos_infos["pdos_entries_infos"].extend(entries_infos)
   677                                 pdos_infos["pdos_entries_infos"].extend(pdo_entries)
   571                                 
   678                             
   572                                 
       
   573                         pdo_offset = 0
       
   574                         for sync_manager_infos in sync_managers:
       
   575                             sync_manager_infos["offset"] = pdo_offset
   679                             sync_manager_infos["offset"] = pdo_offset
   576                             pdos_infos["pdos_sync_infos"].append(
   680                             pdos_infos["pdos_sync_infos"].append(
   577                                 ("    {%(index)d, %(sync_manager_type)s, %(pdos_number)d, " + 
   681                                 ("    {%(index)d, %(sync_manager_type)s, %(pdos_number)d, " + 
   578                                  "slave_%(slave)d_pdos + %(offset)d, %(watchdog)s},") % sync_manager_infos)
   682                                  "slave_%(slave)d_pdos + %(offset)d, %(watchdog)s},") % sync_manager_infos)
   579                             pdo_offset += sync_manager_infos["pdos_number"]
   683                             pdo_offset += sync_manager_infos["pdos_number"]
   598 #                 Ethercat Plugin
   702 #                 Ethercat Plugin
   599 #--------------------------------------------------
   703 #--------------------------------------------------
   600 
   704 
   601 EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
   705 EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
   602 
   706 
       
   707 cls = EtherCATInfoClasses["EtherCATInfo.xsd"].get("DeviceType", None)
       
   708 if cls:
       
   709     cls.DataTypes = None
       
   710     
       
   711     def GetProfileDictionaries(self):
       
   712         dictionaries = []
       
   713         
       
   714         for profile in self.getProfile():
       
   715         
       
   716             profile_content = profile.getcontent()
       
   717             if profile_content is None:
       
   718                 return None
       
   719             
       
   720             for content_element in profile_content["value"]:
       
   721                 if content_element["name"] == "Dictionary":
       
   722                     dictionaries.append(content_element["value"])
       
   723                 elif content_element["name"] == "DictionaryFile":
       
   724                     raise ValueError, "DictionaryFile for defining Device Profile is not yet supported!"
       
   725                 
       
   726         return dictionaries
       
   727     setattr(cls, "GetProfileDictionaries", GetProfileDictionaries)
       
   728     
       
   729     def ExtractDataTypes(self):
       
   730         self.DataTypes = {}
       
   731         
       
   732         for dictionary in self.GetProfileDictionaries():
       
   733             
       
   734             datatypes = dictionary.getDataTypes()
       
   735             if datatypes is not None:
       
   736                 
       
   737                 for datatype in datatypes.getDataType():
       
   738                     content = datatype.getcontent()
       
   739                     if content is not None and content["name"] == "SubItem":
       
   740                         self.DataTypes[datatype.getName()] = datatype
       
   741     
       
   742     setattr(cls, "ExtractDataTypes", ExtractDataTypes)
       
   743     
       
   744     def GetEntriesList(self):
       
   745         if self.DataTypes is None:
       
   746             self.ExtractDataTypes()
       
   747         
       
   748         entries = {}
       
   749         
       
   750         for dictionary in self.GetProfileDictionaries():
       
   751             
       
   752             for object in dictionary.getObjects().getObject():
       
   753                 entry_index = object.getIndex().getcontent()
       
   754                 index = ExtractHexDecValue(entry_index)
       
   755                 entry_type = object.getType()
       
   756                 entry_name = ExtractName(object.getName())
       
   757                 
       
   758                 entry_type_infos = self.DataTypes.get(entry_type, None)
       
   759                 if entry_type_infos is not None:
       
   760                     content = entry_type_infos.getcontent()
       
   761                     for subitem in content["value"]:
       
   762                         entry_subidx = subitem.getSubIdx()
       
   763                         if entry_subidx is None:
       
   764                             entry_subidx = "0"
       
   765                         subidx = ExtractHexDecValue(entry_subidx)
       
   766                         subitem_access = ""
       
   767                         subitem_flags = subitem.getFlags()
       
   768                         if subitem_flags is not None:
       
   769                             access = subitem_flags.getAccess()
       
   770                             if access is not None:
       
   771                                 subitem_access = access.getcontent()
       
   772                         entries[(index, subidx)] = {
       
   773                             "Index": entry_index,
       
   774                             "SubIndex": entry_subidx,
       
   775                             "Name": "%s - %s" % 
       
   776                                     (entry_name.decode("utf-8"),
       
   777                                      ExtractName(subitem.getDisplayName(), 
       
   778                                                  subitem.getName()).decode("utf-8")),
       
   779                             "Type": subitem.getType(),
       
   780                             "BitSize": subitem.getBitSize(),
       
   781                             "Access": subitem_access, 
       
   782                             "PDO index": "", 
       
   783                             "PDO name": "", 
       
   784                             "PDO type": ""}
       
   785                 else:
       
   786                     entry_access = ""
       
   787                     entry_flags = object.getFlags()
       
   788                     if entry_flags is not None:
       
   789                         access = entry_flags.getAccess()
       
   790                         if access is not None:
       
   791                             entry_access = access.getcontent()
       
   792                     entries[(index, 0)] = {
       
   793                          "Index": entry_index,
       
   794                          "SubIndex": "0",
       
   795                          "Name": entry_name,
       
   796                          "Type": entry_type,
       
   797                          "BitSize": object.getBitSize(),
       
   798                          "Access": entry_access,
       
   799                          "PDO index": "", 
       
   800                          "PDO name": "", 
       
   801                          "PDO type": ""}
       
   802         
       
   803         for TxPdo in self.getTxPdo():
       
   804             ExtractPdoInfos(TxPdo, "Transmit", entries)
       
   805         for RxPdo in self.getRxPdo():
       
   806             ExtractPdoInfos(RxPdo, "Receive", entries)
       
   807         
       
   808         return entries
       
   809     setattr(cls, "GetEntriesList", GetEntriesList)
       
   810 
       
   811     def GetSyncManagers(self):
       
   812         sync_managers = []
       
   813         for sync_manager in self.getSm():
       
   814             sync_manager_infos = {}
       
   815             for name, value in [("Name", sync_manager.getcontent()),
       
   816                                 ("Start Address", sync_manager.getStartAddress()),
       
   817                                 ("Default Size", sync_manager.getDefaultSize()),
       
   818                                 ("Control Byte", sync_manager.getControlByte()),
       
   819                                 ("Enable", sync_manager.getEnable())]:
       
   820                 if value is None:
       
   821                     value =""
       
   822                 sync_manager_infos[name] = value
       
   823             sync_managers.append(sync_manager_infos)
       
   824         return sync_managers
       
   825     setattr(cls, "GetSyncManagers", GetSyncManagers)
       
   826 
   603 def GroupItemCompare(x, y):
   827 def GroupItemCompare(x, y):
   604     if x["type"] == y["type"]:
   828     if x["type"] == y["type"]:
   605         if x["type"] == ETHERCAT_GROUP:
   829         if x["type"] == ETHERCAT_GROUP:
   606             return x["order"].__cmp__(y["order"])
   830             return x["order"].__cmp__(y["order"])
   607         else:
   831         else:
   623         for name in names:
   847         for name in names:
   624             if name.getLcId() == 1033:
   848             if name.getLcId() == 1033:
   625                 return name.getcontent()
   849                 return name.getcontent()
   626     return default
   850     return default
   627 
   851 
   628 def ExtractPdoInfos(pdo, pdo_type, infos):
   852 def ExtractPdoInfos(pdo, pdo_type, entries):
   629     pdo_index = pdo.getIndex().getcontent()
   853     pdo_index = pdo.getIndex().getcontent()
   630     for entry in pdo.getEntry():
   854     pdo_name = ExtractName(pdo.getName())
   631         infos["variables"].append({"Index": entry.getIndex().getcontent(),
   855     for pdo_entry in pdo.getEntry():
   632                                    "SubIndex": entry.getSubIndex(),
   856         entry_index = pdo_entry.getIndex().getcontent()
   633                                    "Name": ExtractName(entry.getName()),
   857         entry_subindex = pdo_entry.getSubIndex()
   634                                    "Type": entry.getDataType().getcontent(),
   858         index = ExtractHexDecValue(entry_index)
   635                                    "PDO index": pdo_index, 
   859         subindex = ExtractHexDecValue(entry_subindex)
   636                                    "PDO name": ExtractName(pdo.getName()), 
   860         
   637                                    "PDO type": pdo_type})
   861         entry = entries.get((index, subindex), None)
       
   862         if entry is not None:
       
   863             entry["PDO index"] = pdo_index
       
   864             entry["PDO name"] = pdo_name
       
   865             entry["PDO type"] = pdo_type
       
   866         else:
       
   867             if pdo_type == "Transmit":
       
   868                 access = "ro"
       
   869             else:
       
   870                 access = "wo"
       
   871             entries[(index, subindex)] = {
       
   872                 "Index": entry_index,
       
   873                 "SubIndex": entry_subindex,
       
   874                 "Name": ExtractName(pdo_entry.getName()),
       
   875                 "Type": pdo_entry.getDataType().getcontent(),
       
   876                 "Access": access,
       
   877                 "PDO index": pdo_index, 
       
   878                 "PDO name": pdo_name, 
       
   879                 "PDO type": pdo_type}
   638 
   880 
   639 class RootClass:
   881 class RootClass:
   640     
   882     
   641     PlugChildsTypes = [("EthercatNode",_EthercatPlug,"Ethercat Master")]
   883     PlugChildsTypes = [("EthercatNode",_EthercatPlug,"Ethercat Master")]
   642     
   884     
   748     def GetModuleInfos(self, type_infos):
   990     def GetModuleInfos(self, type_infos):
   749         vendor = self.ModulesLibrary.get(type_infos["vendor"], None)
   991         vendor = self.ModulesLibrary.get(type_infos["vendor"], None)
   750         if vendor is not None:
   992         if vendor is not None:
   751             for group_name, group in vendor["groups"].iteritems():
   993             for group_name, group in vendor["groups"].iteritems():
   752                 for device_type, device in group["devices"]:
   994                 for device_type, device in group["devices"]:
   753                     product_code = device.getType().getProductCode()
   995                     product_code = ExtractHexDecValue(device.getType().getProductCode())
   754                     revision_number = device.getType().getRevisionNo()
   996                     revision_number = ExtractHexDecValue(device.getType().getRevisionNo())
   755                     if (device_type == type_infos["device_type"] and
   997                     if (device_type == type_infos["device_type"] and
   756                         product_code == type_infos["product_code"] and
   998                         product_code == ExtractHexDecValue(type_infos["product_code"]) and
   757                         revision_number == type_infos["revision_number"]):
   999                         revision_number == ExtractHexDecValue(type_infos["revision_number"])):
   758                         return device
  1000                         return device
   759         return None
  1001         return None
   760     
  1002