etherlab/EthercatCFileGenerator.py
changeset 2111 f2cffda17d00
child 2116 2b1980a038b1
equal deleted inserted replaced
2110:e8c43f542eb1 2111:f2cffda17d00
       
     1 import os
       
     2 
       
     3 from EthercatSlave import ExtractHexDecValue, DATATYPECONVERSION, ExtractName
       
     4 
       
     5 SLAVE_PDOS_CONFIGURATION_DECLARATION = """
       
     6 /* Slave %(slave)d, "%(device_type)s"
       
     7  * Vendor ID:       0x%(vendor).8x
       
     8  * Product code:    0x%(product_code).8x
       
     9  * Revision number: 0x%(revision_number).8x
       
    10  */
       
    11 
       
    12 ec_pdo_entry_info_t slave_%(slave)d_pdo_entries[] = {
       
    13 %(pdos_entries_infos)s
       
    14 };
       
    15 
       
    16 ec_pdo_info_t slave_%(slave)d_pdos[] = {
       
    17 %(pdos_infos)s
       
    18 };
       
    19 
       
    20 ec_sync_info_t slave_%(slave)d_syncs[] = {
       
    21 %(pdos_sync_infos)s
       
    22     {0xff}
       
    23 };
       
    24 """
       
    25 
       
    26 SLAVE_CONFIGURATION_TEMPLATE = """
       
    27     if (!(slave%(slave)d = ecrt_master_slave_config(master, %(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x))) {
       
    28         SLOGF(LOG_CRITICAL, "Failed to get slave %(device_type)s configuration at alias %(alias)d and position %(position)d.\\n");
       
    29         return -1;
       
    30     }
       
    31 
       
    32     if (ecrt_slave_config_pdos(slave%(slave)d, EC_END, slave_%(slave)d_syncs)) {
       
    33         SLOGF(LOG_CRITICAL, "Failed to configure PDOs for slave %(device_type)s at alias %(alias)d and position %(position)d.\\n");
       
    34         return -1;
       
    35     }
       
    36 """
       
    37 
       
    38 SLAVE_INITIALIZATION_TEMPLATE = """
       
    39     {
       
    40         uint8_t value[%(data_size)d];
       
    41         EC_WRITE_%(data_type)s((uint8_t *)value, %(data)s);
       
    42         if (ecrt_master_sdo_download(master, %(slave)d, 0x%(index).4x, 0x%(subindex).2x, (uint8_t *)value, %(data_size)d, &abort_code)) {
       
    43             SLOGF(LOG_CRITICAL, "Failed to initialize slave %(device_type)s at alias %(alias)d and position %(position)d.\\nError: %%d\\n", abort_code);
       
    44             return -1;
       
    45         }
       
    46     }
       
    47 """
       
    48 
       
    49 SLAVE_OUTPUT_PDO_DEFAULT_VALUE = """
       
    50     {
       
    51         uint8_t value[%(data_size)d];
       
    52         if (ecrt_master_sdo_upload(master, %(slave)d, 0x%(index).4x, 0x%(subindex).2x, (uint8_t *)value, %(data_size)d, &result_size, &abort_code)) {
       
    53             SLOGF(LOG_CRITICAL, "Failed to get default value for output PDO in slave %(device_type)s at alias %(alias)d and position %(position)d.\\nError: %%ud\\n", abort_code);
       
    54             return -1;
       
    55         }
       
    56         %(real_var)s = EC_READ_%(data_type)s((uint8_t *)value);
       
    57     }
       
    58 """
       
    59 
       
    60 def ConfigureVariable(entry_infos, str_completion):
       
    61     entry_infos["data_type"] = DATATYPECONVERSION.get(entry_infos["var_type"], None)
       
    62     if entry_infos["data_type"] is None:
       
    63         raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"]
       
    64     
       
    65     if not entry_infos.get("no_decl", False):
       
    66         if entry_infos.has_key("real_var"):
       
    67             str_completion["located_variables_declaration"].append(
       
    68                 "IEC_%(var_type)s %(real_var)s;" % entry_infos)
       
    69         else:
       
    70             entry_infos["real_var"] = "beremiz" + entry_infos["var_name"]
       
    71             str_completion["located_variables_declaration"].extend(
       
    72                 ["IEC_%(var_type)s %(real_var)s;" % entry_infos,
       
    73                  "IEC_%(var_type)s *%(var_name)s = &%(real_var)s;" % entry_infos])
       
    74         for declaration in entry_infos.get("extra_declarations", []):
       
    75             entry_infos["extra_decl"] = declaration
       
    76             str_completion["located_variables_declaration"].append(
       
    77                  "IEC_%(var_type)s *%(extra_decl)s = &%(real_var)s;" % entry_infos)
       
    78     elif not entry_infos.has_key("real_var"):
       
    79         entry_infos["real_var"] = "beremiz" + entry_infos["var_name"]
       
    80     
       
    81     str_completion["used_pdo_entry_offset_variables_declaration"].append(
       
    82         "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos)
       
    83     
       
    84     if entry_infos["data_type"] == "BIT":
       
    85         str_completion["used_pdo_entry_offset_variables_declaration"].append(
       
    86             "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos)
       
    87         
       
    88         str_completion["used_pdo_entry_configuration"].append(
       
    89              ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + 
       
    90               "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
    91               "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos)
       
    92         
       
    93         if entry_infos["dir"] == "I":
       
    94             str_completion["retrieve_variables"].append(
       
    95               ("    %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
    96                "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos)
       
    97         elif entry_infos["dir"] == "Q":
       
    98             str_completion["publish_variables"].append(
       
    99               ("    EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   100                "slave%(slave)d_%(index).4x_%(subindex).2x_bit, %(real_var)s);") % entry_infos)
       
   101     
       
   102     else:
       
   103         str_completion["used_pdo_entry_configuration"].append(
       
   104             ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + 
       
   105              "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos)
       
   106         
       
   107         if entry_infos["dir"] == "I":
       
   108             str_completion["retrieve_variables"].append(
       
   109                 ("    %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + 
       
   110                  "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos)
       
   111         elif entry_infos["dir"] == "Q":
       
   112             str_completion["publish_variables"].append(
       
   113                 ("    EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
       
   114                  "%(real_var)s);") % entry_infos)
       
   115 
       
   116 def ExclusionSortFunction(x, y):
       
   117     if x["matching"] == y["matching"]:
       
   118         if x["assigned"] and not y["assigned"]:
       
   119             return -1
       
   120         elif not x["assigned"] and y["assigned"]:
       
   121             return 1
       
   122         return cmp(x["count"], y["count"])
       
   123     return -cmp(x["matching"], y["matching"])
       
   124 
       
   125 class _EthercatCFileGenerator:
       
   126     
       
   127     def __init__(self, controler):
       
   128         self.Controler = controler
       
   129         
       
   130         self.Slaves = []
       
   131         self.UsedVariables = {}
       
   132 
       
   133     def __del__(self):
       
   134         self.Controler = None            
       
   135     
       
   136     def DeclareSlave(self, slave_index, slave):
       
   137         self.Slaves.append((slave_index, slave.getInfo().getAutoIncAddr(), slave))
       
   138 
       
   139     def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name, no_decl=False):
       
   140         slave_variables = self.UsedVariables.setdefault(slave_index, {})
       
   141         
       
   142         entry_infos = slave_variables.get((index, subindex), None)
       
   143         if entry_infos is None:
       
   144             slave_variables[(index, subindex)] = {
       
   145                 "infos": (iec_type, dir, name, no_decl, []),
       
   146                 "mapped": False}
       
   147             return name
       
   148         elif entry_infos["infos"][:2] == (iec_type, dir):
       
   149             if name != entry_infos["infos"][2]:
       
   150                 if dir == "I":
       
   151                     entry_infos["infos"][4].append(name)
       
   152                     return entry_infos["infos"][2]
       
   153                 else:
       
   154                     raise ValueError, _("Output variables can't be defined with different locations (%s and %s)") % (entry_infos["infos"][2], name)
       
   155         else:
       
   156             raise ValueError, _("Definition conflict for location \"%s\"") % name 
       
   157         
       
   158     def GenerateCFile(self, filepath, location_str, master_number):
       
   159         
       
   160         # Extract etherlab master code template
       
   161         plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c")
       
   162         plc_etherlab_file = open(plc_etherlab_filepath, 'r')
       
   163         plc_etherlab_code = plc_etherlab_file.read()
       
   164         plc_etherlab_file.close()
       
   165         
       
   166         # Initialize strings for formatting master code template
       
   167         str_completion = {
       
   168             "location": location_str,
       
   169             "master_number": master_number,
       
   170             "located_variables_declaration": [],
       
   171             "used_pdo_entry_offset_variables_declaration": [],
       
   172             "used_pdo_entry_configuration": [],
       
   173             "pdos_configuration_declaration": "",
       
   174             "slaves_declaration": "",
       
   175             "slaves_configuration": "",
       
   176             "slaves_output_pdos_default_values_extraction": "",
       
   177             "slaves_initialization": "",
       
   178             "retrieve_variables": [],
       
   179             "publish_variables": [],
       
   180         }
       
   181         
       
   182         # Initialize variable storing variable mapping state
       
   183         for slave_entries in self.UsedVariables.itervalues():
       
   184             for entry_infos in slave_entries.itervalues():
       
   185                 entry_infos["mapped"] = False
       
   186         
       
   187         # Sort slaves by position (IEC_Channel)
       
   188         self.Slaves.sort()
       
   189         # Initialize dictionary storing alias auto-increment position values
       
   190         alias = {}
       
   191         
       
   192         # Generating code for each slave
       
   193         for (slave_idx, slave_alias, slave) in self.Slaves:
       
   194             type_infos = slave.getType()
       
   195             
       
   196             # Defining slave alias and auto-increment position
       
   197             if alias.get(slave_alias) is not None:
       
   198                 alias[slave_alias] += 1
       
   199             else:
       
   200                 alias[slave_alias] = 0
       
   201             slave_pos = (slave_alias, alias[slave_alias])
       
   202             
       
   203             # Extract slave device informations
       
   204             device, alignment = self.Controler.GetModuleInfos(type_infos)
       
   205             if device is not None:
       
   206                 
       
   207                 # Extract slaves variables to be mapped
       
   208                 slave_variables = self.UsedVariables.get(slave_idx, {})
       
   209                 
       
   210                 # Extract slave device object dictionary entries
       
   211                 device_entries = device.GetEntriesList()
       
   212                 
       
   213                 # Adding code for declaring slave in master code template strings
       
   214                 for element in ["vendor", "product_code", "revision_number"]:
       
   215                     type_infos[element] = ExtractHexDecValue(type_infos[element])
       
   216                 type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos)))
       
   217                 
       
   218                 # Extract slave device CoE informations
       
   219                 device_coe = device.getCoE()
       
   220                 if device_coe is not None:
       
   221                     
       
   222                     # If device support CanOpen over Ethernet, adding code for calling 
       
   223                     # init commands when initializing slave in master code template strings
       
   224                     initCmds = []
       
   225                     for initCmd in device_coe.getInitCmd():
       
   226                         initCmds.append({
       
   227                             "Index": ExtractHexDecValue(initCmd.getIndex()),
       
   228                             "Subindex": ExtractHexDecValue(initCmd.getSubIndex()),
       
   229                             "Value": initCmd.getData().getcontent()})
       
   230                     initCmds.extend(slave.getStartupCommands())
       
   231                     for initCmd in initCmds:
       
   232                         index = initCmd["Index"]
       
   233                         subindex = initCmd["Subindex"]
       
   234                         entry = device_entries.get((index, subindex), None)
       
   235                         if entry is not None:
       
   236                             data_size = entry["BitSize"] / 8
       
   237                             data_str = ("0x%%.%dx" % (data_size * 2)) % initCmd["Value"]
       
   238                             init_cmd_infos = {
       
   239                                 "index": index,
       
   240                                 "subindex": subindex,
       
   241                                 "data": data_str,
       
   242                                 "data_type": DATATYPECONVERSION.get(entry["Type"]),
       
   243                                 "data_size": data_size
       
   244                             }
       
   245                             init_cmd_infos.update(type_infos)
       
   246                             str_completion["slaves_initialization"] += SLAVE_INITIALIZATION_TEMPLATE % init_cmd_infos
       
   247                 
       
   248                     # Extract slave device PDO configuration capabilities
       
   249                     PdoAssign = device_coe.getPdoAssign()
       
   250                     PdoConfig = device_coe.getPdoConfig()
       
   251                 else:
       
   252                     PdoAssign = PdoConfig = False
       
   253                 
       
   254                 # Test if slave has a configuration or need one
       
   255                 if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0 and PdoConfig and PdoAssign:
       
   256                     
       
   257                     str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos
       
   258                     str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos
       
   259                     
       
   260                     # Initializing 
       
   261                     pdos_infos = {
       
   262                         "pdos_entries_infos": [],
       
   263                         "pdos_infos": [],
       
   264                         "pdos_sync_infos": [], 
       
   265                     }
       
   266                     pdos_infos.update(type_infos)
       
   267                     
       
   268                     sync_managers = []
       
   269                     for sync_manager_idx, sync_manager in enumerate(device.getSm()):
       
   270                         sync_manager_infos = {
       
   271                             "index": sync_manager_idx, 
       
   272                             "name": sync_manager.getcontent(),
       
   273                             "slave": slave_idx,
       
   274                             "pdos": [], 
       
   275                             "pdos_number": 0,
       
   276                         }
       
   277                         
       
   278                         sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte())
       
   279                         sync_manager_direction = sync_manager_control_byte & 0x0c
       
   280                         sync_manager_watchdog = sync_manager_control_byte & 0x40
       
   281                         if sync_manager_direction:
       
   282                             sync_manager_infos["sync_manager_type"] = "EC_DIR_OUTPUT"
       
   283                         else:
       
   284                             sync_manager_infos["sync_manager_type"] = "EC_DIR_INPUT"
       
   285                         if sync_manager_watchdog:
       
   286                             sync_manager_infos["watchdog"] = "EC_WD_ENABLE"
       
   287                         else:
       
   288                             sync_manager_infos["watchdog"] = "EC_WD_DISABLE"
       
   289                         
       
   290                         sync_managers.append(sync_manager_infos)
       
   291                     
       
   292                     pdos_index = []
       
   293                     exclusive_pdos = {}
       
   294                     selected_pdos = []
       
   295                     for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] +
       
   296                                           [(pdo, "Outputs") for pdo in device.getRxPdo()]):
       
   297                         
       
   298                         pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
       
   299                         pdos_index.append(pdo_index)
       
   300                         
       
   301                         excluded_list = pdo.getExclude()
       
   302                         if len(excluded_list) > 0:
       
   303                             exclusion_list = [pdo_index]
       
   304                             for excluded in excluded_list:
       
   305                                 exclusion_list.append(ExtractHexDecValue(excluded.getcontent()))
       
   306                             exclusion_list.sort()
       
   307                             
       
   308                             exclusion_scope = exclusive_pdos.setdefault(tuple(exclusion_list), [])
       
   309                             
       
   310                             entries = pdo.getEntry()
       
   311                             pdo_mapping_match = {
       
   312                                 "index": pdo_index, 
       
   313                                 "matching": 0, 
       
   314                                 "count": len(entries), 
       
   315                                 "assigned": pdo.getSm() is not None
       
   316                             }
       
   317                             exclusion_scope.append(pdo_mapping_match)
       
   318                             
       
   319                             for entry in entries:
       
   320                                 index = ExtractHexDecValue(entry.getIndex().getcontent())
       
   321                                 subindex = ExtractHexDecValue(entry.getSubIndex())
       
   322                                 if slave_variables.get((index, subindex), None) is not None:
       
   323                                     pdo_mapping_match["matching"] += 1
       
   324                         
       
   325                         elif pdo.getMandatory():
       
   326                             selected_pdos.append(pdo_index)
       
   327                     
       
   328                     excluded_pdos = []
       
   329                     for exclusion_scope in exclusive_pdos.itervalues():
       
   330                         exclusion_scope.sort(ExclusionSortFunction)
       
   331                         start_excluding_index = 0
       
   332                         if exclusion_scope[0]["matching"] > 0:
       
   333                             selected_pdos.append(exclusion_scope[0]["index"])
       
   334                             start_excluding_index = 1
       
   335                         excluded_pdos.extend([pdo["index"] for pdo in exclusion_scope[start_excluding_index:] if PdoAssign or not pdo["assigned"]])
       
   336                     
       
   337                     for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] +
       
   338                                           [(pdo, "Outputs") for pdo in device.getRxPdo()]):
       
   339                         entries = pdo.getEntry()
       
   340                         
       
   341                         pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
       
   342                         if pdo_index in excluded_pdos:
       
   343                             continue
       
   344                         
       
   345                         pdo_needed = pdo_index in selected_pdos
       
   346                         
       
   347                         entries_infos = []
       
   348                         
       
   349                         for entry in entries:
       
   350                             index = ExtractHexDecValue(entry.getIndex().getcontent())
       
   351                             subindex = ExtractHexDecValue(entry.getSubIndex())
       
   352                             entry_infos = {
       
   353                                 "index": index,
       
   354                                 "subindex": subindex,
       
   355                                 "name": ExtractName(entry.getName()),
       
   356                                 "bitlen": entry.getBitLen(),
       
   357                             }
       
   358                             entry_infos.update(type_infos)
       
   359                             entries_infos.append("    {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
       
   360                             
       
   361                             entry_declaration = slave_variables.get((index, subindex), None)
       
   362                             if entry_declaration is not None and not entry_declaration["mapped"]:
       
   363                                 pdo_needed = True
       
   364                                 
       
   365                                 entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], 
       
   366                                                             entry_declaration["infos"])))
       
   367                                 entry_declaration["mapped"] = True
       
   368                                 
       
   369                                 entry_type = entry.getDataType().getcontent()
       
   370                                 if entry_infos["var_type"] != entry_type:
       
   371                                     message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
       
   372                                     if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
       
   373                                         self.Controler.GetSizeOfType(entry_type)):
       
   374                                         raise ValueError, message
       
   375                                     else:
       
   376                                         self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n")
       
   377                                 
       
   378                                 if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or 
       
   379                                     entry_infos["dir"] == "Q" and pdo_type != "Outputs"):
       
   380                                     raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
       
   381                                 
       
   382                                 ConfigureVariable(entry_infos, str_completion)
       
   383                             
       
   384                             elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None:
       
   385                                 data_type = entry.getDataType().getcontent()
       
   386                                 entry_infos["dir"] = "Q"
       
   387                                 entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8)
       
   388                                 entry_infos["data_type"] = DATATYPECONVERSION.get(data_type)
       
   389                                 entry_infos["var_type"] = data_type
       
   390                                 entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos
       
   391                                 
       
   392                                 ConfigureVariable(entry_infos, str_completion)
       
   393                                 
       
   394                                 str_completion["slaves_output_pdos_default_values_extraction"] += \
       
   395                                     SLAVE_OUTPUT_PDO_DEFAULT_VALUE % entry_infos
       
   396                                 
       
   397                         if pdo_needed:
       
   398                             for excluded in pdo.getExclude():
       
   399                                 excluded_index = ExtractHexDecValue(excluded.getcontent())
       
   400                                 if excluded_index not in excluded_pdos:
       
   401                                     excluded_pdos.append(excluded_index)
       
   402                             
       
   403                             sm = pdo.getSm()
       
   404                             if sm is None:
       
   405                                 for sm_idx, sync_manager in enumerate(sync_managers):
       
   406                                     if sync_manager["name"] == pdo_type:
       
   407                                         sm = sm_idx
       
   408                             if sm is None:
       
   409                                 raise ValueError, _("No sync manager available for %s pdo!") % pdo_type
       
   410                                 
       
   411                             sync_managers[sm]["pdos_number"] += 1
       
   412                             sync_managers[sm]["pdos"].append(
       
   413                                 {"slave": slave_idx,
       
   414                                  "index": pdo_index,
       
   415                                  "name": ExtractName(pdo.getName()),
       
   416                                  "type": pdo_type, 
       
   417                                  "entries": entries_infos,
       
   418                                  "entries_number": len(entries_infos),
       
   419                                  "fixed": pdo.getFixed() == True})
       
   420                 
       
   421                     if PdoConfig and PdoAssign:
       
   422                         dynamic_pdos = {}
       
   423                         dynamic_pdos_number = 0
       
   424                         for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), 
       
   425                                                                ("Outputs", 0x1a00, 0x1C00)]:
       
   426                             for sync_manager in sync_managers:
       
   427                                 if sync_manager["name"] == category:
       
   428                                     category_infos = dynamic_pdos.setdefault(category, {})
       
   429                                     category_infos["sync_manager"] = sync_manager
       
   430                                     category_infos["pdos"] = [pdo for pdo in category_infos["sync_manager"]["pdos"] 
       
   431                                                               if not pdo["fixed"] and pdo["type"] == category]
       
   432                                     category_infos["current_index"] = min_index
       
   433                                     category_infos["max_index"] = max_index
       
   434                                     break
       
   435                         
       
   436                         for (index, subindex), entry_declaration in slave_variables.iteritems():
       
   437                             
       
   438                             if not entry_declaration["mapped"]:
       
   439                                 entry = device_entries.get((index, subindex), None)
       
   440                                 if entry is None:
       
   441                                     raise ValueError, _("Unknown entry index 0x%4.4x, subindex 0x%2.2x for device %s") % \
       
   442                                                      (index, subindex, type_infos["device_type"])
       
   443                                 
       
   444                                 entry_infos = {
       
   445                                     "index": index,
       
   446                                     "subindex": subindex,
       
   447                                     "name": entry["Name"],
       
   448                                     "bitlen": entry["BitSize"],
       
   449                                 }
       
   450                                 entry_infos.update(type_infos)
       
   451                                 
       
   452                                 entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], 
       
   453                                                             entry_declaration["infos"])))
       
   454                                 entry_declaration["mapped"] = True
       
   455                                 
       
   456                                 if entry_infos["var_type"] != entry["Type"]:
       
   457                                     message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
       
   458                                     if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
       
   459                                         self.Controler.GetSizeOfType(entry["Type"])):
       
   460                                         raise ValueError, message
       
   461                                     else:
       
   462                                         self.Controler.GetCTRoot().logger.write_warning(message + "\n")
       
   463                                 
       
   464                                 if entry_infos["dir"] == "I" and entry["PDOMapping"] in ["T", "RT"]:
       
   465                                     pdo_type = "Inputs"
       
   466                                 elif entry_infos["dir"] == "Q" and entry["PDOMapping"] in ["R", "RT"]:
       
   467                                     pdo_type = "Outputs"
       
   468                                 else:
       
   469                                     raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
       
   470                                 
       
   471                                 if not dynamic_pdos.has_key(pdo_type):
       
   472                                     raise ValueError, _("No Sync manager defined for %s!") % pdo_type
       
   473                                 
       
   474                                 ConfigureVariable(entry_infos, str_completion)
       
   475                                 
       
   476                                 if len(dynamic_pdos[pdo_type]["pdos"]) > 0:
       
   477                                     pdo = dynamic_pdos[pdo_type]["pdos"][0]
       
   478                                 else:
       
   479                                     while dynamic_pdos[pdo_type]["current_index"] in pdos_index:
       
   480                                         dynamic_pdos[pdo_type]["current_index"] += 1
       
   481                                     if dynamic_pdos[pdo_type]["current_index"] >= dynamic_pdos[pdo_type]["max_index"]:
       
   482                                         raise ValueError, _("No more free PDO index available for %s!") % pdo_type
       
   483                                     pdos_index.append(dynamic_pdos[pdo_type]["current_index"])
       
   484                                     
       
   485                                     dynamic_pdos_number += 1
       
   486                                     pdo = {"slave": slave_idx,
       
   487                                            "index": dynamic_pdos[pdo_type]["current_index"],
       
   488                                            "name": "Dynamic PDO %d" % dynamic_pdos_number,
       
   489                                            "type": pdo_type, 
       
   490                                            "entries": [],
       
   491                                            "entries_number": 0,
       
   492                                            "fixed": False}
       
   493                                     dynamic_pdos[pdo_type]["sync_manager"]["pdos_number"] += 1
       
   494                                     dynamic_pdos[pdo_type]["sync_manager"]["pdos"].append(pdo)
       
   495                                     dynamic_pdos[pdo_type]["pdos"].append(pdo)
       
   496                                 
       
   497                                 pdo["entries"].append("    {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
       
   498                                 if entry_infos["bitlen"] < alignment:
       
   499                                     print (alignment, entry_infos["bitlen"])
       
   500                                     pdo["entries"].append("    {0x0000, 0x00, %d}, /* None */" % (alignment - entry_infos["bitlen"]))
       
   501                                 pdo["entries_number"] += 1
       
   502                                 
       
   503                                 if pdo["entries_number"] == 255:
       
   504                                     dynamic_pdos[pdo_type]["pdos"].pop(0)
       
   505                     
       
   506                     pdo_offset = 0
       
   507                     entry_offset = 0
       
   508                     for sync_manager_infos in sync_managers:
       
   509                     
       
   510                         for pdo_infos in sync_manager_infos["pdos"]:
       
   511                             pdo_infos["offset"] = entry_offset
       
   512                             pdo_entries = pdo_infos["entries"]
       
   513                             pdos_infos["pdos_infos"].append(
       
   514                                 ("    {0x%(index).4x, %(entries_number)d, " + 
       
   515                                  "slave_%(slave)d_pdo_entries + %(offset)d}, /* %(name)s */") % pdo_infos)
       
   516                             entry_offset += len(pdo_entries)
       
   517                             pdos_infos["pdos_entries_infos"].extend(pdo_entries)
       
   518                         
       
   519                         sync_manager_infos["offset"] = pdo_offset
       
   520                         pdo_offset_shift = sync_manager_infos["pdos_number"]
       
   521                         pdos_infos["pdos_sync_infos"].append(
       
   522                             ("    {%(index)d, %(sync_manager_type)s, %(pdos_number)d, " + 
       
   523                              ("slave_%(slave)d_pdos + %(offset)d" if pdo_offset_shift else "NULL") +
       
   524                              ", %(watchdog)s},") % sync_manager_infos)
       
   525                         pdo_offset += pdo_offset_shift  
       
   526                     
       
   527                     for element in ["pdos_entries_infos", "pdos_infos", "pdos_sync_infos"]:
       
   528                         pdos_infos[element] = "\n".join(pdos_infos[element])
       
   529                     
       
   530                     str_completion["pdos_configuration_declaration"] += SLAVE_PDOS_CONFIGURATION_DECLARATION % pdos_infos
       
   531                 
       
   532                 for (index, subindex), entry_declaration in slave_variables.iteritems():
       
   533                     if not entry_declaration["mapped"]:
       
   534                         message = _("Entry index 0x%4.4x, subindex 0x%2.2x not mapped for device %s") % \
       
   535                                         (index, subindex, type_infos["device_type"])
       
   536                         self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n")
       
   537                     
       
   538         for element in ["used_pdo_entry_offset_variables_declaration", 
       
   539                         "used_pdo_entry_configuration", 
       
   540                         "located_variables_declaration", 
       
   541                         "retrieve_variables", 
       
   542                         "publish_variables"]:
       
   543             str_completion[element] = "\n".join(str_completion[element])
       
   544         
       
   545         etherlabfile = open(filepath, 'w')
       
   546         etherlabfile.write(plc_etherlab_code % str_completion)
       
   547         etherlabfile.close()