150 self.ListCobIDAvailable = range(0x180, 0x580) |
150 self.ListCobIDAvailable = range(0x180, 0x580) |
151 # Dictionary of mapping value where unexpected variables are stored |
151 # Dictionary of mapping value where unexpected variables are stored |
152 self.TrashVariables = {} |
152 self.TrashVariables = {} |
153 # Dictionary of pointed variables |
153 # Dictionary of pointed variables |
154 self.PointedVariables = {} |
154 self.PointedVariables = {} |
155 |
155 |
156 self.NodeList = nodelist |
156 self.NodeList = nodelist |
157 self.Manager = self.NodeList.Manager |
157 self.Manager = self.NodeList.Manager |
158 self.MasterNode = self.Manager.GetCurrentNodeCopy() |
158 self.MasterNode = self.Manager.GetCurrentNodeCopy() |
159 self.MasterNode.SetNodeName(nodename) |
159 self.MasterNode.SetNodeName(nodename) |
160 self.PrepareMasterNode() |
160 self.PrepareMasterNode() |
161 |
161 |
162 def GetPointedVariables(self): |
162 def GetPointedVariables(self): |
163 return self.PointedVariables |
163 return self.PointedVariables |
164 |
164 |
165 def RemoveUsedNodeCobId(self, node): |
165 def RemoveUsedNodeCobId(self, node): |
166 """ |
166 """ |
167 Remove all PDO COB ID used by the given node from the list of available COB ID |
167 Remove all PDO COB ID used by the given node from the list of available COB ID |
168 @param node: node |
168 @param node: node |
169 @return: a tuple of number of RPDO and TPDO for the node |
169 @return: a tuple of number of RPDO and TPDO for the node |
170 """ |
170 """ |
171 |
171 |
172 # Get list of all node TPDO and RPDO indexes |
172 # Get list of all node TPDO and RPDO indexes |
173 nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True) |
173 nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True) |
174 nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True) |
174 nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True) |
175 |
175 |
176 # Mark all the COB ID of the node already mapped PDO as not available |
176 # Mark all the COB ID of the node already mapped PDO as not available |
177 for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes: |
177 for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes: |
178 pdo_cobid = node.GetEntry(PdoIdx, 0x01) |
178 pdo_cobid = node.GetEntry(PdoIdx, 0x01) |
179 # Extract COB ID, if PDO isn't active |
179 # Extract COB ID, if PDO isn't active |
180 if pdo_cobid > 0x600 : |
180 if pdo_cobid > 0x600 : |
181 pdo_cobid -= 0x80000000 |
181 pdo_cobid -= 0x80000000 |
182 # Remove COB ID from the list of available COB ID |
182 # Remove COB ID from the list of available COB ID |
183 if pdo_cobid in self.ListCobIDAvailable: |
183 if pdo_cobid in self.ListCobIDAvailable: |
184 self.ListCobIDAvailable.remove(pdo_cobid) |
184 self.ListCobIDAvailable.remove(pdo_cobid) |
185 |
185 |
186 return len(nodeRpdoIndexes), len(nodeTpdoIndexes) |
186 return len(nodeRpdoIndexes), len(nodeTpdoIndexes) |
187 |
187 |
188 |
188 |
189 def PrepareMasterNode(self): |
189 def PrepareMasterNode(self): |
190 """ |
190 """ |
191 Add mandatory entries for DCF generation into MasterNode. |
191 Add mandatory entries for DCF generation into MasterNode. |
192 """ |
192 """ |
193 |
193 |
194 # Adding DCF entry into Master node |
194 # Adding DCF entry into Master node |
195 if not self.MasterNode.IsEntry(0x1F22): |
195 if not self.MasterNode.IsEntry(0x1F22): |
196 self.MasterNode.AddEntry(0x1F22, 1, "") |
196 self.MasterNode.AddEntry(0x1F22, 1, "") |
197 self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode) |
197 self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode) |
198 |
198 |
199 # Adding trash mappable variables for unused mapped datas |
199 # Adding trash mappable variables for unused mapped datas |
200 idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID() |
200 idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID() |
201 # Add an entry for storing unexpected all variable |
201 # Add an entry for storing unexpected all variable |
202 self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode) |
202 self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode) |
203 for subidx, (size, typeidx) in enumerate(TrashVariables): |
203 for subidx, (size, typeidx) in enumerate(TrashVariables): |
204 # Add a subentry for storing unexpected variable of this size |
204 # Add a subentry for storing unexpected variable of this size |
205 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode) |
205 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode) |
206 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode) |
206 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode) |
207 # Store the mapping value for this entry |
207 # Store the mapping value for this entry |
208 self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size |
208 self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size |
209 |
209 |
210 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode) |
210 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode) |
211 |
211 |
212 # Store the indexes of the first RPDO and TPDO available for MasterNode |
212 # Store the indexes of the first RPDO and TPDO available for MasterNode |
213 self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber} |
213 self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber} |
214 |
214 |
215 # Prepare MasterNode with all nodelist slaves |
215 # Prepare MasterNode with all nodelist slaves |
216 for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()): |
216 for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()): |
217 node = nodeinfos["Node"] |
217 node = nodeinfos["Node"] |
218 node.SetNodeID(nodeid) |
218 node.SetNodeID(nodeid) |
219 |
219 |
220 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node) |
220 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node) |
221 |
221 |
222 # Get Slave's default SDO server parameters |
222 # Get Slave's default SDO server parameters |
223 RSDO_cobid = node.GetEntry(0x1200,0x01) |
223 RSDO_cobid = node.GetEntry(0x1200,0x01) |
224 if not RSDO_cobid: |
224 if not RSDO_cobid: |
225 RSDO_cobid = 0x600 + nodeid |
225 RSDO_cobid = 0x600 + nodeid |
226 TSDO_cobid = node.GetEntry(0x1200,0x02) |
226 TSDO_cobid = node.GetEntry(0x1200,0x02) |
227 if not TSDO_cobid: |
227 if not TSDO_cobid: |
228 TSDO_cobid = 0x580 + nodeid |
228 TSDO_cobid = 0x580 + nodeid |
229 |
229 |
230 # Configure Master's SDO parameters entries |
230 # Configure Master's SDO parameters entries |
231 self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode) |
231 self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode) |
232 self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid) |
232 self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid) |
233 self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid) |
233 self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid) |
234 self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid) |
234 self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid) |
235 |
235 |
236 |
236 |
237 def GetMasterNode(self): |
237 def GetMasterNode(self): |
238 """ |
238 """ |
239 Return MasterNode. |
239 Return MasterNode. |
240 """ |
240 """ |
241 return self.MasterNode |
241 return self.MasterNode |
242 |
242 |
243 def AddParamsToDCF(self, nodeid, data, nbparams): |
243 def AddParamsToDCF(self, nodeid, data, nbparams): |
244 """ |
244 """ |
245 Add entry to DCF, for the requested nodeID |
245 Add entry to DCF, for the requested nodeID |
246 @param nodeid: id of the slave (int) |
246 @param nodeid: id of the slave (int) |
247 @param data: data to add to slave DCF (string) |
247 @param data: data to add to slave DCF (string) |
248 @param nbparams: number of params added to slave DCF (int) |
248 @param nbparams: number of params added to slave DCF (int) |
249 """ |
249 """ |
250 # Get current DCF for slave |
250 # Get current DCF for slave |
251 nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid) |
251 nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid) |
252 |
252 |
253 # Extract data and number of params in current DCF |
253 # Extract data and number of params in current DCF |
254 if nodeDCF != None and nodeDCF != '': |
254 if nodeDCF != None and nodeDCF != '': |
255 tmpnbparams = [i for i in nodeDCF[:4]] |
255 tmpnbparams = [i for i in nodeDCF[:4]] |
256 tmpnbparams.reverse() |
256 tmpnbparams.reverse() |
257 nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16) |
257 nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16) |
258 data = nodeDCF[4:] + data |
258 data = nodeDCF[4:] + data |
259 |
259 |
260 # Build new DCF |
260 # Build new DCF |
261 dcf = LE_to_BE(nbparams, 0x04) + data |
261 dcf = LE_to_BE(nbparams, 0x04) + data |
262 # Set new DCF for slave |
262 # Set new DCF for slave |
263 self.MasterNode.SetEntry(0x1F22, nodeid, dcf) |
263 self.MasterNode.SetEntry(0x1F22, nodeid, dcf) |
264 |
264 |
265 def GetEmptyPDO(self, nodeid, pdotype, start_index=None): |
265 def GetEmptyPDO(self, nodeid, pdotype, start_index=None): |
266 """ |
266 """ |
267 Search a not configured PDO for a slave |
267 Search a not configured PDO for a slave |
268 @param node: the slave node object |
268 @param node: the slave node object |
269 @param pdotype: type of PDO to generated (RPDO or TPDO) |
269 @param pdotype: type of PDO to generated (RPDO or TPDO) |
294 if cobid not in self.ListCobIDAvailable: |
294 if cobid not in self.ListCobIDAvailable: |
295 cobid = self.ListCobIDAvailable.pop(0) |
295 cobid = self.ListCobIDAvailable.pop(0) |
296 return index, cobid, values[0] |
296 return index, cobid, values[0] |
297 index += 1 |
297 index += 1 |
298 return None |
298 return None |
299 |
299 |
300 def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs): |
300 def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs): |
301 """ |
301 """ |
302 Record a new mapping request for a slave, and add related slave config to the DCF |
302 Record a new mapping request for a slave, and add related slave config to the DCF |
303 @param nodeid: id of the slave (int) |
303 @param nodeid: id of the slave (int) |
304 @param pdotype: type of PDO to generated (RPDO or TPDO) |
304 @param pdotype: type of PDO to generated (RPDO or TPDO) |
305 @param pdomapping: list od variables to map with PDO |
305 @param pdomapping: list od variables to map with PDO |
306 """ |
306 """ |
307 # Add an entry to MasterMapping |
307 # Add an entry to MasterMapping |
308 self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], |
308 self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], |
309 "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]} |
309 "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]} |
310 |
310 |
311 # Return the data to add to DCF |
311 # Return the data to add to DCF |
312 if sync_TPDOs: |
312 if sync_TPDOs: |
313 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping) |
313 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping) |
314 else: |
314 else: |
315 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping) |
315 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping) |
316 return 0, "" |
316 return 0, "" |
317 |
317 |
318 def GenerateDCF(self, locations, current_location, sync_TPDOs): |
318 def GenerateDCF(self, locations, current_location, sync_TPDOs): |
319 """ |
319 """ |
320 Generate Concise DCF of MasterNode for the locations list given |
320 Generate Concise DCF of MasterNode for the locations list given |
321 @param locations: list of locations to be mapped |
321 @param locations: list of locations to be mapped |
322 @param current_location: tuple of the located prefixes not to be considered |
322 @param current_location: tuple of the located prefixes not to be considered |
323 @param sync_TPDOs: indicate if TPDO must be synchronous |
323 @param sync_TPDOs: indicate if TPDO must be synchronous |
324 """ |
324 """ |
325 |
325 |
326 #------------------------------------------------------------------------------- |
326 #------------------------------------------------------------------------------- |
327 # Verify that locations correspond to real slave variables |
327 # Verify that locations correspond to real slave variables |
328 #------------------------------------------------------------------------------- |
328 #------------------------------------------------------------------------------- |
329 |
329 |
330 # Get list of locations check if exists and mappables -> put them in IECLocations |
330 # Get list of locations check if exists and mappables -> put them in IECLocations |
331 for location in locations: |
331 for location in locations: |
332 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
332 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
333 name = location["NAME"] |
333 name = location["NAME"] |
334 if name in self.IECLocations: |
334 if name in self.IECLocations: |
335 if self.IECLocations[name]["type"] != COlocationtype: |
335 if self.IECLocations[name]["type"] != COlocationtype: |
336 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
336 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
337 else: |
337 else: |
338 # Get only the part of the location that concern this node |
338 # Get only the part of the location that concern this node |
339 loc = location["LOC"][len(current_location):] |
339 loc = location["LOC"][len(current_location):] |
340 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
340 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
341 if len(loc) not in (2, 3, 4): |
341 if len(loc) not in (2, 3, 4): |
342 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
342 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
343 elif len(loc) == 2: |
343 elif len(loc) == 2: |
344 continue |
344 continue |
345 |
345 |
346 direction = location["DIR"] |
346 direction = location["DIR"] |
347 |
347 |
348 sizelocation = location["SIZE"] |
348 sizelocation = location["SIZE"] |
349 |
349 |
350 # Extract and check nodeid |
350 # Extract and check nodeid |
351 nodeid, index, subindex = loc[:3] |
351 nodeid, index, subindex = loc[:3] |
352 |
352 |
353 # Check Id is in slave node list |
353 # Check Id is in slave node list |
354 if nodeid not in self.NodeList.SlaveNodes.keys(): |
354 if nodeid not in self.NodeList.SlaveNodes.keys(): |
355 raise PDOmappingException, _("Non existing node ID : {a1} (variable {a2})").format(a1 = nodeid, a2 = name) |
355 raise PDOmappingException, _("Non existing node ID : {a1} (variable {a2})").format(a1 = nodeid, a2 = name) |
356 |
356 |
357 # Get the model for this node (made from EDS) |
357 # Get the model for this node (made from EDS) |
358 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
358 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
359 |
359 |
360 # Extract and check index and subindex |
360 # Extract and check index and subindex |
361 if not node.IsEntry(index, subindex): |
361 if not node.IsEntry(index, subindex): |
362 msg = _("No such index/subindex ({a1},{a2}) in ID : {a3} (variable {a4})").\ |
362 msg = _("No such index/subindex ({a1},{a2}) in ID : {a3} (variable {a4})").\ |
363 format(a1 = "%x" % index, a2 ="%x" % subindex, a3 = nodeid, a4 = name) |
363 format(a1 = "%x" % index, a2 ="%x" % subindex, a3 = nodeid, a4 = name) |
364 raise PDOmappingException, msg |
364 raise PDOmappingException, msg |
365 |
365 |
366 # Get the entry info |
366 # Get the entry info |
367 subentry_infos = node.GetSubentryInfos(index, subindex) |
367 subentry_infos = node.GetSubentryInfos(index, subindex) |
368 |
368 |
369 # If a PDO mappable |
369 # If a PDO mappable |
370 if subentry_infos and subentry_infos["pdo"]: |
370 if subentry_infos and subentry_infos["pdo"]: |
371 if sizelocation == "X" and len(loc) > 3: |
371 if sizelocation == "X" and len(loc) > 3: |
372 numbit = loc[3] |
372 numbit = loc[3] |
373 elif sizelocation != "X" and len(loc) > 3: |
373 elif sizelocation != "X" and len(loc) > 3: |
374 msg = _("Cannot set bit offset for non bool '{a1}' variable (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
374 msg = _("Cannot set bit offset for non bool '{a1}' variable (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
375 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
375 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
376 raise PDOmappingException, msg |
376 raise PDOmappingException, msg |
377 else: |
377 else: |
378 numbit = None |
378 numbit = None |
379 |
379 |
380 if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype: |
380 if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype: |
381 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
381 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
382 format(a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
382 format(a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
383 |
383 |
384 typeinfos = node.GetEntryInfos(COlocationtype) |
384 typeinfos = node.GetEntryInfos(COlocationtype) |
385 self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction], |
385 self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction], |
386 "nodeid": nodeid, "index": index,"subindex": subindex, |
386 "nodeid": nodeid, "index": index,"subindex": subindex, |
387 "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation} |
387 "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation} |
388 else: |
388 else: |
389 raise PDOmappingException, _("Not PDO mappable variable : '{a1}' (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
389 raise PDOmappingException, _("Not PDO mappable variable : '{a1}' (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
390 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
390 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
391 |
391 |
392 #------------------------------------------------------------------------------- |
392 #------------------------------------------------------------------------------- |
393 # Search for locations already mapped |
393 # Search for locations already mapped |
394 #------------------------------------------------------------------------------- |
394 #------------------------------------------------------------------------------- |
395 |
395 |
396 for name, locationinfos in self.IECLocations.items(): |
396 for name, locationinfos in self.IECLocations.items(): |
397 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
397 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
398 |
398 |
399 # Search if slave has a PDO mapping this locations |
399 # Search if slave has a PDO mapping this locations |
400 result = SearchNodePDOMapping(locationinfos, node) |
400 result = SearchNodePDOMapping(locationinfos, node) |
401 if result != None: |
401 if result != None: |
402 index, subindex = result |
402 index, subindex = result |
403 # Get COB ID of the PDO |
403 # Get COB ID of the PDO |
404 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
404 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
405 |
405 |
406 # Add PDO to MasterMapping |
406 # Add PDO to MasterMapping |
407 if cobid not in self.MasterMapping.keys(): |
407 if cobid not in self.MasterMapping.keys(): |
408 # Verify that PDO transmit type is conform to sync_TPDOs |
408 # Verify that PDO transmit type is conform to sync_TPDOs |
409 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
409 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
410 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
410 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
412 # Change TransmitType to SYNCHRONE |
412 # Change TransmitType to SYNCHRONE |
413 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, []) |
413 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, []) |
414 else: |
414 else: |
415 # Change TransmitType to ASYCHRONE |
415 # Change TransmitType to ASYCHRONE |
416 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, []) |
416 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, []) |
417 |
417 |
418 # Add entry to slave dcf to change transmit type of |
418 # Add entry to slave dcf to change transmit type of |
419 self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams) |
419 self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams) |
420 |
420 |
421 mapping = [None] |
421 mapping = [None] |
422 values = node.GetEntry(index) |
422 values = node.GetEntry(index) |
423 # Store the size of each entry mapped in PDO |
423 # Store the size of each entry mapped in PDO |
424 for value in values[1:]: |
424 for value in values[1:]: |
425 if value != 0: |
425 if value != 0: |
426 mapping.append(value % 0x100) |
426 mapping.append(value % 0x100) |
427 self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping} |
427 self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping} |
428 |
428 |
429 # Indicate that this PDO entry must be saved |
429 # Indicate that this PDO entry must be saved |
430 if locationinfos["bit"] is not None: |
430 if locationinfos["bit"] is not None: |
431 if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType): |
431 if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType): |
432 self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex] |
432 self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex] |
433 if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]): |
433 if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]): |
434 self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name) |
434 self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name) |
435 else: |
435 else: |
436 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
436 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
437 |
437 |
438 else: |
438 else: |
439 # Add location to those that haven't been mapped yet |
439 # Add location to those that haven't been mapped yet |
440 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): |
440 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): |
441 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []} |
441 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []} |
442 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
442 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
443 |
443 |
444 #------------------------------------------------------------------------------- |
444 #------------------------------------------------------------------------------- |
445 # Build concise DCF for the others locations |
445 # Build concise DCF for the others locations |
446 #------------------------------------------------------------------------------- |
446 #------------------------------------------------------------------------------- |
447 |
447 |
448 for nodeid, locations in self.LocationsNotMapped.items(): |
448 for nodeid, locations in self.LocationsNotMapped.items(): |
449 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
449 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
450 |
450 |
451 # Initialize number of params and data to add to node DCF |
451 # Initialize number of params and data to add to node DCF |
452 nbparams = 0 |
452 nbparams = 0 |
453 dataparams = "" |
453 dataparams = "" |
454 |
454 |
455 # Generate the best PDO mapping for each type of PDO |
455 # Generate the best PDO mapping for each type of PDO |
456 for pdotype in (TPDO, RPDO): |
456 for pdotype in (TPDO, RPDO): |
457 if len(locations[pdotype]) > 0: |
457 if len(locations[pdotype]) > 0: |
458 pdosize = 0 |
458 pdosize = 0 |
459 pdomapping = [] |
459 pdomapping = [] |
481 if len(pdomapping) > 0: |
481 if len(pdomapping) > 0: |
482 # Generate a new PDO Mapping |
482 # Generate a new PDO Mapping |
483 data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) |
483 data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) |
484 dataparams += data |
484 dataparams += data |
485 nbparams += nbaddedparams |
485 nbparams += nbaddedparams |
486 |
486 |
487 # Add number of params and data to node DCF |
487 # Add number of params and data to node DCF |
488 self.AddParamsToDCF(nodeid, dataparams, nbparams) |
488 self.AddParamsToDCF(nodeid, dataparams, nbparams) |
489 |
489 |
490 #------------------------------------------------------------------------------- |
490 #------------------------------------------------------------------------------- |
491 # Master Node Configuration |
491 # Master Node Configuration |
492 #------------------------------------------------------------------------------- |
492 #------------------------------------------------------------------------------- |
493 |
493 |
494 # Generate Master's Configuration from informations stored in MasterMapping |
494 # Generate Master's Configuration from informations stored in MasterMapping |
495 for cobid, pdo_infos in self.MasterMapping.items(): |
495 for cobid, pdo_infos in self.MasterMapping.items(): |
496 # Get next PDO index in MasterNode for this PDO type |
496 # Get next PDO index in MasterNode for this PDO type |
497 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
497 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
498 |
498 |
499 # Search if there is already a PDO in MasterNode with this cob id |
499 # Search if there is already a PDO in MasterNode with this cob id |
500 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
500 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
501 if self.MasterNode.GetEntry(idx, 1) == cobid: |
501 if self.MasterNode.GetEntry(idx, 1) == cobid: |
502 current_idx = idx |
502 current_idx = idx |
503 |
503 |
504 # Add a PDO to MasterNode if not PDO have been found |
504 # Add a PDO to MasterNode if not PDO have been found |
505 if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]: |
505 if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]: |
506 addinglist = [current_idx, current_idx + 0x200] |
506 addinglist = [current_idx, current_idx + 0x200] |
507 self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode) |
507 self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode) |
508 self.MasterNode.SetEntry(current_idx, 0x01, cobid) |
508 self.MasterNode.SetEntry(current_idx, 0x01, cobid) |
509 |
509 |
510 # Increment the number of PDO for this PDO type |
510 # Increment the number of PDO for this PDO type |
511 self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1 |
511 self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1 |
512 |
512 |
513 # Change the transmit type of the PDO |
513 # Change the transmit type of the PDO |
514 if sync_TPDOs: |
514 if sync_TPDOs: |
515 self.MasterNode.SetEntry(current_idx, 0x02, 0x01) |
515 self.MasterNode.SetEntry(current_idx, 0x02, 0x01) |
516 else: |
516 else: |
517 self.MasterNode.SetEntry(current_idx, 0x02, 0xFF) |
517 self.MasterNode.SetEntry(current_idx, 0x02, 0xFF) |
518 |
518 |
519 mapping = [] |
519 mapping = [] |
520 for item in pdo_infos["mapping"]: |
520 for item in pdo_infos["mapping"]: |
521 if isinstance(item, ListType): |
521 if isinstance(item, ListType): |
522 mapping.extend(item) |
522 mapping.extend(item) |
523 else: |
523 else: |
524 mapping.append(item) |
524 mapping.append(item) |
525 |
525 |
526 # Add some subentries to PDO mapping if there is not enough |
526 # Add some subentries to PDO mapping if there is not enough |
527 if len(mapping) > 1: |
527 if len(mapping) > 1: |
528 self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode) |
528 self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode) |
529 |
529 |
530 # Generate MasterNode's PDO mapping |
530 # Generate MasterNode's PDO mapping |
531 for subindex, variable in enumerate(mapping): |
531 for subindex, variable in enumerate(mapping): |
532 if subindex == 0: |
532 if subindex == 0: |
533 continue |
533 continue |
534 new_index = False |
534 new_index = False |
535 |
535 |
536 if isinstance(variable, (IntType, LongType)): |
536 if isinstance(variable, (IntType, LongType)): |
537 # If variable is an integer then variable is unexpected |
537 # If variable is an integer then variable is unexpected |
538 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
538 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
539 else: |
539 else: |
540 typeidx, varname = variable |
540 typeidx, varname = variable |
541 variable_infos = self.IECLocations[varname] |
541 variable_infos = self.IECLocations[varname] |
542 |
542 |
543 # Calculate base index for storing variable |
543 # Calculate base index for storing variable |
544 mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \ |
544 mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \ |
545 VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \ |
545 VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \ |
546 variable_infos["nodeid"] |
546 variable_infos["nodeid"] |
547 |
547 |
548 # Generate entry name |
548 # Generate entry name |
549 indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]], |
549 indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]], |
550 variable_infos["sizelocation"], |
550 variable_infos["sizelocation"], |
551 '_'.join(map(str,current_location)), |
551 '_'.join(map(str,current_location)), |
552 variable_infos["nodeid"]) |
552 variable_infos["nodeid"]) |
553 |
553 |
554 # Search for an entry that has an empty subindex |
554 # Search for an entry that has an empty subindex |
555 while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
555 while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
556 # Entry doesn't exist |
556 # Entry doesn't exist |
557 if not self.MasterNode.IsEntry(mapvariableidx): |
557 if not self.MasterNode.IsEntry(mapvariableidx): |
558 # Add entry to MasterNode |
558 # Add entry to MasterNode |
559 self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode) |
559 self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode) |
560 new_index = True |
560 new_index = True |
561 nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) |
561 nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) |
562 else: |
562 else: |
619 for location in locations: |
619 for location in locations: |
620 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
620 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
621 name = location["NAME"] |
621 name = location["NAME"] |
622 if name in IECLocations: |
622 if name in IECLocations: |
623 if IECLocations[name] != COlocationtype: |
623 if IECLocations[name] != COlocationtype: |
624 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
624 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
625 else: |
625 else: |
626 # Get only the part of the location that concern this node |
626 # Get only the part of the location that concern this node |
627 loc = location["LOC"][len(current_location):] |
627 loc = location["LOC"][len(current_location):] |
628 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
628 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
629 if len(loc) not in (2, 3, 4): |
629 if len(loc) not in (2, 3, 4): |
630 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
630 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
631 elif len(loc) != 2: |
631 elif len(loc) != 2: |
632 continue |
632 continue |
633 |
633 |
634 # Extract and check nodeid |
634 # Extract and check nodeid |
635 index, subindex = loc[:2] |
635 index, subindex = loc[:2] |
636 |
636 |
637 # Extract and check index and subindex |
637 # Extract and check index and subindex |
638 if not slave.IsEntry(index, subindex): |
638 if not slave.IsEntry(index, subindex): |
639 raise PDOmappingException, _("No such index/subindex ({a1},{a2}) (variable {a3})").\ |
639 raise PDOmappingException, _("No such index/subindex ({a1},{a2}) (variable {a3})").\ |
640 format(a1 = "%x" % index, a2 = "%x" % subindex, a3 = name) |
640 format(a1 = "%x" % index, a2 = "%x" % subindex, a3 = name) |
641 |
641 |
642 # Get the entry info |
642 # Get the entry info |
643 subentry_infos = slave.GetSubentryInfos(index, subindex) |
643 subentry_infos = slave.GetSubentryInfos(index, subindex) |
644 if subentry_infos["type"] != COlocationtype: |
644 if subentry_infos["type"] != COlocationtype: |
645 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
645 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
646 format( a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
646 format( a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
647 |
647 |
648 IECLocations[name] = COlocationtype |
648 IECLocations[name] = COlocationtype |
649 pointers[(index, subindex)] = name |
649 pointers[(index, subindex)] = name |
650 return pointers |
650 return pointers |
651 |
651 |
652 if __name__ == "__main__": |
652 if __name__ == "__main__": |
653 import os, sys, getopt |
653 import os, sys, getopt |
654 |
654 |
655 def usage(): |
655 def usage(): |
656 print """ |
656 print """ |
691 base_folder = sys.path[0] |
691 base_folder = sys.path[0] |
692 for i in xrange(3): |
692 for i in xrange(3): |
693 base_folder = os.path.split(base_folder)[0] |
693 base_folder = os.path.split(base_folder)[0] |
694 # Add CanFestival folder to search pathes |
694 # Add CanFestival folder to search pathes |
695 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
695 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
696 |
696 |
697 from nodemanager import * |
697 from nodemanager import * |
698 from nodelist import * |
698 from nodelist import * |
699 |
699 |
700 # Open the test nodelist contained into test_config folder |
700 # Open the test nodelist contained into test_config folder |
701 manager = NodeManager() |
701 manager = NodeManager() |
702 nodelist = NodeList(manager) |
702 nodelist = NodeList(manager) |
703 result = nodelist.LoadProject("test_config") |
703 result = nodelist.LoadProject("test_config") |
704 |
704 |
705 # List of locations, we try to map for test |
705 # List of locations, we try to map for test |
706 locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)}, |
706 locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)}, |
707 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)}, |
707 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)}, |
708 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)}, |
708 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)}, |
709 {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)}, |
709 {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)}, |
711 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)}, |
711 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)}, |
712 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)}, |
712 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)}, |
713 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)}, |
713 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)}, |
714 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)}, |
714 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)}, |
715 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}] |
715 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}] |
716 |
716 |
717 # Generate MasterNode configuration |
717 # Generate MasterNode configuration |
718 try: |
718 try: |
719 masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode") |
719 masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode") |
720 except ValueError, message: |
720 except ValueError, message: |
721 print "%s\nTest Failed!"%message |
721 print "%s\nTest Failed!"%message |
722 sys.exit() |
722 sys.exit() |
723 |
723 |
724 import pprint |
724 import pprint |
725 # Get Text corresponding to MasterNode |
725 # Get Text corresponding to MasterNode |
726 result_node = masternode.PrintString() |
726 result_node = masternode.PrintString() |
727 result_vars = pprint.pformat(pointedvariables) |
727 result_vars = pprint.pformat(pointedvariables) |
728 result = result_node + "\n********POINTERS*********\n" + result_vars + "\n" |
728 result = result_node + "\n********POINTERS*********\n" + result_vars + "\n" |
729 |
729 |
730 # If reset has been choosen |
730 # If reset has been choosen |
731 if reset: |
731 if reset: |
732 # Write Text into reference result file |
732 # Write Text into reference result file |
733 testfile = open("test_config/result.txt", "w") |
733 testfile = open("test_config/result.txt", "w") |
734 testfile.write(result) |
734 testfile.write(result) |
735 testfile.close() |
735 testfile.close() |
736 |
736 |
737 print "Reset Successful!" |
737 print "Reset Successful!" |
738 else: |
738 else: |
739 import os |
739 import os |
740 |
740 |
741 testfile = open("test_config/result_tmp.txt", "w") |
741 testfile = open("test_config/result_tmp.txt", "w") |
742 testfile.write(result) |
742 testfile.write(result) |
743 testfile.close() |
743 testfile.close() |
744 |
744 |
745 os.system("diff test_config/result.txt test_config/result_tmp.txt") |
745 os.system("diff test_config/result.txt test_config/result_tmp.txt") |
746 os.remove("test_config/result_tmp.txt") |
746 os.remove("test_config/result_tmp.txt") |