21 # You should have received a copy of the GNU General Public License |
21 # You should have received a copy of the GNU General Public License |
22 # along with this program; if not, write to the Free Software |
22 # along with this program; if not, write to the Free Software |
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 |
24 |
25 |
25 |
26 from __future__ import absolute_import |
26 |
27 from __future__ import print_function |
27 |
28 import os |
28 import os |
29 import sys |
29 import sys |
30 import getopt |
30 import getopt |
31 from past.builtins import long |
31 from past.builtins import int |
|
32 from functools import reduce |
32 |
33 |
33 # Translation between IEC types and Can Open types |
34 # Translation between IEC types and Can Open types |
34 IECToCOType = { |
35 IECToCOType = { |
35 "BOOL": 0x01, |
36 "BOOL": 0x01, |
36 "SINT": 0x02, |
37 "SINT": 0x02, |
61 PDOTypeBaseCobId = {RPDO: 0x200, TPDO: 0x180} |
62 PDOTypeBaseCobId = {RPDO: 0x200, TPDO: 0x180} |
62 |
63 |
63 VariableIncrement = 0x100 |
64 VariableIncrement = 0x100 |
64 VariableStartIndex = {TPDO: 0x2000, RPDO: 0x4000} |
65 VariableStartIndex = {TPDO: 0x2000, RPDO: 0x4000} |
65 VariableDirText = {TPDO: "__I", RPDO: "__Q"} |
66 VariableDirText = {TPDO: "__I", RPDO: "__Q"} |
66 VariableTypeOffset = dict(zip(["", "X", "B", "W", "D", "L"], range(6))) |
67 VariableTypeOffset = dict(list(zip(["", "X", "B", "W", "D", "L"], list(range(6))))) |
67 |
68 |
68 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)] |
69 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)] |
69 |
70 |
70 # ------------------------------------------------------------------------------- |
71 # ------------------------------------------------------------------------------- |
71 # Specific exception for PDO mapping errors |
72 # Specific exception for PDO mapping errors |
83 @param size: number of bytes generated |
84 @param size: number of bytes generated |
84 @return: a string containing the value converted |
85 @return: a string containing the value converted |
85 """ |
86 """ |
86 |
87 |
87 data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value |
88 data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value |
88 list_car = [data[i:i+2] for i in xrange(0, len(data), 2)] |
89 list_car = [data[i:i+2] for i in range(0, len(data), 2)] |
89 list_car.reverse() |
90 list_car.reverse() |
90 return "".join([chr(int(car, 16)) for car in list_car]) |
91 return "".join([chr(int(car, 16)) for car in list_car]) |
91 |
92 |
92 |
93 |
93 def GetNodePDOIndexes(node, type, parameters=False): |
94 def GetNodePDOIndexes(node, type, parameters=False): |
168 # Dictionary of location that have not been mapped yet |
169 # Dictionary of location that have not been mapped yet |
169 self.LocationsNotMapped = {} |
170 self.LocationsNotMapped = {} |
170 # Dictionary of location informations classed by name |
171 # Dictionary of location informations classed by name |
171 self.MasterMapping = {} |
172 self.MasterMapping = {} |
172 # List of COB IDs available |
173 # List of COB IDs available |
173 self.ListCobIDAvailable = range(0x180, 0x580) |
174 self.ListCobIDAvailable = list(range(0x180, 0x580)) |
174 # Dictionary of mapping value where unexpected variables are stored |
175 # Dictionary of mapping value where unexpected variables are stored |
175 self.TrashVariables = {} |
176 self.TrashVariables = {} |
176 # Dictionary of pointed variables |
177 # Dictionary of pointed variables |
177 self.PointedVariables = {} |
178 self.PointedVariables = {} |
178 |
179 |
301 # starting from start_index |
302 # starting from start_index |
302 while index < PDOTypeBaseIndex[pdotype] + 0x200: |
303 while index < PDOTypeBaseIndex[pdotype] + 0x200: |
303 values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200) |
304 values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200) |
304 if values is not None and values[0] > 0: |
305 if values is not None and values[0] > 0: |
305 # Check that all subindex upper than 0 equal 0 => configurable PDO |
306 # Check that all subindex upper than 0 equal 0 => configurable PDO |
306 if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True): |
307 if reduce(lambda x, y: x and y, [x == 0 for x in values[1:]], True): |
307 cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1) |
308 cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1) |
308 # If no COB ID defined in PDO, generate a new one (not used) |
309 # If no COB ID defined in PDO, generate a new one (not used) |
309 if cobid == 0: |
310 if cobid == 0: |
310 if len(self.ListCobIDAvailable) == 0: |
311 if len(self.ListCobIDAvailable) == 0: |
311 return None |
312 return None |
372 |
373 |
373 # Extract and check nodeid |
374 # Extract and check nodeid |
374 nodeid, index, subindex = loc[:3] |
375 nodeid, index, subindex = loc[:3] |
375 |
376 |
376 # Check Id is in slave node list |
377 # Check Id is in slave node list |
377 if nodeid not in self.NodeList.SlaveNodes.keys(): |
378 if nodeid not in list(self.NodeList.SlaveNodes.keys()): |
378 raise PDOmappingException( |
379 raise PDOmappingException( |
379 _("Non existing node ID : {a1} (variable {a2})"). |
380 _("Non existing node ID : {a1} (variable {a2})"). |
380 format(a1=nodeid, a2=name)) |
381 format(a1=nodeid, a2=name)) |
381 |
382 |
382 # Get the model for this node (made from EDS) |
383 # Get the model for this node (made from EDS) |
428 |
429 |
429 # ------------------------------------------------------------------------------- |
430 # ------------------------------------------------------------------------------- |
430 # Search for locations already mapped |
431 # Search for locations already mapped |
431 # ------------------------------------------------------------------------------- |
432 # ------------------------------------------------------------------------------- |
432 |
433 |
433 for name, locationinfos in self.IECLocations.items(): |
434 for name, locationinfos in list(self.IECLocations.items()): |
434 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
435 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
435 |
436 |
436 # Search if slave has a PDO mapping this locations |
437 # Search if slave has a PDO mapping this locations |
437 result = SearchNodePDOMapping(locationinfos, node) |
438 result = SearchNodePDOMapping(locationinfos, node) |
438 if result is not None: |
439 if result is not None: |
439 index, subindex = result |
440 index, subindex = result |
440 # Get COB ID of the PDO |
441 # Get COB ID of the PDO |
441 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
442 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
442 |
443 |
443 # Add PDO to MasterMapping |
444 # Add PDO to MasterMapping |
444 if cobid not in self.MasterMapping.keys(): |
445 if cobid not in list(self.MasterMapping.keys()): |
445 # Verify that PDO transmit type is conform to sync_TPDOs |
446 # Verify that PDO transmit type is conform to sync_TPDOs |
446 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
447 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
447 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
448 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
448 if sync_TPDOs: |
449 if sync_TPDOs: |
449 # Change TransmitType to SYNCHRONE |
450 # Change TransmitType to SYNCHRONE |
472 else: |
473 else: |
473 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
474 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
474 |
475 |
475 else: |
476 else: |
476 # Add location to those that haven't been mapped yet |
477 # Add location to those that haven't been mapped yet |
477 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): |
478 if locationinfos["nodeid"] not in list(self.LocationsNotMapped.keys()): |
478 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO: [], RPDO: []} |
479 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO: [], RPDO: []} |
479 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
480 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
480 |
481 |
481 # ------------------------------------------------------------------------------- |
482 # ------------------------------------------------------------------------------- |
482 # Build concise DCF for the others locations |
483 # Build concise DCF for the others locations |
483 # ------------------------------------------------------------------------------- |
484 # ------------------------------------------------------------------------------- |
484 |
485 |
485 for nodeid, locations in self.LocationsNotMapped.items(): |
486 for nodeid, locations in list(self.LocationsNotMapped.items()): |
486 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
487 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
487 |
488 |
488 # Initialize number of params and data to add to node DCF |
489 # Initialize number of params and data to add to node DCF |
489 nbparams = 0 |
490 nbparams = 0 |
490 dataparams = "" |
491 dataparams = "" |
529 # ------------------------------------------------------------------------------- |
530 # ------------------------------------------------------------------------------- |
530 # Master Node Configuration |
531 # Master Node Configuration |
531 # ------------------------------------------------------------------------------- |
532 # ------------------------------------------------------------------------------- |
532 |
533 |
533 # Generate Master's Configuration from informations stored in MasterMapping |
534 # Generate Master's Configuration from informations stored in MasterMapping |
534 for cobid, pdo_infos in self.MasterMapping.items(): |
535 for cobid, pdo_infos in list(self.MasterMapping.items()): |
535 # Get next PDO index in MasterNode for this PDO type |
536 # Get next PDO index in MasterNode for this PDO type |
536 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
537 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
537 |
538 |
538 # Search if there is already a PDO in MasterNode with this cob id |
539 # Search if there is already a PDO in MasterNode with this cob id |
539 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
540 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
570 for subindex, variable in enumerate(mapping): |
571 for subindex, variable in enumerate(mapping): |
571 if subindex == 0: |
572 if subindex == 0: |
572 continue |
573 continue |
573 new_index = False |
574 new_index = False |
574 |
575 |
575 if isinstance(variable, (int, long)): |
576 if isinstance(variable, int): |
576 # If variable is an integer then variable is unexpected |
577 # If variable is an integer then variable is unexpected |
577 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
578 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
578 else: |
579 else: |
579 typeidx, varname = variable |
580 typeidx, varname = variable |
580 variable_infos = self.IECLocations[varname] |
581 variable_infos = self.IECLocations[varname] |
733 elif o in ("-r", "--reset"): |
734 elif o in ("-r", "--reset"): |
734 reset = True |
735 reset = True |
735 |
736 |
736 # Extract workspace base folder |
737 # Extract workspace base folder |
737 base_folder = sys.path[0] |
738 base_folder = sys.path[0] |
738 for i in xrange(3): |
739 for i in range(3): |
739 base_folder = os.path.split(base_folder)[0] |
740 base_folder = os.path.split(base_folder)[0] |
740 # Add CanFestival folder to search pathes |
741 # Add CanFestival folder to search pathes |
741 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
742 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
742 |
743 |
743 from nodemanager import * |
744 from nodemanager import * |