plugins/canfestival/config_utils.py
changeset 340 651b8fb572e7
parent 307 b80d3a84b8bf
child 361 331d698e1118
equal deleted inserted replaced
339:6dbde4a0c31d 340:651b8fb572e7
    34 RPDO = 1
    34 RPDO = 1
    35 TPDO = 2
    35 TPDO = 2
    36 
    36 
    37 SlavePDOType = {"I" : TPDO, "Q" : RPDO}
    37 SlavePDOType = {"I" : TPDO, "Q" : RPDO}
    38 InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
    38 InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
       
    39 PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
       
    40 PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
    39 
    41 
    40 VariableIncrement = 0x100
    42 VariableIncrement = 0x100
    41 VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
    43 VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
    42 VariableDirText = {TPDO : "__I", RPDO : "__Q"}
    44 VariableDirText = {TPDO : "__I", RPDO : "__Q"}
    43 VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
    45 VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
    44 
    46 
    45 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
    47 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
       
    48 
       
    49 #-------------------------------------------------------------------------------
       
    50 #                  Specific exception for PDO mapping errors
       
    51 #-------------------------------------------------------------------------------
       
    52 
       
    53 class PDOmappingException(Exception):
       
    54     pass
       
    55 
    46 
    56 
    47 def LE_to_BE(value, size):
    57 def LE_to_BE(value, size):
    48     """
    58     """
    49     Convert Little Endian to Big Endian
    59     Convert Little Endian to Big Endian
    50     @param value: value expressed in integer
    60     @param value: value expressed in integer
   107     @param pdomapping: list of PDO mappings
   117     @param pdomapping: list of PDO mappings
   108     @return: a tuple of value and number of parameters to add to DCF 
   118     @return: a tuple of value and number of parameters to add to DCF 
   109     """
   119     """
   110     
   120     
   111     # Create entry for RPDO or TPDO parameters and Disable PDO
   121     # Create entry for RPDO or TPDO parameters and Disable PDO
   112     dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE((0x80000000 + cobid), 4)
   122     dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
   113     # Set Transmit type synchrone
   123     # Set Transmit type synchrone
   114     dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
   124     dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
   115     # Re-Enable PDO
   125     # Re-Enable PDO
   116     #         ---- INDEX -----   --- SUBINDEX ----   ----- SIZE ------   ------ DATA ------
   126     #         ---- INDEX -----   --- SUBINDEX ----   ----- SIZE ------   ------ DATA ------
   117     dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x00000000 + cobid, 4)
   127     dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
   118     nbparams = 3
   128     nbparams = 3
   119     # Map Variables
   129     if len(pdomapping) > 0:
   120     for subindex, (name, loc_infos) in enumerate(pdomapping):
   130         dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
   121         value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
       
   122         dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
       
   123         nbparams += 1
   131         nbparams += 1
       
   132         # Map Variables
       
   133         for subindex, (name, loc_infos) in enumerate(pdomapping):
       
   134             value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
       
   135             dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
       
   136             nbparams += 1
   124     return dcfdata, nbparams
   137     return dcfdata, nbparams
   125 
   138 
   126 class ConciseDCFGenerator:
   139 class ConciseDCFGenerator:
   127 
   140 
   128     def __init__(self, nodelist, nodename):
   141     def __init__(self, nodelist, nodename):
   132         self.LocationsNotMapped = {}
   145         self.LocationsNotMapped = {}
   133         # Dictionary of location informations classed by name
   146         # Dictionary of location informations classed by name
   134         self.MasterMapping = {}
   147         self.MasterMapping = {}
   135         # List of COB IDs available
   148         # List of COB IDs available
   136         self.ListCobIDAvailable = range(0x180, 0x580)
   149         self.ListCobIDAvailable = range(0x180, 0x580)
   137         self.SlavesPdoNumber = {}
       
   138         # Dictionary of mapping value where unexpected variables are stored
   150         # Dictionary of mapping value where unexpected variables are stored
   139         self.TrashVariables = {}
   151         self.TrashVariables = {}
   140         # Dictionary of pointed variables
   152         # Dictionary of pointed variables
   141         self.PointedVariables = {}
   153         self.PointedVariables = {}
   142         
   154         
   204             node = nodeinfos["Node"]
   216             node = nodeinfos["Node"]
   205             node.SetNodeID(nodeid)
   217             node.SetNodeID(nodeid)
   206             
   218             
   207             RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
   219             RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
   208             
   220             
   209             # Store the number of TPDO and RPDO for this node
       
   210             self.SlavesPdoNumber[nodeid] = {RPDO : RPDOnumber, TPDO : TPDOnumber}
       
   211             
       
   212             # Get Slave's default SDO server parameters
   221             # Get Slave's default SDO server parameters
   213             RSDO_cobid = node.GetEntry(0x1200,0x01)
   222             RSDO_cobid = node.GetEntry(0x1200,0x01)
   214             if not RSDO_cobid:
   223             if not RSDO_cobid:
   215                 RSDO_cobid = 0x600 + nodeid
   224                 RSDO_cobid = 0x600 + nodeid
   216             TSDO_cobid = node.GetEntry(0x1200,0x02)
   225             TSDO_cobid = node.GetEntry(0x1200,0x02)
   227     def GetMasterNode(self):
   236     def GetMasterNode(self):
   228         """
   237         """
   229         Return MasterNode.
   238         Return MasterNode.
   230         """
   239         """
   231         return self.MasterNode
   240         return self.MasterNode
   232 
       
   233     
       
   234     def GetNewCobID(self, nodeid, type):
       
   235         """
       
   236         Select a COB ID from the list of those available
       
   237         @param nodeid: id of the slave (int)
       
   238         @param type: type of PDO (RPDO or TPDO)
       
   239         @return: a tuple of the COD ID and PDO index or None
       
   240         """
       
   241         # Verify that there is still some cobid available
       
   242         if len(self.ListCobIDAvailable) == 0:
       
   243             return None
       
   244         
       
   245         # Get the number of PDO of the type given for the node
       
   246         nbSlavePDO = self.SlavesPdoNumber[nodeid][type]
       
   247         if type == RPDO:
       
   248             if nbSlavePDO < 4:
       
   249                 # For the four first RPDO -> cobid = 0x200 + ( numPdo parameters * 0x100) + nodeid
       
   250                 newcobid = (0x200 + nbSlavePDO * 0x100 + nodeid)
       
   251                 # Return calculated cobid if it's still available
       
   252                 if newcobid in self.ListCobIDAvailable:
       
   253                     self.ListCobIDAvailable.remove(newcobid)
       
   254                     return newcobid, 0x1400 + nbSlavePDO
       
   255             # Return the first cobid available if no cobid found
       
   256             return self.ListCobIDAvailable.pop(0), 0x1400 + nbSlavePDO
       
   257     
       
   258         elif type == TPDO:
       
   259             if nbSlavePDO < 4:
       
   260                 # For the four first TPDO -> cobid = 0x180 + ( numPdo parameters * 0x100) + nodeid
       
   261                 newcobid = (0x180 + nbSlavePDO * 0x100 + nodeid)
       
   262                 # Return calculated cobid if it's still available
       
   263                 if newcobid in self.ListCobIDAvailable:
       
   264                     self.ListCobIDAvailable.remove(newcobid)
       
   265                     return newcobid, 0x1800 + nbSlavePDO
       
   266             # Return the first cobid available if no cobid found
       
   267             return self.ListCobIDAvailable.pop(0), 0x1800 + nbSlavePDO
       
   268         
       
   269         return None
       
   270     
       
   271     
   241     
   272     def AddParamsToDCF(self, nodeid, data, nbparams):
   242     def AddParamsToDCF(self, nodeid, data, nbparams):
   273         """
   243         """
   274         Add entry to DCF, for the requested nodeID
   244         Add entry to DCF, for the requested nodeID
   275         @param nodeid: id of the slave (int)
   245         @param nodeid: id of the slave (int)
   289         # Build new DCF
   259         # Build new DCF
   290         dcf = LE_to_BE(nbparams, 0x04) + data
   260         dcf = LE_to_BE(nbparams, 0x04) + data
   291         # Set new DCF for slave
   261         # Set new DCF for slave
   292         self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
   262         self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
   293     
   263     
   294     def AddPDOMapping(self, nodeid, pdotype, pdomapping, sync_TPDOs):
   264     def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
       
   265         """
       
   266         Search a not configured PDO for a slave
       
   267         @param node: the slave node object
       
   268         @param pdotype: type of PDO to generated (RPDO or TPDO)
       
   269         @param start_index: Index where search must start (default: None)
       
   270         @return tuple of PDO index, COB ID and number of subindex defined
       
   271         """
       
   272         # If no start_index defined, start with PDOtype base index
       
   273         if start_index is None:
       
   274             index = PDOTypeBaseIndex[pdotype]
       
   275         else:
       
   276             index = start_index
       
   277         
       
   278         # Search for all PDO possible index until find a configurable PDO
       
   279         # starting from start_index
       
   280         while index < PDOTypeBaseIndex[pdotype] + 0x200:
       
   281             values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
       
   282             if values != None and values[0] > 0:
       
   283                 # Check that all subindex upper than 0 equal 0 => configurable PDO
       
   284                 if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
       
   285                     cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
       
   286                     # If no COB ID defined in PDO, generate a new one (not used)
       
   287                     if cobid == 0:
       
   288                         if len(self.ListCobIDAvailable) == 0:
       
   289                             return None
       
   290                         # Calculate COB ID from standard values
       
   291                         if index < PDOTypeBaseIndex[pdotype] + 4:
       
   292                             cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
       
   293                         if cobid not in self.ListCobIDAvailable:
       
   294                             cobid = self.ListCobIDAvailable.pop(0)
       
   295                     return index, cobid, values[0]
       
   296             index += 1
       
   297         return None
       
   298     
       
   299     def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
   295         """
   300         """
   296         Record a new mapping request for a slave, and add related slave config to the DCF
   301         Record a new mapping request for a slave, and add related slave config to the DCF
   297         @param nodeid: id of the slave (int)
   302         @param nodeid: id of the slave (int)
   298         @param pdotype: type of PDO to generated (RPDO or TPDO)
   303         @param pdotype: type of PDO to generated (RPDO or TPDO)
   299         @param pdomapping: list od variables to map with PDO
   304         @param pdomapping: list od variables to map with PDO
   300         """
   305         """
   301         # Get a new cob id
   306         # Add an entry to MasterMapping
   302         result = self.GetNewCobID(nodeid, pdotype)
   307         self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], 
   303         if result:
   308             "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
   304             new_cobid, new_idx = result
   309         
   305             
   310         # Return the data to add to DCF
   306             # Increment the number of PDO of this type for node
   311         if sync_TPDOs:
   307             self.SlavesPdoNumber[nodeid][pdotype] += 1
   312             return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
   308             
   313         else:
   309             # Add an entry to MasterMapping
   314             return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
   310             self.MasterMapping[new_cobid] = {"type" : InvertPDOType[pdotype], 
       
   311                 "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
       
   312             
       
   313             # Return the data to add to DCF
       
   314             if sync_TPDOs:
       
   315                 return GeneratePDOMappingDCF(new_idx, new_cobid, 0x01, pdomapping)
       
   316             else:
       
   317                 return GeneratePDOMappingDCF(new_idx, new_cobid, 0xFF, pdomapping)
       
   318         return 0, ""
   315         return 0, ""
   319     
   316     
   320     def GenerateDCF(self, locations, current_location, sync_TPDOs):
   317     def GenerateDCF(self, locations, current_location, sync_TPDOs):
   321         """
   318         """
   322         Generate Concise DCF of MasterNode for the locations list given
   319         Generate Concise DCF of MasterNode for the locations list given
   333         for location in locations:
   330         for location in locations:
   334             COlocationtype = IECToCOType[location["IEC_TYPE"]]
   331             COlocationtype = IECToCOType[location["IEC_TYPE"]]
   335             name = location["NAME"]
   332             name = location["NAME"]
   336             if name in self.IECLocations:
   333             if name in self.IECLocations:
   337                 if self.IECLocations[name]["type"] != COlocationtype:
   334                 if self.IECLocations[name]["type"] != COlocationtype:
   338                     raise ValueError, "Conflict type for location \"%s\"" % name 
   335                     raise PDOmappingException, "Conflict type for location \"%s\"" % name 
   339             else:
   336             else:
   340                 # Get only the part of the location that concern this node
   337                 # Get only the part of the location that concern this node
   341                 loc = location["LOC"][len(current_location):]
   338                 loc = location["LOC"][len(current_location):]
   342                 # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
   339                 # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
   343                 if len(loc) not in (2, 3, 4):
   340                 if len(loc) not in (2, 3, 4):
   344                     raise ValueError, "Bad location size : %s"%str(loc)
   341                     raise PDOmappingException, "Bad location size : %s"%str(loc)
   345                 elif len(loc) == 2:
   342                 elif len(loc) == 2:
   346                     continue
   343                     continue
   347                 
   344                 
   348                 direction = location["DIR"]
   345                 direction = location["DIR"]
   349                 
   346                 
   352                 # Extract and check nodeid
   349                 # Extract and check nodeid
   353                 nodeid, index, subindex = loc[:3]
   350                 nodeid, index, subindex = loc[:3]
   354                 
   351                 
   355                 # Check Id is in slave node list
   352                 # Check Id is in slave node list
   356                 if nodeid not in self.NodeList.SlaveNodes.keys():
   353                 if nodeid not in self.NodeList.SlaveNodes.keys():
   357                     raise ValueError, "Non existing node ID : %d (variable %s)" % (nodeid,name)
   354                     raise PDOmappingException, "Non existing node ID : %d (variable %s)" % (nodeid,name)
   358                 
   355                 
   359                 # Get the model for this node (made from EDS)
   356                 # Get the model for this node (made from EDS)
   360                 node = self.NodeList.SlaveNodes[nodeid]["Node"]
   357                 node = self.NodeList.SlaveNodes[nodeid]["Node"]
   361                 
   358                 
   362                 # Extract and check index and subindex
   359                 # Extract and check index and subindex
   363                 if not node.IsEntry(index, subindex):
   360                 if not node.IsEntry(index, subindex):
   364                     raise ValueError, "No such index/subindex (%x,%x) in ID : %d (variable %s)" % (index,subindex,nodeid,name)
   361                     raise PDOmappingException, "No such index/subindex (%x,%x) in ID : %d (variable %s)" % (index,subindex,nodeid,name)
   365                 
   362                 
   366                 # Get the entry info
   363                 # Get the entry info
   367                 subentry_infos = node.GetSubentryInfos(index, subindex)
   364                 subentry_infos = node.GetSubentryInfos(index, subindex)
   368                 
   365                 
   369                 # If a PDO mappable
   366                 # If a PDO mappable
   370                 if subentry_infos and subentry_infos["pdo"]:
   367                 if subentry_infos and subentry_infos["pdo"]:
   371                     if sizelocation == "X" and len(loc) > 3:
   368                     if sizelocation == "X" and len(loc) > 3:
   372                         numbit = loc[3]
   369                         numbit = loc[3]
   373                     elif sizelocation != "X" and len(loc) > 3:
   370                     elif sizelocation != "X" and len(loc) > 3:
   374                         raise ValueError, "Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))" % (name,nodeid,index,subindex)
   371                         raise PDOmappingException, "Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))" % (name,nodeid,index,subindex)
   375                     else:
   372                     else:
   376                         numbit = None
   373                         numbit = None
   377                     
   374                     
   378                     if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
   375                     if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
   379                         raise ValueError, "Invalid type \"%s\"-> %d != %d  for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
   376                         raise PDOmappingException, "Invalid type \"%s\"-> %d != %d  for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
   380                     
   377                     
   381                     typeinfos = node.GetEntryInfos(COlocationtype)
   378                     typeinfos = node.GetEntryInfos(COlocationtype)
   382                     self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
   379                     self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
   383                                                 "nodeid": nodeid, "index": index,"subindex": subindex,
   380                                                 "nodeid": nodeid, "index": index,"subindex": subindex,
   384                                                 "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
   381                                                 "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
   385                 else:
   382                 else:
   386                     raise ValueError, "Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))" % (name,nodeid,index,subindex)
   383                     raise PDOmappingException, "Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))" % (name,nodeid,index,subindex)
   387         
   384         
   388         #-------------------------------------------------------------------------------
   385         #-------------------------------------------------------------------------------
   389         #                         Search for locations already mapped
   386         #                         Search for locations already mapped
   390         #-------------------------------------------------------------------------------
   387         #-------------------------------------------------------------------------------
   391         
   388         
   448             nbparams = 0
   445             nbparams = 0
   449             dataparams = ""
   446             dataparams = ""
   450             
   447             
   451             # Generate the best PDO mapping for each type of PDO
   448             # Generate the best PDO mapping for each type of PDO
   452             for pdotype in (TPDO, RPDO):
   449             for pdotype in (TPDO, RPDO):
   453                 pdosize = 0
   450                 if len(locations[pdotype]) > 0:
   454                 pdomapping = []
   451                     pdosize = 0
   455                 for name, loc_infos in locations[pdotype]:
   452                     pdomapping = []
   456                     pdosize += loc_infos["size"]
   453                     result = self.GetEmptyPDO(nodeid, pdotype)
   457                     # If pdo's size > 64 bits
   454                     if result is None:
   458                     if pdosize > 64:
   455                         raise PDOmappingException, "Impossible to define PDO mapping for node %02x"%nodeid
       
   456                     pdoindex, pdocobid, pdonbparams = result
       
   457                     for name, loc_infos in locations[pdotype]:
       
   458                         pdosize += loc_infos["size"]
       
   459                         # If pdo's size > 64 bits
       
   460                         if pdosize > 64 or len(pdomapping) >= pdonbparams:
       
   461                             # Generate a new PDO Mapping
       
   462                             data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
       
   463                             dataparams += data
       
   464                             nbparams += nbaddedparams
       
   465                             pdosize = loc_infos["size"]
       
   466                             pdomapping = [(name, loc_infos)]
       
   467                             result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
       
   468                             if result is None:
       
   469                                 raise PDOmappingException, "Impossible to define PDO mapping for node %02x"%nodeid
       
   470                             pdoindex, pdocobid, pdonbparams = result
       
   471                         else:
       
   472                             pdomapping.append((name, loc_infos))
       
   473                     # If there isn't locations yet but there is still a PDO to generate
       
   474                     if len(pdomapping) > 0:
   459                         # Generate a new PDO Mapping
   475                         # Generate a new PDO Mapping
   460                         data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdomapping, sync_TPDOs)
   476                         data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
   461                         dataparams += data
   477                         dataparams += data
   462                         nbparams += nbaddedparams
   478                         nbparams += nbaddedparams
   463                         pdosize = loc_infos["size"]
   479                 
   464                         pdomapping = [(name, loc_infos)]
       
   465                     else:
       
   466                         pdomapping.append((name, loc_infos))
       
   467                 # If there isn't locations yet but there is still a PDO to generate
       
   468                 if len(pdomapping) > 0:
       
   469                     # Generate a new PDO Mapping
       
   470                     data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdomapping, sync_TPDOs)
       
   471                     dataparams += data
       
   472                     nbparams += nbaddedparams
       
   473             
       
   474             # Add number of params and data to node DCF
   480             # Add number of params and data to node DCF
   475             self.AddParamsToDCF(nodeid, dataparams, nbparams)
   481             self.AddParamsToDCF(nodeid, dataparams, nbparams)
   476         
   482         
   477         #-------------------------------------------------------------------------------
   483         #-------------------------------------------------------------------------------
   478         #                         Master Node Configuration
   484         #                         Master Node Configuration
   606     for location in locations:
   612     for location in locations:
   607         COlocationtype = IECToCOType[location["IEC_TYPE"]]
   613         COlocationtype = IECToCOType[location["IEC_TYPE"]]
   608         name = location["NAME"]
   614         name = location["NAME"]
   609         if name in IECLocations:
   615         if name in IECLocations:
   610             if IECLocations[name] != COlocationtype:
   616             if IECLocations[name] != COlocationtype:
   611                 raise ValueError, "Conflict type for location \"%s\"" % name 
   617                 raise PDOmappingException, "Conflict type for location \"%s\"" % name 
   612         else:
   618         else:
   613             # Get only the part of the location that concern this node
   619             # Get only the part of the location that concern this node
   614             loc = location["LOC"][len(current_location):]
   620             loc = location["LOC"][len(current_location):]
   615             # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
   621             # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
   616             if len(loc) not in (2, 3, 4):
   622             if len(loc) not in (2, 3, 4):
   617                 raise ValueError, "Bad location size : %s"%str(loc)
   623                 raise PDOmappingException, "Bad location size : %s"%str(loc)
   618             elif len(loc) != 2:
   624             elif len(loc) != 2:
   619                 continue
   625                 continue
   620             
   626             
   621             # Extract and check nodeid
   627             # Extract and check nodeid
   622             index, subindex = loc[:2]
   628             index, subindex = loc[:2]
   623             
   629             
   624             # Extract and check index and subindex
   630             # Extract and check index and subindex
   625             if not slave.IsEntry(index, subindex):
   631             if not slave.IsEntry(index, subindex):
   626                 raise ValueError, "No such index/subindex (%x,%x) (variable %s)" % (index, subindex, name)
   632                 raise PDOmappingException, "No such index/subindex (%x,%x) (variable %s)" % (index, subindex, name)
   627             
   633             
   628             # Get the entry info
   634             # Get the entry info
   629             subentry_infos = slave.GetSubentryInfos(index, subindex)    
   635             subentry_infos = slave.GetSubentryInfos(index, subindex)    
   630             if subentry_infos["type"] != COlocationtype:
   636             if subentry_infos["type"] != COlocationtype:
   631                 raise ValueError, "Invalid type \"%s\"-> %d != %d  for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
   637                 raise PDOmappingException, "Invalid type \"%s\"-> %d != %d  for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
   632             
   638             
   633             IECLocations[name] = COlocationtype
   639             IECLocations[name] = COlocationtype
   634             pointers[(index, subindex)] = name
   640             pointers[(index, subindex)] = name
   635     return pointers
   641     return pointers
   636         
   642